Annotation of embedaddon/lighttpd/src/mod_usertrack.c, revision 1.1
1.1 ! misho 1: #include "base.h"
! 2: #include "log.h"
! 3: #include "buffer.h"
! 4:
! 5: #include "plugin.h"
! 6:
! 7: #include <ctype.h>
! 8: #include <stdlib.h>
! 9: #include <string.h>
! 10:
! 11: #include "md5.h"
! 12:
! 13: /* plugin config for all request/connections */
! 14:
! 15: typedef struct {
! 16: buffer *cookie_name;
! 17: buffer *cookie_domain;
! 18: unsigned int cookie_max_age;
! 19: } plugin_config;
! 20:
! 21: typedef struct {
! 22: PLUGIN_DATA;
! 23:
! 24: plugin_config **config_storage;
! 25:
! 26: plugin_config conf;
! 27: } plugin_data;
! 28:
! 29: /* init the plugin data */
! 30: INIT_FUNC(mod_usertrack_init) {
! 31: plugin_data *p;
! 32:
! 33: p = calloc(1, sizeof(*p));
! 34:
! 35: return p;
! 36: }
! 37:
! 38: /* detroy the plugin data */
! 39: FREE_FUNC(mod_usertrack_free) {
! 40: plugin_data *p = p_d;
! 41:
! 42: UNUSED(srv);
! 43:
! 44: if (!p) return HANDLER_GO_ON;
! 45:
! 46: if (p->config_storage) {
! 47: size_t i;
! 48: for (i = 0; i < srv->config_context->used; i++) {
! 49: plugin_config *s = p->config_storage[i];
! 50:
! 51: buffer_free(s->cookie_name);
! 52: buffer_free(s->cookie_domain);
! 53:
! 54: free(s);
! 55: }
! 56: free(p->config_storage);
! 57: }
! 58:
! 59: free(p);
! 60:
! 61: return HANDLER_GO_ON;
! 62: }
! 63:
! 64: /* handle plugin config and check values */
! 65:
! 66: SETDEFAULTS_FUNC(mod_usertrack_set_defaults) {
! 67: plugin_data *p = p_d;
! 68: size_t i = 0;
! 69:
! 70: config_values_t cv[] = {
! 71: { "usertrack.cookie-name", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 0 */
! 72: { "usertrack.cookie-max-age", NULL, T_CONFIG_INT, T_CONFIG_SCOPE_CONNECTION }, /* 1 */
! 73: { "usertrack.cookie-domain", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 2 */
! 74:
! 75: { "usertrack.cookiename", NULL, T_CONFIG_DEPRECATED, T_CONFIG_SCOPE_CONNECTION },
! 76: { NULL, NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
! 77: };
! 78:
! 79: if (!p) return HANDLER_ERROR;
! 80:
! 81: p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
! 82:
! 83: for (i = 0; i < srv->config_context->used; i++) {
! 84: plugin_config *s;
! 85:
! 86: s = calloc(1, sizeof(plugin_config));
! 87: s->cookie_name = buffer_init();
! 88: s->cookie_domain = buffer_init();
! 89: s->cookie_max_age = 0;
! 90:
! 91: cv[0].destination = s->cookie_name;
! 92: cv[1].destination = &(s->cookie_max_age);
! 93: cv[2].destination = s->cookie_domain;
! 94:
! 95: p->config_storage[i] = s;
! 96:
! 97: if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
! 98: return HANDLER_ERROR;
! 99: }
! 100:
! 101: if (buffer_is_empty(s->cookie_name)) {
! 102: buffer_copy_string_len(s->cookie_name, CONST_STR_LEN("TRACKID"));
! 103: } else {
! 104: size_t j;
! 105: for (j = 0; j < s->cookie_name->used - 1; j++) {
! 106: char c = s->cookie_name->ptr[j] | 32;
! 107: if (c < 'a' || c > 'z') {
! 108: log_error_write(srv, __FILE__, __LINE__, "sb",
! 109: "invalid character in usertrack.cookie-name:",
! 110: s->cookie_name);
! 111:
! 112: return HANDLER_ERROR;
! 113: }
! 114: }
! 115: }
! 116:
! 117: if (!buffer_is_empty(s->cookie_domain)) {
! 118: size_t j;
! 119: for (j = 0; j < s->cookie_domain->used - 1; j++) {
! 120: char c = s->cookie_domain->ptr[j];
! 121: if (c <= 32 || c >= 127 || c == '"' || c == '\\') {
! 122: log_error_write(srv, __FILE__, __LINE__, "sb",
! 123: "invalid character in usertrack.cookie-domain:",
! 124: s->cookie_domain);
! 125:
! 126: return HANDLER_ERROR;
! 127: }
! 128: }
! 129: }
! 130: }
! 131:
! 132: return HANDLER_GO_ON;
! 133: }
! 134:
! 135: #define PATCH(x) \
! 136: p->conf.x = s->x;
! 137: static int mod_usertrack_patch_connection(server *srv, connection *con, plugin_data *p) {
! 138: size_t i, j;
! 139: plugin_config *s = p->config_storage[0];
! 140:
! 141: PATCH(cookie_name);
! 142: PATCH(cookie_domain);
! 143: PATCH(cookie_max_age);
! 144:
! 145: /* skip the first, the global context */
! 146: for (i = 1; i < srv->config_context->used; i++) {
! 147: data_config *dc = (data_config *)srv->config_context->data[i];
! 148: s = p->config_storage[i];
! 149:
! 150: /* condition didn't match */
! 151: if (!config_check_cond(srv, con, dc)) continue;
! 152:
! 153: /* merge config */
! 154: for (j = 0; j < dc->value->used; j++) {
! 155: data_unset *du = dc->value->data[j];
! 156:
! 157: if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-name"))) {
! 158: PATCH(cookie_name);
! 159: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-max-age"))) {
! 160: PATCH(cookie_max_age);
! 161: } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("usertrack.cookie-domain"))) {
! 162: PATCH(cookie_domain);
! 163: }
! 164: }
! 165: }
! 166:
! 167: return 0;
! 168: }
! 169: #undef PATCH
! 170:
! 171: URIHANDLER_FUNC(mod_usertrack_uri_handler) {
! 172: plugin_data *p = p_d;
! 173: data_string *ds;
! 174: unsigned char h[16];
! 175: li_MD5_CTX Md5Ctx;
! 176: char hh[32];
! 177:
! 178: if (con->uri.path->used == 0) return HANDLER_GO_ON;
! 179:
! 180: mod_usertrack_patch_connection(srv, con, p);
! 181:
! 182: if (NULL != (ds = (data_string *)array_get_element(con->request.headers, "Cookie"))) {
! 183: char *g;
! 184: /* we have a cookie, does it contain a valid name ? */
! 185:
! 186: /* parse the cookie
! 187: *
! 188: * check for cookiename + (WS | '=')
! 189: *
! 190: */
! 191:
! 192: if (NULL != (g = strstr(ds->value->ptr, p->conf.cookie_name->ptr))) {
! 193: char *nc;
! 194:
! 195: /* skip WS */
! 196: for (nc = g + p->conf.cookie_name->used-1; *nc == ' ' || *nc == '\t'; nc++);
! 197:
! 198: if (*nc == '=') {
! 199: /* ok, found the key of our own cookie */
! 200:
! 201: if (strlen(nc) > 32) {
! 202: /* i'm lazy */
! 203: return HANDLER_GO_ON;
! 204: }
! 205: }
! 206: }
! 207: }
! 208:
! 209: /* set a cookie */
! 210: if (NULL == (ds = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
! 211: ds = data_response_init();
! 212: }
! 213: buffer_copy_string_len(ds->key, CONST_STR_LEN("Set-Cookie"));
! 214: buffer_copy_string_buffer(ds->value, p->conf.cookie_name);
! 215: buffer_append_string_len(ds->value, CONST_STR_LEN("="));
! 216:
! 217:
! 218: /* taken from mod_auth.c */
! 219:
! 220: /* generate shared-secret */
! 221: li_MD5_Init(&Md5Ctx);
! 222: li_MD5_Update(&Md5Ctx, (unsigned char *)con->uri.path->ptr, con->uri.path->used - 1);
! 223: li_MD5_Update(&Md5Ctx, (unsigned char *)"+", 1);
! 224:
! 225: /* we assume sizeof(time_t) == 4 here, but if not it ain't a problem at all */
! 226: LI_ltostr(hh, srv->cur_ts);
! 227: li_MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
! 228: li_MD5_Update(&Md5Ctx, (unsigned char *)srv->entropy, sizeof(srv->entropy));
! 229: LI_ltostr(hh, rand());
! 230: li_MD5_Update(&Md5Ctx, (unsigned char *)hh, strlen(hh));
! 231:
! 232: li_MD5_Final(h, &Md5Ctx);
! 233:
! 234: buffer_append_string_encoded(ds->value, (char *)h, 16, ENCODING_HEX);
! 235: buffer_append_string_len(ds->value, CONST_STR_LEN("; Path=/"));
! 236: buffer_append_string_len(ds->value, CONST_STR_LEN("; Version=1"));
! 237:
! 238: if (!buffer_is_empty(p->conf.cookie_domain)) {
! 239: buffer_append_string_len(ds->value, CONST_STR_LEN("; Domain="));
! 240: buffer_append_string_encoded(ds->value, CONST_BUF_LEN(p->conf.cookie_domain), ENCODING_REL_URI);
! 241: }
! 242:
! 243: if (p->conf.cookie_max_age) {
! 244: buffer_append_string_len(ds->value, CONST_STR_LEN("; max-age="));
! 245: buffer_append_long(ds->value, p->conf.cookie_max_age);
! 246: }
! 247:
! 248: array_insert_unique(con->response.headers, (data_unset *)ds);
! 249:
! 250: return HANDLER_GO_ON;
! 251: }
! 252:
! 253: /* this function is called at dlopen() time and inits the callbacks */
! 254:
! 255: int mod_usertrack_plugin_init(plugin *p);
! 256: int mod_usertrack_plugin_init(plugin *p) {
! 257: p->version = LIGHTTPD_VERSION_ID;
! 258: p->name = buffer_init_string("usertrack");
! 259:
! 260: p->init = mod_usertrack_init;
! 261: p->handle_uri_clean = mod_usertrack_uri_handler;
! 262: p->set_defaults = mod_usertrack_set_defaults;
! 263: p->cleanup = mod_usertrack_free;
! 264:
! 265: p->data = NULL;
! 266:
! 267: return 0;
! 268: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>