Browse Source

add support for sending a TLS client certificate

Anton Khirnov 10 years ago
parent
commit
167964933f
5 changed files with 41 additions and 0 deletions
  1. 2 0
      NEWS
  2. 14 0
      src/drv_imap.c
  3. 12 0
      src/mbsync.1
  4. 11 0
      src/socket.c
  5. 2 0
      src/socket.h

+ 2 - 0
NEWS

@@ -4,6 +4,8 @@ Network timeout handling has been added.
 
 
 A Maildir sub-folder naming style without extra dots has been added.
 A Maildir sub-folder naming style without extra dots has been added.
 
 
+Support for TLS client certificates was added.
+
 [1.2.0]
 [1.2.0]
 
 
 The 'isync' compatibility wrapper is now deprecated.
 The 'isync' compatibility wrapper is now deprecated.

+ 14 - 0
src/drv_imap.c

@@ -2779,6 +2779,20 @@ imap_parse_store( conffile_t *cfg, store_conf_t **storep )
 			}
 			}
 		} else if (!strcasecmp( "SystemCertificates", cfg->cmd )) {
 		} else if (!strcasecmp( "SystemCertificates", cfg->cmd )) {
 			server->sconf.system_certs = parse_bool( cfg );
 			server->sconf.system_certs = parse_bool( cfg );
+		} else if (!strcasecmp( "ClientCertificate", cfg->cmd )) {
+			server->sconf.client_certfile = expand_strdup( cfg->val );
+			if (access( server->sconf.client_certfile, R_OK )) {
+				sys_error( "%s:%d: ClientCertificate '%s'",
+				           cfg->file, cfg->line, server->sconf.client_certfile );
+				cfg->err = 1;
+			}
+		} else if (!strcasecmp( "ClientKey", cfg->cmd )) {
+			server->sconf.client_keyfile = expand_strdup( cfg->val );
+			if (access( server->sconf.client_keyfile, R_OK )) {
+				sys_error( "%s:%d: ClientKey '%s'",
+				           cfg->file, cfg->line, server->sconf.client_keyfile );
+				cfg->err = 1;
+			}
 		} else if (!strcasecmp( "SSLType", cfg->cmd )) {
 		} else if (!strcasecmp( "SSLType", cfg->cmd )) {
 			if (!strcasecmp( "None", cfg->val )) {
 			if (!strcasecmp( "None", cfg->val )) {
 				server->ssl_type = SSL_None;
 				server->ssl_type = SSL_None;

+ 12 - 0
src/mbsync.1

@@ -378,6 +378,18 @@ Note that the system's default certificate store is always used
 and should not be specified here.
 and should not be specified here.
 ..
 ..
 .TP
 .TP
+\fBClientCertificate\fR \fIpath\fR
+File containing a client certificate to send to the server.
+\fBClientKey\fR should also be specified.
+.br
+Note that client certificate verification is usually not required,
+so it is unlikely that you need this option.
+..
+.TP
+\fBClientKey\fR \fIpath\fR
+File containing the private key corresponding to \fBClientCertificate\fR.
+..
+.TP
 \fBPipelineDepth\fR \fIdepth\fR
 \fBPipelineDepth\fR \fIdepth\fR
 Maximum number of IMAP commands which can be simultaneously in flight.
 Maximum number of IMAP commands which can be simultaneously in flight.
 Setting this to \fI1\fR disables pipelining.
 Setting this to \fI1\fR disables pipelining.

+ 11 - 0
src/socket.c

@@ -230,6 +230,17 @@ init_ssl_ctx( const server_conf_t *conf )
 
 
 	SSL_CTX_set_verify( mconf->SSLContext, SSL_VERIFY_NONE, NULL );
 	SSL_CTX_set_verify( mconf->SSLContext, SSL_VERIFY_NONE, NULL );
 
 
+	if (conf->client_certfile && !SSL_CTX_use_certificate_chain_file( mconf->SSLContext, conf->client_certfile)) {
+		error( "Error while loading client certificate file '%s': %s\n",
+		       conf->client_certfile, ERR_error_string( ERR_get_error(), 0 ) );
+		return 0;
+	}
+	if (conf->client_keyfile && !SSL_CTX_use_PrivateKey_file( mconf->SSLContext, conf->client_keyfile, SSL_FILETYPE_PEM)) {
+		error( "Error while loading client private key '%s': %s\n",
+		       conf->client_keyfile, ERR_error_string( ERR_get_error(), 0 ) );
+		return 0;
+	}
+
 	mconf->ssl_ctx_valid = 1;
 	mconf->ssl_ctx_valid = 1;
 	return 1;
 	return 1;
 }
 }

+ 2 - 0
src/socket.h

@@ -50,6 +50,8 @@ typedef struct server_conf {
 	int timeout;
 	int timeout;
 #ifdef HAVE_LIBSSL
 #ifdef HAVE_LIBSSL
 	char *cert_file;
 	char *cert_file;
+	char *client_certfile;
+	char *client_keyfile;
 	char system_certs;
 	char system_certs;
 	char ssl_versions;
 	char ssl_versions;