int parse_header(int fd_src, t_parser *parser, header_t *header, int *size) { char *line; reset_str(header->comment, COMMENT_LENGTH + 1); if ((line = get_next_size(fd_src, parser, size)) == NULL) return (1); if (parse_header_line(line, NAME_CMD_STRING, header->prog_name) == 1) { syntax_error(parser->line_nb); return (1); } free(line); header->prog_size = 0; if ((line = get_next_size(fd_src, parser, size)) == NULL) return (1); if (parse_header_line(line, COMMENT_CMD_STRING, header->comment) == 1) { syntax_error(parser->line_nb); return (1); } free(line); return (0); }
http_status http_server::http_request_state::parse_message_line(const char* line) // Parse the next line. { VLOG("parse_message_line: '%s'\n", line); http_status status = HTTP_BAD_REQUEST; switch (m_request_state) { default: case PARSE_DONE: assert(0); break; case PARSE_START_LINE: status = parse_request_line(line); if (status < 400) { // Move on to the rest of the header. m_request_state = PARSE_HEADER; } break; case PARSE_HEADER: status = parse_header_line(line); break; } return status; }
/* parse an option */ static int parse_option(char *line) { if (req.method==0) return parse_first_line(line); else return parse_header_line(line); }
static int finish_header_line(struct owfd_rtsp_decoder *dec, size_t rlen) { char *line; size_t l; int r; l = rlen; line = shl_ring_copy(&dec->ring, &l); if (!line) return -ENOMEM; shl_ring_pull(&dec->ring, rlen); l = sanitize_header_line(dec, line, l); r = parse_header_line(dec, line); if (r < 0) { free(line); return r; } r = push_header_line(dec, line, l); if (r < 0) { free(line); return r; } return 0; }
ssize_t req_parse(req_t *req, const char *data, size_t len) { g_return_val_if_fail(req != NULL, -1); g_return_val_if_fail(data != NULL, -1); if (req_is_complete(req)) { g_warning("request already complete"); return 0; } if (strlen(data) < len) { // we have a null somewhere in the string req->state = STATE_INVALID; return -1; } /* request not complete, data looks good. * time to split and parse. */ ssize_t pos = 0; while (pos < len && !req_is_complete(req)) { ssize_t line_len; line_len = req_feed_line(req, data + pos, len - pos); if (line_len < 0) { // TODO better errors return -1; } pos += line_len; if (req->line_ready) { switch (req->state) { case STATE_INITIAL: if (parse_request_line(req, req->buf, req->buf_size) < 0) { return -1; } break; case STATE_IN_HEADER: if (req->buf_size == 0) { req->state = STATE_COMPLETE; } else if (parse_header_line(req, req->buf, req->buf_size) < 0) { return -1; } break; case STATE_COMPLETE: case STATE_INVALID: g_return_val_if_reached(-1); break; } g_free(req->buf); req->buf = NULL; req->buf_size = 0; req->line_ready = false; } } return pos; }
/* * parse the first line (by first_line_fn) and headers * return -1 if the message is too long or non-standard */ static int parse_general_http(struct parser *req, int (*first_line_fn)(struct parser *p)) { enum parse_state p_state = REQUEST_LINE; while (1) { if (req->parse_start >= req->parse_end) { int ret = try_read(req, (req->recv_buf_end - req->parse_end)); if (ret == 0 || ret == -1) { /* 0 means client closed */ syslog(LOG_INFO, "early close"); return -1; } } char *p = line_end(req); if (!p) { syslog(LOG_CRIT, "The headers are too long to handle"); return -1; } switch (p_state) { case REQUEST_LINE: if (first_line_fn(req) == -1) { syslog(LOG_CRIT, "The 1st line is bad"); return -1; } p_state = HEADER_LINES; break; case HEADER_LINES: if (p == req->parse_start) { /* meeting 2 CRLF: end of headers */ req->parse_start += 2; return 0; } if (parse_header_line(req) == -1) { syslog(LOG_CRIT, "The header line is bad"); return -1; } break; } } }
AW_Result aw_session_run (AW_Session *sess) { AW_MethodFunc func; AW_Char *line; AW_Result r; AW_ASSERT(sess); if (!(line = get_line(sess))) { return AW_ERR_SYNTAX; } if ((r = parse_request_line(sess, line)) != AW_OK) return r; while (1) { if (!(line = get_line(sess))) { return AW_ERR_SYNTAX; } if (line[0] == 0) break; if ((r = parse_header_line(sess, line)) != AW_OK) return r; } func = sess->serv->methods[sess->method]; if (func) { r = func(sess, sess->method); } else { AW_ERROR(("do not support the method %d", sess->method)); r = AW_ERR_NOTSUPP; } return r; }
static void process_data(struct http_client_request *req) { int bytes_to_commit = 0; while (req->state == EINPROGRESS) { char *parse_head = req->rcvbuf + req->parse_ptr; char *endline; int bytes_left; int line_size; bytes_left = req->read_ptr - req->parse_ptr; endline = memchr(parse_head, '\n', bytes_left); if (endline == NULL) { endline = memchr(parse_head, '\r', bytes_left); if (endline == NULL) { bytes_to_commit += bytes_left; break; } } line_size = endline - parse_head + 1; bytes_to_commit += line_size; req->parse_ptr += line_size; *endline = 0; if (parse_head != endline && endline[-1] == '\r') endline[-1] = 0; if (req->response_code == -1) parse_first_line(req, parse_head); else parse_header_line(req, parse_head); } commit(req, bytes_to_commit); }
/* Process each packet that passes the capture filter */ void parse_http_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *pkt) { struct tm *pkt_time; char *header_line, *req_value; char saddr[INET6_ADDRSTRLEN], daddr[INET6_ADDRSTRLEN]; char sport[PORTSTRLEN], dport[PORTSTRLEN]; char ts[MAX_TIME_LEN]; int is_request = 0, is_response = 0; unsigned int eth_type = 0, offset; const struct eth_header *eth; const struct ip_header *ip; const struct ip6_header *ip6; const struct tcp_header *tcp; const char *data; int size_ip, size_tcp, size_data, family; /* Check the ethernet type and insert a VLAN offset if necessary */ eth = (struct eth_header *) pkt; eth_type = ntohs(eth->ether_type); if (eth_type == ETHER_TYPE_VLAN) { offset = link_offset + 4; } else { offset = link_offset; } offset += eth_skip_bits; /* Position pointers within packet stream and do sanity checks */ ip = (struct ip_header *) (pkt + offset); ip6 = (struct ip6_header *) (pkt + offset); switch (IP_V(ip)) { case 4: family = AF_INET; break; case 6: family = AF_INET6; break; default: return; } if (family == AF_INET) { size_ip = IP_HL(ip) * 4; if (size_ip < 20) return; if (ip->ip_p != IPPROTO_TCP) return; } else { /* AF_INET6 */ size_ip = sizeof(struct ip6_header); if (ip6->ip6_nh != IPPROTO_TCP) size_ip = process_ip6_nh(pkt, size_ip, header->caplen, offset); if (size_ip < 40) return; } tcp = (struct tcp_header *) (pkt + offset + size_ip); size_tcp = TH_OFF(tcp) * 4; if (size_tcp < 20) return; data = (char *) (pkt + offset + size_ip + size_tcp); size_data = (header->caplen - (offset + size_ip + size_tcp)); if (size_data <= 0) return; /* Check if we appear to have a valid request or response */ if (is_request_method(data)) { is_request = 1; } else if (strncmp(data, HTTP_STRING, strlen(HTTP_STRING)) == 0) { is_response = 1; } else { return; } /* Copy packet data to editable buffer that was created in main() */ if (size_data > BUFSIZ) size_data = BUFSIZ; memcpy(buf, data, size_data); buf[size_data] = '\0'; /* Parse header line, bail if malformed */ if ((header_line = parse_header_line(buf)) == NULL) return; if (is_request) { if (parse_client_request(header_line)) return; } else if (is_response) { if (parse_server_response(header_line)) return; } /* Iterate through request/entity header fields */ while ((header_line = parse_header_line(NULL)) != NULL) { if ((req_value = strchr(header_line, ':')) == NULL) continue; *req_value++ = '\0'; while (isspace(*req_value)) req_value++; insert_value(header_line, req_value); } /* Grab source/destination IP addresses */ if (family == AF_INET) { inet_ntop(family, &ip->ip_src, saddr, sizeof(saddr)); inet_ntop(family, &ip->ip_dst, daddr, sizeof(daddr)); } else { /* AF_INET6 */ inet_ntop(family, &ip6->ip_src, saddr, sizeof(saddr)); inet_ntop(family, &ip6->ip_dst, daddr, sizeof(daddr)); } insert_value("source-ip", saddr); insert_value("dest-ip", daddr); /* Grab source/destination ports */ snprintf(sport, PORTSTRLEN, "%d", ntohs(tcp->th_sport)); snprintf(dport, PORTSTRLEN, "%d", ntohs(tcp->th_dport)); insert_value("source-port", sport); insert_value("dest-port", dport); /* Extract packet capture time */ pkt_time = localtime((time_t *) &header->ts.tv_sec); strftime(ts, MAX_TIME_LEN, "%Y-%m-%d %H:%M:%S", pkt_time); insert_value("timestamp", ts); if (rate_stats) { update_host_stats(get_value("host"), header->ts.tv_sec); clear_values(); } else { print_format_values(); } if (dumpfile) pcap_dump((unsigned char *) dumpfile, header, pkt); num_parsed++; if (parse_count && (num_parsed >= parse_count)) pcap_breakloop(pcap_hnd); return; }
/* Process each packet that passes the capture filter */ void parse_http_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *pkt) { struct tm *pkt_time; char *header_line, *req_value; char saddr[INET_ADDRSTRLEN], daddr[INET_ADDRSTRLEN]; char sport[PORTSTRLEN], dport[PORTSTRLEN]; char ts[MAX_TIME_LEN]; int is_request = 0, is_response = 0; const struct ip_header *ip; const struct tcp_header *tcp; const char *data; int size_ip, size_tcp, size_data; /* Position pointers within packet stream and do sanity checks */ ip = (struct ip_header *) (pkt + header_offset); size_ip = IP_HL(ip) * 4; if (size_ip < 20) return; if (ip->ip_p != IPPROTO_TCP) return; tcp = (struct tcp_header *) (pkt + header_offset + size_ip); size_tcp = TH_OFF(tcp) * 4; if (size_tcp < 20) return; data = (char *) (pkt + header_offset + size_ip + size_tcp); size_data = (header->caplen - (header_offset + size_ip + size_tcp)); if (size_data <= 0) return; /* Check if we appear to have a valid request or response */ if (is_request_method(data)) { is_request = 1; } else if (strncmp(data, HTTP_STRING, strlen(HTTP_STRING)) == 0) { is_response = 1; } else { return; } /* Copy packet data to editable buffer that was created in main() */ if (size_data > BUFSIZ) size_data = BUFSIZ; strncpy(buf, data, size_data); buf[size_data] = '\0'; /* Parse header line, bail if malformed */ if ((header_line = parse_header_line(buf)) == NULL) return; if (is_request) { if (parse_client_request(header_line)) return; } else if (is_response) { if (parse_server_response(header_line)) return; } /* Iterate through request/entity header fields */ while ((header_line = parse_header_line(NULL)) != NULL) { if ((req_value = strchr(header_line, ':')) == NULL) continue; *req_value++ = '\0'; while (isspace(*req_value)) req_value++; insert_value(header_line, req_value); } /* Grab source/destination IP addresses */ strncpy(saddr, (char *) inet_ntoa(ip->ip_src), INET_ADDRSTRLEN); strncpy(daddr, (char *) inet_ntoa(ip->ip_dst), INET_ADDRSTRLEN); insert_value("source-ip", saddr); insert_value("dest-ip", daddr); /* Grab source/destination ports */ sprintf(sport, "%d", ntohs(tcp->th_sport)); sprintf(dport, "%d", ntohs(tcp->th_dport)); insert_value("source-port", sport); insert_value("dest-port", dport); /* Extract packet capture time */ pkt_time = localtime((time_t *) &header->ts.tv_sec); strftime(ts, MAX_TIME_LEN, "%Y-%m-%d %H:%M:%S", pkt_time); insert_value("timestamp", ts); print_format_values(); if (dumpfile) pcap_dump((unsigned char *) dumpfile, header, pkt); num_parsed++; if (parse_count && (num_parsed >= parse_count)) pcap_breakloop(pcap_hnd); return; }
void blizzard::http::process() { bool quit = false; int res = 0; while (!quit) { switch (state_) { case sUndefined: want_read = true; want_write = false; state_ = sReadingHead; break; case sReadingHead: res = parse_title(); if (res > 0) { state_ = sDone; quit = true; } else if (res < 0) { quit = true; } break; case sReadingHeaders: res = parse_header_line(); if (res > 0) { state_ = sDone; quit = true; } else if (res < 0) { quit = true; } if (state_ == sReadyToHandle) { quit = true; } break; case sReadingPost: res = parse_post(); if (res < 0) { quit = true; } break; case sReadyToHandle: commit(); state_ = sWriting; break; case sWriting: want_write = true; res = write_data(); if (res < 0) { quit = true; } break; case sDone: quit = true; break; default: break; } } }
/* Just a lightweight http request processor */ void process_http(ape_socket *co, acetables *g_ape) { ape_buffer *buffer = &co->buffer_in; http_state *http = co->parser.data; ape_parser *parser = &co->parser; char *data = buffer->data; int pos, read, p = 0; if (buffer->length == 0 || parser->ready == 1 || http->error == 1) { return; } /* 0 will be erased by the next read()'ing loop */ data[buffer->length] = '\0'; data = &data[http->pos]; if (*data == '\0') { return; } /* Update the address of http->data and http->uri if buffer->data has changed (realloc) */ if (http->buffer_addr != NULL && buffer->data != http->buffer_addr) { if (http->data != NULL) http->data = &buffer->data[(void *)http->data - (void *)http->buffer_addr]; if (http->uri != NULL) http->uri = &buffer->data[(void *)http->uri - (void *)http->buffer_addr]; http->buffer_addr = buffer->data; } switch(http->step) { case 0: pos = seof(data, '\n'); if (pos == -1) { return; } switch(*(unsigned int *)data) { #ifdef _LITTLE_ENDIAN case 0x20544547: /* GET + space */ #endif #ifdef _BIG_ENDIAN case 0x47455420: /* GET + space */ #endif http->type = HTTP_GET; p = 4; break; #ifdef _LITTLE_ENDIAN case 0x54534F50: /* POST */ #endif #ifdef _BIG_ENDIAN case 0x504F5354: /* POST */ #endif http->type = HTTP_POST; p = 5; break; default: ape_log(APE_INFO, __FILE__, __LINE__, g_ape, "Invalid HTTP method in request: %s", data); http->error = 1; shutdown(co->fd, 2); return; } if (data[p] != '/') { http->error = 1; shutdown(co->fd, 2); return; } else { int i = p; while (p++) { switch(data[p]) { case ' ': http->pos = pos; http->step = 1; http->uri = &data[i]; http->buffer_addr = buffer->data; data[p] = '\0'; process_http(co, g_ape); return; case '?': if (data[p+1] != ' ' && data[p+1] != '\r' && data[p+1] != '\n') { http->buffer_addr = buffer->data; http->data = &data[p+1]; } break; case '\r': case '\n': case '\0': ape_log(APE_INFO, __FILE__, __LINE__, g_ape, "Invalid line ending in request: %s", data); http->error = 1; shutdown(co->fd, 2); return; } } } break; case 1: pos = seof(data, '\n'); if (pos == -1) { return; } if (pos == 1 || (pos == 2 && *data == '\r')) { if (http->type == HTTP_GET) { /* Ok, at this point we have a blank line. Ready for GET */ buffer->data[http->pos] = '\0'; urldecode(http->uri); parser->onready(parser, g_ape); parser->ready = -1; buffer->length = 0; return; } else if (http->type == HTTP_GET_WS) { /* WebSockets handshake needs to read 8 bytes */ //urldecode(http->uri); http->contentlength = 8; http->buffer_addr = buffer->data; http->data = &buffer->data[http->pos+(pos)]; http->step = 2; } else { /* Content-Length is mandatory in case of POST */ if (http->contentlength == 0) { http->error = 1; shutdown(co->fd, 2); return; } else { http->buffer_addr = buffer->data; // save the addr http->data = &buffer->data[http->pos+(pos)]; http->step = 2; } } } else { struct _http_header_line *hl; if ((hl = parse_header_line(data)) != NULL) { hl->next = http->hlines; http->hlines = hl; if (strcasecmp(hl->key.val, "host") == 0) { http->host = hl->value.val; } } if (http->type == HTTP_POST) { /* looking for content-length instruction */ if (pos <= 25 && strncasecmp("content-length: ", data, 16) == 0) { int cl = atoi(&data[16]); /* Content-length can't be negative... */ if (cl < 1 || cl > MAX_CONTENT_LENGTH) { http->error = 1; shutdown(co->fd, 2); return; } /* At this time we are ready to read "cl" bytes contents */ http->contentlength = cl; } } else if (http->type == HTTP_GET) { if (strncasecmp("Sec-WebSocket-Key1: ", data, 20) == 0) { http->type = HTTP_GET_WS; } } } http->pos += pos; process_http(co, g_ape); break; case 2: read = buffer->length - http->pos; // data length http->pos += read; http->read += read; if (http->read >= http->contentlength) { parser->ready = 1; urldecode(http->uri); /* no more than content-length */ buffer->data[http->pos - (http->read - http->contentlength)] = '\0'; parser->onready(parser, g_ape); parser->ready = -1; buffer->length = 0; } break; default: break; } }
static void kum_read_header( kum_file* kum, FILE* fp ) { char line[ MAX_LINE_SIZE ]; char* key; char* value; char* s; while( fgets( line, MAX_LINE_SIZE, fp ) != NULL ) { s = prepare_line( line, NULL ); if( *s == '\0' ) { continue; } if( strcmp( s, "BEGIN CHARMAP" ) == 0 ) { break; } parse_header_line( line, &key, &value ); // fprintf( stderr, "\'%s\' = \'%s\'\n", key, value ); if( strcmp( "name", key ) == 0 ) { strcpy( kum->name, value ); } else if( strcmp( "type", key ) == 0 ) { if( strcmp( value, "SBCS" ) == 0 ) { kum->conv_type = KUM_SBCS; } else if( strcmp( value, "DBCS" ) == 0 ) { kum->conv_type = KUM_DBCS; } else if( strcmp( value, "MBCS" ) == 0 ) { kum->conv_type = KUM_MBCS; } else { fprintf( stderr, "kum error: invalid 'type' value\n." ); exit( 1 ); } } else if( strcmp( "min_char_len", key ) == 0 ) { char* end; kum->min_char_len = strtol( value, &end, 10 ); if( kum->min_char_len <= 0 || *end != '\0' ) { fprintf( stderr, "kum warning: invalid value of 'min_char_len'.\n" ); } } else if( strcmp( "max_char_len", key ) == 0 ) { char* end; kum->max_char_len = strtol( value, &end, 10 ); if( kum->max_char_len <= 0 || *end != '\0' ) { fprintf( stderr, "kum warning: invalid value of 'max_char_len'.\n" ); } } else if( strcmp( "sub_char", key ) == 0 ) { uint8_t bytes[ KUCONV_MAX_CHAR_LEN ]; int8_t len; s = value; len = kum_parse_bytes( bytes, line, &s ); if( len < 1 || len > 4 || *s != '\0' ) { fprintf( stderr, "kum error: invalid value of 'sub_char'.\n" ); exit( 1 ); } kum->sub_char_len = len; memcpy( kum->sub_char, bytes, len ); } else if( strcmp( "sub_char1", key ) == 0 ) { uint8_t bytes[ KUCONV_MAX_CHAR_LEN ]; int8_t len; s = value; len = kum_parse_bytes( bytes, line, &s ); if( len != 1 || *s != '\0' ) { fprintf( stderr, "kum error: invalid value of 'sub_char'.\n" ); exit( 1 ); } kum->sub_char1 = bytes[ 0 ]; } else if( strcmp( "state", key ) == 0 ) { switch( kum->conv_type ) { case KUM_SBCS: case KUM_DBCS: kum->conv_type = KUM_MBCS; break; case KUM_MBCS: break; default: fprintf( stderr, "kum error: 'state' entry before the 'type'.\n"); exit( 1 ); } kum_add_state( &kum->states, value ); } else { fprintf( stderr, "kum warning: unknown header value '%s'.\n", key ); } } }