From c442cee390175d0e8f84d11d11125f880a672dd7 Mon Sep 17 00:00:00 2001 From: Art Cancro Date: Sun, 15 Feb 2004 06:06:50 +0000 Subject: [PATCH] * More work on IMAP TLS. Still not working correctly. :( Added in support for server-side certificates. Now instead of failing it hangs. VS: ---------------------------------------------------------------------- --- citadel/ChangeLog | 6 ++ citadel/serv_crypto.c | 150 ++++++++++++++++++++++++++++-------------- citadel/serv_imap.c | 6 +- 3 files changed, 109 insertions(+), 53 deletions(-) diff --git a/citadel/ChangeLog b/citadel/ChangeLog index 7cf4ccd1b..63f518f2d 100644 --- a/citadel/ChangeLog +++ b/citadel/ChangeLog @@ -1,4 +1,9 @@ $Log$ + Revision 614.30 2004/02/15 06:06:49 ajc + * More work on IMAP TLS. Still not working correctly. :( Added in + support for server-side certificates. Now instead of failing it hangs. + VS: ---------------------------------------------------------------------- + Revision 614.29 2004/02/14 04:41:55 ajc * STARTTLS attempt #2. Still disabled because it's broken. @@ -5323,3 +5328,4 @@ Sat Jul 11 00:20:48 EDT 1998 Nathan Bryant Fri Jul 10 1998 Art Cancro * Initial CVS import + diff --git a/citadel/serv_crypto.c b/citadel/serv_crypto.c index d046bfc04..f21a045df 100644 --- a/citadel/serv_crypto.c +++ b/citadel/serv_crypto.c @@ -38,13 +38,52 @@ #ifdef HAVE_OPENSSL -SSL_CTX *ssl_ctx; /* SSL context */ -pthread_mutex_t **SSLCritters; /* Things needing locking */ +SSL_CTX *ssl_ctx; /* SSL context */ +pthread_mutex_t **SSLCritters; /* Things needing locking */ -static unsigned long id_callback(void) { - return (unsigned long)pthread_self(); +static unsigned long id_callback(void) +{ + return (unsigned long) pthread_self(); +} + + /* + * Set up the cert things on the server side. We do need both the + * private key (in key_file) and the cert (in cert_file). + * Both files may be identical. + * + * This function is taken from OpenSSL apps/s_cb.c + */ + +static int set_cert_stuff(SSL_CTX * ctx, + const char *cert_file, const char *key_file) +{ + if (cert_file != NULL) { + if (SSL_CTX_use_certificate_file(ctx, cert_file, + SSL_FILETYPE_PEM) <= 0) { + lprintf(3, "unable to get certificate from '%s'", + cert_file); + return (0); + } + if (key_file == NULL) + key_file = cert_file; + if (SSL_CTX_use_PrivateKey_file(ctx, key_file, + SSL_FILETYPE_PEM) <= 0) { + lprintf(3, "unable to get private key from '%s'", + key_file); + return (0); + } + /* Now we know that a key and cert have been set against + * the SSL context */ + if (!SSL_CTX_check_private_key(ctx)) { + lprintf(3, + "Private key does not match the certificate public key"); + return (0); + } + } + return (1); } + void init_ssl(void) { SSL_METHOD *ssl_method; @@ -52,12 +91,14 @@ void init_ssl(void) if (!access("/var/run/egd-pool", F_OK)) RAND_egd("/var/run/egd-pool"); - + if (!RAND_status()) { - lprintf(2, "PRNG not adequately seeded, won't do SSL/TLS\n"); + lprintf(2, + "PRNG not adequately seeded, won't do SSL/TLS\n"); return; } - SSLCritters = mallok(CRYPTO_num_locks() * sizeof (pthread_mutex_t *)); + SSLCritters = + mallok(CRYPTO_num_locks() * sizeof(pthread_mutex_t *)); if (!SSLCritters) { lprintf(1, "citserver: can't allocate memory!!\n"); /* Nothing's been initialized, just die */ @@ -65,10 +106,11 @@ void init_ssl(void) } else { int a; - for (a=0; a= 0x00906000L SSL_CTX_set_mode(ssl_ctx, SSL_CTX_get_mode(ssl_ctx) | - SSL_MODE_AUTO_RETRY); + SSL_MODE_AUTO_RETRY); #endif #endif CRYPTO_set_locking_callback(ssl_lock); @@ -106,21 +148,21 @@ void init_ssl(void) dh = DH_new(); if (!dh) { lprintf(2, "init_ssl() can't allocate a DH object: %s\n", - ERR_reason_error_string(ERR_get_error())); + ERR_reason_error_string(ERR_get_error())); SSL_CTX_free(ssl_ctx); ssl_ctx = NULL; return; } if (!(BN_hex2bn(&(dh->p), DH_P))) { lprintf(2, "init_ssl() can't assign DH_P: %s\n", - ERR_reason_error_string(ERR_get_error())); + ERR_reason_error_string(ERR_get_error())); SSL_CTX_free(ssl_ctx); ssl_ctx = NULL; return; } if (!(BN_hex2bn(&(dh->g), DH_G))) { lprintf(2, "init_ssl() can't assign DH_G: %s\n", - ERR_reason_error_string(ERR_get_error())); + ERR_reason_error_string(ERR_get_error())); SSL_CTX_free(ssl_ctx); ssl_ctx = NULL; return; @@ -129,9 +171,19 @@ void init_ssl(void) SSL_CTX_set_tmp_dh(ssl_ctx, dh); DH_free(dh); + /* Get our certificates in order */ + if (set_cert_stuff(ssl_ctx, + "/etc/ssh/mail01.jemcaterers.net.cer", + "/etc/ssh/ssh_host_rsa_key") != 1) { + + lprintf(3, "SSL ERROR: cert is bad!\n"); + + } + /* Finally let the server know we're here */ CtdlRegisterProtoHook(cmd_stls, "STLS", "Start SSL/TLS session"); - CtdlRegisterProtoHook(cmd_gtls, "GTLS", "Get SSL/TLS session status"); + CtdlRegisterProtoHook(cmd_gtls, "GTLS", + "Get SSL/TLS session status"); CtdlRegisterSessionHook(endtls, EVT_STOP); } @@ -154,21 +206,18 @@ void client_write_ssl(char *buf, int nbytes) ERR_print_errors_fp(stderr); } } - retval = SSL_write(CC->ssl, &buf[nbytes - nremain], nremain); - lprintf(9, "SSL_write(%d) returned %d\n", nremain, retval); + retval = + SSL_write(CC->ssl, &buf[nbytes - nremain], nremain); if (retval < 1) { long errval; errval = SSL_get_error(CC->ssl, retval); if (errval == SSL_ERROR_WANT_READ || - errval == SSL_ERROR_WANT_WRITE) { + errval == SSL_ERROR_WANT_WRITE) { sleep(1); continue; } - lprintf(9, "SSL_write: error %ld: %s\n", - errval, - ERR_error_string(errval, NULL) - ); + lprintf(9, "SSL_write got error %ld\n", errval); endtls(); client_write(&buf[nbytes - nremain], nremain); return; @@ -183,7 +232,7 @@ void client_write_ssl(char *buf, int nbytes) */ int client_read_ssl(char *buf, int bytes, int timeout) { - int len,rlen; + int len, rlen; fd_set rfds; struct timeval tv; int retval; @@ -191,17 +240,17 @@ int client_read_ssl(char *buf, int bytes, int timeout) char junk[1]; len = 0; - while(lenssl->rbio, NULL); FD_SET(s, &rfds); tv.tv_sec = timeout; tv.tv_usec = 0; - retval = select(s+1, &rfds, NULL, NULL, &tv); + retval = select(s + 1, &rfds, NULL, NULL, &tv); if (FD_ISSET(s, &rfds) == 0) { - return(0); + return (0); } if (SSL_want_read(CC->ssl)) { @@ -210,27 +259,24 @@ int client_read_ssl(char *buf, int bytes, int timeout) ERR_print_errors_fp(stderr); } } - rlen = SSL_read(CC->ssl, &buf[len], bytes-len); - lprintf(9, "SSL_read(%d) returned %d\n", bytes-len, rlen); - if (rlen<1) { + rlen = SSL_read(CC->ssl, &buf[len], bytes - len); + if (rlen < 1) { long errval; errval = SSL_get_error(CC->ssl, rlen); if (errval == SSL_ERROR_WANT_READ || - errval == SSL_ERROR_WANT_WRITE) { + errval == SSL_ERROR_WANT_WRITE) { sleep(1); continue; } - lprintf(9, "SSL_read: error %ld: %s\n", - errval, - ERR_error_string(errval, NULL) - ); + lprintf(9, "SSL_read got error %ld\n", errval); endtls(); - return (client_read_to(&buf[len], bytes - len, timeout)); + return (client_read_to + (&buf[len], bytes - len, timeout)); } len += rlen; } - return(1); + return (1); } @@ -247,18 +293,18 @@ void cmd_stls(char *params) } if (!(CC->ssl = SSL_new(ssl_ctx))) { lprintf(2, "SSL_new failed: %s\n", - ERR_reason_error_string(ERR_peek_error())); + ERR_reason_error_string(ERR_peek_error())); cprintf("%d SSL_new: %s\n", ERROR, - ERR_reason_error_string(ERR_get_error())); + ERR_reason_error_string(ERR_get_error())); return; } if (!(SSL_set_fd(CC->ssl, CC->client_socket))) { lprintf(2, "SSL_set_fd failed: %s\n", - ERR_reason_error_string(ERR_peek_error())); + ERR_reason_error_string(ERR_peek_error())); SSL_free(CC->ssl); CC->ssl = NULL; cprintf("%d SSL_set_fd: %s\n", ERROR, - ERR_reason_error_string(ERR_get_error())); + ERR_reason_error_string(ERR_get_error())); return; } cprintf("%d \n", CIT_OK); @@ -273,17 +319,19 @@ void cmd_stls(char *params) errval = SSL_get_error(CC->ssl, retval); lprintf(2, "SSL_accept failed: %s\n", - ERR_reason_error_string(ERR_get_error())); + ERR_reason_error_string(ERR_get_error())); SSL_free(CC->ssl); CC->ssl = NULL; return; } BIO_set_close(CC->ssl->rbio, BIO_NOCLOSE); - bits = SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl), &alg_bits); + bits = + SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl), + &alg_bits); lprintf(3, "SSL/TLS using %s on %s (%d of %d bits)\n", - SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)), - SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)), - bits, alg_bits); + SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)), + SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)), + bits, alg_bits); CC->redirect_ssl = 1; } @@ -294,12 +342,14 @@ void cmd_stls(char *params) void cmd_gtls(char *params) { int bits, alg_bits; - + if (!CC->ssl || !CC->redirect_ssl) { cprintf("%d Session is not encrypted.\n", ERROR); return; } - bits = SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl), &alg_bits); + bits = + SSL_CIPHER_get_bits(SSL_get_current_cipher(CC->ssl), + &alg_bits); cprintf("%d %s|%s|%d|%d\n", CIT_OK, SSL_CIPHER_get_version(SSL_get_current_cipher(CC->ssl)), SSL_CIPHER_get_name(SSL_get_current_cipher(CC->ssl)), @@ -321,7 +371,7 @@ void endtls(void) CC->redirect_ssl = 0; return; } - + SSL_shutdown(CC->ssl); SSL_free(CC->ssl); CC->ssl = NULL; @@ -339,4 +389,4 @@ void ssl_lock(int mode, int n, const char *file, int line) else pthread_mutex_unlock(SSLCritters[n]); } -#endif /* HAVE_OPENSSL */ +#endif /* HAVE_OPENSSL */ diff --git a/citadel/serv_imap.c b/citadel/serv_imap.c index 421046210..8a757b5fa 100644 --- a/citadel/serv_imap.c +++ b/citadel/serv_imap.c @@ -418,7 +418,7 @@ void imap_capability(int num_parms, char *parms[]) { cprintf("* CAPABILITY IMAP4 IMAP4REV1 AUTH=LOGIN"); -#ifdef HAVE_OPENSSL_XXX_DISABLED +#ifdef HAVE_OPENSSL_XXX cprintf(" STARTTLS"); #endif @@ -430,7 +430,7 @@ void imap_capability(int num_parms, char *parms[]) /* * implements the STARTTLS command (lifted-from-Cyrus version) */ -#ifdef HAVE_OPENSSL +#ifdef HAVE_OPENSSL_XXX void imap_starttls(int num_parms, char *parms[]) { int sts; @@ -502,7 +502,7 @@ done: /* * implements the STARTTLS command (original version) */ -#ifdef HAVE_OPENSSL_XXX +#ifdef HAVE_OPENSSL void imap_starttls(int num_parms, char *parms[]) { int retval, bits, alg_bits; -- 2.39.2