From: Ken Coar Date: Thu, 16 Aug 2001 01:46:50 +0000 (+0000) Subject: Add CookieDomain directive to allow setting of the Domain= X-Git-Tag: 2.0.24~87 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2c8dd7727411a0ddb88af013680df19b263c9e7b;p=apache Add CookieDomain directive to allow setting of the Domain= cookie attribute; add CookieStyle to allow specification of cookie syntax: Netscape (default), Cookie or RFC2109, or Cookie2 or RFC2965. We have historically supported only the obsolete Netscape syntax. PR: several against 1.3 Obtained from: brought forward from 1.3 git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@90180 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 04822bf35b..8ba44329a8 100644 --- a/CHANGES +++ b/CHANGES @@ -1,5 +1,11 @@ Changes with Apache 2.0.24-dev + *) We have always used the obsolete/deprecated Netscape syntax + for our tracking cookies; now the CookieStyle directive + allows the Webmaster to choose the Netscape, RFC2109, or + RFC2965 format. The new CookieDomain directive allows the + setting of the cookie's Domain= attribute, too. + *) Tweak server/Makefile so that the rules for generating exports.c are compatible with make utilities which don't expand wildcards in a dependency list (e.g., OS/390 make, certain levels of GNU diff --git a/modules/metadata/mod_usertrack.c b/modules/metadata/mod_usertrack.c index dfe39f0875..b23a80b87d 100644 --- a/modules/metadata/mod_usertrack.c +++ b/modules/metadata/mod_usertrack.c @@ -120,9 +120,18 @@ typedef struct { int expires; } cookie_log_state; +typedef enum { + CT_UNSET, + CT_NETSCAPE, + CT_COOKIE, + CT_COOKIE2 +} cookie_type_e; + typedef struct { int enabled; + cookie_type_e style; char *cookie_name; + char *cookie_domain; } cookie_dir_rec; /* Make Cookie: Now we have to generate something that is going to be @@ -148,23 +157,50 @@ static void make_cookie(request_rec *r) if (cls->expires) { apr_exploded_time_t tms; + time_t when; + + when = cls->expires; + if ((dcfg->style == CT_UNSET) || (dcfg->style == CT_NETSCAPE)) { + when += r->request_time; + } - apr_explode_gmt(&tms, r->request_time + cls->expires * APR_USEC_PER_SEC); + apr_explode_gmt(&tms, + r->request_time + cls->expires * APR_USEC_PER_SEC); /* Cookie with date; as strftime '%a, %d-%h-%y %H:%M:%S GMT' */ - new_cookie = apr_psprintf(r->pool, - "%s=%s; path=/; expires=%s, %.2d-%s-%.2d %.2d:%.2d:%.2d GMT", - dcfg->cookie_name, cookiebuf, apr_day_snames[tms.tm_wday], - tms.tm_mday, apr_month_snames[tms.tm_mon], - tms.tm_year % 100, - tms.tm_hour, tms.tm_min, tms.tm_sec); + new_cookie = apr_psprintf(r->pool, "%s=%s; path=/", + dcfg->cookie_name, cookiebuf); + if ((dcfg->style == CT_UNSET) || (dcfg->style == CT_NETSCAPE)) { + new_cookie = apr_psprintf(r->pool, + "%s; expires=%s, " + "%.2d-%s-%.2d %.2d:%.2d:%.2d GMT", + new_cookie, apr_day_snames[tms.tm_wday], + tms.tm_mday, + apr_month_snames[tms.tm_mon], + tms.tm_year % 100, + tms.tm_hour, tms.tm_min, tms.tm_sec); + } + else { + new_cookie = apr_psprintf(r->pool, "%s; max-age=%d", + new_cookie, (int) when); + } } else { - new_cookie = apr_psprintf(r->pool, "%s=%s; path=/", - dcfg->cookie_name, cookiebuf); + new_cookie = apr_psprintf(r->pool, "%s=%s; path=/", + dcfg->cookie_name, cookiebuf); + } + if (dcfg->cookie_domain != NULL) { + new_cookie = apr_pstrcat(r->pool, new_cookie, "; domain=", + dcfg->cookie_domain, + (dcfg->style == CT_COOKIE2 + ? "; version=1" + : ""), + NULL); } - apr_table_setn(r->headers_out, "Set-Cookie", new_cookie); + apr_table_setn(r->headers_out, + (dcfg->style == CT_COOKIE2 ? "Set-Cookie2" : "Set-Cookie"), + new_cookie); apr_table_setn(r->notes, "cookie", apr_pstrdup(r->pool, cookiebuf)); /* log first time */ return; } @@ -180,7 +216,10 @@ static int spot_cookie(request_rec *r) return DECLINED; } - if ((cookie = apr_table_get(r->headers_in, "Cookie"))) + if ((cookie = apr_table_get(r->headers_in, + (dcfg->style == CT_COOKIE2 + ? "Cookie2" + : "Cookie")))) if ((value = ap_strstr_c(cookie, dcfg->cookie_name))) { char *cookiebuf, *cookieend; @@ -215,6 +254,8 @@ static void *make_cookie_dir(apr_pool_t *p, char *d) dcfg = (cookie_dir_rec *) apr_pcalloc(p, sizeof(cookie_dir_rec)); dcfg->cookie_name = COOKIE_NAME; + dcfg->cookie_domain = NULL; + dcfg->style = CT_UNSET; dcfg->enabled = 0; return dcfg; } @@ -227,14 +268,16 @@ static const char *set_cookie_enable(cmd_parms *cmd, void *mconfig, int arg) return NULL; } -static const char *set_cookie_exp(cmd_parms *parms, void *dummy, const char *arg) +static const char *set_cookie_exp(cmd_parms *parms, void *dummy, + const char *arg) { - cookie_log_state *cls = ap_get_module_config(parms->server->module_config, - &usertrack_module); + cookie_log_state *cls; time_t factor, modifier = 0; time_t num = 0; char *word; + cls = ap_get_module_config(parms->server->module_config, + &usertrack_module); /* The simple case first - all numbers (we assume) */ if (apr_isdigit(arg[0]) && apr_isdigit(arg[strlen(arg) - 1])) { cls->expires = atol(arg); @@ -294,7 +337,8 @@ static const char *set_cookie_exp(cmd_parms *parms, void *dummy, const char *arg return NULL; } -static const char *set_cookie_name(cmd_parms *cmd, void *mconfig, const char *name) +static const char *set_cookie_name(cmd_parms *cmd, void *mconfig, + const char *name) { cookie_dir_rec *dcfg = (cookie_dir_rec *) mconfig; @@ -302,9 +346,69 @@ static const char *set_cookie_name(cmd_parms *cmd, void *mconfig, const char *na return NULL; } +/* + * Set the value for the 'Domain=' attribute. + */ +static const char *set_cookie_domain(cmd_parms *cmd, void *mconfig, + const char *name) +{ + cookie_dir_rec *dcfg; + + dcfg = (cookie_dir_rec *) mconfig; + + /* + * Apply the restrictions on cookie domain attributes. + */ + if (strlen(name) == 0) { + return "CookieDomain values may not be null"; + } + if (name[0] != '.') { + return "CookieDomain values must begin with a dot"; + } + if (strchr(&name[1], '.') == NULL) { + return "CookieDomain values must contain at least one embedded dot"; + } + + dcfg->cookie_domain = apr_pstrdup(cmd->pool, name); + return NULL; +} + +/* + * Make a note of the cookie style we should use. + */ +static const char *set_cookie_style(cmd_parms *cmd, void *mconfig, + const char *name) +{ + cookie_dir_rec *dcfg; + + dcfg = (cookie_dir_rec *) mconfig; + + if (strcasecmp(name, "Netscape") == 0) { + dcfg->style = CT_NETSCAPE; + } + else if ((strcasecmp(name, "Cookie") == 0) + || (strcasecmp(name, "RFC2109") == 0)) { + dcfg->style = CT_COOKIE; + } + else if ((strcasecmp(name, "Cookie2") == 0) + || (strcasecmp(name, "RFC2965") == 0)) { + dcfg->style = CT_COOKIE2; + } + else { + return apr_psprintf(cmd->pool, "Invalid %s keyword: '%s'", + cmd->cmd->name, name); + } + + return NULL; +} + static const command_rec cookie_log_cmds[] = { - AP_INIT_TAKE1("CookieExpires", set_cookie_exp, NULL, RSRC_CONF, + AP_INIT_TAKE1("CookieExpires", set_cookie_exp, NULL, OR_FILEINFO, "an expiry date code"), + AP_INIT_TAKE1("CookieDomain", set_cookie_domain, NULL, OR_FILEINFO, + "domain to which this cookie applies"), + AP_INIT_TAKE1("CookieStyle", set_cookie_style, NULL, OR_FILEINFO, + "'Netscape', 'Cookie' (RFC2109), or 'Cookie2' (RFC2965)"), AP_INIT_FLAG("CookieTracking", set_cookie_enable, NULL, OR_FILEINFO, "whether or not to enable cookies"), AP_INIT_TAKE1("CookieName", set_cookie_name, NULL, OR_FILEINFO,