mod_authmemcookie_v1.0.2/0000755000000000000000000000000011032534367014155 5ustar rootrootmod_authmemcookie_v1.0.2/docs/0000755000000000000000000000000011032534367015105 5ustar rootrootmod_authmemcookie_v1.0.2/docs/readme_files/0000755000000000000000000000000011032534367017524 5ustar rootrootmod_authmemcookie_v1.0.2/docs/readme_files/memcached.css0000644000000000000000000000441710402671212022141 0ustar rootroot/* Generated by CaScadeS, a stylesheet editor for Mozilla Composer */ body { border: 5px solid rgb(112, 112, 208); margin: 0pt; padding: 30px; background: white none repeat scroll 0%; font-family: sans-serif; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; } a { color: rgb(80, 80, 208); } h1 { color: rgb(112, 112, 208); letter-spacing: 0.2em; text-align: center; width: auto; font-size: 20pt; margin-bottom: 0pt; } h2 { border-bottom: 2px dotted blue; margin: 1em 0pt 0.5em -0.7em; background: rgb(224, 224, 255) none repeat scroll 0%; font-size: 13pt; font-style: italic; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; } h3 { border-bottom: 2px dotted blue; margin: 1em 0pt 0.5em 0em; font-size: 10pt; font-style: italic; background-image: none; background-repeat: repeat; background-attachment: scroll; background-position: 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; } p { margin-top: 0pt; } div.linkbar { width: auto; text-align: center; } div.pagetitle { width: auto; text-align: center; font-weight: bold; font-size: 17pt; margin-bottom: 10px; margin-top: 10px; } pre.example { background: rgb(224, 224, 224) none repeat scroll 0%; margin-left: 40px; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; } div.exampletitle { background: rgb(208, 208, 240) none repeat scroll 0%; font-family: sans-serif; font-weight: bold; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; margin-bottom: 0pt; } ul.spaced li { margin-top: 0.7em; } a.barlink:active { background: yellow none repeat scroll 0%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; } div.footer { margin: 30px -30px -30px; padding: 5px; font-size: smaller; font-style: italic; } tt.mem { color: rgb(0, 0, 48); } mod_authmemcookie_v1.0.2/docs/readme.htm0000644000000000000000000002551510763605474017074 0ustar rootroot memcached: a distributed memory object caching system

Auth MemCookie

What is "Auth MemCookie"?

"Auth MemCookie" are an Apache v2 authentification and authorization modules are based on "cookie" authentification mecanism.

The module don't  make authentification by it self, but verify if authentification "the cookie" are valid for each url protected by the module. The module validate also if the "authentificated user" have authorisation to acces url.

Authentification are made externaly by an authentification form page and all authentification information nessary to the module a stored in memcached indentified by the cookie value "authentification session id" by this login page.

How it Works

Phase 1 : The login Form

Authentification are made by a login formular page.

This login page must authenticate the user with any authenticate source (ldap, /etc/password, file, database....) accessible to langage of the page (php, perl, java... an ldap login page sample in php are in samples directory).

Then must set cookie that contain only a key the "authentification unique id" of the "authentification session".

The login page must store authorisation and user information of the authenticated user in memcached identified by the cookie key "authentification unique id".

The login page can be developted in any langage you want, but must be capable to use memcached (they must have memcache client api for us)

Phase 2 : The Apache v2 Module

After the user are logged, the apache 2 module check on each protected page by apache ACL the presence of the "cookie".

if the "cookie" exist, try to get session in memcached with the "cookie" value if not found return "HTTP_UNAUTHORIZED" page.

if session exist in memcached verify if acl match user session information if not match return "HTTP_FORBIDDEN" page. 

Session format stored in memcached


The session store in memcached are composed with multiple line in forme of "name" egual "value" ended by "\r\n". some are mandatory, other are obtional and the reste are information only (all this field are transmited to the script langage protect the module).

Session format :
UserName=<user name>\r\n
Groups=<groupe name1>:<group name2>:...\r\n
RemoteIP=<remote ip>\r\n
Password=<password>\r\n
Expiration=<expiration time>\r\n
Email=<email>\r\n
Name=<name>\r\n
GivenName=<given name>\r\n

The session fields size are for the moment limited to 10 fields by default.

Build dependency

You must have compiled and installed :

Compilation

You must modify Makefile:
How to compile:
#make
#make install
After that the "mod_auth_memcookie.so" are genereted in apache "modules" directory.

How to configure Apache Module

Module configuration option:

