SecurityModule.pm - Web Security Module
Note: This applies specifically to the MySQL implementation. There is also a SecurityModule::SQLite implementation.
use SecurityModule::MySQL; $sec = new SecurityModule::MySQL({CALLER_URL => $myurl, CONFIG => "/etc/sec/SecMod.conf"; LOGLEVEL => 5, KEYVALIDTIME => 7200, PWDFORM_HANDLER => \&myPasswordForm });
$ret = $sec->init(); # returns 0 in case of failure
$errmsg = $sec->getErrMsg(); # returns error message
# if getCookie() returns a defined value, your page needs to make # sure that this cookie will be set using CGI.pm's # header(-cookie => $cookie ) command if( ($cookie=$sec->getCookie) ) { print header(-cookie => $cookie ); } else { print header(); }
# Access to authentication / authorization information $state = $sec->getAuthnState(); # returns (failed | cert | passwd) $user_dn = $sec->getDN(); # returns user's distinguished name $roles = $sec->getRoles(); # returns a hash of roles, each role mapping to a # list of scopes
# Protecting functions: reqAuthnCert() and reqAuthnPasswd() sub my_certificate_protected_function { $sec->reqAuthnCert(); ... } sub my_password_protected_function { $sec->reqAuthnPasswd(); ... }
The SecurityModule handles authentication and authorization to a web site. Users are identified by a certificate loaded in their browser or by a previously set cookie that was issued upon a successful password authentication.
Certificate based authentication is the strongest authentication type,
so functions protected by the reqAuthnPasswd()
method will allow
access to certificate authenticated users, but reqAuthnCert()
will deny
access to password authenticated users.
The SecurityModule was written for a setup where a remote Proxy mediates access to a number of backend servers. The remote proxy handles the SSL authentication and is required to set the following request headers to the values of the respective environment variables for this request:
SSL_CLIENT_VERIFY, SSL_CLIENT_S_DN, HTTPS.
On the backend servers these must be available as environment variables of identical names except for the prefix HTTP_, e.g. HTTP_SSL_CLIENT_S_DN.
Since all backend servers are hidden behind the reverse proxy, an authentication cookie is set restrictively to only be sent back to the issueing server. The necessary translation for the proxy is handled transparently by apache's mod_proxy module (needs >= apache-2.2).
The SecurityModule can also be run without a reverse proxy in pure SSL mode if the REVPROXY directive is left out or set to 0.
Arguments which can be passed to the constructor:
CALLER_URL: (Required) URL of the current page that was invoked by the browser, i.e. it must contain the URL which the reverse proxy got before redirecting to the backend server.
CONFIG: Filename of a configuration file. The file must contain ``option = value'' lines as in this example:
LOGFILE = /tmp/SecMod.log REVPROXY = 137.138.65.249,137.138.65.224 LOGLEVEL = 5 KEYVALIDTIME = 1500 # Comments and empty lines are allowed DBHOST = localhost DBPORT = 3306 DBNAME = secmod DBUSER = smwriter DBPASS = mypasswd REQCERT_FAIL_HANDLER = https://localhost/bclear/testSecMod/nopermission PWDFORM_HANDLER = https://localhost/bclear/testSecMod/passform
Note: The configuration options specified in the constructor will override any options specified in the configuration file.
REVPROXY: comma separated list of the IP addresses of allowed reverse proxies. If this directive is ommitted, the module will work in non reverse proxy mode. If defined and the module receives a connection from a not allowed host, a high priority warning is issued to the log.
KEYVALIDTIME: Validity time in seconds of generated keys
PWDFORM_HANDLER: URL or reference to a function generating a password page. If a function reference is given, two values will be passed into the function: The URL of the present page (so we can get back) and a status message describing why the password form was called. If an URL is given, the two values will be passed using a query string (?caller_url=...&msg=...) in the redirection.
Status messages: password authentication required reauthentication invalid cookie
item *
SIGNUP_HANDLER: URL or reference to a function implementing a sign up page. Users which are not registered in the system (internally: users with no entry in the contacts table of SiteDB), but whose certificate was accepted by the web server are redirected to the sig up page. The same applies to users who have a valid login/password (since this information is synced from an external source), but are not registered with SiteDB yet.
REQCERT_FAIL_HANDLER: URL or reference to a function to call when a page secured by
reqAuthnCert()
is encountered and the client is not certificate authenticated.
Typically, to display some diagnostic message.
LOGFILE: Filename of the logfile. If this is undefined, all log messages are written to STDERR, i.e. they should end up in the web server's error log.
LOGLEVEL: Integer value from 0-5
0: no log messages at all 1: error and security relevant messages only 3: Logs password authentications (standard log level) 5: debugging messages
For the MySQL implementation you can also supply the DB connection parameters DBHOST, DBPORT, DBNAME, DBUSER, DBPASS
For the SQLite implementation you only need to supply a DBFILE parameter with the location of the data base file.
these functions can be used to formulate conditions easily
isSecure(): returns 1 if connection is SSL secured, 0 otherwise
isAuthenticated(): returns 1 if user is authenticated either by certificate or by password/cookie, 0 otherwise
isCertAuthenticated(): returns 1 if user is authenticated by SSL/certificate, 0 otherwise
isPasswdAuthenticated(): returns 1 if user is authenticated by password, 0 otherwise
hasRole(role)
or hasRole(role,scope): returns 1 if user is authorized to have the given role
or the given role/scope pair., 0 otherwise
These functions can be used to retrieve additional information about a user
getID(): returns the user ID. This is the principal authentication token
getDN(): returns the associated distinguished name
getUsername(): returns the short name used as the login name
getSurname(), getForename(): normal human name of the user
getEmail(): returns user's email
You can pass SecModPwd=1 as a GET variable to any page using the SecurityModule. This will call the handler for / redirect to the password form and insure that the user can return to the same page (the original page will be encoded in the caller_url parameter)
Derek Feichtinger <derek.feichtinger@psi.ch>
CMS web interfaces group <hn-cms-webInterfaces@cern.ch>
List of issues to resolve:
POST arguments are not carried across the password form
The mapping from username to certificate distinguished name needs to be established separately.
Look at ``TODO'' comments in the code.