aboutsummaryrefslogtreecommitdiffstats
path: root/imap.c
diff options
context:
space:
mode:
Diffstat (limited to 'imap.c')
-rw-r--r--imap.c38
1 files changed, 36 insertions, 2 deletions
diff --git a/imap.c b/imap.c
index d1ee1c2b..d397542f 100644
--- a/imap.c
+++ b/imap.c
@@ -347,6 +347,24 @@ static void capa_probe(int sock, struct query *ctl)
peek_capable = (imap_version >= IMAP4);
}
+static int do_authcert (int sock, char *command, const char *name)
+/* do authentication "external" (authentication provided by client cert) */
+{
+ char buf[256];
+
+ if (name && name[0])
+ {
+ size_t len = strlen(name);
+ if ((len / 3) + ((len % 3) ? 4 : 0) < sizeof(buf))
+ to64frombits (buf, name, strlen(name));
+ else
+ return PS_AUTHFAIL; /* buffer too small. */
+ }
+ else
+ buf[0]=0;
+ return gen_transact(sock, "%s EXTERNAL %s",command,buf);
+}
+
static int imap_getauth(int sock, struct query *ctl, char *greeting)
/* apply for connection authorization */
{
@@ -378,7 +396,7 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
}
#ifdef SSL_ENABLE
- if ((!ctl->sslproto || !strcmp(ctl->sslproto,"tls1"))
+ if ((!ctl->sslproto || !strcasecmp(ctl->sslproto,"tls1"))
&& !ctl->use_ssl
&& strstr(capabilities, "STARTTLS"))
{
@@ -393,7 +411,7 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
if (ok == PS_SUCCESS &&
SSLOpen(sock,ctl->sslcert,ctl->sslkey,"tls1",ctl->sslcertck,
ctl->sslcertpath,ctl->sslfingerprint,
- realhost,ctl->server.pollname) == -1)
+ realhost,ctl->server.pollname,&ctl->remotename) == -1)
{
if (!ctl->sslproto && !ctl->wehaveauthed)
{
@@ -430,6 +448,22 @@ static int imap_getauth(int sock, struct query *ctl, char *greeting)
*/
ok = PS_AUTHFAIL;
+ if ((ctl->server.authenticate == A_ANY
+ || ctl->server.authenticate == A_EXTERNAL)
+ && strstr(capabilities, "AUTH=EXTERNAL"))
+ {
+ ok = do_authcert(sock, "AUTHENTICATE", ctl->remotename);
+ if (ok)
+ {
+ /* SASL cancellation of authentication */
+ gen_send(sock, "*");
+ if (ctl->server.authenticate != A_ANY)
+ return ok;
+ } else {
+ return ok;
+ }
+ }
+
#ifdef GSSAPI
if ((ctl->server.authenticate == A_ANY
|| ctl->server.authenticate == A_GSSAPI)