---------------------
PatchSet 1161 
Date: 2001/01/07 11:09:08
Author: rbcollins
Branch: auth_rewrite
Tag: (none) 
Log:
auth scheme API added

Members: 
	doc/Programming-Guide/prog-guide.sgml:1.1.1.2.10.3.2.3->1.1.1.2.10.3.2.4 

Index: squid/doc/Programming-Guide/prog-guide.sgml
===================================================================
RCS file: /cvsroot/squid-sf//squid/doc/Programming-Guide/prog-guide.sgml,v
retrieving revision 1.1.1.2.10.3.2.3
retrieving revision 1.1.1.2.10.3.2.4
diff -u -r1.1.1.2.10.3.2.3 -r1.1.1.2.10.3.2.4
--- squid/doc/Programming-Guide/prog-guide.sgml	7 Jan 2001 00:34:19 -0000	1.1.1.2.10.3.2.3
+++ squid/doc/Programming-Guide/prog-guide.sgml	7 Jan 2001 11:09:08 -0000	1.1.1.2.10.3.2.4
@@ -2,7 +2,7 @@
 <article>
 <title>Squid Programmers Guide</title>
 <author>Duane Wessels, Squid Developers
-<date>$Id: prog-guide.sgml,v 1.1.1.2.10.3.2.3 2001/01/07 00:34:19 rbcollins Exp $</date>
+<date>$Id: prog-guide.sgml,v 1.1.1.2.10.3.2.4 2001/01/07 11:09:08 rbcollins Exp $</date>
 
 <abstract>
 Squid is a WWW Cache application developed by the National Laboratory
@@ -153,6 +153,14 @@
 	information and continues the access control checks when
 	the information is available.
 
+<sect1>Authentication Framework
+
+	<P>
+	These functions are responsible for handling HTTP authentication.
+	They follow a modular framework allow different auth schemes
+	to be added at will. For information on working with the auth schemes
+	See the chapter Authentication Framework.
+
 <sect1>Network Communication
 
 	<P>
@@ -2011,6 +2019,343 @@
 	<P>
 	To be written...
 
