Hello
Friday afternoon proposed feature enhancement...
The attached patch extends the functionality of backend.c to support
client certificates when setting up TLS sessions between one Cyrus
machine and another.
The new options tls_client_cert_file and tls_client_key_file can use the
established "<service>_" and/or "<shorthost>_" prefixes just like the
server certificate equivalents and "<shorthost>_password".
Client certificates can be used to augment or, by the magic of SASL's
"EXTERNAL" mechanism, replace passwords for Cyrus-to-Cyrus
authentication in Murder.
Tested (very briefly) on Debian x86_64 for imap proxy authentication and
mupdate authentication (with our mupdate TLS patches -- see
https://bugzilla.andrew.cmu.edu/show_bug.cgi?id=3119 ).
Cheers
Duncan
--
Duncan Gibb, Technical Director
Sirius Corporation plc - The Open Source Experts
http://www.siriusit.co.uk/
Tel: +44 870 608 0063
diff -rub cyrus-imapd-2.3.13/imap/backend.c cyrus23_client_certs/imap/backend.c
--- cyrus-imapd-2.3.13/imap/backend.c 2008-10-08 14:12:41.000000000 +0100
+++ cyrus23_client_certs/imap/backend.c 2008-11-07 14:50:55.000000000 +0000
@@ -131,7 +131,8 @@
return ret;
}
-static int do_starttls(struct backend *s, struct tls_cmd_t *tls_cmd)
+static int do_starttls(struct backend *s, struct tls_cmd_t *tls_cmd,
+ char *c_cert_file, char *c_key_file)
{
#ifndef HAVE_SSL
return -1;
@@ -151,7 +152,7 @@
strncmp(buf, tls_cmd->ok, strlen(tls_cmd->ok)))
return -1;
- r = tls_init_clientengine(5, "", "");
+ r = tls_init_clientengine(5, c_cert_file, c_key_file);
if (r == -1) return -1;
/* SASL and openssl have different ideas about whether ssf is signed */
@@ -187,6 +188,8 @@
int local_cb = 0;
char buf[2048], optstr[128], *p;
const char *mech_conf, *pass;
+ char *c_cert_file = NULL;
+ char *c_key_file = NULL;
if (!cb) {
local_cb = 1;
@@ -241,6 +244,26 @@
mech_conf = config_getstring(IMAPOPT_FORCE_SASL_CLIENT_MECH);
}
+#ifdef HAVE_SSL
+ strlcpy(optstr, s->hostname, sizeof(optstr));
+ p = strchr(optstr, '.');
+ if (p) *p = '\0';
+ strlcat(optstr, "_tls_client_cert_file", sizeof(optstr));
+ c_cert_file = config_getoverflowstring(optstr, NULL);
+ if(!c_cert_file) {
+ c_cert_file = config_getstring(IMAPOPT_TLS_CLIENT_CERT_FILE);
+ }
+
+ strlcpy(optstr, s->hostname, sizeof(optstr));
+ p = strchr(optstr, '.');
+ if (p) *p = '\0';
+ strlcat(optstr, "_tls_client_key_file", sizeof(optstr));
+ c_key_file = config_getoverflowstring(optstr, NULL);
+ if(!c_key_file) {
+ c_key_file = config_getstring(IMAPOPT_TLS_CLIENT_KEY_FILE);
+ }
+#endif
+
do {
/* If we have a mech_conf, use it */
if (mech_conf) {
@@ -261,7 +284,7 @@
/* If we don't have a usable mech, do TLS and try again */
} while (r == SASL_NOMECH && CAPA(s, CAPA_STARTTLS) &&
- do_starttls(s, &prot->tls_cmd) != -1 &&
+ do_starttls(s, &prot->tls_cmd, c_cert_file, c_key_file) != -1 &&
(*mechlist = ask_capability(s->out, s->in, prot,
&s->capability,
prot->tls_cmd.auto_capa)));
diff -rub cyrus-imapd-2.3.13/imap/tls.c cyrus23_client_certs/imap/tls.c
--- cyrus-imapd-2.3.13/imap/tls.c 2008-04-15 18:58:08.000000000 +0100
+++ cyrus23_client_certs/imap/tls.c 2008-11-07 14:25:59.000000000 +0000
@@ -1214,11 +1214,11 @@
syslog(LOG_NOTICE,"TLS client engine: cannot load CA data");
}
- if (strlen(var_tls_cert_file) == 0)
+ if (var_tls_cert_file && (strlen(var_tls_cert_file) == 0))
c_cert_file = NULL;
else
c_cert_file = var_tls_cert_file;
- if (strlen(var_tls_key_file) == 0)
+ if (var_tls_key_file && (strlen(var_tls_key_file) == 0))
c_key_file = NULL;
else
c_key_file = var_tls_key_file;
diff -rub cyrus-imapd-2.3.13/lib/imapoptions cyrus23_client_certs/lib/imapoptions
--- cyrus-imapd-2.3.13/lib/imapoptions 2008-10-08 18:18:12.000000000 +0100
+++ cyrus23_client_certs/lib/imapoptions 2008-11-07 14:25:59.000000000 +0000
@@ -1075,6 +1075,14 @@
/* The list of SSL/TLS ciphers to allow. The format of the string is
described in ciphers(1). */
+{ "tls_client_cert_file", NULL, STRING }
+/* File containing the client certificate to send to remote servers
+ when making an SSL/TLS connection. */
+
+{ "tls_client_key_file", NULL, STRING }
+/* File containing the private key belonging to the client
+ certificate used when making an SSL/TLS connection. */
+
{ "tls_key_file", NULL, STRING }
/* File containing the private key belonging to the server
certificate. A value of "disabled" will disable SSL/TLS. */
Only in cyrus23_client_certs/lib: imapoptions.orig