summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorstbuehler <stbuehler@152afb58-edef-0310-8abb-c4023f1b3aa9>2009-10-14 18:19:54 +0000
committerstbuehler <stbuehler@152afb58-edef-0310-8abb-c4023f1b3aa9>2009-10-14 18:19:54 +0000
commit20eab04d57337075f6d7b03b184c68a88ff3576c (patch)
tree3e3f548ecde3466f49b1186173864fa8113243b5
parent9b794792b8c02c29c2e4b4e495aa27022bfb3e22 (diff)
downloadlighttpd-20eab04d57337075f6d7b03b184c68a88ff3576c.tar.gz
Add SSL Client Certificate verification (#1288)
git-svn-id: svn://svn.lighttpd.net/lighttpd/trunk@2655 152afb58-edef-0310-8abb-c4023f1b3aa9
-rw-r--r--NEWS1
-rw-r--r--src/base.h5
-rw-r--r--src/configfile.c27
-rw-r--r--src/network.c24
-rw-r--r--src/server.c1
5 files changed, 58 insertions, 0 deletions
diff --git a/NEWS b/NEWS
index 756ba7d6..3b5aea94 100644
--- a/NEWS
+++ b/NEWS
@@ -144,6 +144,7 @@ NEWS
* Allow chunkqueue_skip to skip all types of chunks
* Use linux-epoll by default if available (fixes #2021)
* Add TLS servername indication (SNI) support (fixes #386, thx Peter Colberg <peter@colberg.org>)
+ * Add SSL Client Certificate verification (#1288)
- 1.5.0-r19.. -
* -F option added for spawn-fcgi
diff --git a/src/base.h b/src/base.h
index 7363ae0a..c3880af3 100644
--- a/src/base.h
+++ b/src/base.h
@@ -310,6 +310,11 @@ typedef struct {
buffer *ssl_ca_file;
buffer *ssl_cipher_list;
unsigned short ssl_use_sslv2;
+ unsigned short ssl_verifyclient;
+ unsigned short ssl_verifyclient_enforce;
+ unsigned short ssl_verifyclient_depth;
+ buffer *ssl_verifyclient_username;
+
unsigned short use_ipv6;
unsigned short is_ssl;
unsigned short allow_http11;
diff --git a/src/configfile.c b/src/configfile.c
index fe4a0a9a..0aa5778e 100644
--- a/src/configfile.c
+++ b/src/configfile.c
@@ -105,6 +105,10 @@ static int config_insert(server *srv) {
{ "server.breakagelog", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 57 */
{ "debug.log-timeouts", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION }, /* 58 */
{ "debug.log-ssl-noise", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 59 */
+ { "ssl.verifyclient.activate", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 60 */
+ { "ssl.verifyclient.enforce", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 61 */
+ { "ssl.verifyclient.depth", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 62 */
+ { "ssl.verifyclient.username", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 63 */
{ "server.host", "use server.bind instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
{ "server.docroot", "use server.document-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET },
@@ -173,6 +177,10 @@ static int config_insert(server *srv) {
s->errorfile_prefix = buffer_init();
s->ssl_cipher_list = buffer_init();
s->ssl_use_sslv2 = 1;
+ s->ssl_verifyclient = 0;
+ s->ssl_verifyclient_enforce = 1;
+ s->ssl_verifyclient_username = buffer_init();
+ s->ssl_verifyclient_depth = 9;
s->max_keep_alive_requests = 16;
s->max_keep_alive_idle = 5;
s->max_read_idle = 60;
@@ -242,6 +250,12 @@ static int config_insert(server *srv) {
cv[58].destination = &(s->log_timeouts);
cv[59].destination = &(s->log_ssl_noise);
+ /* ssl.verify */
+ cv[60].destination = &(s->ssl_verifyclient);
+ cv[61].destination = &(s->ssl_verifyclient_enforce);
+ cv[62].destination = &(s->ssl_verifyclient_depth);
+ cv[63].destination = s->ssl_verifyclient_username;
+
srv->config_storage[i] = s;
if (0 != (ret = config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv))) {
@@ -320,6 +334,11 @@ int config_setup_connection(server *srv, connection *con) {
PATCH(etag_use_mtime);
PATCH(etag_use_size);
+ PATCH(ssl_verifyclient);
+ PATCH(ssl_verifyclient_enforce);
+ PATCH(ssl_verifyclient_depth);
+ PATCH(ssl_verifyclient_username);
+
return 0;
}
@@ -416,6 +435,14 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) {
PATCH(global_kbytes_per_second);
PATCH(global_bytes_per_second_cnt);
con->conf.global_bytes_per_second_cnt_ptr = &s->global_bytes_per_second_cnt;
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.activate"))) {
+ PATCH(ssl_verifyclient);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.enforce"))) {
+ PATCH(ssl_verifyclient_enforce);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.depth"))) {
+ PATCH(ssl_verifyclient_depth);
+ } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.username"))) {
+ PATCH(ssl_verifyclient_username);
}
}
}
diff --git a/src/network.c b/src/network.c
index e2a06b68..9671c27e 100644
--- a/src/network.c
+++ b/src/network.c
@@ -670,6 +670,30 @@ int network_init(server *srv) {
ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
return -1;
}
+ if (s->ssl_verifyclient) {
+ STACK_OF(X509_NAME) *certs = SSL_load_client_CA_file(s->ssl_ca_file->ptr);
+ if (!certs) {
+ log_error_write(srv, __FILE__, __LINE__, "ssb", "SSL:",
+ ERR_error_string(ERR_get_error(), NULL), s->ssl_ca_file);
+ }
+ if (SSL_CTX_set_session_id_context(s->ssl_ctx, (void*) &srv, sizeof(srv)) != 1) {
+ log_error_write(srv, __FILE__, __LINE__, "ss", "SSL:",
+ ERR_error_string(ERR_get_error(), NULL));
+ return -1;
+ }
+ SSL_CTX_set_client_CA_list(s->ssl_ctx, certs);
+ SSL_CTX_set_verify(
+ s->ssl_ctx,
+ SSL_VERIFY_PEER | (s->ssl_verifyclient_enforce ? SSL_VERIFY_FAIL_IF_NO_PEER_CERT : 0),
+ NULL
+ );
+ SSL_CTX_set_verify_depth(s->ssl_ctx, s->ssl_verifyclient_depth);
+ }
+ } else if (s->ssl_verifyclient) {
+ log_error_write(
+ srv, __FILE__, __LINE__, "s",
+ "SSL: You specified ssl.verifyclient.activate but no ca_file"
+ );
}
if (SSL_CTX_use_certificate_file(s->ssl_ctx, s->ssl_pemfile->ptr, SSL_FILETYPE_PEM) < 0) {
diff --git a/src/server.c b/src/server.c
index 262f222f..c95dc2c9 100644
--- a/src/server.c
+++ b/src/server.c
@@ -338,6 +338,7 @@ static void server_free(server *srv) {
buffer_free(s->errorfile_prefix);
array_free(s->mimetypes);
buffer_free(s->ssl_cipher_list);
+ buffer_free(s->ssl_verifyclient_username);
#ifdef USE_OPENSSL
SSL_CTX_free(s->ssl_ctx);
#endif