Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SMTP through Exchange using Integrated Windows Authentication (NTLM) using Python

I want to use the credentials of the logged-in Windows user to authenticate an SMTP connection to an Exchange server using NTLM.

I'm aware of the python-ntlm module and the two patches that enable NTLM authentication for SMTP, however I want to use the current user's security token and not have to supply a username and password.

Very similar problem to Windows Authentication with Python and urllib2.

like image 335
Louis Avatar asked May 26 '10 20:05

Louis


People also ask

Does Exchange use NTLM authentication?

NTLM authenticationWorks "out of the box" with your Exchange server. You can configure access to Exchange services by using an Exchange Management Shell cmdlet.

Does Windows authentication use NTLM?

Windows Challenge/Response (NTLM) is the authentication protocol used on networks that include systems running the Windows operating system and on stand-alone systems. The Microsoft Kerberos security package adds greater security than NTLM to systems on a network.


2 Answers

Although the solution below only uses the Python Win32 extensions (the sspi example code included with the Python Win32 extensions was very helpful), the python-ntlm IMAP & SMTP patches mentioned in the question also served as useful guides.

from smtplib import SMTPException, SMTPAuthenticationError
import string
import base64
import sspi

# NTLM Guide -- http://curl.haxx.se/rfc/ntlm.html

SMTP_EHLO_OKAY = 250
SMTP_AUTH_CHALLENGE = 334
SMTP_AUTH_OKAY = 235

def asbase64(msg):
    # encoding the message then convert to string
    return base64.b64encode(msg).decode("utf-8")

def connect_to_exchange_as_current_user(smtp):
    """Example:
    >>> import smtplib
    >>> smtp = smtplib.SMTP("my.smtp.server")
    >>> connect_to_exchange_as_current_user(smtp)
    """

    # Send the SMTP EHLO command
    code, response = smtp.ehlo()
    if code != SMTP_EHLO_OKAY:
        raise SMTPException("Server did not respond as expected to EHLO command")

    sspiclient = sspi.ClientAuth('NTLM')

    # Generate the NTLM Type 1 message
    sec_buffer=None
    err, sec_buffer = sspiclient.authorize(sec_buffer)
    ntlm_message = asbase64(sec_buffer[0].Buffer)

    # Send the NTLM Type 1 message -- Authentication Request
    code, response = smtp.docmd("AUTH", "NTLM " + ntlm_message)

    # Verify the NTLM Type 2 response -- Challenge Message
    if code != SMTP_AUTH_CHALLENGE:
        raise SMTPException("Server did not respond as expected to NTLM negotiate message")

    # Generate the NTLM Type 3 message
    err, sec_buffer = sspiclient.authorize(base64.decodebytes(response))
    ntlm_message = asbase64(sec_buffer[0].Buffer)

    # Send the NTLM Type 3 message -- Response Message
    code, response = smtp.docmd(ntlm_message)
    if code != SMTP_AUTH_OKAY:
        raise SMTPAuthenticationError(code, response)
like image 147
Louis Avatar answered Nov 01 '22 11:11

Louis


Great answer but as an update for python 3

def asbase64(msg):
    # encoding the message then convert to string
    return base64.b64encode(msg).decode("utf-8")
like image 22
techmakin Avatar answered Nov 01 '22 10:11

techmakin