示例#1
0
 def __init__(self, auth_data=b''):
     super(NTLMChallenge, self).__init__("NTLM")
     # a default realm will have been added, remove it
     del self._pdict['realm']
     self._params = []
     #: base64 encoded binary string containing ntlm-data
     auth_data = auth_data.strip()
     if auth_data:
         self.auth_data = auth_data
         self.server_challenge, self.flags = \
             ntlm.parse_NTLM_CHALLENGE_MESSAGE(auth_data)
     else:
         # empty auth_data is the same as no auth data
         self.auth_data = None
         self.server_challenge = None
         self.flags = None
示例#2
0
def ntlm_authenticate(smtp, username, password):
    # Send the NTLM Type 1 message -- Authentication Request
    msg = ntlm.create_NTLM_NEGOTIATE_MESSAGE(username)
    print(msg)
    code, response = smtp.docmd(
        "AUTH",
        "NTLM " + ntlm.create_NTLM_NEGOTIATE_MESSAGE(username).decode())
    if code != SMTP_AUTH_CHALLENGE:
        raise SMTPException(
            "Server did not respond as expected to NTLM negotiate message")
    challenge, flags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(response)
    user_parts = username.split("\\", 1)
    DomainName = user_parts[0].upper()
    UserName = user_parts[1]
    msg = ntlm.create_NTLM_AUTHENTICATE_MESSAGE(challenge, UserName,
                                                DomainName, password, flags)
    print(msg)
    code, response = smtp.docmd(
        "",
        ntlm.create_NTLM_AUTHENTICATE_MESSAGE(challenge, UserName, DomainName,
                                              password, flags).decode())
    print(code)
    if code != SMTP_AUTH_OKAY:
        raise SMTPAuthenticationError(code, response)
示例#3
0
    def retry_using_http_NTLM_auth(self, auth_header_field, auth_header,
                                   response, auth_type, args):
        """Attempt to authenticate using HTTP NTLM challenge/response."""
        if auth_header in response.request.headers:
            return response

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

        # Consume content and release the original connection
        # to allow our new request to reuse the same one.
        response.content
        response.raw.release_conn()
        request = response.request.copy()

        # initial auth header with username. will result in challenge
        msg = "%s\\%s" % (self.domain, self.username) if self.domain else self.username

        # ntlm returns the headers as a base64 encoded bytestring. Convert to
        # a string.
        auth = '%s %s' % (auth_type, ntlm.create_NTLM_NEGOTIATE_MESSAGE(msg).decode('ascii'))
        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 = response.connection.send(request, **args_nostream)

        # needed to make NTLM auth compatible with requests-2.3.0

        # Consume content and release the original connection
        # to allow our new request to reuse the same one.
        response2.content
        response2.raw.release_conn()
        request = response2.request.copy()

        # 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]

        auth_strip = auth_type + ' '

        ntlm_header_value = next(
            s for s in (val.lstrip() for val in auth_header_value.split(','))
            if s.startswith(auth_strip)
        ).strip()

        ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(
            ntlm_header_value[len(auth_strip):]
        )

        # build response

        # ntlm returns the headers as a base64 encoded bytestring. Convert to a
        # string.
        auth = '%s %s' % (auth_type, ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
            ServerChallenge, self.username, self.domain, self.password,
            NegotiateFlags
        ).decode('ascii'))
        request.headers[auth_header] = auth

        response3 = response2.connection.send(request, **args)

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

        return response3
示例#4
0
from flask import Flask,request
from ntlm3 import ntlm
from tests.test_utils import username, password, domain
app = Flask(__name__)

REQUEST_2_TEMPLATE = '{0} %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(domain + "\\" + username).decode('ascii')

RESPONSE_2_NONCE = 'TlRMTVNTUAACAAAADAAMADAAAAAHAgMAESIzRFVmd4gAAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABYAZQB4AGEAbQBwAGwAZQAuAGMAbwBtAAMAJABTAEUAUgBWAEUAUgAuAGUAeABhAG0AcABsAGUALgBjAG8AbQAAAAAA'
RESPONSE_2_TEMPLATE = '{0} %s' % RESPONSE_2_NONCE

ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(RESPONSE_2_NONCE)

REQUEST_3_TEMPLATE = '{0} %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, username, domain, password, NegotiateFlags).decode('ascii')

@app.route("/ntlm")
def ntlm_auth():
    return get_auth_response('NTLM')

@app.route("/negotiate")
def negotiate_auth():
    return get_auth_response('Negotiate')

@app.route("/both")
def negotiate_and_ntlm_auth():
    return get_auth_response('NTLM', advertise_nego_and_ntlm=True)

def get_auth_response(auth_type, advertise_nego_and_ntlm=False):
    response_headers = {'WWW-Authenticate':auth_type if not advertise_nego_and_ntlm else 'Negotiate, NTLM'}
    status_code = 401
    response = "auth with '%s\\%s':'%s'" % (domain, username, password)
示例#5
0
from flask import Flask, request
from ntlm3 import ntlm

app = Flask(__name__)

REQUEST_2_TEMPLATE = "{0} %s" % ntlm.create_NTLM_NEGOTIATE_MESSAGE("domain\\username").decode("ascii")