This option can be used in "location" or "directory" apache context.
Liste of ip or host adresse(s) and port ':' separed of memcache(s) daemon to be used, coma separed.
For exemple:
host1:12000,host2:12000
Session object stored in memcached expiry time, in secondes.
Used only if "Auth_memCookie_Memcached_SessionObject_ExpiryReset" is set to on.
Set to 3600 seconds by default.
Set to 'no' to not reset object expiry time in memcache on each url... set to yes by default
Max number of element in session information table. set to 10 by default.
Set to 'yes' to set session information to http header of the authenticated users, set to no by default.
Set to 'yes' to mime64 encode session information to http header, set to no by default.
Name of the cookie to used for check authentification, set to "AuthMemCookie" by default.
Set to '0' to not check IP address set in cookie with the remote browser ip, set to '0' by default.
To check cookie ip adresse, Set to '1' to use 'X-Forwarded-For' http header, to '2' to use 'Via' http header, and to '3' to use apache remote_ip.
Set to 'no' to allow access control to be passed along to lower modules, for group acl check. set to 'yes' by default.
Set to 'yes' to allow access control to be passed along to lower modules.Set to 'no' by default.
Set to 'no' to not fix http header and auth_type for simulating auth basic for scripting language like php auth framework work (set PHP_AUTH_* $SERVER variable in php and apache REMOTE_USER and AUTH_TYPE vars)., set to 'yes' by default

Sample to configure Apache v2 Module:

Configuration sample for using Auth_memcookie apache V2 module:

LoadModule mod_auth_memcookie_module modules/mod_auth_memcookie.so

<IfModule mod_auth_memcookie.c>
<Location />
Auth_memCookie_CookieName myauthcookie
Auth_memCookie_Memcached_AddrPort 127.0.0.1:11000

# to redirect unauthorized user to the login page
ErrorDocument 401 "/gestionuser/login.php"

# to specify if the module are autoritative in this directory
Auth_memCookie_Authoritative on
# must be set without that the refuse authentification
AuthType Cookie
# must be set (apache mandatory) but not used by the module
AuthName "My Login"
</Location>

</IfModule>

# to protect juste user authentification
<Location "/myprotectedurl">
require valid-user
</Location>

# to protect acces to user in group1
<Location "/myprotectedurlgroup1">
require group group1
</Location>

