<<< Date Index >>>     <<< Thread Index >>>

[no subject]



I couldn't get NTLM authentication to work with an Exchange IMAP server.
I always got a "SASL authentication failed." error.  I tried both 1.5.13
and CVS.  The changes on 2006-04-18 to fix Exchange + NTLM issues didn't
make things work for me.  So I took Grant Edwards' NTLM patch
(mutt-1.2.5-ntlmauth.patch) and produced a patch against mutt-1.5.13.
And it works!  The files involved are

    configure.in
    imap/Makefile.am
    imap/auth.c
    imap/auth.h
    imap/auth_ntlm.c
    imap/command.c
    imap/imap_private.h

I am new to this list and to the mutt source code and IMAP; I hope it is
OK to attach the patch here.  Are there any issues with incorporating
this into mutt?

To get the patch working, you need to:

+ Have libntlm installed
+ Use the configure flag --with-ntlm
+ Use the format
    set imap_user=user@domain
  in your muttrc instead of "domain\\user"

Best,
Hsiu-Khuern.
--- mutt-1.5.13/imap/Makefile.am        2006-07-18 11:16:24.000000000 -0700
+++ mutt-1.5.13-patched/imap/Makefile.am        2006-10-18 19:10:22.000000000 
-0700
@@ -9,12 +9,12 @@
 endif
 
 if USE_SASL
-AUTHENTICATORS = auth_sasl.c
+AUTHENTICATORS = auth_ntlm.c auth_sasl.c
 else
-AUTHENTICATORS = auth_anon.c auth_cram.c
+AUTHENTICATORS = auth_anon.c auth_cram.c auth_ntlm.c
 endif
 
-EXTRA_DIST = BUGS README TODO auth_anon.c auth_cram.c auth_gss.c auth_sasl.c
+EXTRA_DIST = BUGS README TODO auth_anon.c auth_cram.c auth_gss.c auth_ntlm.c 
auth_sasl.c
 
 AM_CPPFLAGS = -I$(top_srcdir) -I../intl
 
--- mutt-1.5.13/imap/auth.c     2005-09-18 01:22:23.000000000 -0700
+++ mutt-1.5.13-patched/imap/auth.c     2006-10-18 19:08:03.000000000 -0700
@@ -29,6 +29,9 @@
 #include "auth.h"
 
 static imap_auth_t imap_authenticators[] = {
+#ifdef USE_NTLM
+  { imap_auth_ntlm, NULL },
+#endif
 #ifdef USE_SASL
   { imap_auth_sasl, NULL },
 #else
--- mutt-1.5.13/imap/auth.h     2005-09-18 01:22:23.000000000 -0700
+++ mutt-1.5.13-patched/imap/auth.h     2006-10-18 19:05:39.000000000 -0700
@@ -48,6 +48,9 @@
 #ifdef USE_GSS
 imap_auth_res_t imap_auth_gss (IMAP_DATA* idata, const char* method);
 #endif
+#ifdef USE_NTLM
+imap_auth_res_t imap_auth_ntlm (IMAP_DATA* idata, const char* method);
+#endif
 #ifdef USE_SASL
 imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata, const char* method);
 #endif
