Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#342 closed enhancement (wontfix)

ssl hash of subject and issuer dn

Reported by: Alfred Reibenschuh Owned by:
Priority: major Milestone:
Component: nginx-module Version:
Keywords: ssl Cc:
uname -a: Linux NMFMQ1 2.6.32-042stab053.5 #1 SMP Tue Mar 27 11:42:17 MSD 2012 x86_64 x86_64 x86_64 GNU/Linux
nginx -V: nginx version: nginx/1.4.0

Description

the following patch enable to have the (open)ssl hash of issuer and subject in addition to the normal dn available as variables

diff -ur nginx-1.4.0/src/event/ngx_event_openssl.c nginx-1.4.0.patched/src/event/ngx_event_openssl.c
--- nginx-1.4.0/src/event/ngx_event_openssl.c 2013-02-23 12:54:25.000000000 +0100
+++ nginx-1.4.0.patched/src/event/ngx_event_openssl.c 2013-04-26 15:14:16.506854085 +0200
@@ -2391,6 +2391,41 @@


ngx_int_t

+ngx_ssl_get_subject_hash(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+ size_t len;
+ X509 *cert;
+ X509_NAME *name;
+
+ s->len = 0;
+
+ cert = SSL_get_peer_certificate(c->ssl->connection);
+ if (cert == NULL) {
+ return NGX_OK;
+ }
+
+ name = X509_get_subject_name(cert);
+ if (name == NULL) {
+ X509_free(cert);
+ return NGX_ERROR;
+ }
+
+ s->len = 16;
+ s->data = ngx_pnalloc(pool, 16);
+ if (s->data == NULL) {
+ X509_free(cert);
+ return NGX_ERROR;
+ }
+
+ len = sprintf((char*)s->data, "%08lX", X509_NAME_hash(name));
+
+ X509_free(cert);
+
+ return NGX_OK;
+}
+
+
+ngx_int_t

ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{

char *p;

@@ -2431,6 +2466,40 @@

return NGX_OK;

}


+ngx_int_t
+ngx_ssl_get_issuer_hash(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+ size_t len;
+ X509 *cert;
+ X509_NAME *name;
+
+ s->len = 0;
+
+ cert = SSL_get_peer_certificate(c->ssl->connection);
+ if (cert == NULL) {
+ return NGX_OK;
+ }
+
+ name = X509_get_issuer_name(cert);
+ if (name == NULL) {
+ X509_free(cert);
+ return NGX_ERROR;
+ }
+
+ s->len = 16;
+ s->data = ngx_pnalloc(pool, 16);
+ if (s->data == NULL) {
+ X509_free(cert);
+ return NGX_ERROR;
+ }
+
+ len = sprintf((char*)s->data, "%08lX", X509_NAME_hash(name));
+
+ X509_free(cert);
+
+ return NGX_OK;
+}
+

ngx_int_t
ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)

diff -ur nginx-1.4.0/src/event/ngx_event_openssl.h nginx-1.4.0.patched/src/event/ngx_event_openssl.h
--- nginx-1.4.0/src/event/ngx_event_openssl.h 2012-10-03 17:24:08.000000000 +0200
+++ nginx-1.4.0.patched/src/event/ngx_event_openssl.h 2013-04-26 15:11:49.966886008 +0200
@@ -145,10 +145,10 @@

ngx_str_t *s);

ngx_int_t ngx_ssl_get_certificate(ngx_connection_t *c, ngx_pool_t *pool,

ngx_str_t *s);

-ngx_int_t ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool,

  • ngx_str_t *s);

-ngx_int_t ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool,

  • ngx_str_t *s);

+ngx_int_t ngx_ssl_get_subject_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s);
+ngx_int_t ngx_ssl_get_subject_hash(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s);
+ngx_int_t ngx_ssl_get_issuer_dn(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s);
+ngx_int_t ngx_ssl_get_issuer_hash(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s);

ngx_int_t ngx_ssl_get_serial_number(ngx_connection_t *c, ngx_pool_t *pool,

ngx_str_t *s);

