Apache lookup module: Difference between revisions

From RavenWiki
Jump to navigationJump to search
(→‎Building the module: note changing APLOG_ERR -> APLOG_INFO)
(Note that 'Require LookupInst CS' doesn't actually work.)
Line 63: Line 63:
   Require LookupInst CS
   Require LookupInst CS


in a protection block. See below for other configuration options.
in a protection block (except that this example doesn't currently work - see below). See below for other configuration options.


<pre><nowiki>
<pre><nowiki>

Revision as of 18:00, 1 November 2007

This is an Apache2 module (which appears to work in Apache 2.0 and Apache 2.2) designed to perform authorization functions for an existing REMOTE_USER (as derived from Raven or otherwise) by querying lookup.

Please send questions about this module to lookup-support@ucs.cam.ac.uk.

Building the module

To build the module from source and copy it into the correct Apache directory, first unpack the distribution tar file and cd into the directory it creates:

 tar zxf mod_ucam_lookupquery-<ver>.tar.gz
 cd mod_ucam_lookupquery-<ver>

then issue the following command as root:

 apxs -c -i mod_ucam_lookupquery.c

apxs may not be on root's default path and may be renamed, e.g. to apxs2, on some platforms. apxs and related files are sometimes provided by a httpd-devel, apache-devel, or apache2-devel package which will need to be installed. You will also need the OpenLDAP development files which will probably be provided by an openldap2-devel package or similar.

Version 0.90 of the module isn't as portable as one might like. Depending on your platform details (Apache version, OpenLDAP version, C compiler, etc.) you may need to make some or all of the following changes:

  • Add, around line 26:
#include "http_request.h"  /* for ap_hook_auth_checker */
#include "apr_lib.h"       /* for apr_isspace.h */
  • At line 150, change
int error_code;

to

int error_code = 0;
  • For some older versions of OpenLDAP, Change lines 187/8 from
else if (strcmp(scope, "one") == 0) intscope = LDAP_SCOPE_ONE;
else if (strcmp(scope, "sub") == 0) intscope = LDAP_SCOPE_SUB;

to

else if (strcmp(scope, "one") == 0) intscope = LDAP_SCOPE_ONELEVEL;
else if (strcmp(scope, "sub") == 0) intscope = LDAP_SCOPE_SUBTREE;
  • Change line 575 from
regex_t *r = ap_pregcomp(p, w, REG_ICASE);

to

ap_regex_t *r = ap_pregcomp(p, w, AP_REG_ICASE);
  • Change line 829 from
while (s > fakeuser && isspace(s[-1])) s--;

to

while (s > fakeuser && apr_isspace(s[-1])) s--;

In addition you might want to change a number of instances (e.g. at lines 877, 910, and 196) of APLOG_ERR to APLOG_INFO to reduce the noise in your Apache error log.

Basic documentation

Load the module by including

 LoadModule ucam_lookupquery_module modules/mod_ucam_lookupquery.so

in the Apache configuration file, replacing 'modules/mod_ucamlookupquery.so' if necessary with the path to the the file containing the module, relative to ServerRoot if it doesn't start '/'.

To use it, include something like

 Require LookupInst CS

in a protection block (except that this example doesn't currently work - see below). See below for other configuration options.

OPTIONS
-------

LookupAuthoritative   
  Value:    on|off                 
  Default:  on

LookupHostPort        
  Value:    space-separated list   
  Default:  ldap.lookup.cam.ac.uk:389        (actually uses LDAP_PORT)
  
(1) IPv6 literal addresses can be enclosed in []. 
(2) It tries each one till one answers, one way or another.
   
LookupBase
  Value:    string
  Default:  "o=University of Cambridge,dc=cam,dc=ac,dc=uk"
  

AUTHENTICATION
--------------

LookupBindDN
  Value:    string
  Default:  unset
  
LookupPwd
  Value:    string
  Default:  unset    
  
If both of these are set, a non-anonymous LDAP bind is done, first setting up 
an encrypted (TLS) session. If either one is not set, a non-encrypted, 
anonymous bind is done.

  

REQUIREMENTS
------------

Apart from LookupQuery, all these come in pairs, LookupXxx and LookupXxxMatch.
The former do exact matches on the data, the latter do regular expression
matches. Multiple data values for a Require implement OR. Multiple Requires 
implement AND. It is not clear if this is the True Apache Way or not - I have
failed to find a definitive statement - but it seems to me that whether
multiple Requires do AND or OR should be controlled from a higher level
(compare "satisfy any" for Require+Allow) because each run of the module just
deals with a single Require and returns yes/no. There would have to be a much 
more elaborate memory scheme to implement OR at this level.

Require LookupInst[Match] name1 [name2 ...]
  Runs:     ou=people sub (uid=%u) inst
  Needs:    (a) Exactly one entry
            (b) Exactly one attribute value, must match one of the names 
  Example:  Require LookupInst CS CL 
 
Require LookupAttr[Match] comma-separated-attrnames value1 [value2 ...]
  Runs:     ou=people sub (uid=%u) comma-separated-attrnames
  Needs:    (a) Exactly one entry
            (b) At least one attribute value must match something in the list
  Example:  Require LookupAttr cn,displayName "Jon Warbrick" "Philip Hazel"
  
Require LookupParentInst[Match] name1 [name2 ...]
  Runs:     ou=people sub (uid=%u) inst  
  Needs:    (a) Exactly one entry
            (b) Exactly one attribute value, must match one of the names 
  Else:     ou=insts sub (instID=inst) parentInstID
  Needs:    (a) Exactly one entry
            (b) Exactly one attribute value, must match one of the names
  Else:     Loop up the tree till ROOT (which is checked).
  Example:  Require LookupParentInst COLL
  
Require LookupUserInGroup[Match] name1 [name2 ...]
  Runs:     ou=groups sub (uid=%u) groupID
  Needs:    (a) One or more entries
            (b) At least one of the groupIDs to match one of the names.
  Example:  Require LookupUserInGroup 100001 100656
  
Require LookupQuery baseplus scope filter
  Runs:     baseplus scope filter
  Needs:    One or more entries (no attributes are looked up)
  Example:  RequireLookupQuery ou=groups sub 
              (&(uid=%u)(groupTitle=*Computing Service*))
  
The last rather artificial example checks that the user is a member of at least
one group that has "Computing Service" in its title. To run a query on the base 
itself, the first argument can be given as an empty string in quotes.

In the filter, literal characters * ( ) \ must be escaped as follows:

  *  =>  \2A
  (  =>  \28
  )  =>  \29
  \  =>  \5C

The sequence %u is replaced by the userid. To include a literal % before a 
lower case u, use \75.

Bugs and potential enhancements

  • What about Apache 1.3?
  • Is there any way to keep a cached connection to ldap.lookup.cam.ac.uk? If so, should it be done?
  • 'Require LookupInst[Match]' expects exactly one attribute value, which won't be the case for someone affiliated to multiple institutions. To confuse matters, it reports a 'Temporary failure accessing the database' (because it gets an unexpected number of attributes). It should require at least one attribute value, which must match one of the names. As a work around, you can use something like
Require LookupQuery ou=people sub (&(uid=%u)(instID=CS))
  • The same applies (without the convenient work around) to LookupParentInst[Match]
  • There is no scope for matching against the allUid when checking group membership using a privileged account. Probably needs to run
ou=groups sub (&(uid=%u)(allUid=%u)) groupID