Commit cef17fb9 authored by Ken Coar's avatar Ken Coar
Browse files

	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
parent 893397cc
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
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
+120 −16
Original line number Diff line number Diff line
@@ -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=/",
                                  dcfg->cookie_name, cookiebuf);
        if ((dcfg->style == CT_UNSET) || (dcfg->style == CT_NETSCAPE)) {
            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],
                                       "%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);
    }
    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,