static int parse_multipart_header(AVIOContext *pb, void *log_ctx) { char line[128]; int found_content_type = 0; int ret, size = -1; ret = get_line(pb, line, sizeof(line)); if (ret < 0) return ret; if (strncmp(line, "--", 2)) return AVERROR_INVALIDDATA; while (!pb->eof_reached) { char *tag, *value; ret = get_line(pb, line, sizeof(line)); if (ret < 0) { if (ret == AVERROR_EOF) break; return ret; } if (line[0] == '\0') break; ret = split_tag_value(&tag, &value, line); if (ret < 0) return ret; if (!av_strcasecmp(tag, "Content-type")) { if (av_strcasecmp(value, "image/jpeg")) { if (log_ctx) { av_log(log_ctx, AV_LOG_ERROR, "Unexpected %s : %s\n", tag, value); } return AVERROR_INVALIDDATA; } else found_content_type = 1; } else if (!av_strcasecmp(tag, "Content-Length")) { size = parse_content_length(value); if (size < 0) return size; } } if (!found_content_type || size < 0) { return AVERROR_INVALIDDATA; } return size; }
static utility_retcode_t parse_one_header(struct rtsp_response *response) { utility_retcode_t ret = UTILITY_SUCCESS; char *start_value; char *header_name = response->current_header.name; char *header_value = response->current_header.value; FUNC_ENTER; ret = utility_copy_token(header_name, MAX_HEADER_NAME_LEN, response->parsep, ": ", NULL); if (UTILITY_SUCCESS != ret) { ERRR("Failed to copy header name\n"); goto out; } start_value = begin_token(response->parsep, ": "); ret = utility_copy_token(header_value, MAX_HEADER_VALUE_LEN, start_value, "\r\n", NULL); if (UTILITY_SUCCESS != ret) { ERRR("Failed to copy header value\n"); goto out; } DEBG("Found header name: \"%s\" value: \"%s\"\n", header_name, header_value); if (0 == syscalls_strcmp(header_name, "Content-Length")) { ret = parse_content_length(response); } else if (0 == syscalls_strcmp(header_name, "Apple-Response")) { ret = parse_apple_response(response); } else if (0 == syscalls_strcmp(header_name, "Audio-Jack-Status")) { ret = parse_audio_jack_status(response); } else if (0 == syscalls_strcmp(header_name, "Session")) { ret = parse_session(response); } else if (0 == syscalls_strcmp(header_name, "Transport")) { ret = parse_transport(response); } else if (0 == syscalls_strcmp(header_name, "Public")) { ret = parse_public(response); } else { parse_unknown_header(response); } out: FUNC_RETURN; return ret; }
void http_header::init_properties() { static const std::string header_end{"\r\n\r\n"}; type = Type::HEADER; size_t pos = data.find("\r\n"); head = data.substr(0, pos); transform_to_relative(); parse_is_chunked_encoding(); parse_content_length(); sz = data.find(header_end) + header_end.size(); state = State::COMPLETE; }
/** * Check if a Service Point Trigger for Session Description matches the SDP body * @param spt - the service point trigger * @param msg - the message * @returns - 1 on success, 0 on failure */ static int isc_check_session_desc(ims_spt *spt, struct sip_msg *msg) { int len; char *body, c; char *x; regex_t comp; if (msg->content_type == NULL) return FALSE; if (strncasecmp(msg->content_type->body.s, sdp.s, msg->content_type->body.len) != 0) return FALSE; LM_DBG("ifc_check_session_desc: Found Content-Type == appliction/sdp\n"); //check for sdp line body = get_body(msg); if (body == 0) return FALSE; if (msg->content_length->parsed == NULL) { parse_content_length(msg->content_length->body.s, msg->content_length->body.s + msg->content_length->body.len, &len); msg->content_length->parsed = (void*) (long) len; } else len = (long) msg->content_length->parsed; c = body[len]; body[len] = 0; x = pkg_malloc(spt->session_desc.line.len + 2 + spt->session_desc.content.len); sprintf(x, "%.*s=%.*s", spt->session_desc.line.len, spt->session_desc.line.s, spt->session_desc.content.len, spt->session_desc.content.s); /* compile the whole regexp */ regcomp(&(comp), x, REG_ICASE | REG_EXTENDED); if (regexec(&(comp), body, 0, NULL, 0) == 0) //regex match { body[len] = c; LM_DBG("ifc_check_session_desc: Found Session Desc. > %s\n", body); pkg_free(x); return TRUE; } body[len] = c; pkg_free(x); return FALSE; }
/* returns pointer to next header line, and fill hdr_f ; * if at end of header returns pointer to the last crlf (always buf)*/ char* get_hdr_field(char* const buf, char* const end, struct hdr_field* const hdr) { char *tmp = 0; char *match; struct via_body *vb; struct cseq_body* cseq_b; struct to_body* to_b; int integer, err; unsigned uval; if(!buf) { DBG("null buffer pointer\n"); goto error; } if ((*buf)=='\n' || (*buf)=='\r') { /* double crlf or lflf or crcr */ DBG("found end of header\n"); hdr->type=HDR_EOH_T; return buf; } tmp=parse_hname(buf, end, hdr); if (hdr->type==HDR_ERROR_T) { LOG(L_ERR, "ERROR: get_hdr_field: bad header\n"); goto error; } /* eliminate leading whitespace */ tmp=eat_lws_end(tmp, end); if (tmp>=end) { LOG(L_ERR, "ERROR: get_hdr_field: HF empty\n"); goto error; } /* if header-field well-known, parse it, find its end otherwise ; * after leaving the hdr->type switch, tmp should be set to the * next header field */ switch(hdr->type) { case HDR_VIA_T: /* keep number of vias parsed -- we want to report it in replies for diagnostic purposes */ via_cnt++; vb=pkg_malloc(sizeof(struct via_body)); if (vb==0) { LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(vb,0,sizeof(struct via_body)); hdr->body.s=tmp; tmp=parse_via(tmp, end, vb); if (vb->error==PARSE_ERROR) { LOG(L_ERR, "ERROR: get_hdr_field: bad via\n"); free_via_list(vb); goto error; } hdr->parsed=vb; vb->hdr.s=hdr->name.s; vb->hdr.len=hdr->name.len; hdr->body.len=tmp-hdr->body.s; break; case HDR_CSEQ_T: cseq_b=pkg_malloc(sizeof(struct cseq_body)); if (cseq_b==0) { LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(cseq_b, 0, sizeof(struct cseq_body)); hdr->body.s=tmp; tmp=parse_cseq(tmp, end, cseq_b); if (cseq_b->error==PARSE_ERROR) { LOG(L_ERR, "ERROR: get_hdr_field: bad cseq\n"); free_cseq(cseq_b); goto error; } hdr->parsed=cseq_b; hdr->body.len=tmp-hdr->body.s; DBG("get_hdr_field: cseq <%.*s>: <%.*s> <%.*s>\n", hdr->name.len, ZSW(hdr->name.s), cseq_b->number.len, ZSW(cseq_b->number.s), cseq_b->method.len, cseq_b->method.s); break; case HDR_TO_T: to_b=pkg_malloc(sizeof(struct to_body)); if (to_b==0) { LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(to_b, 0, sizeof(struct to_body)); hdr->body.s=tmp; tmp=parse_to(tmp, end,to_b); if (to_b->error==PARSE_ERROR) { LOG(L_ERR, "ERROR: get_hdr_field: bad to header\n"); free_to(to_b); goto error; } hdr->parsed=to_b; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_field: <%.*s> [%d]; uri=[%.*s] \n", hdr->name.len, ZSW(hdr->name.s), hdr->body.len, to_b->uri.len,ZSW(to_b->uri.s)); DBG("DEBUG: to body [%.*s]\n",to_b->body.len, ZSW(to_b->body.s)); break; case HDR_CONTENTLENGTH_T: hdr->body.s=tmp; tmp=parse_content_length(tmp,end, &integer); if (tmp==0) { LOG(L_ERR, "ERROR:get_hdr_field: bad content_length header\n"); goto error; } hdr->parsed=(void*)(long)integer; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_body : content_length=%d\n", (int)(long)hdr->parsed); break; case HDR_RETRY_AFTER_T: hdr->body.s=tmp; tmp=parse_retry_after(tmp,end, &uval, &err); if (err) { LOG(L_ERR, "ERROR:get_hdr_field: bad retry_after header\n"); goto error; } hdr->parsed=(void*)(unsigned long)uval; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_body : retry_after=%d\n", (unsigned)(long)hdr->parsed); break; case HDR_IDENTITY_T: case HDR_DATE_T: case HDR_IDENTITY_INFO_T: case HDR_SUPPORTED_T: case HDR_REQUIRE_T: case HDR_CONTENTTYPE_T: case HDR_FROM_T: case HDR_CALLID_T: case HDR_CONTACT_T: case HDR_ROUTE_T: case HDR_RECORDROUTE_T: case HDR_MAXFORWARDS_T: case HDR_AUTHORIZATION_T: case HDR_EXPIRES_T: case HDR_PROXYAUTH_T: case HDR_PROXYREQUIRE_T: case HDR_UNSUPPORTED_T: case HDR_ALLOW_T: case HDR_EVENT_T: case HDR_ACCEPT_T: case HDR_ACCEPTLANGUAGE_T: case HDR_ORGANIZATION_T: case HDR_PRIORITY_T: case HDR_SUBJECT_T: case HDR_USERAGENT_T: case HDR_SERVER_T: case HDR_CONTENTDISPOSITION_T: case HDR_DIVERSION_T: case HDR_RPID_T: case HDR_SIPIFMATCH_T: case HDR_REFER_TO_T: case HDR_SESSIONEXPIRES_T: case HDR_MIN_SE_T: case HDR_SUBSCRIPTION_STATE_T: case HDR_ACCEPTCONTACT_T: case HDR_ALLOWEVENTS_T: case HDR_CONTENTENCODING_T: case HDR_REFERREDBY_T: case HDR_REJECTCONTACT_T: case HDR_REQUESTDISPOSITION_T: case HDR_WWW_AUTHENTICATE_T: case HDR_PROXY_AUTHENTICATE_T: case HDR_PATH_T: case HDR_PRIVACY_T: case HDR_PAI_T: case HDR_PPI_T: case HDR_REASON_T: case HDR_OTHER_T: /* just skip over it */ hdr->body.s=tmp; /* find end of header */ /* find lf */ do { match=q_memchr(tmp, '\n', end-tmp); if (match) { match++; } else { LOG(L_ERR, "ERROR: get_hdr_field: bad body for <%s>(%d)\n", hdr->name.s, hdr->type); /* abort(); */ tmp=end; goto error; } tmp=match; } while( match<end &&( (*match==' ')||(*match=='\t') ) ); tmp=match; hdr->body.len=match-hdr->body.s; break; default: LOG(L_CRIT, "BUG: get_hdr_field: unknown header type %d\n", hdr->type); goto error; } /* jku: if \r covered by current length, shrink it */ trim_r( hdr->body ); hdr->len=tmp-hdr->name.s; return tmp; error: DBG("get_hdr_field: error exit\n"); STATS_BAD_MSG_HDR(); hdr->type=HDR_ERROR_T; hdr->len=tmp-hdr->name.s; return tmp; }
static int parse_multipart_header(AVIOContext *pb, int* size, const char* expected_boundary, void *log_ctx) { char line[128]; int found_content_type = 0; int ret; *size = -1; // get the CRLF as empty string ret = get_line(pb, line, sizeof(line)); if (ret < 0) return ret; /* some implementation do not provide the required * initial CRLF (see rfc1341 7.2.1) */ while (!line[0]) { ret = get_line(pb, line, sizeof(line)); if (ret < 0) return ret; } if (!av_strstart(line, expected_boundary, NULL)) { if (log_ctx) av_log(log_ctx, AV_LOG_ERROR, "Expected boundary '%s' not found, instead found a line of %zu bytes\n", expected_boundary, strlen(line)); return AVERROR_INVALIDDATA; } while (!pb->eof_reached) { char *tag, *value; ret = get_line(pb, line, sizeof(line)); if (ret < 0) { if (ret == AVERROR_EOF) break; return ret; } if (line[0] == '\0') break; ret = split_tag_value(&tag, &value, line); if (ret < 0) return ret; if (value==NULL || tag==NULL) break; if (!av_strcasecmp(tag, "Content-type")) { if (av_strcasecmp(value, "image/jpeg")) { if (log_ctx) av_log(log_ctx, AV_LOG_ERROR, "Unexpected %s : %s\n", tag, value); return AVERROR_INVALIDDATA; } else found_content_type = 1; } else if (!av_strcasecmp(tag, "Content-Length")) { *size = parse_content_length(value); if ( *size < 0 ) if (log_ctx) av_log(log_ctx, AV_LOG_WARNING, "Invalid Content-Length value : %s\n", value); } } return found_content_type ? 0 : AVERROR_INVALIDDATA; }
/* returns pointer to next header line, and fill hdr_f ; * if at end of header returns pointer to the last crlf (always buf)*/ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr) { char* tmp; char *match; struct via_body *vb; struct cseq_body* cseq_b; struct to_body* to_b; int integer; if ((*buf)=='\n' || (*buf)=='\r'){ /* double crlf or lflf or crcr */ LM_DBG("found end of header\n"); hdr->type=HDR_EOH_T; return buf; } tmp=parse_hname(buf, end, hdr); if (hdr->type==HDR_ERROR_T){ LM_ERR("bad header\n"); goto error_bad_hdr; } /* eliminate leading whitespace */ tmp=eat_lws_end(tmp, end); if (tmp>=end) { LM_ERR("hf empty\n"); goto error_bad_hdr; } /* if header-field well-known, parse it, find its end otherwise ; * after leaving the hdr->type switch, tmp should be set to the * next header field */ switch(hdr->type){ case HDR_VIA_T: /* keep number of vias parsed -- we want to report it in replies for diagnostic purposes */ via_cnt++; vb=pkg_malloc(sizeof(struct via_body)); if (vb==0){ LM_ERR("out of pkg memory\n"); goto error; } memset(vb,0,sizeof(struct via_body)); hdr->body.s=tmp; tmp=parse_via(tmp, end, vb); if (vb->error==PARSE_ERROR){ LM_ERR("bad via\n"); free_via_list(vb); set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing Via"); set_err_reply(400, "bad Via header"); goto error; } hdr->parsed=vb; vb->hdr.s=hdr->name.s; vb->hdr.len=hdr->name.len; hdr->body.len=tmp-hdr->body.s; break; case HDR_CSEQ_T: cseq_b=pkg_malloc(sizeof(struct cseq_body)); if (cseq_b==0){ LM_ERR("out of pkg memory\n"); goto error; } memset(cseq_b, 0, sizeof(struct cseq_body)); hdr->body.s=tmp; tmp=parse_cseq(tmp, end, cseq_b); if (cseq_b->error==PARSE_ERROR){ LM_ERR("bad cseq\n"); pkg_free(cseq_b); set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing CSeq`"); set_err_reply(400, "bad CSeq header"); goto error; } hdr->parsed=cseq_b; hdr->body.len=tmp-hdr->body.s; LM_DBG("cseq <%.*s>: <%.*s> <%.*s>\n", hdr->name.len, ZSW(hdr->name.s), cseq_b->number.len, ZSW(cseq_b->number.s), cseq_b->method.len, cseq_b->method.s); break; case HDR_TO_T: to_b=pkg_malloc(sizeof(struct to_body)); if (to_b==0){ LM_ERR("out of pkg memory\n"); goto error; } memset(to_b, 0, sizeof(struct to_body)); hdr->body.s=tmp; tmp=parse_to(tmp, end,to_b); if (to_b->error==PARSE_ERROR){ LM_ERR("bad to header\n"); pkg_free(to_b); set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing To header"); set_err_reply(400, "bad header"); goto error; } hdr->parsed=to_b; hdr->body.len=tmp-hdr->body.s; LM_DBG("<%.*s> [%d]; uri=[%.*s] \n", hdr->name.len, ZSW(hdr->name.s), hdr->body.len, to_b->uri.len,ZSW(to_b->uri.s)); LM_DBG("to body [%.*s]\n",to_b->body.len, ZSW(to_b->body.s)); break; case HDR_CONTENTLENGTH_T: hdr->body.s=tmp; tmp=parse_content_length(tmp,end, &integer); if (tmp==0){ LM_ERR("bad content_length header\n"); set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing Content-Length"); set_err_reply(400, "bad Content-Length header"); goto error; } hdr->parsed=(void*)(long)integer; hdr->body.len=tmp-hdr->body.s; LM_DBG("content_length=%d\n", (int)(long)hdr->parsed); break; case HDR_SUPPORTED_T: case HDR_CONTENTTYPE_T: case HDR_FROM_T: case HDR_CALLID_T: case HDR_CONTACT_T: case HDR_ROUTE_T: case HDR_RECORDROUTE_T: case HDR_PATH_T: case HDR_MAXFORWARDS_T: case HDR_AUTHORIZATION_T: case HDR_EXPIRES_T: case HDR_PROXYAUTH_T: case HDR_PROXYREQUIRE_T: case HDR_UNSUPPORTED_T: case HDR_ALLOW_T: case HDR_EVENT_T: case HDR_ACCEPT_T: case HDR_ACCEPTLANGUAGE_T: case HDR_ORGANIZATION_T: case HDR_PRIORITY_T: case HDR_SUBJECT_T: case HDR_USERAGENT_T: case HDR_CONTENTDISPOSITION_T: case HDR_ACCEPTDISPOSITION_T: case HDR_DIVERSION_T: case HDR_RPID_T: case HDR_REFER_TO_T: case HDR_SESSION_EXPIRES_T: case HDR_MIN_SE_T: case HDR_MIN_EXPIRES_T: case HDR_PPI_T: case HDR_PAI_T: case HDR_PRIVACY_T: case HDR_RETRY_AFTER_T: case HDR_CALL_INFO_T: case HDR_WWW_AUTHENTICATE_T: case HDR_PROXY_AUTHENTICATE_T: case HDR_OTHER_T: /* just skip over it */ hdr->body.s=tmp; /* find end of header */ /* find lf */ do{ match=q_memchr(tmp, '\n', end-tmp); if (match){ match++; }else { LM_ERR("bad body for <%s>(%d)\n", hdr->name.s, hdr->type); tmp=end; goto error_bad_hdr; } tmp=match; }while( match<end &&( (*match==' ')||(*match=='\t') ) ); tmp=match; hdr->body.len=match-hdr->body.s; break; default: LM_CRIT("unknown header type %d\n", hdr->type); goto error; } /* jku: if \r covered by current length, shrink it */ trim_r( hdr->body ); hdr->len=tmp-hdr->name.s; return tmp; error_bad_hdr: set_err_info(OSER_EC_PARSER, OSER_EL_MEDIUM, "error parsing headers"); set_err_reply(400, "bad headers"); error: LM_DBG("error exit\n"); update_stat( bad_msg_hdr, 1); hdr->type=HDR_ERROR_T; hdr->len=tmp-hdr->name.s; return tmp; }
/* * This function encodes an arbitrary header into a chunk of bytes, * ready to be sent to the Application Server. * * The header codes start with this encoded-bytes: * 2: SIP-MSG-START based pointer to the header (including header name) * 2: length of the header * 1: length of the header name */ int encode_header(struct sip_msg *sipmsg,struct hdr_field *hdr,unsigned char *payload,int paylen) { int len=0; unsigned int integer,*methods=0; char *hdrstart,*tmp; unsigned short int ptr; struct to_body *tobody=0; struct via_body *viabody=0; struct cseq_body *cseqbody=0; char *msg,*myerror; int mlen; msg=sipmsg->buf; mlen=sipmsg->len; hdrstart = hdr->name.s; if(hdrstart-msg<0){ LM_ERR("header(%.*s) does not belong to sip_msg(hdrstart<msg)\n", hdr->name.len,hdr->name.s); return -1; } ptr=htons((short int)(hdrstart-msg)); if((hdrstart-msg)>mlen){ LM_ERR("out of the sip_msg bounds (%d>%d)\n",ntohs(ptr),mlen); return -1; } if(hdr->len>(1<<16)){ LM_ERR("length of header too long\n"); return -1; } memcpy(payload,&ptr,2); ptr=htons((short int)(hdr->len)); memcpy(payload+HEADER_LEN_IDX,&ptr,2); payload[HEADER_NAME_LEN_IDX]=(unsigned char)hdr->name.len; switch(hdr->type){ case HDR_FROM_T: case HDR_TO_T: case HDR_REFER_TO_T: case HDR_RPID_T: if(!hdr->parsed){ if((tobody=pkg_malloc(sizeof(struct to_body)))==0){ myerror="Out of memory !!\n"; goto error; } parse_to(hdr->body.s,hdr->body.s+hdr->body.len+1,tobody); if (tobody->error == PARSE_ERROR) { myerror="bad (REFER,TO,FROM,RPID) header\n"; pkg_free(tobody); return 5; goto error; } hdr->parsed=(struct to_body*)tobody; }else tobody=(struct to_body*)hdr->parsed; if((len=encode_to_body(hdr->name.s,hdr->len,tobody,payload+5))<0){ myerror="parsing from or to header\n"; goto error; }else{ return 5+len; } break; case HDR_CONTACT_T: if(!hdr->parsed) if(parse_contact(hdr)<0){ myerror="parsing contact\n"; goto error; } if((len=encode_contact_body(hdr->name.s,hdr->len,(contact_body_t*)hdr->parsed,payload+5))<0){ myerror="encoding contact header\n"; goto error; }else{ return 5+len; } break; case HDR_ROUTE_T: case HDR_RECORDROUTE_T: if(!hdr->parsed) if(parse_rr(hdr)<0){ myerror="encoding route or recordroute\n"; goto error; } if((len=encode_route_body(hdr->name.s,hdr->len,(rr_t*)hdr->parsed,payload+5))<0){ myerror="encoding route or recordroute header\n"; goto error; }else{ return 5+len; } break; case HDR_CONTENTLENGTH_T: if(!hdr->parsed){ tmp=parse_content_length(hdr->body.s,hdr->body.s+hdr->body.len+1,(int*)&integer); if (tmp==0){ myerror="bad content_length header\n"; goto error; } hdr->parsed=(void*)(long)integer; } if((len=encode_contentlength(hdr->name.s,hdr->len,(long int)hdr->parsed,(char*)(payload+5)))<0){ myerror="encoding content-length header\n"; goto error; }else{ return 5+len; } break; case HDR_VIA_T: if(!hdr->parsed){ if((viabody=pkg_malloc(sizeof(struct via_body)))==0){ myerror="out of memory\n"; goto error; } memset(viabody,0,sizeof(struct via_body)); if(parse_via(hdr->body.s,hdr->body.s+hdr->body.len+1,viabody)==0){ myerror="encoding via \n"; goto error; } hdr->parsed=viabody; } if((len=encode_via_body(hdr->name.s,hdr->len,(struct via_body*)hdr->parsed,payload+5))<0){ myerror="encoding via header\n"; goto error; }else{ return 5+len; } break; case HDR_ACCEPT_T: if(!hdr->parsed){ if(parse_accept_hdr(sipmsg)<0){ return 5; } } if((len=encode_accept(hdr->name.s,hdr->len,(unsigned int*)hdr->parsed,(char*)(payload+5)))<0){ myerror="encoding via header\n"; goto error; }else{ return 5+len; } break; case HDR_CONTENTTYPE_T: if(!hdr->parsed){ if(parse_content_type_hdr(sipmsg)<0){ myerror="encoding content-type header\n"; goto error; } } if((len=encode_content_type(hdr->name.s,hdr->len,(unsigned int)get_content_type(sipmsg),(char*)(payload+5)))<0){ myerror="encoding via header\n"; goto error; }else{ return 5+len; } break; case HDR_CSEQ_T: if(!hdr->parsed){ if((cseqbody=pkg_malloc(sizeof(struct cseq_body)))==0){ myerror="out of memory\n"; goto error; } memset(cseqbody,0,sizeof(struct cseq_body)); if(parse_cseq(hdr->name.s,hdr->body.s+hdr->body.len+1,cseqbody)==0){ myerror="encoding cseq header\n"; goto error; } hdr->parsed=cseqbody; } if((len=encode_cseq(hdr->name.s,hdr->len,(struct cseq_body*)hdr->parsed,payload+5))<0){ myerror="encoding via header\n"; goto error; }else{ return 5+len; } break; case HDR_EXPIRES_T: if(!hdr->parsed){ if(parse_expires(hdr)<0){ myerror="encoding expires header\n"; goto error; } } if((len=encode_expires(hdr->name.s,hdr->len,(exp_body_t *)hdr->parsed,payload+5))<0){ myerror="encoding expires header\n"; goto error; }else{ return 5+len; } break; case HDR_ALLOW_T: if(!hdr->parsed){ if((methods=pkg_malloc(sizeof(unsigned int)))==0){ myerror="out of memory\n"; goto error; } *methods=0; if(parse_methods(&hdr->body,methods)!=0){ myerror="encoding allow header\n"; pkg_free(methods); return 5; /*goto error;*/ } hdr->parsed=methods; } if((len=encode_allow(hdr->name.s,hdr->len,(unsigned int*)hdr->parsed,(char*)(payload+5)))<0){ myerror="encoding allow header\n"; goto error; }else{ return 5+len; } break; case HDR_AUTHORIZATION_T: case HDR_PROXYAUTH_T: if(!hdr->parsed){ if(parse_credentials(hdr)<0){ myerror="encoding a digest header\n"; goto error; } } if((len=encode_digest(hdr->name.s,hdr->len,(dig_cred_t*)(&(((auth_body_t*)hdr->parsed)->digest)),payload+5))<0){ myerror="encoding allow header\n"; goto error; }else{ return 5+len; } break; default: return 5; } return 1; error: if(tobody) pkg_free(tobody); if(cseqbody) pkg_free(cseqbody); if(viabody) free_via_list(viabody); if(methods) pkg_free(methods); LM_ERR("%s",myerror); return -1; }
static gboolean relay_headers (CockpitHttpStream *self, CockpitChannel *channel, GByteArray *buffer) { GHashTable *headers = NULL; gchar *version = NULL; gchar *reason = NULL; JsonObject *object; const gchar *data; JsonObject *heads; GHashTableIter iter; GBytes *message; gpointer key; gpointer value; guint status; gsize length; gssize offset; gssize offset2; data = (const gchar *)buffer->data; length = buffer->len; offset = web_socket_util_parse_status_line (data, length, &version, &status, &reason); if (offset == 0) return FALSE; /* want more data */ if (offset < 0) { cockpit_channel_fail (channel, "protocol-error", "%s: received response with bad HTTP status line", self->name); goto out; } offset2 = web_socket_util_parse_headers (data + offset, length - offset, &headers); if (offset2 == 0) return FALSE; /* want more data */ if (offset2 < 0) { cockpit_channel_fail (channel, "protocol-error", "%s: received response with bad HTTP headers", self->name); goto out; } g_debug ("%s: response: %u %s", self->name, status, reason); g_hash_table_iter_init (&iter, headers); while (g_hash_table_iter_next (&iter, &key, &value)) g_debug ("%s: header: %s %s", self->name, (gchar *)key, (gchar *)value); if (!parse_transfer_encoding (self, channel, headers) || !parse_content_length (self, channel, status, headers) || !parse_keep_alive (self, channel, version, headers)) goto out; cockpit_pipe_skip (buffer, offset + offset2); if (!self->binary) { g_hash_table_remove (headers, "Content-Length"); g_hash_table_remove (headers, "Range"); } g_hash_table_remove (headers, "Connection"); g_hash_table_remove (headers, "Transfer-Encoding"); /* Now serialize all the rest of this into JSON */ object = json_object_new (); json_object_set_int_member (object, "status", status); json_object_set_string_member (object, "reason", reason); heads = json_object_new(); g_hash_table_iter_init (&iter, headers); while (g_hash_table_iter_next (&iter, &key, &value)) json_object_set_string_member (heads, key, value); json_object_set_object_member (object, "headers", heads); if (self->headers_inline) { message = cockpit_json_write_bytes (object); cockpit_channel_send (channel, message, TRUE); g_bytes_unref (message); } else { cockpit_channel_control (channel, "response", object); } json_object_unref (object); out: if (headers) g_hash_table_unref (headers); g_free (version); g_free (reason); return TRUE; }
/* returns pointer to next header line, and fill hdr_f ; * if at end of header returns pointer to the last crlf (always buf)*/ char* get_hdr_field(char* buf, char* end, struct hdr_field* hdr) { char* tmp; char *match; struct via_body *vb; struct cseq_body* cseq_b; struct to_body* to_b; int integer; if ((*buf)=='\n' || (*buf)=='\r'){ /* double crlf or lflf or crcr */ DBG("found end of header\n"); hdr->type=HDR_EOH; return buf; } tmp=parse_hname(buf, end, hdr); if (hdr->type==HDR_ERROR){ LOG(L_ERR, "ERROR: get_hdr_field: bad header\n"); goto error; } /* eliminate leading whitespace */ tmp=eat_lws_end(tmp, end); if (tmp>=end) { LOG(L_ERR, "ERROR: get_hdr_field: HF empty\n"); goto error; } /* if header-field well-known, parse it, find its end otherwise ; * after leaving the hdr->type switch, tmp should be set to the * next header field */ switch(hdr->type){ case HDR_VIA: /* keep number of vias parsed -- we want to report it in replies for diagnostic purposes */ via_cnt++; vb=pkg_malloc(sizeof(struct via_body)); if (vb==0){ LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(vb,0,sizeof(struct via_body)); hdr->body.s=tmp; tmp=parse_via(tmp, end, vb); if (vb->error==PARSE_ERROR){ LOG(L_ERR, "ERROR: get_hdr_field: bad via\n"); free_via_list(vb); goto error; } hdr->parsed=vb; vb->hdr.s=hdr->name.s; vb->hdr.len=hdr->name.len; hdr->body.len=tmp-hdr->body.s; break; case HDR_CSEQ: cseq_b=pkg_malloc(sizeof(struct cseq_body)); if (cseq_b==0){ LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(cseq_b, 0, sizeof(struct cseq_body)); hdr->body.s=tmp; tmp=parse_cseq(tmp, end, cseq_b); if (cseq_b->error==PARSE_ERROR){ LOG(L_ERR, "ERROR: get_hdr_field: bad cseq\n"); pkg_free(cseq_b); goto error; } hdr->parsed=cseq_b; hdr->body.len=tmp-hdr->body.s; DBG("get_hdr_field: cseq <%.*s>: <%.*s> <%.*s>\n", hdr->name.len, ZSW(hdr->name.s), cseq_b->number.len, ZSW(cseq_b->number.s), cseq_b->method.len, cseq_b->method.s); break; case HDR_TO: to_b=pkg_malloc(sizeof(struct to_body)); if (to_b==0){ LOG(L_ERR, "get_hdr_field: out of memory\n"); goto error; } memset(to_b, 0, sizeof(struct to_body)); hdr->body.s=tmp; tmp=parse_to(tmp, end,to_b); if (to_b->error==PARSE_ERROR){ LOG(L_ERR, "ERROR: get_hdr_field: bad to header\n"); pkg_free(to_b); goto error; } hdr->parsed=to_b; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_field: <%.*s> [%d]; uri=[%.*s] \n", hdr->name.len, ZSW(hdr->name.s), hdr->body.len, to_b->uri.len,ZSW(to_b->uri.s)); DBG("DEBUG: to body [%.*s]\n",to_b->body.len, ZSW(to_b->body.s)); break; case HDR_CONTENTLENGTH: hdr->body.s=tmp; tmp=parse_content_length(tmp,end, &integer); if (tmp==0){ LOG(L_ERR, "ERROR:get_hdr_field: bad content_length header\n"); goto error; } hdr->parsed=(void*)(long)integer; hdr->body.len=tmp-hdr->body.s; DBG("DEBUG: get_hdr_body : content_length=%d\n", (int)(long)hdr->parsed); break; case HDR_SUPPORTED: case HDR_CONTENTTYPE: case HDR_FROM: case HDR_CALLID: case HDR_CONTACT: case HDR_ROUTE: case HDR_RECORDROUTE: case HDR_MAXFORWARDS: case HDR_AUTHORIZATION: case HDR_EXPIRES: case HDR_PROXYAUTH: case HDR_PROXYREQUIRE: case HDR_UNSUPPORTED: case HDR_ALLOW: case HDR_EVENT: case HDR_ACCEPT: case HDR_ACCEPTLANGUAGE: case HDR_ORGANIZATION: case HDR_PRIORITY: case HDR_SUBJECT: case HDR_USERAGENT: case HDR_CONTENTDISPOSITION: case HDR_ACCEPTDISPOSITION: case HDR_DIVERSION: case HDR_RPID: case HDR_OTHER: /* just skip over it */ hdr->body.s=tmp; /* find end of header */ /* find lf */ do{ match=q_memchr(tmp, '\n', end-tmp); if (match){ match++; }else { LOG(L_ERR, "ERROR: get_hdr_field: bad body for <%s>(%d)\n", hdr->name.s, hdr->type); /* abort(); */ tmp=end; goto error; } tmp=match; }while( match<end &&( (*match==' ')||(*match=='\t') ) ); tmp=match; hdr->body.len=match-hdr->body.s; break; default: LOG(L_CRIT, "BUG: get_hdr_field: unknown header type %d\n", hdr->type); goto error; } /* jku: if \r covered by current length, shrink it */ trim_r( hdr->body ); hdr->len=tmp-hdr->name.s; return tmp; error: DBG("get_hdr_field: error exit\n"); hdr->type=HDR_ERROR; hdr->len=tmp-hdr->name.s; return tmp; }