--- mutt-1.5.13/imap/auth_ntlm.c        1969-12-31 16:00:00.000000000 -0800
+++ mutt-1.5.13-patched/imap/auth_ntlm.c        2006-10-19 01:38:52.000000000 
-0700
@@ -0,0 +1,113 @@
+/* NTLM login/authentication code */
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "mutt.h"
+#include "imap_private.h"
+#include "auth.h"
+
+#include <ntlm.h>
+
+imap_auth_res_t imap_auth_ntlm (IMAP_DATA* idata, const char* method)
+{
+  char buf[LONG_STRING];
+  int len, rc;
+  tSmbNtlmAuthRequest   request;              
+  tSmbNtlmAuthChallenge challenge;
+  tSmbNtlmAuthResponse  response;
+
+  if (!mutt_bit_isset (idata->capabilities, ANTLM))
+    return IMAP_AUTH_UNAVAIL;
+
+  mutt_message _("Authenticating (NTLM)...");
+
+  /* get auth info */
+  if (mutt_account_getlogin (&idata->conn->account))
+    return IMAP_AUTH_FAILURE;
+  if (mutt_account_getpass (&idata->conn->account))
+    return IMAP_AUTH_FAILURE;
+
+  imap_cmd_start (idata, "AUTHENTICATE NTLM");
+
+  do
+    rc = imap_cmd_step (idata);
+  while (rc == IMAP_CMD_CONTINUE);
+  
+  if (rc != IMAP_CMD_RESPOND)
+  {
+    dprint (1, (debugfile, "Invalid response from server: %s\n", idata->buf));
+    goto bail;
+  }
+
+  /* Need to handle the case where Exchange incorrectly returns +\r\n instead
+   * of + \r\n? */
+
+  buildSmbNtlmAuthRequest(&request, idata->conn->account.user, "AMERICAS");
+
+#ifdef DEBUG
+  if (debuglevel > 0)
+    dumpSmbNtlmAuthRequest(debugfile, &request);
+#endif  
+
+  memset(buf, 0, sizeof buf);
+  mutt_to_base64((unsigned char*)buf, (unsigned char*)&request,
+    SmbLength(&request), sizeof (buf) - 2);
+  safe_strcat (buf, sizeof buf, "\r\n");
+
+  mutt_socket_write (idata->conn, buf);
+
+  do
+    rc = imap_cmd_step (idata);
+  while (rc == IMAP_CMD_CONTINUE);
+
+  if (rc != IMAP_CMD_RESPOND)
+  {
+    dprint (1, (debugfile, "Invalid response from server: %s\n", idata->buf));
+    goto bail;
+  }
+
+  if ((idata->buf[0] != '+') || (idata->buf[1] != ' '))
+    goto bail;
+
+  len = mutt_from_base64((char*)&challenge, idata->buf+2);
+
+#ifdef DEBUG
+  if (debuglevel > 0)
+    dumpSmbNtlmAuthChallenge(debugfile, &challenge);
+#endif
+ 
+  buildSmbNtlmAuthResponse(&challenge, &response, idata->conn->account.user,
+    idata->conn->account.pass);
+ 
+#ifdef DEBUG
+  if (debuglevel > 0)
+    dumpSmbNtlmAuthResponse(debugfile, &response);
+#endif
+   
+  memset(buf, 0, sizeof buf);
+  mutt_to_base64((unsigned char*)buf, (unsigned char*)&response, 
SmbLength(&response),
+    sizeof (buf) - 2);
+  safe_strcat (buf, sizeof buf, "\r\n");
+ 
+  mutt_socket_write (idata->conn, buf);
+
+  do
+    rc = imap_cmd_step (idata);
+  while (rc == IMAP_CMD_CONTINUE);
+
+  if (rc != IMAP_CMD_OK)
+  {
+    dprint (1, (debugfile, "Error receiving server response.\n"));
+    goto bail;
+  }
+
+  if (imap_code (idata->buf))
+    return IMAP_AUTH_SUCCESS;
+
+ bail:
+  mutt_error _("NTLM authentication failed.");
+  mutt_sleep (2);
+  return IMAP_AUTH_FAILURE;
+}
--- mutt-1.5.13/imap/command.c  2006-08-11 02:04:36.000000000 -0700
+++ mutt-1.5.13-patched/imap/command.c  2006-10-18 18:40:13.000000000 -0700
@@ -58,6 +58,7 @@
   "NAMESPACE",
   "AUTH=CRAM-MD5",
   "AUTH=GSSAPI",
+  "AUTH=NTLM", 
   "AUTH=ANONYMOUS",
   "STARTTLS",
   "LOGINDISABLED",
--- mutt-1.5.13/imap/imap_private.h     2006-08-11 02:04:36.000000000 -0700
+++ mutt-1.5.13-patched/imap/imap_private.h     2006-10-18 18:39:10.000000000 
-0700
@@ -120,6 +120,7 @@
   NAMESPACE,                           /* RFC 2342: IMAP4 Namespace */
   ACRAM_MD5,                   /* RFC 2195: CRAM-MD5 authentication */
   AGSSAPI,                     /* RFC 1731: GSSAPI authentication */
+  ANTLM,                        /* AUTH=NTLM for MS Exchange Server */
   AUTH_ANON,                   /* AUTH=ANONYMOUS */
   STARTTLS,                    /* RFC 2595: STARTTLS */
   LOGINDISABLED,               /*           LOGINDISABLED */
--- mutt-1.5.13/configure.in    2006-08-14 07:09:18.000000000 -0700
+++ mutt-1.5.13-patched/configure.in    2006-10-18 19:01:58.000000000 -0700
@@ -594,6 +594,34 @@
 
 dnl -- imap dependencies --
 
+AC_ARG_WITH(ntlm, AC_HELP_STRING([--with-ntlm[=PFX]], [Compile in NTLM 
authentication for IMAP]), 
+      [
+      if test "$with_ntlm" != "no"
+      then
+       if test "$need_imap" = "yes"
+       then
+         if test "$with_ntlm" != "yes"
+         then
+           CPPFLAGS="$CPPFLAGS -I$with_ntlm/include"
+           LDFLAGS="$LDFLAGS -L$with_ntlm/lib"
+         fi
+
+         saved_LIBS="$LIBS"
+         AC_CHECK_LIB(ntlm, buildSmbNtlmAuthResponse,,
+           AC_MSG_ERROR([could not find libntlm which is needed for ntlm 
authentication]))
+         LIBS="$saved_LIBS"
+         MUTTLIBS="$MUTTLIBS -lntlm"
+         AC_DEFINE([USE_NTLM], 1, [ Define if you want support for NTLM. ])
+
+         need_ntlm=yes
+
+       else
+         AC_MSG_WARN([NTLM was requested but IMAP is not enabled])
+       fi
+      fi
+])
+AM_CONDITIONAL(USE_NTLM, test x$need_ntlm = xyes)
+
 AC_ARG_WITH(gss, AC_HELP_STRING([--with-gss[=PFX]], [Compile in GSSAPI 
authentication for IMAP]), 
     gss_prefix="$withval", gss_prefix="no")
 if test "$gss_prefix" != "no"