/* This file is part of mod_auth_cache $Id$ Copyright (c) 2002 EnBW Service GmbH, M.Kuhn Copyright (c) 2001 Heiko Schwarz Copyright (c) 2003 Sergey Strakhov Visit http://mod-auth-cache.sourceforge.net for updates. This product includes software developed by the Apache Group for use in the Apache HTTP server project (http://www.apache.org/). mod_auth_cache is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. mod_auth_cache is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "httpd.h" #include "http_config.h" #include "http_log.h" #include "http_protocol.h" #include "ap_config.h" #if MODULE_MAGIC_COOKIE == 0x41503230UL /* Apache 2.0.x */ #include "ap_compat.h" #endif #include #ifndef FALSE #define FALSE 0 #define TRUE !FALSE #endif #ifndef MOD_AUTHCACHE_TIME_RELAX #define MOD_AUTHCACHE_TIME_RELAX (60*30) // to prevent an error, when two servers have a different time, this are the seconds to tolerate #endif // #define MOD_AUTHCACHE_DEBUG 1 // to enable debug messages into error_log #if MODULE_MAGIC_COOKIE == 0x41503230UL /* Apache 2.0.x */ module AP_MODULE_DECLARE_DATA auth_cache_module; #else /* Apache 1.3.x */ module MODULE_VAR_EXPORT auth_cache_module; #endif typedef struct auth_cache_config_struct { unsigned int auth_cache_on; unsigned int auth_cache_save_authorization; unsigned int auth_cache_strong_encryption; /* not yet implemented */ unsigned int auth_cache_on_server; /* not yet implemented */ unsigned int auth_cache_suppress_port; /* no : send our port in header(default for backward compatibility), yes: donīt send it (use a 0 instead) */ unsigned int auth_cache_send_def_domain_flag; /* 0 : use actual domain = default for backward compatibility */ /* 1 : send the domain specified auth_cache_send_domain_name */ char *auth_cache_send_domain; /* 0 : use servername, no domain = default for backward compatibility */ /* 1 : use full actual domain */ /* 1 : ommits the first part, send only the last parts of a domain */ /* 2 : ommits the first 2 parts, send only the last parts of a domain */ /* 3 : ommits the first 3 parts, send only the last parts of a domain */ char *auth_cache_send_full_path; /* 0 : use full actual path = default for backward compatibility */ /* 1 : send only the root / as path */ char *auth_cache_timeout; char *auth_cache_send_domain_name; /* Name of the Domain we should send in cookie, if auth_cache_send_domain > 0*/ char *auth_cache_send_extra_domain_name; /* Name of an extra Domain we should send also an cookie, if auth_cache_send_domain > 0*/ } auth_cache_config_rec; #if MODULE_MAGIC_COOKIE == 0x41503230UL /* Apache 2.0.x */ #define ap_set_flag_slot {.flag=ap_set_flag_slot} #define ap_set_string_slot {.take1=ap_set_string_slot} /* Was in ap_config.h before (in Apache 1.3.x) */ /* Finding offsets of elements within structures. * Taken from the X code... they've sweated portability of this stuff * so we don't have to. Sigh... */ #if defined(CRAY) || (defined(__arm) && !defined(LINUX)) #ifdef __STDC__ #define XtOffset(p_type,field) _Offsetof(p_type,field) #else #ifdef CRAY2 #define XtOffset(p_type,field) \ (sizeof(int)*((unsigned int)&(((p_type)NULL)->field))) #else /* !CRAY2 */ #define XtOffset(p_type,field) ((unsigned int)&(((p_type)NULL)->field)) #endif /* !CRAY2 */ #endif /* __STDC__ */ #else /* ! (CRAY || __arm) */ #define XtOffset(p_type,field) \ ((long) (((char *) (&(((p_type)NULL)->field))) - ((char *) NULL))) #endif /* !CRAY */ #ifdef offsetof #define XtOffsetOf(s_type,field) offsetof(s_type,field) #else #define XtOffsetOf(s_type,field) XtOffset(s_type*,field) #endif #define R_USER r->user #define R_PORT r->server->port #define R_AUTH_TYPE r->ap_auth_type #else /* Apache 1.3.x */ /* A wrapper for ap_log_rerror() to drop the 4th parameter */ inline void __ap_log_rerror(const char *file, int line, int level, int status, const request_rec *s, ...) { va_list args; va_start(args, s); ap_log_rerror(file, line, level, s, args); va_end(args); } #define ap_log_rerror __ap_log_rerror #define R_USER r->connection->user #define R_PORT r->connection->server->port #define R_AUTH_TYPE r->connection->ap_auth_type #endif /* init config with default values */ static void *create_auth_cache_dir_config( #if MODULE_MAGIC_COOKIE == 0x41503230UL apr_pool_t *p, #else pool *p, #endif char *d) { auth_cache_config_rec *crec = (auth_cache_config_rec *) ap_pcalloc(p, sizeof(auth_cache_config_rec)); crec->auth_cache_on = 0; /* default: don't cache */ crec->auth_cache_save_authorization = 0; /* default: don't save authorization header */ crec->auth_cache_strong_encryption = 0; /* not yet implemented */ crec->auth_cache_on_server = 0; /* not yet implemented */ crec->auth_cache_timeout = "0"; /* default: never */ crec->auth_cache_send_def_domain_flag = 0;/* default: use actual domain (backward compatibile) */ crec->auth_cache_send_domain = 0; /* default: use servername, no domain (backward compatibile) */ crec->auth_cache_send_full_path = 0; /* default: use full actual path (backward compatibile) */ crec->auth_cache_send_domain_name = ""; /* default: empty */ crec->auth_cache_suppress_port = 0; /* default: send our port in header(backward compatibile) */ crec->auth_cache_send_extra_domain_name = ""; /* default: empty */ return crec; } /* configuration commands */ static const command_rec auth_cache_cmds[] = { {"AuthCache", ap_set_flag_slot, (void *) XtOffsetOf(auth_cache_config_rec, auth_cache_on), OR_AUTHCFG, FLAG, "set to 'on' to activate authentication caching here"}, {"AuthCacheSaveAuthorization", ap_set_flag_slot, (void *) XtOffsetOf(auth_cache_config_rec, auth_cache_save_authorization), OR_AUTHCFG, FLAG, "set to 'on' to activate saving and restoring of authorization header"}, {"AuthCacheTimeout", ap_set_string_slot, (void *) XtOffsetOf(auth_cache_config_rec, auth_cache_timeout), OR_AUTHCFG, TAKE1, "set to number of seconds after that a reauthentication is needed (0=never)"}, {"AuthCacheDomainName", ap_set_string_slot, (void *) XtOffsetOf(auth_cache_config_rec, auth_cache_send_domain_name), OR_AUTHCFG, TAKE1, "when set to a domain name, this is used instead of the server-info"}, {"AuthCacheSendDomain", ap_set_string_slot, (void *) XtOffsetOf(auth_cache_config_rec, auth_cache_send_domain), OR_AUTHCFG, TAKE1, "set '0'=dont send domain,use severname '1':send full domain '2':send last 2parts of domain '3':last 3 parts of domain"}, {"AuthCacheSendFullPath", ap_set_string_slot, (void *) XtOffsetOf(auth_cache_config_rec, auth_cache_send_full_path ), OR_AUTHCFG, TAKE1, "set '0'=send full path in cookie '1': only root-path"}, {"AuthCacheSuppressPort", ap_set_flag_slot, (void *) XtOffsetOf(auth_cache_config_rec, auth_cache_suppress_port ), OR_AUTHCFG, FLAG, "set to 'on' to suppress port in CookieName"}, {"AuthCacheExtraDomainName", ap_set_string_slot, (void *) XtOffsetOf(auth_cache_config_rec, auth_cache_send_extra_domain_name), OR_AUTHCFG, TAKE1, "when set to a domain name, an additional cookie is set for this domain"}, {NULL} }; /* Kill first n-parts of a domain name */ static char *kill_domain_parts( request_rec *r, char *domain, long parts_to_kill ) { long I; char *dom, *dom2; dom = domain; #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: kill_domain_parts, startdom=%s, partstokill=%d", dom,parts_to_kill); #endif if( dom == NULL ) return dom; for ( I=1; I < parts_to_kill; I++ ) { dom2 = strchr(dom, '.'); if(( dom2 == NULL ) || (dom2==dom)) { return dom2; } dom = dom2; #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: kill_domain_parts, rest=%s",dom); #endif } return dom; } /* Analyse our config and prepare the string needed by read_cookie and set_cookie */ /* take care: domain_name, cookiepath and cookie_start_name must be allocated in */ /* the caller function, we estimate 1024 free char in every ! */ void analyse_config( request_rec *r, auth_cache_config_rec *crec, long *timeout, unsigned int *send_domain, unsigned int *port, char *domain_name, char *cookiepath, char *cookie_start_name ) { char *pathend; long l; /* get cookie timeout value from configuration */ if (crec->auth_cache_timeout) *timeout=atol(crec->auth_cache_timeout); /* get cookie domain_name from configuration */ if( (crec->auth_cache_send_domain_name) && (crec->auth_cache_send_domain_name != "")) { strcpy(domain_name, crec->auth_cache_send_domain_name); } else { strcpy(domain_name, (char*)ap_get_server_name(r)); } if (crec->auth_cache_send_domain) { l=atol(crec->auth_cache_send_domain); } else { l = 0; } #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: analyse_config, send_domain_name=%s, send_domain=%s, l=%d", crec->auth_cache_send_domain_name, crec->auth_cache_send_domain, l); #endif switch (l) { case 1 : case 2 : case 3 : case 4 : strcpy( domain_name, kill_domain_parts( r, domain_name, l )); strcpy( cookie_start_name, domain_name ); *send_domain = 1; break; default: strcpy( cookie_start_name, (char*)ap_get_server_name(r)); *send_domain = 0; break; } #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: send_domain_name=%s cookiestart_domain_name=%s send_domain=%d", domain_name, cookie_start_name, *send_domain); #endif /* get full_path value from configuration */ if (crec->auth_cache_send_full_path == 0) { ap_snprintf(cookiepath, sizeof(cookiepath), r->uri); pathend=strrchr(cookiepath,'/'); if (pathend) *++pathend='\0'; } else { strcpy( cookiepath,"/" ); } #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: cookiepath=%s ", cookiepath); #endif if (!crec->auth_cache_suppress_port) { *port = R_PORT; } else { *port = 0; } return; } /***********************************************************/ /* in fixup: */ /* add cookie to response if necessary */ static int auth_cache_set_cookie(request_rec *r) { char cookiename[1024]; char cookie_extraname[1024]; char cookiebuf[1024]; char enc_cookiebuf[1024]; char cookiepath[1024] = ""; char domain_name[1024] = ""; char cookie_start_name[1024] = ""; char *pathend; char *value; char *new_cookie; const char *cookie; const char *sendoutcookie; const char *authorization; long timeout; unsigned int send_domain; unsigned int port; int res; time_t t; auth_cache_config_rec *crec = (auth_cache_config_rec *) ap_get_module_config(r->per_dir_config, &auth_cache_module); /* module activated; if not -> return */ if (!crec->auth_cache_on) return OK; /* check if user was authenticated by a different module; if not -> return */ if (R_USER==NULL || strlen(R_USER)==0 || strstr(cookiebuf,"(null)")) return OK; /* init memory. */ memset(cookie_start_name, 0, sizeof(*cookie_start_name)); memset(cookiepath, 0, sizeof(*cookiepath)); memset(domain_name, 0, sizeof(*domain_name)); memset(cookiename, 0, sizeof(*cookiename)); memset(cookie_extraname, 0, sizeof(*cookie_extraname)); memset(cookiebuf, 0, sizeof(*cookiebuf)); memset(enc_cookiebuf, 0, sizeof(*enc_cookiebuf)); /* analyse our config and prepare all information */ analyse_config( r, crec, &timeout, &send_domain, &port, domain_name,cookiepath,cookie_start_name ); /* construct cookie name */ ap_snprintf(cookiename, sizeof(cookiename), "Apache-AuthCache-%s:%d-%s:%s", cookie_start_name, port, ap_auth_type(r), ap_auth_name(r)); #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: make cookie_extraname from %s:%d-%s:%s ", crec->auth_cache_send_extra_domain_name,port, ap_auth_type(r), ap_auth_name(r)); #endif ap_snprintf(cookie_extraname, sizeof(cookiename), "Apache-AuthCache-%s:%d-%s:%s", crec->auth_cache_send_extra_domain_name,port, ap_auth_type(r), ap_auth_name(r)); /* is cookie already set ? */ if ((cookie = (char *)ap_table_get(r->headers_in, "Cookie"))) { #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: set_cookie, checking cookies = %s, searching for %s", cookie, cookiename ); #endif if ((value = strstr(cookie, cookiename))) { char *cookiebuf, *cookieend; value += strlen(cookiename) + 1; cookiebuf = (char *)ap_pstrdup(r->pool, value); cookieend = strchr(cookiebuf, ';'); if (cookieend) *cookieend = '\0'; // check if cookie is already set; if set -> return if (!(cookiebuf==NULL||strstr(cookiebuf,"(null)")||strlen(cookiebuf)==0)) { return OK; } } else { ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: set_cookie, wrong cookie = %s found, searching for %s, setting ours", cookie, cookiename ); } } /* if saving of authorization header is deactivated, set it in cookie to "" */ if (!(crec->auth_cache_save_authorization&& (authorization = (char *)ap_table_get(r->headers_in, "Authorization")))) { authorization=""; } /* construct cookie value */ t=time(&t); /* get current time and store it in cookie */ ap_snprintf(cookiebuf, sizeof(cookiebuf), "%ld:%s:%s:%s", t, r->connection->remote_ip, authorization, R_USER); #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: make cookievalues= %s", cookiebuf); #endif /* encode the content base64 */ res = ap_base64encode(enc_cookiebuf,cookiebuf,strlen(cookiebuf)); /* construct the whole cookie */ if ( send_domain != 0 ) { new_cookie = (char *)ap_psprintf(r->pool, "%s=%s; path=%s; domain=%s;", cookiename, enc_cookiebuf, cookiepath, domain_name ); } else { new_cookie = (char *)ap_psprintf(r->pool, "%s=%s; path=%s", cookiename, enc_cookiebuf, cookiepath); } /* add cookie in response, take care not to kill other set-cookie headers */ if ((sendoutcookie = (char *)ap_table_get(r->headers_out, "Set-Cookie"))) { ap_table_addn(r->headers_out, "Set-Cookie", new_cookie); ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: Adding Set-cookie = %s", new_cookie); ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: Old cookie header = %s", sendoutcookie); } else { ap_table_setn(r->headers_out, "Set-Cookie", new_cookie); ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: Send Set-cookie = %s", new_cookie); } if ( send_domain != 0 ) { /* get cookie extra_domain_name from configuration */ if( (crec->auth_cache_send_extra_domain_name) && (crec->auth_cache_send_extra_domain_name != "")) { new_cookie = (char *) ap_psprintf(r->pool, "%s=; path=%s; domain=%s;", cookie_extraname, cookiepath, crec->auth_cache_send_extra_domain_name ); ap_table_addn(r->headers_out, "Set-Cookie", new_cookie); ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: Adding drop timeout cookie = %s", new_cookie); } } return OK; } /***********************************************************/ /* check a single cookie value */ static int check_cookie(request_rec *r, long timeout, unsigned int send_domain, char *domain_name, char *cookiename, char *cookieStart, char *cookiepath, char **cookieende ) { char *pathend; int res; char *enc_cookiebuf; char *cookieend; char *username; char *remote_ip; char *authorization; char *timestamp; char *cookiebuf; const char *sendoutcookie; int l; time_t t, cur_t; ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: found cookie = %s, checking it", cookieStart); enc_cookiebuf = (char *)ap_pstrdup(r->pool, cookieStart); // find end cookieend = strchr(enc_cookiebuf, ';'); if (cookieend) *cookieend = '\0'; *cookieende = cookieStart + strlen(enc_cookiebuf) + 1; cookiebuf = (char *) ap_palloc(r->pool, 1 + ap_base64decode_len(enc_cookiebuf)); /* base64 decode cookie value */ l = ap_base64decode(cookiebuf, enc_cookiebuf); cookiebuf[l] = '\0'; username = strrchr(cookiebuf, ':'); #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: check username= %s ", username); #endif if (username==NULL) return FALSE; /* no username in cookie ? -> return FALSE */ else *username = '\0'; username++; authorization = strrchr(cookiebuf, ':'); #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: check authorization= %s ", authorization); #endif if (authorization==NULL) return FALSE; /* no authorization in cookie ? -> return FALSE */ else *authorization = '\0'; authorization++; remote_ip = strrchr(cookiebuf, ':'); #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: check remote_ip= %s ", remote_ip); #endif if (remote_ip==NULL) return FALSE; /* no remote_ip in cookie ? -> return FALSE */ else *remote_ip = '\0'; remote_ip++; /* check if remote_ip from cookie is the same as real remote_ip ? -> return FALSE */ if (strcasecmp(remote_ip,r->connection->remote_ip)!=0) return FALSE; timestamp = cookiebuf; t=atol(timestamp); cur_t=time(&cur_t); ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO|APLOG_NOERRNO, 0, r, "mod_auth_cache: check timestamp= %s against %d", timestamp, cur_t); if ((t > cur_t + MOD_AUTHCACHE_TIME_RELAX ) || ( (timeout > 0 ) && ( t + timeout < cur_t + MOD_AUTHCACHE_TIME_RELAX))) { /* Drop cookie because it timed out */ char *new_cookie; ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO|APLOG_NOERRNO, 0, r, "mod_auth_cache: wrong timestamp, cur_time=%d, old_t=%d", cur_t, t ); /* construct the whole cookie */ if ( send_domain != 0 ) { new_cookie = (char *)ap_psprintf(r->pool, "%s=; path=%s; domain=%s; expires=Thu, 01-Jan-1970 00:00:00 GMT", cookiename, cookiepath, domain_name ); } else { new_cookie = (char *)ap_psprintf(r->pool, "%s=; path=%s; domain=%s; expires=Thu, 01-Jan-1970 00:00:00 GMT", cookiename, cookiepath); } /* add cookie in response, take care not to kill other set-cookie headers */ if ((sendoutcookie = (char *)ap_table_get(r->headers_out, "Set-Cookie"))) { ap_table_addn(r->headers_out, "Set-Cookie", new_cookie); ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: Adding drop timeout cookie = %s", new_cookie); ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: Old cookie header = %s", sendoutcookie); } else { ap_table_setn(r->headers_out, "Set-Cookie", new_cookie); ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: Set drop timeout cookie = %s", new_cookie); } return FALSE; } if (cookiebuf==NULL||strstr(cookiebuf,"(null)")||strlen(cookiebuf)==0) { return FALSE; } else { /* restore authorization header from cookie value */ if (strlen(authorization)>0) { #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: restore authorization = %s", authorization); #endif ap_table_setn(r->headers_in,"Authorization",authorization); } /* set remote user from cookie value */ R_USER = (char *)ap_pstrdup(r->connection->pool, username); /* set authorization type from cookie value */ R_AUTH_TYPE = (char *)ap_pstrdup(r->connection->pool, (char *)ap_auth_type(r)); ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: set remote_user= %s", R_USER); return TRUE; /* cookie authorization was successfull*/ } return FALSE; } /* read cookie from request */ static int read_cookie( request_rec *r, long timeout, unsigned int send_domain, unsigned int port, char *domain_name, char *cookiepath, char *cookie_start_name ) { char cookiename[1024]; char *cookieStart; char *value, *valueEnd; char *pathend; const char *cookie; int res; ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: read_cookie/start. timeout=%d, send_domain=%d ", timeout, send_domain); /* init memory. */ memset(cookiename, 0, sizeof(*cookiename)); // port = r->connection->server->port; #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: makeing cookiename from %s:%d-%s:%s ", cookie_start_name, port, ap_auth_type(r), ap_auth_name(r)); #endif ap_snprintf(cookiename, sizeof(cookiename), "Apache-AuthCache-%s:%d-%s:%s", cookie_start_name, port, ap_auth_type(r), ap_auth_name(r)); #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: searching headers for coookies"); #endif if ((cookie = (char *)ap_table_get(r->headers_in, "Cookie"))) { #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: read cookie = %s, searching for %s", cookie, cookiename); #endif cookieStart = (char *)cookie; while ( cookieStart ) { if ((value = strstr(cookieStart, cookiename ))) { int l; #ifdef MOD_AUTHCACHE_DEBUG ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: begin found cookie = %s, now searching for ;", value); #endif value += strlen(cookiename) + 1; // now call the check l = check_cookie(r, timeout, send_domain, domain_name, cookiename, value, cookiepath, &valueEnd ); if ( l == TRUE ) { return l; } cookieStart = valueEnd; } else { ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: wrong cookie=%s, searching for=%s value=%s", cookie, cookiename, value ); return FALSE; } } return FALSE; } else { ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: no cookie header found"); } return FALSE; } /* authentication procedure */ static int auth_cache_validate(request_rec *r) { long timeout; unsigned int send_domain; char domain_name[1024] = ""; char cookiepath[1024] = ""; char cookie_start_name[1024] = ""; const char *authorization; unsigned int port; auth_cache_config_rec *crec = (auth_cache_config_rec *) ap_get_module_config(r->per_dir_config, &auth_cache_module); /* are we activated ? */ if (!crec->auth_cache_on) return DECLINED; if ((authorization = (char *)ap_table_get(r->headers_in, "Authorization"))) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, "mod_auth_cache: auth_cache_validate/passing authorization=%s", authorization); return DECLINED; } /* init memory. */ memset(cookie_start_name, 0, sizeof(*cookie_start_name)); memset(cookiepath, 0, sizeof(*cookiepath)); memset(domain_name, 0, sizeof(*domain_name)); /* analyse our config and prepare all information */ analyse_config( r, crec, &timeout, &send_domain, &port, domain_name,cookiepath,cookie_start_name ); /* if cookie is not OK, someone else should do the work of authentication */ if (!read_cookie(r,timeout, send_domain, port, domain_name,cookiepath,cookie_start_name )) { return DECLINED; } /* if cookie OK, we had done all the work -> return OK */ return OK; } #if MODULE_MAGIC_COOKIE == 0x41503230UL /* Apache 2.0.x */ /* Setup hooks */ static void register_hooks(apr_pool_t *p) { ap_hook_check_user_id(auth_cache_validate, NULL, NULL, APR_HOOK_FIRST); ap_hook_fixups(auth_cache_set_cookie, NULL, NULL, APR_HOOK_MIDDLE); } /***********************************************************/ /* Dispatch list for API hooks */ module AP_MODULE_DECLARE_DATA auth_cache_module = { STANDARD20_MODULE_STUFF, create_auth_cache_dir_config, /* per-directory config creator */ NULL, /* merge per-dir config structures */ NULL, /* server config creator */ NULL, /* server config merger */ auth_cache_cmds, /* table of config file commands */ register_hooks /* register hooks */ }; #else /* Apache 1.3.x */ /***********************************************************/ /* Dispatch list for API hooks */ module MODULE_VAR_EXPORT auth_cache_module = { STANDARD_MODULE_STUFF, NULL, /* module initializer */ create_auth_cache_dir_config, /* create per-dir config structures */ NULL, /* merge per-dir config structures */ NULL, /* create per-server config structures */ NULL, /* merge per-server config structures */ auth_cache_cmds, /* table of config file commands */ NULL, /* [#8] MIME-typed-dispatched handlers */ NULL, /* [#1] URI to filename translation */ auth_cache_validate, /* [#4] validate user id from request */ NULL, /* [#5] check if the user is ok _here_ */ NULL, /* [#3] check access by host address */ NULL, /* [#6] determine MIME type */ auth_cache_set_cookie, /* [#7] pre-run fixups */ NULL, /* [#9] log a transaction */ NULL, /* [#2] header parser */ NULL, /* child_init */ NULL, /* child_exit */ NULL /* [#0] post read-request */ #ifdef EAPI ,NULL, /* EAPI: add_module */ NULL, /* EAPI: remove_module */ NULL, /* EAPI: rewrite_command */ NULL /* EAPI: new_connection */ #endif }; #endif