comparison env/lib/python3.7/site-packages/urllib3/contrib/ntlmpool.py @ 5:9b1c78e6ba9c draft default tip

"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author shellac
date Mon, 01 Jun 2020 08:59:25 -0400
parents 79f47841a781
children
comparison
equal deleted inserted replaced
4:79f47841a781 5:9b1c78e6ba9c
1 """
2 NTLM authenticating pool, contributed by erikcederstran
3
4 Issue #10, see: http://code.google.com/p/urllib3/issues/detail?id=10
5 """
6 from __future__ import absolute_import
7
8 from logging import getLogger
9 from ntlm import ntlm
10
11 from .. import HTTPSConnectionPool
12 from ..packages.six.moves.http_client import HTTPSConnection
13
14
15 log = getLogger(__name__)
16
17
18 class NTLMConnectionPool(HTTPSConnectionPool):
19 """
20 Implements an NTLM authentication version of an urllib3 connection pool
21 """
22
23 scheme = "https"
24
25 def __init__(self, user, pw, authurl, *args, **kwargs):
26 """
27 authurl is a random URL on the server that is protected by NTLM.
28 user is the Windows user, probably in the DOMAIN\\username format.
29 pw is the password for the user.
30 """
31 super(NTLMConnectionPool, self).__init__(*args, **kwargs)
32 self.authurl = authurl
33 self.rawuser = user
34 user_parts = user.split("\\", 1)
35 self.domain = user_parts[0].upper()
36 self.user = user_parts[1]
37 self.pw = pw
38
39 def _new_conn(self):
40 # Performs the NTLM handshake that secures the connection. The socket
41 # must be kept open while requests are performed.
42 self.num_connections += 1
43 log.debug(
44 "Starting NTLM HTTPS connection no. %d: https://%s%s",
45 self.num_connections,
46 self.host,
47 self.authurl,
48 )
49
50 headers = {"Connection": "Keep-Alive"}
51 req_header = "Authorization"
52 resp_header = "www-authenticate"
53
54 conn = HTTPSConnection(host=self.host, port=self.port)
55
56 # Send negotiation message
57 headers[req_header] = "NTLM %s" % ntlm.create_NTLM_NEGOTIATE_MESSAGE(
58 self.rawuser
59 )
60 log.debug("Request headers: %s", headers)
61 conn.request("GET", self.authurl, None, headers)
62 res = conn.getresponse()
63 reshdr = dict(res.getheaders())
64 log.debug("Response status: %s %s", res.status, res.reason)
65 log.debug("Response headers: %s", reshdr)
66 log.debug("Response data: %s [...]", res.read(100))
67
68 # Remove the reference to the socket, so that it can not be closed by
69 # the response object (we want to keep the socket open)
70 res.fp = None
71
72 # Server should respond with a challenge message
73 auth_header_values = reshdr[resp_header].split(", ")
74 auth_header_value = None
75 for s in auth_header_values:
76 if s[:5] == "NTLM ":
77 auth_header_value = s[5:]
78 if auth_header_value is None:
79 raise Exception(
80 "Unexpected %s response header: %s" % (resp_header, reshdr[resp_header])
81 )
82
83 # Send authentication message
84 ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(
85 auth_header_value
86 )
87 auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
88 ServerChallenge, self.user, self.domain, self.pw, NegotiateFlags
89 )
90 headers[req_header] = "NTLM %s" % auth_msg
91 log.debug("Request headers: %s", headers)
92 conn.request("GET", self.authurl, None, headers)
93 res = conn.getresponse()
94 log.debug("Response status: %s %s", res.status, res.reason)
95 log.debug("Response headers: %s", dict(res.getheaders()))
96 log.debug("Response data: %s [...]", res.read()[:100])
97 if res.status != 200:
98 if res.status == 401:
99 raise Exception("Server rejected request: wrong username or password")
100 raise Exception("Wrong server response: %s %s" % (res.status, res.reason))
101
102 res.fp = None
103 log.debug("Connection established")
104 return conn
105
106 def urlopen(
107 self,
108 method,
109 url,
110 body=None,
111 headers=None,
112 retries=3,
113 redirect=True,
114 assert_same_host=True,
115 ):
116 if headers is None:
117 headers = {}
118 headers["Connection"] = "Keep-Alive"
119 return super(NTLMConnectionPool, self).urlopen(
120 method, url, body, headers, retries, redirect, assert_same_host
121 )