diff options
author | Stefan Bühler <stbuehler@web.de> | 2009-11-05 21:46:48 +0000 |
---|---|---|
committer | Stefan Bühler <stbuehler@web.de> | 2009-11-05 21:46:48 +0000 |
commit | e430ce09bc63a5a04f6eddd358db2fb5e0a314bd (patch) | |
tree | fa655120718239d0a86fb343e173cd510cd0d6a4 | |
parent | 2b79b9c3cbac44a966edc921c90e45ea6d4a9e7e (diff) | |
download | lighttpd-git-e430ce09bc63a5a04f6eddd358db2fb5e0a314bd.tar.gz |
export some SSL_CLIENT_* vars for client cert validation (fixes #1288, thx presbrey)
git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2688 152afb58-edef-0310-8abb-c4023f1b3aa9
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | src/base.h | 1 | ||||
-rw-r--r-- | src/configfile.c | 6 | ||||
-rw-r--r-- | src/response.c | 75 |
4 files changed, 83 insertions, 0 deletions
@@ -10,6 +10,7 @@ NEWS * disable warning "CLOSE-read" (fixes #2091) * mod_rrdtool: fix creating file if it doesn't exist (#1788) * reset tlsext_server_name in connection_reset - fixes random hostnames in the $HTTP["host"] conditional + * export some SSL_CLIENT_* vars for client cert validation (fixes #1288, thx presbrey) - 1.4.24 - 2009-10-25 * Add T_CONFIG_INT for bigger integers from the config (needed for #1966) @@ -280,6 +280,7 @@ typedef struct { unsigned short ssl_verifyclient_enforce; unsigned short ssl_verifyclient_depth; buffer *ssl_verifyclient_username; + unsigned short ssl_verifyclient_export_cert; unsigned short use_ipv6; unsigned short defer_accept; diff --git a/src/configfile.c b/src/configfile.c index 01213e7a..30371851 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -99,6 +99,7 @@ static int config_insert(server *srv) { { "ssl.verifyclient.enforce", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 57 */ { "ssl.verifyclient.depth", NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_SERVER }, /* 58 */ { "ssl.verifyclient.username", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_SERVER }, /* 59 */ + { "ssl.verifyclient.exportcert", NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_SERVER }, /* 60 */ { "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 }, { "server.virtual-root", "load mod_simple_vhost and use simple-vhost.server-root instead", T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_UNSET }, @@ -187,6 +188,7 @@ static int config_insert(server *srv) { s->ssl_verifyclient_enforce = 1; s->ssl_verifyclient_username = buffer_init(); s->ssl_verifyclient_depth = 9; + s->ssl_verifyclient_export_cert = 0; cv[2].destination = s->errorfile_prefix; @@ -238,6 +240,7 @@ static int config_insert(server *srv) { cv[57].destination = &(s->ssl_verifyclient_enforce); cv[58].destination = &(s->ssl_verifyclient_depth); cv[59].destination = s->ssl_verifyclient_username; + cv[60].destination = &(s->ssl_verifyclient_export_cert); srv->config_storage[i] = s; @@ -325,6 +328,7 @@ int config_setup_connection(server *srv, connection *con) { PATCH(ssl_verifyclient_enforce); PATCH(ssl_verifyclient_depth); PATCH(ssl_verifyclient_username); + PATCH(ssl_verifyclient_export_cert); return 0; } @@ -425,6 +429,8 @@ int config_patch_connection(server *srv, connection *con, comp_key_t comp) { PATCH(ssl_verifyclient_depth); } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.username"))) { PATCH(ssl_verifyclient_username); + } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("ssl.verifyclient.exportcert"))) { + PATCH(ssl_verifyclient_export_cert); } } } diff --git a/src/response.c b/src/response.c index df543a51..7ba5281c 100644 --- a/src/response.c +++ b/src/response.c @@ -131,6 +131,75 @@ int http_response_write_header(server *srv, connection *con) { return 0; } +#ifdef USE_OPENSSL +static void https_add_ssl_entries(connection *con) { + X509 *xs; + X509_NAME *xn; + X509_NAME_ENTRY *xe; + if ( + SSL_get_verify_result(con->ssl) != X509_V_OK + || !(xs = SSL_get_peer_certificate(con->ssl)) + ) { + return; + } + + xn = X509_get_subject_name(xs); + for (int i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) { + int xobjnid; + const char * xobjsn; + data_string *envds; + + if (!(xe = X509_NAME_get_entry(xn, i))) { + continue; + } + xobjnid = OBJ_obj2nid((ASN1_OBJECT*)X509_NAME_ENTRY_get_object(xe)); + xobjsn = OBJ_nid2sn(xobjnid); + if (!xobjsn) { + continue; + } + + if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) { + envds = data_string_init(); + } + buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_S_DN_")); + buffer_append_string(envds->key, xobjsn); + buffer_copy_string_len( + envds->value, + (const char *)xe->value->data, xe->value->length + ); + /* pick one of the exported values as "authed user", for example + * ssl.verifyclient.username = "SSL_CLIENT_S_DN_UID" or "SSL_CLIENT_S_DN_emailAddress" + */ + if (buffer_is_equal(con->conf.ssl_verifyclient_username, envds->key)) { + buffer_copy_string_buffer(con->authed_user, envds->value); + } + array_insert_unique(con->environment, (data_unset *)envds); + } + if (con->conf.ssl_verifyclient_export_cert) { + BIO *bio; + if (NULL != (bio = BIO_new(BIO_s_mem()))) { + data_string *envds; + int n; + + PEM_write_bio_X509(bio, xs); + n = BIO_pending(bio); + + if (NULL == (envds = (data_string *)array_get_unused_element(con->environment, TYPE_STRING))) { + envds = data_string_init(); + } + + buffer_copy_string_len(envds->key, CONST_STR_LEN("SSL_CLIENT_CERT")); + buffer_prepare_copy(envds->value, n+1); + BIO_read(bio, envds->value->ptr, n); + BIO_free(bio); + envds->value->ptr[n] = '\0'; + envds->value->used = n+1; + array_insert_unique(con->environment, (data_unset *)envds); + } + } + X509_free(xs); +} +#endif handler_t http_response_prepare(server *srv, connection *con) { @@ -279,6 +348,12 @@ handler_t http_response_prepare(server *srv, connection *con) { log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path : ", con->uri.path); } +#ifdef USE_OPENSSL + if (con->conf.is_ssl && con->conf.ssl_verifyclient) { + https_add_ssl_entries(con); + } +#endif + /** * * call plugins |