Exemple #1
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)
Exemple #2
0
 def to_bytes(self):
     format = [self.scheme.encode('ascii'), b' ']
     auth = ntlm.create_NTLM_NEGOTIATE_MESSAGE(self.user, self.type1_flags)
     format.append(auth)
     return b''.join(format)
Exemple #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
Exemple #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)
Exemple #5
0
 def test_ntlm_negotiate_message(self):
     assert "TlRMTVNTUAABAAAAB7IIogYABgAwAAAACAAIACgAAAAFASgKAAAAD1dTMDQyMzc4RE9NQUlO" == create_NTLM_NEGOTIATE_MESSAGE(
         FULL_DOMAIN)
Exemple #6
0
from flask import Flask, request
from ntlm3 import ntlm

app = Flask(__name__)

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

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).decode('ascii')


@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 = {}
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)
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)
Exemple #9
0
 def test_ntlm_negotiate_message(self):
     assert "TlRMTVNTUAABAAAAB7IIogYABgAwAAAACAAIACgAAAAFASgKAAAAD1dTMDQyMzc4RE9NQUlO" == create_NTLM_NEGOTIATE_MESSAGE(FULL_DOMAIN)
Exemple #10
0
from flask import Flask,request
from ntlm3 import ntlm
app = Flask(__name__)

REQUEST_2 = 'NTLM {0!s}'.format(ntlm.create_NTLM_NEGOTIATE_MESSAGE("domain\\username").decode('ascii'))

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

REQUEST_3 = 'NTLM {0!s}'.format(ntlm.create_NTLM_AUTHENTICATE_MESSAGE(ServerChallenge, 'username', 'domain', 'password', NegotiateFlags).decode('ascii'))

@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__":
Exemple #11
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
from flask import Flask,request
from ntlm3 import ntlm
app = Flask(__name__)

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

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).decode('ascii')

@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__":