I recently took over a system from a colleague which was built up using Apache, so I did my first steps using PHP. This document describes how to enable the sever with certificate authentication, something I havent found on the web.
How can I extract the user dn from the certificate ? I use the certificate data from apache, modify the presentation and do a ldap query using this one. Then I can enable users in the ldap group in order to authenticate them againts the server. Different groups with different rights are possible using user variables.
I set up a PHP Script for the Apache 2 which required PKI protection and a user management using given LDAP groups.
The following steps lead to a solution :
You have to put the CA in the cafile (PEM encoded, all in one file). Then you can test the https://servername connection. A real DNS name for the certificate is needer here to order a PKI certificate.
Create a private key for the server :
opensslreq -newkey rsa:2048 -keyout private.key -out request.csr -days 1095
– length 2048 bit
– algorithm RSA
– lifetime 1095 days= 3 years
Unprotect the server key from the password (otherwise, daemon would ask every restart for the password):
Use the request.csr for a certificate request against the ca (if you dont have a trust center available, maybe you have a look at open-ca).
Important are the following ssl.conf options for apache :
# Server Certificate:
# Point SSLCertificateFile at a PEM encoded certificate. If
# the certificate is encrypted, then you will be prompted for a
# pass phrase. Note that a kill -HUP will prompt again. A new
# certificate can be generated using the genkey(1) command.
SSLCertificateFile /etc/pki/tls/certs/server.crt (A)
# Server Private Key:
# If the key is not combined with the certificate, use this
# directive to point at the key file. Keep in mind that if
# you’ve both a RSA and a DSA private key you can configure
# both in parallel (to also allow the use of DSA ciphers, etc.)
SSLCertificateKeyFile /etc/pki/tls/private/server-key.pem (B)
# Server Certificate Chain:
# Point SSLCertificateChainFile at a file containing the
# concatenation of PEM encoded CA certificates which form the
# certificate chain for the server certificate. Alternatively
# the referenced file can be the same as SSLCertificateFile
# when the CA certificates are directly appended to the server
# certificate for convinience.
SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt (C)
# Certificate Authority (CA):
# Set the CA certificate verification path where to find CA
# certificates for client authentication or alternatively one
# huge file containing all of them (file must be PEM encoded)
SSLCACertificateFile /etc/pki/tls/certs/ssl_ca_certfile.crt (D)
# Client Authentication (Type):
# Client certificate verification type and depth. Types are
# none, optional, require and optional_no_ca. Depth is a
# number which specifies how deeply to verify the certificate
# issuer chain before deciding the certificate is not valid.
SSLVerifyClient require
SSLVerifyDepth 10
/etc/sysconfig/apache2 set
APACHE_SERVER_FLAGS=”SSL”
and finally
SSLOptions +ExportCertData
to export the certificate data. Using this, its possible to get the certifcate of the user.
<?php
if (!isset($_SERVER[‘SSL_CLIENT_S_DN’])) {
echo (“No PKI info, please contact server admins”);
#header(“location:../no_access.php”);
break;
} else {
$client_c_dn = $_SERVER[‘SSL_CLIENT_S_DN’];
}
# This little hack reformats the presentation of the user to an ldap friendly format
$client_c_cn=””;
$parts=explode(“/”,$client_c_dn);
for ($i=sizeof($parts)-1;$i>0;–$i) {
if (strlen($parts[$i])>1) {
#echo $parts[$i];
$client_c_cn=$client_c_cn.$parts[$i];
if ($i!=1){
#echo “,”;
$client_c_cn=$client_c_cn.”,”;
}
}
}
#echo $client_c_cn;
ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL, 7);
$ldapconn = ldap_connect(“ldaps://ldapserver”, 636) or die (“Cant connect to server”);
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
$ldapuser=”cn=ldapuser,[…]c=de”;
$ldappwd=”password”;
ldap_bind($ldapconn, $ldapuser, $ldappwd);
$basis_dn = “cn=ldapgroup,[…],c=de”;
$sr=ldap_search($ldapconn, $basis_dn, “member=$client_c_cn”);
$info = ldap_get_entries($ldapconn, $sr);
if (ldap_count_entries($ldapconn,$sr) > 0) {
ldap_close($ldapconn);
echo “Ldap group found”;
session_start();
$_SESSION[‘User’] = $client_c_cn;
header (“location:sapplication.php”);
break;
}
ldap_close($ldapconn);
# No LDAP Group found
#header(“location:../no_groupaccess.php”);
echo (“No ldap group found, please contact server admins”);
break;
Now you can check that the session variable has been set using
<?php
session_start();
#echo ("Start, user set:");
#echo $_SESSION['User'];
if(!isset($_SESSION[‘User’])){
header(“location:index.php”);
#echo (“No user variable found”);
break;
}
…program code starts here…
Using similar code, you can use pki 2factor authentication for the apache2 and use ldap to make a authorisation description per PHP page or per PHP function.
Feel free to ask for any more details.
How to create your own self signed ca :
http://oshogsb.blogspot.com/2007/07/how-to-create-custom-ca-and.html