+<!-- %%%% Chapter : Authentication Framework %%%% -->
+<sect>Authentication Framework
+
+	<P>
+        <enum>
+        <item>Definition of an auth scheme.
+        <item>Data types
+        <item>How to add a new auth scheme
+        <item>How to 'hook in' new functions to the API.</enum>
+		
+	<P>
+	Definition of an auth scheme
+		
+	<P>An auth scheme in squid is the collection of functions required to
+        manage the authentication process for a given HTTP authentication
+        scheme. Existing auth schemes in squid are Basic and NTLM. Other HTTP
+        schemes (see for example rfc 2617) have been published and could be
+        implemented in squid. The term auth scheme and auth module are
+        interchangable. An auth module is not to be confused with an
+        authentication helper, which is a scheme specific external program used
+        by a specific scheme to perform data manipulation external to squid.
+        Typically this involves comparing the browser submitted credentials with
+        those in the organisation's user directory.
+		
+	<P>Auth modules SHOULD NOT perform access control functions. Squid has
+        advanced caching access control functionality already. Future work in
+        squid will allow a auth scheme helper to return group information for a
+        user, to allow Squid to more seamlessly implement access control.
+		
+	<P>Data types
+		
+	<P>The data types are presented in C for the simple reason that squid is
+        currently written exclusively in C.
+		
+	<P>Function typedefs.
+	
+	<P>Each function related to the general case of http authentication has
+        a matching typedef. There are some additional function types used to
+        register/initialise, deregister/shutdown and provide stats on auth
+        modules:
+		
+	<P>typedef int   AUTHSACTIVE();
+		
+	<P>The Active function is used by squid to determine whether the auth
+        module has successfully configured and initialised itself. If Active
+        returns 0 no other module functions except Shutdown/Dump/Parse/FreeConfig
+	will be called by Squid.
+		
+	<P>typedef void  AUTHSSETUP(authscheme_entry_t *);
+		
+	<P>functions of type AUTHSSETUP are used to register an auth module with
+        squid. The registration function MUST be named
+        "authSchemeSetup_SCHEME" where SCHEME is the auth_scheme as
+        defined by rfc 2617. Only one auth scheme registered in squid can
+        provide functionality for a given auth_scheme. (I.e. only one auth
+        module can handle Basic, only one can handle Digest and so forth). The
+        Setup function is responsible for registering the functions in the
+        auth module into the passed authscheme_entry_t. The authscheme_entry_t
+        will never be NULL. If it is NULL the auth module should log an error
+        and do nothing. The other functions can have any desired name that does
+        not collide with any statically linked function name within Squid. It is
+        recommended to use names of the form "authe_SCHEME_FUNCTIONNAME" (for example
+        authenticate_NTLM_Active is the Active() function for the NTLM auth
+        module.
+		
+	<P>typedef void  AUTHSSHUTDOWN(void);
+		
+	<P>Functions of type AUTHSSHUTDOWN are responsible for freeing any
+        resources used by the auth modules. The shutdown function will be called
+        before squid reconfigures, and before squid shutsdown.
+		
+	<P>typedef void  AUTHSINIT(authScheme *);
+		
+	<P>Functions of type AUTHSINIT are responsible for allocating any
+        needed resources for the authentication module. AUTHSINIT functions are
+        called after each configuration takes place before any new requests are
+        made.
+		
+	<P>typedef void  AUTHSPARSE(authScheme *, int, char *);
+		
+	<P>Functions of type AUTHSPARSE are responsible for parsing
+        authentication parameters. The function currently needs a scheme scope
+        data structure to store the configuration in. The passed scheme's
+        scheme_data pointer should point to the local data structure. Future
+        development will allow all authentication schemes direct access to their
+        configuration data without a locally scope structure. The parse function
+        is called by squid's config file parser when a auth_param scheme_name
+        entry is encountered.
+		
+	<P>typedef void  AUTHSFREECONFIG(authScheme *);
+		
+	<P>Functions of type AUTHSFREECONFIG are called by squid when freeing
+        configuration data. The auth scheme should free any memory allocated
+        that is related to parse data structures. The scheme MAY take advantage
+        of this call to remove scheme local configuration dependent data. (Ie
+        cached user details that are only relevant to a config setting).
+		
+	<P>typedef void  AUTHSDUMP(StoreEntry *, const char *, authScheme *);
+		
+	<P>Functions of type AUTHSDUMP are responsible for writing to the
+        StoreEntry the configuration parameters that a user would put in a
+        config file to recreate the running configuration.
+		
+	<P>typedef void  AUTHSSTATS(StoreEntry *);
+        <P>Functions of type AUTHSSTATS are called by the cachemgr to provide
+        statistics on the authmodule. Current modules simply provide the
+        statistics from the back end helpers (number of requests, state of the
+        helpers), but more detailed statistics are possible - for example unique
+        users seen or failed authentication requests.
+        <P>The next set of functions work on the data structures used by the
+        authentication schemes.
+		
+	<P>typedef void  AUTHSREQFREE(auth_user_request_t *);
+	
+	<P>The AUTHSREQFREE function is called when a auth_user_request is being
+        freed by the authentication framework, and scheme specific data was
+        present. The function should free any scheme related data and MUST set
+        the scheme_data pointer to NULL. Failure to unlink the scheme data will
+        result in squid dieing.
+		
+	<P>typedef char *AUTHSUSERNAME(auth_user_t *);
+		
+	<P>Squid does not make assumptions about where the username is stored.
+        This function must return a pointer to a NULL terminated string to be
+        used in logging the request. Return NULL if no username/usercode is
+        known. The string should NOT be allocated each time this function is
+        called.
+		
+	<P>typedef int   AUTHSAUTHED(auth_user_request_t *);
+	
+	<P>The AUTHED function is used by squid to determine whether the auth
+        scheme has successfully authenticated the user request. If timeouts on
+        cached credentials have occured or for any reason the credentials are
+        not valid, return false.<P>The next set of
+        functions perform the actual authentication. The functions are used by
+        squid for both WWW- and Proxy- authentication. Therefore they MUST NOT
+        assume the authentication will be based on the Proxy-* Headers.
+		
+	<P>typedef void  AUTHSAUTHUSER(auth_user_request_t *, request_t *, ConnStateData *, http_hdr_type);
+        <P>Functions of type AUTHSAUTHUSER are called when Squid has a request
+        that needs authentication. If needed the auth scheme can alter the
+        auth_user pointer (usually to point to a previous instance of the user
+        whose name is discovered late in the auth process. For an example of
+        this see the ntlm scheme). These functions are responsible for
+        performing any in-squid routines for the authentication of the user. The
+        auth_user_request struct that is passed around is only persistent for
+        the current request. If the auth module requires access to the structure
+        in the future it MUST lock it, and implement some method for identifying
+        it in the future. For example the NTLM module implements a connection
+        based authentication scheme, so the auth_user_request struct gets
+        referenced from the ConnStateData.
+		
+	<P>typedef void  AUTHSDECODE(auth_user_request_t *, const char *);
+		
+	<P>Functions of type AUTHSDECODE are responsible for decoding the passed
+        authentication header, creating or linking to a auth_user struct and for
+        storing any needed details to complete authentication in AUTHSAUTHUSER.
+		
+	<P>typedef int   AUTHSDIRECTION(auth_user_request_t *);
+		
+	<P>Functions of type AUTHSDIRECTION are used by squid to determine what
+        the next step in performing authentication for a given scheme is. The
+        following are the return codes:
+        
+        -2 = error in the auth module. Cannot determine request direction.
+        -1 = the auth module needs to send data to an external helper.
+        Squid will prepare for a callback on the request and call the
+         AUTHSSTART function.
+         0 = the auth module has all the information it needs to
+           perform the authentication and provide a succeed/fail result.
+         1 = the auth module needs to send a new challenge to the
+         request originator. Squid will return the appropriate status code
+         (401 or 407) and call the registered FixError function to allow the
+         auth module to insert it's challenge.
+		
+	<P>typedef void  AUTHSFIXERR(auth_user_request_t *, HttpReply *, http_hdr_type, request_t *);
+		
+	<P>Functions of type AUTHSFIXERR are used by squid to add scheme
+        specific challenges when returning a 401 or 407 error code. On requests
+        where no authentication information was provided, all registered auth
+        modules will have their AUTHSFIXERR function called. When the client
+        makes a request with an authentication header, on subsequent calls only the matching
+        AUTHSFIXERR function is called (and then only if the auth module
+        indicated it had a new challenge to send the client). If no auth schemes
+        match the request, the authentication credentials in the request are
+        ignored - and all auth modules are called.
+
+	<P>typedef void  AUTHSFREE(auth_user_t *);
+		
+	<P>These functions are responsible for freeing scheme specific data from
+        the passed auth_user_t structure. This should only be called by squid
+        when there are no outstanding requests linked to the auth user. This includes
+	removing the user from any scheme specific memory caches.
+		
+	<P>typedef void  AUTHSADDHEADER(auth_user_request_t *, HttpReply *, int);
+        typedef void  AUTHSADDTRAILER(auth_user_request_t *, HttpReply *, int);
+		
+	<P>These functions are responsible for adding any authentication
+        specific header(s) or trailer(s) OTHER THAN the WWW-Authenticate and
+        Proxy-Authenticate headers to the passed HttpReply. The int indicates
+        whether the request was an accelerated request or a proxied request. For
+        example operation see the digest auth scheme. (Digest uses a
+        Authentication-Info header.) This function is called whenever a
+        auth_user_request exists in a request when the reply is constructed
+        after the body is sent on chunked replies respectively.
+		
+	<P>typedef void  AUTHSONCLOSEC(ConnStateData *);
+		
+	<P>This function type is called when a auth_user_request is
+        linked into a ConnStateData struct, and the connection is closed. If any
+        scheme specific activities related to the request or connection are in
+        progress, this function MUST clear them.
+		
+	<P>typedef void AUTHSSTART(auth_user_request_t * , RH * , void *);
+		
+	<P>This function type is called when squid is ready to put the request
+        on hold and wait for a callback from the auth module when the auth
+        module has performed it's external activities.
+		
+	<P>Structures
+		
+	<P>This is used to link auth_users into the username cache. Because some
+        schemes may link in aliases to a user, the link is not part of the
+        auth_user structure itself.
+		
+	<P>struct _auth_user_hash_pointer {
+    /* first two items must be same as hash_link */
+    char *key;
+    auth_user_hash_pointer *next;
+    auth_user_t *auth_user;
+    dlink_node link; /* other hash entries that point to the same auth_user */
+        };
+		
+	<P>This is the main user related structure. It stores user-related data,
+        and is persistent across requests. It can even persistent across
+        multiple external authentications. One major benefit of preserving this
+        structure is the cached acl match results. This structure, is private to
+        the authentication framework.
+		
+	<P>struct _auth_user_t {
+    /* extra fields for proxy_auth */
+    /* this determines what scheme owns the user data. */
+    auth_type_t auth_type;
+    /* the index +1 in the authscheme_list to the authscheme entry */
+    int auth_module;
+    /* we only have one username associated with a given auth_user struct */
+    auth_user_hash_pointer *usernamehash;
+    /* we may have many proxy-authenticate strings that decode to the same user*/
+    dlink_list proxy_auth_list;
+    dlink_list proxy_match_cache;
+    struct {
+    unsigned int credentials_ok:2; /*0=unchecked,1=ok,2=failed*/
+    } flags;
+    long expiretime;
+    /* IP addr this user authenticated from */
+    struct in_addr ipaddr;
+    time_t ip_expiretime;
+    /* how many references are outstanding to this instance*/
+    size_t references;
+    /* the auth scheme has it's own private data area */
+    void *scheme_data;
+    /* the auth_user_request structures that link to this. Yes it could be a splaytree
+     * but how many requests will a single username have in parallel? */
+    dlink_list requests;
+        };
+		
+	<P>This is a short lived structure is the visible aspect of the
+        authentication framework.
+		
+	<P>struct _auth_user_request_t {
+    /* this is the object passed around by client_side and acl functions */
+    /* it has request specific data, and links to user specific data */
+    /* the user */
+    auth_user_t *auth_user;
+    /* return a message on the 401/407 error pages */
+    char *message;
+    /* any scheme specific request related data */
+    void *scheme_data;
+    /* how many 'processes' are working on this data */
+    size_t references;
+        };
+       
+        The authscheme_entry struct is used to store the runtime registered
+        functions that make up an auth scheme. An auth scheme module MUST implement
+        ALL functions except the
+        following functions: oncloseconnection, AddHeader, AddTrailer.. In
+        the future more optional functions may be added to this data type.
+		
+	<P>
+        struct _authscheme_entry {
+    char *typestr;
+    AUTHSACTIVE   *Active;
+    AUTHSADDHEADER *AddHeader;
+    AUTHSADDTRAILER *AddTrailer;
+    AUTHSAUTHED   *authenticated;
+    AUTHSAUTHUSER *authAuthenticate;
+    AUTHSDUMP     *dump;
+    AUTHSFIXERR   *authFixHeader;
+    AUTHSFREE     *FreeUser;
+    AUTHSFREECONFIG *freeconfig;
+    AUTHSUSERNAME *authUserUsername;
+    AUTHSONCLOSEC *oncloseconnection; /*optional*/
+    AUTHSDECODE   *decodeauth;
+    AUTHSDIRECTION *getdirection;
+    AUTHSPARSE    *parse;
+    AUTHSINIT     *init;
+    AUTHSREQFREE  *requestFree;
+    AUTHSSHUTDOWN *donefunc;
+    AUTHSSTART    *authStart;
+    AUTHSSTATS    *authStats;
+        };
+		
+	<P>For information on the requirements for each of the functions, see
+        the details under the typedefs above. For reference implementations, see
+        the squid source code, /src/auth/basic for a request based stateless auth module, and
+        /src/auth/ntlm for a connection based stateful auth module.
+	
+	<P>How to add a new auth scheme
+		
+	<P>Copy the nearest existing auth scheme and modify to recieve the
+        approprate scheme headers. Now step through the acl.c MatchAclProxyUser
+        function's code path and see how the functions call down through
+        authenticate.c to your scheme. Write a helper to provide you scheme with
+        any backend existence it needs. Remember any blocking code must go in
+        AUTHSSTART function(s) and _MUST_ use callbacks.
+		
+	<P>How to 'hook in' new functions to the API.
+		
+	<P>Start of by figuring the code path that will result in the function
+        being called, and what data it will need. Then create a typedef for the
+        function, add and entry to the authscheme_entry struct. Add a wrapper
+        function to authenticate.c (or if approprate cf_cache.c) that called the
+        scheme specific function if it exists. Test it. Test it again. Now
+        port to all the existing auth schemes, or at least add a setting
+        of NULL for the function for each scheme.
+
+
 <!-- %%%% Chapter : ICP %%%% -->
 <sect>ICP
 
