X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=ntlmsubr.c;h=63cbed8f34a91fae338e3f1c0f6f6044de554895;hb=c189f6a54f36f5b6f7734303db3cfc52311aab5f;hp=ab685ff04a23a850429db89cae63430457e43a3c;hpb=c0db499f36439269c81c0d83fc4655502985bbc5;p=~andy%2Ffetchmail diff --git a/ntlmsubr.c b/ntlmsubr.c index ab685ff0..63cbed8f 100644 --- a/ntlmsubr.c +++ b/ntlmsubr.c @@ -2,6 +2,7 @@ #ifdef NTLM_ENABLE #include "fetchmail.h" +#include "i18n.h" #include "ntlm.h" #include "socket.h" @@ -29,8 +30,13 @@ int ntlm_helper(int sock, struct query *ctl, const char *proto) if ((result = gen_recv(sock, msgbuf, sizeof msgbuf))) return result; - if (0 != strcmp(msgbuf, "+ ")) - return PS_AUTHFAIL; + if (msgbuf[0] != '+' && strspn(msgbuf+1, " \t") < strlen(msgbuf+1)) { + if (outlevel >= O_VERBOSE) { + report(stdout, GT_("Warning: received malformed challenge to \"AUTH(ENTICATE) NTLM\"!\n")); + } + result = PS_AUTHFAIL; + goto cancelfail; + } buildSmbNtlmAuthRequest(&request,ctl->remotename,NULL); @@ -46,10 +52,35 @@ int ntlm_helper(int sock, struct query *ctl, const char *proto) strcat(msgbuf,"\r\n"); SockWrite (sock, msgbuf, strlen (msgbuf)); - if ((gen_recv(sock, msgbuf, sizeof msgbuf))) - return result; - - (void)from64tobits (&challenge, msgbuf, sizeof(challenge)); + if ((result = gen_recv(sock, msgbuf, sizeof msgbuf))) + goto cancelfail; + + if ((result = from64tobits (&challenge, msgbuf, sizeof(challenge))) < 0 + || result < ((void *)&challenge.context - (void *)&challenge)) + { + report (stderr, GT_("could not decode BASE64 challenge\n")); + /* We do not goto cancelfail; the server has already sent the + * tagged reply, so the protocol exchange has ended, no need + * for us to send the asterisk. */ + return PS_AUTHFAIL; + } + + /* validate challenge: + * - ident + * - message type + * - that offset points into buffer + * - that offset + length does not wrap + * - that offset + length is not bigger than buffer */ + if (0 != memcmp("NTLMSSP", challenge.ident, 8) + || challenge.msgType != 2 + || challenge.uDomain.offset > result + || challenge.uDomain.offset + challenge.uDomain.len < challenge.uDomain.offset + || challenge.uDomain.offset + challenge.uDomain.len > result) + { + report (stderr, GT_("NTLM challenge contains invalid data.\n")); + result = PS_AUTHFAIL; + goto cancelfail; + } if (outlevel >= O_DEBUG) dumpSmbNtlmAuthChallenge(stdout, &challenge); @@ -69,6 +100,14 @@ int ntlm_helper(int sock, struct query *ctl, const char *proto) SockWrite (sock, msgbuf, strlen (msgbuf)); return PS_SUCCESS; + +cancelfail: /* cancel authentication and return failure */ + { + if (outlevel >= O_MONITOR) + report(stdout, "%s> *\n", proto); + SockWrite(sock, "*\r\n", 3); + return result; + } } #endif /* NTLM_ENABLE */