title: How do I obtain SSL_CLIENT_* variables from the SSL client certificate using PHP 5.6 running on Apache 2.4?
body: <p><strong>Introduction</strong></p>
  
  <p>I'm using PHP 5.6 and Apache 2.4 in the back-end of my web site where I use SSL to authenticate clients as an optional form of entering the site. I want to get some SSL_CLIENT_* variables which are contained in the certificate but aren't being shown by Apache 2.4, therefore, I cannot access them using <code>$_SERVER</code>.</p>
  
  <p><strong>Description</strong></p>
  
  <p>I want to get the following environment variables from the client certificate:</p>
  
  <ul>
  <li>SSL_CLIENT_S_DN_CN</li>
  <li>SSL_CLIENT_SAN_OTHER_msUPN_0</li>
  <li>SSL_CLIENT_SAN_Email_0</li>
  </ul>
  
  <p>When I dump <code>$_SERVER</code> in PHP 5.6 I can see what is returned by the variable <code>SSL_CLIENT_VERIFY</code>. If it returns <code>GENEROUS</code>, all three variables are shown; if it is <code>SUCCESS</code> only the first on the list above, <code>SSL_CLIENT_S_DN_CN</code>, is shown; and, if <code>SSL_CLIENT_VERIFY</code> is <code>NONE</code>, there is no certificate supplied by the client.</p>
  
  <p>I used XAMPP v3.2.2 on Windows 10 (Apache 2.4 and PHP 7.0) locally and I can access all the variables, but, somehow, I cannot do the same using a remote Debian 9 server running Apache 2.4 and PHP 5.6.</p>
  
  <p>I tried unsuccessfully to set up the <code>SSLRequire</code> (which is deprecated according to the docs - mod_ssl) option and Require as well.</p>
  
  <p>I resorted to StackOverflow and ServerFault search for similar questions, involving SSL client certificates, but all the questions I came across involve SSL basic configuration (HTTP to HTTPS, Proxy, etc.) and creating headers with existing environment variables, like SSLRequire that works this way, for what I understood by reading the docs.</p>
  
  <p>In the <code>default-ssl.conf</code> I tried to set the headers using the variables, but when I do the following:</p>
  
  <p><code>print_r(getallheaders());</code></p>
  
  <p>PHP 5.6 returns <code>NULL</code>:</p>
  
  <p><code>Array ( [...] [SSL_CLIENT_SAN_OTHER_msUPN_0] =&gt; (null) [SSL_CLIENT_SAN_Email_0] =&gt; (null) )</code></p>
  
  <p>The question again is how to get the variables <code>SSL_CLIENT_SAN_OTHER_msUPN_0</code> and <code>SSL_CLIENT_SAN_Email_0</code> from the client certificate.</p>
  
  <p><strong>Attachments</strong></p>
  
  <p><em>1. My Apache 2.4 SSL configuration file:</em></p>
  
  <p><code>default-ssl.conf</code></p>
  
  <pre><code>&lt;VirtualHost *:443&gt;
      ServerName myserver.name #Omitted
      RequestHeader set SSL_CLIENT_SAN_OTHER_msUPN_0 "%{SSL_CLIENT_SAN_OTHER_msUPN_0}s"
      RequestHeader set SSL_CLIENT_SAN_Email_0 "%{SSL_CLIENT_SAN_Email_0}s"
      ServerAdmin webmaster@localhost
      DocumentRoot /var/www/html
      # Configuracoes de cache    
      Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
      Header set Note "Cache desabilitado no servidor/host"
  
      ErrorLog ${APACHE_LOG_DIR}/error.log
      CustomLog ${APACHE_LOG_DIR}/access.log combined
      # Configuracao do SSL
      SSLEngine on
      # [...] Certificados AC e certificados da aplicacao: OMITTED
      SSLOptions +StdEnvVars +OptRenegotiate -StrictRequire +FakeBasicAuth -ExportCertData  
      # Solicita certificado SSL/TLS do cliente            
      SSLVerifyClient optional_no_ca 
      SSLVerifyDepth 3
  
      &lt;FilesMatch "\.(cgi|shtml|phtml|php)$"&gt;
          SSLOptions +OptRenegotiate -ExportCertData -StrictRequire +FakeBasicAuth +StdEnvVars
      &lt;/FilesMatch&gt;
      &lt;Directory /usr/lib/cgi-bin&gt;
          SSLOptions +StdEnvVars
      &lt;/Directory&gt;
      BrowserMatch "MSIE [2-6]" \
                   nokeepalive ssl-unclean-shutdown \
                   downgrade-1.0 force-response-1.0
      BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
  &lt;/VirtualHost&gt;
  </code></pre>
  
  <p><em>2. PHP 5.6 file</em></p>
  
  <p><code>index.php</code></p>
  
  <pre><code>&lt;?php //index.php
  
  // Get client certificate data
  $cn = $_SERVER['SSL_CLIENT_S_DN_CN'];
  $email = $_SERVER['SSL_CLIENT_SAN_Email_0'];
  $id = $_SERVER['SSL_CLIENT_SAN_OTHER_msUPN_0'];
  
  $client_certificate_data = [
      'cn' =&gt; $cn,
      'email' =&gt; $email,
      'id' =&gt; $id
  ];
  
  echo json_encode(
      $client_certificate_data,
      JSON_NUMERIC_CHECK
  );
  </code></pre>
  
  <p><code>// Output: {"cn":"EXAMPLE CN CONTENT HERE","email":null,"id":null}</code></p>