Pregunta

I have a PHP login module that's based on SSL client certificates. It works well with Apache. Now I'm trying to figure out how to port it to nginx as well.

Using Apache it is very convenient to access the cert's content using the many environment variables set. The mail address will be in $_SERVER['SSL_CLIENT_S_DN_Email'] for example.

I've found the nginx variable $ssl_client_s_dn which I can pass to PHP via fastcgi_param. However, I will get the whole DN string.

  • Do I have to parse the provided DN string on my own or are there better ways?
  • If I have to parse it, which specification can I use to get the format right?
  • Does nginx provide the same string as Apache does for SSL_CLIENT_S_DN?
¿Fue útil?

Solución 2

Nginx uses OpenSSL's X509_NAME_oneline() function to generate the string. The documentation of this function states the following:

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.

Apache 2.2 uses the same function for SSL_CLIENT_S_DN. Since version 2.3.11, Apache HTTPD uses a RFC 2253 compatible format by default.

So to answer my own questions:

  • Do I have to parse the provided DN string on my own or are there better ways?

    The $ssl_client_s_dn variable is the only information nginx provides. As an alternative, the raw certificate data is availabe too. However, this would possibly lead to performance issue since nginx would have to copy the whole certificate for each call.

  • If I have to parse it, which specification can I use to get the format right?

    The string is formated as X509_NAME_oneline() is implemented. It looks like parsing this string can't be done in a bulletproof way.

  • Does nginx provide the same string as Apache does for SSL_CLIENT_S_DN?

    Apache prior to 2.3.11 does, later versions use the RFC 2253 format by default. However, they can be configured to use the legacy format.

Otros consejos

You can use a map directive like

 map  $ssl_client_s_dn  $ssl_client_s_dn_cn {
     default           "";
    ~/CN=(?<CN>[^/]+) $CN;
};

Then you can use $ssl_client_s_dn_cn variable. Similarly use a regex for email.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top