static PyObject *parse_qs(PyObject *self, PyObject *args, PyObject *kw) { PyObject *pairs, *dict; int i, n, len, lsize; char *qs; int keep_blank_values = 0; int strict_parsing = 0; /* XXX not implemented */ char *keywords[] = { "qs", "keep_blank_values", "strict_parsing", 0 }; if (! PyArg_ParseTupleAndKeywords(args, kw, "s|ii", keywords, &qs, &keep_blank_values, &strict_parsing)) return NULL; /* error */ /* split query string by '&' and ';' into a list of pairs */ /* PYTHON 2.5: 'PyList_New' uses Py_ssize_t for input parameters */ pairs = PyList_New(0); if (pairs == NULL) return NULL; i = 0; len = strlen(qs); while (i < len) { PyObject *pair; char *cpair; int j = 0; /* PYTHON 2.5: 'PyString_FromStringAndSize' uses Py_ssize_t for input parameters */ pair = PyString_FromStringAndSize(NULL, len); if (pair == NULL) return NULL; /* split by '&' or ';' */ cpair = PyString_AS_STRING(pair); while ((qs[i] != '&') && (qs[i] != ';') && (i < len)) { /* replace '+' with ' ' */ cpair[j] = (qs[i] == '+') ? ' ' : qs[i]; i++; j++; } if (j) { /* PYTHON 2.5: '_PyString_Resize' uses Py_ssize_t for input parameters */ _PyString_Resize(&pair, j); if (pair) PyList_Append(pairs, pair); } Py_XDECREF(pair); i++; } /* * now we have a list of "abc=def" string (pairs), let's split * them all by '=' and put them in a dictionary. */ dict = PyDict_New(); if (dict == NULL) return NULL; /* PYTHON 2.5: 'PyList_Size' uses Py_ssize_t for input parameters */ lsize = PyList_Size(pairs); n = 0; while (n < lsize) { PyObject *pair, *key, *val; char *cpair, *ckey, *cval; int k, v; pair = PyList_GET_ITEM(pairs, n); cpair = PyString_AS_STRING(pair); len = strlen(cpair); /* PYTHON 2.5: 'PyString_FromStringAndSize' uses Py_ssize_t for input parameters */ key = PyString_FromStringAndSize(NULL, len); if (key == NULL) return NULL; /* PYTHON 2.5: 'PyString_FromStringAndSize' uses Py_ssize_t for input parameters */ val = PyString_FromStringAndSize(NULL, len); if (val == NULL) return NULL; ckey = PyString_AS_STRING(key); cval = PyString_AS_STRING(val); i = 0; k = 0; v = 0; while (i < len) { if (cpair[i] != '=') { ckey[k] = cpair[i]; k++; i++; } else { i++; /* skip '=' */ while (i < len) { cval[v] = cpair[i]; v++; i++; } } } ckey[k] = '\0'; cval[v] = '\0'; if (keep_blank_values || (v > 0)) { ap_unescape_url(ckey); ap_unescape_url(cval); /* PYTHON 2.5: '_PyString_Resize' uses Py_ssize_t for input parameters */ _PyString_Resize(&key, strlen(ckey)); /* PYTHON 2.5: '_PyString_Resize' uses Py_ssize_t for input parameters */ _PyString_Resize(&val, strlen(cval)); if (key && val) { ckey = PyString_AS_STRING(key); cval = PyString_AS_STRING(val); if (PyMapping_HasKeyString(dict, ckey)) { PyObject *list; list = PyDict_GetItem(dict, key); PyList_Append(list, val); /* PyDict_GetItem is a borrowed ref, no decref */ } else { PyObject *list; list = Py_BuildValue("[O]", val); PyDict_SetItem(dict, key, list); Py_DECREF(list); } } } Py_XDECREF(key); Py_XDECREF(val); n++; } Py_DECREF(pairs); return dict; }
static void argstr_to_table(apr_pool_t *p, char *str, apr_table_t *parms) { char *key; char *value; char *strtok_state; key = apr_strtok(str, "&", &strtok_state); while (key) { value = strchr(key, '='); if (value) { *value = '\0'; /* Split the string in two */ value++; /* Skip passed the = */ } else { value = "1"; } ap_unescape_url(key); ap_unescape_url(value); apr_table_set(parms, key, value); /* ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Found query arg: %s = %s", key, value); */ key = apr_strtok(NULL, "&", &strtok_state); } }
/* parse parameter */ static apr_hash_t *parse_parameter(request_rec *r) { char *str = apr_pstrdup(r->pool, r->args); if( str == NULL ) { return NULL; } apr_hash_t *hash = NULL; const char *del = "&"; char *items, *last, *st; hash = apr_hash_make(r->pool); // set hash for ( items = apr_strtok(str, del, &last); items != NULL; items = apr_strtok(NULL, del, &last) ){ st = strchr(items, '='); if (st) { *st++ = '\0'; ap_unescape_url(items); ap_unescape_url(st); } else { st = ""; ap_unescape_url(items); } apr_hash_set( hash, items, APR_HASH_KEY_STRING, st ); } return hash; }
/** * Nomalize charset in HTTP request line and HTTP header(s). * Returns 0 on success, -1 (non-zero) on error. * * FIXME: Should handle/consider partial success? * * @param r Apache request object structure * @param cd Conversion descriptor, made by iconv_open(3). */ static int iconv_header(request_rec *r, iconv_t cd) { char *buff; char *keys[] = { "Destination", NULL }; int i; /* Normalize encoding in HTTP request line */ ap_unescape_url(r->unparsed_uri); if ((buff = iconv_string(r, cd, r->unparsed_uri, strlen(r->unparsed_uri))) == NULL) return -1; ap_parse_uri(r, buff); ap_getparents(r->uri); /* normalize given path for security */ /* Normalize encoding in HTTP request header(s) */ for (i = 0 ; keys[i] ; i++) { if ((buff = (char *)ap_table_get(r->headers_in, keys[i])) != NULL) { ap_unescape_url(buff); if ((buff = iconv_string(r, cd, buff, strlen(buff))) == NULL) return -1; ap_table_set(r->headers_in, keys[i], buff); } } return 0; }
/** * Copied from httpd/trunk/modules/cluster/mod_heartbeat.c. * * Copyright 2009 The Apache Software Foundation. * * The following function is licensed under the Apache * License, Version 2.0. See COPYING for more details. */ static void qs_to_table(const char *input, apr_table_t *parms, apr_pool_t *p) { char *key; char *value; char *query_string; char *strtok_state; if (input == NULL) { return; } query_string = apr_pstrdup(p, input); key = apr_strtok(query_string, "&", &strtok_state); while (key) { value = strchr(key, '='); if (value) { *value = '\0'; /* Split the string in two */ value++; /* Skip passed the = */ } else { value = "1"; } ap_unescape_url(key); ap_unescape_url(value); apr_table_set(parms, key, value); /* ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Found query arg: %s = %s", key, value); */ key = apr_strtok(NULL, "&", &strtok_state); } }
static apr_hash_t *parse_form_from_string(request_rec *r, char *args) { apr_hash_t *form; /* apr_array_header_t *values = NULL;*/ char *pair; char *eq; const char *delim = "&"; char *last; char *values; if(args == NULL) { return NULL; } form = apr_hash_make(r->pool); /* Split the input on '&' */ for (pair = apr_strtok(args, delim, &last); pair != NULL; pair = apr_strtok(NULL, delim, &last)) { for (eq = pair; *eq; ++eq) { if (*eq == '+') { *eq = ' '; } } /* split into key value and unescape it */ eq = strchr(pair, '='); if(eq) { *eq++ = '\0'; ap_unescape_url(pair); ap_unescape_url(eq); } else { eq = ""; ap_unescape_url(pair); } /* Store key/value pair in out form hash. Given that there * may be many values for the same key, we store values * in an array (which we'll have to create the first * time we encounter the key in question). */ values = apr_hash_get(form, pair, APR_HASH_KEY_STRING); if(values != NULL) { values = apr_pstrcat(r->pool, values, "&", eq, NULL); /* values = apr_array_make(r->pool, 1, sizeof(const char*)); apr_hash_set(form, pair, APR_HASH_KEY_STRING, values);*/ } else { values = apr_pstrdup(r->pool, eq); } apr_hash_set(form, pair, APR_HASH_KEY_STRING, values); } return form; }
static void cwx_parse_args(CWX_CONNECT* conn){ char *begin = NULL; char const *mid = NULL; char const *end =NULL; char* args = conn->m_args; CWX_KEY_VALUE* key_value; unsigned int key_len = 0; unsigned int data_len = 0; conn->m_args_head = NULL; conn->m_args_tail =NULL; if (!args) return; begin = args; mid = strchr(begin, '='); while(mid){ key_value = (CWX_KEY_VALUE*)apr_pcalloc(conn->m_request->pool, sizeof(CWX_KEY_VALUE)); //get key while(*begin == '&') begin++; key_len = mid - begin; key_value->m_key = (char*)apr_pcalloc(conn->m_request->pool, key_len+1); key_value->m_lowerkey = (char*)apr_pcalloc(conn->m_request->pool, key_len+1); memcpy(key_value->m_key, begin, key_len); key_value->m_key[key_len] = 0x00; ap_unescape_url(key_value->m_key); cwx_trim(key_value->m_key); strcpy(key_value->m_lowerkey, key_value->m_key); cwx_tolower(key_value->m_lowerkey); //get data mid++; end = strchr(mid, '&'); if (0 == end) data_len = strlen(mid); else data_len = end - mid; key_value->m_value = (char*)apr_pcalloc(conn->m_request->pool, data_len+1); memcpy(key_value->m_value, mid, data_len); key_value->m_value[data_len] = 0x00; ap_unescape_url(key_value->m_value); //add to the key_value->m_next = NULL; if (!conn->m_args_head){ conn->m_args_head = conn->m_args_tail = key_value; }else{ conn->m_args_tail->m_next = key_value; conn->m_args_tail = key_value; } if (end){ begin = end+1; mid = strchr(begin, '='); }else{ break; } } }
static int twms_handler(request_rec *r) { twms_dir_conf *dcfg; const char *data; const char *val; apr_table_t *tab; apr_file_t *fh; apr_size_t nsend; apr_finfo_t info; if ((r->method_number != M_GET )||(r->args==0)) return DECLINED; data=r->args; // scfg=ap_get_module_config(r->server->module_config,&twms_module); dcfg=ap_get_module_config(r->per_dir_config,&twms_module); if (!dcfg) return DECLINED; // Does this ever happen? if (!ap_strstr(data,"GetTileService")) return DECLINED; // Do we have a config for this directory // ap_log_error(APLOG_MARK,APLOG_ERR,0,r->server,"TWMS_handler: args %s, path %s scfg %x dcfg %x dir %s conf %s", // data,r->parsed_uri.path,scfg,dcfg,dcfg->path,dcfg->Config); if (!dcfg->Config) return DECLINED; // This is overkill here, but it works tab=apr_table_make(r->pool,0); while (*data && (val=ap_getword(r->pool, &data, '&'))) { char *key=apr_pstrdup(r->pool,ap_getword(r->pool, &val, '=')); char *ival=apr_pstrdup(r->pool,val); ap_unescape_url(key);ap_unescape_url(ival); apr_table_merge(tab,key,ival); } if (!(val=apr_table_get(tab,"request"))) return DECLINED; if (apr_strnatcmp(val,"GetTileService")) return DECLINED; if (APR_SUCCESS!=apr_file_open(&fh,apr_pstrcat(r->pool,dcfg->path,dcfg->Config,0), APR_READ,APR_OS_DEFAULT,r->pool)) { ap_log_error(APLOG_MARK,APLOG_ERR,0,r->server,"TWMS file can't be read"); return HTTP_CONFLICT; } ap_log_error(APLOG_MARK,APLOG_ERR,0,r->server,"TWMS Sending GTS file"); apr_file_info_get(&info,APR_FINFO_SIZE,fh); ap_set_content_type(r,"text/xml"); ap_send_fd(fh,r,0,info.size,&nsend); apr_file_close(fh); return OK; }
/* This is the special environment used for running the "exec cmd=" * variety of SSI directives. */ static void add_ssi_vars(request_rec *r) { apr_table_t *e = r->subprocess_env; if (r->path_info && r->path_info[0] != '\0') { request_rec *pa_req; apr_table_setn(e, "PATH_INFO", ap_escape_shell_cmd(r->pool, r->path_info)); pa_req = ap_sub_req_lookup_uri(ap_escape_uri(r->pool, r->path_info), r, NULL); if (pa_req->filename) { apr_table_setn(e, "PATH_TRANSLATED", apr_pstrcat(r->pool, pa_req->filename, pa_req->path_info, NULL)); } ap_destroy_sub_req(pa_req); } if (r->args) { char *arg_copy = apr_pstrdup(r->pool, r->args); apr_table_setn(e, "QUERY_STRING", r->args); ap_unescape_url(arg_copy); apr_table_setn(e, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(r->pool, arg_copy)); } }
/* Parse x-www-url-formencoded args */ apr_table_t *parse_args(request_rec *r, char *args) { char* pair; char* last = NULL; char* eq; char *delim = "&"; apr_table_t *vars = apr_table_make(r->pool, 10); for (pair = apr_strtok(r->args, delim, &last); pair; pair = apr_strtok(NULL, delim, &last)) { for (eq = pair; *eq; ++eq) if (*eq == '+') *eq = ' '; ap_unescape_url(pair); eq = strchr(pair, '='); if (eq) { *eq++ = 0; apr_table_merge(vars, pair, eq); } else { apr_table_merge(vars, pair, ""); } } return vars; }
static void split_to_parms(ApacheRequest *req, const char *data) { request_rec *r = req->r; const char *val; while (*data && (val = my_urlword(r->pool, &data))) { const char *key = ap_getword(r->pool, &val, '='); req_plustospace((char*)key); ap_unescape_url((char*)key); req_plustospace((char*)val); ap_unescape_url((char*)val); ap_table_add(req->parms, key, val); } }
/* This is our simple query decoding function. Should be improved but for now * it works... */ static int mapserver_decode_args (apr_pool_t *p, char *args, char ***ParamNames, char ***ParamValues) { char **argv = NULL; int i; int n; int argc = 0; char *sep; /* alloc the name/value pointer list */ argv = (char**) apr_pcalloc (p, (WMS_MAX_ARGS + 1) * 2 * sizeof (char*)); *ParamNames = argv; *ParamValues = argv + WMS_MAX_ARGS + 1; /* No arguments? Then we're done */ if (!args) return 0; argv [0] = args; /* separate the arguments */ for (i = 1, n = 0; args [n] && (i < WMS_MAX_ARGS); n++) if (args [n] == '&') { argv [i++] = args + n + 1; args [n ] = '\0'; } /* eleminate empty args */ for (n = 0, i = 0; argv [i]; i++) if (*(argv [i]) != '\0') argv [n++] = argv [i]; else argv [i ] = NULL; /* argument count is the number of non-zero arguments! */ argc = n; /* split the name/value pairs */ for (i = 0; argv [i]; i++) { sep = strchr (argv [i], '='); if (!sep) continue; *sep = '\0'; argv [i + WMS_MAX_ARGS + 1] = (char*) apr_pstrdup (p, sep + 1); if (ap_unescape_url (argv [i + WMS_MAX_ARGS + 1]) == HTTP_BAD_REQUEST) { ap_log_error (APLOG_MARK, APLOG_ERR, 0, NULL, "%s: malformed URI, couldn't unescape parm %s", __func__, argv [i]); argv [i + WMS_MAX_ARGS + 1] = NULL; } else { plustospace (argv [i + WMS_MAX_ARGS + 1]); } } return argc; }
/* Look through 'Cookie' header for indicated cookie; extract it * and URL-unescape it. Return the cookie on success, NULL on failure. */ static char * extract_cookie(request_rec *r, const char *szCookie_name) { const char *szRaw_cookie, *szRaw_cookie_start = NULL, *szRaw_cookie_end; char *szCookie; int i; /* get cookie string */ szRaw_cookie = apr_table_get(r->headers_in, "Cookie"); if (!szRaw_cookie) return 0; /* loop to search cookie name in cookie header */ do { /* search cookie name in cookie string */ if ((szRaw_cookie = strstr(szRaw_cookie, szCookie_name)) == 0) return 0; szRaw_cookie_start = szRaw_cookie; /* search '=' */ if ((szRaw_cookie = strchr(szRaw_cookie, '=')) == 0) return 0; } while (strncmp(szCookie_name, szRaw_cookie_start, szRaw_cookie - szRaw_cookie_start) != 0); /* skip '=' */ szRaw_cookie++; /* search end of cookie name value: ';' or end of cookie strings */ if ((szRaw_cookie_end = strchr(szRaw_cookie, ';')) == 0 && (szRaw_cookie_end = strchr(szRaw_cookie, '\0')) == 0) return 0; /* dup the value string found in apache pool and set the result pool ptr to szCookie ptr */ if ((szCookie = apr_pstrndup(r->pool, szRaw_cookie, szRaw_cookie_end-szRaw_cookie)) == 0) return 0; /* unescape the value string */ if (ap_unescape_url(szCookie) != 0) return 0; /* be extra paranoid about the cookie value, reject if no md5sum */ if (!(strlen(szCookie) == 32 || strlen(szCookie)== 43)) return 0; for (i = 0; i < 32; i++) { if (szCookie[i] == '_') continue; if (szCookie[i] >= '0' && szCookie[i] <= '9') continue; if (szCookie[i] >= 'a' && szCookie[i] <= 'f') continue; return 0; } ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, ERRTAG "Cleaned Cookie: %s ", szCookie); return szCookie; }
static apr_status_t default_build_command(const char **cmd, const char ***argv, request_rec *r, apr_pool_t *p, cgi_exec_info_t *e_info) { int numwords, x, idx; char *w; const char *args = NULL; if (e_info->process_cgi) { *cmd = r->filename; /* Do not process r->args if they contain an '=' assignment */ if (r->args && r->args[0] && !ap_strchr_c(r->args, '=')) { args = r->args; } } if (!args) { numwords = 1; } else { /* count the number of keywords */ for (x = 0, numwords = 2; args[x]; x++) { if (args[x] == '+') { ++numwords; } } } /* Everything is - 1 to account for the first parameter * which is the program name. */ if (numwords > APACHE_ARG_MAX - 1) { numwords = APACHE_ARG_MAX - 1; /* Truncate args to prevent overrun */ } *argv = apr_palloc(p, (numwords + 2) * sizeof(char *)); (*argv)[0] = *cmd; for (x = 1, idx = 1; x < numwords; x++) { w = ap_getword_nulls(p, &args, '+'); ap_unescape_url(w); (*argv)[idx++] = ap_escape_shell_cmd(p, w); } (*argv)[idx] = NULL; return APR_SUCCESS; }
static int light_search_handler(request_rec *r, softbot_handler_rec *s) { int rv = 0; int i = 0; init_server(r, s); set_con_config(r->server); msg_record_init(&s->msg); rv = sb_run_qp_init(); if(rv != SUCCESS && rv != DECLINE) { MSG_RECORD(&s->msg, error, "qp init failed"); return FAIL; } if(apr_table_get(s->parameters_in, "q") == NULL || strlen(apr_table_get(s->parameters_in, "q")) == 0) { MSG_RECORD(&s->msg, error, "query is null, must use http get method"); return FAIL; } ap_unescape_url((char *)apr_table_get(s->parameters_in, "q")); rv = sb_run_qp_init_request(&qp_request, (char *)apr_table_get(s->parameters_in, "q")); if(rv != SUCCESS) { s->msg = qp_request.msg; error("can not init request"); return FAIL; } rv = sb_run_qp_init_response(&qp_response); if(rv != SUCCESS) { s->msg = qp_request.msg; error("can not init request"); return FAIL; } timelog("sb_run_qp_light_search start"); rv = sb_run_qp_light_search(&qp_request, &qp_response); timelog("sb_run_qp_light_search finish"); if (rv != SUCCESS) { s->msg = qp_request.msg; error("sb_run_qp_light_search failed: query[%s]", qp_request.query); return FAIL; } ap_set_content_type(r, "x-softbotd/binary"); timelog("send_result_start"); // 0. node id - 0 ~ 16 ap_rwrite(&(this_node_id), sizeof(uint32_t), r); // 1. 총 검색건수 ap_rwrite(&(qp_response.search_result), sizeof(uint32_t), r); // 2. 전송 검색건수 ap_rwrite(&(qp_response.vdl->cnt), sizeof(uint32_t), r); // 3. 검색 단어 리스트 ap_rwrite(qp_response.parsed_query, sizeof(qp_response.parsed_query), r); debug("search_result[%u], send_cnt[%u], parsed_query[%s]", qp_response.search_result, qp_response.vdl->cnt, qp_response.parsed_query); // 4. 검색결과 전송 for(i = 0; i < qp_response.vdl->cnt; i++) { virtual_document_t* vd = &(qp_response.vdl->data[i]); print_virtual_document(vd); ap_rwrite((void*)&vd->id, sizeof(uint32_t), r); ap_rwrite((void*)&vd->relevance, sizeof(uint32_t), r); ap_rwrite((void*)&vd->dochit_cnt, sizeof(uint32_t), r); ap_rwrite((void*)vd->dochits, sizeof(doc_hit_t)*vd->dochit_cnt, r); ap_rwrite(&(this_node_id), sizeof(uint32_t), r); debug("send node_id[%0X]", this_node_id); ap_rwrite((void*)vd->docattr, sizeof(docattr_t), r); } timelog("send_result_finish"); s->msg = qp_request.msg; sb_run_qp_finalize_search(&qp_request, &qp_response); timelog("qp_finalize"); return SUCCESS; }
static int preprocess_handler(request_rec *r, softbot_handler_rec *s) { int i = 0; int num_of_node = 0; QueryNode qnodes[MAX_QUERY_NODES]; char content_type[SHORT_STRING_SIZE+1]; if(apr_table_get(s->parameters_in, "q") == NULL || strlen(apr_table_get(s->parameters_in, "q")) == 0) { MSG_RECORD(&s->msg, error, "Parameter 'q' is null or has zero length. query is null." " You have to input a valid query or use GET method instead of POST."); return FAIL; } ap_unescape_url((char *)apr_table_get(s->parameters_in, "q")); num_of_node = sb_run_preprocess(word_db, (char *)apr_table_get(s->parameters_in, "q"), MAX_QUERY_STRING_SIZE, qnodes, MAX_QUERY_NODES); snprintf( content_type, SHORT_STRING_SIZE, "text/xml; charset=%s", default_charset); ap_set_content_type(r, content_type); ap_rprintf(r, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", default_charset); ap_rprintf(r, "<xml>\n"); for ( i=0; i<num_of_node; i++) { if (qnodes[i].type == OPERAND) { ap_rprintf(r, "<node type=\"OPERAND\">\n" "<word>\n" "<string>%s</string>\n" "<id>%u</id>\n" "</word>\n" "<field>%s</field>\n" "<opParam>%d</opParam>\n" "<weight>%f</weight>\n" "<original_word>%s</original_word>\n" "</node>\n", qnodes[i].word_st.string, qnodes[i].word_st.id, sb_strbin(qnodes[i].field, sizeof(qnodes[i].field)), qnodes[i].opParam, qnodes[i].weight, qnodes[i].original_word); } else { ap_rprintf(r, "<node type=\"OPERATOR\">\n" "<operator>%s</operator>\n" "<num_of_operands>%d</num_of_operands>\n" "<opParam>%d</opParam>\n" "<weight>%f</weight>\n" "<original_word>%s</original_word>\n" "</node>\n", gOperatorNames[qnodes[i].operator], qnodes[i].num_of_operands, qnodes[i].opParam, qnodes[i].weight, qnodes[i].original_word); } } ap_rprintf(r, "</xml>\n"); return SUCCESS; }
static int search_handler(request_rec *r, softbot_handler_rec *s) { int rv = 0; int i = 0, j = 0, cmt_idx = 0, deleted_cnt = 0; struct timeval tv; uint32_t start_time = 0, end_time = 0; char content_type[SHORT_STRING_SIZE+1]; init_server(r, s); if ( print_elapsed_time ) { gettimeofday(&tv, NULL); start_time = tv.tv_sec*1000 + tv.tv_usec/1000; } msg_record_init(&s->msg); set_con_config(r->server); rv = sb_run_qp_init(); if(rv != SUCCESS && rv != DECLINE) { MSG_RECORD(&s->msg, error, "qp init failed"); return FAIL; } if(apr_table_get(s->parameters_in, "q") == NULL || strlen(apr_table_get(s->parameters_in, "q")) == 0) { MSG_RECORD(&s->msg, error, "Parameter 'q' is null or has zero length. query is null." " You have to input a valid query or use GET method instead of POST."); return FAIL; } ap_unescape_url((char *)apr_table_get(s->parameters_in, "q")); rv = sb_run_qp_init_request(&qp_request, (char *)apr_table_get(s->parameters_in, "q")); if(rv != SUCCESS) { error("can not init request"); s->msg = qp_request.msg; return FAIL; } rv = sb_run_qp_init_response(&qp_response); if(rv != SUCCESS) { error("can not init request"); return FAIL; } //2. get result timelog("full_search_start"); rv = sb_run_qp_full_search(&qp_request, &qp_response); timelog("full_search_finish"); if (rv != SUCCESS) { error("sb_run_qp_full_search failed: query[%s]", qp_request.query); s->msg = qp_request.msg; return FAIL; } if ( qp_request.is_delete ) { int i = 0; int j = 0; int is_recovery = 0; if( qp_request.select_list.cnt > 0 && qp_request.select_list.field[0].name[0] == '0' ) { info("recovery deleted document"); is_recovery = 1; } for(i = 0; i < qp_response.vdl->cnt; i++) { for(j = 0; j < qp_response.vdl->data[i].dochit_cnt; j++) { int rv = 0; uint32_t docid = qp_response.vdl->data[i].dochits[j].id; docattr_t* docattr = NULL; debug("delete docid[%u]", docid); rv = sb_run_docattr_ptr_get(docid, &docattr); if ( rv < 0 ) { error("cannot get docattr of docid[%u]", docid); continue; } if( is_recovery ) { rv = sb_run_docattr_set_docattr_function(docattr, "Delete", "0"); } else { rv = sb_run_docattr_set_docattr_function(docattr, "Delete", "1"); } if ( rv < 0 ) { error("cannot delete docid[%u]", docid); continue; } deleted_cnt++; } } } if ( print_elapsed_time ) { gettimeofday(&tv, NULL); end_time = tv.tv_sec*1000 + tv.tv_usec/1000; } timelog("send_result_start"); snprintf( content_type, SHORT_STRING_SIZE, "text/xml; charset=%s", default_charset); ap_set_content_type(r, content_type); ap_rprintf(r, "<?xml version=\"1.0\" encoding=\"%s\"?>\n", default_charset); ap_rprintf(r, "<xml>\n" "<status>1</status>\n" "<query><![CDATA[%s]]></query>\n" "<parsed_query><![CDATA[%s]]></parsed_query>\n" "<result_count>%d</result_count>\n", qp_request.query, qp_response.parsed_query, qp_response.search_result); if ( qp_request.is_delete ) { ap_rprintf(r, "<deleted_count>%d</deleted_count>\n", deleted_cnt); } if(server_id[0] == '\0') { ap_rprintf(r, "<server_id><![CDATA[%s]]></server_id>\n", get_ipaddress(r->pool)); } else { ap_rprintf(r, "<server_id><![CDATA[%s]]></server_id>\n", server_id); } /* elapsed time */ if ( print_elapsed_time ) { ap_rprintf(r, "<elapsed_time>%u</elapsed_time>\n", end_time - start_time); } /* group result */ ap_rprintf(r, "<groups count=\"%d\">\n", qp_response.groupby_result_vid.rules.cnt); print_group(r, &qp_response.groupby_result_vid); ap_rprintf(r, "</groups>\n"); /* ap_rprintf(r, "<groups type=\"did\">\n"); print_group(r, &qp_response.groupby_result_did); ap_rprintf(r, "</groups>\n"); */ if( qp_request.is_delete ) { } else { /* each result */ ap_rprintf(r, "<vdocs count=\"%d\">\n", qp_response.vdl->cnt); for(i = 0; i < qp_response.vdl->cnt; i++) { virtual_document_t* vd = (virtual_document_t*)&qp_response.vdl->data[i]; ap_rprintf(r, "<vdoc vid=\"%d\" node_id=\"%0X\" relevance=\"%d\">\n", vd->id, vd->node_id, vd->relevance); ap_rprintf(r, "<docs count=\"%d\">\n", vd->comment_cnt); for(j = 0; j < vd->comment_cnt; j++) { comment_t* cmt = &qp_response.comments[cmt_idx++]; ap_rprintf(r, "<doc doc_id=\"%d\">\n", cmt->did); if(qp_request.output_style == STYLE_XML) { ap_rprintf(r, "%s\n", cmt->s); } else { ap_rprintf(r, "<![CDATA[%s]]>\n", cmt->s); } ap_rprintf(r, "</doc>\n"); } ap_rprintf(r, "</docs>\n"); ap_rprintf(r, "</vdoc>\n"); } ap_rprintf(r, "</vdocs>\n"); } ap_rprintf(r, "</xml>\n"); timelog("send_result_finish"); s->msg = qp_request.msg; sb_run_qp_finalize_search(&qp_request, &qp_response); timelog("qp_finalize"); return SUCCESS; }
static int check_auth_cookie(request_rec *r) { const char *cookies = NULL, *auth_line = NULL; char *cookie = NULL; /* Debug. */ /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "check_auth_cookie called");*/ /* Get config for this directory. */ cookie_auth_config_rec *conf = ap_get_module_config(r->per_dir_config, &auth_cookie_module); /* Check we have been configured. */ if (!conf->cookie_auth_cookie) { return DECLINED; } /* Do not override real auth header, unless config instructs us to. */ if (!conf->cookie_auth_override && apr_table_get(r->headers_in, "Authorization")) { if (conf->cookie_auth_env) { unsetenv(conf->cookie_auth_env); } return DECLINED; } /* todo: protect against xxxCookieNamexxx, regex? */ /* todo: make case insensitive? */ /* Get the cookie (code from mod_log_config). */ if ((cookies = apr_table_get(r->headers_in, "Cookie"))) { char *start_cookie, *end_cookie; if ((start_cookie = ap_strstr_c(cookies, conf->cookie_auth_cookie))) { start_cookie += strlen(conf->cookie_auth_cookie) + 1; cookie = apr_pstrdup(r->pool, start_cookie); /* kill everything in cookie after ';' */ end_cookie = strchr(cookie, ';'); if (end_cookie) { *end_cookie = '\0'; } ap_unescape_url(cookie); } } /* No cookie? Nothing for us to do. */ if (!cookie) { if (conf->cookie_auth_unauth_redirect) { const char* redirect = conf->cookie_auth_unauth_redirect; compose_and_set_redirect(r, redirect); return HTTP_MOVED_TEMPORARILY; } else { return DECLINED; } } /* Debug. */ /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "%s=%s", conf->cookie_auth_cookie, cookie);*/ char* aux_auth_info = ""; /* Construct the fake auth_line. */ if (conf->cookie_auth_base64) { char* decoded_cookie = apr_palloc(r->pool, apr_base64_decode_len(cookie)); int decoded_cookie_length = apr_base64_decode(decoded_cookie, cookie); int valid = 1; /* if the cookie is encrypted, decrypt it in place */ if (conf->cookie_auth_encrypt) { MCRYPT td = mcrypt_module_open("rijndael-128", NULL, "cbc", NULL); int keysize = strlen(conf->cookie_auth_encrypt); int blocksize = mcrypt_enc_get_block_size(td); // We will copy the iv from the beginning of the cookie. // The iv does not need to be null-terminated, but we will // null-terminate it for convenience. int iv_length = mcrypt_enc_get_iv_size(td); char* iv = (char*) apr_palloc(r->pool, iv_length + 1); memcpy(iv, decoded_cookie, iv_length); iv[iv_length] = '\0'; // Take the iv off the beginning of the cookie decoded_cookie += iv_length; decoded_cookie_length -= iv_length; mcrypt_generic_init( td, conf->cookie_auth_encrypt, keysize, iv); // Encryption in CBC is performed in blocks, so our // decryption string will always be an integral number // of full blocks. char* decrypt_ptr = decoded_cookie; while (decoded_cookie_length >= blocksize) { mdecrypt_generic(td, decrypt_ptr, blocksize); decrypt_ptr += blocksize; decoded_cookie_length -= blocksize; } if (decoded_cookie_length != 0) { valid = 0; } mcrypt_generic_deinit (td); mcrypt_module_close(td); /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "mdecrypt(%s)=%s", conf->cookie_auth_cookie, decoded_cookie);*/ } /* if the cookie did not decrypt, then do nothing */ if (valid) { char* end_auth_info = strchr(decoded_cookie, '\t'); if (end_auth_info) { aux_auth_info = decoded_cookie; char* unencoded_cookie = end_auth_info + 1; *end_auth_info = 0; auth_line = apr_pstrcat(r->pool, "Basic ", ap_pbase64encode(r->pool, unencoded_cookie), NULL); } else { auth_line = apr_pstrcat(r->pool, "Basic ", ap_pbase64encode(r->pool, decoded_cookie), NULL); } } } else { // Aux auth info and cookie encrypt features only available in base64 mode ap_unescape_url(cookie); auth_line = apr_pstrcat(r->pool, "Basic ", ap_pbase64encode(r->pool, cookie), NULL); } /* If there is aux auth info, then set the env variable */ if (conf->cookie_auth_env) { apr_table_set(r->subprocess_env, conf->cookie_auth_env, aux_auth_info); } /* Debug. */ /*ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Authorization: %s", auth_line);*/ /* If there is no aux auth info, then force a redirect if our conf directives say that we should */ if (conf->cookie_auth_env_redirect && !strlen(aux_auth_info)) { const char* redirect = conf->cookie_auth_env_redirect; compose_and_set_redirect(r, redirect); return HTTP_MOVED_TEMPORARILY; } else { /* Set fake auth_line. */ if (auth_line) { apr_table_set(r->headers_in, "Authorization", auth_line); } } /* Always return DECLINED because we don't authorize, */ /* we just set things up for the next auth module to. */ return DECLINED; }
static PyObject *parse_qsl(PyObject *self, PyObject *args) { PyObject *pairs; int i, len; PyObject *qso; char unicode = 0; char *qs = NULL; int keep_blank_values = 0; int strict_parsing = 0; /* XXX not implemented */ if (! PyArg_ParseTuple(args, "O|ii", &qso, &keep_blank_values, &strict_parsing)) return NULL; /* error */ if (PyUnicode_Check(qso)) unicode = 1; MP_ANYSTR_AS_STR(qs, qso, 1); if (!qs) { Py_DECREF(qso); /* MP_ANYSTR_AS_STR */ return NULL; } /* split query string by '&' and ';' into a list of pairs */ pairs = PyList_New(0); if (pairs == NULL) { Py_DECREF(qso); /* MP_ANYSTR_AS_STR */ return NULL; } i = 0; len = strlen(qs); while (i < len) { PyObject *pair, *key, *val; char *cpair, *ckey, *cval; int plen, j, p, k, v; pair = PyBytes_FromStringAndSize(NULL, len); if (pair == NULL) return NULL; /* split by '&' or ';' */ cpair = PyBytes_AS_STRING(pair); j = 0; while ((qs[i] != '&') && (qs[i] != ';') && (i < len)) { /* replace '+' with ' ' */ cpair[j] = (qs[i] == '+') ? ' ' : qs[i]; i++; j++; } if (j == 0) { Py_XDECREF(pair); i++; continue; } cpair[j] = '\0'; _PyBytes_Resize(&pair, j); cpair = PyBytes_AS_STRING(pair); /* split the "abc=def" pair */ plen = strlen(cpair); key = PyBytes_FromStringAndSize(NULL, plen); if (key == NULL) { Py_DECREF(qso); /* MP_ANYSTR_AS_STR */ return NULL; } val = PyBytes_FromStringAndSize(NULL, plen); if (val == NULL) { Py_DECREF(qso); /* MP_ANYSTR_AS_STR */ return NULL; } ckey = PyBytes_AS_STRING(key); cval = PyBytes_AS_STRING(val); p = 0; k = 0; v = 0; while (p < plen) { if (cpair[p] != '=') { ckey[k] = cpair[p]; k++; p++; } else { p++; /* skip '=' */ while (p < plen) { cval[v] = cpair[p]; v++; p++; } } } ckey[k] = '\0'; cval[v] = '\0'; if (keep_blank_values || (v > 0)) { ap_unescape_url(ckey); ap_unescape_url(cval); _PyBytes_Resize(&key, strlen(ckey)); _PyBytes_Resize(&val, strlen(cval)); if (key && val) { PyObject *listitem = NULL; if (unicode) { PyObject *ukey, *uval; ukey = PyUnicode_DecodeLatin1(ckey, strlen(ckey), NULL); uval = PyUnicode_DecodeLatin1(cval, strlen(cval), NULL); listitem = Py_BuildValue("(O,O)", ukey, uval); Py_DECREF(ukey); Py_DECREF(uval); } else listitem = Py_BuildValue("(O,O)", key, val); if(listitem) { PyList_Append(pairs, listitem); Py_DECREF(listitem); } } } Py_XDECREF(pair); Py_XDECREF(key); Py_XDECREF(val); i++; } Py_DECREF(qso); return pairs; }
static PyObject *parse_qs(PyObject *self, PyObject *args) { PyObject *pairs, *dict; int i, n, len, lsize; char *qs; PyObject *qso; char unicode = 0; int keep_blank_values = 0; int strict_parsing = 0; /* XXX not implemented */ if (! PyArg_ParseTuple(args, "O|ii", &qso, &keep_blank_values, &strict_parsing)) return NULL; /* error */ if (PyUnicode_Check(qso)) unicode = 1; MP_ANYSTR_AS_STR(qs, qso, 1); if (!qs) { Py_DECREF(qso); /* MP_ANYSTR_AS_STR */ return NULL; } /* split query string by '&' and ';' into a list of pairs */ pairs = PyList_New(0); if (pairs == NULL) { Py_DECREF(qso); return NULL; } i = 0; len = strlen(qs); while (i < len) { PyObject *pair; char *cpair; int j = 0; pair = PyBytes_FromStringAndSize(NULL, len); if (pair == NULL) { Py_DECREF(qso); return NULL; } /* split by '&' or ';' */ cpair = PyBytes_AS_STRING(pair); while ((qs[i] != '&') && (qs[i] != ';') && (i < len)) { /* replace '+' with ' ' */ cpair[j] = (qs[i] == '+') ? ' ' : qs[i]; i++; j++; } if (j) { _PyBytes_Resize(&pair, j); if (pair) PyList_Append(pairs, pair); } Py_XDECREF(pair); i++; } Py_DECREF(qso); /* MP_ANYSTR_AS_STR */ /* * now we have a list of "abc=def" string (pairs), let's split * them all by '=' and put them in a dictionary. */ dict = PyDict_New(); if (dict == NULL) return NULL; lsize = PyList_Size(pairs); n = 0; while (n < lsize) { PyObject *pair, *key, *val; char *cpair, *ckey, *cval; int k, v; pair = PyList_GET_ITEM(pairs, n); cpair = PyBytes_AS_STRING(pair); len = strlen(cpair); key = PyBytes_FromStringAndSize(NULL, len); if (key == NULL) return NULL; val = PyBytes_FromStringAndSize(NULL, len); if (val == NULL) return NULL; ckey = PyBytes_AS_STRING(key); cval = PyBytes_AS_STRING(val); i = 0; k = 0; v = 0; while (i < len) { if (cpair[i] != '=') { ckey[k] = cpair[i]; k++; i++; } else { i++; /* skip '=' */ while (i < len) { cval[v] = cpair[i]; v++; i++; } } } ckey[k] = '\0'; cval[v] = '\0'; if (keep_blank_values || (v > 0)) { ap_unescape_url(ckey); ap_unescape_url(cval); _PyBytes_Resize(&key, strlen(ckey)); _PyBytes_Resize(&val, strlen(cval)); if (key && val) { ckey = PyBytes_AS_STRING(key); cval = PyBytes_AS_STRING(val); if (unicode) { PyObject *list, *ukey, *uval; ukey = PyUnicode_DecodeLatin1(ckey, strlen(ckey), NULL); uval = PyUnicode_DecodeLatin1(ckey, strlen(cval), NULL); list = PyDict_GetItem(dict, ukey); if (list) { PyList_Append(list, uval); Py_DECREF(uval); } else { list = Py_BuildValue("[O]", uval); PyDict_SetItem(dict, ukey, list); Py_DECREF(ukey); Py_DECREF(list); } } else { PyObject *list; list = PyDict_GetItem(dict, key); if (list) PyList_Append(list, val); else { list = Py_BuildValue("[O]", val); PyDict_SetItem(dict, key, list); Py_DECREF(list); } } } } Py_XDECREF(key); Py_XDECREF(val); n++; } Py_DECREF(pairs); return dict; }
static osrfStringArray* apacheParseParms(request_rec* r) { if( r == NULL ) return NULL; //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "got a valid request_rec"); char* arg = NULL; apr_pool_t *p = r->pool; /* memory pool */ growing_buffer* buffer = buffer_init(1025); /* gather the post args and append them to the url query string */ if( !strcmp(r->method,"POST") ) { ap_setup_client_block(r, REQUEST_CHUNKED_DECHUNK); //osrfLogDebug(OSRF_LOG_MARK, "gateway reading post data.."); //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "idlchunk reading post data.."); if(ap_should_client_block(r)) { /* Start with url query string, if any */ if(r->args && r->args[0]) buffer_add(buffer, r->args); char body[1025]; //osrfLogDebug(OSRF_LOG_MARK, "gateway client has post data, reading..."); /* Append POST data */ long bread; while( (bread = ap_get_client_block(r, body, sizeof(body) - 1)) ) { if(bread < 0) { //osrfLogInfo(OSRF_LOG_MARK, // "ap_get_client_block(): returned error, exiting POST reader"); break; } body[bread] = '\0'; buffer_add( buffer, body ); //osrfLogDebug(OSRF_LOG_MARK, // "gateway read %ld bytes: %d bytes of data so far", bread, buffer->n_used); if(buffer->n_used > APACHE_TOOLS_MAX_POST_SIZE) { //osrfLogError(OSRF_LOG_MARK, "gateway received POST larger " // "than %d bytes. dropping request", APACHE_TOOLS_MAX_POST_SIZE); buffer_free(buffer); return NULL; } } //osrfLogDebug(OSRF_LOG_MARK, "gateway done reading post data"); } } else { /* GET */ if(r->args && r->args[0]) buffer_add(buffer, r->args); //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "idlchunk read GET data.."); } if(buffer->n_used > 0) arg = apr_pstrdup(p, buffer->buf); else arg = NULL; buffer_free(buffer); if( !arg || !arg[0] ) { /* we received no request */ return NULL; } //osrfLogDebug(OSRF_LOG_MARK, "parsing URL params from post/get request data: %s", arg); //ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "parsing URL params from post/get request data: %s", arg); osrfStringArray* sarray = osrfNewStringArray(12); /* method parameters */ int sanity = 0; char* key = NULL; /* query item name */ char* val = NULL; /* query item value */ /* Parse the post/get request data into a series of name/value pairs. */ /* Load each name into an even-numbered slot of an osrfStringArray, and */ /* the corresponding value into the following odd-numbered slot. */ while( arg && (val = ap_getword(p, (const char**) &arg, '&'))) { key = ap_getword(r->pool, (const char**) &val, '='); if(!key || !key[0]) break; ap_unescape_url(key); ap_unescape_url(val); //osrfLogDebug(OSRF_LOG_MARK, "parsed URL params %s=%s", key, val); osrfStringArrayAdd(sarray, key); osrfStringArrayAdd(sarray, val); if( sanity++ > 1000 ) { //osrfLogError(OSRF_LOG_MARK, // "Parsing URL params failed sanity check: 1000 iterations"); osrfStringArrayFree(sarray); return NULL; } } //osrfLogDebug(OSRF_LOG_MARK, // "Apache tools parsed %d params key/values", sarray->size / 2 ); return sarray; }
static int abstract_search_handler(request_rec *r, softbot_handler_rec *s) { int rv = 0; int i = 0; int recv_pos = 0; memfile *buf = NULL; virtual_document_t* vd = NULL; int max_doc_hits_size = 0; sb_run_qp_get_max_doc_hits_size( &max_doc_hits_size ); init_server(r, s); set_con_config(r->server); msg_record_init(&s->msg); rv = sb_run_qp_init(); if(rv != SUCCESS && rv != DECLINE) { MSG_RECORD(&s->msg, error, "qp init failed"); return FAIL; } if(apr_table_get(s->parameters_in, "q") == NULL || strlen(apr_table_get(s->parameters_in, "q")) == 0) { MSG_RECORD(&s->msg, error, "query is null, must use http get method"); return FAIL; } ap_unescape_url((char *)apr_table_get(s->parameters_in, "q")); rv = sb_run_qp_init_request(&qp_request, (char *)apr_table_get(s->parameters_in, "q")); if(rv != SUCCESS) { s->msg = qp_request.msg; error("can not init request"); return FAIL; } rv = sb_run_qp_init_response(&qp_response); if(rv != SUCCESS) { s->msg = qp_request.msg; error("can not init request"); return FAIL; } /* 수신할 doc_hit 를 assign */ qp_response.vdl->cnt = 1; vd = &(qp_response.vdl->data[0]); if(g_dochits_buffer == NULL) { g_dochits_buffer = (doc_hit_t*)sb_calloc(max_doc_hits_size, sizeof(doc_hit_t)); } vd->dochits = g_dochits_buffer; /* comment를 추출할 virtual document 정보 받기 */ CHECK_REQUEST_CONTENT_TYPE(r, "x-softbotd/binary"); if (sb_run_sbhandler_make_memfile(r, &buf) != SUCCESS) { MSG_RECORD(&s->msg, error, "make_memfile_from_postdata failed"); if(buf != NULL) memfile_free(buf); return FAIL; } vd->dochit_cnt = memfile_getSize(buf) / (sizeof(doc_hit_t) + sizeof(uint32_t)); for (i = 0; i < vd->dochit_cnt; i++) { uint32_t node_id = 0; uint32_t recv_data_size = 0; recv_data_size = sizeof(doc_hit_t); if ( memfile_read(buf, (char*)&(vd->dochits[recv_pos]), recv_data_size) != recv_data_size ) { MSG_RECORD(&s->msg, error, "incomplete result at [%d]th node: doc_hits ", i); if(buf != NULL) memfile_free(buf); return FAIL; } // 2. node_id 수신 recv_data_size = sizeof(uint32_t); if ( memfile_read(buf, (char*)&node_id, recv_data_size) != recv_data_size ) { MSG_RECORD(&s->msg, error, "incomplete result at [%d]th node: node_id ", i); if(buf != NULL) memfile_free(buf); return FAIL; } // 자신의 node_id가 아니면 error if(get_node_id(node_id) != this_node_id) { MSG_RECORD(&s->msg, error, "node_id[%u] not equals this_node_id[%0X]", get_node_id(node_id), this_node_id); if(buf != NULL) memfile_free(buf); return FAIL; } debug("did[%u], node_id[%0X]", vd->dochits[recv_pos].id, node_id); // 자신의 node_id pop node_id = pop_node_id(node_id); recv_pos++; } vd->dochit_cnt = recv_pos; /* comment 추출 */ timelog("sb_run_qp_abstract_search start"); rv = sb_run_qp_abstract_search(&qp_request, &qp_response); timelog("sb_run_qp_abstract_search finish"); if (rv != SUCCESS) { s->msg = qp_request.msg; error("sb_run_qp_abstract_search failed: query[%s]", qp_request.query); if(buf != NULL) memfile_free(buf); return FAIL; } /////////// abstarct search 결과 전송 //////////////////////////////////////// ap_set_content_type(r, "x-softbotd/binary"); // 1. 전송건수. ap_rwrite(&vd->comment_cnt, sizeof(uint32_t), r); // 2. doc_hits 전송. for (i = 0; i < vd->comment_cnt; i++ ) { // 2.1 doc_id 전송. ap_rwrite(&vd->dochits[i].id, sizeof(uint32_t), r); // 2.2 node_id 전송. ap_rwrite(&this_node_id, sizeof(uint32_t), r); // 2.3. comment ap_rwrite(qp_response.comments[i].s, LONG_LONG_STRING_SIZE, r); debug("comments[%s]", qp_response.comments[i].s); } // log를 위하여 setting 해준다. qp_response.search_result = vd->comment_cnt; s->msg = qp_request.msg; if(buf != NULL) memfile_free(buf); return SUCCESS; }
static PyObject *parse_qsl(PyObject *self, PyObject *args, PyObject *kw) { PyObject *pairs; int i, len; char *qs; int keep_blank_values = 0; int strict_parsing = 0; /* XXX not implemented */ char *keywords[] = { "qs", "keep_blank_values", "strict_parsing", 0 }; if (! PyArg_ParseTupleAndKeywords(args, kw, "s|ii", keywords, &qs, &keep_blank_values, &strict_parsing)) return NULL; /* error */ /* split query string by '&' and ';' into a list of pairs */ /* PYTHON 2.5: 'PyList_New' uses Py_ssize_t for input parameters */ pairs = PyList_New(0); if (pairs == NULL) return NULL; i = 0; len = strlen(qs); while (i < len) { PyObject *pair, *key, *val; char *cpair, *ckey, *cval; int plen, j, p, k, v; /* PYTHON 2.5: 'PyString_FromStringAndSize' uses Py_ssize_t for input parameters */ pair = PyString_FromStringAndSize(NULL, len); if (pair == NULL) return NULL; /* split by '&' or ';' */ cpair = PyString_AS_STRING(pair); j = 0; while ((qs[i] != '&') && (qs[i] != ';') && (i < len)) { /* replace '+' with ' ' */ cpair[j] = (qs[i] == '+') ? ' ' : qs[i]; i++; j++; } if (j == 0) { Py_XDECREF(pair); i++; continue; } cpair[j] = '\0'; /* PYTHON 2.5: '_PyString_Resize' uses Py_ssize_t for input parameters */ _PyString_Resize(&pair, j); cpair = PyString_AS_STRING(pair); /* split the "abc=def" pair */ plen = strlen(cpair); /* PYTHON 2.5: 'PyString_FromStringAndSize' uses Py_ssize_t for input parameters */ key = PyString_FromStringAndSize(NULL, plen); if (key == NULL) return NULL; /* PYTHON 2.5: 'PyString_FromStringAndSize' uses Py_ssize_t for input parameters */ val = PyString_FromStringAndSize(NULL, plen); if (val == NULL) return NULL; ckey = PyString_AS_STRING(key); cval = PyString_AS_STRING(val); p = 0; k = 0; v = 0; while (p < plen) { if (cpair[p] != '=') { ckey[k] = cpair[p]; k++; p++; } else { p++; /* skip '=' */ while (p < plen) { cval[v] = cpair[p]; v++; p++; } } } ckey[k] = '\0'; cval[v] = '\0'; if (keep_blank_values || (v > 0)) { ap_unescape_url(ckey); ap_unescape_url(cval); /* PYTHON 2.5: '_PyString_Resize' uses Py_ssize_t for input parameters */ _PyString_Resize(&key, strlen(ckey)); /* PYTHON 2.5: '_PyString_Resize' uses Py_ssize_t for input parameters */ _PyString_Resize(&val, strlen(cval)); if (key && val) { PyObject* listitem = Py_BuildValue("(O,O)", key, val); if(listitem) { PyList_Append(pairs, listitem); Py_DECREF(listitem); } } } Py_XDECREF(pair); Py_XDECREF(key); Py_XDECREF(val); i++; } return pairs; }
/* * resolves the code received from the OP in to an access_token and id_token and returns the parsed contents */ apr_byte_t oidc_proto_resolve_code(request_rec *r, oidc_cfg *cfg, oidc_provider_t *provider, const char *code, char **s_idtoken, char **s_access_token, char **s_token_type) { ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r, "oidc_proto_resolve_code: entering"); const char *response = NULL; /* assemble the parameters for a call to the token endpoint */ apr_table_t *params = apr_table_make(r->pool, 5); apr_table_addn(params, "grant_type", "authorization_code"); apr_table_addn(params, "code", code); apr_table_addn(params, "redirect_uri", cfg->redirect_uri); /* see if we need to do basic auth or auth-through-post-params (both applied through the HTTP POST method though) */ const char *basic_auth = NULL; if ((apr_strnatcmp(provider->token_endpoint_auth, "client_secret_basic")) == 0) { basic_auth = apr_psprintf(r->pool, "%s:%s", provider->client_id, provider->client_secret); } else { apr_table_addn(params, "client_id", provider->client_id); apr_table_addn(params, "client_secret", provider->client_secret); } /* see if we've configured any extra static parameters to the token endpoint */ if (provider->token_endpoint_params != NULL) { const char *key, *val; const char *p = provider->token_endpoint_params; while (*p && (val = ap_getword(r->pool, &p, '&'))) { key = ap_getword(r->pool, &val, '='); ap_unescape_url((char *) key); ap_unescape_url((char *) val); apr_table_addn(params, key, val); } } /* resolve the code against the token endpoint */ if (oidc_util_http_post_form(r, provider->token_endpoint_url, params, basic_auth, NULL, provider->ssl_validate_server, &response, cfg->http_timeout_long, cfg->outgoing_proxy) == FALSE) { ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r, "oidc_proto_resolve_code: could not successfully resolve the \"code\" (%s) against the token endpoint (%s)", code, provider->token_endpoint_url); return FALSE; } /* check for errors, the response itself will have been logged already */ json_t *result = NULL; if (oidc_util_decode_json_and_check_error(r, response, &result) == FALSE) return FALSE; /* get the access_token from the parsed response */ json_t *access_token = json_object_get(result, "access_token"); if ((access_token != NULL) && (json_is_string(access_token))) { *s_access_token = apr_pstrdup(r->pool, json_string_value(access_token)); /* log and set the obtained acces_token */ ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r, "oidc_proto_resolve_code: returned access_token: %s", *s_access_token); /* the provider must return the token type */ json_t *token_type = json_object_get(result, "token_type"); if ((token_type == NULL) || (!json_is_string(token_type))) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "oidc_proto_resolve_code: response JSON object did not contain a token_type string"); json_decref(result); return FALSE; } *s_token_type = apr_pstrdup(r->pool, json_string_value(token_type)); } else { ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r, "oidc_proto_resolve_code: response JSON object did not contain an access_token string"); } /* get the id_token from the response */ json_t *id_token = json_object_get(result, "id_token"); if ((id_token != NULL) && (json_is_string(id_token))) { *s_idtoken = apr_pstrdup(r->pool, json_string_value(id_token)); /* log and set the obtained id_token */ ap_log_rerror(APLOG_MARK, OIDC_DEBUG, 0, r, "oidc_proto_resolve_code: returned id_token: %s", *s_idtoken); } json_decref(result); return TRUE; }
static int handle_request(request_rec *r) { tmcdreq_t tmcdreq, *reqp = &tmcdreq; tmcdresp_t *response = NULL; char *command; struct in_addr local_addr; struct in_addr remote_addr; struct sockaddr_in redir_client; int tmcd_status; int status = OK; char *status_line = NULL; char *args = NULL; char *function_args = NULL; char *p; char **argv = NULL; int argc, i; reqp->istcp = 1; reqp->isssl = 1; /* FIXME */ if (strcmp(r->handler, "tmcd")) { status = DECLINED; goto err; } #if 0 r->allowed |= (AP_METHOD_BIT << M_GET); if (r->method_number != M_GET) { status = DECLINED; goto err; } #endif memset(reqp, 0, sizeof(*reqp)); local_addr = r->connection->local_addr.sin_addr; remote_addr = r->connection->remote_addr.sin_addr; reqp->version = 1; /* FIXME need sane default */ tmcd_init(reqp, &local_addr, NULL); command = r->path_info; while (*command && *command == '/') { command++; } if (command[0] == '\0') { status = HTTP_BAD_REQUEST; goto err; } if (r->args) { args = malloc(strlen(r->args) + 1); if (args == NULL) { status = HTTP_INTERNAL_SERVER_ERROR; goto err; } strcpy(args, r->args); argv = make_argv(args, &argc, '&'); if (argv == NULL) { status = HTTP_INTERNAL_SERVER_ERROR; goto err; } for (i = 0; i < argc; i++) { /* Unescape the arguments */ p = args; while (*p) { if (*p == '+') *p = ' '; p++; } status = ap_unescape_url(args); if (status != OK) { goto err; } if (strncasecmp(argv[i], "version=", 8) == 0) { long version; char *end; version = strtol(argv[i] + 8, &end, 10); if (*end != '\0' || *(argv[i] + 8) == '\0') { status = HTTP_BAD_REQUEST; status_line = "Invalid Version"; goto err; } reqp->version = version; } else if (strncasecmp(argv[i], "redirect=", 9) == 0) { if (inet_pton(AF_INET, argv[i] + 9, &redir_client.sin_addr) <= 0) { status = HTTP_BAD_REQUEST; status_line = "Invalid IP Address"; goto err; } /* FIXME info message */ if (remote_addr.s_addr != local_addr.s_addr) { status = HTTP_FORBIDDEN; status_line = "Redirection Not Allowed"; goto err; } remote_addr = redir_client.sin_addr; } else if (strncasecmp(argv[i], "vnodeid=", 8) == 0) { if (strlen(argv[i] + 8) >= sizeof(reqp->vnodeid)) { status = HTTP_BAD_REQUEST; status_line = "Virtual Node ID Too Long"; goto err; } reqp->isvnode = 1; strcpy(reqp->vnodeid, argv[i] + 8); } else if (strncasecmp(argv[i], "args=", 5) == 0) { function_args = argv[i] + 5; } } } /* FIXME handle wanodekey */ if ((tmcd_status = iptonodeid(reqp, remote_addr, NULL))) { if (reqp->isvnode) { status_line = "Invalid Virtual Node"; } else { status_line = "Invalid Node"; } status = HTTP_NOT_FOUND; goto err; } if (reqp->tmcd_redirect[0]) { /* FIXME what if https should be used? */ /* FIXME do I need to specify the args should be passed too? */ char *uri = ap_psprintf(r->pool, "http://%s%s?%s", reqp->tmcd_redirect, r->uri, r->args); ap_table_setn(r->headers_out, "Location", uri); status = HTTP_MOVED_TEMPORARILY; goto done; } tmcd_status = tmcd_handle_request(reqp, &response, command, function_args); if (tmcd_status == TMCD_STATUS_OK) { r->content_type = response->type; ap_set_content_length(r, response->length); /* FIXME doctype */ ap_soft_timeout("tmcd response call trace", r); ap_send_http_header(r); ap_rprintf(r, "%s", response->data); ap_kill_timeout(r); status = OK; goto done; } else { switch(tmcd_status) { case TMCD_STATUS_UNKNOWN_COMMAND: status = HTTP_NOT_FOUND; status_line = "Unknown Command"; break; case TMCD_STATUS_REQUIRES_ENCRYPTION: status = HTTP_FORBIDDEN; status_line = "SSL Required"; break; case TMCD_STATUS_NODE_NOT_ALLOCATED: status = HTTP_FORBIDDEN; status_line = "Node Not Allocated"; break; case TMCD_STATUS_COMMAND_FAILED: status = HTTP_INTERNAL_SERVER_ERROR; if (response && response->data) { status_line = response->data; } break; case TMCD_STATUS_MALLOC_FAILED: status = HTTP_INTERNAL_SERVER_ERROR; break; } goto err; } err: done: if (argv) free(argv); if (args) free(args); if (response) tmcd_free_response(response); if (status_line) { r->status_line = ap_psprintf(r->pool, "%3.3u %s", status, status_line); } return status; }
/* * ic_send_request() * ----------------- * Send the client's page/form request to the Interchange server */ static int ic_send_request(request_rec *r,ic_conf_rec *conf_rec,BUFF *ic_buff) { char **env,**e,*rp; int env_count,rc; char request_uri[MAX_STRING_LEN]; char redirect_url[MAX_STRING_LEN]; /* * send the Interchange-link arg parameter * (this is always empty for a CGI request) */ ap_hard_timeout("ic_send_request",r); if (ap_bputs("arg 0\n",ic_buff) < 0){ ap_log_reason("error writing to Interchange",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } ap_reset_timeout(r); /* * initialize the environment to send to Interchange */ ap_add_common_vars(r); ap_add_cgi_vars(r); env = ap_create_environment(r->pool,r->subprocess_env); /* * count the number of environment variables present */ for (e = env,env_count = 0; *e != NULL; e++,env_count++){ if (strncmp(*e,"PATH_INFO=",10) == 0) env_count--; } env_count++; /* * send the environment variable count to Interchange */ if (ap_bprintf(ic_buff,"env %d\n",env_count) < 0){ ap_log_reason("error writing to Interchange",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } ap_reset_timeout(r); /* * ignore the PATH_INFO variable and fix the SCRIPT_NAME, * REQUEST_URI and REDIRECT_URL variable content */ request_uri[0] = '\0'; redirect_url[0] = '\0'; for (e = env; *e != NULL; e++){ int len; char tmp[MAX_STRING_LEN]; char *p = *e; if (strncmp(p,"PATH_INFO=",10) == 0) continue; if (strncmp(p,"REDIRECT_URL=",13) == 0){ strncpy(redirect_url,p + 13,MAX_STRING_LEN - 14); continue; } if (strncmp(p,"REQUEST_URI=",12) == 0) strncpy(request_uri,p + 12,MAX_STRING_LEN - 13); else if (strncmp(p,"SCRIPT_NAME=",12) == 0){ p = tmp; strcpy(p,"SCRIPT_NAME="); if (conf_rec->script_name[0]) strcat(p,conf_rec->script_name); else{ strcat(p,"/"); strcat(p,conf_rec->location); } } len = strlen(p); if (len && ap_bprintf(ic_buff,"%d %s\n",len,p) < 0){ ap_log_reason("error writing to Interchange",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } } rp = request_uri; while (*rp == '/') rp++; /* * strip the location path from the request_uri string * unless the location is "/" */ if (conf_rec->location[0] != '\0'){ if (strncmp(rp,conf_rec->location,conf_rec->location_len) == 0) rp += conf_rec->location_len; }else{ if (rp != request_uri) rp--; } strncpy(request_uri,rp,MAX_STRING_LEN - 1); request_uri[MAX_STRING_LEN - 1] = '\0'; for (rp = request_uri; *rp != '\0'; rp++){ if (*rp == '?'){ *rp = '\0'; break; } } switch (ap_unescape_url(request_uri)){ case BAD_REQUEST: case NOT_FOUND: ap_log_reason("Bad URI entities found",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } /* * send the PATH_INFO variable as our "fixed" REQUEST_URI */ if (ap_bprintf(ic_buff,"%d PATH_INFO=%s\n",strlen(request_uri) + 10,request_uri) < 0){ ap_log_reason("error writing to Interchange",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } /* * check if we have a REDIRECT_URL * if so then give it the same "fixes" as PATH_INFO (REQUEST_URI) */ if (redirect_url[0] != '\0'){ rp = redirect_url; while (*rp == '/') rp++; /* * strip the location path from the request_uri string * unless the location is "/" */ if (conf_rec->location[0] != '\0'){ if (strncmp(rp,conf_rec->location,conf_rec->location_len) == 0) rp += conf_rec->location_len; }else{ if (rp != redirect_url) rp--; } strncpy(redirect_url,rp,MAX_STRING_LEN - 1); redirect_url[MAX_STRING_LEN - 1] = '\0'; for (rp = redirect_url; *rp != '\0'; rp++){ if (*rp == '?'){ *rp = '\0'; break; } } switch (ap_unescape_url(redirect_url)){ case BAD_REQUEST: case NOT_FOUND: ap_log_reason("Bad URI entities found",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } if (ap_bprintf(ic_buff,"%d REDIRECT_URL=%s\n",strlen(redirect_url) + 13,redirect_url) < 0){ ap_log_reason("error writing to Interchange",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } } ap_reset_timeout(r); /* * send the request body, if any */ if (ap_should_client_block(r)){ char buffer[MAX_STRING_LEN]; int len_read; long length = r->remaining; if (ap_bprintf(ic_buff,"entity\n%ld ",length) < 0){ ap_log_reason("error writing to Interchange",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } /* * read a block of data from the client and send * it to the Interchange server, until there * is nothing more to read from the client */ while ((len_read = ap_get_client_block(r,buffer,sizeof(buffer))) > 0){ ap_reset_timeout(r); if (ap_bwrite(ic_buff,buffer,len_read) != len_read){ ap_log_reason("error writing client block to Interchange",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } ap_reset_timeout(r); } if (len_read < 0){ ap_log_reason("error reading block from client",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } /* * send an end of line character to Interchange */ if (ap_bputc('\n',ic_buff) < 0){ ap_log_reason("error writing to Interchange",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } } /* * all data has been sent, so send the "end" marker */ ap_reset_timeout(r); if (ap_bputs("end\n",ic_buff) < 0){ ap_log_reason("error writing the end marker to Interchange",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } if (ap_bflush(ic_buff) < 0){ ap_log_reason("error flushing data to Interchange",r->uri,r); return HTTP_INTERNAL_SERVER_ERROR; } ap_kill_timeout(r); return OK; }
static int verify_auth_token(cdn_conf *cfg, request_rec *r) { char *last, *uri_base, *query_string, *vox_timestamp_decoded, *forwarded_list; const char *token, *vox_sig, *vox_timestamp, *ip; apr_table_t *params; struct tm ctime; long remote_east_of_utc, local_east_of_utc; time_t raw; apr_time_t vox_ts; /* URI must have '?' in it */ if (!strchr(r->unparsed_uri, '?')) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "verify_auth_token: URI %s missing '?'", r->unparsed_uri); return DECLINED; } /* The base URL of the request, without the query arguments. */ uri_base = apr_strtok(r->unparsed_uri, "?", &last); uri_base = apr_pstrcat(r->pool, cfg->to_server, uri_base, NULL); /* All of the query string parameters */ query_string = apr_strtok(NULL, "", &last); /* Convert the query string to a table */ params = apr_table_make(r->pool, 1); qs_to_table(query_string, params, r->pool); /* Get vox_sig from the parameters */ vox_sig = apr_table_get(params, "vox_sig"); if (!vox_sig) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "verify_auth_token: vox_sig missing"); return DECLINED; } /* Remove vox_sig from params so it can be regenerated */ apr_table_unset(params, "vox_sig"); /* Get vox_timestamp from the parameters */ vox_timestamp = apr_table_get(params, "vox_timestamp"); if (!vox_timestamp) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "verify_auth_token: vox_timestamp missing"); return DECLINED; } /* Parse vox_timestamp, which must be in ISO 8601 format */ memset(&ctime, 0, sizeof(struct tm)); vox_timestamp_decoded = apr_pstrdup(r->pool, vox_timestamp); ap_unescape_url(vox_timestamp_decoded); strptime(vox_timestamp_decoded, "%FT%T%z", &ctime); remote_east_of_utc = ctime.tm_gmtoff; /* have to save because mktime overwrites */ ctime.tm_isdst = -1; /* mktime needs to auto-determine DST */ raw = mktime(&ctime); local_east_of_utc = ctime.tm_gmtoff; apr_time_ansi_put(&vox_ts, raw - remote_east_of_utc + local_east_of_utc); /* verify vox_timestamp is in the future; if not, authentication has failed */ if (vox_ts < apr_time_now()) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "Authenticated URL %s is expired (expired %ld, now %ld, raw %ld, " "remote_east_of_utc %ld, local_east_of_utc %ld)", r->uri, apr_time_sec(vox_ts), apr_time_sec(apr_time_now()), raw, remote_east_of_utc, local_east_of_utc); return DECLINED; } /* compute the correct auth token using the connection's remote IP */ token = make_auth_token(r, r->connection->remote_ip, uri_base, params, cfg->auth_key); ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server, "verify_auth_token: comparing vox_sig %s with token %s " "using remote_ip %s", vox_sig, token, r->connection->remote_ip); if (!strncasecmp(token, vox_sig, SHA1_STR_SIZE)) return OK; /* if that IP didn't work, try every IP in the X-Forwarded-For header in order */ forwarded_list = (char *)apr_table_get(r->headers_in, "X-Forwarded-For"); if (forwarded_list && (forwarded_list = apr_pstrdup(r->pool, forwarded_list))) { last = NULL; if (!(ip = apr_strtok(forwarded_list, ", \t", &last))) return DECLINED; do { token = make_auth_token(r, ip, uri_base, params, cfg->auth_key); ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, r->server, "verify_auth_token: comparing vox_sig %s with token %s " "using X-Forwarded-For ip %s", vox_sig, token, ip); if (!strncasecmp(token, vox_sig, SHA1_STR_SIZE)) return OK; } while ((ip = apr_strtok(NULL, ", \t", &last))); } return DECLINED; }
/* init_ext_filter_process: get the external filter process going * This is per-filter-instance (i.e., per-request) initialization. */ static apr_status_t init_ext_filter_process(ap_filter_t *f) { ef_ctx_t *ctx = f->ctx; apr_status_t rc; ef_dir_t *dc = ctx->dc; const char * const *env; ctx->proc = apr_pcalloc(ctx->p, sizeof(*ctx->proc)); rc = apr_procattr_create(&ctx->procattr, ctx->p); ap_assert(rc == APR_SUCCESS); rc = apr_procattr_io_set(ctx->procattr, APR_CHILD_BLOCK, APR_CHILD_BLOCK, APR_CHILD_BLOCK); ap_assert(rc == APR_SUCCESS); rc = set_resource_limits(f->r, ctx->procattr); ap_assert(rc == APR_SUCCESS); if (dc->log_stderr > 0) { rc = apr_procattr_child_err_set(ctx->procattr, f->r->server->error_log, /* stderr in child */ NULL); ap_assert(rc == APR_SUCCESS); } rc = apr_procattr_child_errfn_set(ctx->procattr, child_errfn); ap_assert(rc == APR_SUCCESS); apr_pool_userdata_set(f->r, ERRFN_USERDATA_KEY, apr_pool_cleanup_null, ctx->p); rc = apr_procattr_error_check_set(ctx->procattr, 1); if (rc != APR_SUCCESS) { return rc; } /* add standard CGI variables as well as DOCUMENT_URI, DOCUMENT_PATH_INFO, * and QUERY_STRING_UNESCAPED */ ap_add_cgi_vars(f->r); ap_add_common_vars(f->r); apr_table_setn(f->r->subprocess_env, "DOCUMENT_URI", f->r->uri); apr_table_setn(f->r->subprocess_env, "DOCUMENT_PATH_INFO", f->r->path_info); if (f->r->args) { /* QUERY_STRING is added by ap_add_cgi_vars */ char *arg_copy = apr_pstrdup(f->r->pool, f->r->args); ap_unescape_url(arg_copy); apr_table_setn(f->r->subprocess_env, "QUERY_STRING_UNESCAPED", ap_escape_shell_cmd(f->r->pool, arg_copy)); } env = (const char * const *) ap_create_environment(ctx->p, f->r->subprocess_env); rc = apr_proc_create(ctx->proc, ctx->filter->command, (const char * const *)ctx->filter->args, env, /* environment */ ctx->procattr, ctx->p); if (rc != APR_SUCCESS) { ap_log_rerror(APLOG_MARK, APLOG_ERR, rc, f->r, "couldn't create child process to run `%s'", ctx->filter->command); return rc; } apr_pool_note_subprocess(ctx->p, ctx->proc, APR_KILL_AFTER_TIMEOUT); /* We don't want the handle to the child's stdin inherited by any * other processes created by httpd. Otherwise, when we close our * handle, the child won't see EOF because another handle will still * be open. */ apr_pool_cleanup_register(ctx->p, ctx->proc->in, apr_pool_cleanup_null, /* other mechanism */ ef_close_file); #if APR_FILES_AS_SOCKETS { apr_pollfd_t pfd = { 0 }; rc = apr_pollset_create(&ctx->pollset, 2, ctx->p, 0); ap_assert(rc == APR_SUCCESS); pfd.p = ctx->p; pfd.desc_type = APR_POLL_FILE; pfd.reqevents = APR_POLLOUT; pfd.desc.f = ctx->proc->in; rc = apr_pollset_add(ctx->pollset, &pfd); ap_assert(rc == APR_SUCCESS); pfd.reqevents = APR_POLLIN; pfd.desc.f = ctx->proc->out; rc = apr_pollset_add(ctx->pollset, &pfd); ap_assert(rc == APR_SUCCESS); } #endif return APR_SUCCESS; }
int spep::apache::RequestHandler::handleRequestInner( request_rec *req ) { if( !this->_spep->isStarted() ) { return HTTP_SERVICE_UNAVAILABLE; } spep::SPEPConfigData *spepConfigData = this->_spep->getSPEPConfigData(); char *properURI = apr_pstrdup( req->pool, req->parsed_uri.path ); if( req->parsed_uri.query != NULL ) { properURI = apr_psprintf( req->pool, "%s?%s", properURI, req->parsed_uri.query ); } ap_unescape_url( properURI ); Cookies cookies( req ); std::vector<std::string> cookieValues; cookies.getCookieValuesByName( cookieValues, spepConfigData->getTokenName() ); if( !cookieValues.empty() ) { std::string sessionID; spep::PrincipalSession principalSession; bool validSession = false; // SPEP cookie was found, validate using one of the values and use that to proceed. for (std::vector<std::string>::iterator cookieValueIterator = cookieValues.begin(); cookieValueIterator != cookieValues.end(); ++cookieValueIterator) { sessionID = *cookieValueIterator; try { principalSession = this->_spep->getAuthnProcessor()->verifySession( sessionID ); validSession = true; break; } catch( std::exception& e ) { } } if( validSession ) { // If attribute querying is not disabled... if( !this->_spep->getSPEPConfigData()->disableAttributeQuery() ) { // Put attributes into the environment. std::string usernameAttribute = spepConfigData->getUsernameAttribute(); std::string attributeValueSeparator = spepConfigData->getAttributeValueSeparator(); std::string attributeNamePrefix = spepConfigData->getAttributeNamePrefix(); for( spep::PrincipalSession::AttributeMapType::iterator attributeIterator = principalSession.getAttributeMap().begin(); attributeIterator != principalSession.getAttributeMap().end(); ++attributeIterator ) { std::string name = spep::UnicodeStringConversion::toString( attributeIterator->first ); std::string envName = attributeNamePrefix + name; std::stringstream valueStream; bool first = true; for( std::vector<UnicodeString>::iterator attributeValueIterator = attributeIterator->second.begin(); attributeValueIterator != attributeIterator->second.end(); ++attributeValueIterator ) { std::string value = spep::UnicodeStringConversion::toString( *attributeValueIterator ); if( first ) { valueStream << value; first = false; } else { valueStream << attributeValueSeparator << value; } } std::string envValue = valueStream.str(); // Insert the attribute name/value pair into the subprocess environment. apr_table_set( req->subprocess_env, envName.c_str(), envValue.c_str() ); if( name.compare( usernameAttribute ) == 0 ) { #ifndef APACHE1 req->user = apr_pstrdup( req->pool, envValue.c_str() ); #else req->connection->user = apr_pstrdup( req->pool, envValue.c_str() ); #endif } } } if( this->_spep->getSPEPConfigData()->disablePolicyEnforcement() ) { // No need to perform authorization, just let them in. return DECLINED; } // Perform authorization on the URI requested. spep::PolicyEnforcementProcessorData pepData; pepData.setESOESessionID( principalSession.getESOESessionID() ); pepData.setResource( properURI ); this->_spep->getPolicyEnforcementProcessor()->makeAuthzDecision( pepData ); spep::Decision authzDecision( pepData.getDecision() ); validSession = false; try { principalSession = this->_spep->getAuthnProcessor()->verifySession( sessionID ); validSession = true; } catch( std::exception& e ) { } if( validSession ) { if( authzDecision == spep::Decision::PERMIT ) { return DECLINED; } else if( authzDecision == spep::Decision::DENY ) { return HTTP_FORBIDDEN; } else if( authzDecision == spep::Decision::ERROR ) { return HTTP_INTERNAL_SERVER_ERROR; } else { return HTTP_INTERNAL_SERVER_ERROR; } } } } // If we get to this stage, the session has not been authenticated. We proceed to clear the // cookies configured by the SPEP to be cleared upon logout, since this is potentially the // first time they have come back to the SPEP since logging out. bool requireSend = false; const std::vector<std::string>& logoutClearCookies = this->_spep->getSPEPConfigData()->getLogoutClearCookies(); for( std::vector<std::string>::const_iterator logoutClearCookieIterator = logoutClearCookies.begin(); logoutClearCookieIterator != logoutClearCookies.end(); ++logoutClearCookieIterator ) { // Throw the configured string into a stringstream std::stringstream ss( *logoutClearCookieIterator ); // Split into name, domain, path. Doc says that stringstream operator>> won't throw std::string cookieNameString, cookieDomainString, cookiePathString; ss >> cookieNameString >> cookieDomainString >> cookiePathString; // Default to NULL, and then check if they were specified const char *cookieName = NULL, *cookieDomain = NULL, *cookiePath = NULL; // No cookie name, no clear. if( cookieNameString.length() == 0 ) { continue; } // If the user sent this cookie. Cookies cookies( req ); std::vector<std::string> cookieValues; cookies.getCookieValuesByName( cookieValues, spepConfigData->getTokenName() ); if( !cookieValues.empty() ) { cookieName = cookieNameString.c_str(); if( cookieDomainString.length() > 0 ) { cookieDomain = cookieDomainString.c_str(); } if( cookiePathString.length() > 0 ) { cookiePath = cookiePathString.c_str(); } // Set the cookie to an empty value. cookies.addCookie( req, cookieName, "", cookiePath, cookieDomain, false ); // Flag that we need to send the cookies, because we have set at least one. requireSend = true; } } if( requireSend ) { cookies.sendCookies( req ); } // Lazy init code. if( spepConfigData->isLazyInit() ) { std::string globalESOECookieName( spepConfigData->getGlobalESOECookieName() ); Cookies cookies( req ); std::vector<std::string> cookieValues; cookies.getCookieValuesByName( cookieValues, globalESOECookieName ); if( cookieValues.empty() ) { bool matchedLazyInitResource = false; UnicodeString properURIUnicode( spep::UnicodeStringConversion::toUnicodeString( properURI ) ); std::vector<UnicodeString>::const_iterator lazyInitResourceIterator; for( lazyInitResourceIterator = spepConfigData->getLazyInitResources().begin(); lazyInitResourceIterator != spepConfigData->getLazyInitResources().end(); ++lazyInitResourceIterator ) { // TODO Opportunity for caching of compiled regex patterns is here. UParseError parseError; UErrorCode errorCode = U_ZERO_ERROR; // Perform the regular expression matching here. UBool result = RegexPattern::matches( *lazyInitResourceIterator, properURIUnicode, parseError, errorCode ); if ( U_FAILURE( errorCode ) ) { // TODO throw u_errorName( errorCode ) return HTTP_INTERNAL_SERVER_ERROR; } // FALSE is defined by ICU. This line for portability. if (result != FALSE) { matchedLazyInitResource = true; break; } } if( matchedLazyInitResource ) { if( !spepConfigData->isLazyInitDefaultPermit() ) { return DECLINED; } } else { if( spepConfigData->isLazyInitDefaultPermit() ) { return DECLINED; } } } } boost::posix_time::ptime epoch( boost::gregorian::date( 1970, 1, 1 ) ); boost::posix_time::time_duration timestamp = boost::posix_time::microsec_clock::local_time() - epoch; boost::posix_time::time_duration::tick_type currentTimeMillis = timestamp.total_milliseconds(); apr_uri_t *uri = static_cast<apr_uri_t*>( apr_pcalloc( req->pool, sizeof(apr_uri_t) ) ); apr_uri_parse( req->pool, this->_spep->getSPEPConfigData()->getServiceHost().c_str(), uri ); const char *hostname = apr_table_get( req->headers_in, "Host" ); if( hostname == NULL ) { hostname = req->server->server_hostname; } const char *format = NULL; const char *base64RequestURI = NULL; // If we can't determine our own hostname, just fall through to the service host. // If the service host was requested obviously we want that. if( hostname == NULL || std::strcmp( uri->hostinfo, hostname ) == 0 ) { // Join the service hostname and requested URI to form the return URL char *returnURL = apr_psprintf( req->pool, "%s%s", this->_spep->getSPEPConfigData()->getServiceHost().c_str(), req->unparsed_uri ); // Base64 encode this so that the HTTP redirect doesn't corrupt it. base64RequestURI = ap_pbase64encode( req->pool, returnURL ); // Create the format string for building the redirect URL. format = apr_psprintf( req->pool, "%s%s", this->_spep->getSPEPConfigData()->getServiceHost().c_str(), this->_spep->getSPEPConfigData()->getSSORedirect().c_str() ); } else { base64RequestURI = ap_pbase64encode( req->pool, req->unparsed_uri ); // getSSORedirect() will only give us a temporary.. dup it into the pool so we don't lose it when we leave this scope. format = apr_pstrdup( req->pool, this->_spep->getSPEPConfigData()->getSSORedirect().c_str() ); } char *redirectURL = apr_psprintf( req->pool, format, base64RequestURI ); std::stringstream timestampParameter; if( strchr( redirectURL, '?' ) != NULL ) { // Query string already exists.. append the timestamp as another parameter timestampParameter << "&ts=" << currentTimeMillis; redirectURL = apr_psprintf( req->pool, "%s%s", redirectURL, timestampParameter.str().c_str() ); } else { // No query string. Add one with the timestamp as a parameter. timestampParameter << "?ts=" << currentTimeMillis; redirectURL = apr_psprintf( req->pool, "%s%s", redirectURL, timestampParameter.str().c_str() ); } apr_table_setn( req->headers_out, "Location", redirectURL ); return HTTP_MOVED_TEMPORARILY; }
/* Manages the loadfactors and member status */ static int balancer_handler(request_rec *r) { void *sconf = r->server->module_config; proxy_server_conf *conf = (proxy_server_conf *) ap_get_module_config(sconf, &proxy_module); proxy_balancer *balancer, *bsel = NULL; proxy_worker *worker, *wsel = NULL; apr_table_t *params = apr_table_make(r->pool, 10); int access_status; int i, n; const char *name; /* is this for us? */ if (strcmp(r->handler, "balancer-manager")) return DECLINED; r->allowed = (AP_METHOD_BIT << M_GET); if (r->method_number != M_GET) return DECLINED; if (r->args) { char *args = apr_pstrdup(r->pool, r->args); char *tok, *val; while (args && *args) { if ((val = ap_strchr(args, '='))) { *val++ = '\0'; if ((tok = ap_strchr(val, '&'))) *tok++ = '\0'; /* * Special case: workers are allowed path information */ if ((access_status = ap_unescape_url(val)) != OK) if (strcmp(args, "w") || (access_status != HTTP_NOT_FOUND)) return access_status; apr_table_setn(params, args, val); args = tok; } else return HTTP_BAD_REQUEST; } } /* Check that the supplied nonce matches this server's nonce; * otherwise ignore all parameters, to prevent a CSRF attack. */ if ((name = apr_table_get(params, "nonce")) == NULL || strcmp(balancer_nonce, name) != 0) { apr_table_clear(params); } if ((name = apr_table_get(params, "b"))) bsel = ap_proxy_get_balancer(r->pool, conf, apr_pstrcat(r->pool, "balancer://", name, NULL)); if ((name = apr_table_get(params, "w"))) { proxy_worker *ws; ws = ap_proxy_get_worker(r->pool, conf, name); if (bsel && ws) { worker = (proxy_worker *)bsel->workers->elts; for (n = 0; n < bsel->workers->nelts; n++) { if (strcasecmp(worker->name, ws->name) == 0) { wsel = worker; break; } ++worker; } } } /* First set the params */ /* * Note that it is not possible set the proxy_balancer because it is not * in shared memory. */ if (wsel) { const char *val; if ((val = apr_table_get(params, "lf"))) { int ival = atoi(val); if (ival >= 1 && ival <= 100) { wsel->s->lbfactor = ival; if (bsel) recalc_factors(bsel); } } if ((val = apr_table_get(params, "wr"))) { if (strlen(val) && strlen(val) < PROXY_WORKER_MAX_ROUTE_SIZ) strcpy(wsel->s->route, val); else *wsel->s->route = '\0'; } if ((val = apr_table_get(params, "rr"))) { if (strlen(val) && strlen(val) < PROXY_WORKER_MAX_ROUTE_SIZ) strcpy(wsel->s->redirect, val); else *wsel->s->redirect = '\0'; } if ((val = apr_table_get(params, "dw"))) { if (!strcasecmp(val, "Disable")) wsel->s->status |= PROXY_WORKER_DISABLED; else if (!strcasecmp(val, "Enable")) wsel->s->status &= ~PROXY_WORKER_DISABLED; } if ((val = apr_table_get(params, "ls"))) { int ival = atoi(val); if (ival >= 0 && ival <= 99) { wsel->s->lbset = ival; } } } if (apr_table_get(params, "xml")) { ap_set_content_type(r, "text/xml"); ap_rputs("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n", r); ap_rputs("<httpd:manager xmlns:httpd=\"http://httpd.apache.org\">\n", r); ap_rputs(" <httpd:balancers>\n", r); balancer = (proxy_balancer *)conf->balancers->elts; for (i = 0; i < conf->balancers->nelts; i++) { ap_rputs(" <httpd:balancer>\n", r); ap_rvputs(r, " <httpd:name>", balancer->name, "</httpd:name>\n", NULL); ap_rputs(" <httpd:workers>\n", r); worker = (proxy_worker *)balancer->workers->elts; for (n = 0; n < balancer->workers->nelts; n++) { ap_rputs(" <httpd:worker>\n", r); ap_rvputs(r, " <httpd:scheme>", worker->scheme, "</httpd:scheme>\n", NULL); ap_rvputs(r, " <httpd:hostname>", worker->hostname, "</httpd:hostname>\n", NULL); ap_rprintf(r, " <httpd:loadfactor>%d</httpd:loadfactor>\n", worker->s->lbfactor); ap_rputs(" </httpd:worker>\n", r); ++worker; } ap_rputs(" </httpd:workers>\n", r); ap_rputs(" </httpd:balancer>\n", r); ++balancer; } ap_rputs(" </httpd:balancers>\n", r); ap_rputs("</httpd:manager>", r); } else { ap_set_content_type(r, "text/html; charset=ISO-8859-1"); ap_rputs(DOCTYPE_HTML_3_2 "<html><head><title>Balancer Manager</title></head>\n", r); ap_rputs("<body><h1>Load Balancer Manager for ", r); ap_rvputs(r, ap_get_server_name(r), "</h1>\n\n", NULL); ap_rvputs(r, "<dl><dt>Server Version: ", ap_get_server_description(), "</dt>\n", NULL); ap_rvputs(r, "<dt>Server Built: ", ap_get_server_built(), "\n</dt></dl>\n", NULL); balancer = (proxy_balancer *)conf->balancers->elts; for (i = 0; i < conf->balancers->nelts; i++) { ap_rputs("<hr />\n<h3>LoadBalancer Status for ", r); ap_rvputs(r, balancer->name, "</h3>\n\n", NULL); ap_rputs("\n\n<table border=\"0\" style=\"text-align: left;\"><tr>" "<th>StickySession</th><th>Timeout</th><th>FailoverAttempts</th><th>Method</th>" "</tr>\n<tr>", r); if (balancer->sticky) { ap_rvputs(r, "<td>", balancer->sticky, NULL); } else { ap_rputs("<td> - ", r); } ap_rprintf(r, "</td><td>%" APR_TIME_T_FMT "</td>", apr_time_sec(balancer->timeout)); ap_rprintf(r, "<td>%d</td>\n", balancer->max_attempts); ap_rprintf(r, "<td>%s</td>\n", balancer->lbmethod->name); ap_rputs("</table>\n<br />", r); ap_rputs("\n\n<table border=\"0\" style=\"text-align: left;\"><tr>" "<th>Worker URL</th>" "<th>Route</th><th>RouteRedir</th>" "<th>Factor</th><th>Set</th><th>Status</th>" "<th>Elected</th><th>To</th><th>From</th>" "</tr>\n", r); worker = (proxy_worker *)balancer->workers->elts; for (n = 0; n < balancer->workers->nelts; n++) { char fbuf[50]; ap_rvputs(r, "<tr>\n<td><a href=\"", r->uri, "?b=", balancer->name + sizeof("balancer://") - 1, "&w=", ap_escape_uri(r->pool, worker->name), "&nonce=", balancer_nonce, "\">", NULL); ap_rvputs(r, worker->name, "</a></td>", NULL); ap_rvputs(r, "<td>", ap_escape_html(r->pool, worker->s->route), NULL); ap_rvputs(r, "</td><td>", ap_escape_html(r->pool, worker->s->redirect), NULL); ap_rprintf(r, "</td><td>%d</td>", worker->s->lbfactor); ap_rprintf(r, "<td>%d</td><td>", worker->s->lbset); if (worker->s->status & PROXY_WORKER_DISABLED) ap_rputs("Dis ", r); if (worker->s->status & PROXY_WORKER_IN_ERROR) ap_rputs("Err ", r); if (worker->s->status & PROXY_WORKER_STOPPED) ap_rputs("Stop ", r); if (worker->s->status & PROXY_WORKER_HOT_STANDBY) ap_rputs("Stby ", r); if (PROXY_WORKER_IS_USABLE(worker)) ap_rputs("Ok", r); if (!PROXY_WORKER_IS_INITIALIZED(worker)) ap_rputs("-", r); ap_rputs("</td>", r); ap_rprintf(r, "<td>%" APR_SIZE_T_FMT "</td><td>", worker->s->elected); ap_rputs(apr_strfsize(worker->s->transferred, fbuf), r); ap_rputs("</td><td>", r); ap_rputs(apr_strfsize(worker->s->read, fbuf), r); ap_rputs("</td></tr>\n", r); ++worker; } ap_rputs("</table>\n", r); ++balancer; } ap_rputs("<hr />\n", r); if (wsel && bsel) { ap_rputs("<h3>Edit worker settings for ", r); ap_rvputs(r, wsel->name, "</h3>\n", NULL); ap_rvputs(r, "<form method=\"GET\" action=\"", NULL); ap_rvputs(r, r->uri, "\">\n<dl>", NULL); ap_rputs("<table><tr><td>Load factor:</td><td><input name=\"lf\" type=text ", r); ap_rprintf(r, "value=\"%d\"></td></tr>\n", wsel->s->lbfactor); ap_rputs("<tr><td>LB Set:</td><td><input name=\"ls\" type=text ", r); ap_rprintf(r, "value=\"%d\"></td></tr>\n", wsel->s->lbset); ap_rputs("<tr><td>Route:</td><td><input name=\"wr\" type=text ", r); ap_rvputs(r, "value=\"", ap_escape_html(r->pool, wsel->s->route), NULL); ap_rputs("\"></td></tr>\n", r); ap_rputs("<tr><td>Route Redirect:</td><td><input name=\"rr\" type=text ", r); ap_rvputs(r, "value=\"", ap_escape_html(r->pool, wsel->s->redirect), NULL); ap_rputs("\"></td></tr>\n", r); ap_rputs("<tr><td>Status:</td><td>Disabled: <input name=\"dw\" value=\"Disable\" type=radio", r); if (wsel->s->status & PROXY_WORKER_DISABLED) ap_rputs(" checked", r); ap_rputs("> | Enabled: <input name=\"dw\" value=\"Enable\" type=radio", r); if (!(wsel->s->status & PROXY_WORKER_DISABLED)) ap_rputs(" checked", r); ap_rputs("></td></tr>\n", r); ap_rputs("<tr><td colspan=2><input type=submit value=\"Submit\"></td></tr>\n", r); ap_rvputs(r, "</table>\n<input type=hidden name=\"w\" ", NULL); ap_rvputs(r, "value=\"", ap_escape_uri(r->pool, wsel->name), "\">\n", NULL); ap_rvputs(r, "<input type=hidden name=\"b\" ", NULL); ap_rvputs(r, "value=\"", bsel->name + sizeof("balancer://") - 1, "\">\n", NULL); ap_rvputs(r, "<input type=hidden name=\"nonce\" value=\"", balancer_nonce, "\">\n", NULL); ap_rvputs(r, "</form>\n", NULL); ap_rputs("<hr />\n", r); } ap_rputs(ap_psignature("",r), r); ap_rputs("</body></html>\n", r); } return OK; }