From 4681adf1bb1d0a1313706d7d96a3ef930ebe5fd9 Mon Sep 17 00:00:00 2001 From: Eduardo Chappa Date: Fri, 29 Sep 2017 23:51:00 -0600 Subject: * NTLM authentication support with the ntlm library, in Unix systems. Based on code provided by Maciej W. Rozycki. --- Makefile.am | 2 +- configure | 118 +++++++++++++++++++++++++++++++++++++-- configure.ac | 48 +++++++++++++++- imap/src/c-client/auth_ntl.c | 112 +++++++++++++++++++++++++++++++++++++ imap/src/osdep/amiga/Makefile | 2 +- imap/src/osdep/nt/makefile.nt | 2 +- imap/src/osdep/nt/makefile.ntk | 3 +- imap/src/osdep/nt/makefile.w2k | 3 +- imap/src/osdep/unix/Makefile | 2 +- imap/src/osdep/unix/Makefile.ntl | 27 +++++++++ pith/pine.hlp | 10 +++- 11 files changed, 315 insertions(+), 14 deletions(-) create mode 100644 imap/src/c-client/auth_ntl.c create mode 100644 imap/src/osdep/unix/Makefile.ntl diff --git a/Makefile.am b/Makefile.am index af73be92..dcb918f1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,7 +27,7 @@ c-client.d: c-client: $(C_CLIENT_WITH_IPV6) - cd imap && $(MAKE) $(C_CLIENT_TARGET) $(C_CLIENT_CFLAGS) $(C_CLIENT_LDFLAGS) $(C_CLIENT_GCCOPTLEVEL) EXTRASPECIALS="$(C_CLIENT_SPECIALS)" + cd imap && $(MAKE) $(C_CLIENT_TARGET) $(C_CLIENT_CFLAGS) $(C_CLIENT_LDFLAGS) $(C_CLIENT_GCCOPTLEVEL) EXTRAAUTHENTICATORS="$(C_CLIENT_AUTHS)" EXTRASPECIALS="$(C_CLIENT_SPECIALS)" gssapi_proxy.l: if test ! -L c-client/auth_gss_proxy.c ; then $(LN_S) @abs_top_srcdir@/web/src/pubcookie/auth_gss_proxy.c c-client/auth_gss_proxy.c ; fi diff --git a/configure b/configure index f2dea087..c1c29580 100755 --- a/configure +++ b/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.ac Rev:21 by chappa@washington.edu. +# From configure.ac Rev:23 by chappa@washington.edu. # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for alpine 2.21.9. # @@ -647,6 +647,7 @@ WEB_BINDIR WEB_BUILD REGEX_BUILD C_CLIENT_SPECIALS +C_CLIENT_AUTHS C_CLIENT_GCCOPTLEVEL C_CLIENT_LDFLAGS C_CLIENT_CFLAGS @@ -918,6 +919,7 @@ with_pthread with_system_mail_directory with_c_client_target with_ipv6 +with_ntlm ' ac_precious_vars='build_alias host_alias @@ -1759,6 +1761,7 @@ Optional Packages: IMAP build target (see imap/Makefile) --without-ipv6 Disable IPv6, primarily to work around resolver problems + --without-ntlm Disable NTLM client support Some influential environment variables: CC C compiler command @@ -3510,8 +3513,8 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -{ $as_echo "$as_me:${as_lineno-$LINENO}: Configuring for $PACKAGE_STRING ($host))" >&5 -$as_echo "$as_me: Configuring for $PACKAGE_STRING ($host))" >&6;} +{ $as_echo "$as_me:${as_lineno-$LINENO}: Configuring for $PACKAGE_STRING ($host)" >&5 +$as_echo "$as_me: Configuring for $PACKAGE_STRING ($host)" >&6;} # start out with intent to build Web Alpine WEB_BUILD=web/src/alpined.d @@ -19181,6 +19184,101 @@ $as_echo "$as_me: NOT including Kerberos Support: $alpine_gss_none_reason" >&6;} fi fi + +# Check whether --with-ntlm was given. +if test "${with_ntlm+set}" = set; then : + withval=$with_ntlm; with_ntlm=$withval +fi + + +if test "x$with_ntlm" = "xno" ; then + alpine_NTLM="none" +else + alpine_NTLM= + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing buildSmbNtlmAuthRequest" >&5 +$as_echo_n "checking for library containing buildSmbNtlmAuthRequest... " >&6; } +if ${ac_cv_search_buildSmbNtlmAuthRequest+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char buildSmbNtlmAuthRequest (); +int +main () +{ +return buildSmbNtlmAuthRequest (); + ; + return 0; +} +_ACEOF +for ac_lib in '' ntlm; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_buildSmbNtlmAuthRequest=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_buildSmbNtlmAuthRequest+:} false; then : + break +fi +done +if ${ac_cv_search_buildSmbNtlmAuthRequest+:} false; then : + +else + ac_cv_search_buildSmbNtlmAuthRequest=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_buildSmbNtlmAuthRequest" >&5 +$as_echo "$ac_cv_search_buildSmbNtlmAuthRequest" >&6; } +ac_res=$ac_cv_search_buildSmbNtlmAuthRequest +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + + ac_fn_c_check_header_mongrel "$LINENO" "ntlm.h" "ac_cv_header_ntlm_h" "$ac_includes_default" +if test "x$ac_cv_header_ntlm_h" = xyes; then : + + extra_auth_ntlm=ntl + { $as_echo "$as_me:${as_lineno-$LINENO}: including NTLM support" >&5 +$as_echo "$as_me: including NTLM support" >&6;} + +else + + alpine_NTLM="none" + alpine_ntlm_none_reason="header file ntlm.h not found" + +fi + + + +else + + alpine_NTLM="none" + alpine_ntlm_none_reason="ntlm library not found" + +fi + + if test -n "$alpine_ntlm_none_reason" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: NOT including NTLM Support: $alpine_ntlm_none_reason" >&5 +$as_echo "$as_me: NOT including NTLM Support: $alpine_ntlm_none_reason" >&6;} + fi +fi + if test -n "$WEB_BUILD" ; then TCL_VERSIONS_DOT="tcl8.6 tcl8.5 tcl8.4 tcl8.3" TCL_VERSIONS_NODOT="`echo ${TCL_VERSIONS_DOT} | ${SED} 's/\.//g'`" @@ -21593,12 +21691,20 @@ $as_echo "$as_me: * * * in Alpine, this might be the reason for them." >&6;} fi fi +extra_auth_gss= if test "x$alpine_GSSTYPE" != "xnone" ; then - c_client_specials="${c_client_specials}EXTRAAUTHENTICATORS=gss " + extra_auth_gss=gss { $as_echo "$as_me:${as_lineno-$LINENO}: * * * Including Kerberos5 functionality" >&5 $as_echo "$as_me: * * * Including Kerberos5 functionality" >&6;} fi +extra_auth_ntlm= +if test "x$alpine_NTLM" != "xnone" ; then + extra_auth_ntlm=ntl + { $as_echo "$as_me:${as_lineno-$LINENO}: * * * Including NTLM Authenticator" >&5 +$as_echo "$as_me: * * * Including NTLM Authenticator" >&6;} +fi + if test -n "$CPPFLAGS" ; then alpine_c_client_cflags="$alpine_c_client_cflags ${CPPFLAGS}" fi @@ -21628,6 +21734,10 @@ if test -n "$alpine_c_client_gccoptlevel" ; then fi +c_client_auths="$extra_auth_gss $extra_auth_ntlm" +C_CLIENT_AUTHS=$c_client_auths + + C_CLIENT_SPECIALS=$c_client_specials diff --git a/configure.ac b/configure.ac index 8c06f870..82666843 100644 --- a/configure.ac +++ b/configure.ac @@ -15,7 +15,7 @@ dnl */ AC_PREREQ([2.69]) -AC_REVISION([Rev:21 by chappa@washington.edu]) +AC_REVISION([Rev:23 by chappa@washington.edu]) dnl Alpine Version Number is in $srcdir/VERSION AC_INIT([alpine],[m4_normalize(m4_include(VERSION))],[chappa@washington.edu]) @@ -31,7 +31,7 @@ AC_CANONICAL_HOST AC_LANG(C) -AC_MSG_NOTICE([Configuring for $PACKAGE_STRING ($host))]) +AC_MSG_NOTICE([Configuring for $PACKAGE_STRING ($host)]) # start out with intent to build Web Alpine WEB_BUILD=web/src/alpined.d @@ -1584,6 +1584,38 @@ if test "x$alpine_GSSTYPE" != "xnone" ; then fi fi +dnl Include NTLM? +AC_ARG_WITH(ntlm, + AC_HELP_STRING([--without-ntlm],[Disable NTLM client support]), + [with_ntlm=$withval]) + +dnl provide NTLM support? +if test "x$with_ntlm" = "xno" ; then + alpine_NTLM="none" +else + alpine_NTLM= + + AC_SEARCH_LIBS(buildSmbNtlmAuthRequest, ntlm, + [ + AC_CHECK_HEADER([ntlm.h], + [ + extra_auth_ntlm=ntl + AC_MSG_NOTICE([including NTLM support]) + ], + [ + alpine_NTLM="none" + alpine_ntlm_none_reason="header file ntlm.h not found" + ]) + ], + [ + alpine_NTLM="none" + alpine_ntlm_none_reason="ntlm library not found" + ]) + if test -n "$alpine_ntlm_none_reason" ; then + AC_MSG_NOTICE([NOT including NTLM Support: $alpine_ntlm_none_reason]) + fi +fi + dnl check for tcl libraries for Web Alpine (HACKY) if test -n "$WEB_BUILD" ; then TCL_VERSIONS_DOT="tcl8.6 tcl8.5 tcl8.4 tcl8.3" @@ -1985,11 +2017,18 @@ else fi fi +extra_auth_gss= if test "x$alpine_GSSTYPE" != "xnone" ; then - c_client_specials="${c_client_specials}EXTRAAUTHENTICATORS=gss " + extra_auth_gss=gss AC_MSG_NOTICE([* * * Including Kerberos5 functionality]) fi +extra_auth_ntlm= +if test "x$alpine_NTLM" != "xnone" ; then + extra_auth_ntlm=ntl + AC_MSG_NOTICE([* * * Including NTLM Authenticator]) +fi + if test -n "$CPPFLAGS" ; then alpine_c_client_cflags="$alpine_c_client_cflags ${CPPFLAGS}" fi @@ -2016,6 +2055,9 @@ if test -n "$alpine_c_client_gccoptlevel" ; then AC_SUBST(C_CLIENT_GCCOPTLEVEL, GCCOPTLEVEL=\"$alpine_c_client_gccoptlevel\") fi +c_client_auths="$extra_auth_gss $extra_auth_ntlm" +AC_SUBST([C_CLIENT_AUTHS], $c_client_auths) + AC_SUBST([C_CLIENT_SPECIALS], $c_client_specials) dnl Deal with Web Alpine diff --git a/imap/src/c-client/auth_ntl.c b/imap/src/c-client/auth_ntl.c new file mode 100644 index 00000000..0afe99fc --- /dev/null +++ b/imap/src/c-client/auth_ntl.c @@ -0,0 +1,112 @@ +/* ======================================================================== + * Copyright 1988-2008 University of Washington + * Copyright 2015 Imagination Technologies + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * + * ======================================================================== + */ + +/* + * Program: NT LAN Manager authenticator + * + * Author: Maciej W. Rozycki + * + * Date: 25 January 2015 + * Last Edited: 25 January 2015 + */ + +#include + +long auth_ntlm_client (authchallenge_t challenger,authrespond_t responder, + char *service,NETMBX *mb,void *stream, + unsigned long *trial,char *user); + +AUTHENTICATOR auth_ntl = { /* secure, has full auth, hidden */ + AU_SECURE | AU_AUTHUSER | AU_HIDE, + "NTLM", /* authenticator name */ + NIL, /* always valid */ + auth_ntlm_client, /* client method */ + NIL, /* no server method */ + NIL /* next authenticator */ +}; + +/* Client authenticator + * Accepts: challenger function + * responder function + * SASL service name + * parsed network mailbox structure + * stream argument for functions + * pointer to current trial count + * returned user name + * Returns: T if success, NIL otherwise, number of trials incremented if retry + */ + +long auth_ntlm_client (authchallenge_t challenger, authrespond_t responder, + char *service, NETMBX *mb, void *stream, + unsigned long *trial, char *user) +{ + tSmbNtlmAuthChallenge *challenge; + tSmbNtlmAuthResponse response; + tSmbNtlmAuthRequest request; + char tbuf[MAILTMPLEN]; + char ubuf[MAILTMPLEN]; + char pass[MAILTMPLEN]; + unsigned long clen; + unsigned long ulen; + unsigned long dlen; + long ret = NIL; + char *sep; + + /* get initial (empty) challenge */ + if (challenge = (*challenger) (stream, &clen)) { + fs_give ((void **) &challenge); + pass[0] = NIL; /* prompt user */ + mm_login (mb, user, pass, *trial); + if (!pass[0]) { /* user requested abort */ + (*responder) (stream, NIL, 0); + *trial = 0; /* cancel subsequent attempts */ + ret = LONGT; /* will get a BAD response back */ + } else { + /* translate domain\user to user@domain */ + /* otherwise buildSmbNtlmAuthResponse */ + /* will override the domain requested with */ + /* one returned by the challenge message */ + sep = strchr (user, '\\'); + if (*sep) { + dlen = sep - user; + ulen = strlen (sep + 1); + memcpy (ubuf, sep + 1, ulen); + ubuf[ulen] = '@'; + memcpy (ubuf + ulen + 1, user, dlen); + ubuf[ulen + dlen + 1] = '\0'; + user = ubuf; + } + buildSmbNtlmAuthRequest (&request, user, NULL); + /* send a negotiate message */ + if ((*responder) (stream, (void *) &request, SmbLength (&request)) && + (challenge = (*challenger) (stream, &clen))) { + /* interpret the challenge message */ + buildSmbNtlmAuthResponse (challenge, &response, user, pass); + fs_give ((void **) &challenge); + /* send a response message */ + if ((*responder) (stream, (void *) &response, SmbLength (&response))) { + if (challenge = (*challenger) (stream, &clen)) + fs_give ((void **) &challenge); + else { + ++*trial; /* can try again if necessary */ + ret = LONGT; /* check the authentication */ + } + } + } + } + } + memset (pass,0,MAILTMPLEN); /* erase password */ + if (!ret) *trial = 65535; /* don't retry if bad protocol */ + return ret; +} diff --git a/imap/src/osdep/amiga/Makefile b/imap/src/osdep/amiga/Makefile index 1f08e97e..60458e61 100644 --- a/imap/src/osdep/amiga/Makefile +++ b/imap/src/osdep/amiga/Makefile @@ -187,7 +187,7 @@ osdep.o:mail.h misc.h env.h fs.h ftl.h nl.h tcp.h \ osdep.c env_ami.c fs_ami.c ftl_ami.c nl_ami.c tcp_ami.c \ auths.c gethstid.c \ gr_waitp.c \ - auth_log.c auth_md5.c auth_pla.c \ + auth_log.c auth_md5.c auth_ntl.c auth_pla.c \ pmatch.c scandir.c \ tz_bsd.c \ write.c \ diff --git a/imap/src/osdep/nt/makefile.nt b/imap/src/osdep/nt/makefile.nt index 0ea96e5a..a30dfc40 100644 --- a/imap/src/osdep/nt/makefile.nt +++ b/imap/src/osdep/nt/makefile.nt @@ -84,7 +84,7 @@ smtp.obj: mail.h smtp.h rfc822.h misc.h osdep.h smtp.c os_nt.obj: mail.h osdep.h env_nt.h fs.h ftl.h nl.h tcp.h tcp_nt.h yunchan.h \ os_nt.c fs_nt.c ftl_nt.c nl_nt.c env_nt.c ssl_nt.c ssl_none.c \ ip_nt.c tcp_nt.c yunchan.c pmatch.c write.c \ - mailfile.h auth_md5.c auth_pla.c auth_log.c + mailfile.h auth_md5.c auth_ntl.c auth_pla.c auth_log.c mbxnt.obj: mail.h misc.h osdep.h mbxnt.c diff --git a/imap/src/osdep/nt/makefile.ntk b/imap/src/osdep/nt/makefile.ntk index e383e0f8..507d7541 100644 --- a/imap/src/osdep/nt/makefile.ntk +++ b/imap/src/osdep/nt/makefile.ntk @@ -84,7 +84,8 @@ smtp.obj: mail.h smtp.h rfc822.h misc.h osdep.h smtp.c os_ntk.obj: mail.h osdep.h env_nt.h fs.h ftl.h nl.h tcp.h tcp_nt.h yunchan.h \ os_ntk.c fs_nt.c ftl_nt.c nl_nt.c env_nt.c ssl_nt.c ssl_none.c \ ip_nt.c tcp_nt.c yunchan.c pmatch.c write.c \ - mailfile.h auth_gss.c auth_md5.c auth_pla.c auth_log.c kerb_mit.c + mailfile.h auth_gss.c auth_md5.c auth_ntl.c auth_pla.c auth_log.c \ + kerb_mit.c mbxnt.obj: mail.h misc.h osdep.h mbxnt.c diff --git a/imap/src/osdep/nt/makefile.w2k b/imap/src/osdep/nt/makefile.w2k index a3d62ad6..a58f0274 100644 --- a/imap/src/osdep/nt/makefile.w2k +++ b/imap/src/osdep/nt/makefile.w2k @@ -85,7 +85,8 @@ smtp.obj: mail.h smtp.h rfc822.h misc.h osdep.h smtp.c os_w2k.obj: mail.h osdep.h env_nt.h fs.h ftl.h nl.h tcp.h tcp_nt.h yunchan.h \ os_w2k.c fs_nt.c ftl_nt.c nl_nt.c env_nt.c ssl_w2k.c ssl_none.c \ ip_nt.c tcp_nt.c yunchan.c pmatch.c write.c \ - mailfile.h auth_gss.c auth_md5.c auth_pla.c auth_log.c kerb_w2k.c + mailfile.h auth_gss.c auth_md5.c auth_ntl.c auth_pla.c auth_log.c \ + kerb_w2k.c mbxnt.obj: mail.h misc.h osdep.h mbxnt.c diff --git a/imap/src/osdep/unix/Makefile b/imap/src/osdep/unix/Makefile index 14975c82..8d740bb4 100644 --- a/imap/src/osdep/unix/Makefile +++ b/imap/src/osdep/unix/Makefile @@ -922,7 +922,7 @@ osdep.o:mail.h misc.h env.h fs.h ftl.h nl.h tcp.h \ gethstid.c getspnam.c \ gr_wait.c gr_wait4.c gr_waitp.c \ kerb_mit.c \ - auth_ext.c auth_gss.c auth_log.c auth_md5.c auth_pla.c \ + auth_ext.c auth_gss.c auth_log.c auth_md5.c auth_ntl.c auth_pla.c \ pmatch.c scandir.c setpgrp.c strerror.c truncate.c write.c \ memmove.c memmove2.c memset.c \ tz_bsd.c tz_nul.c tz_sv4.c \ diff --git a/imap/src/osdep/unix/Makefile.ntl b/imap/src/osdep/unix/Makefile.ntl new file mode 100644 index 00000000..2ffa78ff --- /dev/null +++ b/imap/src/osdep/unix/Makefile.ntl @@ -0,0 +1,27 @@ +# ======================================================================== +# Copyright 1988-2007 University of Washington +# Copyright 2015 Imagination Technologies +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# +# ======================================================================== + +# Program: NTLM makefile +# +# Author: Maciej W. Rozycki +# +# Date: 25 January 2015 +# Last Edited: 25 January 2015 + + +# Extended flags needed for additional authenticators. You may need to modify. + +NTLMLDFLAGS= -lntlm + +ntl: # NTLM flags + echo $(NTLMLDFLAGS) >> LDFLAGS diff --git a/pith/pine.hlp b/pith/pine.hlp index e4a2bac0..8e76ec20 100644 --- a/pith/pine.hlp +++ b/pith/pine.hlp @@ -140,7 +140,7 @@ with help text for the config screen and the composer that didn't have any reasonable place to be called from. Dummy change to get revision in pine.hlp ============= h_revision ================= -Alpine Commit 221 2017-09-29 22:01:56 +Alpine Commit 222 2017-09-29 23:39:51 ============= h_news ================= @@ -176,6 +176,14 @@ Apache web server. Version () addresses bugs found in previous releases and has a few additions as well. +

+Additions include: + +

+

Bugs that have been addressed include: