My favorites | Sign in
Project Home Downloads
Search
for
CertificateAuthentication  
Certificate based authentication for php-syslog-ng with apache
Phase-Deploy, Featured
Updated Feb 4, 2010 by miguel.tormo

Introduction

This howto explains the set up for access control to php-syslog-ng using x.509 certificates. Almost any web browser is capable of doing client authentication in SSL protocol, and apache is easy to configure to allow that.

This authentication module works as follows:

  1. Check if the client certificate serial number exists in users table (using it as username)
  2. If not, check if client certificate subject's DN exists in users table.
  3. If no users where found, then deny access and revert to login page.

Needed php-syslog-ng version

This was first introduced in version 2.9.8f.

If you have a prior version, branch 2.9.8, you can apply the patch below:

diff -Nur html/includes/common_funcs.php htmlnew/includes/common_funcs.php
--- html/includes/common_funcs.php      2008-08-08 05:38:01.000000000 +0200
+++ htmlnew/includes/common_funcs.php   2008-08-12 22:19:58.000000000 +0200
@@ -761,6 +761,22 @@
                        $error .= " Sorry, $username does not have access to this service.";
                        $_SESSION["error"] = "$error";
                }
+       } elseif ($forms["authtype"] == "cert") {
+           // Using Cert basic authentication.Check certificate SerialNumber first, Subject DN if SerialNumber fails
+           $dbLink = db_connect_syslog(DBUSER, DBUSERPW);
+           if (verify_user($_SERVER['SSL_CLIENT_M_SERIAL'], $dbLink) || verify_user($_SERVER['SSL_CLIENT_S_DN'], $dbLink)) {
+             $sessionId = md5(mt_rand());
+             $_SESSION["pageId"] = "searchform";
+             $expTime = time()+SESSION_EXP_TIME;
+             $expTimeDB = date('Y-m-d H:i:s', $expTime);
+             // Update sessionId and exptime in database
+             $query = "UPDATE ".AUTHTABLENAME." SET sessionid='".$sessionId."',
+             exptime='".$expTimeDB."' WHERE username='".$username."'";
+             $result = perform_query($query, $dbLink);
+           } else {
+             $error .= " Sorry, $username does not have access to this service.";
+             $_SESSION["error"] = "$error";
+           }
        } else {
                // Not using LDAP or WebBasic, revert to local db authentication
                if ($_POST["username"]) {
diff -Nur html/login.php htmlnew/login.php
--- html/login.php      2008-05-10 19:18:32.000000000 +0200
+++ htmlnew/login.php   2008-08-12 22:18:20.000000000 +0200
@@ -47,6 +47,33 @@
        } else {
                print "Error:$error";
        }
+} elseif (defined('CERTAUTH_ENABLE') && (CERTAUTH_ENABLE == TRUE)) {
+    $_POST['username'] = $_SERVER['SSL_CLIENT_S_DN'];
+    $_POST['password'] = "nothing";
+    $_POST['authtype'] = "cert";
+
+    $error = login_check($_POST);
+    if (trim($error)=="") {
+        $_SESSION["member_id"] = login($_POST);
+        if ((stristr($_SESSION["member_id"], "Invalid") == TRUE) ||
+                (stristr($_SESSION["member_id"], "Sorry") == TRUE)) {
+            die($_SESSION["member_id"] ."<br><a href=" .INDEX_URL .">Return</a>");
+        }
+        // Cdukes: 3/20/08: Carry post variables through login
+        // Ref: http://code.google.com/p/php-syslog-ng/issues/detail?id=35
+        // Header("Location: " .INDEX_URL); // Redirect authenticated member
+        $destination = INDEX_URL;
+        // Remember search query across login
+        if (!empty($_POST['searchQuery']))
+        {
+            $destination .= '?' . ($_POST['searchQuery']);
+        }
+        Header("Location: " . $destination); // Redirect authenticated member
+        exit();
+    } else {
+        print "Error:$error";
+    }
+
 } else {
        ?>
                <html>

Configuration

You need to configure apache and php-syslog-ng to get this working. Needed changes are explained below.

Apache configuration

First, you need to configure apache to accept certificates from only the CA or CAs you want user certificates to be issued by. You can even force the SSL connection with client certificates from these CAs only. Imagine you have your running php-syslog-ng in a url such as https://myvirtualhost/logs. In your virtualhost directory config, put this:

    SSLEngine On
    # Next line is important for this to work
    SSLOptions +StdEnvVars +OptRenegotiate
    SSLCertificateFile /etc/apache2/ssl/server.pem
    SSLCertificateKeyFile /etc/apache2/ssl/server.key

    # Line below only needed if the CA signing apache server
    # cert is not distributed with the browser software:
    SSLCertificateChainFile /etc/apache2/ssl/serverca.pem

    <Location /logs>
      # CAs you want to use to issue certificates to users:
      SSLCACertificateFile /etc/apache2/certs/validca.pem

      # Here put 'require' to force client to provide certificate for SSL
      # or 'optional' to allow but not forcing (in the later case, you would
      # be able to access php-syslog-ng with fallback local user auth)
      SSLVerifyClient require
    </Location>

Now, restart apache. It should ask you for a client certificate when accessing php-syslog-ng.

php-syslog-ng database modification

Certificate DNs are often quite long, so it's advisable to extend the maximum length allowed for user names (not needed if you installed php-syslog-ng with version 2.9.8f or newer):

alter table users modify  username varchar(128) not null;
alter table user_access modify  username varchar(128) not null; 

Adding certificate-based users to php-syslog-ng

You have two ways to add them.

Web GUI

This is the common way to add users, and works for usual internal php-syslog-ng authentication. You can use this method too for adding subject DNs from certificates as usernames. Please notice that a certificate serial number can also be used as username. The expected format is in hexadecimal form, without digit separator like ':' and all capital letters. Example: 6424DAC46826DC45.

The only problem with this method is you have to enter a password, and thus this password could be used to authenticate using normal login instead of a certificate. You should also take into account that the regexp used for validating usernames won't work, so you should change this:

         "username" => "(^[A-Za-z_.@]{4,}\$)",

for something like this to catch most variants:

         "username" => "(^[A-Za-z0-9_.@/ =-]{4,}\$)",
Manual database insertion

You can insert subject DNs or certificate serial numbers manually into the database tables, just like this:

insert into users values (username='/CN=some common name/GN=First Name/SN=Family Name/OU=IT department', pwhash='nothingthatworks');

php-syslog-ng configuration

You must enable support for certificate based authentication in config.php by setting CERTAUTH_ENABLE to TRUE. Add line below if you don't have it:

define('CERTAUTH_ENABLE',TRUE);

Certificate TIPS

  • To have the Subject DN in the same format as Apache:
  • openssl x509 -in certificatefile.pem -noout -text | grep Subject:
  • To get the serial number in the expected format (take the output without ':' and in capitals):
  • openssl x509 -in certificatefile.pem -noout -text | grep -A 1 "Serial Number"
  • If you have the certificate in DER format instead of PEM, the commands are the same as the above but with -inform option, ie:
  • openssl x509 -in certificatefile.der -inform DER -noout -text | grep Subject:
Comment by project member cdu...@gmail.com, Aug 12, 2008

I've implemented this into v2.9.8f, so if you have 2.9.8f or later, there is no need to patch, alter the db tables or add the config variable (you will need to turn it on in config.php though)

Comment by cpirillo...@gmail.com, Dec 10, 2008

Hi Guys,

I am using appache 2.28 and PHP 5.2.7. I would like to implement supporting DN certificate at the php-syslog-ng web site. The place that appache will be modified is under the directory /usr/local/apache2/conf/extra/? The file is httpd-ssl.conf? If yes, it seems it does not correspond to the instruction for appache configuration ("your virtualhost directory config")given above. Has it implemeted at your sites? Could you email the config file (httpd-ssl.conf)?
Thanks in advance.

-Chris

Comment by cpirillo...@gmail.com, Dec 10, 2008

Hi Guys,

I also got another problem when I tried to insert the table users with DN manually using the command: insert into users values (username='/CN=some common name/GN=First Name/SN=Family Name/OU=IT department', pwhash='nothingthatworks'); Note that I have replaced it with my personal DN. The error is: ERROR 1136 (21S01): Column count doesn't match value count at row 1. The columns of table users are listed as follows:
mysql> describe users; +-----------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------+--------------+------+-----+---------+-------+ | username | varchar(128) | NO | PRI | NULL | | | pwhash | char(40) | YES | | NULL | | | sessionid | char(32) | YES | | NULL | | | exptime | datetime | YES | | NULL | | +-----------+--------------+------+-----+---------+-------+ 4 rows in set (0.00 sec)


Sign in to add a comment
Powered by Google Project Hosting