#include "config.h"
#include <stdio.h>
#include <string.h>
+#include <strings.h>
#include <ctype.h>
#if defined(STDC_HEADERS)
#include <stdlib.h>
static int do_imap_ntlm(int sock, struct query *ctl)
{
- tSmbNtlmAuthRequest request;
- tSmbNtlmAuthChallenge challenge;
- tSmbNtlmAuthResponse response;
-
- char msgbuf[2048];
- int result,len;
+ int result;
gen_send(sock, "AUTHENTICATE NTLM");
- 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, &request, SmbLength(&request));
-
- if (outlevel >= O_MONITOR)
- report(stdout, "IMAP> %s\n", msgbuf);
-
- strcat(msgbuf,"\r\n");
- SockWrite (sock, msgbuf, strlen (msgbuf));
-
- if ((gen_recv(sock, msgbuf, sizeof msgbuf)))
+ if ((result = ntlm_helper(sock, ctl, "IMAP")))
return result;
-
- len = from64tobits (&challenge, msgbuf, sizeof(challenge));
-
- 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, &response, SmbLength(&response));
-
- if (outlevel >= O_MONITOR)
- report(stdout, "IMAP> %s\n", msgbuf);
-
- strcat(msgbuf,"\r\n");
- SockWrite (sock, msgbuf, strlen (msgbuf));
-
+
result = imap_ok (sock, NULL);
if (result == PS_SUCCESS)
return PS_SUCCESS;
* (see below). */
if (gen_transact(sock, "STARTTLS") == PS_SUCCESS
&& SSLOpen(sock, ctl->sslcert, ctl->sslkey, "tls1", ctl->sslcertck,
- ctl->sslcertpath, ctl->sslfingerprint, commonname,
+ ctl->sslcertfile, ctl->sslcertpath, ctl->sslfingerprint, commonname,
ctl->server.pollname, &ctl->remotename) != -1)
{
/*
}
#ifdef GSSAPI
- if ((ctl->server.authenticate == A_ANY
+ if (((ctl->server.authenticate == A_ANY && check_gss_creds("imap", ctl->server.truename) == PS_SUCCESS)
|| ctl->server.authenticate == A_GSSAPI)
&& strstr(capabilities, "AUTH=GSSAPI"))
{
if ((ok = do_gssauth(sock, "AUTHENTICATE", "imap",
ctl->server.truename, ctl->remotename)))
{
- /* SASL cancellation of authentication */
- gen_send(sock, "*");
if (ctl->server.authenticate != A_ANY)
return ok;
} else {
{
if ((ok = do_cram_md5 (sock, "AUTHENTICATE", ctl, NULL)))
{
- /* SASL cancellation of authentication */
- gen_send(sock, "*");
if(ctl->server.authenticate != A_ANY)
return ok;
}
&& strstr (capabilities, "AUTH=NTLM")) {
if ((ok = do_imap_ntlm(sock, ctl)))
{
- /* SASL cancellation of authentication */
- gen_send(sock, "*");
if(ctl->server.authenticate != A_ANY)
return ok;
}
free(remotename);
if (ok)
{
- /* SASL cancellation of authentication */
- gen_send(sock, "*");
if(ctl->server.authenticate != A_ANY)
return ok;
}
while ((ok = imap_response(sock, buf)) == PS_UNTAGGED)
{
unsigned int num;
+ int consumed;
/* expected response format:
* IMAP< * 1 FETCH (FLAGS (\Seen))
* IMAP< * 5 FETCH (UID 10 FLAGS (\Recent))
*/
if (unseen < count
- && sscanf(buf, "* %u FETCH ", &num) == 1
+ && sscanf(buf, "* %u %n", &num, &consumed) == 1
+ && 0 == strncasecmp(buf+consumed, "FETCH", 5)
+ && isspace((unsigned char)buf[consumed+5])
&& num >= 1 && num <= (unsigned)count
&& strstr(buf, "FLAGS ")
&& !strstr(buf, "\\SEEN")
{
unsigned int size;
int num;
+ int consumed;
+ char *ptr;
- if (sscanf(buf, "* %d FETCH (RFC822.SIZE %u)", &num, &size) == 2
- /* some servers (like mail.internode.on.net bld-mail04) return UID information here
- *
+ /* expected response formats:
* IMAP> A0005 FETCH 1 RFC822.SIZE
+ * IMAP< * 1 FETCH (RFC822.SIZE 1187)
* IMAP< * 1 FETCH (UID 16 RFC822.SIZE 1447)
- * IMAP< A0005 OK FETCH completed
- *
*/
- || sscanf(buf, "* %d FETCH (UID %*s RFC822.SIZE %u)", &num, &size) == 2)
+ if (sscanf(buf, "* %d %n", &num, &consumed) == 1
+ && 0 == strncasecmp(buf + consumed, "FETCH", 5)
+ && isspace((unsigned char)buf[consumed + 5])
+ && (ptr = strstr(buf, "RFC822.SIZE "))
+ && sscanf(ptr, "RFC822.SIZE %u", &size) == 1)
{
if (num >= first && num <= last)
sizes[num - first] = size;
return(seen);
}
+#if 0
static char *skip_token(char *ptr)
{
while(isspace((unsigned char)*ptr)) ptr++;
while(isspace((unsigned char)*ptr)) ptr++;
return(ptr);
}
+#endif
static int imap_fetch_headers(int sock, struct query *ctl,int number,int *lenp)
/* request headers of nth message */
{
char buf [MSGBUFSIZE+1];
int num;
+ int ok;
+ char *ptr;
(void)ctl;
/* expunges change the fetch numbers */
gen_send(sock, "FETCH %d RFC822.HEADER", number);
/* looking for FETCH response */
- for (;;)
+ if ((ok = imap_response(sock, buf)) == PS_UNTAGGED)
{
- int ok;
- char *ptr;
-
- if ((ok = gen_recv(sock, buf, sizeof(buf))))
- return(ok);
- ptr = skip_token(buf); /* either "* " or "AXXXX " */
- if (sscanf(ptr, "%d FETCH (RFC822.HEADER {%d}", &num, lenp) == 2
- /* some servers (like mail.internode.on.net bld-mail04) return UID information here
- *
+ int consumed;
+ /* expected response formats:
* IMAP> A0006 FETCH 1 RFC822.HEADER
+ * IMAP< * 1 FETCH (RFC822.HEADER {1360}
* IMAP< * 1 FETCH (UID 16 RFC822.HEADER {1360}
- * ...
- * IMAP< )
- * IMAP< A0006 OK FETCH completed
- *
+ * IMAP< * 1 FETCH (UID 16 RFC822.SIZE 4029 RFC822.HEADER {1360}
*/
- || sscanf(ptr, "%d FETCH (UID %*s RFC822.HEADER {%d}", &num, lenp) == 2)
- break;
- /* try to recover from chronically fucked-up M$ Exchange servers */
- else if (!strncmp(ptr, "NO", 2))
+ if (sscanf(buf, "* %d %n", &num, &consumed) == 1
+ && 0 == strncasecmp(buf + consumed, "FETCH", 5)
+ && isspace((unsigned char)buf[5+consumed])
+ && num == number
+ && (ptr = strstr(buf, "RFC822.HEADER"))
+ && sscanf(ptr, "RFC822.HEADER {%d}%n", lenp, &consumed) == 1
+ && ptr[consumed-1] == '}')
{
- /* wait for a tagged response */
- if (strstr (buf, "* NO"))
- imap_ok (sock, 0);
- return(PS_TRANSIENT);
+ return(PS_SUCCESS);
}
- else if (!strncmp(ptr, "BAD", 3))
+
+ /* wait for a tagged response */
+ imap_ok (sock, 0);
+
+ /* try to recover for some responses */
+ if (!strncmp(buf, "* NO", 4) ||
+ !strncmp(buf, "* BAD", 5))
{
- /* wait for a tagged response */
- if (strstr (buf, "* BAD"))
- imap_ok (sock, 0);
- return(PS_TRANSIENT);
+ return(PS_TRANSIENT);
}
- }
- if (num != number)
+ /* a response which does not match any of the above */
+ if (outlevel > O_SILENT)
+ report(stderr, GT_("Incorrect FETCH response: %s.\n"), buf);
return(PS_ERROR);
- else
- return(PS_SUCCESS);
+ }
+ else if (ok == PS_SUCCESS)
+ {
+ /* an unexpected tagged response */
+ if (outlevel > O_SILENT)
+ report(stderr, GT_("Incorrect FETCH response: %s.\n"), buf);
+ return(PS_ERROR);
+ }
+ return(ok);
}
static int imap_fetch_body(int sock, struct query *ctl, int number, int *lenp)