2 * Copyright (C) 2005 QSDN,Inc. All rights reserved.
3 * Copyright (C) 2005 Atsushi Konno All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include "chxj_cookie.h"
19 #include "chxj_url_encode.h"
20 #include "chxj_apply_convrule.h"
26 #include "apr_base64.h"
28 static char* s_get_hostname_from_url(request_rec* r, char* value);
29 static char* s_cut_until_end_hostname(request_rec*, char* value);
35 chxj_save_cookie(request_rec* r)
38 apr_array_header_t* headers;
39 apr_table_entry_t* hentryp;
46 unsigned char* md5_value;
49 mod_chxj_config* dconf;
50 chxjconvrule_entry* entryp;
52 apr_table_t* new_cookie_table;
58 DBG(r, "start chxj_save_cookie()");
60 cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t));
61 cookie->cookie_id = NULL;
65 dconf = ap_get_module_config(r->per_dir_config, &chxj_module);
66 entryp = chxj_apply_convrule(r, dconf->convrules);
68 DBG(r, "end chxj_save_cookie() no pattern");
71 if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) {
72 DBG(r, "end chxj_save_cookie() CookieOff");
77 headers = (apr_array_header_t*)apr_table_elts(r->headers_out);
78 hentryp = (apr_table_entry_t*)headers->elts;
81 new_cookie_table = apr_table_make(r->pool, 0);
83 for (ii=0; ii<headers->nelts; ii++) {
84 if (strcasecmp(hentryp[ii].key, "Set-Cookie") == 0) {
85 DBG(r, "=====================================");
86 DBG2(r, "cookie=[%s:%s]", hentryp[ii].key, hentryp[ii].val);
92 buff = apr_pstrdup(r->pool, hentryp[ii].val);
93 val = strchr(buff, '=');
97 apr_table_add(new_cookie_table, key, val);
101 DBG(r, "=====================================");
106 * check input parameters
108 old_cookie_id = (char*)apr_table_get(r->headers_in, "CHXJ_COOKIE_ID");
110 old_cookie = chxj_load_cookie(r, old_cookie_id);
111 if (old_cookie && old_cookie->cookie_headers) {
112 hentryp = (apr_table_entry_t*)old_cookie->cookie_headers->elts;
113 for (ii=0; ii<old_cookie->cookie_headers->nelts; ii++) {
114 if (hentryp[ii].key && apr_table_get(new_cookie_table, hentryp[ii].key) == NULL) {
115 apr_table_setn(new_cookie_table, hentryp[ii].key, hentryp[ii].val);
119 chxj_delete_cookie(r, old_cookie_id);
128 file = chxj_cookie_db_lock(r);
130 ERR(r, "mod_chxj: Can't lock cookie db");
136 retval = apr_dbm_open_ex(&f,
142 if (retval != APR_SUCCESS) {
143 ERR2(r, "could not open dbm (type %s) auth file: %s", "default", "/tmp/cookie.db");
144 chxj_cookie_db_unlock(r, file);
149 uuid_string = apr_palloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1);
150 memset(uuid_string, 0, APR_UUID_FORMATTED_LENGTH + 1);
151 apr_uuid_format(uuid_string, &uuid);;
153 md5_value = (unsigned char*)apr_palloc(r->pool, APR_MD5_DIGESTSIZE + 1);
154 memset(md5_value, 0, APR_MD5_DIGESTSIZE + 1);
155 retval = apr_md5(md5_value,
156 (const char*)uuid_string, (apr_size_t)APR_UUID_FORMATTED_LENGTH);
157 if (retval != APR_SUCCESS) {
158 ERR(r, "md5 failed.");
162 cookie->cookie_id = apr_palloc(r->pool, apr_base64_encode_len(APR_MD5_DIGESTSIZE)+1);
163 memset(cookie->cookie_id, 0, APR_MD5_DIGESTSIZE+1);
164 apr_base64_encode(cookie->cookie_id, (char*)md5_value, APR_MD5_DIGESTSIZE);
166 DBG1(r, "cookie->cookie_id=[%s]", cookie->cookie_id);
168 cookie->cookie_id = chxj_url_encode(r,cookie->cookie_id);
170 DBG1(r, "cookie->cookie_id=[%s]", cookie->cookie_id);
176 dbmkey.dptr = cookie->cookie_id;
177 dbmkey.dsize = strlen(cookie->cookie_id);
182 cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(new_cookie_table);
183 store_string = apr_palloc(r->pool, 1);
185 hentryp = (apr_table_entry_t*)cookie->cookie_headers->elts;
187 for (ii=0; ii<cookie->cookie_headers->nelts; ii++) {
188 if (ii) store_string = apr_pstrcat(r->pool,
193 store_string = apr_pstrcat(r->pool,
200 dbmval.dptr = store_string;
201 dbmval.dsize = strlen(store_string);
206 retval = apr_dbm_store(f, dbmkey, dbmval);
207 if (retval != APR_SUCCESS) {
208 ERR1(r, "Cannot store SSL session to DBM file `%s'","/tmp/cookie.db");
215 chxj_cookie_db_unlock(r, file);
217 DBG(r, "end chxj_save_cookie()");
224 * @return loaded data.
227 chxj_load_cookie(request_rec* r, char* cookie_id)
233 mod_chxj_global_config* gconf;
234 mod_chxj_config* dconf;
235 chxjconvrule_entry* entryp;
238 apr_table_t* load_cookie_table;
247 DBG1(r, "start chxj_load_cookie() cookie_id=[%s]", cookie_id);
249 cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t));
250 cookie->cookie_headers = NULL;
251 cookie->cookie_id = apr_pstrdup(r->pool, cookie_id);
253 gconf = ap_get_module_config(r->server->module_config, &chxj_module);
254 dconf = ap_get_module_config(r->per_dir_config, &chxj_module);
255 entryp = chxj_apply_convrule(r, dconf->convrules);
257 DBG(r, "end chxj_load_cookie() no pattern");
260 if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) {
261 DBG(r, "end chxj_load_cookie() CookieOff");
266 file = chxj_cookie_db_lock(r);
268 ERR(r, "mod_chxj: Can't lock cookie db");
272 retval = apr_dbm_open_ex(&f,
278 if (retval != APR_SUCCESS) {
279 ERR2(r, "could not open dbm (type %s) auth file: %s", "default", "/tmp/cookie.db");
286 dbmkey.dptr = apr_pstrdup(r->pool, cookie->cookie_id);
287 dbmkey.dsize = strlen(dbmkey.dptr);
288 if (apr_dbm_exists(f, dbmkey)) {
290 retval = apr_dbm_fetch(f, dbmkey, &dbmval);
291 if (retval != APR_SUCCESS) {
292 ERR2(r, "could not fetch dbm (type %s) auth file: %s", "default", "/tmp/cookie.db");
295 load_cookie_table = apr_table_make(r->pool, 0);
296 load_string = apr_palloc(r->pool, dbmval.dsize+1);
298 memset(load_string, 0, dbmval.dsize+1);
299 memcpy(load_string, dbmval.dptr, dbmval.dsize);
301 pair = apr_strtok(load_string, "\n", &pstat);
305 DBG1(r, "Cookie:[%s]", pair);
308 tmp_pair = apr_pstrdup(r->pool, pair);
309 val = strchr(tmp_pair, '=');
313 apr_table_add(load_cookie_table, key, val);
315 apr_table_setn(r->headers_in, "Cookie", pair);
318 cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(load_cookie_table);
321 * save cookie_id to request header.
323 apr_table_setn(r->headers_in, "CHXJ_COOKIE_ID", cookie->cookie_id);
326 chxj_cookie_db_unlock(r, file);
327 DBG(r, "end chxj_load_cookie()");
336 chxj_cookie_db_unlock(r, file);
340 DBG(r, "end chxj_load_cookie()");
346 chxj_add_cookie_parameter(request_rec* r, char* value, cookie_t* cookie)
351 DBG1(r, "start chxj_add_cookie_parameter() cookie_id=[%s]", (cookie) ? cookie->cookie_id : NULL);
358 if (!cookie->cookie_id)
361 if (chxj_cookie_check_host(r, value) != 0) {
362 DBG(r, "end chxj_add_cookie_parameter()(check host)");
367 qs = strchr(dst, '?');
369 dst = apr_psprintf(r->pool, "%s&%s=%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id);
372 dst = apr_psprintf(r->pool, "%s?%s=%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id);
375 DBG1(r, "end chxj_add_cookie_parameter() dst=[%s]", dst);
380 DBG(r, "end chxj_add_cookie_parameter() (on_error)");
386 chxj_cookie_check_host(request_rec* r, char* value)
390 DBG1(r, "hostname=[%s]", r->hostname);
392 hostnm = s_get_hostname_from_url(r, value);
394 if (strcasecmp(hostnm, r->hostname) == 0)
404 s_get_hostname_from_url(request_rec* r, char* value)
406 if (!value) return NULL;
408 if (strncasecmp(value, "http://", 7) == 0 )
409 return s_cut_until_end_hostname(r, &value[7]);
411 if (strncasecmp(value, "https://", 8) == 0)
412 return s_cut_until_end_hostname(r, &value[8]);
418 s_cut_until_end_hostname(request_rec* r, char* value)
423 hostnm = sp = apr_pstrdup(r->pool, value);
425 if (*sp == '/'|| *sp == '?') {
434 chxj_cookie_db_lock(request_rec* r)
439 rv = apr_file_open(&file, "/tmp/cookie_db.lock", APR_CREATE|APR_WRITE, APR_OS_DEFAULT, r->pool);
440 if (rv != APR_SUCCESS) {
441 ERR(r, "cookie lock file open failed.");
445 rv = apr_file_lock(file,APR_FLOCK_EXCLUSIVE);
446 if (rv != APR_SUCCESS) {
447 ERR(r, "cookie lock file open failed.");
448 apr_file_close(file);
456 chxj_cookie_db_unlock(request_rec* r, apr_file_t* file)
460 rv = apr_file_unlock(file);
461 if (rv != APR_SUCCESS) {
462 ERR(r, "cookie lock file open failed.");
466 apr_file_close(file);
470 chxj_delete_cookie(request_rec* r, char* cookie_id)
477 DBG(r, "start chxj_delete_cookie()");
479 file = chxj_cookie_db_lock(r);
481 ERR(r, "mod_chxj: Can't lock cookie db");
485 retval = apr_dbm_open_ex(&f,
491 if (retval != APR_SUCCESS) {
492 ERR2(r, "could not open dbm (type %s) auth file: %s", "default", "/tmp/cookie.db");
498 dbmkey.dptr = apr_pstrdup(r->pool, cookie_id);
499 dbmkey.dsize = strlen(dbmkey.dptr);
500 if (apr_dbm_exists(f, dbmkey)) {
501 apr_dbm_delete(f, dbmkey);
504 chxj_cookie_db_unlock(r, file);
506 DBG(r, "end chxj_delete_cookie()");
511 chxj_cookie_db_unlock(r, file);