mod_authmemcookie_v1.0.2/Makefile0000644000000000000000000000103310635567350015620 0ustar rootrootMY_APXS=/usr/sbin/apxs2 MY_LDFLAGS=-lmemcache -L/mnt/distributions/rpmbuilds/ste-1.0/ste-php/TMP/SFR-libmemcache-1.4.0.rc2-build/product/sfr-suse-addon/lib MY_CFLAGS=-I/mnt/distributions/rpmbuilds/ste-1.0/ste-php/TMP/SFR-libmemcache-1.4.0.rc2-build/product/sfr-suse-addon/include .SUFFIXES: .c .o .la .c.la: $(MY_APXS) $(MY_LDFLAGS) $(MY_CFLAGS) -c $< all: mod_auth_memcookie.la install: mod_auth_memcookie.la @echo "-"$*"-" "-"$?"-" "-"$%"-" "-"$@"-" "-"$<"-" $(MY_APXS) -i $? clean: -rm -f *.o *.lo *.la *.slo -rm -rf .libs mod_authmemcookie_v1.0.2/mod_auth_memcookie.c0000644000000000000000000006543010763603636020167 0ustar rootroot/* Copyright 1999-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * mod_auth_memcookie_module: memcached cookies authentication * * Autor: Mathieu CARBONNEAUX * */ #include #include #define APR_WANT_STRFUNC #include "apr_want.h" #include "apr_strings.h" #include "apr_uuid.h" #include "apr_md5.h" /* for apr_password_validate */ #include "apr_tables.h" #include "httpd.h" #include "http_config.h" #include "http_core.h" #include "http_log.h" #include "http_protocol.h" #include "http_request.h" /* for ap_hook_(check_user_id | auth_checker)*/ #include "apr_base64.h" #include "memcache.h" #define ERRTAG "Auth_memCookie: " #define VERSION "1.0.2" #define unless(c) if(!(c)) /* apache module name */ module AP_MODULE_DECLARE_DATA mod_auth_memcookie_module; /* config structure */ typedef struct { char * szAuth_memCookie_memCached_addr; apr_time_t tAuth_memCookie_MemcacheObjectExpiry; int nAuth_memCookie_MemcacheObjectExpiryReset; int nAuth_memCookie_SetSessionHTTPHeader; int nAuth_memCookie_SetSessionHTTPHeaderEncode; int nAuth_memCookie_SessionTableSize; char * szAuth_memCookie_CookieName; int nAuth_memCookie_GroupAuthoritative; int nAuth_memCookie_Authoritative; int nAuth_memCookie_MatchIP_Mode; int nAuth_memCookie_authbasicfix; } strAuth_memCookie_config_rec; /* Look through 'Cookie' header for indicated cookie; extract it * and URL-unescape it. Return the cookie on success, NULL on failure. */ static char * extract_cookie(request_rec *r, const char *szCookie_name) { char *szRaw_cookie_start=NULL, *szRaw_cookie_end; char *szCookie; /* get cookie string */ char*szRaw_cookie = (char*)apr_table_get( r->headers_in, "Cookie"); unless(szRaw_cookie) return 0; /* loop to search cookie name in cookie header */ do { /* search cookie name in cookie string */ unless (szRaw_cookie =strstr(szRaw_cookie, szCookie_name)) return 0; szRaw_cookie_start=szRaw_cookie; /* search '=' */ unless (szRaw_cookie = strchr(szRaw_cookie, '=')) return 0; } while (strncmp(szCookie_name,szRaw_cookie_start,szRaw_cookie-szRaw_cookie_start)!=0); /* skip '=' */ szRaw_cookie++; /* search end of cookie name value: ';' or end of cookie strings */ unless ((szRaw_cookie_end = strchr(szRaw_cookie, ';')) || (szRaw_cookie_end = strchr(szRaw_cookie, '\0'))) return 0; /* dup the value string found in apache pool and set the result pool ptr to szCookie ptr */ unless (szCookie = apr_pstrndup(r->pool, szRaw_cookie, szRaw_cookie_end-szRaw_cookie)) return 0; /* unescape the value string */ unless (ap_unescape_url(szCookie) == 0) return 0; return szCookie; } /* function to fix any headers in the input request that may be relied on by an application. e.g. php uses the Authorization header when logging the request in apache and not r->user (like it ought to). It is applied after the request has been authenticated. */ static void fix_headers_in(request_rec *r,char*szPassword) { char *szUser=NULL; /* Set an Authorization header in the input request table for php and other applications that use it to obtain the username (mainly to fix apache logging of php scripts). We only set this if there is no header already present. */ if (apr_table_get(r->headers_in,"Authorization")==NULL) { ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, ERRTAG "fixing apache Authorization header for this request using user:%s",r->user); /* concat username and ':' */ if (szPassword!=NULL) szUser=(char*)apr_pstrcat(r->pool,r->user,":",szPassword,NULL); else szUser=(char*)apr_pstrcat(r->pool,r->user,":",NULL); /* alloc memory for the estimated encode size of the username */ char *szB64_enc_user=(char*)apr_palloc(r->pool,apr_base64_encode_len(strlen(szUser))+1); unless (szB64_enc_user) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ERRTAG "memory alloc failed!"); return; } /* encode username in base64 format */ apr_base64_encode(szB64_enc_user,szUser,strlen(szUser)); /* set authorization header */ apr_table_set(r->headers_in,"Authorization", (char*)apr_pstrcat(r->pool,"Basic ",szB64_enc_user,NULL)); /* force auth type to basic */ r->ap_auth_type=apr_pstrdup(r->pool,"Basic"); } return; } /* get session with szCookieValue key from memcached server */ static apr_table_t *Auth_memCookie_get_session(request_rec *r, strAuth_memCookie_config_rec *conf, char *szCookieValue) { char *szMemcached_addr=conf->szAuth_memCookie_memCached_addr; apr_time_t tExpireTime=conf->tAuth_memCookie_MemcacheObjectExpiry; struct memcache *mc_session=NULL; apr_table_t *pMySession=NULL; size_t nGetKeyLen=strlen(szCookieValue); size_t nGetLen=0; char *szServer; char *szTokenPos; char *szFieldTokenPos; char *szField; char *szValue; char *szFieldName; char *szFieldValue; char *szMyValue; char *szSeparator=", \t"; int mc_err=0; int nbInfo=0; /* init memcache lib */ unless(mc_session=mc_new()) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ERRTAG "memcache lib init failed"); return NULL; } unless(pMySession=apr_table_make(r->pool,conf->nAuth_memCookie_SessionTableSize)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, ERRTAG "apr_tablemake failed"); return NULL; } /* add memcached servers from szMemcached_addr who contain host:port server adresse/port separed with coma */ szTokenPos=NULL; for(szServer= strtok_r(szMemcached_addr, szSeparator, &szTokenPos) ; szServer!=NULL; szServer=strtok_r(NULL," \t",&szTokenPos)) { if ((mc_err=mc_server_add4(mc_session,( mc_const char *) szServer))!=0) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ERRTAG "mc_server_add4 failed to add server: '%s' errcode=%d",szServer,mc_err); return NULL; } } /* get value for the key 'szCookieValue' in memcached server */ unless(szValue=(char*)mc_aget2(mc_session,szCookieValue,nGetKeyLen,&nGetLen)) { ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "mc_aget2 failed to found key '%s'",szCookieValue); return NULL; } /* dup szValue in pool */ szMyValue=apr_pstrdup(r->pool,szValue); /* split szValue into struct strAuthSession */ /* szValue is formated multi line (\r\n) with name=value on each line */ /* must containe UserName,Groups,RemoteIP fieldname */ szTokenPos=NULL; for(szField=strtok_r(szMyValue,"\r\n",&szTokenPos);szField;szField=strtok_r(NULL,"\r\n",&szTokenPos)) { szFieldTokenPos=NULL; ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "session field:%s",szField); szFieldName=strtok_r(szField,"=",&szFieldTokenPos); szFieldValue=strtok_r(NULL,"=",&szFieldTokenPos); if (szFieldName!=NULL&&szFieldValue!=NULL) { /* add key and value in pMySession table */ apr_table_set(pMySession,szFieldName,szFieldValue); ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "session information %s=%s",szFieldName,szFieldValue); /* count the number of element added to table to check table size not reached */ nbInfo++; if (nbInfo>conf->nAuth_memCookie_SessionTableSize) { ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO, 0,r,ERRTAG "maximum session information reached!"); return NULL; } } } if (!apr_table_get(pMySession,"UserName")) { ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO, 0,r,ERRTAG "Username not found in Session value(key:%s) found = %s",szCookieValue,szValue); pMySession=NULL; } else if (conf->nAuth_memCookie_MatchIP_Mode!=0&&!apr_table_get(pMySession,"RemoteIP")) { ap_log_rerror(APLOG_MARK,APLOG_ERR|APLOG_NOERRNO, 0,r,ERRTAG "MatchIP_Mode activated and RemoteIP not found in Session value(key:%s) found = %s",szCookieValue,szValue); pMySession=NULL; } else { ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "Value for Session (key:%s) found => Username=%s Groups=%s RemoteIp=%s", szCookieValue, apr_table_get(pMySession,"UserName"), apr_table_get(pMySession,"Groups"), apr_table_get(pMySession,"RemoteIP")); } /* reset expire time */ if (conf->nAuth_memCookie_MemcacheObjectExpiryReset&&pMySession) { if ((mc_err=mc_set(mc_session,szCookieValue,nGetKeyLen,szValue,nGetLen,tExpireTime,0))) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,ERRTAG "Expire time with mc_set (key:%s) failed with errcode=%d",szCookieValue,mc_err); pMySession=NULL; } } /* free aget2 retruned valued */ if (!szValue) free(szValue); /* free the mc session */ mc_free(mc_session); /* set the good username found in request structure */ if (pMySession!=NULL&&apr_table_get(pMySession,"UserName")!=NULL) r->user=(char*)apr_table_get(pMySession,"UserName"); return pMySession; } /* check if szGroup are in szGroups. */ static int get_Auth_memCookie_grp(request_rec *r, char *szGroup, char *szGroups) { char *szGrp_End; char *szGrp_Pos; char *szMyGroups; /* make a copy */ szMyGroups=apr_pstrdup(r->pool,szGroups); /* search group in groups */ unless(szGrp_Pos=strstr(szMyGroups,szGroup)) { return DECLINED; } /* search the next ':' and set '\0' in place of ':' */ if ((szGrp_End=strchr(szGrp_Pos,':'))) szGrp_End[0]='\0'; /* compar szGroup with szGrp_Pos if ok return ok */ if(strcmp(szGroup,szGrp_Pos)) return DECLINED; ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, ERRTAG "group found=%s",szGrp_Pos); return OK; } /* user apr_table_do to set session information in child environment variable */ static int Auth_memCookie_DoSetEnv(void*rec,const char *szKey, const char *szValue) { request_rec *r=(request_rec*)rec; char*szEnvName=apr_pstrcat(r->pool,"MCAC_",szKey,NULL); /* set env var MCAC_USER to the user session value */ apr_table_setn(r->subprocess_env,szEnvName,szValue); return 1; } /* user apr_table_do to set session information in header http */ static int Auth_memCookie_DoSetHeader(void*rec,const char *szKey, const char *szValue) { strAuth_memCookie_config_rec *conf=NULL; request_rec *r=(request_rec*)rec; char *szHeaderName=apr_pstrcat(r->pool,"X-MCAC_",szKey,NULL); /* get apache config */ conf = ap_get_module_config(r->per_dir_config, &mod_auth_memcookie_module); if (conf->nAuth_memCookie_SetSessionHTTPHeaderEncode) { /* alloc memory for the estimated encode size of the string */ char *szB64_enc_string=(char*)apr_palloc(r->pool,apr_base64_encode_len(strlen(szValue))+1); unless (szB64_enc_string) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ERRTAG "memory alloc for encoding http header failed!"); return 0; } /* encode string in base64 format */ apr_base64_encode(szB64_enc_string,szValue,strlen(szValue)); /* set string header */ apr_table_set(r->headers_in,szHeaderName, (char*)szB64_enc_string); } else { /* set string header */ apr_table_set(r->headers_in,szHeaderName, (char*)szValue); } return 1; } /************************************************** * authentification phase: * verify if cookie is set and if is know in memcache server **************************************************/ static int Auth_memCookie_check_cookie(request_rec *r) { strAuth_memCookie_config_rec *conf=NULL; char *szCookieValue=NULL; apr_table_t *pAuthSession=NULL; apr_status_t tRetStatus; char *szRemoteIP=NULL; ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "ap_hook_check_user_id in"); /* get apache config */ conf = ap_get_module_config(r->per_dir_config, &mod_auth_memcookie_module); ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "check MatchIP_Mode:%d",conf->nAuth_memCookie_MatchIP_Mode); /* set remote ip in case of conf->nAuth_memCookie_MatchIP_Mode value */ if (conf->nAuth_memCookie_MatchIP_Mode==2&&apr_table_get(r->headers_in,"Via")!=NULL) szRemoteIP=apr_pstrdup(r->pool,apr_table_get(r->headers_in,"Via")); else if (conf->nAuth_memCookie_MatchIP_Mode==1&&apr_table_get(r->headers_in,"X-Forwarded-For")!=NULL) szRemoteIP=apr_pstrdup(r->pool,apr_table_get(r->headers_in,"X-Forwarded-For")); else szRemoteIP=apr_pstrdup(r->pool,r->connection->remote_ip); unless(conf->nAuth_memCookie_Authoritative) return DECLINED; ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "AuthType are '%s'", ap_auth_type(r)); unless(strncmp("Cookie",ap_auth_type(r),6)==0) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ERRTAG "Auth type not specified has 'Cookie'"); return HTTP_UNAUTHORIZED; } unless(conf->szAuth_memCookie_CookieName) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ERRTAG "No Auth_memCookie_CookieName specified"); return HTTP_UNAUTHORIZED; } unless(conf->szAuth_memCookie_memCached_addr) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ERRTAG "No Auth_memCookie_Memcached_AddrPort specified"); return HTTP_UNAUTHORIZED; } ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "Memcached server(s) adresse(s) are %s",conf->szAuth_memCookie_memCached_addr); /* get cookie who are named szAuth_memCookie_CookieName */ unless(szCookieValue = extract_cookie(r, conf->szAuth_memCookie_CookieName)) { ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r, ERRTAG "cookie not found! not authorized! RemoteIP:%s",szRemoteIP); return HTTP_UNAUTHORIZED; } ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "got cookie; value is %s", szCookieValue); /* check cookie vs session in memcache */ if((pAuthSession = Auth_memCookie_get_session(r, conf, szCookieValue))==NULL) { ap_log_rerror(APLOG_MARK, APLOG_WARNING|APLOG_NOERRNO, 0, r, ERRTAG "AuthSession %s not found: %s", szCookieValue, r->filename); return HTTP_UNAUTHORIZED; } /* push session returned structure in request pool */ if ((tRetStatus=apr_pool_userdata_setn(pAuthSession,"SESSION",NULL,r->pool))) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ERRTAG "apr_pool_userdata_setn Apr Error: %d", tRetStatus); return HTTP_UNAUTHORIZED; } /* check remote ip if option is enabled */ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, ERRTAG "check ip: remote_ip=%s cookie_ip=%s", szRemoteIP ,apr_table_get(pAuthSession,"RemoteIP")); if (conf->nAuth_memCookie_MatchIP_Mode!=0) { if (strcmp(szRemoteIP ,apr_table_get(pAuthSession,"RemoteIP"))) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r, ERRTAG "unauthorized, by ip. user:%s remote_ip:%s != cookie_ip:%s", apr_table_get(pAuthSession,"UserName"),szRemoteIP ,apr_table_get(pAuthSession,"RemoteIP")); return HTTP_UNAUTHORIZED; } } /* set env var MCAC_ to the information session value */ apr_table_do(Auth_memCookie_DoSetEnv,r,pAuthSession,NULL); /* set REMOTE_USER var for scripts language */ apr_table_setn(r->subprocess_env,"REMOTE_USER",apr_table_get(pAuthSession,"UserName")); /* set MCAC-SESSIONKEY var for scripts language */ apr_table_setn(r->subprocess_env,"MCAC_SESSIONKEY",szCookieValue); /* set in http header the session value */ if (conf->nAuth_memCookie_SetSessionHTTPHeader) apr_table_do(Auth_memCookie_DoSetHeader,r,pAuthSession,NULL); /* log authorisation ok */ ap_log_rerror(APLOG_MARK, APLOG_DEBUG|APLOG_NOERRNO, 0, r, ERRTAG "authentication ok"); /* fix http header for php */ if (conf->nAuth_memCookie_authbasicfix) fix_headers_in(r,(char*)apr_table_get(pAuthSession,"Password")); /* if all is ok return auth ok */ return OK; } /************************************************** * authentification phase: * Checking authoriszation for user and group of the authenticated cookie **************************************************/ static int Auth_memCookie_check_auth(request_rec *r) { strAuth_memCookie_config_rec *conf=NULL; char *szMyUser=r->user; char *szUser; int m = r->method_number; const apr_array_header_t *reqs_arr=NULL; require_line *reqs=NULL; register int x; const char *szRequireLine; char *szRequire_cmd; char *szGroup; char *szGroups; apr_table_t *pAuthSession=NULL; apr_status_t tRetStatus; ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "ap_hook_auth_checker in"); /* get apache config */ conf = ap_get_module_config(r->per_dir_config, &mod_auth_memcookie_module); /* check if module are authoritative */ unless(conf->nAuth_memCookie_Authoritative) return DECLINED; /* check if module are authoritative in group check */ unless(conf->nAuth_memCookie_GroupAuthoritative) return DECLINED; if((tRetStatus=apr_pool_userdata_get((void**)&pAuthSession,"SESSION",r->pool))) { ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r,ERRTAG "apr_pool_userdata_get Apr Error: %d", tRetStatus); return HTTP_FORBIDDEN; } /* get require line */ reqs_arr = ap_requires(r); reqs = reqs_arr ? (require_line *) reqs_arr->elts : NULL; /* decline if no require line found */ if (!reqs_arr) return DECLINED; /* walk throug the array to check eatch require command */ for (x = 0; x < reqs_arr->nelts; x++) { if (!(reqs[x].method_mask & (AP_METHOD_BIT << m))) continue; /* get require line */ szRequireLine = reqs[x].requirement; ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "Require Line is '%s'", szRequireLine); /* get the first word in require line */ szRequire_cmd = ap_getword_white(r->pool, &szRequireLine); ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "Require Cmd is '%s'", szRequire_cmd); /* if require cmd are valid-user, they are already authenticated than allow and return OK */ if (!strcmp("valid-user",szRequire_cmd)) { ap_log_rerror(APLOG_MARK,APLOG_DEBUG|APLOG_NOERRNO, 0,r,ERRTAG "Require Cmd valid-user"); return OK; } /* check the required user */ else if (!strcmp("user",szRequire_cmd)) { szUser = ap_getword_conf(r->pool, &szRequireLine); if (strcmp(szMyUser, szUser)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r ,ERRTAG "the user logged '%s' are not the user required '%s'",szMyUser,szUser); return HTTP_FORBIDDEN; } ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r ,ERRTAG "the user logged '%s' is authorized",szMyUser); return OK; } else if (!strcmp("group",szRequire_cmd)) { szGroups=(char*)apr_table_get(pAuthSession,"Groups"); szGroup = ap_getword_white(r->pool, &szRequireLine); ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r ,ERRTAG "check group '%s' in '%s'",szGroup,szGroups); if (szGroups==NULL) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r ,ERRTAG "user %s not in group", szMyUser); return HTTP_FORBIDDEN; } if (get_Auth_memCookie_grp(r, szGroup, szGroups)!=OK) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r ,ERRTAG "user %s not in right group", szMyUser); return HTTP_FORBIDDEN; } ap_log_rerror(APLOG_MARK, APLOG_INFO|APLOG_NOERRNO, 0, r ,ERRTAG "the user logged '%s' as the good group %s and is authorized",szMyUser,szGroup); return OK; } } ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, r ,ERRTAG "the user logged '%s' not authorized",szMyUser); /* forbid by default */ return HTTP_FORBIDDEN; } /************************************************** * register module hook **************************************************/ static void register_hooks(apr_pool_t *p) { ap_hook_check_user_id(Auth_memCookie_check_cookie, NULL, NULL, APR_HOOK_FIRST); ap_hook_auth_checker(Auth_memCookie_check_auth, NULL, NULL, APR_HOOK_FIRST); } /************************************************************************************ * Apache CONFIG Phase: ************************************************************************************/ static void *create_Auth_memCookie_dir_config(apr_pool_t *p, char *d) { strAuth_memCookie_config_rec *conf = apr_palloc(p, sizeof(*conf)); conf->szAuth_memCookie_memCached_addr = apr_pstrdup(p,"127.0.0.1:11211"); conf->szAuth_memCookie_CookieName = apr_pstrdup(p,"AuthMemCookie"); conf->tAuth_memCookie_MemcacheObjectExpiry = 3600; /* memcache object expire time, 1H by default */ conf->nAuth_memCookie_MemcacheObjectExpiryReset = 1; /* fortress is secure by default, reset object expire time in memcache by default */ conf->nAuth_memCookie_MatchIP_Mode = 0; /* method used in matchip, use (0) remote ip by default, if set to 1 for use ip from x_forwarded_for http header and 2 for use Via http header */ conf->nAuth_memCookie_GroupAuthoritative = 1; /* group are handled by this module by default */ conf->nAuth_memCookie_Authoritative = 0; /* not by default */ conf->nAuth_memCookie_authbasicfix = 1; /* fix header for php auth by default */ conf->nAuth_memCookie_SetSessionHTTPHeader = 0; /* set session information in http header of authenticated user */ conf->nAuth_memCookie_SetSessionHTTPHeaderEncode = 1; /* encode http header groups value by default */ conf->nAuth_memCookie_SessionTableSize=10; /* Max number of element in session information table, 10 by default */ return conf; } static const char *cmd_MatchIP_Mode(cmd_parms *cmd, void *InDirConf, const char *p1) { strAuth_memCookie_config_rec *conf=(strAuth_memCookie_config_rec*)InDirConf; if ((strcasecmp("1",p1)==0) || (strcasecmp("X-Forwarded-For",p1)==0)) { conf->nAuth_memCookie_MatchIP_Mode=1; } else if ((strcasecmp("2",p1)==0) || (strcasecmp("Via",p1)==0)) { conf->nAuth_memCookie_MatchIP_Mode=2; } else if ((strcasecmp("3",p1)==0) || (strcasecmp("RemoteIP",p1)==0)) { conf->nAuth_memCookie_MatchIP_Mode=3; } else { conf->nAuth_memCookie_MatchIP_Mode=0; } return NULL; } /* apache config fonction of the module */ static const command_rec Auth_memCookie_cmds[] = { AP_INIT_TAKE1("Auth_memCookie_Memcached_AddrPort", ap_set_string_slot, (void *)APR_OFFSETOF(strAuth_memCookie_config_rec, szAuth_memCookie_memCached_addr), OR_AUTHCFG, "ip or host adressei(s) and port (':' separed) of memcache(s) daemon to be used, coma separed"), AP_INIT_TAKE1("Auth_memCookie_Memcached_SessionObject_ExpireTime", ap_set_int_slot, (void *)APR_OFFSETOF(strAuth_memCookie_config_rec, tAuth_memCookie_MemcacheObjectExpiry), OR_AUTHCFG, "Session object in memcached expiry time, in secondes."), AP_INIT_TAKE1("Auth_memCookie_SessionTableSize", ap_set_int_slot, (void *)APR_OFFSETOF(strAuth_memCookie_config_rec, nAuth_memCookie_SessionTableSize), OR_AUTHCFG, "Max number of element in session information table. 10 by default"), AP_INIT_FLAG ("Auth_memCookie_Memcached_SessionObject_ExpiryReset", ap_set_flag_slot, (void *)APR_OFFSETOF(strAuth_memCookie_config_rec, nAuth_memCookie_MemcacheObjectExpiryReset), OR_AUTHCFG, "Set to 'no' to not reset object expiry time in memcache... yes by default"), AP_INIT_FLAG ("Auth_memCookie_SetSessionHTTPHeader", ap_set_flag_slot, (void *)APR_OFFSETOF(strAuth_memCookie_config_rec, nAuth_memCookie_SetSessionHTTPHeader), OR_AUTHCFG, "Set to 'yes' to set session information to http header of the authenticated users, no by default"), AP_INIT_FLAG ("Auth_memCookie_SetSessionHTTPHeaderEncode", ap_set_flag_slot, (void *)APR_OFFSETOF(strAuth_memCookie_config_rec, nAuth_memCookie_SetSessionHTTPHeaderEncode), OR_AUTHCFG, "Set to 'yes' to mime64 encode session information to http header, no by default"), AP_INIT_TAKE1("Auth_memCookie_CookieName", ap_set_string_slot, (void *)APR_OFFSETOF(strAuth_memCookie_config_rec, szAuth_memCookie_CookieName), OR_AUTHCFG, "Name of cookie to set"), AP_INIT_TAKE1 ( "Auth_memCookie_MatchIP_Mode", cmd_MatchIP_Mode, NULL, OR_AUTHCFG, "To check cookie ip adresse, Set to '1' to use 'X-Forwarded-For' http header, to '2' to use 'Via' http header, and to '3' to use apache remote_ip. set to '0' by default to desactivate the ip check."), AP_INIT_FLAG ("Auth_memCookie_GroupAuthoritative", ap_set_flag_slot, (void *)APR_OFFSETOF(strAuth_memCookie_config_rec, nAuth_memCookie_GroupAuthoritative), OR_AUTHCFG, "Set to 'no' to allow access control to be passed along to lower modules, for group acl check, set to 'yes' by default."), AP_INIT_FLAG ("Auth_memCookie_Authoritative", ap_set_flag_slot, (void *)APR_OFFSETOF(strAuth_memCookie_config_rec, nAuth_memCookie_Authoritative), OR_AUTHCFG, "Set to 'yes' to allow access control to be passed along to lower modules, set to 'no' by default"), AP_INIT_FLAG ("Auth_memCookie_SilmulateAuthBasic", ap_set_flag_slot, (void *)APR_OFFSETOF(strAuth_memCookie_config_rec, nAuth_memCookie_authbasicfix), OR_AUTHCFG, "Set to 'no' to fix http header and auth_type for simulating auth basic for scripting language like php auth framework work, set to 'yes' by default"), {NULL} }; /* apache module structure */ module AP_MODULE_DECLARE_DATA mod_auth_memcookie_module = { STANDARD20_MODULE_STUFF, create_Auth_memCookie_dir_config, /* dir config creater */ NULL, /* dir merger --- default is to override */ NULL, /* server config */ NULL, /* merge server config */ Auth_memCookie_cmds, /* command apr_table_t */ register_hooks /* register hooks */ }; mod_authmemcookie_v1.0.2/samples/0000755000000000000000000000000011032534367015621 5ustar rootrootmod_authmemcookie_v1.0.2/samples/login.php0000644000000000000000000000316310402563354017443 0ustar rootroot page de login

 

 

