Commit 61333b00 authored by Thomas Roessler's avatar Thomas Roessler

Brendan Cully's SASL patch. I hope I didn't miss any files.

parent e15e685b
......@@ -63,15 +63,15 @@ non_us_sources = pgp.c pgpinvoke.c pgpkey.c pgplib.c sha1dgst.c \
contrib/pgp2.rc contrib/pgp5.rc contrib/gpg.rc \
imap/imap_ssl.c imap/imap_ssl.h README.SSL
EXTRA_mutt_SOURCES = account.c mutt_socket.c pop.c pgp.c pgpinvoke.c pgpkey.c \
pgplib.c sha1dgst.c gnupgparse.c resize.c dotlock.c remailer.c \
browser.h mbyte.h remailer.h
EXTRA_mutt_SOURCES = account.c mutt_sasl.c mutt_socket.c pop.c pgp.c \
pgpinvoke.c pgpkey.c pgplib.c sha1dgst.c gnupgparse.c resize.c \
dotlock.c remailer.c browser.h mbyte.h remailer.h
EXTRA_DIST = COPYRIGHT GPL OPS OPS.PGP TODO configure acconfig.h account.h \
attach.h buffy.h charset.h copy.h dotlock.h functions.h gen_defs \
globals.h hash.h history.h init.h keymap.h \
mailbox.h mapping.h mime.h mutt.h mutt_curses.h mutt_menu.h \
mutt_regex.h mutt_socket.h mx.h pager.h pgp.h protos.h \
mutt_regex.h mutt_sasl.h mutt_socket.h mx.h pager.h pgp.h protos.h \
reldate.h rfc1524.h rfc2047.h rfc2231.h rfc822.h sha.h sha_locl.h \
sort.h mime.types VERSION prepare _regex.h OPS.MIX \
README.SECURITY remailer.c remailer.h browser.h \
......
......@@ -46,13 +46,17 @@
/* Do you want support for the IMAP protocol? (--enable-imap) */
#undef USE_IMAP
/* Do you want to use the Cyrus SASL library for POP/IMAP authentication?
* (--with-sasl) */
#undef USE_SASL
/* Do you want support for IMAP GSSAPI authentication? (--with-gss) */
#undef USE_GSS
/* Do you have the Heimdal version of Kerberos V? (for gss support) */
#undef HAVE_HEIMDAL
/* Do you want support for SSL? (--enable-ssl) */
/* Do you want support for SSL? (--with-ssl) */
#undef USE_SSL
/* Avoid SSL routines which used patent-encumbered RC5 algorithms */
......
......@@ -52,3 +52,57 @@ int mutt_account_match (const ACCOUNT* a1, const ACCOUNT* a2)
return 1;
}
/* mutt_account_getuser: retrieve username into ACCOUNT, if neccessary */
int mutt_account_getuser (ACCOUNT* account)
{
/* already set */
if (account->flags & M_ACCT_USER)
return 0;
#ifdef USE_IMAP
else if ((account->type == M_ACCT_TYPE_IMAP) && ImapUser)
strfcpy (account->user, ImapUser, sizeof (account->user));
#endif
#ifdef USE_POP
else if ((account->type == M_ACCT_TYPE_POP) && PopUser)
strfcpy (account->user, PopUser, sizeof (account->user));
#endif
/* prompt (defaults to unix username), copy into account->user */
else
{
strfcpy (account->user, NONULL (Username), sizeof (account->user));
if (mutt_get_field (_("Username: "), account->user,
sizeof (account->user), 0))
return -1;
}
account->flags |= M_ACCT_USER;
return 0;
}
/* mutt_account_getpass: fetch password into ACCOUNT, if neccessary */
int mutt_account_getpass (ACCOUNT* account)
{
if (account->flags & M_ACCT_PASS)
return 0;
#ifdef USE_IMAP
else if ((account->type == M_ACCT_TYPE_IMAP) && ImapPass)
strfcpy (account->pass, ImapPass, sizeof (account->pass));
#endif
#ifdef USE_POP
else if ((account->type == M_ACCT_TYPE_POP) && PopPass)
strfcpy (account->pass, PopPass, sizeof (account->pass));
#endif
else
{
account->pass[0] = '\0';
if (mutt_get_field (_("Password: "), account->pass,
sizeof (account->pass), M_PASS))
return -1;
}
account->flags |= M_ACCT_PASS;
return 0;
}
......@@ -32,9 +32,8 @@ enum
/* account flags */
#define M_ACCT_PORT (1<<0)
#define M_ACCT_USER (1<<1)
#define M_ACCT_SSL (1<<2)
#define M_ACCT_CRAM (1<<3)
#define M_ACCT_PASS (1<<4)
#define M_ACCT_PASS (1<<2)
#define M_ACCT_SSL (1<<3)
typedef struct
{
......@@ -46,7 +45,8 @@ typedef struct
unsigned char flags;
} ACCOUNT;
/* imap_account_match: compare account info (host/port/user) */
int mutt_account_match (const ACCOUNT* a1, const ACCOUNT* m2);
int mutt_account_getuser (ACCOUNT* account);
int mutt_account_getpass (ACCOUNT* account);
#endif /* _MUTT_ACCOUNT_H_ */
......@@ -663,6 +663,37 @@ AM_CONDITIONAL(USE_SSL, test x$need_ssl = xyes)
dnl -- end imap dependencies --
AC_ARG_WITH(sasl, [ --with-sasl[=DIR] Use Cyrus SASL library for POP/IMAP authentication],
[
if test "$need_socket" != "yes"
then
AC_MSG_ERROR([SASL support is only useful with POP or IMAP support])
fi
if test "$with_sasl" != "no"
then
if test "$with_sasl" != "yes"
then
CPPFLAGS="$CPPFLAGS -I$with_sasl/include"
LDFLAGS="$LDFLAGS -L$with_sasl/lib"
fi
saved_LIBS="$LIBS"
AC_CHECK_LIB(sasl, sasl_client_init,,
AC_MSG_ERROR([could not find libsasl]),)
MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS mutt_sasl.o"
MUTTLIBS="$MUTTLIBS -lsasl"
LIBS="$saved_LIBS"
AC_DEFINE(USE_SASL)
need_sasl=yes
fi
])
AM_CONDITIONAL(USE_SASL, test x$need_sasl = xyes)
dnl -- end socket --
AC_ARG_ENABLE(debug, [ --enable-debug Enable debugging support],
[ if test x$enableval = xyes ; then
AC_DEFINE(DEBUG)
......@@ -702,7 +733,7 @@ AC_ARG_ENABLE(buffy-size, [ --enable-buffy-size Use file size attribute
AC_DEFINE(BUFFY_SIZE)
fi])
AC_ARG_ENABLE(mailtool, [ --enable-mailtool Enable Sun mailtool attachments support ],
AC_ARG_ENABLE(mailtool, [ --enable-mailtool Enable Sun mailtool attachments support ],
[if test x$enableval = xyes; then
AC_DEFINE(SUN_ATTACHMENT)
fi])
......@@ -717,7 +748,7 @@ AC_ARG_WITH(exec-shell, [ --with-exec-shell=SHELL Specify alternate shell (O
AC_DEFINE_UNQUOTED(EXECSHELL, "$withval")
fi])
AC_ARG_ENABLE(exact-address, [ --enable-exact-address enable regeneration of email addresses],
AC_ARG_ENABLE(exact-address, [ --enable-exact-address Enable regeneration of email addresses],
[if test $enableval = yes; then
AC_DEFINE(EXACT_ADDRESS)
fi])
......
......@@ -50,7 +50,6 @@ WHERE char *Homedir;
WHERE char *Hostname;
#ifdef USE_IMAP
WHERE char *ImapUser INITVAL (NULL);
WHERE char *ImapCRAMKey INITVAL (NULL);
WHERE char *ImapPass INITVAL (NULL);
WHERE short ImapCheckTimeout;
WHERE char *ImapHomeNamespace INITVAL (NULL);
......
......@@ -6,6 +6,12 @@ if USE_GSS
GSSSOURCES = auth_gss.c
endif
if USE_SASL
SASLSOURCES = auth_sasl.c
else
CRAMSOURCES = auth_cram.c
endif
if USE_SSL
SSLSOURCES = imap_ssl.c
SSLHEADERS = imap_ssl.h
......@@ -16,7 +22,8 @@ EXTRA_DIST = BUGS README TODO imap_ssl.c imap_ssl.h auth_gss.c
INCLUDES = -I$(top_srcdir) -I../intl
noinst_LIBRARIES = libimap.a
noinst_HEADERS = imap_private.h md5.h message.h $(SSLHEADERS)
noinst_HEADERS = auth.h imap_private.h md5.h message.h $(SSLHEADERS)
libimap_a_SOURCES = auth.c browse.c command.c imap.c imap.h md5c.c message.c \
utf7.c util.c $(GSSSOURCES) $(SSLSOURCES)
libimap_a_SOURCES = auth.c auth_anon.c auth_login.c c browse.c \
command.c imap.c imap.h md5c.c message.c utf7.c \
util.c $(GSSSOURCES) $(SASLSOURCES) $(CRAMSOURCES) $(SSLSOURCES)
......@@ -22,390 +22,37 @@
#include "mutt.h"
#include "imap_private.h"
#include "md5.h"
#include "auth.h"
#define MD5_BLOCK_LEN 64
#define MD5_DIGEST_LEN 16
/* external authenticator prototypes */
static imap_auth_t imap_authenticators[] = {
imap_auth_anon,
#ifdef USE_SASL
imap_auth_sasl,
#endif
#ifdef USE_GSS
int imap_auth_gss (IMAP_DATA* idata, const char* user);
imap_auth_gss,
#endif
/* SASL includes CRAM-MD5 (and GSSAPI, but that's not enabled by default) */
#ifndef USE_SASL
imap_auth_cram_md5,
#endif
imap_auth_login,
/* forward declarations */
static void hmac_md5 (const char* password, char* challenge,
unsigned char* response);
static int imap_auth_cram_md5 (IMAP_DATA* idata, const char* user,
const char* pass);
static int imap_auth_anon (IMAP_DATA *idata);
/* hmac_md5: produce CRAM-MD5 challenge response. */
static void hmac_md5 (const char* password, char* challenge,
unsigned char* response)
{
MD5_CTX ctx;
unsigned char ipad[MD5_BLOCK_LEN], opad[MD5_BLOCK_LEN];
unsigned char secret[MD5_BLOCK_LEN+1];
unsigned char hash_passwd[MD5_DIGEST_LEN];
unsigned int secret_len, chal_len;
int i;
secret_len = strlen (password);
chal_len = strlen (challenge);
/* passwords longer than MD5_BLOCK_LEN bytes are substituted with their MD5
* digests */
if (secret_len > MD5_BLOCK_LEN)
{
MD5Init (&ctx);
MD5Update (&ctx, (unsigned char*) password, secret_len);
MD5Final (hash_passwd, &ctx);
strfcpy ((char*) secret, (char*) hash_passwd, MD5_DIGEST_LEN);
secret_len = MD5_DIGEST_LEN;
}
else
strfcpy ((char *) secret, password, sizeof (secret));
memset (ipad, 0, sizeof (ipad));
memset (opad, 0, sizeof (opad));
memcpy (ipad, secret, secret_len);
memcpy (opad, secret, secret_len);
for (i = 0; i < MD5_BLOCK_LEN; i++)
{
ipad[i] ^= 0x36;
opad[i] ^= 0x5c;
}
/* inner hash: challenge and ipadded secret */
MD5Init (&ctx);
MD5Update (&ctx, ipad, MD5_BLOCK_LEN);
MD5Update (&ctx, (unsigned char*) challenge, chal_len);
MD5Final (response, &ctx);
/* outer hash: inner hash and opadded secret */
MD5Init (&ctx);
MD5Update (&ctx, opad, MD5_BLOCK_LEN);
MD5Update (&ctx, response, MD5_DIGEST_LEN);
MD5Final (response, &ctx);
}
/* imap_auth_cram_md5: AUTH=CRAM-MD5 support. Used unconditionally if the
* server supports it */
static int imap_auth_cram_md5 (IMAP_DATA* idata, const char* user,
const char* pass)
{
char ibuf[LONG_STRING], obuf[LONG_STRING];
unsigned char hmac_response[MD5_DIGEST_LEN];
int len;
dprint (2, (debugfile, "Attempting CRAM-MD5 login...\n"));
mutt_message _("Authenticating (CRAM-MD5)...");
imap_cmd_start (idata, "AUTHENTICATE CRAM-MD5");
/* From RFC 2195:
* The data encoded in the first ready response contains a presumptively
* arbitrary string of random digits, a timestamp, and the fully-qualified
* primary host name of the server. The syntax of the unencoded form must
* correspond to that of an RFC 822 'msg-id' [RFC822] as described in [POP3].
*/
if (mutt_socket_readln (ibuf, sizeof (ibuf), idata->conn) < 0)
{
dprint (1, (debugfile, "Error receiving server response.\n"));
return -1;
}
if (ibuf[0] != '+')
{
dprint (1, (debugfile, "Invalid response from server: %s\n", ibuf));
return -1;
}
if ((len = mutt_from_base64 (obuf, ibuf + 2)) == -1)
{
dprint (1, (debugfile, "Error decoding base64 response.\n"));
return -1;
}
obuf[len] = '\0';
dprint (2, (debugfile, "CRAM challenge: %s\n", obuf));
/* The client makes note of the data and then responds with a string
* consisting of the user name, a space, and a 'digest'. The latter is
* computed by applying the keyed MD5 algorithm from [KEYED-MD5] where the
* key is a shared secret and the digested text is the timestamp (including
* angle-brackets).
*
* Note: The user name shouldn't be quoted. Since the digest can't contain
* spaces, there is no ambiguity. Some servers get this wrong, we'll work
* around them when the bug report comes in. Until then, we'll remain
* blissfully RFC-compliant.
*/
hmac_md5 (pass, obuf, hmac_response);
/* dubious optimisation I saw elsewhere: make the whole string in one call */
snprintf (obuf, sizeof (obuf),
"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
user,
hmac_response[0], hmac_response[1], hmac_response[2], hmac_response[3],
hmac_response[4], hmac_response[5], hmac_response[6], hmac_response[7],
hmac_response[8], hmac_response[9], hmac_response[10], hmac_response[11],
hmac_response[12], hmac_response[13], hmac_response[14], hmac_response[15]);
dprint(2, (debugfile, "CRAM response: %s\n", obuf));
mutt_to_base64 ((unsigned char*) ibuf, (unsigned char*) obuf, strlen (obuf));
strcpy (ibuf + strlen (ibuf), "\r\n");
mutt_socket_write (idata->conn, ibuf);
if (mutt_socket_readln (ibuf, LONG_STRING, idata->conn) < 0)
{
dprint (1, (debugfile, "Error receiving server response.\n"));
return -1;
}
if (imap_code (ibuf))
{
dprint (2, (debugfile, "CRAM login complete.\n"));
return 0;
}
dprint (2, (debugfile, "CRAM login failed.\n"));
return -1;
}
/* this is basically a stripped-down version of the cram-md5 method. */
static int imap_auth_anon (IMAP_DATA* idata)
{
char buf[LONG_STRING];
dprint (2, (debugfile, "Attempting anonymous login...\n"));
mutt_message _("Authenticating (anonymous)...");
imap_cmd_start (idata, "AUTHENTICATE ANONYMOUS");
if (mutt_socket_readln (buf, sizeof (buf), idata->conn) < 0)
{
dprint (1, (debugfile, "Error receiving server response.\n"));
return -1;
}
if (buf[0] != '+')
{
dprint (1, (debugfile, "Invalid response from server.\n"));
return -1;
}
strfcpy (buf, "ZHVtbXkK\r\n", sizeof (buf)); /* base64 ("dummy") */
mutt_socket_write (idata->conn, buf);
if (mutt_socket_readln (buf, sizeof (buf), idata->conn) < 0)
{
dprint (1, (debugfile, "Error receiving server response.\n"));
return -1;
}
if (imap_code (buf))
{
dprint (2, (debugfile, "Anonymous login complete.\n"));
return 0;
}
dprint (2, (debugfile, "Anonymous login failed.\n"));
NULL
};
return -1;
}
/* imap_authenticate: loop until success or user abort. At each loop, all
* supported authentication methods are tried, from strongest to weakest.
* Currently available:
* GSSAPI: strongest available form, requires Kerberos V infrastructure,
* or possibly alternatively Heimdal.
* CRAM-MD5: like APOP or CHAP. Safe against replay and sniffing, but
* requires that your key be stored on the server, readable by the
* server account. UW-IMAP supports this method since at least 4.5, if
* the key file exists on the server.
* LOGIN: ugh. Don't use this if you can help it. Uses cleartext password
* exchange, furthermore uses unix login techniques so this same password
* can be used to log in to the server or others that share the
* credentials database.
* Unavailable:
* KERBEROS_V4. Superceded by GSSAPI.
*/
/* imap_authenticate: oh how simple! loops through authenticators. */
int imap_authenticate (IMAP_DATA* idata)
{
char buf[LONG_STRING];
char user[SHORT_STRING], q_user[SHORT_STRING];
char ckey[SHORT_STRING];
char pass[SHORT_STRING], q_pass[SHORT_STRING];
CONNECTION* conn = idata->conn;
int r = 1;
imap_auth_t* authenticator = imap_authenticators;
int r = -1;
while (r != 0)
while (authenticator)
{
if (! (conn->account.flags & M_ACCT_USER))
{
if (!ImapUser)
{
strfcpy (user, NONULL(Username), sizeof (user));
if (mutt_get_field (_("IMAP Username: "), user, sizeof (user), 0) != 0)
{
user[0] = 0;
return (-1);
}
}
else
strfcpy (user, ImapUser, sizeof (user));
}
else
strfcpy (user, conn->account.user, sizeof (user));
if (!user[0])
{
if (!mutt_bit_isset (idata->capabilities, AUTH_ANON))
{
mutt_error _("Anonymous authentication not supported.");
return -1;
}
return imap_auth_anon (idata);
}
#ifdef USE_GSS
/* attempt GSSAPI authentication, if available */
if (mutt_bit_isset (idata->capabilities, AGSSAPI))
{
if ((r = imap_auth_gss (idata, user)))
{
mutt_error _("GSSAPI authentication failed.");
sleep (1);
}
else
return 0;
}
else
dprint (2, (debugfile, "GSSAPI authentication is not available\n"));
#endif
/* attempt CRAM-MD5 if available */
if (mutt_bit_isset (idata->capabilities, ACRAM_MD5))
{
if (!(conn->account.flags & M_ACCT_CRAM))
{
if (!ImapCRAMKey)
{
ckey[0] = '\0';
snprintf (buf, sizeof (buf), _("CRAM key for %s@%s: "), user,
conn->account.host);
if (mutt_get_field (buf, ckey, sizeof (ckey), M_PASS) != 0)
return -1;
}
else
strfcpy (ckey, ImapCRAMKey, sizeof (ckey));
}
else
strfcpy (ckey, conn->account.pass, sizeof (ckey));
if (*ckey)
{
if ((r = imap_auth_cram_md5 (idata, user, ckey)))
{
mutt_error _("CRAM-MD5 authentication failed.");
sleep (1);
if (!(conn->account.flags & M_ACCT_CRAM))
FREE (&ImapCRAMKey);
conn->account.flags &= ~M_ACCT_CRAM;
}
else
{
strfcpy (conn->account.pass, ckey, sizeof (conn->account.pass));
conn->account.flags |= M_ACCT_CRAM;
return 0;
}
}
else
{
mutt_message _("Skipping CRAM-MD5 authentication.");
sleep (1);
}
}
else
dprint (2, (debugfile, "CRAM-MD5 authentication is not available\n"));
if (! (conn->account.flags & M_ACCT_PASS))
{
if (!ImapPass)
{
pass[0]=0;
snprintf (buf, sizeof (buf), _("Password for %s@%s: "), user,
conn->account.host);
if (mutt_get_field (buf, pass, sizeof (pass), M_PASS) != 0 ||
!pass[0])
return -1;
}
else
strfcpy (pass, ImapPass, sizeof (pass));
}
else
strfcpy (pass, conn->account.pass, sizeof (pass));
imap_quote_string (q_user, sizeof (q_user), user);
imap_quote_string (q_pass, sizeof (q_pass), pass);
mutt_message _("Logging in...");
#ifdef DEBUG
/* don't print the password unless we're at the ungodly debugging level
* of 5 or higher */
if (debuglevel < IMAP_LOG_PASS)
dprint (2, (debugfile, "Sending LOGIN command for %s...\n", user));
#endif
snprintf (buf, sizeof (buf), "LOGIN %s %s", q_user, q_pass);
r = imap_exec (buf, sizeof (buf), idata, buf,
IMAP_CMD_FAIL_OK | IMAP_CMD_PASS);
if (r == -1)
{
/* connection or protocol problem */
imap_error ("imap_authenticate", buf);
return (-1);
}
else if (r == -2)
{
/* Login failed, try again */
mutt_error _("Login failed.");
sleep (1);
if (!(conn->account.flags & M_ACCT_USER))
FREE (&ImapUser);
if (!(conn->account.flags & M_ACCT_PASS))
FREE (&ImapPass);
conn->account.flags &= ~M_ACCT_PASS;
}
else
{
/* If they have a successful login, we may as well cache the
* user/password. */
if (!(conn->account.flags & M_ACCT_USER))
strfcpy (conn->account.user, user, sizeof (conn->account.user));
if (!(conn->account.flags & M_ACCT_PASS))
strfcpy (conn->account.pass, pass, sizeof (conn->account.pass));
conn->account.flags |= (M_ACCT_USER | M_ACCT_PASS);
}
if ((r = (*authenticator)(idata)) != IMAP_AUTH_UNAVAIL)
return r;
authenticator++;
}
return 0;
return r;
}
/*
* Copyright (C) 2000 Brendan Cully <brendan@kublai.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
/* common defs for authenticators. A good place to set up a generic callback
* system */
#ifndef _IMAP_AUTH_H
#define _IMAP_AUTH_H 1
typedef enum
{
IMAP_AUTH_SUCCESS = 0,
IMAP_AUTH_FAILURE,
IMAP_AUTH_UNAVAIL
} imap_auth_res_t;
typedef imap_auth_res_t (*imap_auth_t)(IMAP_DATA* idata);
/* external authenticator prototypes */
imap_auth_res_t imap_auth_anon (IMAP_DATA* idata);
imap_auth_res_t imap_auth_cram_md5 (IMAP_DATA* idata);
imap_auth_res_t imap_auth_login (IMAP_DATA* idata);
#ifdef USE_GSS
imap_auth_res_t imap_auth_gss (IMAP_DATA* idata);
#endif
#ifdef USE_SASL
imap_auth_res_t imap_auth_sasl (IMAP_DATA* idata);
#endif
#endif /* _IMAP_AUTH_H */
/*
* Copyright (C) 1999-2000 Brendan Cully <brendan@kublai.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
/* IMAP login/authentication code */
#include "mutt.h"
#include "imap_private.h"
#include "auth.h"
/* this is basically a stripped-down version of the cram-md5 method. */
imap_auth_res_t imap_auth_anon (IMAP_DATA* idata)
{
char buf[LONG_STRING];
if (!mutt_bit_isset (idata->capabilities, AUTH_ANON))
return IMAP_AUTH_UNAVAIL;
if (mutt_account_getuser (&idata->conn->account))
return IMAP_AUTH_FAILURE;
if (idata->conn->account.user[0] != '\0')
return IMAP_AUTH_UNAVAIL;
mutt_message _("Authenticating (anonymous)...");
imap_cmd_start (idata, "AUTHENTICATE ANONYMOUS");
if (mutt_socket_readln (buf, sizeof (buf), idata->conn) < 0)
{
dprint (1, (debugfile, "Error receiving server response.\n"));
goto bail;
}
if (buf[0] != '+')
{
dprint (1, (debugfile, "Invalid response from server.\n"));
goto bail;
}
strfcpy (buf, "ZHVtbXkK\r\n", sizeof (buf)); /* base64 ("dummy") */
mutt_socket_write (idata->conn, buf);
if (mutt_socket_readln (buf, sizeof (buf), idata->conn) < 0)
{
dprint (1, (debugfile, "Error receiving server response.\n"));
goto bail;
}
if (imap_code (buf))
return IMAP_AUTH_SUCCESS;
bail:
mutt_error _("Anonymous authentication failed.");
sleep (2);
return IMAP_AUTH_FAILURE;
}
/*
* Copyright (C) 1999-2000 Brendan Cully <brendan@kublai.com>
*
* This program is free software; you can redistribute it and/or modify