X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=src%2Fchxj_cookie.c;h=f212eecabe714feb9604b42860b6ab45e4373c18;hb=c4d72b4f93440e225129aee2b79a9710e6cfb79c;hp=655e2455bd16cd5c1f99d1a636b8d13e58d3728e;hpb=a6bdfea8c2303145edb174ca5ab3a83575a53ead;p=modchxj%2Fmod_chxj.git diff --git a/src/chxj_cookie.c b/src/chxj_cookie.c index 655e2455..f212eeca 100644 --- a/src/chxj_cookie.c +++ b/src/chxj_cookie.c @@ -1,6 +1,6 @@ /* + * Copyright (C) 2005-2009 Atsushi Konno All rights reserved. * Copyright (C) 2005 QSDN,Inc. All rights reserved. - * Copyright (C) 2005 Atsushi Konno All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,51 +20,123 @@ #include "chxj_cookie.h" #include "chxj_url_encode.h" #include "chxj_apply_convrule.h" +#include "chxj_str_util.h" + +#include "ap_release.h" #include "apu.h" #include "apr_dbm.h" #include "apr_uuid.h" #include "apr_md5.h" #include "apr_base64.h" +#include "apr_uri.h" +#include "apr_time.h" +#include "apr_date.h" + +#if defined(USE_MYSQL_COOKIE) +# include "chxj_mysql.h" +#endif +#if defined(USE_MEMCACHE_COOKIE) +# include "chxj_memcache.h" +#endif +#include "chxj_dbm.h" + +#define DUMP_HEADERS(X) do { \ + int __ii; \ + apr_array_header_t *__headers = (apr_array_header_t*)apr_table_elts((X)); \ + apr_table_entry_t *__hentryp = (apr_table_entry_t*)__headers->elts; \ + for (__ii=0; __ii<__headers->nelts; __ii++) { \ + DBG(r, "key:[%s] val:[%s]", __hentryp[__ii].key, __hentryp[__ii].val); \ + } \ +} while (0) + + static char* s_get_hostname_from_url(request_rec* r, char* value); static char* s_cut_until_end_hostname(request_rec*, char* value); +static int valid_domain(request_rec *r, const char *value); +static int valid_path(request_rec *r, const char *value); +static int valid_expires(request_rec *r, const char *value); +static int valid_secure(request_rec *r, const char *value); +static int check_valid_cookie_attribute(request_rec *r, const char *pair); +static int check_valid_cookie_attribute_expires_only(request_rec *r, const char *value); + +apr_proc_mutex_t *global_cookie_mutex; + +static char * +alloc_cookie_id(request_rec *r) +{ + char *cookie_id; + char *uuid_string; + unsigned char *md5_value; + apr_uuid_t uuid; + apr_status_t retval; + + apr_uuid_get(&uuid); + uuid_string = apr_palloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1); + memset(uuid_string, 0, APR_UUID_FORMATTED_LENGTH + 1); + apr_uuid_format(uuid_string, &uuid);; + + md5_value = (unsigned char*)apr_palloc(r->pool, APR_MD5_DIGESTSIZE + 1); + memset(md5_value, 0, APR_MD5_DIGESTSIZE + 1); + + retval = apr_md5(md5_value, + (const char*)uuid_string, + APR_UUID_FORMATTED_LENGTH); + if (retval != APR_SUCCESS) { + ERR(r, "md5 failed."); + return NULL; + } + + cookie_id = apr_palloc(r->pool, apr_base64_encode_len(APR_MD5_DIGESTSIZE)+1); + memset(cookie_id, 0, APR_MD5_DIGESTSIZE+1); + apr_base64_encode(cookie_id, (char*)md5_value, APR_MD5_DIGESTSIZE); + + DBG(r, "cookie_id=[%s]", cookie_id); + + cookie_id = chxj_url_encode(r->pool,cookie_id); + + DBG(r, "cookie_id=[%s]", cookie_id); + return cookie_id; +} + /* * */ -cookie_t* -chxj_save_cookie(request_rec* r) +cookie_t * +chxj_save_cookie(request_rec *r) { int ii; - apr_array_header_t* headers; - apr_table_entry_t* hentryp; - apr_status_t retval; - apr_datum_t dbmkey; - apr_datum_t dbmval; - apr_dbm_t* f; - apr_uuid_t uuid; - char* uuid_string; - unsigned char* md5_value; - char* old_cookie_id; - char* store_string; - mod_chxj_config* dconf; - chxjconvrule_entry* entryp; - apr_file_t* file; - apr_table_t* new_cookie_table; + apr_array_header_t *headers; + apr_table_entry_t *hentryp; + apr_array_header_t *err_headers; + apr_table_entry_t *err_hentryp; + char *old_cookie_id; + char *store_string; + mod_chxj_config *dconf; + chxjconvrule_entry *entryp; + apr_table_t *new_cookie_table; int has_cookie = 0; - cookie_t* cookie; - cookie_t* old_cookie; + cookie_t *cookie; + cookie_t *old_cookie; + char *refer_string; + apr_uri_t parsed_uri; + int has_refer; + apr_pool_t *pool; DBG(r, "start chxj_save_cookie()"); - cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t)); + apr_pool_create(&pool, r->pool); + + cookie = (cookie_t*)apr_palloc(pool, sizeof(cookie_t)); cookie->cookie_id = NULL; has_cookie = 0; + has_refer = 0; - dconf = ap_get_module_config(r->per_dir_config, &chxj_module); + dconf = chxj_get_module_config(r->per_dir_config, &chxj_module); entryp = chxj_apply_convrule(r, dconf->convrules); if (! entryp) { DBG(r, "end chxj_save_cookie() no pattern"); @@ -76,34 +148,79 @@ chxj_save_cookie(request_rec* r) } + headers = (apr_array_header_t*)apr_table_elts(r->headers_out); hentryp = (apr_table_entry_t*)headers->elts; + err_headers = (apr_array_header_t*)apr_table_elts(r->err_headers_out); + err_hentryp = (apr_table_entry_t*)err_headers->elts; - new_cookie_table = apr_table_make(r->pool, 0); + new_cookie_table = apr_table_make(pool, 0); for (ii=0; iinelts; ii++) { if (strcasecmp(hentryp[ii].key, "Set-Cookie") == 0) { - DBG(r, "====================================="); - DBG2(r, "cookie=[%s:%s]", hentryp[ii].key, hentryp[ii].val); + DBG(r, "REQ[%X] cookie=[%s:%s]", TO_ADDR(r), hentryp[ii].key, hentryp[ii].val); char* key; char* val; char* buff; - buff = apr_pstrdup(r->pool, hentryp[ii].val); - val = strchr(buff, '='); - if (val) { - key = buff; - *val++ = 0; - apr_table_add(new_cookie_table, key, val); + char *pair = apr_psprintf(pool, "%s:%s", hentryp[ii].key, hentryp[ii].val); + if (check_valid_cookie_attribute_expires_only(r, pair)) { + buff = apr_pstrdup(pool, hentryp[ii].val); + val = strchr(buff, '='); + if (val) { + key = buff; + *val++ = 0; + apr_table_set(new_cookie_table, apr_pstrdup(pool, key), apr_pstrdup(pool, val)); + if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++; + } + has_cookie = 1; } + } + } + for (ii=0; iinelts; ii++) { + if (strcasecmp(err_hentryp[ii].key, "Set-Cookie") == 0) { + DBG(r, "REQ[%X] cookie=[%s:%s]", TO_ADDR(r), err_hentryp[ii].key, err_hentryp[ii].val); - has_cookie = 1; - DBG(r, "====================================="); + char* key; + char* val; + char* buff; + + char *pair = apr_psprintf(pool, "%s:%s", err_hentryp[ii].key, err_hentryp[ii].val); + if (check_valid_cookie_attribute_expires_only(r, pair)) { + buff = apr_pstrdup(pool, err_hentryp[ii].val); + val = strchr(buff, '='); + if (val) { + key = buff; + *val++ = 0; + apr_table_set(new_cookie_table, apr_pstrdup(pool, key), apr_pstrdup(pool, val)); + if (strcasecmp(REFERER_COOKIE_KEY, key) == 0) has_refer++; + } + has_cookie = 1; + } } } apr_table_unset(r->headers_out, "Set-Cookie"); + apr_table_unset(r->err_headers_out, "Set-Cookie"); + + if (! has_refer) { + apr_uri_parse(pool,r->uri, &parsed_uri); + refer_string = apr_psprintf(pool, + "%s://%s%s", + chxj_run_http_scheme(r), + r->hostname, + apr_uri_unparse(pool, + &parsed_uri, + APR_URI_UNP_OMITSITEPART)); + if (r->args && strlen(r->args)) { + refer_string = apr_pstrcat(pool, refer_string, "?", r->args, NULL); + } + apr_table_setn(new_cookie_table, REFERER_COOKIE_KEY, refer_string); + DBG(r, "ADD REFER[%s]", refer_string); + has_cookie++; + } + /* * check input parameters @@ -114,142 +231,125 @@ chxj_save_cookie(request_rec* r) if (old_cookie && old_cookie->cookie_headers) { hentryp = (apr_table_entry_t*)old_cookie->cookie_headers->elts; for (ii=0; iicookie_headers->nelts; ii++) { - if (hentryp[ii].key && apr_table_get(new_cookie_table, hentryp[ii].key) == NULL) { - apr_table_setn(new_cookie_table, hentryp[ii].key, hentryp[ii].val); - has_cookie = 1; + if (hentryp && apr_table_get(new_cookie_table, hentryp[ii].key) == NULL) { + apr_table_add(new_cookie_table, apr_pstrdup(pool, hentryp[ii].key), apr_pstrdup(pool, hentryp[ii].val)); } } - chxj_delete_cookie(r, old_cookie_id); - chxj_delete_cookie_expire(r, old_cookie_id); + if (has_cookie) { + chxj_delete_cookie(r, old_cookie_id); + chxj_delete_cookie_expire(r, old_cookie_id); + } } } - if (! has_cookie) { - DBG(r, "no cookie"); - return NULL; - } - file = chxj_cookie_db_lock(r); - if (! file) { - ERR(r, "mod_chxj: Can't lock cookie db"); - return NULL; - } - - DBG(r, " "); - retval = apr_dbm_open_ex(&f, - "default", - chxj_cookie_db_name_create(r, dconf->cookie_db_dir), - APR_DBM_RWCREATE, - APR_OS_DEFAULT, - r->pool); - if (retval != APR_SUCCESS) { - ERR2(r, "could not open dbm (type %s) auth file: %s", - "default", - chxj_cookie_db_name_create(r,dconf->cookie_db_dir)); - chxj_cookie_db_unlock(r, file); + if (! has_cookie) { + DBG(r, "REQ[%X] end chxj_save_cookie() (no cookie)", (unsigned int)(apr_size_t)r); return NULL; } - apr_uuid_get(&uuid); - uuid_string = apr_palloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1); - memset(uuid_string, 0, APR_UUID_FORMATTED_LENGTH + 1); - apr_uuid_format(uuid_string, &uuid);; - - md5_value = (unsigned char*)apr_palloc(r->pool, APR_MD5_DIGESTSIZE + 1); - memset(md5_value, 0, APR_MD5_DIGESTSIZE + 1); - - retval = apr_md5(md5_value, - (const char*)uuid_string, - (apr_size_t)APR_UUID_FORMATTED_LENGTH); - if (retval != APR_SUCCESS) { - ERR(r, "md5 failed."); - goto on_error; - } - - cookie->cookie_id = apr_palloc(r->pool, apr_base64_encode_len(APR_MD5_DIGESTSIZE)+1); - memset(cookie->cookie_id, 0, APR_MD5_DIGESTSIZE+1); - apr_base64_encode(cookie->cookie_id, (char*)md5_value, APR_MD5_DIGESTSIZE); - - DBG1(r, "cookie->cookie_id=[%s]", cookie->cookie_id); - - cookie->cookie_id = chxj_url_encode(r,cookie->cookie_id); - - DBG1(r, "cookie->cookie_id=[%s]", cookie->cookie_id); - - /* - * create key - */ - - dbmkey.dptr = cookie->cookie_id; - dbmkey.dsize = strlen(cookie->cookie_id); - /* * create val */ cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(new_cookie_table); - store_string = apr_palloc(r->pool, 1); - store_string[0] = 0; hentryp = (apr_table_entry_t*)cookie->cookie_headers->elts; - + apr_size_t store_string_len = 0; for (ii=0; iicookie_headers->nelts; ii++) { - if (ii) store_string = apr_pstrcat(r->pool, - store_string, - "\n", - NULL); + if (ii) store_string_len++; + store_string_len += (strlen(hentryp[ii].key) + strlen(hentryp[ii].val) + 1); + } + store_string = apr_palloc(pool, store_string_len + 1); + memset(store_string, 0, store_string_len + 1); + apr_size_t npos = 0; - store_string = apr_pstrcat(r->pool, - store_string, - hentryp[ii].key, - "=", - hentryp[ii].val, - NULL); + for (ii=0; iicookie_headers->nelts; ii++) { + if (ii) store_string[npos++] = '\n'; + memcpy(&store_string[npos], hentryp[ii].key, strlen(hentryp[ii].key)); + npos += strlen(hentryp[ii].key); + store_string[npos++] = '='; + memcpy(&store_string[npos], hentryp[ii].val, strlen(hentryp[ii].val)); + npos += strlen(hentryp[ii].val); } - dbmval.dptr = store_string; - dbmval.dsize = strlen(store_string); - /* - * store to db - */ - retval = apr_dbm_store(f, dbmkey, dbmval); - if (retval != APR_SUCCESS) { - ERR1(r, "Cannot store Cookie data to DBM file `%s'", - chxj_cookie_db_name_create(r, dconf->cookie_db_dir)); - goto on_error; + if (old_cookie_id && IS_COOKIE_LAZY(dconf)) { + DBG(r, "REQ[%X] LAZY COOKIE save",(unsigned int)(apr_size_t)r); + cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id); + } + else if (old_cookie_id && apr_table_get(r->headers_in, "X-Chxj-Cookie-No-Update")) { + DBG(r, "REQ[%X] NO UPDATE MODE",(unsigned int)(apr_size_t)r); + cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id); + } + else { + if (old_cookie_id && apr_table_get(r->headers_in, "X-Chxj-Forward")) { + DBG(r, "REQ[%X] NO LAZY COOKIE(X-Chxj-Forward) save",(unsigned int)(apr_size_t)r); + cookie->cookie_id = apr_pstrdup(r->pool, old_cookie_id); + } + else { + DBG(r, "REQ[%X] NO LAZY COOKIE save",(unsigned int)(apr_size_t)r); + cookie->cookie_id = alloc_cookie_id(r); + } } - chxj_save_cookie_expire(r, cookie); + DBG(r, "REQ[%X] TYPE:[%d]", (unsigned int)(apr_size_t)r, dconf->cookie_store_type); + + { + int done_proc = 0; +#if defined(USE_MYSQL_COOKIE) + if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) { + if (! chxj_save_cookie_mysql(r, dconf, cookie->cookie_id, store_string)) { + ERR(r, "%s:%d faild: chxj_save_cookie_mysql() cookie_id:[%s]", APLOG_MARK,cookie->cookie_id); + cookie = NULL; + goto on_error; + } + done_proc = 1; + } +#endif +#if defined(USE_MEMCACHE_COOKIE) + if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) { + if (! chxj_save_cookie_memcache(r, dconf, cookie->cookie_id, store_string)) { + ERR(r, "%s:%d failed: chxj_save_cookie_memcache() cookie_id:[%s]", APLOG_MARK, cookie->cookie_id); + cookie = NULL; + goto on_error; + } + done_proc = 1; + } +#endif + if (IS_COOKIE_STORE_DBM(dconf->cookie_store_type) || ! done_proc) { + if (! chxj_save_cookie_dbm(r, dconf, cookie->cookie_id, store_string)) { + ERR(r, "%s:%d failed: chxj_save_cookie_dbm() cookie_id:[%s]", APLOG_MARK, cookie->cookie_id); + cookie = NULL; + goto on_error; + } + } + } + apr_table_unset(r->headers_out, "Set-Cookie"); + apr_table_unset(r->err_headers_out, "Set-Cookie"); + if (cookie) { + chxj_save_cookie_expire(r, cookie); + } on_error: - apr_dbm_close(f); - chxj_cookie_db_unlock(r, file); - - DBG(r, "end chxj_save_cookie()"); + DBG(r, "end chxj_save_cookie()"); return cookie; } + + /* * */ -cookie_t* -chxj_update_cookie(request_rec* r, cookie_t* old_cookie) +cookie_t * +chxj_update_cookie(request_rec *r, cookie_t *old_cookie) { int ii; - apr_array_header_t* headers; - apr_table_entry_t* hentryp; - apr_status_t retval; - apr_datum_t dbmkey; - apr_datum_t dbmval; - apr_dbm_t* f; - apr_uuid_t uuid; - char* uuid_string; - unsigned char* md5_value; - char* store_string; - mod_chxj_config* dconf; - chxjconvrule_entry* entryp; - apr_file_t* file; - cookie_t* cookie; + apr_array_header_t *headers; + apr_table_entry_t *hentryp; + char *store_string; + mod_chxj_config *dconf; + chxjconvrule_entry *entryp; + cookie_t *cookie; DBG(r, "start chxj_update_cookie()"); @@ -258,11 +358,10 @@ chxj_update_cookie(request_rec* r, cookie_t* old_cookie) return NULL; } - cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t)); + cookie = (cookie_t *)apr_palloc(r->pool, sizeof(cookie_t)); cookie->cookie_id = NULL; - - dconf = ap_get_module_config(r->per_dir_config, &chxj_module); + dconf = chxj_get_module_config(r->per_dir_config, &chxj_module); entryp = chxj_apply_convrule(r, dconf->convrules); if (! entryp) { DBG(r, "end chxj_update_cookie() no pattern"); @@ -273,72 +372,21 @@ chxj_update_cookie(request_rec* r, cookie_t* old_cookie) return NULL; } - headers = (apr_array_header_t*)apr_table_elts(r->headers_out); hentryp = (apr_table_entry_t*)headers->elts; - chxj_delete_cookie(r, old_cookie->cookie_id); chxj_delete_cookie_expire(r, old_cookie->cookie_id); - file = chxj_cookie_db_lock(r); - if (! file) { - ERR(r, "mod_chxj: Can't lock cookie db"); - return NULL; + if (IS_COOKIE_LAZY(dconf)) { + DBG(r, "LAZY MODE"); + cookie->cookie_id = apr_pstrdup(r->pool, old_cookie->cookie_id); } - - DBG(r, " "); - - retval = apr_dbm_open_ex(&f, - "default", - chxj_cookie_db_name_create(r, dconf->cookie_db_dir), - APR_DBM_RWCREATE, - APR_OS_DEFAULT, - r->pool); - if (retval != APR_SUCCESS) { - ERR2(r, "could not open dbm (type %s) auth file: %s", - "default", - chxj_cookie_db_name_create(r,dconf->cookie_db_dir)); - chxj_cookie_db_unlock(r, file); - return NULL; - } - DBG(r, " "); - - apr_uuid_get(&uuid); - uuid_string = apr_palloc(r->pool, APR_UUID_FORMATTED_LENGTH + 1); - memset(uuid_string, 0, APR_UUID_FORMATTED_LENGTH + 1); - apr_uuid_format(uuid_string, &uuid);; - - md5_value = (unsigned char*)apr_palloc(r->pool, APR_MD5_DIGESTSIZE + 1); - memset(md5_value, 0, APR_MD5_DIGESTSIZE + 1); - - retval = apr_md5(md5_value, - (const char*)uuid_string, - (apr_size_t)APR_UUID_FORMATTED_LENGTH); - if (retval != APR_SUCCESS) { - ERR(r, "md5 failed."); - goto on_error; + else { + DBG(r, "NO LAZY MODE"); + cookie->cookie_id = alloc_cookie_id(r); } - DBG(r, " "); - - cookie->cookie_id = apr_palloc(r->pool, apr_base64_encode_len(APR_MD5_DIGESTSIZE)+1); - memset(cookie->cookie_id, 0, APR_MD5_DIGESTSIZE+1); - apr_base64_encode(cookie->cookie_id, (char*)md5_value, APR_MD5_DIGESTSIZE); - cookie->cookie_id = chxj_url_encode(r,cookie->cookie_id); - - DBG(r, " "); - - /* - * create key - */ - - dbmkey.dptr = cookie->cookie_id; - dbmkey.dsize = strlen(cookie->cookie_id); - - /* - * create val - */ cookie->cookie_headers = old_cookie->cookie_headers; store_string = apr_palloc(r->pool, 1); store_string[0] = 0; @@ -350,7 +398,7 @@ chxj_update_cookie(request_rec* r, cookie_t* old_cookie) "\n", NULL); - DBG2(r, "OLD COOKIE VALUE=[%s][%s]", hentryp[ii].key, hentryp[ii].val); + DBG(r, "OLD COOKIE VALUE=[%s][%s]", hentryp[ii].key, hentryp[ii].val); store_string = apr_pstrcat(r->pool, store_string, hentryp[ii].key, @@ -358,17 +406,34 @@ chxj_update_cookie(request_rec* r, cookie_t* old_cookie) hentryp[ii].val, NULL); } - dbmval.dptr = store_string; - dbmval.dsize = strlen(store_string); - /* - * store to db - */ - retval = apr_dbm_store(f, dbmkey, dbmval); - if (retval != APR_SUCCESS) { - ERR1(r, "Cannot store Cookie data to DBM file `%s'", - chxj_cookie_db_name_create(r, dconf->cookie_db_dir)); - goto on_error; + { + int done_proc = 0; +#if defined(USE_MYSQL_COOKIE) + if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) { + if (!chxj_update_cookie_mysql(r, dconf, cookie->cookie_id, store_string)) { + ERR(r, "failed: chxj_update_cookie_mysql() cookie_id:[%s]", cookie->cookie_id); + goto on_error; + } + done_proc = 1; + } +#endif + +#if defined(USE_MEMCACHE_COOKIE) + if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) { + if (! chxj_update_cookie_memcache(r, dconf, cookie->cookie_id, store_string)) { + ERR(r, "failed: chxj_update_cookie_memcache() cookie_id:[%s]", cookie->cookie_id); + goto on_error; + } + done_proc = 1; + } +#endif + if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) { + if (! chxj_update_cookie_dbm(r, dconf, cookie->cookie_id, store_string)) { + ERR(r, "failed: chxj_update_cookie_dbm() cookie_id:[%s]", cookie->cookie_id); + goto on_error; + } + } } chxj_save_cookie_expire(r, cookie); @@ -377,9 +442,6 @@ chxj_update_cookie(request_rec* r, cookie_t* old_cookie) on_error: - apr_dbm_close(f); - chxj_cookie_db_unlock(r, file); - DBG(r, "end chxj_update_cookie()"); return cookie; } @@ -389,94 +451,81 @@ on_error: * * @return loaded data. */ -cookie_t* -chxj_load_cookie(request_rec* r, char* cookie_id) +cookie_t * +chxj_load_cookie(request_rec *r, char *cookie_id) { - apr_status_t retval; - apr_datum_t dbmkey; - apr_datum_t dbmval; - apr_dbm_t* f; - mod_chxj_config* dconf; - chxjconvrule_entry* entryp; - apr_file_t* file; - cookie_t* cookie; - apr_table_t* load_cookie_table; - char* load_string; - char* pstat; - char* key; - char* val; - char* pair; - - DBG(r, "========================================================"); - DBG(r, "========================================================"); - DBG(r, "========================================================"); - DBG(r, "========================================================"); - DBG1(r, "start chxj_load_cookie() cookie_id=[%s]", cookie_id); + mod_chxj_config *dconf; + chxjconvrule_entry *entryp; + cookie_t *cookie; + apr_table_t *load_cookie_table; + char *load_string = NULL; + char *pstat; + char *key; + char *val; + char *pair; + char *header_cookie; + + DBG(r, "REQ[%X] start chxj_load_cookie() cookie_id=[%s]", TO_ADDR(r), cookie_id); chxj_cookie_expire_gc(r); cookie = (cookie_t*)apr_palloc(r->pool, sizeof(cookie_t)); cookie->cookie_headers = NULL; - cookie->cookie_id = apr_pstrdup(r->pool, cookie_id); + cookie->cookie_id = chxj_url_decode(r->pool, apr_pstrdup(r->pool, cookie_id)); + cookie->cookie_id = chxj_url_encode(r->pool, cookie->cookie_id); + - dconf = ap_get_module_config(r->per_dir_config, &chxj_module); + dconf = chxj_get_module_config(r->per_dir_config, &chxj_module); entryp = chxj_apply_convrule(r, dconf->convrules); if (! entryp) { - DBG(r, "end chxj_load_cookie() no pattern"); + DBG(r, "REQ[%X] end chxj_load_cookie() no pattern", TO_ADDR(r)); goto on_error0; } if (! (entryp->action & CONVRULE_COOKIE_ON_BIT)) { - DBG(r, "end chxj_load_cookie() CookieOff"); + DBG(r, "REQ[%X] end chxj_load_cookie() CookieOff", TO_ADDR(r)); goto on_error0; } + load_cookie_table = apr_table_make(r->pool, 0); - - file = chxj_cookie_db_lock(r); - if (! file) { - ERR(r, "mod_chxj: Can't lock cookie db"); - goto on_error0; - } - - retval = apr_dbm_open_ex(&f, - "default", - chxj_cookie_db_name_create(r, dconf->cookie_db_dir), - APR_DBM_RWCREATE, - APR_OS_DEFAULT, - r->pool); - if (retval != APR_SUCCESS) { - ERR2(r, - "could not open dbm (type %s) auth file: %s", - "default", - chxj_cookie_db_name_create(r, dconf->cookie_db_dir)); - goto on_error1; - } - - /* - * create key - */ - dbmkey.dptr = apr_pstrdup(r->pool, cookie->cookie_id); - dbmkey.dsize = strlen(dbmkey.dptr); - if (apr_dbm_exists(f, dbmkey)) { - - retval = apr_dbm_fetch(f, dbmkey, &dbmval); - if (retval != APR_SUCCESS) { - ERR2(r, - "could not fetch dbm (type %s) auth file: %s", "default", - chxj_cookie_db_name_create(r, dconf->cookie_db_dir)); - goto on_error2; + { + int done_proc = 0; +#if defined(USE_MYSQL_COOKIE) + if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) { + if (! (load_string = chxj_load_cookie_mysql(r, dconf, cookie->cookie_id))) { + ERR(r, "%s:%d failed: chxj_load_cookie_mysql() cookie_id:[%s]", APLOG_MARK, cookie_id); + goto on_error0; + } + done_proc = 1; } - load_cookie_table = apr_table_make(r->pool, 0); - load_string = apr_palloc(r->pool, dbmval.dsize+1); +#endif +#if defined(USE_MEMCACHE_COOKIE) + if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) { + if (! (load_string = chxj_load_cookie_memcache(r, dconf, cookie->cookie_id))) { + ERR(r, "%s:%d failed: chxj_load_cookie_memcache() cookie_id:[%s]", APLOG_MARK,cookie_id); + goto on_error0; + } + done_proc = 1; + } +#endif + if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) { + if (! (load_string = chxj_load_cookie_dbm(r, dconf, cookie->cookie_id))) { + ERR(r, "%s:%d failed: chxj_load_cookie_dbm() cookie_id:[%s]", APLOG_MARK,cookie_id); + goto on_error0; + } + } + } - memset(load_string, 0, dbmval.dsize+1); - memcpy(load_string, dbmval.dptr, dbmval.dsize); + if (load_string) { + DBG(r, "REQ[%X] load_string=[%s]", TO_ADDR(r), load_string); + header_cookie = apr_palloc(r->pool, 1); + header_cookie[0] = 0; for (;;) { - char* tmp_sem; + char *tmp_sem; + char *tmp_pair; pair = apr_strtok(load_string, "\n", &pstat); load_string = NULL; if (!pair) break; - DBG1(r, "Cookie:[%s]", pair); - char* tmp_pair; + DBG(r, "REQ[%X] Cookie:[%s]", TO_ADDR(r), pair); tmp_pair = apr_pstrdup(r->pool, pair); val = strchr(tmp_pair, '='); @@ -484,56 +533,288 @@ chxj_load_cookie(request_rec* r, char* cookie_id) key = tmp_pair; *val++ = 0; apr_table_add(load_cookie_table, key, val); + DBG(r, "REQ[%X] ADD key:[%s] val:[%s]", TO_ADDR(r), key, val); } - tmp_sem = strchr(pair, ';'); + tmp_pair = apr_pstrdup(r->pool, pair); + tmp_sem = strchr(tmp_pair, ';'); if (tmp_sem) *tmp_sem = '\0'; - apr_table_setn(r->headers_in, "Cookie", pair); + if (check_valid_cookie_attribute(r, pair)) { + if (strlen(header_cookie)) + header_cookie = apr_pstrcat(r->pool, header_cookie, ";", NULL); + + header_cookie = apr_pstrcat(r->pool, header_cookie, tmp_pair, NULL); + } + } + if (strlen(header_cookie)) { + DBG(r, "REQ[%X] ADD COOKIE to REQUEST HEADER:[%s]", TO_ADDR(r), header_cookie); + apr_table_add(r->headers_in, "Cookie", header_cookie); } cookie->cookie_headers = (apr_array_header_t*)apr_table_elts(load_cookie_table); + + if (apr_table_get(r->headers_in, "referer") == NULL) { + apr_table_setn(r->headers_in, + "referer", + apr_table_get(load_cookie_table, REFERER_COOKIE_KEY)); + } /* * save cookie_id to request header. */ apr_table_setn(r->headers_in, "CHXJ_COOKIE_ID", cookie->cookie_id); } - apr_dbm_close(f); - chxj_cookie_db_unlock(r, file); - DBG(r, "end chxj_load_cookie()"); - DBG(r, "========================================================"); - DBG(r, "========================================================"); - DBG(r, "========================================================"); - DBG(r, "========================================================"); + DBG(r, "REQ[%X] end chxj_load_cookie()", TO_ADDR(r)); return cookie; -on_error2: - apr_dbm_close(f); - -on_error1: - chxj_cookie_db_unlock(r, file); - on_error0: - DBG(r, "end chxj_load_cookie()"); - DBG(r, "========================================================"); - DBG(r, "========================================================"); - DBG(r, "========================================================"); - DBG(r, "========================================================"); + DBG(r, "REQ[%X] end chxj_load_cookie()", TO_ADDR(r)); return NULL; } +static int +check_valid_cookie_attribute(request_rec *r, const char *value) +{ + char *pstat; + char *pair; + char *first_pair; + char *domain_pair; + char *path_pair; + char *expire_pair; + char *secure_pair; + char *p; + + DBG(r, "start check_valid_cookie_attribute() value:[%s]", value); + + domain_pair = path_pair = expire_pair = secure_pair = NULL; + p = apr_pstrdup(r->pool, value); + + /* pass first pair */ + first_pair = apr_strtok(p, ";", &pstat); + + for (;;) { + pair = apr_strtok(NULL, ";", &pstat); + if (! pair) break; + pair = qs_trim_string(r->pool, pair); + if (STRNCASEEQ('d','D',"domain", pair, sizeof("domain")-1)) { + domain_pair = apr_pstrdup(r->pool, pair); + } + else if (STRNCASEEQ('p','P',"path", pair, sizeof("path")-1)) { + path_pair = apr_pstrdup(r->pool, pair); + } + else if (STRNCASEEQ('e','E',"expires", pair, sizeof("expires")-1)) { + expire_pair = apr_pstrdup(r->pool, pair); + } + else if (STRNCASEEQ('s','S',"secure", pair, sizeof("secure")-1)) { + secure_pair = apr_pstrdup(r->pool, pair); + } + } + + if (domain_pair) { + if (!valid_domain(r, domain_pair)) { + DBG(r, "invalid domain. domain_pair:[%s]", domain_pair); + return CHXJ_FALSE; + } + } + if (path_pair) { + if (!valid_path(r, path_pair)) { + DBG(r, "invalid path. path_pair:[%s]", path_pair); + return CHXJ_FALSE; + } + } + if (expire_pair) { + if (!valid_expires(r, expire_pair)) { + DBG(r, "invalid expire. expire_pair:[%s]", expire_pair); + return CHXJ_FALSE; + } + } + if (secure_pair) { + if (!valid_secure(r, secure_pair)) { + DBG(r, "invalid secure. secure_pair:[%s]", secure_pair); + return CHXJ_FALSE; + } + } + DBG(r, "end check_valid_cookie_attribute() value:[%s]", value); + return CHXJ_TRUE; +} + + +static int +check_valid_cookie_attribute_expires_only(request_rec *r, const char *value) +{ + char *pstat; + char *pair; + char *first_pair; + char *expire_pair = NULL; + char *p; + + DBG(r, "REQ[%X] start check_valid_cookie_attribute_expires_only() value:[%s]", (unsigned int)(apr_size_t)r, value); + + expire_pair = NULL; + p = apr_pstrdup(r->pool, value); + + /* pass first pair */ + first_pair = apr_strtok(p, ";", &pstat); + + for (;;) { + pair = apr_strtok(NULL, ";", &pstat); + if (! pair) break; + pair = qs_trim_string(r->pool, pair); + if (STRNCASEEQ('e','E',"expires", pair, sizeof("expires")-1)) { + expire_pair = apr_pstrdup(r->pool, pair); + } + } + + if (expire_pair) { + if (!valid_expires(r, expire_pair)) { + DBG(r, "REQ[%X] invalid expire. expire_pair:[%s]", (unsigned int)(apr_size_t)r, expire_pair); + return CHXJ_FALSE; + } + } + DBG(r, "REQ[%X] end check_valid_cookie_attribute_expires_only() value:[%s]", (unsigned int)(apr_size_t)r, value); + return CHXJ_TRUE; +} + + +static int +valid_domain(request_rec *r, const char *value) +{ + int len; + char *name; + char *val; + char *pstat; + char *p = apr_pstrdup(r->pool, value); + char *host = (char *)apr_table_get(r->headers_in, HTTP_HOST); + + DBG(r, "REQ[%X] start valid_domain() value:[%s]", TO_ADDR(r), value); + if (!host) { + DBG(r, "REQ[%X] end valid_domain() value:[%s]", TO_ADDR(r), value); + return CHXJ_TRUE; + } + DBG(r, "REQ[%X] host:[%s]", TO_ADDR(r), host); + host = s_cut_until_end_hostname(r, apr_pstrdup(r->pool, host)); + DBG(r, "REQ[%X] host:[%s](after s_cut_until_end_hostname())", TO_ADDR(r), host); + + name = apr_strtok(p,"=", &pstat); + name = qs_trim_string(r->pool, name); + val = apr_strtok(NULL, "=", &pstat); + val = qs_trim_string(r->pool, val); + len = strlen(host); + if (len) { + if (chxj_strcasenrcmp(r->pool, host, val, strlen(val))) { + DBG(r, "REQ[%X] not match domain. host domain:[%s] vs value:[%s]", TO_ADDR(r), host, val); + DBG(r, "REQ[%X] end valid_domain() value:[%s]", TO_ADDR(r), value); + return CHXJ_FALSE; + } + } + DBG(r, "REQ[%X] end valid_domain() value:[%s]", TO_ADDR(r), value); + return CHXJ_TRUE; +} + + +static int +valid_path(request_rec *r, const char *value) +{ + char *p = apr_pstrdup(r->pool, value); + char *uri; + char *tmp; + char *name; + char *val; + char *pstat; + + DBG(r, "start valid_path() unparsed_uri:[%s] value:[%s]", r->unparsed_uri, value); + if (chxj_starts_with(r->unparsed_uri, "http://")) { + uri = strchr(&r->unparsed_uri[sizeof("http://")], '/'); + if (uri != NULL) { + uri = apr_pstrdup(r->pool, uri); + } + } + else if (chxj_starts_with(r->unparsed_uri, "https://")) { + uri = strchr(&r->unparsed_uri[sizeof("https://")], '/'); + if (uri != NULL) { + uri = apr_pstrdup(r->pool, uri); + } + } + else if (chxj_starts_with(r->unparsed_uri, "/")) { + uri = apr_pstrdup(r->pool, r->unparsed_uri); + } + else { + uri = apr_pstrdup(r->pool, "/"); + } + + if ((tmp = strchr(uri, '?'))) { + *tmp = '\0'; + } + DBG(r, "uri=[%s]", uri); + name = apr_strtok(p, "=", &pstat); + val = apr_strtok(NULL, "=", &pstat); + name = qs_trim_string(r->pool, name); + val = qs_trim_string(r->pool, val); + DBG(r, "name=[%s] val=[%s]", name, val); + + DBG(r, "val:[%s] vs uri:[%s]", val, uri); + if (! chxj_starts_with(uri, val)) { + DBG(r, "end valid_path() unparsed_uri:[%s] value:[%s] (false)", r->unparsed_uri, value); + return CHXJ_FALSE; + } + DBG(r, "end valid_path() unparsed_uri:[%s] value:[%s] (true)", r->unparsed_uri, value); + return CHXJ_TRUE; +} + -char* -chxj_add_cookie_parameter(request_rec* r, char* value, cookie_t* cookie) +static int +valid_expires(request_rec *r, const char *value) { - char* qs; - char* dst; + char *name; + char *val; + char *p = apr_pstrdup(r->pool, value); + char *pstat; + apr_time_t expires; + apr_time_t now; + + DBG(r, "start valid_expire() value:[%s]", value); + name = apr_strtok(p, "=", &pstat); + val = apr_strtok(NULL, "=", &pstat); + DBG(r, "name=[%s] val=[%s]", name, val); + now = apr_time_now(); + expires = chxj_parse_cookie_expires(val); + if (expires < now) { + DBG(r, "end valid_expire() value:[%s] (expired)", value); + return CHXJ_FALSE; + } + + DBG(r, "end valid_expire() value:[%s] (non expired)", value); + return CHXJ_TRUE; +} - DBG1(r, "start chxj_add_cookie_parameter() cookie_id=[%s]", (cookie) ? cookie->cookie_id : NULL); + +static int +valid_secure(request_rec *r, const char *value) +{ + const char *scheme; + DBG(r, "start valid_secure() value:[%s]", value); + scheme = chxj_apache_run_http_scheme(r); + if (strcasecmp("https", scheme)) { + DBG(r, "end valid_secure() value:[%s] (non secure)", value); + return CHXJ_FALSE; + } + DBG(r, "end valid_secure() value:[%s] (secure)", value); + return CHXJ_TRUE; +} + + +char * +chxj_add_cookie_parameter(request_rec *r, char *value, cookie_t *cookie) +{ + char *qs; + char *dst; + char *name = ""; + + DBG(r, "REQ[%X] start chxj_add_cookie_parameter() cookie_id=[%s]", TO_ADDR(r), (cookie) ? cookie->cookie_id : NULL); dst = apr_pstrdup(r->pool, value); @@ -544,48 +825,121 @@ chxj_add_cookie_parameter(request_rec* r, char* value, cookie_t* cookie) goto on_error; if (chxj_cookie_check_host(r, value) != 0) { - DBG(r, "end chxj_add_cookie_parameter()(check host)"); + DBG(r, "REQ[%X] end chxj_add_cookie_parameter()(check host)", TO_ADDR(r)); goto on_error; } + qs = strchr(dst, '#'); + if (qs) { + name = apr_pstrdup(r->pool, qs); + *qs = 0; + } + qs = strchr(dst, '?'); if (qs) { - dst = apr_psprintf(r->pool, "%s&%s=%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id); + char *sv_qs = qs; + qs = chxj_delete_chxj_cc_param(r, ++qs); + DBG(r, "REQ[%X] qs:[%s]",TO_ADDR(r), qs); + *sv_qs = 0; + if (qs && strlen(qs)) { + dst = apr_psprintf(r->pool, "%s?%s", dst, qs); + } + } + if (qs) { + dst = apr_psprintf(r->pool, "%s&%s=%s%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id, name); } else { - dst = apr_psprintf(r->pool, "%s?%s=%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id); + dst = apr_psprintf(r->pool, "%s?%s=%s%s", dst, CHXJ_COOKIE_PARAM, cookie->cookie_id, name); + } + + DBG(r, "REQ[%X] end chxj_add_cookie_parameter() dst=[%s]", TO_ADDR(r), dst); + + return dst; + +on_error: + DBG(r, "REQ[%X] end chxj_add_cookie_parameter() (on_error)", TO_ADDR(r)); + return dst; +} + + +char * +chxj_add_cookie_no_update_parameter(request_rec *r, char *value) +{ + char *qs; + char *dst; + char *name = ""; + + DBG(r, "REQ[%X] start chxj_add_cookie_no_update_parameter()", (unsigned int)(apr_size_t)r); + + if (! value || ! *value) { + DBG(r, "REQ[%X] end chxj_add_cookie_parameter()(void value)", (unsigned int)(apr_size_t)r); + return apr_pstrdup(r->pool, ""); } - DBG1(r, "end chxj_add_cookie_parameter() dst=[%s]", dst); + dst = apr_pstrdup(r->pool, value); + + if (chxj_cookie_check_host(r, value) != 0) { + DBG(r, "REQ[%X] end chxj_add_cookie_parameter()(check host)", (unsigned int)(apr_size_t)r); + goto on_error; + } + qs = strchr(dst, '#'); + if (qs) { + name = apr_pstrdup(r->pool, qs); + *qs = 0; + } + dst = apr_psprintf(r->pool, "%s%c%s=true%s", dst, (strchr(dst,'?')) ? '&' : '?',CHXJ_COOKIE_NOUPDATE_PARAM, name); + DBG(r, "REQ[%X] end chxj_add_cookie_no_update_parameter() dst=[%s]", (unsigned int)(apr_size_t)r, dst); return dst; on_error: - DBG(r, "end chxj_add_cookie_parameter() (on_error)"); + DBG(r, "REQ[%X] end chxj_add_cookie_no_update_parameter() (on_error)", (unsigned int)(apr_size_t)r); return dst; } int -chxj_cookie_check_host(request_rec* r, char* value) +chxj_cookie_check_host(request_rec *r, char *value) { - char* hostnm; + char *hostnm; + mod_chxj_config *dconf; - DBG1(r, "hostname=[%s]", r->hostname); + DBG(r, "REQ[%X] start chxj_cookie_check_host()", (unsigned int)(apr_size_t)r); + DBG(r, "REQ[%X] hostname=[%s] vs Location:[%s]", (unsigned int)(apr_size_t)r, r->hostname, value); + + dconf = chxj_get_module_config(r->per_dir_config, &chxj_module); hostnm = s_get_hostname_from_url(r, value); if (hostnm) { - if (strcasecmp(hostnm, r->hostname) == 0) - return 0; - else - return 1; + if (dconf->allowed_cookie_domain) { + DBG(r, "REQ[%X] allowed_domain[%s] vs Location:[%s]", (unsigned int)(apr_size_t)r, dconf->allowed_cookie_domain, value); + if (chxj_strcasenrcmp(r->pool, hostnm, dconf->allowed_cookie_domain, strlen(dconf->allowed_cookie_domain))) { + DBG(r, "REQ[%X] end chxj_cookie_check_host() (false/allowed_domain)", (unsigned int)(apr_size_t)r); + return 1; + } + else { + DBG(r, "REQ[%X] end chxj_cookie_check_host() (true/allowed_domain)", (unsigned int)(apr_size_t)r); + return 0; + } + } + else { + if (strcasecmp(hostnm, r->hostname) == 0) { + DBG(r, "REQ[%X] end chxj_cookie_check_host() (true)", (unsigned int)(apr_size_t)r); + return 0; + } + else { + DBG(r, "REQ[%X] end chxj_cookie_check_host() (false)", (unsigned int)(apr_size_t)r); + return 1; + } + } } + DBG(r, "REQ[%X] end chxj_cookie_check_host() (true)", (unsigned int)(apr_size_t)r); return 0; } -static char* -s_get_hostname_from_url(request_rec* r, char* value) +static char * +s_get_hostname_from_url(request_rec *r, char *value) { if (!value) return NULL; @@ -600,15 +954,15 @@ s_get_hostname_from_url(request_rec* r, char* value) } -static char* -s_cut_until_end_hostname(request_rec* r, char* value) +static char * +s_cut_until_end_hostname(request_rec *r, char *value) { - char* sp; - char* hostnm; + char *sp; + char *hostnm; hostnm = sp = apr_pstrdup(r->pool, value); for (;*sp; sp++) { - if (*sp == '/'|| *sp == '?') { + if (*sp == '/'|| *sp == '?' || *sp == ':') { *sp = '\0'; break; } @@ -617,475 +971,285 @@ s_cut_until_end_hostname(request_rec* r, char* value) } -apr_file_t* -chxj_cookie_db_lock(request_rec* r) -{ - apr_file_t* file; - apr_status_t rv; - mod_chxj_config* dconf; - - dconf = (mod_chxj_config*)ap_get_module_config(r->per_dir_config, &chxj_module); - - rv = apr_file_open(&file, - chxj_cookie_db_lock_name_create(r, dconf->cookie_db_dir), - APR_CREATE|APR_WRITE, - APR_OS_DEFAULT, - r->pool); - if (rv != APR_SUCCESS) { - ERR(r, "cookie lock file open failed."); - return NULL; - } - - rv = apr_file_lock(file,APR_FLOCK_EXCLUSIVE); - if (rv != APR_SUCCESS) { - ERR(r, "cookie lock file open failed."); - apr_file_close(file); - return NULL; - } - - return file; -} - void -chxj_cookie_db_unlock(request_rec* r, apr_file_t* file) +chxj_delete_cookie(request_rec *r, const char *cookie_id) { - apr_status_t rv; - - rv = apr_file_unlock(file); - if (rv != APR_SUCCESS) { - ERR(r, "cookie lock file open failed."); - return; - } - - apr_file_close(file); -} - - -void -chxj_delete_cookie(request_rec* r, char* cookie_id) -{ - apr_status_t retval; - apr_datum_t dbmkey; - apr_dbm_t* f; - apr_file_t* file; - mod_chxj_config* dconf; + int done_proc = 0; + mod_chxj_config *dconf; DBG(r, "start chxj_delete_cookie()"); - - file = chxj_cookie_db_lock(r); - if (! file) { - ERR(r, "mod_chxj: Can't lock cookie db"); - goto on_error0; - } - dconf = ap_get_module_config(r->per_dir_config, &chxj_module); - - retval = apr_dbm_open_ex(&f, - "default", - chxj_cookie_db_name_create(r, dconf->cookie_db_dir), - APR_DBM_RWCREATE, - APR_OS_DEFAULT, - r->pool); - if (retval != APR_SUCCESS) { - ERR2(r, - "could not open dbm (type %s) auth file: %s", - "default", - chxj_cookie_db_name_create(r,dconf->cookie_db_dir)); - goto on_error1; - } - - /* - * create key - */ - dbmkey.dptr = apr_pstrdup(r->pool, cookie_id); - dbmkey.dsize = strlen(dbmkey.dptr); - if (apr_dbm_exists(f, dbmkey)) { - apr_dbm_delete(f, dbmkey); + dconf = chxj_get_module_config(r->per_dir_config, &chxj_module); + +#if defined(USE_MYSQL_COOKIE) + if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) { + if (! chxj_delete_cookie_mysql(r, dconf, cookie_id)) { + ERR(r, "failed: chxj_delete_cookie_mysql() cookie_id:[%s]", cookie_id); + DBG(r, "end chxj_delete_cookie()"); + return; + } + done_proc = 1; + } +#endif +#if defined(USE_MEMCACHE_COOKIE) + if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) { + if (! chxj_delete_cookie_memcache(r, dconf, cookie_id)) { + ERR(r, "failed: chxj_delete_cookie_memcache() cookie_id:[%s]", cookie_id); + DBG(r, "end chxj_delete_cookie()"); + return; + } + done_proc = 1; + } +#endif + if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) { + if (! chxj_delete_cookie_dbm(r, dconf, cookie_id)) { + ERR(r, "failed: chxj_delete_cookie_dbm() cookie_id:[%s]", cookie_id); + DBG(r, "end chxj_delete_cookie()"); + return; + } } - apr_dbm_close(f); - chxj_cookie_db_unlock(r, file); DBG(r, "end chxj_delete_cookie()"); - - return; - -on_error1: - chxj_cookie_db_unlock(r, file); - -on_error0: - return; - -} - - -char* -chxj_cookie_db_name_create(request_rec* r, const char* dir) -{ - char* dst; - - if (!dir) { - dst = apr_pstrdup(r->pool, DEFAULT_COOKIE_DB_DIR); - } - else { - dst = apr_pstrdup(r->pool, dir); - } - - if (dst[strlen(dst)-1] != '/') { - dst = apr_pstrcat(r->pool, dst, "/", COOKIE_DB_NAME, NULL); - } - else { - dst = apr_pstrcat(r->pool, dst, COOKIE_DB_NAME, NULL); - } - - return dst; } -char* -chxj_cookie_db_lock_name_create(request_rec* r, const char* dir) -{ - char* dst; - DBG(r, "start chxj_cookie_db_lock_name_create()"); - - if (!dir) { -DBG(r, " "); - dst = apr_pstrdup(r->pool, DEFAULT_COOKIE_DB_DIR); -DBG(r, " "); - } - else { -DBG1(r, " dir=[%x]", (unsigned int)dir); - dst = apr_pstrdup(r->pool, dir); -DBG(r, " "); - } -DBG1(r, "dst[strlen(dst)-1]=[%c]", dst[strlen(dst)-1]); - if (dst[strlen(dst)-1] != '/') { - dst = apr_pstrcat(r->pool, dst, "/", COOKIE_DB_LOCK_NAME, NULL); - } - else { - dst = apr_pstrcat(r->pool, dst, COOKIE_DB_LOCK_NAME, NULL); - } - DBG(r, "end chxj_cookie_db_lock_name_create()"); - return dst; -} /* * */ void -chxj_save_cookie_expire(request_rec* r, cookie_t* cookie) +chxj_save_cookie_expire(request_rec *r, cookie_t *cookie) { - apr_status_t retval; - apr_datum_t dbmkey; - apr_datum_t dbmval; - apr_dbm_t* f; - apr_file_t* file; - mod_chxj_config* dconf; - char* store_string; + int done_proc = 0; + mod_chxj_config *dconf; DBG(r, "start chxj_save_cookie_expire()"); if (!cookie) { DBG(r, "cookie is NULL"); return; } - - dconf = ap_get_module_config(r->per_dir_config, &chxj_module); - if (!dconf) { - DBG(r, "dconf is NULL"); - return; - } - - file = chxj_cookie_expire_db_lock(r); - if (! file) { - ERR(r, "mod_chxj: Can't lock cookie db"); + if (!cookie->cookie_id) { + DBG(r, "cookie->cookie_id is NULL"); return; } - DBG(r, " "); - - retval = apr_dbm_open_ex(&f, - "default", - chxj_cookie_expire_db_name_create(r, dconf->cookie_db_dir), - APR_DBM_RWCREATE, - APR_OS_DEFAULT, - r->pool); - if (retval != APR_SUCCESS) { - ERR2(r, "could not open dbm (type %s) auth file: %s", - "default", - chxj_cookie_expire_db_name_create(r,dconf->cookie_db_dir)); - chxj_cookie_expire_db_unlock(r, file); + dconf = chxj_get_module_config(r->per_dir_config, &chxj_module); + if (!dconf) { + DBG(r, "dconf is NULL"); return; } - /* - * create key - */ - dbmkey.dptr = cookie->cookie_id; - dbmkey.dsize = strlen(cookie->cookie_id); - - /* - * create val - */ - - store_string = apr_psprintf(r->pool, "%d", (int)time(NULL)); - dbmval.dptr = store_string; - dbmval.dsize = strlen(store_string); - - /* - * store to db - */ - retval = apr_dbm_store(f, dbmkey, dbmval); - if (retval != APR_SUCCESS) { - ERR1(r, "Cannot store Cookie data to DBM file `%s'", - chxj_cookie_db_name_create(r, dconf->cookie_db_dir)); +#if defined(USE_MYSQL_COOKIE) + if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) { + if (! chxj_save_cookie_expire_mysql(r, dconf, cookie->cookie_id)) { + ERR(r, "failed: chxj_save_cookie_expire_mysql() cookie_id:[%s]", cookie->cookie_id); + DBG(r, "end chxj_save_cookie_expire()"); + return; + } + done_proc = 1; + } +#endif +#if defined(USE_MEMCACHE_COOKIE) + if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) { + if (! chxj_save_cookie_expire_memcache(r, dconf, cookie->cookie_id)) { + ERR(r, "failed: chxj_save_cookie_expire_memcache() cookie_id:[%s]", cookie->cookie_id); + DBG(r, "end chxj_save_cookie_expire()"); + return; + } + done_proc = 1; + } +#endif + if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) { + if (! chxj_save_cookie_expire_dbm(r, dconf, cookie->cookie_id)) { + ERR(r, "failed: chxj_save_cookie_expire_dbm() cookie_id:[%s]", cookie->cookie_id); + DBG(r, "end chxj_save_cookie_expire()"); + return; + } } - - apr_dbm_close(f); - chxj_cookie_expire_db_unlock(r, file); - DBG(r, "end chxj_save_cookie_expire()"); } -char* -chxj_cookie_expire_db_name_create(request_rec* r, const char* dir) +void +chxj_delete_cookie_expire(request_rec *r, char *cookie_id) { - char* dst; - - if (!dir) { - dst = apr_pstrdup(r->pool, DEFAULT_COOKIE_DB_DIR); - } - else { - dst = apr_pstrdup(r->pool, dir); - } + int done_proc = 0; + mod_chxj_config *dconf; - if (dst[strlen(dst)-1] != '/') { - dst = apr_pstrcat(r->pool, dst, "/", COOKIE_EXPIRE_DB_NAME, NULL); - } - else { - dst = apr_pstrcat(r->pool, dst, COOKIE_EXPIRE_DB_NAME, NULL); - } - - return dst; -} + DBG(r, "start chxj_delete_cookie_expire()"); + dconf = chxj_get_module_config(r->per_dir_config, &chxj_module); -char* -chxj_cookie_expire_db_lock_name_create(request_rec* r, const char* dir) -{ - char* dst; - - if (!dir) { - dst = apr_pstrdup(r->pool, DEFAULT_COOKIE_DB_DIR); +#if defined(USE_MYSQL_COOKIE) + if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) { + if (! chxj_delete_cookie_expire_mysql(r, dconf, cookie_id)) { + ERR(r, "failed: chxj_delete_cookie_expire_mysql() cookie_id:[%s]", cookie_id); + return; + } + done_proc = 1; } - else { - dst = apr_pstrdup(r->pool, dir); +#endif +#if defined(USE_MEMCACHE_COOKIE) + if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) { + if (!chxj_delete_cookie_expire_memcache(r, dconf, cookie_id)) { + ERR(r, "failed: chxj_delete_cookie_expire_memcache() cookie_id:[%s]", cookie_id); + return; + } + done_proc = 1; } - if (dst[strlen(dst)-1] != '/') { - dst = apr_pstrcat(r->pool, dst, "/", COOKIE_EXPIRE_DB_LOCK_NAME, NULL); - } - else { - dst = apr_pstrcat(r->pool, dst, COOKIE_EXPIRE_DB_LOCK_NAME, NULL); +#endif + if (!done_proc || IS_COOKIE_STORE_DBM(dconf->cookie_store_type)) { + if (!chxj_delete_cookie_expire_dbm(r, dconf, cookie_id)) { + ERR(r, "failed: chxj_delete_cookie_expire_dbm() cookie_id:[%s]", cookie_id); + return; + } } - return dst; -} - - -apr_file_t* -chxj_cookie_expire_db_lock(request_rec* r) -{ - apr_file_t* file; - apr_status_t rv; - mod_chxj_config* dconf; - - dconf = (mod_chxj_config*)ap_get_module_config(r->per_dir_config, &chxj_module); - - rv = apr_file_open(&file, - chxj_cookie_expire_db_lock_name_create(r, dconf->cookie_db_dir), - APR_CREATE|APR_WRITE, - APR_OS_DEFAULT, - r->pool); - if (rv != APR_SUCCESS) { - ERR(r, "cookie lock file open failed."); - return NULL; - } - - rv = apr_file_lock(file,APR_FLOCK_EXCLUSIVE); - if (rv != APR_SUCCESS) { - ERR(r, "cookie lock file open failed."); - apr_file_close(file); - return NULL; - } - - return file; + DBG(r, "end chxj_delete_cookie_expire()"); } void -chxj_cookie_expire_db_unlock(request_rec* r, apr_file_t* file) +chxj_cookie_expire_gc(request_rec *r) { - apr_status_t rv; + mod_chxj_config *dconf; + int done_proc = 0; - rv = apr_file_unlock(file); - if (rv != APR_SUCCESS) { - ERR(r, "cookie lock file open failed."); - return; - } + DBG(r, "start chxj_cookie_expire_gc()"); - apr_file_close(file); + dconf = chxj_get_module_config(r->per_dir_config, &chxj_module); +#if defined(USE_MYSQL_COOKIE) + if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) { + if (! chxj_cookie_expire_gc_mysql(r, dconf)) { + ERR(r, "%s:%d end chxj_cookie_expire_gc(): failed: chxj_cookie_expire_gc_mysql()", APLOG_MARK); + return; + } + done_proc = 1; + } +#endif +#if defined(USE_MEMCACHE_COOKIE) + if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) { + if (! chxj_cookie_expire_gc_memcache(r, dconf)) { + ERR(r, "%s:%d end chxj_cookie_expire_gc(): failed: chxj_cookie_expire_gc_memcache()", APLOG_MARK); + return; + } + done_proc = 1; + } +#endif + if (!done_proc) { + if (! chxj_cookie_expire_gc_dbm(r, dconf)) { + ERR(r, "%s:%d end chxj_cookie_expire_gc(): failed: chxj_cookie_expire_gc_dbm()", APLOG_MARK); + return; + } + } + DBG(r, "end chxj_cookie_expire_gc()"); } -void -chxj_delete_cookie_expire(request_rec* r, char* cookie_id) +apr_time_t +chxj_parse_cookie_expires(const char *s) { - apr_status_t retval; - apr_datum_t dbmkey; - apr_dbm_t* f; - apr_file_t* file; - mod_chxj_config* dconf; + if (!s) return (apr_time_t)0; + return apr_date_parse_rfc(s); +} - DBG(r, "start chxj_delete_cookie_expire()"); - file = chxj_cookie_expire_db_lock(r); - if (! file) { - ERR(r, "mod_chxj: Can't lock cookie db"); - goto on_error0; - } - dconf = ap_get_module_config(r->per_dir_config, &chxj_module); +cookie_lock_t * +__chxj_cookie_lock(request_rec *r, const char *filename, int line) +{ + mod_chxj_config *dconf; + apr_status_t rv; + int done_proc = 0; + cookie_lock_t *ret = NULL; - retval = apr_dbm_open_ex(&f, - "default", - chxj_cookie_expire_db_name_create(r, dconf->cookie_db_dir), - APR_DBM_RWCREATE, - APR_OS_DEFAULT, - r->pool); - if (retval != APR_SUCCESS) { - ERR2(r, - "could not open dbm (type %s) auth file: %s", - "default", - chxj_cookie_expire_db_name_create(r,dconf->cookie_db_dir)); - goto on_error1; + DBG(r, "start chxj_cookie_lock() call from %s:%d", filename, line); + if ((rv = apr_proc_mutex_lock(global_cookie_mutex)) != APR_SUCCESS) { + char errstr[255]; + ERR(r, "%s:%d apr_proc_mutex_lock failure.(%d:%s)", APLOG_MARK, rv, apr_strerror(rv, errstr, 255)); + return NULL; } - - /* - * create key - */ - dbmkey.dptr = apr_pstrdup(r->pool, cookie_id); - dbmkey.dsize = strlen(dbmkey.dptr); - if (apr_dbm_exists(f, dbmkey)) { - apr_dbm_delete(f, dbmkey); + dconf = chxj_get_module_config(r->per_dir_config, &chxj_module); +#if defined(USE_MYSQL_COOKIE) + if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) { + if (! chxj_cookie_lock_mysql(r, dconf)) { + ERR(r, "%s:%d end chxj_cookie_lock(): failed: chxj_cookie_lock_mysql()", APLOG_MARK); + return NULL; + } + done_proc = 1; + ret = apr_palloc(r->pool, sizeof(*ret)); + memset(ret, 0, sizeof(*ret)); + } +#endif +#if defined(USE_MEMCACHE_COOKIE) + if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) { + if (! chxj_cookie_lock_memcache(r, dconf)) { + ERR(r, "%s:%d end chxj_cookie_lock(): failed: chxj_cookie_lock_memcache()", APLOG_MARK); + return NULL; + } + done_proc = 1; + ret = apr_palloc(r->pool, sizeof(*ret)); + memset(ret, 0, sizeof(*ret)); + } +#endif + if (!done_proc) { + if (!(ret = chxj_cookie_lock_dbm(r, dconf))) { + ERR(r, "%s:%d end chxj_cookie_lock(): failed: chxj_cookie_lock_dbm()", APLOG_MARK); + DBG(r, "end chxj_cookie_lock() call from %s:%d", filename, line); + return NULL; + } } - apr_dbm_close(f); - chxj_cookie_expire_db_unlock(r, file); - - DBG(r, "end chxj_delete_cookie_expire()"); - - return; - -on_error1: - chxj_cookie_expire_db_unlock(r, file); - -on_error0: - return; - + DBG(r, "REQ:[%X] end chxj_cookie_lock() call from %s:%d", (unsigned int)(apr_size_t)r, filename, line); + return ret; } -void -chxj_cookie_expire_gc(request_rec* r) +int +__chxj_cookie_unlock(request_rec *r, cookie_lock_t *lock, const char *filename, int line) { - apr_status_t retval; - apr_datum_t dbmkey; - apr_datum_t dbmval; - apr_dbm_t* f; - apr_file_t* file; - mod_chxj_config* dconf; - time_t now_time; + mod_chxj_config *dconf; + int done_proc = 0; + apr_status_t rv; + int rtn = 1; - DBG(r, "start chxj_cookie_expire_gc()"); + DBG(r, "start chxj_cookie_unlock() call from %s:%d", filename, line); - file = chxj_cookie_expire_db_lock(r); - if (! file) { - ERR(r, "mod_chxj: Can't lock cookie db"); - goto on_error0; - } - dconf = ap_get_module_config(r->per_dir_config, &chxj_module); - - retval = apr_dbm_open_ex(&f, - "default", - chxj_cookie_expire_db_name_create(r, dconf->cookie_db_dir), - APR_DBM_RWCREATE, - APR_OS_DEFAULT, - r->pool); - if (retval != APR_SUCCESS) { - ERR2(r, - "could not open dbm (type %s) auth file: %s", - "default", - chxj_cookie_expire_db_name_create(r,dconf->cookie_db_dir)); - goto on_error1; + dconf = chxj_get_module_config(r->per_dir_config, &chxj_module); +#if defined(USE_MYSQL_COOKIE) + if (IS_COOKIE_STORE_MYSQL(dconf->cookie_store_type)) { + if (! chxj_cookie_unlock_mysql(r, dconf)) { + ERR(r, "failed: chxj_cookie_unlock_mysql()"); + rtn = 0; + goto end_chxj_cookie_unlock; + } + done_proc = 1; + } +#endif +#if defined(USE_MEMCACHE_COOKIE) + if (IS_COOKIE_STORE_MEMCACHE(dconf->cookie_store_type)) { + if (! chxj_cookie_unlock_memcache(r, dconf)) { + ERR(r, "failed: chxj_cookie_unlock_memcache()"); + rtn = 0; + goto end_chxj_cookie_unlock; + } + done_proc = 1; + } +#endif + if (!done_proc) { + if (! chxj_cookie_unlock_dbm(r, lock, dconf)) { + ERR(r, "failed: chxj_cookie_unlock_dbm()"); + rtn = 0; + goto end_chxj_cookie_unlock; + } } - - /* - * create key - */ - memset(&dbmkey, 0, sizeof(apr_datum_t)); - - now_time = time(NULL); - - retval = apr_dbm_firstkey(f, &dbmkey); - if (retval == APR_SUCCESS) { - DBG2(r, "firstkey=[%.*s]", dbmkey.dsize, dbmkey.dptr); - do { - char* tmp; - char* old_cookie_id; - int val_time; - int cmp_time; - - retval = apr_dbm_fetch(f, dbmkey, &dbmval); - if (retval != APR_SUCCESS) { - break; - } - tmp = apr_palloc(r->pool, dbmval.dsize+1); - memset(tmp, 0, dbmval.dsize+1); - memcpy(tmp, dbmval.dptr, dbmval.dsize); - - - val_time = atoi(tmp); - - if (dconf->cookie_timeout == 0) - cmp_time = now_time - DEFAULT_COOKIE_TIMEOUT; - else - cmp_time = now_time - dconf->cookie_timeout; - - DBG2(r, "key=[%.*s]", dbmkey.dsize, dbmkey.dptr); - if (cmp_time >= val_time) { - apr_dbm_delete(f, dbmkey); - - old_cookie_id = apr_palloc(r->pool, dbmkey.dsize+1); - memset(old_cookie_id, 0, dbmkey.dsize+1); - memcpy(old_cookie_id, dbmkey.dptr, dbmkey.dsize); - - chxj_delete_cookie(r,old_cookie_id); - DBG1(r, "detect timeout cookie [%s]", old_cookie_id); - } - - retval = apr_dbm_nextkey(f, &dbmkey); - } while(retval == APR_SUCCESS && dbmkey.dptr != NULL); +end_chxj_cookie_unlock: + if ((rv = apr_proc_mutex_unlock(global_cookie_mutex)) != APR_SUCCESS) { + char errstr[255]; + ERR(r, "%s:%d apr_proc_mutex_unlock failure.(%d:%s)", APLOG_MARK, rv, apr_strerror(rv, errstr, 255)); + DBG(r, "end chxj_cookie_unlock() call from %s:%d", filename, line); + return 0; } + DBG(r, "end chxj_cookie_unlock() call from %s:%d", filename, line); - apr_dbm_close(f); - chxj_cookie_expire_db_unlock(r, file); - - DBG(r, "end chxj_cookie_expire_gc()"); - - return; - -on_error1: - chxj_cookie_expire_db_unlock(r, file); - -on_error0: - return; - + return rtn; } /* * vim:ts=2 et