PyObject* parse_request(PyObject* ignored, PyObject* args) { PyObject* self; PyObject* source; PyObject* port = NULL; PyObject* ret = NULL; int status; if(!PyArg_ParseTuple(args, "OO", &self, &source)) return NULL; request_t* req = create_request(source); if(req == NULL) goto done; status = do_parse(req); if(status < 0) goto done; if(status == 0) { destroy_request(req); Py_RETURN_NONE; } // Move objects to self if(move_object(self, "method", &(req->method)) != 0) goto done; if(move_object(self, "uri", &(req->uri)) != 0) goto done; if(move_object(self, "scheme", &(req->scheme)) != 0) goto done; if(move_object(self, "host", &(req->host)) != 0) goto done; port = PyInt_FromLong(req->port); if(port == NULL) goto done; if(move_object(self, "port", &port) != 0) goto done; if(move_object(self, "path", &(req->path)) != 0) goto done; if(move_object(self, "query", &(req->query)) != 0) goto done; if(move_object(self, "fragment", &(req->fragment)) != 0) goto done; if(move_object(self, "version", &(req->version)) != 0) goto done; if(move_object(self, "headers", &(req->headers)) != 0) goto done; if(req->buflen > 0) { ret = PyString_FromStringAndSize(req->buffer, req->buflen); } else { ret = PyString_FromString(""); } done: Py_XDECREF(port); if(req != NULL) destroy_request(req); return ret; }
bool mgmt_cancel_index(struct mgmt *mgmt, uint16_t index) { GList *list, *next; if (!mgmt) return false; for (list = g_queue_peek_head_link(mgmt->request_queue); list; list = next) { struct mgmt_request *request = list->data; next = g_list_next(list); if (request->index != index) continue; g_queue_delete_link(mgmt->request_queue, list); destroy_request(request, NULL); } for (list = g_queue_peek_head_link(mgmt->reply_queue); list; list = next) { struct mgmt_request *request = list->data; next = g_list_next(list); if (request->index != index) continue; g_queue_delete_link(mgmt->reply_queue, list); destroy_request(request, NULL); } for (list = g_list_first(mgmt->pending_list); list; list = next) { struct mgmt_request *request = list->data; next = g_list_next(list); if (request->index != index) continue; mgmt->pending_list = g_list_delete_link(mgmt->pending_list, list); destroy_request(request, NULL); } return true; }
bool mgmt_cancel(struct mgmt *mgmt, unsigned int id) { struct mgmt_request *request; if (!mgmt || !id) return false; request = queue_remove_if(mgmt->request_queue, match_request_id, UINT_TO_PTR(id)); if (request) goto done; request = queue_remove_if(mgmt->reply_queue, match_request_id, UINT_TO_PTR(id)); if (request) goto done; request = queue_remove_if(mgmt->pending_list, match_request_id, UINT_TO_PTR(id)); if (!request) return false; done: destroy_request(request); wakeup_writer(mgmt); return true; }
static void request_complete(struct mgmt *mgmt, uint8_t status, uint16_t opcode, uint16_t index, uint16_t length, const void *param) { struct mgmt_request *request; GList *list; list = lookup_pending(mgmt, opcode, index); if (!list) return; request = list->data; mgmt->pending_list = g_list_delete_link(mgmt->pending_list, list); if (request->callback) request->callback(status, length, param, request->user_data); destroy_request(request, NULL); if (mgmt->destroyed) return; wakeup_writer(mgmt); }
/* initiate handshaking */ static void setup_initiate(grpc_transport_setup *sp) { grpc_client_setup *s = (grpc_client_setup *)sp; grpc_client_setup_request *r = gpr_malloc(sizeof(grpc_client_setup_request)); int in_alarm = 0; r->setup = s; r->deadline = gpr_time_add(gpr_now(), gpr_time_from_seconds(60)); gpr_mu_lock(&s->mu); GPR_ASSERT(s->refs > 0); /* there might be more than one request outstanding if the caller calls initiate in some kind of rapid-fire way: we try to connect each time, and keep track of the latest request (which is the only one that gets to finish) */ if (!s->in_alarm) { s->active_request = r; s->refs++; } else { /* TODO(klempner): Maybe do something more clever here */ in_alarm = 1; } gpr_mu_unlock(&s->mu); if (!in_alarm) { s->initiate(s->user_data, r); } else { destroy_request(r); } }
static void destroy_requests(struct observe_st *req, lcb_size_t nreq) { lcb_size_t ii; for (ii = 0; ii < nreq; ++ii) { destroy_request(req + ii); } free(req); }
static void destroy_response(http_response* response, int close_handle) { if (response->pbuf) free(response->pbuf); if (response->request) destroy_request(response->request, close_handle); if (response->fd != -1) { uv_fs_t close_req; uv_fs_close(loop, &close_req, response->fd, NULL); } free(response); }
static void backoff_alarm_done(void *arg /* grpc_client_setup_request */, int success) { grpc_client_setup_request *r = arg; grpc_client_setup *s = r->setup; /* Handle status cancelled? */ gpr_mu_lock(&s->mu); s->in_alarm = 0; if (s->active_request != NULL || !success) { if (0 == --s->refs) { gpr_mu_unlock(&s->mu); destroy_setup(s); destroy_request(r); return; } else { gpr_mu_unlock(&s->mu); destroy_request(r); return; } } s->active_request = r; gpr_mu_unlock(&s->mu); s->initiate(s->user_data, r); }
void grpc_client_setup_request_finish(grpc_client_setup_request *r, int was_successful) { int retry = !was_successful; grpc_client_setup *s = r->setup; gpr_mu_lock(&s->mu); if (s->active_request == r) { s->active_request = NULL; } else { retry = 0; } if (!retry && 0 == --s->refs) { gpr_mu_unlock(&s->mu); destroy_setup(s); destroy_request(r); } else if (retry) { /* TODO(klempner): Replace these values with further consideration. 2x is probably too aggressive of a backoff. */ gpr_timespec max_backoff = gpr_time_from_minutes(2); gpr_timespec now = gpr_now(); gpr_timespec deadline = gpr_time_add(s->current_backoff_interval, now); GPR_ASSERT(!s->in_alarm); s->in_alarm = 1; grpc_alarm_init(&s->backoff_alarm, deadline, backoff_alarm_done, r, now); s->current_backoff_interval = gpr_time_add(s->current_backoff_interval, s->current_backoff_interval); if (gpr_time_cmp(s->current_backoff_interval, max_backoff) > 0) { s->current_backoff_interval = max_backoff; } gpr_mu_unlock(&s->mu); } else { gpr_mu_unlock(&s->mu); destroy_request(r); } }
static void exit_normaly(){ int i=0; server_decl_t *srv; debug_printf(5,"Suppose that all childs are allready exited...\n"); while((srv=threads_list[i])!=NULL){ if(srv->current_req){ close_connection(srv->current_req->connection); destroy_request(srv->current_req); } free(srv); threads_list[i]=NULL; i++; } free(threads_list); dettach_childs_queue(&childs_queue); log_close(); }
static gboolean can_write_data(GIOChannel *channel, GIOCondition cond, gpointer user_data) { struct mgmt *mgmt = user_data; struct mgmt_request *request; ssize_t bytes_written; if (cond & (G_IO_HUP | G_IO_ERR | G_IO_NVAL)) return FALSE; request = g_queue_pop_head(mgmt->reply_queue); if (!request) { /* only reply commands can jump the queue */ if (mgmt->pending_list) return FALSE; request = g_queue_pop_head(mgmt->request_queue); if (!request) return FALSE; } bytes_written = write(mgmt->fd, request->buf, request->len); if (bytes_written < 0) { util_debug(mgmt->debug_callback, mgmt->debug_data, "write failed: %s", strerror(errno)); if (request->callback) request->callback(MGMT_STATUS_FAILED, 0, NULL, request->user_data); destroy_request(request, NULL); return TRUE; } util_debug(mgmt->debug_callback, mgmt->debug_data, "[0x%04x] command 0x%04x", request->index, request->opcode); util_hexdump('<', request->buf, bytes_written, mgmt->debug_callback, mgmt->debug_data); mgmt->pending_list = g_list_append(mgmt->pending_list, request); return FALSE; }
static int lua_request_collect(lua_State *L) { if (!lua_isuserdata(L, -1)) return; const request_t *r = (request_t*) lua_touserdata(L, -1); /* Only delete the request if it has been completed as it is * still referenced by G_CALLBACK */ if (((lua_request_t*) r->user_data)->is_completed) { destroy_request(r); free((request_t*) r); } //TODO if the request is in progress, set a flag to delete it when it's done return 0; }
bool mgmt_cancel(struct mgmt *mgmt, unsigned int id) { struct mgmt_request *request; GList *list; if (!mgmt || !id) return false; list = g_queue_find_custom(mgmt->request_queue, GUINT_TO_POINTER(id), compare_request_id); if (list) { request = list->data; g_queue_delete_link(mgmt->request_queue, list); goto done; } list = g_queue_find_custom(mgmt->reply_queue, GUINT_TO_POINTER(id), compare_request_id); if (list) { request = list->data; g_queue_delete_link(mgmt->reply_queue, list); goto done; } list = g_list_find_custom(mgmt->pending_list, GUINT_TO_POINTER(id), compare_request_id); if (!list) return false; request = list->data; mgmt->pending_list = g_list_delete_link(mgmt->pending_list, list); done: destroy_request(request, NULL); wakeup_writer(mgmt); return true; }
static bool can_write_data(struct io *io, void *user_data) { struct mgmt *mgmt = user_data; struct mgmt_request *request; ssize_t bytes_written; request = queue_pop_head(mgmt->reply_queue); if (!request) { /* only reply commands can jump the queue */ if (!queue_isempty(mgmt->pending_list)) return false; request = queue_pop_head(mgmt->request_queue); if (!request) return false; } bytes_written = write(mgmt->fd, request->buf, request->len); if (bytes_written < 0) { util_debug(mgmt->debug_callback, mgmt->debug_data, "write failed: %s", strerror(errno)); if (request->callback) request->callback(MGMT_STATUS_FAILED, 0, NULL, request->user_data); destroy_request(request); return true; } util_debug(mgmt->debug_callback, mgmt->debug_data, "[0x%04x] command 0x%04x", request->index, request->opcode); util_hexdump('<', request->buf, bytes_written, mgmt->debug_callback, mgmt->debug_data); queue_push_tail(mgmt->pending_list, request); return false; }
void dispatch_request(int socket_fd) { static char buffer[BUFSIZE + 1]; static struct http_request request; request.socket_fd = socket_fd; long ret = read(socket_fd,buffer,BUFSIZE); // read Web request in one go if(ret > 0 && ret < BUFSIZE) // return code is valid chars buffer[ret]=0; // terminate the buffer else buffer[0]=0; if(parse_http_request(buffer, &request) == 0) { printf("Warning: Could not parse incomming request dumping headers!\n"); printf("%s", buffer); http_response_send("400 Bad Request", "text/plain", &request, "Could not parse HTTP headers"); } struct route *active_route; if(routes_match(&request, &active_route) == 0) { printf("Warning: 404 on %s\n", request.path); http_response_send("404 Not Found", "text/plain", &request, "Resource not found"); } else { if(active_route->type == RT_STATIC) { printf("Log: Found static route %s\n", active_route->static_content_source); http_response_send("200 OK", active_route->content_type, &request, active_route->static_content); } else if(active_route->type == RT_DYNAMIC) { printf("Log: Found dynamic route %s\n", active_route->request_string); (*active_route->callback)(&request); } else { printf("Warning: Request method not implemented dumping request\n"); http_response_send("503 Not Implemented", "text/plain", &request, "Method not implemented"); } } destroy_request(&request); }
static void request_complete(struct mgmt *mgmt, uint8_t status, uint16_t opcode, uint16_t index, uint16_t length, const void *param) { struct opcode_index match = { .opcode = opcode, .index = index }; struct mgmt_request *request; request = queue_remove_if(mgmt->pending_list, match_request_opcode_index, &match); if (request) { if (request->callback) request->callback(status, length, param, request->user_data); destroy_request(request); } if (mgmt->destroyed) return; wakeup_writer(mgmt); }
static void on_write(uv_write_t* req, int status) { http_response* response = (http_response*) req->data; if (status != 0) { fprintf(stderr, "Write error: %s: %s\n", uv_err_name(status), uv_strerror(status)); destroy_response(response, 1); return; } if (response->response_offset >= response->response_size) { destroy_response(response, !response->request->keep_alive); return; } int r = uv_fs_read(loop, &response->read_req, response->fd, &response->buf, 1, response->response_offset, on_fs_read); if (r) { fprintf(stderr, "File read error: %s: %s\n", uv_err_name(r), uv_strerror(r)); response_error(response->handle, 500, "Internal Server Error", NULL); destroy_request(response->request, 1); } }
static void request_complete(http_request* request) { memcpy(request->file_path, static_dir, static_dir_len); memcpy(request->file_path + static_dir_len, request->path, request->path_len); if (*(request->path + request->path_len - 1) == '/') { memcpy(request->file_path + static_dir_len + 1, "index.html", 11); } else request->file_path[static_dir_len + request->path_len] = 0; request->keep_alive = find_header_value(request, "Connection", "keep-alive"); uv_fs_t* open_req = malloc(sizeof(uv_fs_t)); if (open_req == NULL) { fprintf(stderr, "Allocate error: %s\n", strerror(errno)); return; } open_req->data = request; int r = uv_fs_open(loop, open_req, request->file_path, O_RDONLY, S_IREAD, on_fs_open); if (r) { fprintf(stderr, "Open error: %s: %s\n", uv_err_name(r), uv_strerror(r)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_request(request, 1); free(open_req); } }
int main(int argc, char** argv) { s32 opt; u32 loop_cnt = 0, purge_age = 0, seed; u8 sig_loaded = 0, show_once = 0, no_statistics = 0, display_mode = 0, has_fake = 0; s32 oindex = 0; u8 *wordlist = NULL, *output_dir = NULL; u8 *sig_list_strg = NULL; u8 *gtimeout_str = NULL; u32 gtimeout = 0; struct termios term; struct timeval tv; u64 st_time, en_time; signal(SIGINT, ctrlc_handler); signal(SIGWINCH, resize_handler); signal(SIGPIPE, SIG_IGN); SSL_library_init(); /* Options, options, and options */ static struct option long_options[] = { {"auth", required_argument, 0, 'A' }, {"host", required_argument, 0, 'F' }, {"cookie", required_argument, 0, 'C' }, {"reject-cookies", required_argument, 0, 'N' }, {"header", required_argument, 0, 'H' }, {"user-agent", required_argument, 0, 'b' }, #ifdef PROXY_SUPPORT {"proxy", required_argument, 0, 'J' }, #endif /* PROXY_SUPPORT */ {"max-depth", required_argument, 0, 'd' }, {"max-child", required_argument, 0, 'c' }, {"max-descendants", required_argument, 0, 'x' }, {"max-requests", required_argument, 0, 'r' }, {"max-rate", required_argument, 0, 'l'}, {"probability", required_argument, 0, 'p' }, {"seed", required_argument, 0, 'q' }, {"include", required_argument, 0, 'I' }, {"exclude", required_argument, 0, 'X' }, {"skip-param", required_argument, 0, 'K' }, {"skip-forms", no_argument, 0, 'O' }, {"include-domain", required_argument, 0, 'D' }, {"ignore-links", no_argument, 0, 'P' }, {"no-ext-fuzzing", no_argument, 0, 'Y' }, {"log-mixed-content", no_argument, 0, 'M' }, {"skip-error-pages", no_argument, 0, 'Z' }, {"log-external-urls", no_argument, 0, 'U' }, {"log-cache-mismatches", no_argument, 0, 'E' }, {"form-value", no_argument, 0, 'T' }, {"rw-wordlist", required_argument, 0, 'W' }, {"no-keyword-learning", no_argument, 0, 'L' }, {"mode", required_argument, 0, 'J' }, {"wordlist", required_argument, 0, 'S'}, {"trust-domain", required_argument, 0, 'B' }, {"max-connections", required_argument, 0, 'g' }, {"max-host-connections", required_argument, 0, 'm' }, {"max-fail", required_argument, 0, 'f' }, {"request-timeout", required_argument, 0, 't' }, {"network-timeout", required_argument, 0, 'w' }, {"idle-timeout", required_argument, 0, 'i' }, {"response-size", required_argument, 0, 's' }, {"discard-binary", required_argument, 0, 'e' }, {"output", required_argument, 0, 'o' }, {"help", no_argument, 0, 'h' }, {"quiet", no_argument, 0, 'u' }, {"verbose", no_argument, 0, 'v' }, {"scan-timeout", required_argument, 0, 'k'}, {"signatures", required_argument, 0, 'z'}, {"checks", no_argument, 0, 0}, {"checks-toggle", required_argument, 0, 0}, {"no-checks", no_argument, 0, 0}, {"fast", no_argument, 0, 0}, {"auth-form", required_argument, 0, 0}, {"auth-form-target", required_argument, 0, 0}, {"auth-user", required_argument, 0, 0}, {"auth-user-field", required_argument, 0, 0}, {"auth-pass", required_argument, 0, 0}, {"auth-pass-field", required_argument, 0, 0}, {"auth-verify-url", required_argument, 0, 0}, {0, 0, 0, 0 } }; /* Come up with a quasi-decent random seed. */ gettimeofday(&tv, NULL); seed = tv.tv_usec ^ (tv.tv_sec << 16) ^ getpid(); SAY("skipfish version " VERSION " by <*****@*****.**>\n"); while ((opt = getopt_long(argc, argv, "+A:B:C:D:EF:G:H:I:J:K:LMNOPQR:S:T:UW:X:YZ" "b:c:d:ef:g:hi:k:l:m:o:p:q:r:s:t:uvw:x:z:", long_options, &oindex)) >= 0) switch (opt) { case 'A': { u8* x = (u8*)strchr(optarg, ':'); if (!x) FATAL("Credentials must be in 'user:pass' form."); *(x++) = 0; auth_user = (u8*)optarg; auth_pass = x; auth_type = AUTH_BASIC; break; } #ifdef PROXY_SUPPORT case 'J': { u8* x = (u8*)strchr(optarg, ':'); if (!x) FATAL("Proxy data must be in 'host:port' form."); *(x++) = 0; use_proxy = (u8*)optarg; use_proxy_port = atoi((char*)x); if (!use_proxy_port) FATAL("Incorrect proxy port number."); break; } #endif /* PROXY_SUPPORT */ case 'F': { u8* x = (u8*)strchr(optarg, '='); u32 fake_addr; if (!x) FATAL("Fake mappings must be in 'host=IP' form."); *x = 0; fake_addr = inet_addr((char*)x + 1); if (fake_addr == (u32)-1) FATAL("Could not parse IP address '%s'.", x + 1); fake_host((u8*)optarg, fake_addr); has_fake = 1; break; } case 'H': { u8* x = (u8*)strchr(optarg, '='); if (!x) FATAL("Extra headers must be in 'name=value' form."); *x = 0; if (!strcasecmp(optarg, "Cookie")) FATAL("Do not use -H to set cookies (try -C instead)."); SET_HDR((u8*)optarg, x + 1, &global_http_par); break; } case 'C': { u8* x = (u8*)strchr(optarg, '='); if (!x) FATAL("Cookies must be in 'name=value' form."); if (strchr(optarg, ';')) FATAL("Split multiple cookies into separate -C options."); *x = 0; SET_CK((u8*)optarg, x + 1, &global_http_par); break; } case 'D': if (*optarg == '*') optarg++; APPEND_FILTER(allow_domains, num_allow_domains, optarg); break; case 'K': APPEND_FILTER(skip_params, num_skip_params, optarg); break; case 'B': if (*optarg == '*') optarg++; APPEND_FILTER(trust_domains, num_trust_domains, optarg); break; case 'I': if (*optarg == '*') optarg++; APPEND_FILTER(allow_urls, num_allow_urls, optarg); break; case 'X': if (*optarg == '*') optarg++; APPEND_FILTER(deny_urls, num_deny_urls, optarg); break; case 'T': { u8* x = (u8*)strchr(optarg, '='); if (!x) FATAL("Rules must be in 'name=value' form."); *x = 0; add_form_hint((u8*)optarg, x + 1); break; } case 'N': ignore_cookies = 1; break; case 'Y': no_fuzz_ext = 1; break; case 'q': if (sscanf(optarg, "0x%08x", &seed) != 1) FATAL("Invalid seed format."); srandom(seed); break; case 'Q': suppress_dupes = 1; break; case 'P': no_parse = 1; break; case 'M': warn_mixed = 1; break; case 'U': log_ext_urls = 1; break; case 'L': dont_add_words = 1; break; case 'E': pedantic_cache = 1; break; case 'O': no_forms = 1; break; case 'R': purge_age = atoi(optarg); if (purge_age < 3) FATAL("Purge age invalid or too low (min 3)."); break; case 'd': max_depth = atoi(optarg); if (max_depth < 2) FATAL("Invalid value '%s'.", optarg); break; case 'c': max_children = atoi(optarg); if (!max_children) FATAL("Invalid value '%s'.", optarg); break; case 'x': max_descendants = atoi(optarg); if (!max_descendants) FATAL("Invalid value '%s'.", optarg); break; case 'p': crawl_prob = atoi(optarg); if (!crawl_prob) FATAL("Invalid value '%s'.", optarg); break; case 'W': if (wordlist) FATAL("Only one -W parameter permitted (use -S to load supplemental dictionaries)."); if (!strcmp(optarg, "-")) wordlist = (u8*)"/dev/null"; else wordlist = (u8*)optarg; break; case 'S': load_keywords((u8*)optarg, 1, 0); break; case 'z': load_signatures((u8*)optarg); sig_loaded = 1; break; case 'b': if (optarg[0] == 'i') browser_type = BROWSER_MSIE; else if (optarg[0] == 'f') browser_type = BROWSER_FFOX; else if (optarg[0] == 'p') browser_type = BROWSER_PHONE; else usage(argv[0]); break; case 'g': max_connections = atoi(optarg); if (!max_connections) FATAL("Invalid value '%s'.", optarg); break; case 'm': max_conn_host = atoi(optarg); if (!max_conn_host) FATAL("Invalid value '%s'.", optarg); break; case 'G': max_guesses = atoi(optarg); if (!max_guesses) FATAL("Invalid value '%s'.", optarg); break; case 'r': max_requests = atoi(optarg); if (!max_requests) FATAL("Invalid value '%s'.", optarg); break; case 'l': max_requests_sec = atof(optarg); if (!max_requests_sec) FATAL("Invalid value '%s'.", optarg); break; case 'f': max_fail = atoi(optarg); if (!max_fail) FATAL("Invalid value '%s'.", optarg); break; case 't': resp_tmout = atoi(optarg); if (!resp_tmout) FATAL("Invalid value '%s'.", optarg); break; case 'w': rw_tmout = atoi(optarg); if (!rw_tmout) FATAL("Invalid value '%s'.", optarg); break; case 'i': idle_tmout = atoi(optarg); if (!idle_tmout) FATAL("Invalid value '%s'.", optarg); break; case 's': size_limit = atoi(optarg); if (!size_limit) FATAL("Invalid value '%s'.", optarg); break; case 'o': if (output_dir) FATAL("Multiple -o options not allowed."); output_dir = (u8*)optarg; rmdir(optarg); if (mkdir(optarg, 0755)) PFATAL("Unable to create '%s'.", output_dir); break; case 'u': no_statistics = 1; break; case 'v': verbosity++; break; case 'e': delete_bin = 1; break; case 'k': if (gtimeout_str) FATAL("Multiple -k options not allowed."); gtimeout_str = (u8*)optarg; break; case 'Z': no_500_dir = 1; break; case 0: if (!strcmp("checks", long_options[oindex].name )) display_injection_checks(); if (!strcmp("checks-toggle", long_options[oindex].name )) toggle_injection_checks((u8*)optarg, 1, 1); if (!strcmp("no-checks", long_options[oindex].name )) no_checks = 1; if (!strcmp("signatures", long_options[oindex].name )) load_signatures((u8*)optarg); if(!strcmp("fast", long_options[oindex].name )) toggle_injection_checks((u8*)"2,4,5,13,14,15,16", 0, 0); if (!strcmp("auth-form", long_options[oindex].name )) auth_form = (u8*)optarg; if (!strcmp("auth-user", long_options[oindex].name )) auth_user = (u8*)optarg; if (!strcmp("auth-pass", long_options[oindex].name )) auth_pass = (u8*)optarg; if (!strcmp("auth-pass-field", long_options[oindex].name )) auth_pass_field = (u8*)optarg; if (!strcmp("auth-user-field", long_options[oindex].name )) auth_user_field = (u8*)optarg; if (!strcmp("auth-form-target", long_options[oindex].name )) auth_form_target = (u8*)optarg; if (!strcmp("auth-verify-url", long_options[oindex].name )) auth_verify_url = (u8*)optarg; break; default: usage(argv[0]); } #ifdef PROXY_SUPPORT if (has_fake && use_proxy) FATAL("-F and -J should not be used together."); #endif /* PROXY_SUPPORT */ if (access(ASSETS_DIR "/index.html", R_OK)) PFATAL("Unable to access '%s/index.html' - wrong directory?", ASSETS_DIR); srandom(seed); if (optind == argc) FATAL("Scan target not specified (try -h for help)."); if (!output_dir) FATAL("Output directory not specified (try -h for help)."); if(verbosity && !no_statistics && isatty(2)) FATAL("Please use -v in combination with the -u flag or, " "run skipfish while redirecting stderr to a file. "); if (resp_tmout < rw_tmout) resp_tmout = rw_tmout; if (max_connections < max_conn_host) max_connections = max_conn_host; /* Parse the timeout string - format h:m:s */ if (gtimeout_str) { int i = 0; int m[3] = { 1, 60, 3600 }; u8* tok = (u8*)strtok((char*)gtimeout_str, ":"); while(tok && i <= 2) { gtimeout += atoi((char*)tok) * m[i]; tok = (u8*)strtok(NULL, ":"); i++; } if(!gtimeout) FATAL("Wrong timeout format, please use h:m:s (hours, minutes, seconds)"); DEBUG("* Scan timeout is set to %d seconds\n", gtimeout); } if (!wordlist) { wordlist = (u8*)"/dev/null"; DEBUG("* No wordlist specified with -W: defaulting to /dev/null\n"); } /* If no signature files have been specified via command-line: load the default file */ if (!sig_loaded) load_signatures((u8*)SIG_FILE); load_keywords(wordlist, 0, purge_age); /* Load the signatures list for the matching */ if (sig_list_strg) load_signatures(sig_list_strg); /* Try to authenticate when the auth_user and auth_pass fields are set. */ if (auth_user && auth_pass) { authenticate(); while (next_from_queue()) { usleep(1000); } switch (auth_state) { case ASTATE_DONE: DEBUGC(L1, "*- Authentication succeeded!\n"); break; default: DEBUG("Auth state: %d\n", auth_state); FATAL("Authentication failed (use -uv for more info)\n"); break; } } /* Schedule all URLs in the command line for scanning. */ while (optind < argc) { struct http_request *req; /* Support @ notation for reading URL lists from files. */ if (argv[optind][0] == '@') { read_urls((u8*)argv[optind++] + 1); continue; } req = ck_alloc(sizeof(struct http_request)); if (parse_url((u8*)argv[optind], req, NULL)) FATAL("Scan target '%s' is not a valid absolute URL.", argv[optind]); if (!url_allowed_host(req)) APPEND_FILTER(allow_domains, num_allow_domains, __DFL_ck_strdup(req->host)); if (!url_allowed(req)) FATAL("URL '%s' explicitly excluded by -I / -X rules.", argv[optind]); maybe_add_pivot(req, NULL, 2); destroy_request(req); optind++; } /* Char-by char stdin. */ tcgetattr(0, &term); term.c_lflag &= ~ICANON; tcsetattr(0, TCSANOW, &term); fcntl(0, F_SETFL, O_NONBLOCK); gettimeofday(&tv, NULL); st_time = tv.tv_sec * 1000LL + tv.tv_usec / 1000; #ifdef SHOW_SPLASH if (!no_statistics) splash_screen(); #endif /* SHOW_SPLASH */ if (!no_statistics) SAY("\x1b[H\x1b[J"); else SAY(cLGN "[*] " cBRI "Scan in progress, please stay tuned...\n"); u64 refresh_time = 0; /* Enter the crawler loop */ while ((next_from_queue() && !stop_soon) || (!show_once++)) { u8 keybuf[8]; u64 end_time; u64 run_time; struct timeval tv_tmp; gettimeofday(&tv_tmp, NULL); end_time = tv_tmp.tv_sec * 1000LL + tv_tmp.tv_usec / 1000; run_time = end_time - st_time; if (gtimeout > 0 && run_time && run_time/1000 > gtimeout) { DEBUG("* Stopping scan due to timeout\n"); stop_soon = 1; } req_sec = (req_count - queue_cur / 1.15) * 1000 / (run_time + 1); if (no_statistics || ((loop_cnt++ % 100) && !show_once && idle == 0)) continue; if (end_time > refresh_time) { refresh_time = (end_time + 10); if (clear_screen) { SAY("\x1b[H\x1b[2J"); clear_screen = 0; } SAY(cYEL "\x1b[H" "skipfish version " VERSION " by [email protected]\n\n" cBRI " -" cPIN " %s " cBRI "-\n\n" cNOR, allow_domains[0]); if (!display_mode) { http_stats(st_time); SAY("\n"); database_stats(); } else { http_req_list(); } SAY(" \r"); } if (fread(keybuf, 1, sizeof(keybuf), stdin) > 0) { display_mode ^= 1; clear_screen = 1; } } gettimeofday(&tv, NULL); en_time = tv.tv_sec * 1000LL + tv.tv_usec / 1000; SAY("\n"); if (stop_soon) SAY(cYEL "[!] " cBRI "Scan aborted by user, bailing out!" cNOR "\n"); term.c_lflag |= ICANON; tcsetattr(0, TCSANOW, &term); fcntl(0, F_SETFL, O_SYNC); save_keywords((u8*)wordlist); write_report(output_dir, en_time - st_time, seed); #ifdef LOG_STDERR SAY("\n== PIVOT DEBUG ==\n"); dump_pivots(0, 0); SAY("\n== END OF DUMP ==\n\n"); #endif /* LOG_STDERR */ SAY(cLGN "[+] " cBRI "This was a great day for science!" cRST "\n\n"); #ifdef DEBUG_ALLOCATOR if (!stop_soon) { destroy_database(); destroy_signature_lists(); destroy_http(); destroy_signatures(); __TRK_report(); } #endif /* DEBUG_ALLOCATOR */ fflush(0); EVP_cleanup(); CRYPTO_cleanup_all_ex_data(); return 0; }
static void read_urls(u8* fn) { FILE* f = fopen((char*)fn, "r"); u8 tmp[MAX_URL_LEN]; u32 loaded = 0; if (!f) FATAL("Unable to open '%s'.", fn); while (fgets((char*)tmp, MAX_URL_LEN, f)) { struct http_request *req; u8* url = tmp; u8* ptr; u32 l; while (isspace(*url)) url++; /* Check if we're reading a pivots.txt file and grab the URL */ if(!strncmp((char*)url,"GET ", 4) || !strncmp((char*)url,"POST ", 4)) { url += 4; /* If the server response code is a 404, than we'll skip the URL to avoid wasting time on things that are likely not to exist. */ if(inl_findstr(url, (u8*)"code=404", MAX_URL_LEN)) continue; ptr = url; /* Find the next space to terminate the URL */ while(ptr && !isspace(*ptr)) ptr++; if(!ptr) FATAL("URL parsing failed at line: %s", tmp); *ptr = 0; /* Else we expect a simple flat file with URLs */ } else { l = strlen((char*)url); while (l && isspace(url[l-1])) l--; url[l] = 0; } if (*url == '#' || !*url) continue; req = ck_alloc(sizeof(struct http_request)); if (parse_url(url, req, NULL)) FATAL("Scan target '%s' in file '%s' is not a valid absolute URL.", url, fn); if (!url_allowed_host(req)) APPEND_FILTER(allow_domains, num_allow_domains, __DFL_ck_strdup(req->host)); if (!url_allowed(req)) FATAL("URL '%s' in file '%s' explicitly excluded by -I / -X rules.", url, fn); maybe_add_pivot(req, NULL, 2); destroy_request(req); loaded++; } fclose(f); if (!loaded) FATAL("No valid URLs found in '%s'.", fn); }
int main(int argc, char *argv[]) { int port = 1220; if (argc > 1) port = atoi(argv[1]); int fd = socket(AF_INET, SOCK_STREAM, 0); int flags = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&flags, sizeof(flags)); setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&flags, sizeof(flags)); struct sockaddr_in addr; memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("bind()"); if(fd > 0) close(fd); exit(1); } if (listen(fd, 1024) < 0) { perror("listen()"); exit(1); } RespRequest *req = create_request(BUF_SIZE); RespResponse *res = create_response(BUF_SIZE); while (1) { reset_request(req); reset_response(res); socklen_t addr_len = sizeof(addr); int cfd = accept(fd, (struct sockaddr*)&addr, &addr_len); if (cfd < 0) { perror("accept()"); continue; } char buf[1024]; int rnum = read(cfd,buf,sizeof(buf)); if (decode_request(req, buf, rnum) == 0 && (req->state == OK || req->state == PART_OK) ){ if (req->argc > 1 && strncmp(request_argv(req,0), "add", 3) == 0) { int total = 0; for (int i = 1; i < req->argc; i++) total += atoi(request_argv(req,i)); encode_response_integer(res, total); } else { encode_response_status(res,0,"ERR unknown command"); } } else { encode_response_status(res,0,"ERR decode command fail"); } write(cfd, res->buf, res->used_size); close(cfd); } destroy_request(req); destroy_response(res); close(fd); return 0; }
static void on_fs_open(uv_fs_t* req) { http_request* request = (http_request*) req->data; int result = req->result; uv_fs_req_cleanup(req); free(req); if (result < 0) { fprintf(stderr, "Open error: %s: %s\n", uv_err_name(result), uv_strerror(result)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_request(request, 1); return; } uv_fs_t stat_req; int r = uv_fs_fstat(loop, &stat_req, result, NULL); if (r) { fprintf(stderr, "Stat error: %s: %s\n", uv_err_name(r), uv_strerror(r)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_request(request, 1); return; } uint64_t response_size = stat_req.statbuf.st_size; uv_fs_req_cleanup(&stat_req); const static char* ctype = "application/octet-stream"; const char* dot = request->file_path; const char* ptr = dot; while (dot) { ptr = dot; dot = strchr(dot + 1, '.'); } khint_t k = kh_get(mime_type, mime_type, ptr); if (k != kh_end(mime_type)) { ctype = kh_value(mime_type, k); } http_response* response = calloc(1, sizeof(http_response)); if (response == NULL) { fprintf(stderr, "Allocate error: %s\n", strerror(r)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_request(request, 1); return; } response->response_size = response_size; response->fd = result; response->request = request; response->handle = request->handle; response->pbuf = malloc(WRITE_BUF_SIZE); if (response->pbuf == NULL) { fprintf(stderr, "Allocate error: %s\n", strerror(r)); response_error(request->handle, 404, "Not Found\n", NULL); destroy_response(response, 1); return; } response->buf = uv_buf_init(response->pbuf, WRITE_BUF_SIZE); response->read_req.data = response; response->write_req.data = response; char bufline[1024]; int nbuf = snprintf(bufline, sizeof(bufline), "HTTP/1.1 200 OK\r\n" "Content-Length: %" PRId64 "\r\n" "Content-Type: %s\r\n" "Connection: %s\r\n" "\r\n", response_size, ctype, (request->keep_alive ? "keep-alive" : "close")); uv_buf_t buf = uv_buf_init(bufline, nbuf); #ifndef _WIN32 r = uv_try_write((uv_stream_t*) request->handle, &buf, 1); if (r == 0) { fprintf(stderr, "Write error\n"); destroy_response(response, 1); return; } #else r = uv_write(&response->write_req, (uv_stream_t*) request->handle, &buf, 1, NULL); if (r) { fprintf(stderr, "Write error: %s: %s\n", uv_err_name(r), uv_strerror(r)); destroy_response(response, 1); return; } #endif r = uv_fs_read(loop, &response->read_req, result, &response->buf, 1, -1, on_fs_read); if (r) { response_error(request->handle, 500, "Internal Server Error\n", NULL); destroy_response(response, 1); } }
int thread_main(server_decl_t *srv){ ci_connection_t con; ci_thread_mutex_t cont_mtx; char clientname[CI_MAXHOSTNAMELEN+1]; int max,ret,request_status=0; request_t *tmp; //*********************** thread_signals(); //************************* srv->srv_id=getpid(); //Setting my pid ... srv->srv_pthread=pthread_self(); for(;;){ if(child_data->to_be_killed) return; //Exiting thread..... if((ret=get_from_queue(con_queue,&con))==0){ wait_for_queue(con_queue); //It is better that the wait_for_queue to be //moved into the get_from_queue continue; } ci_thread_mutex_lock(&counters_mtx); (child_data->freeservers)--; (child_data->usedservers)++; ci_thread_mutex_unlock(&counters_mtx); if(ret<0){ //An error has occured debug_printf(1,"Error getting from connections queue\n"); break; } /* icap_addrtohost(&(con.claddr.sin_addr),clientname, CI_MAXHOSTNAMELEN); debug_printf(1,"Client name: %s server %d\n",clientname,srv->srv_id); */ icap_netio_init(con.fd); if(srv->current_req==NULL) srv->current_req=newrequest(&con); else recycle_request(srv->current_req,&con); do{ if((request_status=process_request(srv->current_req))<0){ debug_printf(5,"Process request timeout or interupted....\n"); reset_request(srv->current_req); break;// } srv->served_requests++; srv->served_requests_no_reallocation++; /*Increase served requests. I dont like this. The delay is small but I don't like...*/ ci_thread_mutex_lock(&counters_mtx); (child_data->requests)++; ci_thread_mutex_unlock(&counters_mtx); log_access(srv->current_req,request_status); // break; //No keep-alive ...... if(child_data->to_be_killed) return; //Exiting thread..... debug_printf(8,"Keep-alive:%d\n",srv->current_req->keepalive); if(srv->current_req->keepalive && check_for_keepalive_data(srv->current_req->connection->fd)){ reset_request(srv->current_req); debug_printf(8,"Server %d going to serve new request from client(keep-alive) \n", srv->srv_id); } else break; }while(1); if(srv->current_req){ if(request_status<0) hard_close_connection(srv->current_req->connection); else close_connection(srv->current_req->connection); } if(srv->served_requests_no_reallocation > MAX_REQUESTS_BEFORE_REALLOCATE_MEM){ debug_printf(5,"Max requests reached, reallocate memory and buffers .....\n"); destroy_request(srv->current_req); srv->current_req=NULL; srv->served_requests_no_reallocation=0; } ci_thread_mutex_lock(&counters_mtx); (child_data->freeservers)++; (child_data->usedservers)--; ci_thread_mutex_unlock(&counters_mtx); ci_thread_cond_signal(&free_server_cond); } return 0; }