From 8247953a322d542966ac58d40a06f262963c0465 Mon Sep 17 00:00:00 2001 From: Dietmar Berg Date: Mon, 6 Apr 2015 08:06:14 +0200 Subject: [PATCH 1/6] Minimum modifs to make it run on Apache 2.4 (Ubuntu LTS 14) --- configure | 11 +- src/mod_auth_tkt.c | 515 ++++++++++++++++++++++----------------------- 2 files changed, 265 insertions(+), 261 deletions(-) diff --git a/configure b/configure index 4780599..926c711 100755 --- a/configure +++ b/configure @@ -5,6 +5,7 @@ # Defaults APXS=/usr/sbin/apxs +test -x $APXS || APXS=/usr/bin/apxs2 test -x $APXS || unset APXS ME=`basename $0` @@ -14,7 +15,7 @@ if [ $DIR = '.' ]; then fi usage() { - echo "usage: $ME [--apxs=/path/to/apxs] [--apachever=<1|2|2.2>] [--debug]" + echo "usage: $ME [--apxs=/path/to/apxs] [--apachever=<1|2|2.2|2.4>] [--debug]" } die() { echo $* @@ -62,14 +63,15 @@ test -x $APXS || die "Error: missing apxs '$APXS' (use --apxs=/path/to/apxs)" # Get Apache version if [ -z "$VERSION" ]; then HTTPD=`$APXS -q SBINDIR`/`$APXS -q TARGET` - test -x $HTTPD || die "Error: cannot determine apache version (use --apachever=<1|2|2.2>)" + test -x $HTTPD || die "Error: cannot determine apache version (use --apachever=<1|2|2.2|2.4>)" VERSION=`$HTTPD -v | head -1 | sed -e 's/.*Apache\///' -e 's/^\([0-9]\.[0-9]\+\).*/\1/'` fi # Standardise test $VERSION = '2.0' && VERSION=2 test $VERSION = '20' && VERSION=2 test $VERSION = '22' && VERSION=2.2 -if [ $VERSION != '1' -a $VERSION != '2' -a $VERSION != '2.2' ]; then +test $VERSION = '24' && VERSION=2.4 +if [ $VERSION != '1' -a $VERSION != '2' -a $VERSION != '2.2' -a $VERSION != '2.4' ]; then die "Error: apache version '$VERSION' not supported" fi @@ -92,6 +94,9 @@ else if [ $VERSION = "2.2" ]; then echo "CFLAGS += -DAPACHE22" >> Makedefs fi + if [ $VERSION = "2.4" ]; then + echo "CFLAGS += -DAPACHE24" >> Makedefs + fi echo "TARGET = mod_auth_tkt.la" >> Makedefs fi echo "BASEDIR = $DIR" >> Makedefs diff --git a/src/mod_auth_tkt.c b/src/mod_auth_tkt.c index 74bb669..6975d52 100644 --- a/src/mod_auth_tkt.c +++ b/src/mod_auth_tkt.c @@ -13,17 +13,26 @@ #ifdef APACHE13 #include "ap_compat.h" #else +/* Apache 2.x */ #define UUID_SUBS 2 #include "apr_lib.h" #include "apr_strings.h" #include "apr_uuid.h" #include "apr_base64.h" -#ifndef APACHE22 +#ifdef APACHE20 #include "pcreposix.h" -#else +#endif +#ifdef APACHE22 #include "ap22_compat.h" #include "ap_regex.h" #endif +#ifdef APACHE24 +#include "ap22_compat.h" +#include "ap_regex.h" +#include "http_request.h" +#include "ap_provider.h" +#include "mod_auth.h" +#endif #endif #define AUTH_COOKIE_NAME "auth_tkt" @@ -38,12 +47,11 @@ #define REMOTE_USER_TOKENS_ENV "REMOTE_USER_TOKENS" #define DEFAULT_TIMEOUT_SEC 7200 #define DEFAULT_GUEST_USER "guest" -#define QUERY_SEPARATOR ';' #define FORCE_REFRESH 1 #define CHECK_REFRESH 0 -#define TKT_AUTH_VERSION "2.1.0" +#define TKT_AUTH_VERSION "2.2.0" /* ----------------------------------------------------------------------- */ /* Per-directory configuration */ @@ -69,7 +77,6 @@ typedef struct { char *guest_user; int guest_fallback; int debug; - const char *query_separator; } auth_tkt_dir_conf; /* Per-server configuration */ @@ -101,24 +108,24 @@ void auth_tkt_version(server_rec *s, pool *p) { ap_add_version_component("mod_auth_tkt/" TKT_AUTH_VERSION); - ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s, + ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s, "mod_auth_tkt: version %s", TKT_AUTH_VERSION); } #else static int -auth_tkt_version(apr_pool_t *p, +auth_tkt_version(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { ap_add_version_component(p, "mod_auth_tkt/" TKT_AUTH_VERSION); - ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s, + ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s, "mod_auth_tkt: version %s", TKT_AUTH_VERSION); return DECLINED; } #endif /* Create per-dir config structures */ -static void * +static void * create_auth_tkt_config(apr_pool_t *p, char* path) { auth_tkt_dir_conf *conf = apr_palloc(p, sizeof(*conf)); @@ -144,12 +151,11 @@ create_auth_tkt_config(apr_pool_t *p, char* path) conf->guest_user = NULL; conf->guest_fallback = -1; conf->debug = -1; - conf->query_separator = (char *)QUERY_SEPARATOR; - return conf; + return conf; } /* Merge per-dir config structures */ -static void * +static void * merge_auth_tkt_config(apr_pool_t *p, void* parent_dirv, void* subdirv) { auth_tkt_dir_conf *parent = (auth_tkt_dir_conf *) parent_dirv; @@ -177,7 +183,6 @@ merge_auth_tkt_config(apr_pool_t *p, void* parent_dirv, void* subdirv) conf->guest_user = (subdir->guest_user) ? subdir->guest_user : parent->guest_user; conf->guest_fallback = (subdir->guest_fallback >= 0) ? subdir->guest_fallback : parent->guest_fallback; conf->debug = (subdir->debug >= 0) ? subdir->debug : parent->debug; - conf->query_separator = (subdir->query_separator) ? subdir->query_separator : parent->query_separator; return conf; } @@ -192,7 +197,7 @@ create_auth_tkt_serv_config(apr_pool_t *p, server_rec* s) sconf->digest_type = NULL; sconf->digest_sz = 0; return sconf; -} +} /* Merge per-server config structures */ static void * @@ -207,7 +212,7 @@ merge_auth_tkt_serv_config(apr_pool_t *p, void* parent_dirv, void* subdirv) sconf->digest_type = (subdir->digest_type) ? subdir->digest_type : parent->digest_type; sconf->digest_sz = (subdir->digest_sz) ? subdir->digest_sz : parent->digest_sz; return sconf; -} +} /* ----------------------------------------------------------------------- */ /* Command-specific functions */ @@ -247,8 +252,8 @@ convert_to_seconds (cmd_parms *cmd, const char *param, int *seconds) multiplier = 30 * 24 * 60 * 60; else if (unit == 'y') multiplier = 365 * 24 * 60 * 60; - else - return apr_psprintf(cmd->pool, + else + return apr_psprintf(cmd->pool, "Bad time string - unrecognised unit '%c'", unit); } @@ -260,7 +265,7 @@ convert_to_seconds (cmd_parms *cmd, const char *param, int *seconds) static const char * set_auth_tkt_token (cmd_parms *cmd, void *cfg, const char *param) { - char **new; + char **new; auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *) cfg; new = (char **) apr_array_push(conf->auth_token); @@ -274,12 +279,12 @@ set_auth_tkt_timeout (cmd_parms *cmd, void *cfg, const char *param) auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *)cfg; int seconds = conf->timeout_sec; const char *error; - + /* Easy case - looks like all digits */ if (apr_isdigit(param[0]) && apr_isdigit(param[strlen(param) - 1])) { seconds = atoi(param); } - + /* Harder case - convert units to seconds */ else { error = convert_to_seconds(cmd, param, &seconds); @@ -290,7 +295,7 @@ set_auth_tkt_timeout (cmd_parms *cmd, void *cfg, const char *param) if (seconds == INT_MAX) return ("Integer overflow or invalid number"); conf->timeout_sec = seconds; - + return NULL; } @@ -298,14 +303,14 @@ static const char * set_auth_tkt_timeout_min (cmd_parms *cmd, void *cfg, const char *param) { auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *)cfg; - + int minutes = atoi(param); - + if (minutes < 0) return ("Timeout must be positive"); if (minutes == INT_MAX) return ("Integer overflow or invalid number"); - + conf->timeout_sec = minutes * 60; - + return NULL; } @@ -313,21 +318,21 @@ static const char * set_auth_tkt_timeout_refresh (cmd_parms *cmd, void *cfg, const char *param) { auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *)cfg; - + double refresh = atof(param); - if (refresh < 0 || refresh > 1) + if (refresh < 0 || refresh > 1) return "Refresh flag must be between 0 and 1"; - + conf->timeout_refresh = refresh; - + return NULL; } static const char * setup_secret (cmd_parms *cmd, void *cfg, const char *param) { - auth_tkt_serv_conf *sconf = + auth_tkt_serv_conf *sconf = ap_get_module_config(cmd->server->module_config, &auth_tkt_module); sconf->secret = param; return NULL; @@ -336,22 +341,12 @@ setup_secret (cmd_parms *cmd, void *cfg, const char *param) static const char * setup_old_secret (cmd_parms *cmd, void *cfg, const char *param) { - auth_tkt_serv_conf *sconf = ap_get_module_config(cmd->server->module_config, + auth_tkt_serv_conf *sconf = ap_get_module_config(cmd->server->module_config, &auth_tkt_module); sconf->old_secret = param; return NULL; } -static const char * -setup_query_separator (cmd_parms *cmd, void *cfg, const char *param) -{ - if (strcmp(param, ";") != 0 && strcmp(param, "&") != 0) - return "QuerySeparator must be either ';' or '&'."; - auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *)cfg; - conf->query_separator = param; - return NULL; -} - void setup_digest_sz (auth_tkt_serv_conf *sconf) { @@ -369,10 +364,10 @@ setup_digest_sz (auth_tkt_serv_conf *sconf) static const char * setup_digest_type (cmd_parms *cmd, void *cfg, const char *param) { - auth_tkt_serv_conf *sconf = + auth_tkt_serv_conf *sconf = ap_get_module_config(cmd->server->module_config, &auth_tkt_module); - if (strcmp(param, "MD5") != 0 && + if (strcmp(param, "MD5") != 0 && strcmp(param, "SHA256") != 0 && strcmp(param, "SHA512") != 0) return "Digest type must be one of: MD5 | SHA256 | SHA512."; @@ -405,7 +400,7 @@ set_cookie_expires (cmd_parms *cmd, void *cfg, const char *param) if (seconds == INT_MAX) return ("Integer overflow or invalid number"); conf->cookie_expires = seconds; - + return NULL; } @@ -413,93 +408,90 @@ static const char * set_auth_tkt_debug (cmd_parms *cmd, void *cfg, const char *param) { auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *)cfg; - + int debug = atoi(param); - + if (debug < 0) return ("Debug level must be positive"); if (debug == INT_MAX) return ("Integer overflow or invalid number"); - + conf->debug = debug; - + return NULL; } /* Command table */ static const command_rec auth_tkt_cmds[] = { - AP_INIT_TAKE1("TKTAuthLoginURL", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthLoginURL", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, login_url), OR_AUTHCFG, "URL to redirect to if authentication fails"), - AP_INIT_TAKE1("TKTAuthTimeoutURL", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthTimeoutURL", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, timeout_url), OR_AUTHCFG, "URL to redirect to if cookie times-out"), - AP_INIT_TAKE1("TKTAuthPostTimeoutURL", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthPostTimeoutURL", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, post_timeout_url), OR_AUTHCFG, "URL to redirect to if cookie times-out doing a POST"), - AP_INIT_TAKE1("TKTAuthUnauthURL", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthUnauthURL", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, unauth_url), OR_AUTHCFG, "URL to redirect to if valid user without required token"), - AP_INIT_TAKE1("TKTAuthCookieName", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthCookieName", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, auth_cookie_name), OR_AUTHCFG, "name to use for ticket cookie"), - AP_INIT_TAKE1("TKTAuthDomain", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthDomain", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, auth_domain), OR_AUTHCFG, "domain to use in cookies"), #ifndef APACHE13 /* TKTAuthCookieExpires is not supported under Apache 1.3 */ - AP_INIT_ITERATE("TKTAuthCookieExpires", set_cookie_expires, + AP_INIT_ITERATE("TKTAuthCookieExpires", set_cookie_expires, (void *)APR_OFFSETOF(auth_tkt_dir_conf, cookie_expires), OR_AUTHCFG, "cookie expiry period, in seconds or units [smhdwMy]"), #endif - AP_INIT_TAKE1("TKTAuthBackCookieName", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthBackCookieName", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, back_cookie_name), - OR_AUTHCFG, "name to use for back cookie (default: none)"), - AP_INIT_TAKE1("TKTAuthBackArgName", ap_set_string_slot, + OR_AUTHCFG, "name to use for back cookie (NULL for none)"), + AP_INIT_TAKE1("TKTAuthBackArgName", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, back_arg_name), - OR_AUTHCFG, "name to use for back url argument ('None' to not use)"), - AP_INIT_FLAG("TKTAuthIgnoreIP", ap_set_flag_slot, + OR_AUTHCFG, "name to use for back url argument (NULL for none)"), + AP_INIT_FLAG("TKTAuthIgnoreIP", ap_set_flag_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, ignore_ip), OR_AUTHCFG, "whether to ignore remote IP address in ticket"), - AP_INIT_FLAG("TKTAuthRequireSSL", ap_set_flag_slot, + AP_INIT_FLAG("TKTAuthRequireSSL", ap_set_flag_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, require_ssl), OR_AUTHCFG, "whether to refuse non-HTTPS requests"), - AP_INIT_FLAG("TKTAuthCookieSecure", ap_set_flag_slot, + AP_INIT_FLAG("TKTAuthCookieSecure", ap_set_flag_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, secure_cookie), OR_AUTHCFG, "whether to set secure flag on ticket cookies"), - AP_INIT_ITERATE("TKTAuthToken", set_auth_tkt_token, + AP_INIT_ITERATE("TKTAuthToken", set_auth_tkt_token, (void *)APR_OFFSETOF(auth_tkt_dir_conf, auth_token), OR_AUTHCFG, "token required to access this area (NULL for none)"), - AP_INIT_ITERATE("TKTAuthTimeout", set_auth_tkt_timeout, + AP_INIT_ITERATE("TKTAuthTimeout", set_auth_tkt_timeout, (void *)APR_OFFSETOF(auth_tkt_dir_conf, timeout_sec), OR_AUTHCFG, "ticket inactivity timeout, in seconds or units [smhdwMy]"), - AP_INIT_TAKE1("TKTAuthTimeoutMin", set_auth_tkt_timeout_min, + AP_INIT_TAKE1("TKTAuthTimeoutMin", set_auth_tkt_timeout_min, NULL, OR_AUTHCFG, "ticket inactivity timeout, in minutes (deprecated)"), - AP_INIT_TAKE1("TKTAuthTimeoutRefresh", set_auth_tkt_timeout_refresh, + AP_INIT_TAKE1("TKTAuthTimeoutRefresh", set_auth_tkt_timeout_refresh, NULL, OR_AUTHCFG, "ticket timeout refresh flag (0-1)"), - AP_INIT_TAKE1("TKTAuthSecret", setup_secret, + AP_INIT_TAKE1("TKTAuthSecret", setup_secret, NULL, RSRC_CONF, "secret key to use in digest"), - AP_INIT_TAKE1("TKTAuthSecretOld", setup_old_secret, + AP_INIT_TAKE1("TKTAuthSecretOld", setup_old_secret, NULL, RSRC_CONF, "old/alternative secret key to check in digests"), - AP_INIT_TAKE1("TKTAuthDigestType", setup_digest_type, - NULL, RSRC_CONF, "digest type to use [MD5|SHA256|SHA512], default: MD5"), + AP_INIT_TAKE1("TKTAuthDigestType", setup_digest_type, + NULL, RSRC_CONF, "digest type to use [MD5|SHA256|SHA512], default MD5"), AP_INIT_FLAG("TKTAuthGuestLogin", ap_set_flag_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, guest_login), OR_AUTHCFG, "whether to log people in as guest if no other auth available"), AP_INIT_FLAG("TKTAuthGuestCookie", ap_set_flag_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, guest_cookie), - OR_AUTHCFG, "whether to set a cookie when accepting guest users (default: off)"), - AP_INIT_TAKE1("TKTAuthGuestUser", ap_set_string_slot, + OR_AUTHCFG, "whether to set a cookie when accepting guest users (default off)"), + AP_INIT_TAKE1("TKTAuthGuestUser", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, guest_user), OR_AUTHCFG, "username to use for guest logins"), AP_INIT_FLAG("TKTAuthGuestFallback", ap_set_flag_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, guest_fallback), - OR_AUTHCFG, "whether to fall back to guest on an expired ticket (default: off)"), - AP_INIT_ITERATE("TKTAuthDebug", set_auth_tkt_debug, + OR_AUTHCFG, "whether to fall back to guest on an expired ticket (default off)"), + AP_INIT_ITERATE("TKTAuthDebug", set_auth_tkt_debug, (void *)APR_OFFSETOF(auth_tkt_dir_conf, debug), OR_AUTHCFG, "debug level (1-3, higher for more debug output)"), - AP_INIT_TAKE1("TKTAuthQuerySeparator", setup_query_separator, - (void *)APR_OFFSETOF(auth_tkt_dir_conf, query_separator), - OR_AUTHCFG, "Character used in query strings to separate arguments (default: ';')"), {NULL}, }; @@ -507,28 +499,28 @@ static const command_rec auth_tkt_cmds[] = /* Support functions */ /* Parse cookie. Returns 1 if valid, and details in *parsed; 0 if not */ -static int +static int parse_ticket(request_rec *r, char **magic, auth_tkt *parsed) { int sepidx, sep2idx; char *ticket = *magic; int len = strlen(ticket); - auth_tkt_serv_conf *sconf = + auth_tkt_serv_conf *sconf = ap_get_module_config(r->server->module_config, &auth_tkt_module); - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); - + /* For some reason (some clients?), tickets sometimes come in quoted */ if (ticket[len-1] == '"') ticket[len-1] = 0; if (ticket[0] == '"') *magic = ++ticket; /* Basic length check for min size */ if (len <= (sconf->digest_sz + TSTAMP_SZ)) - return 0; - + return 0; + /* See if there is a uid/data separator */ sepidx = ap_ind(ticket, SEPARATOR); - if (sepidx == -1) { + if (sepidx == -1) { /* Ticket either uri-escaped, base64-escaped, or bogus */ if (strstr(ticket, SEPARATOR_HEX)) { ap_unescape_url(ticket); @@ -536,7 +528,7 @@ parse_ticket(request_rec *r, char **magic, auth_tkt *parsed) } else { /* base64 encoded string always longer than original, so len+1 sufficient */ - char *buf = (char *) apr_palloc(r->pool, len+1); + char *buf = (char *) apr_palloc(r->pool, len+1); apr_base64_decode(buf, ticket); sepidx = ap_ind(buf, SEPARATOR); /* If still no sepidx, must be bogus */ @@ -549,26 +541,26 @@ parse_ticket(request_rec *r, char **magic, auth_tkt *parsed) } /* Recheck length */ - if (len <= (sconf->digest_sz + TSTAMP_SZ) || - sepidx < (sconf->digest_sz + TSTAMP_SZ)) - return 0; + if (len <= (sconf->digest_sz + TSTAMP_SZ) || + sepidx < (sconf->digest_sz + TSTAMP_SZ)) + return 0; if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT parse_ticket decoded ticket: '%s'", ticket); } - + /* Get the user id */ parsed->uid = apr_palloc(r->pool, sepidx - (sconf->digest_sz + TSTAMP_SZ) + 1); - memcpy(parsed->uid, &ticket[(sconf->digest_sz + TSTAMP_SZ)], + memcpy(parsed->uid, &ticket[(sconf->digest_sz + TSTAMP_SZ)], sepidx - (sconf->digest_sz + TSTAMP_SZ)); parsed->uid[sepidx - (sconf->digest_sz + TSTAMP_SZ)] = '\0'; - + /* Check for tokens */ sep2idx = ap_ind(&ticket[sepidx+1], SEPARATOR); if (sep2idx == -1) { if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT parse_ticket: no tokens"); } parsed->tokens = apr_palloc(r->pool, 1); @@ -580,15 +572,15 @@ parse_ticket(request_rec *r, char **magic, auth_tkt *parsed) sepidx = tmp + sep2idx + 1; sep2idx = tmp; if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, - "TKT parse_ticket: tokens found - sep2=%d, sep=%d, len=%d", - sep2idx, sepidx, len); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + "TKT parse_ticket: tokens found - sep2=%d, sep=%d, len=%d", + sep2idx, sepidx, len); } /* Copy tokens to parsed->tokens */ parsed->tokens = apr_palloc(r->pool, sepidx-sep2idx); apr_snprintf(parsed->tokens, sepidx-sep2idx, "%s", &ticket[sep2idx+1]); if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT parse_ticket tokens: '%s'", parsed->tokens); } } @@ -599,22 +591,22 @@ parse_ticket(request_rec *r, char **magic, auth_tkt *parsed) /* Copy timestamp to parsed->timestamp */ sscanf(&ticket[sconf->digest_sz], "%8x", &(parsed->timestamp)); - + return 1; } /* Search cookie headers for our ticket */ -static int +static int cookie_match(void *result, const char *key, const char *cookie) { cookie_res * cr = (cookie_res *) result; - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(cr->r->per_dir_config, &auth_tkt_module); - + if (cookie != NULL) { char *cookie_name, *value, *cookiebuf, *end; if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, cr->r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, cr->r, "TKT cookie_match, key %s against <%s> (name=%s)", key, cookie, cr->cookie_name); } @@ -640,7 +632,7 @@ cookie_match(void *result, const char *key, const char *cookie) if (strlen(cookiebuf)) { cr->cookie = cookiebuf; if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, cr->r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, cr->r, "TKT cookie_match: found '%s'", cookiebuf); } return(0); @@ -648,7 +640,7 @@ cookie_match(void *result, const char *key, const char *cookie) } } if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, cr->r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, cr->r, "TKT cookie_match: NOT found"); } return (1); @@ -656,7 +648,7 @@ cookie_match(void *result, const char *key, const char *cookie) /* Return the domain to use in cookies */ char * -get_domain(request_rec *r, auth_tkt_dir_conf *conf) +get_domain(request_rec *r, auth_tkt_dir_conf *conf) { /* Set the cookie domain to the first set of TKTAuthDomain, X-Forwarded-Host, Host, or server hostname. Viljo Viitanen @@ -682,7 +674,7 @@ get_domain(request_rec *r, auth_tkt_dir_conf *conf) static void send_auth_cookie(request_rec *r, char *value) { - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); char *cookie, *expires; char *domain = get_domain(r,conf); @@ -696,12 +688,12 @@ send_auth_cookie(request_rec *r, char *value) #ifndef APACHE13 if (conf->cookie_expires > 0) { apr_time_exp_t tms; - apr_time_exp_gmt(&tms, r->request_time + + apr_time_exp_gmt(&tms, r->request_time + apr_time_from_sec(conf->cookie_expires)); - expires = + expires = apr_psprintf(r->pool, "; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT", apr_day_snames[tms.tm_wday], - tms.tm_mday, + tms.tm_mday, apr_month_snames[tms.tm_mon], tms.tm_year % 100, tms.tm_hour, tms.tm_min, tms.tm_sec @@ -710,12 +702,12 @@ send_auth_cookie(request_rec *r, char *value) #endif /* Send the cookie */ - cookie = apr_psprintf(r->pool, "%s=%s; path=/%s%s%s", + cookie = apr_psprintf(r->pool, "%s=%s; path=/%s%s%s", conf->auth_cookie_name, value, domain, expires, secure_cookie); apr_table_setn(r->err_headers_out, "Set-Cookie", cookie); if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: sending cookie: %s=%s; path=/%s%s%s", conf->auth_cookie_name, value, domain, expires, secure_cookie); } @@ -725,7 +717,7 @@ send_auth_cookie(request_rec *r, char *value) static char * get_url_ticket(request_rec *r) { - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); const char *args = NULL; /* url arguments string */ const char *key, *val; @@ -734,12 +726,12 @@ get_url_ticket(request_rec *r) /* Use main request args if subrequest */ request_rec *r_main = r->main == NULL ? r : r->main; if (r_main->args != NULL) { - args = apr_pstrdup(r->pool, r_main->args); + args = apr_pstrdup(r->pool, r_main->args); } if (args != NULL) { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: looking for ticket in url: <%s>", args); } @@ -748,12 +740,12 @@ get_url_ticket(request_rec *r) if (strcmp(key,conf->auth_cookie_name) == 0) { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: found url ticket: <%s>", val); } /* Setup auth cookie using ticket value */ - send_auth_cookie(r, (char *) val); + send_auth_cookie(r, (char *) val); /* Found ticket - ignore rest of arguments */ ticket = (char *) val; @@ -766,12 +758,12 @@ get_url_ticket(request_rec *r) } /* Look for a cookie ticket */ -static char * +static char * get_cookie_ticket(request_rec *r) { - auth_tkt_serv_conf *sconf = + auth_tkt_serv_conf *sconf = ap_get_module_config(r->server->module_config, &auth_tkt_module); - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); /* Walk cookie headers looking for matching ticket */ @@ -787,7 +779,7 @@ get_cookie_ticket(request_rec *r) } if (strlen(cr->cookie) < sconf->digest_sz + TSTAMP_SZ) { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT get_cookie_tkt: found cookie ticket, " "but it's too short for a %s digest (%zu < %d)", sconf->digest_type, strlen(cr->cookie), sconf->digest_sz + TSTAMP_SZ); @@ -799,23 +791,27 @@ get_cookie_ticket(request_rec *r) } /* Generate a ticket digest string from the given details */ -static char * +static char * ticket_digest(request_rec *r, auth_tkt *parsed, unsigned int timestamp, const char *secret) { - auth_tkt_serv_conf *sconf = + auth_tkt_serv_conf *sconf = ap_get_module_config(r->server->module_config, &auth_tkt_module); - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); char *uid = parsed->uid; char *tokens = parsed->tokens; char *user_data = parsed->user_data; - unsigned char *buf = apr_palloc(r->pool, + unsigned char *buf = apr_palloc(r->pool, TSTAMP_SZ + strlen(secret) + strlen(uid) + 1 + strlen(tokens) + 1 + strlen(user_data) + 1); unsigned char *buf2 = apr_palloc(r->pool, sconf->digest_sz + strlen(secret)); int len = 0; char *digest = NULL; +#ifndef APACHE24 char *remote_ip = conf->ignore_ip > 0 ? "0.0.0.0" : r->connection->remote_ip; +#else + char *remote_ip = conf->ignore_ip > 0 ? "0.0.0.0" : r->useragent_ip; +#endif unsigned long ip; struct in_addr ia; char *d; @@ -829,7 +825,7 @@ ticket_digest(request_rec *r, auth_tkt *parsed, unsigned int timestamp, const ch if (timestamp == 0) timestamp = parsed->timestamp; if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT ticket_digest: using secret '%s', ip '%s', ts '%d'", secret, remote_ip, timestamp); } @@ -841,13 +837,13 @@ ticket_digest(request_rec *r, auth_tkt *parsed, unsigned int timestamp, const ch buf[0] = (unsigned char ) ((ip & 0xff000000) >> 24); buf[1] = (unsigned char ) ((ip & 0xff0000) >> 16); buf[2] = (unsigned char ) ((ip & 0xff00) >> 8); - buf[3] = (unsigned char ) ((ip & 0xff)); - buf[4] = (unsigned char ) ((timestamp & 0xff000000) >> 24); - buf[5] = (unsigned char ) ((timestamp & 0xff0000) >> 16); - buf[6] = (unsigned char ) ((timestamp & 0xff00) >> 8); - buf[7] = (unsigned char ) ((timestamp & 0xff)); + buf[3] = (unsigned char ) ((ip & 0xff)); + buf[4] = (unsigned char ) ((timestamp & 0xff000000) >> 24); + buf[5] = (unsigned char ) ((timestamp & 0xff0000) >> 16); + buf[6] = (unsigned char ) ((timestamp & 0xff00) >> 8); + buf[7] = (unsigned char ) ((timestamp & 0xff)); len = 8; - + /* Append remaining components to buf */ strcpy((char *)&buf[len], secret); len += strlen(secret); @@ -874,7 +870,7 @@ ticket_digest(request_rec *r, auth_tkt *parsed, unsigned int timestamp, const ch digest = ap_md5_binary(r->pool, buf, len); } if (conf->debug >= 3) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT ticket_digest: digest0: '%s' (input length %d)", digest, len); } @@ -896,7 +892,7 @@ ticket_digest(request_rec *r, auth_tkt *parsed, unsigned int timestamp, const ch digest = ap_md5_binary(r->pool, buf2, len); } if (conf->debug >= 3) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT ticket_digest: digest: '%s'", digest); } @@ -914,21 +910,21 @@ valid_ticket(request_rec *r, const char *source, char *ticket, auth_tkt *parsed, char *digest; auth_tkt_serv_conf *sconf = ap_get_module_config(r->server->module_config, &auth_tkt_module); - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); /* Attempt to parse ticket */ if (! parse_ticket(r, &ticket, parsed)) { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, "TKT valid_ticket: unparseable %s ticket found ('%s')", source, ticket); } return 0; } if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, - "TKT valid_ticket: (parsed) uid '%s', tokens '%s', user_data '%s', ts '%d'", + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + "TKT valid_ticket: (parsed) uid '%s', tokens '%s', user_data '%s', ts '%d'", parsed->uid, parsed->tokens, parsed->user_data, parsed->timestamp); } @@ -938,9 +934,9 @@ valid_ticket(request_rec *r, const char *source, char *ticket, auth_tkt *parsed, /* Digest mismatch - if no old secret set, fail */ if(sconf->old_secret == NULL) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, "TKT valid_ticket: ticket hash (current secret) is invalid, and no old secret set " - "- digest '%s', ticket '%s'", + "- digest '%s', ticket '%s'", digest, ticket); return 0; } @@ -948,13 +944,13 @@ valid_ticket(request_rec *r, const char *source, char *ticket, auth_tkt *parsed, /* Digest mismatch - if old_secret is set, recalculate using that */ else { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT valid_ticket: ticket hash (current secret) is invalid, but old_secret is set - checking ticket digest against that"); } digest = ticket_digest(r, parsed, 0, sconf->old_secret); if (memcmp(ticket, digest, sconf->digest_sz) != 0) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, - "TKT valid_ticket: ticket hash (old secret) is also invalid - digest '%s', ticket '%s'", + ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, + "TKT valid_ticket: ticket hash (old secret) is also invalid - digest '%s', ticket '%s'", digest, ticket); return 0; } @@ -963,7 +959,7 @@ valid_ticket(request_rec *r, const char *source, char *ticket, auth_tkt *parsed, else { if (force_refresh != NULL) { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT valid_ticket: ticket_digest validated with old_secret - forcing a cookie refresh"); } *force_refresh = 1; @@ -975,31 +971,31 @@ valid_ticket(request_rec *r, const char *source, char *ticket, auth_tkt *parsed, return 1; } -/* Check for required auth tokens +/* Check for required auth tokens * Returns 1 on success, 0 on failure */ static int check_tokens(request_rec *r, char *tokens) { - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); char *next_parsed_token; const char *t = NULL; - int match = 0; + int match = 0; /* Success if no tokens required */ - if (conf->auth_token->nelts == 0 || + if (conf->auth_token->nelts == 0 || strcmp(((char **) conf->auth_token->elts)[0], "NULL") == 0) { return 1; } /* Failure if required and no user tokens found */ if (tokens == NULL || strlen(tokens) == 0) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: no matching tokens! (no user tokens found)"); return 0; } - t = apr_pstrdup(r->pool, tokens); - + t = apr_pstrdup(r->pool, tokens); + while (*t && (next_parsed_token = ap_getword(r->pool, &t, ','))) { char ** auth_tokens = (char **) conf->auth_token->elts; int i; @@ -1007,44 +1003,44 @@ check_tokens(request_rec *r, char *tokens) for (i=0; i < conf->auth_token->nelts; i++) { int token_len = strlen(auth_tokens[i]); if (strncmp(auth_tokens[i], next_parsed_token, token_len) == 0 && - next_parsed_token[token_len] == 0) { - match = 1; - break; + next_parsed_token[token_len] == 0) { + match = 1; + break; } } if (match) break; } if (conf->debug >= 1 && ! match) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: no matching tokens! (user tokens '%s')", tokens); } return match; -} +} /* check_tokens() */ /* Refresh the auth cookie if timeout refresh is set */ static void refresh_cookie(request_rec *r, auth_tkt *parsed, int timeout, int force_flag) { - auth_tkt_serv_conf *sconf = + auth_tkt_serv_conf *sconf = ap_get_module_config(r->server->module_config, &auth_tkt_module); - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); /* The timeout refresh is a double between 0 and 1, signifying what - * proportion of the timeout should be left before we refresh i.e. + * proportion of the timeout should be left before we refresh i.e. * 0 means never refresh (hard timeouts); 1 means always refresh; - * .33 means only refresh if less than a third of the timeout - * period remains. */ + * .33 means only refresh if less than a third of the timeout + * period remains. */ unsigned int now = time(NULL); int remainder = parsed->timestamp + timeout - now; double refresh_sec = conf->timeout_refresh * timeout; if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT refresh_cookie: timeout %d, refresh %.3f, remainder %d, refresh_sec %.3f, force_flag %d", - timeout, conf->timeout_refresh, remainder, refresh_sec, force_flag); + timeout, conf->timeout_refresh, remainder, refresh_sec, force_flag); } /* If less than our refresh_sec threshold, freshen the cookie */ @@ -1053,29 +1049,29 @@ refresh_cookie(request_rec *r, auth_tkt *parsed, int timeout, int force_flag) char *digest = ticket_digest(r, parsed, now, sconf->secret); if (parsed->tokens) { ticket = apr_psprintf(r->pool, - "%s%08x%s%c%s%c%s", - digest, now, parsed->uid, - SEPARATOR, parsed->tokens, - SEPARATOR, parsed->user_data); + "%s%08x%s%c%s%c%s", + digest, now, parsed->uid, + SEPARATOR, parsed->tokens, + SEPARATOR, parsed->user_data); } else { ticket = apr_psprintf(r->pool, - "%s%08x%s%c%s", + "%s%08x%s%c%s", digest, now, parsed->uid, SEPARATOR, parsed->user_data); } ticket_base64 = ap_pbase64encode(r->pool, ticket); - send_auth_cookie(r, ticket_base64); + send_auth_cookie(r, ticket_base64); } } - -/* Check whether the given timestamp has timed out + +/* Check whether the given timestamp has timed out * Returns 1 if okay, 0 if timed out */ static int check_timeout(request_rec *r, auth_tkt *parsed) { char *timeout_date, *timeout_cookie; - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); unsigned int now = time(NULL); unsigned int timestamp = parsed->timestamp; @@ -1090,24 +1086,24 @@ check_timeout(request_rec *r, auth_tkt *parsed) /* Check whether timestamp is still fresh */ if (timestamp + timeout >= now) { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, - "TKT: cookie timeout still good: now %d, timeout: %d, tstamp: %d", + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + "TKT: cookie timeout still good: now %d, timeout: %d, tstamp: %d", now, timeout, timestamp); } /* Check whether to refresh the cookie */ - if (conf->timeout_refresh > 0) + if (conf->timeout_refresh > 0) refresh_cookie(r, parsed, timeout, CHECK_REFRESH); return 1; } if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, - "TKT: ticket timed out: now %d, timeout: %d, tstamp: %d", + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + "TKT: ticket timed out: now %d, timeout: %d, tstamp: %d", now, timeout, timestamp); } - + /* Delete cookie (set expired) if invalid, in case we want to set from url */ timeout_date = ap_ht_time(r->pool, now - 3600, "%a %d %b %Y %T %Z", 0); timeout_cookie = domain ? @@ -1123,7 +1119,7 @@ check_timeout(request_rec *r, auth_tkt *parsed) } /* Strip specified query args from a url */ -static char * +static char * query_strip(request_rec *r, const char *strip) { const char *args = NULL; /* url arguments string */ @@ -1133,10 +1129,10 @@ query_strip(request_rec *r, const char *strip) /* Use main request args if subrequest */ request_rec *r_main = r->main == NULL ? r : r->main; - if (r_main->args == NULL || strip == NULL) + if (r_main->args == NULL || strip == NULL) return NULL; - args = apr_pstrdup(r->pool, r_main->args); + args = apr_pstrdup(r->pool, r_main->args); /* Convert all '&' to ';' */ while ((p = ap_strchr(args, '&'))) @@ -1147,7 +1143,7 @@ query_strip(request_rec *r, const char *strip) key = ap_getword(r->pool, &val, '='); /* Add to new_args only if key != strip */ - if (strlen(strip) != strlen(key) || strncmp(key,strip,strlen(strip)) != 0) + if (strlen(strip) != strlen(key) || strncmp(key,strip,strlen(strip)) != 0) new_args = apr_psprintf(r->pool, "%s&%s=%s", new_args, key, val); } @@ -1172,14 +1168,14 @@ c2x(unsigned what, unsigned char *where) } /* Extra escaping - variant of httpd util.c ap_escape_path_segment */ -static char * +static char * escape_extras(apr_pool_t *p, const char *segment) { char *copy = apr_palloc(p, 3 * strlen(segment) + 1); const unsigned char *s = (const unsigned char *)segment; unsigned char *d = (unsigned char *)copy; unsigned c; - + while ((c = *s)) { if (c == '=' || c == '&' || c == ':') { d = c2x(c, d); @@ -1194,17 +1190,16 @@ escape_extras(apr_pool_t *p, const char *segment) } /* External redirect to the given url, setting back cookie or arg */ -static int +static int redirect(request_rec *r, char *location) { - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); char *domain = get_domain(r,conf); char *back_cookie_name = conf->back_cookie_name; char *back_arg_name = conf->back_arg_name; - char *url = location; - char *cookie, *back; + char *url, *cookie, *back; const char *hostinfo = 0; int port; @@ -1227,10 +1222,10 @@ redirect(request_rec *r, char *location) if (! hostinfo) hostinfo = apr_table_get(r->headers_in, "Host"); if (! hostinfo) { /* Fallback to using r->hostname and the server port. This usually - works, but behind a reverse proxy the port may well be wrong. + works, but behind a reverse proxy the port may well be wrong. On the other hand, it's really the proxy's problem, not ours. */ - ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, "TKT: could not find Host header, falling back to hostname/server port"); port = ap_get_server_port(r); hostinfo = port == apr_uri_default_port_for_scheme(scheme) ? @@ -1240,22 +1235,22 @@ redirect(request_rec *r, char *location) /* If no scheme, assume location is relative and expand using scheme and hostinfo */ if (strncasecmp(location, "http", 4) != 0) { - char *old_location = apr_pstrdup(r->pool, location); + char *old_location = apr_pstrdup(r->pool, location); location = apr_psprintf(r->pool, "%s://%s/%s", scheme, hostinfo, location); if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT relative URL '%s' expanded to '%s'", old_location, location); } } /* Setup back URL */ - back = apr_psprintf(r->pool, "%s://%s%s%s", + back = apr_psprintf(r->pool, "%s://%s%s%s", scheme, hostinfo, r->uri, query); if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: back url '%s'", back); } - + /* Escape testing */ back = ap_escape_path_segment(r->pool, back); back = escape_extras(r->pool, back); @@ -1263,9 +1258,9 @@ redirect(request_rec *r, char *location) /* Set back cookie if name is not null */ if (back_cookie_name) { cookie = domain ? - apr_psprintf(r->pool, "%s=%s; path=/; domain=%s", + apr_psprintf(r->pool, "%s=%s; path=/; domain=%s", back_cookie_name, back, domain) : - apr_psprintf(r->pool, "%s=%s; path=/", + apr_psprintf(r->pool, "%s=%s; path=/", back_cookie_name, back); apr_table_setn(r->err_headers_out, "Set-Cookie", cookie); @@ -1273,18 +1268,18 @@ redirect(request_rec *r, char *location) } /* If back_cookie_name not set, add a back url argument to url */ - else if (back_arg_name) { - char sep = ap_strchr(location, '?') ? conf->query_separator[0] : '?'; - url = apr_psprintf(r->pool, "%s%c%s=%s", + else { + char sep = ap_strchr(location, '?') ? ';' : '?'; + url = apr_psprintf(r->pool, "%s%c%s=%s", location, sep, back_arg_name, back); } if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: redirect '%s'", url); } apr_table_setn(r->headers_out, "Location", url); - + return HTTP_TEMPORARY_REDIRECT; } @@ -1326,14 +1321,14 @@ get_guest_uid(request_rec *r, auth_tkt_dir_conf *conf) if (regm[1].rm_so != -1) { uuid_length_str = ap_pregsub(r->pool, "$1", guest_user, UUID_SUBS, regm); - if (uuid_length_str) + if (uuid_length_str) uuid_length = atoi(uuid_length_str); } if (uuid_length <= 0 || uuid_length > APR_UUID_FORMATTED_LENGTH) { uuid_length = APR_UUID_FORMATTED_LENGTH; } if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, "TKT: %%U found in guest user (length %d)", uuid_length); } /* Generate the UUID */ @@ -1341,7 +1336,7 @@ get_guest_uid(request_rec *r, auth_tkt_dir_conf *conf) uuid_str = apr_palloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1); apr_uuid_get(uuid); apr_uuid_format(uuid_str, uuid); - if (uuid_length < APR_UUID_FORMATTED_LENGTH) + if (uuid_length < APR_UUID_FORMATTED_LENGTH) uuid_str[uuid_length] = '\0'; /* Generate the new guest_user string */ guest_user_length = strlen(guest_user); @@ -1356,7 +1351,7 @@ get_guest_uid(request_rec *r, auth_tkt_dir_conf *conf) else uuid_post = ""; - return apr_psprintf(r->pool, "%s%s%s", + return apr_psprintf(r->pool, "%s%s%s", uuid_pre, uuid_str, uuid_post); } @@ -1366,7 +1361,7 @@ get_guest_uid(request_rec *r, auth_tkt_dir_conf *conf) } /* Set up the guest user info */ -static int +static int setup_guest(request_rec *r, auth_tkt_dir_conf *conf, auth_tkt *tkt) { /* Only applicable if guest access on */ @@ -1377,8 +1372,8 @@ setup_guest(request_rec *r, auth_tkt_dir_conf *conf, auth_tkt *tkt) tkt->uid = get_guest_uid(r, conf); tkt->user_data = ""; tkt->tokens = ""; - ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, - "TKT: no valid ticket found - accepting as guest user '%s'", + ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, + "TKT: no valid ticket found - accepting as guest user '%s'", tkt->uid); return 1; @@ -1386,37 +1381,39 @@ setup_guest(request_rec *r, auth_tkt_dir_conf *conf, auth_tkt *tkt) /* ----------------------------------------------------------------------- */ /* Debug routines */ -void -dump_config(request_rec *r, auth_tkt_serv_conf *sconf, auth_tkt_dir_conf *conf) +void +dump_config(request_rec *r, auth_tkt_serv_conf *sconf, auth_tkt_dir_conf *conf) { +/* Protect against libc which dies on NULL strings :-( (DiB) */ +#define NN(x) ((x)?(x):"(null)") + /* Dump config settings */ fprintf(stderr,"[ mod_auth_tkt config ]\n"); fprintf(stderr,"URI: %s\n", r->uri); - fprintf(stderr,"Filename: %s\n", r->filename); - fprintf(stderr,"TKTAuthSecret: %s\n", sconf->secret); - fprintf(stderr,"TKTAuthSecretOld: %s\n", sconf->old_secret); - fprintf(stderr,"TKTAuthDigestType: %s\n", sconf->digest_type); - fprintf(stderr,"digest_sz: %d\n", sconf->digest_sz); - fprintf(stderr,"directory: %s\n", conf->directory); - fprintf(stderr,"TKTAuthLoginURL: %s\n", conf->login_url); - fprintf(stderr,"TKTAuthTimeoutURL: %s\n", conf->timeout_url); - fprintf(stderr,"TKTAuthPostTimeoutURL: %s\n", conf->post_timeout_url); - fprintf(stderr,"TKTAuthUnauthURL: %s\n", conf->unauth_url); - fprintf(stderr,"TKTAuthCookieName: %s\n", conf->auth_cookie_name); - fprintf(stderr,"TKTAuthDomain: %s\n", conf->auth_domain); - fprintf(stderr,"TKTAuthCookieExpires: %d\n", conf->cookie_expires); - fprintf(stderr,"TKTAuthBackCookieName: %s\n", conf->back_cookie_name); - fprintf(stderr,"TKTAuthBackArgName: %s\n", conf->back_arg_name); - fprintf(stderr,"TKTAuthIgnoreIP: %d\n", conf->ignore_ip); - fprintf(stderr,"TKTAuthRequireSSL: %d\n", conf->require_ssl); - fprintf(stderr,"TKTAuthCookieSecure: %d\n", conf->secure_cookie); - fprintf(stderr,"TKTAuthTimeoutMin: %d\n", conf->timeout_sec); - fprintf(stderr,"TKTAuthTimeoutRefresh: %f\n", conf->timeout_refresh); - fprintf(stderr,"TKTAuthGuestLogin: %d\n", conf->guest_login); - fprintf(stderr,"TKTAuthGuestCookie: %d\n", conf->guest_cookie); - fprintf(stderr,"TKTAuthGuestUser: %s\n", conf->guest_user); - fprintf(stderr,"TKTAuthGuestFallback %d\n", conf->guest_fallback); - fprintf(stderr,"TKTAuthQuerySeparator: %c\n", conf->query_separator); + fprintf(stderr,"Filename: %s\n", NN(r->filename)); + fprintf(stderr,"TKTAuthSecret: %s\n", NN(sconf->secret)); + fprintf(stderr,"TKTAuthSecretOld: %s\n", NN(sconf->old_secret)); + fprintf(stderr,"TKTAuthDigestType: %s\n", NN(sconf->digest_type)); + fprintf(stderr,"digest_sz: %d\n", sconf->digest_sz); + fprintf(stderr,"directory: %s\n", NN(conf->directory)); + fprintf(stderr,"TKTAuthLoginURL: %s\n", NN(conf->login_url)); + fprintf(stderr,"TKTAuthTimeoutURL: %s\n", NN(conf->timeout_url)); + fprintf(stderr,"TKTAuthPostTimeoutURL: %s\n", NN(conf->post_timeout_url)); + fprintf(stderr,"TKTAuthUnauthURL: %s\n", NN(conf->unauth_url)); + fprintf(stderr,"TKTAuthCookieName: %s\n", NN(conf->auth_cookie_name)); + fprintf(stderr,"TKTAuthDomain: %s\n", NN(conf->auth_domain)); + fprintf(stderr,"TKTAuthCookieExpires: %d\n", conf->cookie_expires); + fprintf(stderr,"TKTAuthBackCookieName: %s\n", NN(conf->back_cookie_name)); + fprintf(stderr,"TKTAuthBackArgName: %s\n", NN(conf->back_arg_name)); + fprintf(stderr,"TKTAuthIgnoreIP: %d\n", conf->ignore_ip); + fprintf(stderr,"TKTAuthRequireSSL: %d\n", conf->require_ssl); + fprintf(stderr,"TKTAuthCookieSecure: %d\n", conf->secure_cookie); + fprintf(stderr,"TKTAuthTimeoutMin: %d\n", conf->timeout_sec); + fprintf(stderr,"TKTAuthTimeoutRefresh: %f\n", conf->timeout_refresh); + fprintf(stderr,"TKTAuthGuestLogin: %d\n", conf->guest_login); + fprintf(stderr,"TKTAuthGuestCookie: %d\n", conf->guest_cookie); + fprintf(stderr,"TKTAuthGuestUser: %s\n", NN(conf->guest_user)); + fprintf(stderr,"TKTAuthGuestFallback %d\n", conf->guest_fallback); if (conf->auth_token->nelts > 0) { char ** auth_token = (char **) conf->auth_token->elts; int i; @@ -1435,7 +1432,7 @@ auth_tkt_check(request_rec *r) { char *ticket; auth_tkt *parsed = apr_palloc(r->pool, sizeof(*parsed)); - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); auth_tkt_serv_conf *sconf = ap_get_module_config(r->server->module_config, &auth_tkt_module); @@ -1451,10 +1448,6 @@ auth_tkt_check(request_rec *r) setup_digest_sz(sconf); } - /* Map "None" back_arg_name to NULL */ - if (conf->back_arg_name && strcmp(conf->back_arg_name, "None") == 0) - conf->back_arg_name = NULL; - /* Dump config if debugging */ if (conf->debug >= 2) dump_config(r, sconf, conf); @@ -1465,21 +1458,21 @@ auth_tkt_check(request_rec *r) } /* Module misconfigured unless secret set */ if (! sconf->secret) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, "TKT: TKTAuthSecret missing"); return HTTP_INTERNAL_SERVER_ERROR; } /* Redirect/login if scheme not "https" and require_ssl is set */ if (conf->require_ssl > 0 && strcmp(scheme,"https") != 0) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, "TKT: redirect/login - unsecured request, TKTAuthRequireSSL is on"); return redirect(r, conf->login_url); } /* Backwards compatibility mode for TKTAuthRequireSSL */ if (conf->require_ssl > 0 && conf->secure_cookie == -1) { - /* Set secure_cookie flag if require_ssl is set and secure_cookie is + /* Set secure_cookie flag if require_ssl is set and secure_cookie is undefined (as opposed to 'off') */ - ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, "TKT: TKTAuthRequireSSL on, but no TKTAuthCookieSecure found - " "please set TKTAuthCookieSecure explicitly, assuming 'on'"); conf->secure_cookie = 1; @@ -1495,13 +1488,13 @@ auth_tkt_check(request_rec *r) } if (! guest) { if (conf->login_url) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, "TKT: no valid ticket found - redirecting to login url"); return redirect(r, conf->login_url); } else { /* Fatal error: guest setup failed, but we have no login url defined */ - ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, "TKT: guest login failed and no login url to fall back to - aborting"); return HTTP_INTERNAL_SERVER_ERROR; } @@ -1528,7 +1521,7 @@ auth_tkt_check(request_rec *r) } else { /* Fatal error: guest setup failed, but we have no url to redirect to */ - ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, "TKT: ticket timeout, guest login failed, and no url to fall back to - aborting"); return HTTP_INTERNAL_SERVER_ERROR; } @@ -1560,7 +1553,7 @@ auth_tkt_check(request_rec *r) apr_table_set(r->subprocess_env, REMOTE_USER_TOKENS_ENV, parsed->tokens); return OK; -} +} /* auth_tkt_check() */ /* ----------------------------------------------------------------------- */ /* Setup main module data structure */ @@ -1569,11 +1562,11 @@ auth_tkt_check(request_rec *r) /* Apache 1.3 style */ module MODULE_VAR_EXPORT auth_tkt_module = { - STANDARD_MODULE_STUFF, + STANDARD_MODULE_STUFF, auth_tkt_version, /* initializer */ - create_auth_tkt_config, /* create per-dir config structures */ - merge_auth_tkt_config, /* merge per-dir config structures */ - create_auth_tkt_serv_config, /* create per-server config structures */ + create_auth_tkt_config, /* create per-dir config structures */ + merge_auth_tkt_config, /* merge per-dir config structures */ + create_auth_tkt_serv_config, /* create per-server config structures */ merge_auth_tkt_serv_config, /* merge per-server config structures */ auth_tkt_cmds, /* table of config file commands */ NULL, /* handlers */ @@ -1598,15 +1591,21 @@ static void auth_tkt_register_hooks (apr_pool_t *p) { ap_hook_post_config(auth_tkt_version, NULL, NULL, APR_HOOK_MIDDLE); +#ifndef APACHE24 ap_hook_check_user_id(auth_tkt_check, NULL, NULL, APR_HOOK_FIRST); +#else + /* http://httpd.apache.org/docs/2.4/developer/new_api_2_4.html */ + /* http://ci.apache.org/projects/httpd/trunk/doxygen/ */ + ap_hook_check_authn(auth_tkt_check, NULL, NULL, APR_HOOK_FIRST, AP_AUTH_INTERNAL_PER_CONF); +#endif } /* Declare and populate the main module data structure */ module AP_MODULE_DECLARE_DATA auth_tkt_module = { - STANDARD20_MODULE_STUFF, - create_auth_tkt_config, /* create per-dir config structures */ - merge_auth_tkt_config, /* merge per-dir config structures */ - create_auth_tkt_serv_config, /* create per-server config structures */ + STANDARD20_MODULE_STUFF, + create_auth_tkt_config, /* create per-dir config structures */ + merge_auth_tkt_config, /* merge per-dir config structures */ + create_auth_tkt_serv_config, /* create per-server config structures */ merge_auth_tkt_serv_config, /* merge per-server config structures */ auth_tkt_cmds, /* table of config file commands */ auth_tkt_register_hooks /* register hooks */ @@ -1614,6 +1613,6 @@ module AP_MODULE_DECLARE_DATA auth_tkt_module = { #endif -/* - * vim:sw=2:sm:et +/* + * vim:sw=2:sm */ From 3591bfb0b4d5bbe13f2c14cdeb1143f3828ea238 Mon Sep 17 00:00:00 2001 From: Dietmar Berg Date: Mon, 6 Apr 2015 11:21:48 +0200 Subject: [PATCH 2/6] Minimum change for Apache 2.4, now based on latest GitHub version --- configure | 3 + src/mod_auth_tkt.c | 490 ++++++++++++++++++++++++--------------------- 2 files changed, 261 insertions(+), 232 deletions(-) mode change 100644 => 100755 src/mod_auth_tkt.c diff --git a/configure b/configure index 926c711..c672ca3 100755 --- a/configure +++ b/configure @@ -91,6 +91,9 @@ if [ "$VERSION" = "1" ]; then echo "CFLAGS += -DAPACHE13" >> Makedefs echo "TARGET = mod_auth_tkt.so" >> Makedefs else + if [ $VERSION = "2" ]; then + echo "CFLAGS += -DAPACHE20" >> Makedefs + fi if [ $VERSION = "2.2" ]; then echo "CFLAGS += -DAPACHE22" >> Makedefs fi diff --git a/src/mod_auth_tkt.c b/src/mod_auth_tkt.c old mode 100644 new mode 100755 index 6975d52..d077b5a --- a/src/mod_auth_tkt.c +++ b/src/mod_auth_tkt.c @@ -12,8 +12,7 @@ #ifdef APACHE13 #include "ap_compat.h" -#else -/* Apache 2.x */ +#else /* Apache 2.x */ #define UUID_SUBS 2 #include "apr_lib.h" #include "apr_strings.h" @@ -47,12 +46,14 @@ #define REMOTE_USER_TOKENS_ENV "REMOTE_USER_TOKENS" #define DEFAULT_TIMEOUT_SEC 7200 #define DEFAULT_GUEST_USER "guest" +#define QUERY_SEPARATOR ";" #define FORCE_REFRESH 1 #define CHECK_REFRESH 0 #define TKT_AUTH_VERSION "2.2.0" + /* ----------------------------------------------------------------------- */ /* Per-directory configuration */ typedef struct { @@ -77,6 +78,7 @@ typedef struct { char *guest_user; int guest_fallback; int debug; + const char *query_separator; } auth_tkt_dir_conf; /* Per-server configuration */ @@ -108,24 +110,24 @@ void auth_tkt_version(server_rec *s, pool *p) { ap_add_version_component("mod_auth_tkt/" TKT_AUTH_VERSION); - ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s, + ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s, "mod_auth_tkt: version %s", TKT_AUTH_VERSION); } #else static int -auth_tkt_version(apr_pool_t *p, +auth_tkt_version(apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s) { ap_add_version_component(p, "mod_auth_tkt/" TKT_AUTH_VERSION); - ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s, + ap_log_error(APLOG_MARK, APLOG_INFO, APR_SUCCESS, s, "mod_auth_tkt: version %s", TKT_AUTH_VERSION); return DECLINED; } #endif /* Create per-dir config structures */ -static void * +static void * create_auth_tkt_config(apr_pool_t *p, char* path) { auth_tkt_dir_conf *conf = apr_palloc(p, sizeof(*conf)); @@ -151,11 +153,12 @@ create_auth_tkt_config(apr_pool_t *p, char* path) conf->guest_user = NULL; conf->guest_fallback = -1; conf->debug = -1; - return conf; + conf->query_separator = QUERY_SEPARATOR; + return conf; } /* Merge per-dir config structures */ -static void * +static void * merge_auth_tkt_config(apr_pool_t *p, void* parent_dirv, void* subdirv) { auth_tkt_dir_conf *parent = (auth_tkt_dir_conf *) parent_dirv; @@ -183,6 +186,7 @@ merge_auth_tkt_config(apr_pool_t *p, void* parent_dirv, void* subdirv) conf->guest_user = (subdir->guest_user) ? subdir->guest_user : parent->guest_user; conf->guest_fallback = (subdir->guest_fallback >= 0) ? subdir->guest_fallback : parent->guest_fallback; conf->debug = (subdir->debug >= 0) ? subdir->debug : parent->debug; + conf->query_separator = (subdir->query_separator) ? subdir->query_separator : parent->query_separator; return conf; } @@ -197,7 +201,7 @@ create_auth_tkt_serv_config(apr_pool_t *p, server_rec* s) sconf->digest_type = NULL; sconf->digest_sz = 0; return sconf; -} +} /* Merge per-server config structures */ static void * @@ -212,7 +216,7 @@ merge_auth_tkt_serv_config(apr_pool_t *p, void* parent_dirv, void* subdirv) sconf->digest_type = (subdir->digest_type) ? subdir->digest_type : parent->digest_type; sconf->digest_sz = (subdir->digest_sz) ? subdir->digest_sz : parent->digest_sz; return sconf; -} +} /* ----------------------------------------------------------------------- */ /* Command-specific functions */ @@ -252,8 +256,8 @@ convert_to_seconds (cmd_parms *cmd, const char *param, int *seconds) multiplier = 30 * 24 * 60 * 60; else if (unit == 'y') multiplier = 365 * 24 * 60 * 60; - else - return apr_psprintf(cmd->pool, + else + return apr_psprintf(cmd->pool, "Bad time string - unrecognised unit '%c'", unit); } @@ -265,7 +269,7 @@ convert_to_seconds (cmd_parms *cmd, const char *param, int *seconds) static const char * set_auth_tkt_token (cmd_parms *cmd, void *cfg, const char *param) { - char **new; + char **new; auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *) cfg; new = (char **) apr_array_push(conf->auth_token); @@ -279,12 +283,12 @@ set_auth_tkt_timeout (cmd_parms *cmd, void *cfg, const char *param) auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *)cfg; int seconds = conf->timeout_sec; const char *error; - + /* Easy case - looks like all digits */ if (apr_isdigit(param[0]) && apr_isdigit(param[strlen(param) - 1])) { seconds = atoi(param); } - + /* Harder case - convert units to seconds */ else { error = convert_to_seconds(cmd, param, &seconds); @@ -295,7 +299,7 @@ set_auth_tkt_timeout (cmd_parms *cmd, void *cfg, const char *param) if (seconds == INT_MAX) return ("Integer overflow or invalid number"); conf->timeout_sec = seconds; - + return NULL; } @@ -303,14 +307,14 @@ static const char * set_auth_tkt_timeout_min (cmd_parms *cmd, void *cfg, const char *param) { auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *)cfg; - + int minutes = atoi(param); - + if (minutes < 0) return ("Timeout must be positive"); if (minutes == INT_MAX) return ("Integer overflow or invalid number"); - + conf->timeout_sec = minutes * 60; - + return NULL; } @@ -318,21 +322,21 @@ static const char * set_auth_tkt_timeout_refresh (cmd_parms *cmd, void *cfg, const char *param) { auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *)cfg; - + double refresh = atof(param); - if (refresh < 0 || refresh > 1) + if (refresh < 0 || refresh > 1) return "Refresh flag must be between 0 and 1"; - + conf->timeout_refresh = refresh; - + return NULL; } static const char * setup_secret (cmd_parms *cmd, void *cfg, const char *param) { - auth_tkt_serv_conf *sconf = + auth_tkt_serv_conf *sconf = ap_get_module_config(cmd->server->module_config, &auth_tkt_module); sconf->secret = param; return NULL; @@ -341,12 +345,22 @@ setup_secret (cmd_parms *cmd, void *cfg, const char *param) static const char * setup_old_secret (cmd_parms *cmd, void *cfg, const char *param) { - auth_tkt_serv_conf *sconf = ap_get_module_config(cmd->server->module_config, + auth_tkt_serv_conf *sconf = ap_get_module_config(cmd->server->module_config, &auth_tkt_module); sconf->old_secret = param; return NULL; } +static const char * +setup_query_separator (cmd_parms *cmd, void *cfg, const char *param) +{ + if (strcmp(param, ";") != 0 && strcmp(param, "&") != 0) + return "QuerySeparator must be either ';' or '&'."; + auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *)cfg; + conf->query_separator = param; + return NULL; +} + void setup_digest_sz (auth_tkt_serv_conf *sconf) { @@ -364,10 +378,10 @@ setup_digest_sz (auth_tkt_serv_conf *sconf) static const char * setup_digest_type (cmd_parms *cmd, void *cfg, const char *param) { - auth_tkt_serv_conf *sconf = + auth_tkt_serv_conf *sconf = ap_get_module_config(cmd->server->module_config, &auth_tkt_module); - if (strcmp(param, "MD5") != 0 && + if (strcmp(param, "MD5") != 0 && strcmp(param, "SHA256") != 0 && strcmp(param, "SHA512") != 0) return "Digest type must be one of: MD5 | SHA256 | SHA512."; @@ -400,7 +414,7 @@ set_cookie_expires (cmd_parms *cmd, void *cfg, const char *param) if (seconds == INT_MAX) return ("Integer overflow or invalid number"); conf->cookie_expires = seconds; - + return NULL; } @@ -408,90 +422,93 @@ static const char * set_auth_tkt_debug (cmd_parms *cmd, void *cfg, const char *param) { auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *)cfg; - + int debug = atoi(param); - + if (debug < 0) return ("Debug level must be positive"); if (debug == INT_MAX) return ("Integer overflow or invalid number"); - + conf->debug = debug; - + return NULL; } /* Command table */ static const command_rec auth_tkt_cmds[] = { - AP_INIT_TAKE1("TKTAuthLoginURL", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthLoginURL", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, login_url), OR_AUTHCFG, "URL to redirect to if authentication fails"), - AP_INIT_TAKE1("TKTAuthTimeoutURL", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthTimeoutURL", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, timeout_url), OR_AUTHCFG, "URL to redirect to if cookie times-out"), - AP_INIT_TAKE1("TKTAuthPostTimeoutURL", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthPostTimeoutURL", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, post_timeout_url), OR_AUTHCFG, "URL to redirect to if cookie times-out doing a POST"), - AP_INIT_TAKE1("TKTAuthUnauthURL", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthUnauthURL", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, unauth_url), OR_AUTHCFG, "URL to redirect to if valid user without required token"), - AP_INIT_TAKE1("TKTAuthCookieName", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthCookieName", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, auth_cookie_name), OR_AUTHCFG, "name to use for ticket cookie"), - AP_INIT_TAKE1("TKTAuthDomain", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthDomain", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, auth_domain), OR_AUTHCFG, "domain to use in cookies"), #ifndef APACHE13 /* TKTAuthCookieExpires is not supported under Apache 1.3 */ - AP_INIT_ITERATE("TKTAuthCookieExpires", set_cookie_expires, + AP_INIT_ITERATE("TKTAuthCookieExpires", set_cookie_expires, (void *)APR_OFFSETOF(auth_tkt_dir_conf, cookie_expires), OR_AUTHCFG, "cookie expiry period, in seconds or units [smhdwMy]"), #endif - AP_INIT_TAKE1("TKTAuthBackCookieName", ap_set_string_slot, + AP_INIT_TAKE1("TKTAuthBackCookieName", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, back_cookie_name), - OR_AUTHCFG, "name to use for back cookie (NULL for none)"), - AP_INIT_TAKE1("TKTAuthBackArgName", ap_set_string_slot, + OR_AUTHCFG, "name to use for back cookie (default: none)"), + AP_INIT_TAKE1("TKTAuthBackArgName", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, back_arg_name), - OR_AUTHCFG, "name to use for back url argument (NULL for none)"), - AP_INIT_FLAG("TKTAuthIgnoreIP", ap_set_flag_slot, + OR_AUTHCFG, "name to use for back url argument ('None' to not use)"), + AP_INIT_FLAG("TKTAuthIgnoreIP", ap_set_flag_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, ignore_ip), OR_AUTHCFG, "whether to ignore remote IP address in ticket"), - AP_INIT_FLAG("TKTAuthRequireSSL", ap_set_flag_slot, + AP_INIT_FLAG("TKTAuthRequireSSL", ap_set_flag_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, require_ssl), OR_AUTHCFG, "whether to refuse non-HTTPS requests"), - AP_INIT_FLAG("TKTAuthCookieSecure", ap_set_flag_slot, + AP_INIT_FLAG("TKTAuthCookieSecure", ap_set_flag_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, secure_cookie), OR_AUTHCFG, "whether to set secure flag on ticket cookies"), - AP_INIT_ITERATE("TKTAuthToken", set_auth_tkt_token, + AP_INIT_ITERATE("TKTAuthToken", set_auth_tkt_token, (void *)APR_OFFSETOF(auth_tkt_dir_conf, auth_token), OR_AUTHCFG, "token required to access this area (NULL for none)"), - AP_INIT_ITERATE("TKTAuthTimeout", set_auth_tkt_timeout, + AP_INIT_ITERATE("TKTAuthTimeout", set_auth_tkt_timeout, (void *)APR_OFFSETOF(auth_tkt_dir_conf, timeout_sec), OR_AUTHCFG, "ticket inactivity timeout, in seconds or units [smhdwMy]"), - AP_INIT_TAKE1("TKTAuthTimeoutMin", set_auth_tkt_timeout_min, + AP_INIT_TAKE1("TKTAuthTimeoutMin", set_auth_tkt_timeout_min, NULL, OR_AUTHCFG, "ticket inactivity timeout, in minutes (deprecated)"), - AP_INIT_TAKE1("TKTAuthTimeoutRefresh", set_auth_tkt_timeout_refresh, + AP_INIT_TAKE1("TKTAuthTimeoutRefresh", set_auth_tkt_timeout_refresh, NULL, OR_AUTHCFG, "ticket timeout refresh flag (0-1)"), - AP_INIT_TAKE1("TKTAuthSecret", setup_secret, + AP_INIT_TAKE1("TKTAuthSecret", setup_secret, NULL, RSRC_CONF, "secret key to use in digest"), - AP_INIT_TAKE1("TKTAuthSecretOld", setup_old_secret, + AP_INIT_TAKE1("TKTAuthSecretOld", setup_old_secret, NULL, RSRC_CONF, "old/alternative secret key to check in digests"), - AP_INIT_TAKE1("TKTAuthDigestType", setup_digest_type, - NULL, RSRC_CONF, "digest type to use [MD5|SHA256|SHA512], default MD5"), + AP_INIT_TAKE1("TKTAuthDigestType", setup_digest_type, + NULL, RSRC_CONF, "digest type to use [MD5|SHA256|SHA512], default: MD5"), AP_INIT_FLAG("TKTAuthGuestLogin", ap_set_flag_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, guest_login), OR_AUTHCFG, "whether to log people in as guest if no other auth available"), AP_INIT_FLAG("TKTAuthGuestCookie", ap_set_flag_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, guest_cookie), - OR_AUTHCFG, "whether to set a cookie when accepting guest users (default off)"), - AP_INIT_TAKE1("TKTAuthGuestUser", ap_set_string_slot, + OR_AUTHCFG, "whether to set a cookie when accepting guest users (default: off)"), + AP_INIT_TAKE1("TKTAuthGuestUser", ap_set_string_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, guest_user), OR_AUTHCFG, "username to use for guest logins"), AP_INIT_FLAG("TKTAuthGuestFallback", ap_set_flag_slot, (void *)APR_OFFSETOF(auth_tkt_dir_conf, guest_fallback), - OR_AUTHCFG, "whether to fall back to guest on an expired ticket (default off)"), - AP_INIT_ITERATE("TKTAuthDebug", set_auth_tkt_debug, + OR_AUTHCFG, "whether to fall back to guest on an expired ticket (default: off)"), + AP_INIT_ITERATE("TKTAuthDebug", set_auth_tkt_debug, (void *)APR_OFFSETOF(auth_tkt_dir_conf, debug), OR_AUTHCFG, "debug level (1-3, higher for more debug output)"), + AP_INIT_TAKE1("TKTAuthQuerySeparator", setup_query_separator, + (void *)APR_OFFSETOF(auth_tkt_dir_conf, query_separator), + OR_AUTHCFG, "Character used in query strings to separate arguments (default: ';')"), {NULL}, }; @@ -499,28 +516,28 @@ static const command_rec auth_tkt_cmds[] = /* Support functions */ /* Parse cookie. Returns 1 if valid, and details in *parsed; 0 if not */ -static int +static int parse_ticket(request_rec *r, char **magic, auth_tkt *parsed) { int sepidx, sep2idx; char *ticket = *magic; int len = strlen(ticket); - auth_tkt_serv_conf *sconf = + auth_tkt_serv_conf *sconf = ap_get_module_config(r->server->module_config, &auth_tkt_module); - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); - + /* For some reason (some clients?), tickets sometimes come in quoted */ if (ticket[len-1] == '"') ticket[len-1] = 0; if (ticket[0] == '"') *magic = ++ticket; /* Basic length check for min size */ if (len <= (sconf->digest_sz + TSTAMP_SZ)) - return 0; - + return 0; + /* See if there is a uid/data separator */ sepidx = ap_ind(ticket, SEPARATOR); - if (sepidx == -1) { + if (sepidx == -1) { /* Ticket either uri-escaped, base64-escaped, or bogus */ if (strstr(ticket, SEPARATOR_HEX)) { ap_unescape_url(ticket); @@ -528,7 +545,7 @@ parse_ticket(request_rec *r, char **magic, auth_tkt *parsed) } else { /* base64 encoded string always longer than original, so len+1 sufficient */ - char *buf = (char *) apr_palloc(r->pool, len+1); + char *buf = (char *) apr_palloc(r->pool, len+1); apr_base64_decode(buf, ticket); sepidx = ap_ind(buf, SEPARATOR); /* If still no sepidx, must be bogus */ @@ -541,26 +558,26 @@ parse_ticket(request_rec *r, char **magic, auth_tkt *parsed) } /* Recheck length */ - if (len <= (sconf->digest_sz + TSTAMP_SZ) || - sepidx < (sconf->digest_sz + TSTAMP_SZ)) - return 0; + if (len <= (sconf->digest_sz + TSTAMP_SZ) || + sepidx < (sconf->digest_sz + TSTAMP_SZ)) + return 0; if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT parse_ticket decoded ticket: '%s'", ticket); } - + /* Get the user id */ parsed->uid = apr_palloc(r->pool, sepidx - (sconf->digest_sz + TSTAMP_SZ) + 1); - memcpy(parsed->uid, &ticket[(sconf->digest_sz + TSTAMP_SZ)], + memcpy(parsed->uid, &ticket[(sconf->digest_sz + TSTAMP_SZ)], sepidx - (sconf->digest_sz + TSTAMP_SZ)); parsed->uid[sepidx - (sconf->digest_sz + TSTAMP_SZ)] = '\0'; - + /* Check for tokens */ sep2idx = ap_ind(&ticket[sepidx+1], SEPARATOR); if (sep2idx == -1) { if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT parse_ticket: no tokens"); } parsed->tokens = apr_palloc(r->pool, 1); @@ -572,15 +589,15 @@ parse_ticket(request_rec *r, char **magic, auth_tkt *parsed) sepidx = tmp + sep2idx + 1; sep2idx = tmp; if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, - "TKT parse_ticket: tokens found - sep2=%d, sep=%d, len=%d", - sep2idx, sepidx, len); + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + "TKT parse_ticket: tokens found - sep2=%d, sep=%d, len=%d", + sep2idx, sepidx, len); } /* Copy tokens to parsed->tokens */ parsed->tokens = apr_palloc(r->pool, sepidx-sep2idx); apr_snprintf(parsed->tokens, sepidx-sep2idx, "%s", &ticket[sep2idx+1]); if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT parse_ticket tokens: '%s'", parsed->tokens); } } @@ -591,22 +608,22 @@ parse_ticket(request_rec *r, char **magic, auth_tkt *parsed) /* Copy timestamp to parsed->timestamp */ sscanf(&ticket[sconf->digest_sz], "%8x", &(parsed->timestamp)); - + return 1; } /* Search cookie headers for our ticket */ -static int +static int cookie_match(void *result, const char *key, const char *cookie) { cookie_res * cr = (cookie_res *) result; - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(cr->r->per_dir_config, &auth_tkt_module); - + if (cookie != NULL) { char *cookie_name, *value, *cookiebuf, *end; if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, cr->r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, cr->r, "TKT cookie_match, key %s against <%s> (name=%s)", key, cookie, cr->cookie_name); } @@ -632,7 +649,7 @@ cookie_match(void *result, const char *key, const char *cookie) if (strlen(cookiebuf)) { cr->cookie = cookiebuf; if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, cr->r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, cr->r, "TKT cookie_match: found '%s'", cookiebuf); } return(0); @@ -640,7 +657,7 @@ cookie_match(void *result, const char *key, const char *cookie) } } if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, cr->r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, cr->r, "TKT cookie_match: NOT found"); } return (1); @@ -648,7 +665,7 @@ cookie_match(void *result, const char *key, const char *cookie) /* Return the domain to use in cookies */ char * -get_domain(request_rec *r, auth_tkt_dir_conf *conf) +get_domain(request_rec *r, auth_tkt_dir_conf *conf) { /* Set the cookie domain to the first set of TKTAuthDomain, X-Forwarded-Host, Host, or server hostname. Viljo Viitanen @@ -674,7 +691,7 @@ get_domain(request_rec *r, auth_tkt_dir_conf *conf) static void send_auth_cookie(request_rec *r, char *value) { - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); char *cookie, *expires; char *domain = get_domain(r,conf); @@ -688,12 +705,12 @@ send_auth_cookie(request_rec *r, char *value) #ifndef APACHE13 if (conf->cookie_expires > 0) { apr_time_exp_t tms; - apr_time_exp_gmt(&tms, r->request_time + + apr_time_exp_gmt(&tms, r->request_time + apr_time_from_sec(conf->cookie_expires)); - expires = + expires = apr_psprintf(r->pool, "; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT", apr_day_snames[tms.tm_wday], - tms.tm_mday, + tms.tm_mday, apr_month_snames[tms.tm_mon], tms.tm_year % 100, tms.tm_hour, tms.tm_min, tms.tm_sec @@ -702,12 +719,12 @@ send_auth_cookie(request_rec *r, char *value) #endif /* Send the cookie */ - cookie = apr_psprintf(r->pool, "%s=%s; path=/%s%s%s", + cookie = apr_psprintf(r->pool, "%s=%s; path=/%s%s%s", conf->auth_cookie_name, value, domain, expires, secure_cookie); apr_table_setn(r->err_headers_out, "Set-Cookie", cookie); if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: sending cookie: %s=%s; path=/%s%s%s", conf->auth_cookie_name, value, domain, expires, secure_cookie); } @@ -717,7 +734,7 @@ send_auth_cookie(request_rec *r, char *value) static char * get_url_ticket(request_rec *r) { - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); const char *args = NULL; /* url arguments string */ const char *key, *val; @@ -726,12 +743,12 @@ get_url_ticket(request_rec *r) /* Use main request args if subrequest */ request_rec *r_main = r->main == NULL ? r : r->main; if (r_main->args != NULL) { - args = apr_pstrdup(r->pool, r_main->args); + args = apr_pstrdup(r->pool, r_main->args); } if (args != NULL) { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: looking for ticket in url: <%s>", args); } @@ -740,12 +757,12 @@ get_url_ticket(request_rec *r) if (strcmp(key,conf->auth_cookie_name) == 0) { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: found url ticket: <%s>", val); } /* Setup auth cookie using ticket value */ - send_auth_cookie(r, (char *) val); + send_auth_cookie(r, (char *) val); /* Found ticket - ignore rest of arguments */ ticket = (char *) val; @@ -758,12 +775,12 @@ get_url_ticket(request_rec *r) } /* Look for a cookie ticket */ -static char * +static char * get_cookie_ticket(request_rec *r) { - auth_tkt_serv_conf *sconf = + auth_tkt_serv_conf *sconf = ap_get_module_config(r->server->module_config, &auth_tkt_module); - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); /* Walk cookie headers looking for matching ticket */ @@ -779,7 +796,7 @@ get_cookie_ticket(request_rec *r) } if (strlen(cr->cookie) < sconf->digest_sz + TSTAMP_SZ) { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT get_cookie_tkt: found cookie ticket, " "but it's too short for a %s digest (%zu < %d)", sconf->digest_type, strlen(cr->cookie), sconf->digest_sz + TSTAMP_SZ); @@ -791,18 +808,18 @@ get_cookie_ticket(request_rec *r) } /* Generate a ticket digest string from the given details */ -static char * +static char * ticket_digest(request_rec *r, auth_tkt *parsed, unsigned int timestamp, const char *secret) { - auth_tkt_serv_conf *sconf = + auth_tkt_serv_conf *sconf = ap_get_module_config(r->server->module_config, &auth_tkt_module); - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); char *uid = parsed->uid; char *tokens = parsed->tokens; char *user_data = parsed->user_data; - unsigned char *buf = apr_palloc(r->pool, + unsigned char *buf = apr_palloc(r->pool, TSTAMP_SZ + strlen(secret) + strlen(uid) + 1 + strlen(tokens) + 1 + strlen(user_data) + 1); unsigned char *buf2 = apr_palloc(r->pool, sconf->digest_sz + strlen(secret)); int len = 0; @@ -825,7 +842,7 @@ ticket_digest(request_rec *r, auth_tkt *parsed, unsigned int timestamp, const ch if (timestamp == 0) timestamp = parsed->timestamp; if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT ticket_digest: using secret '%s', ip '%s', ts '%d'", secret, remote_ip, timestamp); } @@ -837,13 +854,13 @@ ticket_digest(request_rec *r, auth_tkt *parsed, unsigned int timestamp, const ch buf[0] = (unsigned char ) ((ip & 0xff000000) >> 24); buf[1] = (unsigned char ) ((ip & 0xff0000) >> 16); buf[2] = (unsigned char ) ((ip & 0xff00) >> 8); - buf[3] = (unsigned char ) ((ip & 0xff)); - buf[4] = (unsigned char ) ((timestamp & 0xff000000) >> 24); - buf[5] = (unsigned char ) ((timestamp & 0xff0000) >> 16); - buf[6] = (unsigned char ) ((timestamp & 0xff00) >> 8); - buf[7] = (unsigned char ) ((timestamp & 0xff)); + buf[3] = (unsigned char ) ((ip & 0xff)); + buf[4] = (unsigned char ) ((timestamp & 0xff000000) >> 24); + buf[5] = (unsigned char ) ((timestamp & 0xff0000) >> 16); + buf[6] = (unsigned char ) ((timestamp & 0xff00) >> 8); + buf[7] = (unsigned char ) ((timestamp & 0xff)); len = 8; - + /* Append remaining components to buf */ strcpy((char *)&buf[len], secret); len += strlen(secret); @@ -870,7 +887,7 @@ ticket_digest(request_rec *r, auth_tkt *parsed, unsigned int timestamp, const ch digest = ap_md5_binary(r->pool, buf, len); } if (conf->debug >= 3) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT ticket_digest: digest0: '%s' (input length %d)", digest, len); } @@ -892,7 +909,7 @@ ticket_digest(request_rec *r, auth_tkt *parsed, unsigned int timestamp, const ch digest = ap_md5_binary(r->pool, buf2, len); } if (conf->debug >= 3) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT ticket_digest: digest: '%s'", digest); } @@ -910,21 +927,21 @@ valid_ticket(request_rec *r, const char *source, char *ticket, auth_tkt *parsed, char *digest; auth_tkt_serv_conf *sconf = ap_get_module_config(r->server->module_config, &auth_tkt_module); - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); /* Attempt to parse ticket */ if (! parse_ticket(r, &ticket, parsed)) { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, "TKT valid_ticket: unparseable %s ticket found ('%s')", source, ticket); } return 0; } if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, - "TKT valid_ticket: (parsed) uid '%s', tokens '%s', user_data '%s', ts '%d'", + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + "TKT valid_ticket: (parsed) uid '%s', tokens '%s', user_data '%s', ts '%d'", parsed->uid, parsed->tokens, parsed->user_data, parsed->timestamp); } @@ -934,9 +951,9 @@ valid_ticket(request_rec *r, const char *source, char *ticket, auth_tkt *parsed, /* Digest mismatch - if no old secret set, fail */ if(sconf->old_secret == NULL) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, "TKT valid_ticket: ticket hash (current secret) is invalid, and no old secret set " - "- digest '%s', ticket '%s'", + "- digest '%s', ticket '%s'", digest, ticket); return 0; } @@ -944,13 +961,13 @@ valid_ticket(request_rec *r, const char *source, char *ticket, auth_tkt *parsed, /* Digest mismatch - if old_secret is set, recalculate using that */ else { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT valid_ticket: ticket hash (current secret) is invalid, but old_secret is set - checking ticket digest against that"); } digest = ticket_digest(r, parsed, 0, sconf->old_secret); if (memcmp(ticket, digest, sconf->digest_sz) != 0) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, - "TKT valid_ticket: ticket hash (old secret) is also invalid - digest '%s', ticket '%s'", + ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, + "TKT valid_ticket: ticket hash (old secret) is also invalid - digest '%s', ticket '%s'", digest, ticket); return 0; } @@ -959,7 +976,7 @@ valid_ticket(request_rec *r, const char *source, char *ticket, auth_tkt *parsed, else { if (force_refresh != NULL) { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT valid_ticket: ticket_digest validated with old_secret - forcing a cookie refresh"); } *force_refresh = 1; @@ -971,31 +988,31 @@ valid_ticket(request_rec *r, const char *source, char *ticket, auth_tkt *parsed, return 1; } -/* Check for required auth tokens +/* Check for required auth tokens * Returns 1 on success, 0 on failure */ static int check_tokens(request_rec *r, char *tokens) { - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); char *next_parsed_token; const char *t = NULL; - int match = 0; + int match = 0; /* Success if no tokens required */ - if (conf->auth_token->nelts == 0 || + if (conf->auth_token->nelts == 0 || strcmp(((char **) conf->auth_token->elts)[0], "NULL") == 0) { return 1; } /* Failure if required and no user tokens found */ if (tokens == NULL || strlen(tokens) == 0) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: no matching tokens! (no user tokens found)"); return 0; } - t = apr_pstrdup(r->pool, tokens); - + t = apr_pstrdup(r->pool, tokens); + while (*t && (next_parsed_token = ap_getword(r->pool, &t, ','))) { char ** auth_tokens = (char **) conf->auth_token->elts; int i; @@ -1003,44 +1020,44 @@ check_tokens(request_rec *r, char *tokens) for (i=0; i < conf->auth_token->nelts; i++) { int token_len = strlen(auth_tokens[i]); if (strncmp(auth_tokens[i], next_parsed_token, token_len) == 0 && - next_parsed_token[token_len] == 0) { - match = 1; - break; + next_parsed_token[token_len] == 0) { + match = 1; + break; } } if (match) break; } if (conf->debug >= 1 && ! match) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: no matching tokens! (user tokens '%s')", tokens); } return match; -} /* check_tokens() */ +} /* Refresh the auth cookie if timeout refresh is set */ static void refresh_cookie(request_rec *r, auth_tkt *parsed, int timeout, int force_flag) { - auth_tkt_serv_conf *sconf = + auth_tkt_serv_conf *sconf = ap_get_module_config(r->server->module_config, &auth_tkt_module); - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); /* The timeout refresh is a double between 0 and 1, signifying what - * proportion of the timeout should be left before we refresh i.e. + * proportion of the timeout should be left before we refresh i.e. * 0 means never refresh (hard timeouts); 1 means always refresh; - * .33 means only refresh if less than a third of the timeout - * period remains. */ + * .33 means only refresh if less than a third of the timeout + * period remains. */ unsigned int now = time(NULL); int remainder = parsed->timestamp + timeout - now; double refresh_sec = conf->timeout_refresh * timeout; if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT refresh_cookie: timeout %d, refresh %.3f, remainder %d, refresh_sec %.3f, force_flag %d", - timeout, conf->timeout_refresh, remainder, refresh_sec, force_flag); + timeout, conf->timeout_refresh, remainder, refresh_sec, force_flag); } /* If less than our refresh_sec threshold, freshen the cookie */ @@ -1049,29 +1066,29 @@ refresh_cookie(request_rec *r, auth_tkt *parsed, int timeout, int force_flag) char *digest = ticket_digest(r, parsed, now, sconf->secret); if (parsed->tokens) { ticket = apr_psprintf(r->pool, - "%s%08x%s%c%s%c%s", - digest, now, parsed->uid, - SEPARATOR, parsed->tokens, - SEPARATOR, parsed->user_data); + "%s%08x%s%c%s%c%s", + digest, now, parsed->uid, + SEPARATOR, parsed->tokens, + SEPARATOR, parsed->user_data); } else { ticket = apr_psprintf(r->pool, - "%s%08x%s%c%s", + "%s%08x%s%c%s", digest, now, parsed->uid, SEPARATOR, parsed->user_data); } ticket_base64 = ap_pbase64encode(r->pool, ticket); - send_auth_cookie(r, ticket_base64); + send_auth_cookie(r, ticket_base64); } } - -/* Check whether the given timestamp has timed out + +/* Check whether the given timestamp has timed out * Returns 1 if okay, 0 if timed out */ static int check_timeout(request_rec *r, auth_tkt *parsed) { char *timeout_date, *timeout_cookie; - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); unsigned int now = time(NULL); unsigned int timestamp = parsed->timestamp; @@ -1086,24 +1103,24 @@ check_timeout(request_rec *r, auth_tkt *parsed) /* Check whether timestamp is still fresh */ if (timestamp + timeout >= now) { if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, - "TKT: cookie timeout still good: now %d, timeout: %d, tstamp: %d", + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + "TKT: cookie timeout still good: now %d, timeout: %d, tstamp: %d", now, timeout, timestamp); } /* Check whether to refresh the cookie */ - if (conf->timeout_refresh > 0) + if (conf->timeout_refresh > 0) refresh_cookie(r, parsed, timeout, CHECK_REFRESH); return 1; } if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, - "TKT: ticket timed out: now %d, timeout: %d, tstamp: %d", + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + "TKT: ticket timed out: now %d, timeout: %d, tstamp: %d", now, timeout, timestamp); } - + /* Delete cookie (set expired) if invalid, in case we want to set from url */ timeout_date = ap_ht_time(r->pool, now - 3600, "%a %d %b %Y %T %Z", 0); timeout_cookie = domain ? @@ -1119,7 +1136,7 @@ check_timeout(request_rec *r, auth_tkt *parsed) } /* Strip specified query args from a url */ -static char * +static char * query_strip(request_rec *r, const char *strip) { const char *args = NULL; /* url arguments string */ @@ -1129,10 +1146,10 @@ query_strip(request_rec *r, const char *strip) /* Use main request args if subrequest */ request_rec *r_main = r->main == NULL ? r : r->main; - if (r_main->args == NULL || strip == NULL) + if (r_main->args == NULL || strip == NULL) return NULL; - args = apr_pstrdup(r->pool, r_main->args); + args = apr_pstrdup(r->pool, r_main->args); /* Convert all '&' to ';' */ while ((p = ap_strchr(args, '&'))) @@ -1143,7 +1160,7 @@ query_strip(request_rec *r, const char *strip) key = ap_getword(r->pool, &val, '='); /* Add to new_args only if key != strip */ - if (strlen(strip) != strlen(key) || strncmp(key,strip,strlen(strip)) != 0) + if (strlen(strip) != strlen(key) || strncmp(key,strip,strlen(strip)) != 0) new_args = apr_psprintf(r->pool, "%s&%s=%s", new_args, key, val); } @@ -1168,14 +1185,14 @@ c2x(unsigned what, unsigned char *where) } /* Extra escaping - variant of httpd util.c ap_escape_path_segment */ -static char * +static char * escape_extras(apr_pool_t *p, const char *segment) { char *copy = apr_palloc(p, 3 * strlen(segment) + 1); const unsigned char *s = (const unsigned char *)segment; unsigned char *d = (unsigned char *)copy; unsigned c; - + while ((c = *s)) { if (c == '=' || c == '&' || c == ':') { d = c2x(c, d); @@ -1190,16 +1207,17 @@ escape_extras(apr_pool_t *p, const char *segment) } /* External redirect to the given url, setting back cookie or arg */ -static int +static int redirect(request_rec *r, char *location) { - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); char *domain = get_domain(r,conf); char *back_cookie_name = conf->back_cookie_name; char *back_arg_name = conf->back_arg_name; - char *url, *cookie, *back; + char *url = location; + char *cookie, *back; const char *hostinfo = 0; int port; @@ -1222,10 +1240,10 @@ redirect(request_rec *r, char *location) if (! hostinfo) hostinfo = apr_table_get(r->headers_in, "Host"); if (! hostinfo) { /* Fallback to using r->hostname and the server port. This usually - works, but behind a reverse proxy the port may well be wrong. + works, but behind a reverse proxy the port may well be wrong. On the other hand, it's really the proxy's problem, not ours. */ - ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, "TKT: could not find Host header, falling back to hostname/server port"); port = ap_get_server_port(r); hostinfo = port == apr_uri_default_port_for_scheme(scheme) ? @@ -1235,22 +1253,22 @@ redirect(request_rec *r, char *location) /* If no scheme, assume location is relative and expand using scheme and hostinfo */ if (strncasecmp(location, "http", 4) != 0) { - char *old_location = apr_pstrdup(r->pool, location); + char *old_location = apr_pstrdup(r->pool, location); location = apr_psprintf(r->pool, "%s://%s/%s", scheme, hostinfo, location); if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT relative URL '%s' expanded to '%s'", old_location, location); } } /* Setup back URL */ - back = apr_psprintf(r->pool, "%s://%s%s%s", + back = apr_psprintf(r->pool, "%s://%s%s%s", scheme, hostinfo, r->uri, query); if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: back url '%s'", back); } - + /* Escape testing */ back = ap_escape_path_segment(r->pool, back); back = escape_extras(r->pool, back); @@ -1258,9 +1276,9 @@ redirect(request_rec *r, char *location) /* Set back cookie if name is not null */ if (back_cookie_name) { cookie = domain ? - apr_psprintf(r->pool, "%s=%s; path=/; domain=%s", + apr_psprintf(r->pool, "%s=%s; path=/; domain=%s", back_cookie_name, back, domain) : - apr_psprintf(r->pool, "%s=%s; path=/", + apr_psprintf(r->pool, "%s=%s; path=/", back_cookie_name, back); apr_table_setn(r->err_headers_out, "Set-Cookie", cookie); @@ -1268,18 +1286,18 @@ redirect(request_rec *r, char *location) } /* If back_cookie_name not set, add a back url argument to url */ - else { - char sep = ap_strchr(location, '?') ? ';' : '?'; - url = apr_psprintf(r->pool, "%s%c%s=%s", + else if (back_arg_name) { + char sep = ap_strchr(location, '?') ? conf->query_separator[0] : '?'; + url = apr_psprintf(r->pool, "%s%c%s=%s", location, sep, back_arg_name, back); } if (conf->debug >= 2) { - ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, "TKT: redirect '%s'", url); } apr_table_setn(r->headers_out, "Location", url); - + return HTTP_TEMPORARY_REDIRECT; } @@ -1321,14 +1339,14 @@ get_guest_uid(request_rec *r, auth_tkt_dir_conf *conf) if (regm[1].rm_so != -1) { uuid_length_str = ap_pregsub(r->pool, "$1", guest_user, UUID_SUBS, regm); - if (uuid_length_str) + if (uuid_length_str) uuid_length = atoi(uuid_length_str); } if (uuid_length <= 0 || uuid_length > APR_UUID_FORMATTED_LENGTH) { uuid_length = APR_UUID_FORMATTED_LENGTH; } if (conf->debug >= 1) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, "TKT: %%U found in guest user (length %d)", uuid_length); } /* Generate the UUID */ @@ -1336,7 +1354,7 @@ get_guest_uid(request_rec *r, auth_tkt_dir_conf *conf) uuid_str = apr_palloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1); apr_uuid_get(uuid); apr_uuid_format(uuid_str, uuid); - if (uuid_length < APR_UUID_FORMATTED_LENGTH) + if (uuid_length < APR_UUID_FORMATTED_LENGTH) uuid_str[uuid_length] = '\0'; /* Generate the new guest_user string */ guest_user_length = strlen(guest_user); @@ -1351,7 +1369,7 @@ get_guest_uid(request_rec *r, auth_tkt_dir_conf *conf) else uuid_post = ""; - return apr_psprintf(r->pool, "%s%s%s", + return apr_psprintf(r->pool, "%s%s%s", uuid_pre, uuid_str, uuid_post); } @@ -1361,7 +1379,7 @@ get_guest_uid(request_rec *r, auth_tkt_dir_conf *conf) } /* Set up the guest user info */ -static int +static int setup_guest(request_rec *r, auth_tkt_dir_conf *conf, auth_tkt *tkt) { /* Only applicable if guest access on */ @@ -1372,8 +1390,8 @@ setup_guest(request_rec *r, auth_tkt_dir_conf *conf, auth_tkt *tkt) tkt->uid = get_guest_uid(r, conf); tkt->user_data = ""; tkt->tokens = ""; - ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, - "TKT: no valid ticket found - accepting as guest user '%s'", + ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, + "TKT: no valid ticket found - accepting as guest user '%s'", tkt->uid); return 1; @@ -1381,39 +1399,42 @@ setup_guest(request_rec *r, auth_tkt_dir_conf *conf, auth_tkt *tkt) /* ----------------------------------------------------------------------- */ /* Debug routines */ -void -dump_config(request_rec *r, auth_tkt_serv_conf *sconf, auth_tkt_dir_conf *conf) -{ -/* Protect against libc which dies on NULL strings :-( (DiB) */ + +/* Protect against libc which dies on NULL strings */ #define NN(x) ((x)?(x):"(null)") +void +dump_config(request_rec *r, auth_tkt_serv_conf *sconf, auth_tkt_dir_conf *conf) +{ /* Dump config settings */ - fprintf(stderr,"[ mod_auth_tkt config ]\n"); + fprintf(stderr,"[ mod_auth_tkt config (server) ]\n"); fprintf(stderr,"URI: %s\n", r->uri); + fprintf(stderr,"TKTAuthSecret: %s\n", NN(sconf->secret)); + fprintf(stderr,"TKTAuthSecretOld: %s\n", NN(sconf->old_secret)); + fprintf(stderr,"TKTAuthDigestType: %s\n", NN(sconf->digest_type)); + fprintf(stderr,"digest_sz: %d\n", sconf->digest_sz); + fprintf(stderr,"[ mod_auth_tkt config (dir) ]\n"); fprintf(stderr,"Filename: %s\n", NN(r->filename)); - fprintf(stderr,"TKTAuthSecret: %s\n", NN(sconf->secret)); - fprintf(stderr,"TKTAuthSecretOld: %s\n", NN(sconf->old_secret)); - fprintf(stderr,"TKTAuthDigestType: %s\n", NN(sconf->digest_type)); - fprintf(stderr,"digest_sz: %d\n", sconf->digest_sz); - fprintf(stderr,"directory: %s\n", NN(conf->directory)); - fprintf(stderr,"TKTAuthLoginURL: %s\n", NN(conf->login_url)); - fprintf(stderr,"TKTAuthTimeoutURL: %s\n", NN(conf->timeout_url)); - fprintf(stderr,"TKTAuthPostTimeoutURL: %s\n", NN(conf->post_timeout_url)); - fprintf(stderr,"TKTAuthUnauthURL: %s\n", NN(conf->unauth_url)); - fprintf(stderr,"TKTAuthCookieName: %s\n", NN(conf->auth_cookie_name)); - fprintf(stderr,"TKTAuthDomain: %s\n", NN(conf->auth_domain)); - fprintf(stderr,"TKTAuthCookieExpires: %d\n", conf->cookie_expires); - fprintf(stderr,"TKTAuthBackCookieName: %s\n", NN(conf->back_cookie_name)); - fprintf(stderr,"TKTAuthBackArgName: %s\n", NN(conf->back_arg_name)); - fprintf(stderr,"TKTAuthIgnoreIP: %d\n", conf->ignore_ip); - fprintf(stderr,"TKTAuthRequireSSL: %d\n", conf->require_ssl); - fprintf(stderr,"TKTAuthCookieSecure: %d\n", conf->secure_cookie); - fprintf(stderr,"TKTAuthTimeoutMin: %d\n", conf->timeout_sec); - fprintf(stderr,"TKTAuthTimeoutRefresh: %f\n", conf->timeout_refresh); + fprintf(stderr,"Directory: %s\n", NN(conf->directory)); + fprintf(stderr,"TKTAuthLoginURL: %s\n", NN(conf->login_url)); + fprintf(stderr,"TKTAuthTimeoutURL: %s\n", NN(conf->timeout_url)); + fprintf(stderr,"TKTAuthPostTimeoutURL: %s\n", NN(conf->post_timeout_url)); + fprintf(stderr,"TKTAuthUnauthURL: %s\n", NN(conf->unauth_url)); + fprintf(stderr,"TKTAuthCookieName: %s\n", NN(conf->auth_cookie_name)); + fprintf(stderr,"TKTAuthDomain: %s\n", NN(conf->auth_domain)); + fprintf(stderr,"TKTAuthCookieExpires: %d\n", conf->cookie_expires); + fprintf(stderr,"TKTAuthBackCookieName: %s\n", NN(conf->back_cookie_name)); + fprintf(stderr,"TKTAuthBackArgName: %s\n", NN(conf->back_arg_name)); + fprintf(stderr,"TKTAuthIgnoreIP: %d\n", conf->ignore_ip); + fprintf(stderr,"TKTAuthRequireSSL: %d\n", conf->require_ssl); + fprintf(stderr,"TKTAuthCookieSecure: %d\n", conf->secure_cookie); + fprintf(stderr,"TKTAuthTimeoutMin: %d\n", conf->timeout_sec); + fprintf(stderr,"TKTAuthTimeoutRefresh: %f\n", conf->timeout_refresh); fprintf(stderr,"TKTAuthGuestLogin: %d\n", conf->guest_login); fprintf(stderr,"TKTAuthGuestCookie: %d\n", conf->guest_cookie); fprintf(stderr,"TKTAuthGuestUser: %s\n", NN(conf->guest_user)); fprintf(stderr,"TKTAuthGuestFallback %d\n", conf->guest_fallback); + fprintf(stderr,"TKTAuthQuerySeparator: %c\n", conf->query_separator[0]); if (conf->auth_token->nelts > 0) { char ** auth_token = (char **) conf->auth_token->elts; int i; @@ -1432,7 +1453,7 @@ auth_tkt_check(request_rec *r) { char *ticket; auth_tkt *parsed = apr_palloc(r->pool, sizeof(*parsed)); - auth_tkt_dir_conf *conf = + auth_tkt_dir_conf *conf = ap_get_module_config(r->per_dir_config, &auth_tkt_module); auth_tkt_serv_conf *sconf = ap_get_module_config(r->server->module_config, &auth_tkt_module); @@ -1448,6 +1469,10 @@ auth_tkt_check(request_rec *r) setup_digest_sz(sconf); } + /* Map "None" back_arg_name to NULL */ + if (conf->back_arg_name && strcmp(conf->back_arg_name, "None") == 0) + conf->back_arg_name = NULL; + /* Dump config if debugging */ if (conf->debug >= 2) dump_config(r, sconf, conf); @@ -1458,21 +1483,21 @@ auth_tkt_check(request_rec *r) } /* Module misconfigured unless secret set */ if (! sconf->secret) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, "TKT: TKTAuthSecret missing"); return HTTP_INTERNAL_SERVER_ERROR; } /* Redirect/login if scheme not "https" and require_ssl is set */ if (conf->require_ssl > 0 && strcmp(scheme,"https") != 0) { - ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, "TKT: redirect/login - unsecured request, TKTAuthRequireSSL is on"); return redirect(r, conf->login_url); } /* Backwards compatibility mode for TKTAuthRequireSSL */ if (conf->require_ssl > 0 && conf->secure_cookie == -1) { - /* Set secure_cookie flag if require_ssl is set and secure_cookie is + /* Set secure_cookie flag if require_ssl is set and secure_cookie is undefined (as opposed to 'off') */ - ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_SUCCESS, r, "TKT: TKTAuthRequireSSL on, but no TKTAuthCookieSecure found - " "please set TKTAuthCookieSecure explicitly, assuming 'on'"); conf->secure_cookie = 1; @@ -1488,13 +1513,13 @@ auth_tkt_check(request_rec *r) } if (! guest) { if (conf->login_url) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_INFO, APR_SUCCESS, r, "TKT: no valid ticket found - redirecting to login url"); return redirect(r, conf->login_url); } else { /* Fatal error: guest setup failed, but we have no login url defined */ - ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, "TKT: guest login failed and no login url to fall back to - aborting"); return HTTP_INTERNAL_SERVER_ERROR; } @@ -1521,7 +1546,7 @@ auth_tkt_check(request_rec *r) } else { /* Fatal error: guest setup failed, but we have no url to redirect to */ - ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR, APR_SUCCESS, r, "TKT: ticket timeout, guest login failed, and no url to fall back to - aborting"); return HTTP_INTERNAL_SERVER_ERROR; } @@ -1553,7 +1578,7 @@ auth_tkt_check(request_rec *r) apr_table_set(r->subprocess_env, REMOTE_USER_TOKENS_ENV, parsed->tokens); return OK; -} /* auth_tkt_check() */ +} /* ----------------------------------------------------------------------- */ /* Setup main module data structure */ @@ -1562,11 +1587,11 @@ auth_tkt_check(request_rec *r) /* Apache 1.3 style */ module MODULE_VAR_EXPORT auth_tkt_module = { - STANDARD_MODULE_STUFF, + STANDARD_MODULE_STUFF, auth_tkt_version, /* initializer */ - create_auth_tkt_config, /* create per-dir config structures */ - merge_auth_tkt_config, /* merge per-dir config structures */ - create_auth_tkt_serv_config, /* create per-server config structures */ + create_auth_tkt_config, /* create per-dir config structures */ + merge_auth_tkt_config, /* merge per-dir config structures */ + create_auth_tkt_serv_config, /* create per-server config structures */ merge_auth_tkt_serv_config, /* merge per-server config structures */ auth_tkt_cmds, /* table of config file commands */ NULL, /* handlers */ @@ -1597,15 +1622,16 @@ auth_tkt_register_hooks (apr_pool_t *p) /* http://httpd.apache.org/docs/2.4/developer/new_api_2_4.html */ /* http://ci.apache.org/projects/httpd/trunk/doxygen/ */ ap_hook_check_authn(auth_tkt_check, NULL, NULL, APR_HOOK_FIRST, AP_AUTH_INTERNAL_PER_CONF); + #endif } /* Declare and populate the main module data structure */ module AP_MODULE_DECLARE_DATA auth_tkt_module = { - STANDARD20_MODULE_STUFF, - create_auth_tkt_config, /* create per-dir config structures */ - merge_auth_tkt_config, /* merge per-dir config structures */ - create_auth_tkt_serv_config, /* create per-server config structures */ + STANDARD20_MODULE_STUFF, + create_auth_tkt_config, /* create per-dir config structures */ + merge_auth_tkt_config, /* merge per-dir config structures */ + create_auth_tkt_serv_config, /* create per-server config structures */ merge_auth_tkt_serv_config, /* merge per-server config structures */ auth_tkt_cmds, /* table of config file commands */ auth_tkt_register_hooks /* register hooks */ @@ -1613,6 +1639,6 @@ module AP_MODULE_DECLARE_DATA auth_tkt_module = { #endif -/* - * vim:sw=2:sm +/* + * vim:sw=2:sm:et */ From 8dd460572968051825e67138b42ea92b9878e142 Mon Sep 17 00:00:00 2001 From: Dietmar Berg Date: Mon, 6 Apr 2015 21:03:01 +0200 Subject: [PATCH 3/6] Implements Apache 2.4 authz provider ("Require tkt-group group1 group2 ...") --- src/mod_auth_tkt.c | 91 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 4 deletions(-) diff --git a/src/mod_auth_tkt.c b/src/mod_auth_tkt.c index d077b5a..015df51 100755 --- a/src/mod_auth_tkt.c +++ b/src/mod_auth_tkt.c @@ -988,6 +988,22 @@ valid_ticket(request_rec *r, const char *source, char *ticket, auth_tkt *parsed, return 1; } +#ifdef APACHE24 +/* Fake the basic authentication header for consumption by applications */ +static void +fake_basic_authentication(request_rec *r, + const char *user, const char *pw) +{ + char *basic = apr_pstrcat(r->pool, user, ":", pw, NULL); + apr_size_t size = (apr_size_t) strlen(basic); + char *base64 = apr_palloc(r->pool, + apr_base64_encode_len(size + 1) * sizeof(char)); + apr_base64_encode(base64, basic, size); + apr_table_setn(r->headers_in, "Authorization", + apr_pstrcat(r->pool, "Basic ", base64, NULL)); +} +#endif + /* Check for required auth tokens * Returns 1 on success, 0 on failure */ static int @@ -1036,6 +1052,64 @@ check_tokens(request_rec *r, char *tokens) return match; } +#ifdef APACHE24 +/* Implement the Apache 2.4 authz provider 'check_authorization' function */ +static authz_status +tkt_check_authorization(request_rec *r, + const char *require_args, + const void *parsed_require_args) +{ + const char *user = r->user; + const char *tokens = apr_table_get(r->subprocess_env, REMOTE_USER_TOKENS_ENV); + ap_log_rerror(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, r, APLOGNO(00000) + "TKT tkt_check_authorization: require_args=%s, user=%s, tokens=%s", + require_args, user, tokens); + + /* We need a parsed ticket, force Apache to get it */ + if (!user) { + return AUTHZ_DENIED_NO_USER; + } + + /* Prepare lookup table from comma-separated list of tokens */ + apr_table_t *token_table = (apr_table_t*)apr_table_make(r->pool, 5); + const char *t = tokens; + char *token; + while (*t && (token = ap_getword(r->pool, &t, ','))) { + apr_table_setn(token_table, token, "x"); + } + + /* Check if at least one group is matched by a token (case insensitive) */ + const char *g = require_args; + char *group; + int match = 0; + while (*g && (group = ap_getword(r->pool, &g, ' '))) { + if (apr_table_get(token_table, group)) { + match = 1; + break; + } + } + + if (!match) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00000) + "Authorization of user %s to access %s failed, reason: " + "ticket has no token that matches one of the 'require'ed " + "group(s): %s; tokens=%s", + r->user, r->uri, require_args, tokens); + return AUTHZ_DENIED; + } + + return AUTHZ_GRANTED; +} + +/* Declare the Apache 2.4 authz provider callbacks */ +static const authz_provider authz_tkt_provider = +{ + &tkt_check_authorization, /* check_authorization */ + NULL, /* parse_require_line */ +}; +#endif + + /* Refresh the auth cookie if timeout refresh is set */ static void refresh_cookie(request_rec *r, auth_tkt *parsed, int timeout, int force_flag) @@ -1577,6 +1651,10 @@ auth_tkt_check(request_rec *r) apr_table_set(r->subprocess_env, REMOTE_USER_DATA_ENV, parsed->user_data); apr_table_set(r->subprocess_env, REMOTE_USER_TOKENS_ENV, parsed->tokens); +#ifdef APACHE24 + fake_basic_authentication(r, (char*)parsed->uid, "password"); +#endif + return OK; } @@ -1603,13 +1681,13 @@ module MODULE_VAR_EXPORT auth_tkt_module = { NULL, /* fixups */ NULL, /* logger */ NULL, /* header parser */ - NULL, /* chitkt_init */ - NULL, /* chitkt_exit */ + NULL, /* child_init */ + NULL, /* child_exit */ NULL /* post read-request */ }; #else -/* Apache 2.0 style */ +/* Apache 2.x style */ /* Register hooks */ static void @@ -1622,7 +1700,12 @@ auth_tkt_register_hooks (apr_pool_t *p) /* http://httpd.apache.org/docs/2.4/developer/new_api_2_4.html */ /* http://ci.apache.org/projects/httpd/trunk/doxygen/ */ ap_hook_check_authn(auth_tkt_check, NULL, NULL, APR_HOOK_FIRST, AP_AUTH_INTERNAL_PER_CONF); - + /* Register ourselves as authz provider */ + /* Require tkt-group group1 group2 ... */ + ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "tkt-group", + AUTHZ_PROVIDER_VERSION, + &authz_tkt_provider, + AP_AUTH_INTERNAL_PER_CONF); #endif } From 0d5628631b438b9964498b5213d6140ff506527f Mon Sep 17 00:00:00 2001 From: Dietmar Berg Date: Mon, 6 Apr 2015 21:07:05 +0200 Subject: [PATCH 4/6] Cleanup (extra blanks at end of line) --- src/mod_auth_tkt.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/mod_auth_tkt.c b/src/mod_auth_tkt.c index 015df51..5746a65 100755 --- a/src/mod_auth_tkt.c +++ b/src/mod_auth_tkt.c @@ -990,8 +990,8 @@ valid_ticket(request_rec *r, const char *source, char *ticket, auth_tkt *parsed, #ifdef APACHE24 /* Fake the basic authentication header for consumption by applications */ -static void -fake_basic_authentication(request_rec *r, +static void +fake_basic_authentication(request_rec *r, const char *user, const char *pw) { char *basic = apr_pstrcat(r->pool, user, ":", pw, NULL); @@ -1054,7 +1054,7 @@ check_tokens(request_rec *r, char *tokens) #ifdef APACHE24 /* Implement the Apache 2.4 authz provider 'check_authorization' function */ -static authz_status +static authz_status tkt_check_authorization(request_rec *r, const char *require_args, const void *parsed_require_args) @@ -1062,7 +1062,7 @@ tkt_check_authorization(request_rec *r, const char *user = r->user; const char *tokens = apr_table_get(r->subprocess_env, REMOTE_USER_TOKENS_ENV); ap_log_rerror(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, r, APLOGNO(00000) - "TKT tkt_check_authorization: require_args=%s, user=%s, tokens=%s", + "TKT tkt_check_authorization: require_args=%s, user=%s, tokens=%s", require_args, user, tokens); /* We need a parsed ticket, force Apache to get it */ @@ -1097,7 +1097,7 @@ tkt_check_authorization(request_rec *r, r->user, r->uri, require_args, tokens); return AUTHZ_DENIED; } - + return AUTHZ_GRANTED; } @@ -1652,7 +1652,7 @@ auth_tkt_check(request_rec *r) apr_table_set(r->subprocess_env, REMOTE_USER_TOKENS_ENV, parsed->tokens); #ifdef APACHE24 - fake_basic_authentication(r, (char*)parsed->uid, "password"); + fake_basic_authentication(r, (char*)parsed->uid, "password"); #endif return OK; @@ -1705,7 +1705,7 @@ auth_tkt_register_hooks (apr_pool_t *p) ap_register_auth_provider(p, AUTHZ_PROVIDER_GROUP, "tkt-group", AUTHZ_PROVIDER_VERSION, &authz_tkt_provider, - AP_AUTH_INTERNAL_PER_CONF); + AP_AUTH_INTERNAL_PER_CONF); #endif } From f3117bb6ad024fbd69e801bff8d2f10d52880d2f Mon Sep 17 00:00:00 2001 From: Dietmar Berg Date: Tue, 7 Apr 2015 09:28:28 +0200 Subject: [PATCH 5/6] Updated/added doc for use with Apache 2.4; made TKTAuthToken deprecated in favor of Require --- INSTALL | 2 +- README.Apache_2.4 | 45 +++++++++++++++++++++++++++++++++++++++++++++ src/mod_auth_tkt.c | 22 +++++++++++++++++----- 3 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 README.Apache_2.4 diff --git a/INSTALL b/INSTALL index 44fa98c..d414dd7 100644 --- a/INSTALL +++ b/INSTALL @@ -1,7 +1,7 @@ Installation ============ -Requires: an apache with DSO support, either 1.3.x, 2.0.x, or 2.2.x. +Requires: an apache with DSO support, either 1.3.x, 2.0.x, 2.2.x, or 2.4.x. $ ./configure --apxs=/path/to/apxs $ make diff --git a/README.Apache_2.4 b/README.Apache_2.4 new file mode 100644 index 0000000..d089eec --- /dev/null +++ b/README.Apache_2.4 @@ -0,0 +1,45 @@ +Upgrading to Apache 2.4 +----------------------- + +Starting with version 2.2.0, mod_auth_tkt supports Apache 2.4 +taking advantage of the new "provider" model for authentication/ +authorization. + +In particular, mod_auth_tkt now acts as an authorization provider +and allows you to use the much more versatile 'Require' directive +instead of TKTAuthToken: + + Require tkt-group token1 token2 ... + +Note that the "entity-name" needs to be 'tkt-group' and not +just 'group' to direct the check to mod_auth_tkt (this also +applies for similar modules, e.g. mod_auth_dbm -> dbm-group +and is *not* documented in the Apache 2.4 doc). + +The remainder of the directive is a list of one or more tokens +of which at least one must be present in the ticket for a user +to be granted access to the resource. + +Using the standard 'Require' directive together with the new + sections allows to build arbitrarily complex +access control expressions. + +Example config: + + TKTAuthSecret "my shared secret" + + TKTAuthLoginURL https://sso.some.where/login + TKTAuthDomain .some.where + # + Order allow,deny + Allow from all + Require all granted + + + + Require tkt-group gamblers taxpayers + + +Note that there are no AuthBasic* directives anywhere. +On authorization failure, the session is immediately +redirected to the error page. diff --git a/src/mod_auth_tkt.c b/src/mod_auth_tkt.c index 5746a65..f16814c 100755 --- a/src/mod_auth_tkt.c +++ b/src/mod_auth_tkt.c @@ -272,6 +272,14 @@ set_auth_tkt_token (cmd_parms *cmd, void *cfg, const char *param) char **new; auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *) cfg; +#ifdef APACHE24 + ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, + "As of Apache 2.4, TKTAuthToken is deprecated in favor " + "of the more versatile standard directive " + "'Require tkt-group group1 group2 ...' " + "(see README.Apache_2.4 for more information)."); +#endif + new = (char **) apr_array_push(conf->auth_token); *new = apr_pstrdup(cmd->pool, param); return NULL; @@ -537,7 +545,7 @@ parse_ticket(request_rec *r, char **magic, auth_tkt *parsed) /* See if there is a uid/data separator */ sepidx = ap_ind(ticket, SEPARATOR); - if (sepidx == -1) { + if (sepidx == -1) { /* Ticket either uri-escaped, base64-escaped, or bogus */ if (strstr(ticket, SEPARATOR_HEX)) { ap_unescape_url(ticket); @@ -1061,9 +1069,13 @@ tkt_check_authorization(request_rec *r, { const char *user = r->user; const char *tokens = apr_table_get(r->subprocess_env, REMOTE_USER_TOKENS_ENV); - ap_log_rerror(APLOG_MARK, APLOG_TRACE2, APR_SUCCESS, r, APLOGNO(00000) - "TKT tkt_check_authorization: require_args=%s, user=%s, tokens=%s", - require_args, user, tokens); + auth_tkt_dir_conf *conf = + ap_get_module_config(r->per_dir_config, &auth_tkt_module); + if (conf->debug >= 2) { + ap_log_rerror(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r, + "TKT tkt_check_authorization: require_args=%s, user=%s, tokens=%s", + require_args, user, tokens); + } /* We need a parsed ticket, force Apache to get it */ if (!user) { @@ -1090,7 +1102,7 @@ tkt_check_authorization(request_rec *r, } if (!match) { - ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(00000) + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Authorization of user %s to access %s failed, reason: " "ticket has no token that matches one of the 'require'ed " "group(s): %s; tokens=%s", From 24c5bea165d87db35f148b7bcbddf7935f0f69a3 Mon Sep 17 00:00:00 2001 From: Dietmar Berg Date: Tue, 7 Apr 2015 20:08:31 +0200 Subject: [PATCH 6/6] Updated manpage; less pressure to move away from 'TKTAuthToken' to 'Require'. --- doc/mod_auth_tkt.pod | 40 ++++++++++++++++++++++++++++++++++++++++ src/mod_auth_tkt.c | 18 +++++++++++------- 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/doc/mod_auth_tkt.pod b/doc/mod_auth_tkt.pod index edf0590..193373c 100644 --- a/doc/mod_auth_tkt.pod +++ b/doc/mod_auth_tkt.pod @@ -337,6 +337,37 @@ see these messages. =back +=head2 Apache 2.4 Specifics + +one of the new features of Apache 2.4 is a framework +for authentication and authorization providers. +mod_auth_tkt registers itself as an authorization +provider, invoked when the standard C directive +is followed by the entity type C and one +more "groups", i.e. tokens in the ticket. +This is more general approach than C, +since these directives can be combined to build +arbitarily complex access control expressions. + +The server now uses the IP address of the user agent +instead of the connection endpoint, which makes it more +useful in a load-balancer or proxy environment. + +mod_auth_tkt now passes the authenticated username +to applications in a fake authentication header. + +=over 4 + +=item Require tkt-group + +mod_auth_tkt allows to use tokens in the same way as you would +use groups in a C directive. +The directive grants access if the current ticket contains at +least one of the tokens listed in the directive. +C also triggers authentication through mod_auth_tkt. + +=back + =head1 EXAMPLES Minimal config using logins: @@ -383,6 +414,15 @@ Example intranet configuration: +Example Apache 2.4 configuration using groups/tokens: + + + AuthType None + require tkt-group token1 token2 + TKTAuthLoginURL https://www.example.com/auth/login.cgi + + + =head1 SUPPORT Support is available on the mod_auth_tkt mailing list, courtesy of diff --git a/src/mod_auth_tkt.c b/src/mod_auth_tkt.c index f16814c..5719d56 100755 --- a/src/mod_auth_tkt.c +++ b/src/mod_auth_tkt.c @@ -273,11 +273,10 @@ set_auth_tkt_token (cmd_parms *cmd, void *cfg, const char *param) auth_tkt_dir_conf *conf = (auth_tkt_dir_conf *) cfg; #ifdef APACHE24 - ap_log_error(APLOG_MARK, APLOG_WARNING, 0, cmd->server, - "As of Apache 2.4, TKTAuthToken is deprecated in favor " - "of the more versatile standard directive " - "'Require tkt-group group1 group2 ...' " - "(see README.Apache_2.4 for more information)."); + ap_log_error(APLOG_MARK, APLOG_INFO, 0, cmd->server, + "With Apache 2.4, 'Require tkt-group group1 group2 ...' " + "is a more versatile alternative to TKTAuthToken (see " + "README.Apache_2.4 or the manpage for more information)."); #endif new = (char **) apr_array_push(conf->auth_token); @@ -1396,10 +1395,15 @@ get_guest_uid(request_rec *r, auth_tkt_dir_conf *conf) int guest_user_length; apr_uuid_t *uuid; char *uuid_str, *uuid_length_str; -#ifndef APACHE22 +#ifdef APACHE20 regex_t *uuid_regex; regmatch_t regm[UUID_SUBS]; -#else +#endif +#ifdef APACHE22 + ap_regex_t *uuid_regex; + ap_regmatch_t regm[UUID_SUBS]; +#endif +#ifdef APACHE24 ap_regex_t *uuid_regex; ap_regmatch_t regm[UUID_SUBS]; #endif