From 736db44524864225b719eda2262cd4b2a940304b Mon Sep 17 00:00:00 2001 From: "Eric S. Raymond" Date: Thu, 17 Jul 2003 15:19:56 +0000 Subject: [PATCH] Yet another round of fixes. svn path=/trunk/; revision=3819 --- NEWS | 2 ++ configure.in | 10 +++--- pop3.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++ socket.c | 41 +++++++++++++++++++++++ 4 files changed, 142 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 38d0944b..0c62a7f4 100644 --- a/NEWS +++ b/NEWS @@ -13,6 +13,8 @@ * Sunil Shetye's configure.in patch to avoid spurious search order messages from GCC. * Header-reading code now copes better with lines ending in \n only. +* Elias Israel's patches for POP3 NTLM support and dealing with byte- + stuffing failures at socket level. fetchmail-6.2.2 (Fri Feb 28 21:34:26 EST 2003), 22345 lines: diff --git a/configure.in b/configure.in index 6b86ebd0..197a0410 100644 --- a/configure.in +++ b/configure.in @@ -601,7 +601,7 @@ then then ### ssl.h found under openssl. Use openssl configuration preferentially echo "Enabling OpenSSL support in $with_ssl" - CEFLAGS="$CEFLAGS -I$with_ssl/include -I$with_ssl/include/openssl" + CEFLAGS="$CEFLAGS -I$with_ssl/include/openssl" ### OpenBSD comes with ssl headers elif test -r /usr/include/ssl/ssl.h then @@ -609,7 +609,7 @@ then CEFLAGS="$CEFLAGS -I/usr/include/ssl" else echo "Enabling SSLeay support in $with_ssl" - CEFLAGS="$CEFLAGS -I$with_ssl/include" + test "$with_ssl" != "/usr" && CEFLAGS="$CEFLAGS -I$with_ssl/include" fi LDEFLAGS="$LDEFLAGS -L$with_ssl/lib" LIBS="$LIBS -lssl -lcrypto" @@ -668,7 +668,8 @@ x) do if test -f "$dir/include/hesiod.h" then - test "$dir" != "/usr" && CEFLAGS="$CEFLAGS -DHESIOD -I$dir/include" + CEFLAGS="$CEFLAGS -DHESIOD" + test "$dir" != "/usr" && CEFLAGS="$CEFLAGS -I$dir/include" LDEFLAGS="$LDEFLAGS -L$dir/lib" LIBS="$LIBS -lhesiod" with_hesiod=$dir @@ -678,7 +679,8 @@ x) ;; *) # Path given - CEFLAGS="$CEFLAGS -DHESIOD -I$with_hesiod/include" + CEFLAGS="$CEFLAGS -DHESIOD" + test "$with_hesiod" != "/usr" && CEFLAGS="$CEFLAGS -I$with_hesiod/include" LDEFLAGS="$LDEFLAGS -L$with_hesiod/lib" LIBS="$LIBS -lhesiod" ;; diff --git a/pop3.c b/pop3.c index 50673ffe..1c06c207 100644 --- a/pop3.c +++ b/pop3.c @@ -54,6 +54,84 @@ static char lastok[POPBUFSIZE+1]; flag has_ssl = FALSE; #endif /* SSL_ENABLE */ +#if NTLM_ENABLE +#include "ntlm.h" + +static tSmbNtlmAuthRequest request; +static tSmbNtlmAuthChallenge challenge; +static tSmbNtlmAuthResponse response; + +/* + * NTLM support by Grant Edwards. + * + * Handle MS-Exchange NTLM authentication method. This is the same + * as the NTLM auth used by Samba for SMB related services. We just + * encode the packets in base64 instead of sending them out via a + * network interface. + * + * Much source (ntlm.h, smb*.c smb*.h) was borrowed from Samba. + */ + +static int do_pop3_ntlm(int sock, struct query *ctl) +{ + char msgbuf[2048]; + int result,len; + + gen_send(sock, "AUTH MSN"); + + if ((result = gen_recv(sock, msgbuf, sizeof msgbuf))) + return result; + + if (msgbuf[0] != '+') + return PS_AUTHFAIL; + + buildSmbNtlmAuthRequest(&request,ctl->remotename,NULL); + + if (outlevel >= O_DEBUG) + dumpSmbNtlmAuthRequest(stdout, &request); + + memset(msgbuf,0,sizeof msgbuf); + to64frombits (msgbuf, (unsigned char*)&request, SmbLength(&request)); + + if (outlevel >= O_MONITOR) + report(stdout, "POP3> %s\n", msgbuf); + + strcat(msgbuf,"\r\n"); + SockWrite (sock, msgbuf, strlen (msgbuf)); + + if ((gen_recv(sock, msgbuf, sizeof msgbuf))) + return result; + + len = from64tobits ((unsigned char*)&challenge, msgbuf, sizeof(msgbuf)); + + if (outlevel >= O_DEBUG) + dumpSmbNtlmAuthChallenge(stdout, &challenge); + + buildSmbNtlmAuthResponse(&challenge, &response,ctl->remotename,ctl->password); + + if (outlevel >= O_DEBUG) + dumpSmbNtlmAuthResponse(stdout, &response); + + memset(msgbuf,0,sizeof msgbuf); + to64frombits (msgbuf, (unsigned char*)&response, SmbLength(&response)); + + if (outlevel >= O_MONITOR) + report(stdout, "POP3> %s\n", msgbuf); + + strcat(msgbuf,"\r\n"); + SockWrite (sock, msgbuf, strlen (msgbuf)); + + if ((result = gen_recv (sock, msgbuf, sizeof msgbuf))) + return result; + + if (strstr (msgbuf, "OK")) + return PS_SUCCESS; + else + return PS_AUTHFAIL; +} +#endif /* NTLM */ + + #define DOTLINE(s) (s[0] == '.' && (s[1]=='\r'||s[1]=='\n'||s[1]=='\0')) static int pop3_ok (int sock, char *argbuf) @@ -205,6 +283,21 @@ static int pop3_getauth(int sock, struct query *ctl, char *greeting) if (!(ctl->server.sdps) && MULTIDROP(ctl) && strstr(greeting, "demon.")) ctl->server.sdps = TRUE; #endif /* SDPS_ENABLE */ +#ifdef NTLM_ENABLE + /* MSN servers require the use of NTLM (MSN) authentication */ + if (!strcasecmp(ctl->server.pollname, "pop3.email.msn.com") || + ctl->server.authenticate == A_NTLM) + { + if (!do_pop3_ntlm(sock, ctl)) + { + return(PS_SUCCESS); + } + else + { + return(PS_AUTHFAIL); + } + } +#endif switch (ctl->server.protocol) { case P_POP3: diff --git a/socket.c b/socket.c index 47f074dd..5f295a04 100644 --- a/socket.c +++ b/socket.c @@ -540,6 +540,7 @@ int SockRead(int sock, char *buf, int len) { char *newline, *bp = buf; int n; + int maxavailable = 0; #ifdef SSL_ENABLE SSL *ssl; #endif @@ -579,6 +580,7 @@ int SockRead(int sock, char *buf, int len) (void)SSL_get_error(ssl, n); return(-1); } + maxavailable = n; if( 0 == n ) { /* SSL_peek says no data... Does he mean no data or did the connection blow up? If we got an error @@ -622,6 +624,7 @@ int SockRead(int sock, char *buf, int len) if ((n = fm_peek(sock, bp, len)) <= 0) #endif return (-1); + maxavailable = n; if ((newline = memchr(bp, '\n', n)) != NULL) n = newline - bp + 1; #ifndef __BEOS__ @@ -634,6 +637,44 @@ int SockRead(int sock, char *buf, int len) } while (!newline && len); *bp = '\0'; + /* OK, very weird hack coming up here: + * When POP and IMAP servers send us a message, they're supposed to + * terminate the message with a line containing only a dot. To protect + * against lines in the real message that might contain only a dot, + * they're supposed to preface any line that starts with a dot with + * an additional dot, which will be removed on the client side. That + * process, called byte-stuffing (and unstuffing) is really not the + * concern of this low-level routine, ordinarily, but there are some + * POP servers (and maybe IMAP servers too, who knows) that fail to + * do the byte-stuffing, and this routine is the best place to try to + * identify and fix that fault. + * + * Since the DOT line is supposed to come only at the end of a + * message, the implication is that right after we see it, the server + * is supposed to go back to waiting for the next command. There + * isn't supposed to be any more data to read after we see the dot. + * THEREFORE, if we see more data to be read after something that + * looks like the dot line, then probably the server is failing to + * do byte-stuffing. In that case, we'll byte-pack it for them so + * that the higher-level routines see things as hunky-dorey. + * This is not a perfect test or fix by any means (it has an + * obvious race condition, for one thing), but it should at least + * reduce the nastiness that ensues when people don't know how + * to write POP servers. + */ + if ((maxavailable > (bp-buf)) && + ((((bp-buf) == 3) && + (buf[0] == '.') && + (buf[1] == '\r') && + (buf[2] == '\n')) || + (((bp-buf) == 2) && + (buf[0] == '.') && + (buf[1] == '\n')))) { + + memmove(buf+1, buf, (bp-buf)+1); + buf[0] = '.'; + bp++; + } return bp - buf; } -- 2.43.2