ngx_int_t ngx_ssl_get_client_verify(ngx_connection_t *c, ngx_pool_t *pool,

diff -ur nginx-1.4.0/src/http/modules/ngx_http_ssl_module.c nginx-1.4.0.patched/src/http/modules/ngx_http_ssl_module.c
--- nginx-1.4.0/src/http/modules/ngx_http_ssl_module.c 2013-03-20 11:36:57.000000000 +0100
+++ nginx-1.4.0.patched/src/http/modules/ngx_http_ssl_module.c 2013-04-26 14:57:00.796853986 +0200
@@ -254,6 +254,12 @@

{ ngx_string("ssl_client_i_dn"), NULL, ngx_http_ssl_variable,

(uintptr_t) ngx_ssl_get_issuer_dn, NGX_HTTP_VAR_CHANGEABLE, 0 },


+ { ngx_string("ssl_client_s_hash"), NULL, ngx_http_ssl_variable,
+ (uintptr_t) ngx_ssl_get_subject_hash, NGX_HTTP_VAR_CHANGEABLE, 0 },
+
+ { ngx_string("ssl_client_i_hash"), NULL, ngx_http_ssl_variable,
+ (uintptr_t) ngx_ssl_get_issuer_hash, NGX_HTTP_VAR_CHANGEABLE, 0 },
+

{ ngx_string("ssl_client_serial"), NULL, ngx_http_ssl_variable,

(uintptr_t) ngx_ssl_get_serial_number, NGX_HTTP_VAR_CHANGEABLE, 0 },

Change History (8)

comment:1 by Maxim Dounin, 7 years ago

What's the expected use of the variables introduced?

comment:2 by Alfred Reibenschuh, 7 years ago

unfortionately nginx uses an non-standad reprensentation of certificate issuer und subject dn.

openssl dn hashes are used primarely to lookup ca and/or issuer certificates.

the intended use is for a (mobile device management) application to provision nginx to whitelist particular sub-ca-issuers and/or subjects with root-ca-certs in ca-bundle.pem for service access outside of normal crl management and in the absense of more powerful methods.

http://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslrequire

vs

http://mod-auth-cert.sourceforge.net/

comment:3 by Maxim Dounin, 7 years ago

Resolution: wontfix
Status: newclosed

Hashes provided are not something expected to be unique, and use of such variables for access control is bad idea. Use $ssl_client_i_dn/$ssl_client_s_dn instead.

Representation used for $ssl_client_i_dn/$ssl_client_s_dn is the same as used by OpenSSL (as produced with X509_NAME_oneline() function and/or show by "openssl x509 -issuer -noout -in <cert>" command). If you think there is a better representation - please suggest one.

comment:4 by Alfred Reibenschuh, 7 years ago

  • the documentation for X509_NAME_oneline() states:

"The functions X509_NAME_oneline() and X509_NAME_print() are legacy functions which produce a non standard output form, they don't handle multi character fields and have various quirks and inconsistencies. Their use is strongly discouraged in new applications."

  • use X509_NAME_print_ex() with flag |XN_FLAG_RFC2253| to produce $ssl_client_?_dn.
  • check with "keytool -printcert -file <cert> |grep Issuer:"

comment:6 by Alfred Reibenschuh, 7 years ago

hmm, if you worry about ssl performance of having more variables to fill -- than you have a point

Last edited 7 years ago by Alfred Reibenschuh (previous) (diff)

comment:7 by Alfred Reibenschuh, 7 years ago

how about an option (ssl_extended_certificate_variables on/off) that produces the intended variables dynamically if set to on (default off) ?

comment:8 by Maxim Dounin, 7 years ago

It looks like Apache switched to a new format since 2.3.11, see LegacyDNStringFormat option. We might consider a switch as well, probably with an additional option to control format used.

Just for record, here is how to query names in RFC2253 using openssl itself:

openssl x509 -issuer -nameopt RFC2253 -noout -in <cert>
Note: See TracTickets for help on using tickets.