1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
# vim: set filencoding=utf8
"""
Exchange Server Authenticators
@author: Mike Crute (mcrute@gmail.com)
@organization: SoftGroup Interactive, Inc.
@date: April 26, 2009
"""
import urllib
from Cookie import SimpleCookie
from httplib import HTTPSConnection
from datetime import datetime, timedelta
from exchange import AuthenticationException
class CookieSession(object):
"""
CookieSession implmenents the authentication protocol for the
Exchange web interface.
"""
AUTH_DLL = "/exchweb/bin/auth/owaauth.dll"
def __init__(self, server, username=None, password=None):
self.server = server
self.username = username
self.password = password
self.cache_timeout = timedelta(minutes=15)
self._token = None
self._last_modified = None
@property
def has_expired(self):
if not self._last_modified:
return False
update_delta = datetime.now() - self._last_modified
return (update_delta >= self.cache_timeout)
@property
def is_authenticated(self):
return bool(self._token) and not self.has_expired
@property
def token(self):
if not self.is_authenticated:
self._authenticate()
self._check_auth()
return self._token
@token.setter
def token(self, token):
self._last_modified = datetime.now()
self._token = token.strip()
def _authenticate(self):
# Another idiotic Exchange issue, you MUST pass the redirect
# destination, and what's more if you don't pass it the name
# of the current server + /echange it will fail to auth
params = urllib.urlencode({
"destination": "https://{0}/exchange".format(self.server),
"username": self.username,
"password": self.password,
})
conn = HTTPSConnection(self.server)
conn.request("POST", self.AUTH_DLL, params)
response = conn.getresponse()
cookie = SimpleCookie(response.getheader("set-cookie"))
self.token = cookie.output(attrs=[], header='', sep=';')
def _check_auth(self):
# Grrr... Exchange is idiotic, instead of returning the correct error
# code with the auth they force you to follow a redirect. If you
# don't get a 200 (you'll get a 302) then you can rest assured that
# your authentication failed.
conn = HTTPSConnection(self.server)
conn.request("GET", '/exchange/',
headers=dict(Cookie=self.token))
resp = conn.getresponse()
if not resp.status == 200:
raise AuthenticationException
|