Show Contents Previous Page Next Page Chapter 6 - Authentication and Authorization / Authentication with the Secure Sockets Layer The SSL protocol does most of its work at a level beneath the workings of the HTTP protocol. The exchange and verificaton of digital certificates and the establishment of the encrypted channel all occur before any of Apache's handlers run. For this reason, authorization based on the contents of a digital certificate looks quite different from the other examples we've seen in this chapter. Furthermore, the details of authorization vary slightly among the different implementations of ApacheSSL. This section describes the way it works in Ralf S. Engelschall's mod_ssl. If you are using a different version of ApacheSSL, you should check your vendor's documentation for differences. The text representation of a typical client certificate is shown in Example 6-15.
It consists of a "Subject" section, which gives information on the person to
whom the certificate is issued, and a "Certificate" section, which gives information
about the certificate itself. Within the Subject section are a series of tag=value
pairs. There can be an arbitrary number of such pairs, but several are standard
and can be found in any certificate:
The user's distinguished name (DN) is a long string consisting of the concatenation of each of these fields in the following format: /C=US/SP=MA/L=Boston/O=Capricorn Organization/OU=Sales/CN=Wanda/Email=wanda@capricorn.com European users will recognize the footprints of the OSI standards committee here. The DN is guaranteed to be unique among all the certificates issued by a particular certificate-granting authority. The Certificate section contains the certificate's unique serial number and other data, followed by more tag=value pairs giving information about the organization issuing the certificate. The standard fields are the same as those described for the Subject. This is followed by a Validity period, which gives the span of time that the certificate should be considered valid. You are free to use any of these fields for authorization. You can authorize based on the user's CN field, on the certificate's serial number, on the Validity period, on the DN, or on any of the Subject or Issuer tags.
The certificate information is actually stored in a compact binary form rather than the text form shown here. When the connection is established, the SSL library parses out the certificate fields and stores them in a private data structure. During the fixup phase, these fields are turned into various environment variables with names like Example 6-15. An Example Client Certificate Subject: C=US SP=MA L=Boston O=Capricorn Organization OU=Sales CN=Wanda Email=wanda@capricorn.com Certificate: Data: Version: 1 (0x0) Serial Number: 866229881 (0x33a19e79) Signature Algorithm: md5WithRSAEncryption The most straightforward way to authenticate based on certificate information is to take advantage of the SSLRequire access control directive. In mod_ssl, such a directive might look like this: <Location /certified> SSLRequire %{SSL_CLIENT_S_DN_CN} in ("Wanda Henderson","Joe Bloe") \ and %{REMOTE_ADDR} =~ m/^192\.128\.3\.[0-9]+$/ </Location> This requires that the CN tag of the DN field of the Subject section of the certificate match either "Wanda Henderson" or "Joe Bloe", and that the browser's IP address satisfy a pattern match placing it within the 192.128.3 subnetwork. mod_ssl has a rich language for querying the contents of the client certificate. See its documentation for the details. Other ApacheSSL implementations also support operations similar to SSLRequire, but they differ somewhat in detail. Note that to Apache, SSLRequire is an access control operation rather than an authentication/authorization operation. This is because no action on the part of the user is needed to gain access--his browser either has the right certificate, or it doesn't.
A slightly more involved technique for combining certificate information with user authorization is to take advantage of the FakeBasicAuth option of the SSLOptions directive. When this option is enabled, mod_ssl installs an authentication handler that retrieves the DN from the certificate. The handler base64-encodes the DN and a hardcoded password (consisting of the string "password"), stuffs them into the incoming Authorization header field, and returns However, using FakeBasicAuth means that mod_ssl must be the first authentication handler run for the request and that an authentication handler further down the chain must be able to authenticate using the client's DN. It is much simpler to bypass all authentication handlers and obtain of the DN by using a subrequest. This takes advantage of the fact that during the fixup phase, mod_ssl places parsed copies of the certificate fields into the subprocess environment table, preparatory to copying them into a CGI script's environment. As an example, we'll show a simple authorization module named Apache::AuthzSSL which checks that a named field of the DN name matches that given in one or more require directives. A typical configuration section will look like this: SSLVerifyClient require SSLVerifyDepth 2 SSLCACertificateFile conf/ssl.crt/ca-bundle.crt <Directory /usr/local/apache/htdocs/ID/please> SSLRequireSSL AuthName SSL AuthType Basic PerlAuthenHandler Apache::OK PerlAuthzHandler Apache::AuthzSSL require C US require O "Capricorn Organization" require OU Sales Marketing </Directory> The SSLVerifyClient directive, which must be present in the main part of the configuration file, requires that browsers present client certificates. The SSLVerifyDepth and SSLCACertificateFile directives are used to configure how deeply mod_ssl should verify client certificates (see the mod_ssl documentation for details). The SSLRequireSSL directive requires that SSL be active in order to access the contents of this directory. AuthName and AuthType are not required, since we are not
performing Basic authentication, but we put them in place just in case some
module downstream is expecting them. Since the password is invariant when client
certificate verification is in use, we bypass password checking by installing
Apache::OK as the authentication handler for this directory.11Apache::OK is a ring module that exits with an Example 6-16 gives the code for Apache::AuthzSSL. It brings in Apache::Constants and the quotewords() text parsing function from the standard Text::ParseWords module. It recovers the request object and calls its requires() method to retrieve the list of authorization requirements that are in effect.
The handler then issues a subrequest and retrieves the value of
Now the routine loops through each of the requirements, breaking them into a DN field name and a list of possible values, each of which it checks in turn. If none of the specified values matches the DN, we log an error and return a Example 6-16. Authorizing Clients Based On Their Digital Certificate's DN package Apache::AuthzSSL; use strict; use Apache::Constants qw(:common); use Text::ParseWords qw(quotewords); sub handler { my $r = shift; return OK unless $r->is_main; my $requires = $r->requires; return DECLINED unless $requires; my $subr = $r->lookup_uri($r->uri); my $dn = $subr->subprocess_env('SSL_CLIENT_S_DN'); return DECLINED unless $dn; my(%dn) = $dn =~ m{/([^=]+)=([^/]+)}g; REQUIRES: for my $entry (@$requires) { my($field, @values) = quotewords('\s+', 0, $entry->{requirement}); foreach (@values) { next REQUIRES if $dn{$field} eq $_; } $r->log_reason("user $dn{CN}: not authorized", $r->filename); return FORBIDDEN; } # if we get here, then we passed all the requirements return OK; } 1; __END__
The only subtlety in this module is the rationale for returning A more advanced certificate authorization module would probably go to a database to determine whether the incoming certificate satisfied the requirements. As another example, Example 6-17 shows a small
access handler that rejects all certificates issued by out-of-state issuers.
It does so by looking at the value of the subprocess variable SSLVerifyClient require <Location /government/local> SSLRequireSSL PerlAccessHandler Apache::CheckCertState PerlSetVar IssuerState Maryland </Location>
The code simply retrieves the contents of the IssuerState configuration variable and the Example 6-17. Apache::CheckCertState Checks the SP (State/Province) Field of the Certificate Issuer package Apache::CheckCertState; # file: Apache/CheckCertState.pm use Apache::Constants qw(:common); sub handler { my $r = shift; return DECLINED unless $r->is_main; my $state = $r->dir_config('IssuerState'); return DECLINED unless defined $state; my $subr = $r->lookup_uri($r->uri); my $client_state = $subr->subprocess_env('SSL_CLIENT_I_DN_SP') || ""; return OK if $client_state eq $state; return FORBIDDEN; } 1; __END__ We hope this chapter has given you some idea of the range and versatility of Apache modules for controlling who can gain access to your site and what they do once they've connected. With the tools and examples presented in this chapter as a starting point, you should be able to implement almost any access control system you can imagine. The next chapter turns to some of the more esoteric handlers and module function-ality, showing you a variety of techniques for simplifying Apache administration and customizing the server's behavior. 11 Apache::OK is always available, along with Apache::DECLINED, since they are imported from Apache::Constants by Apache.pm at server startup time. Show Contents Previous Page Next PageCopyright © 1999 by O'Reilly & Associates, Inc. |
HIVE: All information for read only. Please respect copyright! |