Authentification de l'intranet

 

Identifiant :
Mot de passe :
">

 

mod_authmemcookie_v1.0.2/samples/login_post.php0000644000000000000000000001301610763606024020510 0ustar rootroot Erreur d'authentiufication...

 

 

 

 

 

Utilisateur ou mot de passe incorrect!

Cliquer sur précédant et veuillez recommencer...

connect('localhost', 11000) or die ("Could not connect"); // generate cookie uniq session id $key=md5(uniqid(rand(), true).$_SERVER["REMOTE_ADDR"].time()); // contruct session value to be stored in memcached for the cookie session id. $value="UserName=".$my_user."\r\n"; $value.="Groups=".$my_groups."\r\n"; $value.="RemoteIP=".$my_remoteip."\r\n"; $value.="Expiration=".$my_expiretime."\r\n"; if ($my_send_pass_flag!=FALSE) $value.="Password=".$my_password."\r\n"; $value.="Email=".$my_mail."\r\n"; $value.="Name=".$my_nom."\r\n"; $value.="GivenName=".$my_prenom."\r\n"; // store value for the key in memcache deamon $memcache->set($key,$value,false,$my_expiretime); // set cookie session if ($my_expiretime!=0) setcookie($my_cookie_name,$key,time()+$my_expiretime,$my_path,$my_domain,$my_secure); else setcookie($my_cookie_name,$key,$my_expiretime,$my_path,$my_domain,$my_secure); // redirect to referer page.... header("Location: ".$my_referer); exit; } ?> mod_authmemcookie_v1.0.2/samples/httpd.conf0000644000000000000000000000131510402667500017607 0ustar rootroot# Configuration example for using auth_memcookie module LoadModule mod_auth_memcookie_module modules/mod_auth_memcookie.so Auth_memCookie_CookieName myauthcookie Auth_memCookie_Memcached_AddrPort 127.0.0.1:11000 # to fix header for php buggy authentification mecanism Auth_memCookie_SilmulateAuthBasic on # to redirect unauthorized user to the login page ErrorDocument 401 "/gestionuser/login.php" Auth_memCookie_Authoritative on AuthType Cookie AuthName "Login Intranet DT" require valid-user require group group1 mod_authmemcookie_v1.0.2/ChangeLog0000644000000000000000000000063110763602650015730 0ustar rootroot2007 mcarbonneaux * mod_authmemcookie/1.0 - initial release 2007 mcarbonneaux * mod_authmemcookie/1.01 - bug fix in cookie name. 2008-02-05 mcarbonneaux * mod_authmemcookie/1.02 * bug fix of Auth_memCookie_SessionTableSize to 8 any time... * complete rewrite of match ip option to make possible to use it behind reverse proxy and to check x-forwarded or via http header in place of apache remote_ip.