1 """
2 This module is intended to make it easier to build web clients
3 written in Python using the urllib module that can
4 interoperate with the @LIGO.ORG infrastructure.
5 """
6
7 import re
8 from six.moves import urllib
9
10 import kerberos
11
12
14 """
15 This class uses an existing Kerberos ticket to authenticate
16 via HTTP Negotiate Authentication. An instance of this class
17 can be passed into the build_opener function from the urllib
18 module.
19
20 Modified from source found at
21
22 http://selenic.com/pipermail/mercurial/2008-June/019776.html
23 """
24
25 rx = re.compile('(?:.*,)*\s*Negotiate\s*([^,]*),?', re.I)
26 handler_order = 480
27
29 """
30 service_principal is the Kerberos principal of the
31 host against which the client authenticates. It
32 should usually be the string 'HTTP@login.ligo.org'.
33 """
34 self.retried = 0
35 self.context = None
36 self.service_principal = service_principal
37
47
49 neg_value = self.negotiate_value(headers)
50 if neg_value is None:
51 self.retried = 0
52 return None
53
54 if self.retried > 5:
55 raise urllib.error.HTTPError(req.get_full_url(), 401, "negotiate auth failed", headers, None)
56
57 self.retried += 1
58
59 result, self.context = kerberos.authGSSClientInit(self.service_principal)
60
61 if result < 1:
62 return None
63
64 result = kerberos.authGSSClientStep(self.context, neg_value)
65
66 if result < 0:
67 return None
68
69 response = kerberos.authGSSClientResponse(self.context)
70
71 return "Negotiate %s" % response
72
74 neg_value = self.negotiate_value(headers)
75 if neg_value is None:
76 return None
77
78 if kerberos.authGSSClientStep(self.context, neg_value) < 1:
79 pass
80
81 - def clean_context(self):
82 if self.context is not None:
83 kerberos.authGSSClientClean(self.context)
84
86 try:
87 neg_hdr = self.generate_request_header(req, headers)
88
89 if neg_hdr is None:
90 return None
91
92 req.add_unredirected_header('Authorization', neg_hdr)
93 resp = self.parent.open(req)
94
95 self.authenticate_server(resp.info())
96
97 return resp
98
99 finally:
100 self.clean_context()
101