Moved apache code into a folder to help prepare for packaging where we dont want...
[httpd-crcsyncproxy.git] / apache / modules / session / mod_session_cookie.c
blobb4895489e7641397ffe095ed5dc20fb9a8ed7387
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "mod_session.h"
18 #include "apr_lib.h"
19 #include "apr_strings.h"
20 #include "http_log.h"
21 #include "util_cookies.h"
23 #define LOG_PREFIX "mod_session_cookie: "
24 #define MOD_SESSION_COOKIE "mod_session_cookie"
26 module AP_MODULE_DECLARE_DATA session_cookie_module;
28 /**
29 * Structure to carry the per-dir session config.
31 typedef struct {
32 const char *name;
33 int name_set;
34 const char *name_attrs;
35 const char *name2;
36 int name2_set;
37 const char *name2_attrs;
38 int remove;
39 int remove_set;
40 } session_cookie_dir_conf;
42 /**
43 * Set the cookie and embed the session within it.
45 * This function adds an RFC2109 compliant Set-Cookie header for
46 * the cookie specified in SessionCookieName, and an RFC2965 compliant
47 * Set-Cookie2 header for the cookie specified in SessionCookieName2.
49 * If specified, the optional cookie attributes will be added to
50 * each cookie. If defaults are not specified, DEFAULT_ATTRS
51 * will be used.
53 * On success, this method will return APR_SUCCESS.
55 * @param r The request pointer.
56 * @param z A pointer to where the session will be written.
58 static int session_cookie_save(request_rec * r, session_rec * z)
61 session_cookie_dir_conf *conf = ap_get_module_config(r->per_dir_config,
62 &session_cookie_module);
64 /* don't cache auth protected pages */
65 apr_table_addn(r->headers_out, "Cache-Control", "no-cache");
67 /* create RFC2109 compliant cookie */
68 if (conf->name_set) {
69 if (z->encoded && z->encoded[0]) {
70 ap_cookie_write(r, conf->name, z->encoded, conf->name_attrs, z->maxage, r->headers_out, r->err_headers_out, NULL);
72 else {
73 ap_cookie_remove(r, conf->name, conf->name_attrs, r->headers_out, r->err_headers_out, NULL);
77 /* create RFC2965 compliant cookie */
78 if (conf->name2_set) {
79 if (z->encoded && z->encoded[0]) {
80 ap_cookie_write2(r, conf->name2, z->encoded, conf->name2_attrs, z->maxage, r->headers_out, r->err_headers_out, NULL);
82 else {
83 ap_cookie_remove2(r, conf->name2, conf->name2_attrs, r->headers_out, r->err_headers_out, NULL);
87 if (conf->name_set || conf->name2_set) {
88 return OK;
90 return DECLINED;
94 /**
95 * Isolate the cookie with the name "name", and if present, extract
96 * the payload from the cookie.
98 * If the cookie is found, the cookie and any other cookies with the
99 * same name are removed from the cookies passed in the request, so
100 * that credentials are not leaked to a backend server or process.
102 * A missing or malformed cookie will cause this function to return
103 * APR_EGENERAL.
105 * On success, this returns APR_SUCCESS.
107 static int session_cookie_load(request_rec * r, session_rec ** z)
110 session_cookie_dir_conf *conf = ap_get_module_config(r->per_dir_config,
111 &session_cookie_module);
113 session_rec *zz = NULL;
114 const char *val = NULL;
115 const char *note = NULL;
116 const char *name = NULL;
117 request_rec *m = r;
119 /* find the first redirect */
120 while (m->prev) {
121 m = m->prev;
123 /* find the main request */
124 while (m->main) {
125 m = m->main;
128 /* is our session in a cookie? */
129 if (conf->name2_set) {
130 name = conf->name2;
132 else if (conf->name_set) {
133 name = conf->name;
135 else {
136 return DECLINED;
139 /* first look in the notes */
140 note = apr_pstrcat(r->pool, MOD_SESSION_COOKIE, name, NULL);
141 zz = (session_rec *)apr_table_get(m->notes, note);
142 if (zz) {
143 *z = zz;
144 return OK;
147 /* otherwise, try parse the cookie */
148 ap_cookie_read(r, name, &val, conf->remove);
150 /* create a new session and return it */
151 zz = (session_rec *) apr_pcalloc(r->pool, sizeof(session_rec));
152 zz->pool = r->pool;
153 zz->entries = apr_table_make(r->pool, 10);
154 zz->encoded = val;
155 zz->uuid = (apr_uuid_t *) apr_pcalloc(r->pool, sizeof(apr_uuid_t));
156 *z = zz;
158 /* put the session in the notes so we don't have to parse it again */
159 apr_table_setn(m->notes, note, (char *)zz);
161 return OK;
167 static void *create_session_cookie_dir_config(apr_pool_t * p, char *dummy)
169 session_cookie_dir_conf *new =
170 (session_cookie_dir_conf *) apr_pcalloc(p, sizeof(session_cookie_dir_conf));
172 return (void *) new;
175 static void *merge_session_cookie_dir_config(apr_pool_t * p, void *basev, void *addv)
177 session_cookie_dir_conf *new = (session_cookie_dir_conf *) apr_pcalloc(p, sizeof(session_cookie_dir_conf));
178 session_cookie_dir_conf *add = (session_cookie_dir_conf *) addv;
179 session_cookie_dir_conf *base = (session_cookie_dir_conf *) basev;
181 new->name = (add->name_set == 0) ? base->name : add->name;
182 new->name_attrs = (add->name_set == 0) ? base->name_attrs : add->name_attrs;
183 new->name_set = add->name_set || base->name_set;
184 new->name2 = (add->name2_set == 0) ? base->name2 : add->name2;
185 new->name2_attrs = (add->name2_set == 0) ? base->name2_attrs : add->name2_attrs;
186 new->name2_set = add->name2_set || base->name2_set;
187 new->remove = (add->remove_set == 0) ? base->remove : add->remove;
188 new->remove_set = add->remove_set || base->remove_set;
190 return new;
194 * Sanity check a given string that it exists, is not empty,
195 * and does not contain special characters.
197 static const char *check_string(cmd_parms * cmd, const char *string)
199 if (!string || !*string || ap_strchr_c(string, '=') || ap_strchr_c(string, '&')) {
200 return apr_pstrcat(cmd->pool, cmd->directive->directive,
201 " cannot be empty, or contain '=' or '&'.",
202 NULL);
204 return NULL;
207 static const char *set_cookie_name(cmd_parms * cmd, void *config, const char *args)
209 char *last;
210 char *line = apr_pstrdup(cmd->pool, args);
211 session_cookie_dir_conf *conf = (session_cookie_dir_conf *) config;
212 char *cookie = apr_strtok(line, " \t", &last);
213 conf->name = cookie;
214 conf->name_set = 1;
215 while (apr_isspace(*last)) {
216 last++;
218 conf->name_attrs = last;
219 return check_string(cmd, cookie);
222 static const char *set_cookie_name2(cmd_parms * cmd, void *config, const char *args)
224 char *last;
225 char *line = apr_pstrdup(cmd->pool, args);
226 session_cookie_dir_conf *conf = (session_cookie_dir_conf *) config;
227 char *cookie = apr_strtok(line, " \t", &last);
228 conf->name2 = cookie;
229 conf->name2_set = 1;
230 while (apr_isspace(*last)) {
231 last++;
233 conf->name2_attrs = last;
234 return check_string(cmd, cookie);
237 static const char *
238 set_remove(cmd_parms * parms, void *dconf, int flag)
240 session_cookie_dir_conf *conf = dconf;
242 conf->remove = flag;
243 conf->remove_set = 1;
245 return NULL;
248 static const command_rec session_cookie_cmds[] =
250 AP_INIT_RAW_ARGS("SessionCookieName", set_cookie_name, NULL, RSRC_CONF|OR_AUTHCFG,
251 "The name of the RFC2109 cookie carrying the session"),
252 AP_INIT_RAW_ARGS("SessionCookieName2", set_cookie_name2, NULL, RSRC_CONF|OR_AUTHCFG,
253 "The name of the RFC2965 cookie carrying the session"),
254 AP_INIT_FLAG("SessionCookieRemove", set_remove, NULL, RSRC_CONF|OR_AUTHCFG,
255 "Set to 'On' to remove the session cookie from the headers "
256 "and hide the cookie from a backend server or process"),
257 {NULL}
260 static void register_hooks(apr_pool_t * p)
262 ap_hook_session_load(session_cookie_load, NULL, NULL, APR_HOOK_MIDDLE);
263 ap_hook_session_save(session_cookie_save, NULL, NULL, APR_HOOK_MIDDLE);
266 module AP_MODULE_DECLARE_DATA session_cookie_module =
268 STANDARD20_MODULE_STUFF,
269 create_session_cookie_dir_config, /* dir config creater */
270 merge_session_cookie_dir_config, /* dir merger --- default is to
271 * override */
272 NULL, /* server config */
273 NULL, /* merge server config */
274 session_cookie_cmds, /* command apr_table_t */
275 register_hooks /* register hooks */