int check_client_header(FILE *file) { char buffer[1024]; http_request request; fgets_or_exit(buffer, 1024, file); if (parse_http_request(buffer, &request) == 1) { char *url = rewrite_url(request.url); if (request.method != HTTP_GET) { skip_headers(file); send_response(file, 400, "Bad request", "Bad request\r\n"); free(url); return 400; } else if (strcmp(url, "/")) { skip_headers(file); send_response(file, 404, "Not Found", "Not Found\r\n"); free(url); return 404; } else { skip_headers(file); free(url); return 200; } } else { skip_headers(file); send_response(file, 400, "Bad Request", "Bad request\r\n"); return 400; } }
int parse_http_request ( const char * request_line , http_request * request ){ int i=0; int nbmot=1; int troisieme_mot=0; int deuxieme_mot=0; while(request_line[i]!='\0' && i!=2048){ if(request_line[i]==' '){ nbmot++; if(deuxieme_mot==0){ deuxieme_mot=i+1; } troisieme_mot=i+1; } i++; } if(nbmot!=3){ return 0; } char * url = malloc(troisieme_mot-deuxieme_mot-1); char * buf =url; while(deuxieme_mot<troisieme_mot-1){ *buf=request_line[deuxieme_mot]; buf++; deuxieme_mot++; } request->url=rewrite_url(url); if(!(request_line[0]=='G' && request_line[1]=='E' && request_line[2]=='T')){ return 0; }else{ request->method=HTTP_GET; } if(!(request_line[troisieme_mot]=='H' && request_line[troisieme_mot+1]=='T' && request_line[troisieme_mot+2]=='T' && request_line[troisieme_mot+3]=='P' && request_line[troisieme_mot+4]=='/')){ return 0; }if(!(request_line[troisieme_mot+5]=='1')){ return 0; }if(!(request_line[troisieme_mot+6]=='.')){ return 0; }if(!(request_line[troisieme_mot+7]>='0' && request_line[troisieme_mot+7]<='1')){ return 0; } return 1; }
/* * read_requesthdrs - read and parse HTTP request headers */ int read_http_header(const char* line, http_request *r) { int length = strlen(line); int pos, last = length, current_state = s_start; char ch = 'a'; char s[length]; memset(s, 0, length); for (pos = 0; pos < last; ++pos) { ch = line[pos]; switch (current_state) { case s_start: if (words(line) != 3) { r->m = HTTP_INVALID; current_state = s_header_done; return EXIT_FAILURE; } if (ch == LF || ch == CR) break; if ((ch < 'A' || ch > 'Z') && ch != '_') { r->m = HTTP_INVALID; current_state = s_header_done; return EXIT_FAILURE; } current_state = s_method; break; case s_method: if (ch == ' ') { switch (pos) { case 3: if (strncmp(line, "GET", 3) == 0) { r->m = HTTP_GET; current_state = s_uri; break; } if (strncmp(line, "PUT", 3) == 0) { current_state = s_uri; r->m = HTTP_PUT; break; } break; case 4: if (strncmp(line, "HEAD", 4) == 0) { current_state = s_uri; r->m = HTTP_HEAD; break; } if (strncmp(line, "POST", 4) == 0) { current_state = s_uri; r->m = HTTP_POST; break; } break; case 5: if (strncmp(line, "TRACE", 5) == 0) { current_state = s_uri; r->m = HTTP_TRACE; break; } break; case 6: if (strncmp(line, "DELETE", 6) == 0) { current_state = s_uri; r->m = HTTP_DELETE; break; } break; case 7: if (strncmp(line, "CONNECT", 7) == 0) { r->m = HTTP_CONNECT; break; } if (strncmp(line, "OPTIONS", 7) == 0) { r->m = HTTP_OPTIONS; break; } break; } if (current_state != s_uri) { r->m = HTTP_INVALID; current_state = s_header_done; return EXIT_FAILURE; } } break; case s_uri: if (ch == ' ') { strcpy(r->uri, rewrite_url(s)); current_state = s_http_correct; break; } else { append(s, length, ch); } break; case s_http_correct: switch (ch) { case ' ': break; case CR: current_state = s_header_done; break; case LF: current_state = s_header_done; break; case 'H': current_state = s_http_H; break; default: current_state = s_header_done; return EXIT_FAILURE; } break; case s_http_H: switch (ch) { case 'T': current_state = s_http_HT; break; default: r->m = HTTP_INVALID; current_state = s_header_done; return EXIT_FAILURE; } break; case s_http_HT: switch (ch) { case 'T': current_state = s_http_HTT; break; default: r->m = HTTP_INVALID; current_state = s_header_done; return EXIT_FAILURE; } break; case s_http_HTT: switch (ch) { case 'P': current_state = s_http_HTTP; break; default: r->m = HTTP_INVALID; current_state = s_header_done; return EXIT_FAILURE; } break; case s_http_HTTP: switch (ch) { case '/': current_state = s_http_first_major_version; break; default: r->m = HTTP_INVALID; current_state = s_header_done; return EXIT_FAILURE; } break; case s_http_first_major_version: if (ch < '1' || ch > '9') { r->m = HTTP_INVALID; current_state = s_header_done; return EXIT_FAILURE; } r->major_version = strtol(&ch, NULL, 1); current_state = s_http_major_version; break; case s_http_major_version: if (ch == '.') { current_state = s_http_first_minor_version; break; } if (ch < '0' || ch > '9') { r->m = HTTP_INVALID; current_state = s_header_done; return EXIT_FAILURE; } r->major_version = r->major_version * 10 + strtol(&ch, NULL, 1); break; case s_http_first_minor_version: if (ch < '0' || ch > '9') { r->m = HTTP_INVALID; current_state = s_header_done; return EXIT_FAILURE; } r->minor_version = strtol(&ch, NULL, 1); current_state = s_http_minor_version; break; case s_http_minor_version: if (ch == CR) { current_state = s_header_done; break; } if (ch == LF) { current_state = s_header_done; break; } } } return EXIT_SUCCESS; }
int main(int argc, char **argv) { char **singleusercmd = NULL; char *testurl = NULL; char *dropprivuser = NULL; #ifndef NO_X11 char *display = NULL; #endif int doing_opts = 1; int port = 880; int multiuser = 0; /* * Parse the arguments. */ while (--argc > 0) { char *p = *++argv; if (*p == '-' && doing_opts) { if (!strcmp(p, "--multiuser")) { multiuser = 1; #ifndef NO_X11 } else if (!strcmp(p, "--display") || !strcmp(p, "-display")) { if (--argc <= 0) { fprintf(stderr, "ick-proxy: %s expected a parameter\n", p); return 1; } display = *++argv; #endif } else if (!strcmp(p, "-p")) { if (--argc <= 0) { fprintf(stderr, "ick-proxy: -p expected a parameter\n"); return 1; } port = atoi(*++argv); } else if (!strcmp(p, "-s")) { if (--argc <= 0) { fprintf(stderr, "ick-proxy: -s expected a parameter\n"); return 1; } override_script = *++argv; } else if (!strcmp(p, "-i")) { if (--argc <= 0) { fprintf(stderr, "ick-proxy: -i expected a parameter\n"); return 1; } override_inpac = *++argv; } else if (!strcmp(p, "-o")) { if (--argc <= 0) { fprintf(stderr, "ick-proxy: -o expected a parameter\n"); return 1; } override_outpac = *++argv; } else if (!strcmp(p, "-t")) { if (--argc <= 0) { fprintf(stderr, "ick-proxy: -t expected a parameter\n"); return 1; } testurl = *++argv; } else if (!strcmp(p, "-u")) { if (--argc <= 0) { fprintf(stderr, "ick-proxy: -u expected a parameter\n"); return 1; } dropprivuser = *++argv; } else if (!strcmp(p, "--help") || !strcmp(p, "-help") || !strcmp(p, "-?") || !strcmp(p, "-h")) { /* Valid help request. */ usage(); return 0; } else if (!strcmp(p, "--licence") || !strcmp(p, "--license")) { licence(); return 0; } else if (!strcmp(p, "--version")) { version(); return 0; } else if (!strcmp(p, "--")) { doing_opts = 0; } else { /* Invalid option; give help as well as whining. */ fprintf(stderr, "ick-proxy: unrecognised option '%s'\n", p); usage(); return 1; } } else { singleusercmd = argv; break; } } /* * Handle command-line URL-test mode. */ if (testurl) { char *err, *ret; ick_proxy_setup(); ret = rewrite_url(&err, "", testurl); if (!ret) { fprintf(stderr, "ick-proxy: rewrite error: %s\n", err); sfree(err); return 1; } else { puts(ret); sfree(ret); return 0; } } /* * Otherwise, hand off to uxmain. */ if (!multiuser && !singleusercmd) { #ifdef NO_X11 fprintf(stderr, "ick-proxy: expected a command in single-user" " mode\n"); return 1; #else /* * Open the X display. */ disp = XOpenDisplay(display); if (!disp) { fprintf(stderr, "ick-proxy: unable to open X display\n"); return 1; } /* * When working with an X display, we daemonise, if only * to avoid zombie processes if we're started from a * .xsession that isn't wait()ing for us. */ return uxmain(0, -1, NULL, NULL, ConnectionNumber(disp), xreadfd, 1); #endif } /* * The `daemon' flag is set iff we are multi-user. */ return uxmain(multiuser, port, dropprivuser, singleusercmd, -1, NULL, multiuser); }
static int proxy_balancer_pre_request(proxy_worker **worker, proxy_balancer **balancer, request_rec *r, proxy_server_conf *conf, char **url) { int access_status; proxy_worker *runtime; char *route = NULL; char *sticky = NULL; apr_status_t rv; *worker = NULL; /* Step 1: check if the url is for us * The url we can handle starts with 'balancer://' * If balancer is already provided skip the search * for balancer, because this is failover attempt. */ if (!*balancer && !(*balancer = ap_proxy_get_balancer(r->pool, conf, *url))) return DECLINED; /* Step 2: find the session route */ runtime = find_session_route(*balancer, r, &route, &sticky, url); /* Lock the LoadBalancer * XXX: perhaps we need the process lock here */ if ((rv = PROXY_THREAD_LOCK(*balancer)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, "proxy: BALANCER: (%s). Lock failed for pre_request", (*balancer)->name); return DECLINED; } if (runtime) { int i, total_factor = 0; proxy_worker *workers; /* We have a sticky load balancer * Update the workers status * so that even session routes get * into account. */ workers = (proxy_worker *)(*balancer)->workers->elts; for (i = 0; i < (*balancer)->workers->nelts; i++) { /* Take into calculation only the workers that are * not in error state or not disabled. * * TODO: Abstract the below, since this is dependent * on the LB implementation */ if (PROXY_WORKER_IS_USABLE(workers)) { workers->s->lbstatus += workers->s->lbfactor; total_factor += workers->s->lbfactor; } workers++; } runtime->s->lbstatus -= total_factor; runtime->s->elected++; *worker = runtime; } else if (route && (*balancer)->sticky_force) { int i, member_of = 0; proxy_worker *workers; /* * We have a route provided that doesn't match the * balancer name. See if the provider route is the * member of the same balancer in which case return 503 */ workers = (proxy_worker *)(*balancer)->workers->elts; for (i = 0; i < (*balancer)->workers->nelts; i++) { if (*(workers->s->route) && strcmp(workers->s->route, route) == 0) { member_of = 1; break; } workers++; } if (member_of) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "proxy: BALANCER: (%s). All workers are in error state for route (%s)", (*balancer)->name, route); if ((rv = PROXY_THREAD_UNLOCK(*balancer)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, "proxy: BALANCER: (%s). Unlock failed for pre_request", (*balancer)->name); } return HTTP_SERVICE_UNAVAILABLE; } } if ((rv = PROXY_THREAD_UNLOCK(*balancer)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, "proxy: BALANCER: (%s). Unlock failed for pre_request", (*balancer)->name); } if (!*worker) { runtime = find_best_worker(*balancer, r); if (!runtime) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, "proxy: BALANCER: (%s). All workers are in error state", (*balancer)->name); return HTTP_SERVICE_UNAVAILABLE; } if ((*balancer)->sticky && runtime) { /* * This balancer has sticky sessions and the client either has not * supplied any routing information or all workers for this route * including possible redirect and hotstandby workers are in error * state, but we have found another working worker for this * balancer where we can send the request. Thus notice that we have * changed the route to the backend. */ apr_table_setn(r->subprocess_env, "BALANCER_ROUTE_CHANGED", "1"); } *worker = runtime; } (*worker)->s->busy++; /* Add balancer/worker info to env. */ apr_table_setn(r->subprocess_env, "BALANCER_NAME", (*balancer)->name); apr_table_setn(r->subprocess_env, "BALANCER_WORKER_NAME", (*worker)->name); apr_table_setn(r->subprocess_env, "BALANCER_WORKER_ROUTE", (*worker)->s->route); /* Rewrite the url from 'balancer://url' * to the 'worker_scheme://worker_hostname[:worker_port]/url' * This replaces the balancers fictional name with the * real hostname of the elected worker. */ access_status = rewrite_url(r, *worker, url); /* Add the session route to request notes if present */ if (route) { apr_table_setn(r->notes, "session-sticky", sticky); apr_table_setn(r->notes, "session-route", route); /* Add session info to env. */ apr_table_setn(r->subprocess_env, "BALANCER_SESSION_STICKY", sticky); apr_table_setn(r->subprocess_env, "BALANCER_SESSION_ROUTE", route); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "proxy: BALANCER (%s) worker (%s) rewritten to %s", (*balancer)->name, (*worker)->name, *url); return access_status; }
bool rewrite_urls(xmlNode *n, const char *base, struct save_complete_entry *list) { xmlNode *child; assert(n->type == XML_ELEMENT_NODE); /** * We only need to consider the following cases: * * Attribute: Elements: * * 1) data <object> * 2) href <a> <area> <link> * 3) src <script> <input> <frame> <iframe> <img> * 4) n/a <style> * 5) n/a any <base> tag * 6) background any (except those above) */ if (!n->name) { /* ignore */ } /* 1 */ else if (strcmp((const char *) n->name, "object") == 0) { if (!rewrite_url(n, "data", base, list)) return false; } /* 2 */ else if (strcmp((const char *) n->name, "a") == 0 || strcmp((const char *) n->name, "area") == 0 || strcmp((const char *) n->name, "link") == 0) { if (!rewrite_url(n, "href", base, list)) return false; } /* 3 */ else if (strcmp((const char *) n->name, "frame") == 0 || strcmp((const char *) n->name, "iframe") == 0 || strcmp((const char *) n->name, "input") == 0 || strcmp((const char *) n->name, "img") == 0 || strcmp((const char *) n->name, "script") == 0) { if (!rewrite_url(n, "src", base, list)) return false; } /* 4 */ else if (strcmp((const char *) n->name, "style") == 0) { unsigned int len; xmlChar *content; for (child = n->children; child != 0; child = child->next) { char *rewritten; /* Get current content */ content = xmlNodeGetContent(child); if (!content) /* unfortunately we don't know if this is * due to memory exhaustion, or because * there is no content for this node */ continue; /* Rewrite @import rules */ rewritten = rewrite_stylesheet_urls( (const char *) content, strlen((const char *) content), (int *) &len, base, list); xmlFree(content); if (!rewritten) return false; /* set new content */ xmlNodeSetContentLen(child, (const xmlChar*)rewritten, len); } return true; } /* 5 */ else if (strcmp((const char *) n->name, "base") == 0) { /* simply remove any <base> tags from the document */ xmlUnlinkNode(n); xmlFreeNode(n); /* base tags have no content, so there's no point recursing * additionally, we've just destroyed this node, so trying * to recurse would result in bad things happening */ return true; } /* 6 */ else { if (!rewrite_url(n, "background", base, list)) return false; } /* now recurse */ for (child = n->children; child;) { /* we must extract the next child now, as if the current * child is a <base> element, it will be removed from the * tree (see 5, above), thus preventing extraction of the * next child */ xmlNode *next = child->next; if (child->type == XML_ELEMENT_NODE) { if (!rewrite_urls(child, base, list)) return false; } child = next; } return true; }