ImapResponse imap_handle_starttls(ImapMboxHandle *handle) { ImapResponse rc; SSL *ssl; IMAP_REQUIRED_STATE1(handle, IMHS_CONNECTED, IMR_BAD); if(!imap_mbox_handle_can_do(handle, IMCAP_STARTTLS)) return IMR_NO; ssl = imap_create_ssl(); if(!ssl) { printf("ssl=%p ctx=%p\n", ssl, global_ssl_context); return IMR_NO; } if( (rc=imap_cmd_exec(handle, "StartTLS")) != IMR_OK) { SSL_free(ssl); return rc; } if(imap_setup_ssl(handle->sio, handle->host, ssl, handle->user_cb, handle->user_arg)) { handle->using_tls = 1; handle->has_capabilities = 0; return IMR_OK; } else { /* ssl is owned now by sio, no need to free it SSL_free(ssl); */ imap_handle_disconnect(handle); return IMR_NO; } }
/* imap_auth_cram_md5: AUTH=CRAM-MD5 support. */ ImapResult imap_auth_cram(ImapMboxHandle* handle) { char ibuf[LONG_STRING*2], obuf[LONG_STRING]; unsigned char hmac_response[MD5_DIGEST_LEN]; unsigned cmdno; int len, rc, ok; char *user = NULL, *pass = NULL; if (!imap_mbox_handle_can_do(handle, IMCAP_ACRAM_MD5)) return IMAP_AUTH_UNAVAIL; ok = 0; if(!ok && handle->user_cb) handle->user_cb(IME_GET_USER_PASS, handle->user_arg, "CRAM-MD5", &user, &pass, &ok); if(!ok || user == NULL || pass == NULL) { imap_mbox_handle_set_msg(handle, "Authentication cancelled"); return IMAP_AUTH_CANCELLED; } /* start the interaction */ if(imap_cmd_start(handle, "AUTHENTICATE CRAM-MD5", &cmdno) <0) return IMAP_AUTH_FAILURE; /* 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]. */ imap_handle_flush(handle); do rc = imap_cmd_step(handle, cmdno); while(rc == IMR_UNTAGGED); if (rc != IMR_RESPOND) { g_warning("cram-md5: unexpected response:\n"); return IMAP_AUTH_FAILURE; } imap_mbox_gets(handle, ibuf, sizeof(ibuf)); /* check error */ if ((len = lit_conv_from_base64(obuf, ibuf)) <0) { g_warning("Error decoding base64 response(%s), digit=%d:%d[%c]).\n", ibuf, len, ibuf[-len-1],ibuf[-len-1]); return IMAP_AUTH_FAILURE; } obuf[len] = '\0'; /* 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); g_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]); /* XXX - ibuf must be long enough to store the base64 encoding of obuf, * plus the additional debris */ lit_conv_to_base64(ibuf, obuf, strlen (obuf), sizeof(ibuf)-2); strncat (ibuf, "\r\n", sizeof (ibuf) - strlen(ibuf) - 1); imap_handle_write(handle, ibuf, strlen(ibuf)); imap_handle_flush(handle); g_free(user); g_free(pass); /* FIXME: clean passwd first */ do rc = imap_cmd_step (handle, cmdno); while (rc == IMR_UNTAGGED); return rc == IMR_OK ? IMAP_SUCCESS : IMAP_AUTH_FAILURE; }