2 from mitmproxy
import ctx
, exceptions
3 from requests
.auth
import HTTPDigestAuth
4 from requests
.utils
import parse_dict_header
13 class DigestAuthenticator
:
16 self
.lock
= threading
.Lock()
17 self
.resubmitted_response
= None
21 def load(self
, loader
):
22 ctx
.log
.info('in load')
25 typespec
= typing
.Text
,
27 help = "Please enter your user name"
30 def configure(self
, updates
):
31 ctx
.log
.info('updates: ' + str(updates
))
32 ctx
.log
.info('in configue: ' + str(ctx
.options
))
33 if ctx
.options
.uname
== '':
34 raise exceptions
.OptionsError("Please enter a non-empty value for uname with --set uname=your_username")
36 self
._username
= ctx
.options
.uname
37 self
._password
= getpass
.getpass("Please enter the password for " + self
._username
+ ": ")
40 def response(self
, flow
):
42 if flow
.response
.status_code
== 401 and 'Authorization' not in flow
.request
.headers
:
44 www_authenticate_header
= flow
.response
.headers
['WWW-Authenticate']
46 if 'digest' in www_authenticate_header
.lower():
48 http_digest_auth
= HTTPDigestAuth(self
._username
, self
._password
)
49 http_digest_auth
.init_per_thread_state()
50 pat
= re
.compile(r
'digest ', flags
=re
.IGNORECASE
)
51 http_digest_auth
._thread
_local
.chal
= parse_dict_header(pat
.sub('', www_authenticate_header
, count
=1))
52 authorization_header
= http_digest_auth
.build_digest_header(flow
.request
.method
, flow
.request
.url
)
54 resubmitted_headers
= {}
55 resubmitted_headers
.update(flow
.request
.headers
)
56 resubmitted_headers
.update({'Authorization': str(authorization_header
)})
57 if flow
.request
.method
== 'GET':
58 resubmitted_response
= requests
.get(flow
.request
.url
, headers
=resubmitted_headers
, allow_redirects
=False)
60 # TODO: This probably needs a data=payload arg...
61 resubmitted_response
= requests
.post(flow
.request
.url
, headers
=resubmitted_headers
)
63 if resubmitted_response
.status_code
== 301:
64 ctx
.log
.info("301 response headers: " + str(resubmitted_response
.headers
))
66 flow
.response
.status_code
= resubmitted_response
.status_code
67 flow
.response
.reason
= resubmitted_response
.reason
68 flow
.response
.content
= resubmitted_response
.text
.encode('ascii')
70 # TODO: additional response fields (headers and cookies)
73 # TODO: switch info to debug eventually
74 ctx
.log("DigestAuthenticator other request: " + str(flow
.response
.status_code
) + "\n\n", "info")