RESPONSE_2_NONCE = "TlRMTVNTUAACAAAADAAMADAAAAAHAgMAESIzRFVmd4gAAAAAAAAAAGIAYgA8AAAARABPAE0AQQBJAE4AAgAMAEQATwBNAEEASQBOAAEADABTAEUAUgBWAEUAUgAEABYAZQB4AGEAbQBwAGwAZQAuAGMAbwBtAAMAJABTAEUAUgBWAEUAUgAuAGUAeABhAG0AcABsAGUALgBjAG8AbQAAAAAA"
RESPONSE_2_TEMPLATE = "{0} %s" % RESPONSE_2_NONCE

ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(RESPONSE_2_NONCE)

REQUEST_3_TEMPLATE = "{0} %s" % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
    ServerChallenge, "username", "domain", "password", NegotiateFlags
).decode("ascii")


@app.route("/ntlm")
def ntlm_auth():
    return get_auth_response("NTLM")


@app.route("/negotiate")
def negotiate_auth():
    return get_auth_response("Negotiate")


@app.route("/both")
def negotiate_and_ntlm_auth():
    return get_auth_response("NTLM", advertise_nego_and_ntlm=True)
示例#6
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 = copy_request(response.request)

        content_length = int(request.headers.get('Content-Length', '0'),
                             base=10)
        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

        # ntlm returns the headers as a base64 encoded bytestring. Convert to a string.
        auth = 'NTLM %s' % ntlm.create_NTLM_NEGOTIATE_MESSAGE(msg).decode(
            'ascii')
        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)

        # ntlm returns the headers as a base64 encoded bytestring. Convert to a string.
        auth = 'NTLM %s' % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
            ServerChallenge, self.username, self.domain, self.password,
            NegotiateFlags).decode('ascii')
        request.headers[auth_header] = auth

        response3 = 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):
        """Attempt to authenticate using HTTP NTLM challenge/response."""
        if auth_header in response.request.headers:
            return response

        request = copy_request(response.request)

        content_length = int(request.headers.get("Content-Length", "0"), base=10)
        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

        # ntlm returns the headers as a base64 encoded bytestring. Convert to a string.
        auth = "NTLM %s" % ntlm.create_NTLM_NEGOTIATE_MESSAGE(msg).decode("ascii")
        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)

        # ntlm returns the headers as a base64 encoded bytestring. Convert to a string.
        auth = "NTLM %s" % ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
            ServerChallenge, self.username, self.domain, self.password, NegotiateFlags
        ).decode("ascii")
        request.headers[auth_header] = auth

        response3 = 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, auth_type, args):
        """Attempt to authenticate using HTTP NTLM challenge/response."""
        if auth_header in response.request.headers:
            return response

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

        # Consume content and release the original connection
        # to allow our new request to reuse the same one.
        response.content
        response.raw.release_conn()
        request = response.request.copy()

        # initial auth header with username. will result in challenge
        if self._use_default_credentials:
            pkg_info = win32security.QuerySecurityPackageInfo(_package)
            clientauth = sspi.ClientAuth(_package)
            sec_buffer = win32security.PySecBufferDescType()
            error, auth = clientauth.authorize(sec_buffer)
            request.headers[auth_header] = '{} {}'.format(
                _package,
                b64encode(auth[0].Buffer).decode('ascii'))
        else:
            msg = "%s\\%s" % (self.domain,
                              self.username) if self.domain else self.username

            # ntlm returns the headers as a base64 encoded bytestring. Convert to
            # a string.
            auth = '%s %s' % (auth_type, ntlm.create_NTLM_NEGOTIATE_MESSAGE(
                msg).decode('ascii'))
            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 = response.connection.send(request, **args_nostream)

        # needed to make NTLM auth compatible with requests-2.3.0

        # Consume content and release the original connection
        # to allow our new request to reuse the same one.
        response2.content
        response2.raw.release_conn()
        request = response2.request.copy()

        # 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]

        auth_strip = auth_type + ' '

        ntlm_header_value = next(
            s for s in (val.lstrip() for val in auth_header_value.split(','))
            if s.startswith(auth_strip)).strip()

        challenge_value = ntlm_header_value[len(auth_strip):]

        # build response
        if self._use_default_credentials:
            # Add challenge to security buffer
            tokenbuf = win32security.PySecBufferType(pkg_info['MaxToken'],
                                                     sspicon.SECBUFFER_TOKEN)
            tokenbuf.Buffer = b64decode(challenge_value)
            sec_buffer.append(tokenbuf)

            # Perform next authorization step
            error, auth = clientauth.authorize(sec_buffer)
            request.headers[auth_header] = '{} {}'.format(
                _package,
                b64encode(auth[0].Buffer).decode('ascii'))
        else:
            ServerChallenge, NegotiateFlags = ntlm.parse_NTLM_CHALLENGE_MESSAGE(
                challenge_value)
            # ntlm returns the headers as a base64 encoded bytestring. Convert to a
            # string.
            auth = '%s %s' % (auth_type,
                              ntlm.create_NTLM_AUTHENTICATE_MESSAGE(
                                  ServerChallenge, self.username, self.domain,
                                  self.password,
                                  NegotiateFlags).decode('ascii'))
            request.headers[auth_header] = auth

        response3 = response2.connection.send(request, **args)

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

        return response3