Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #4
0
/**
 *	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;
}
Beispiel #5
0
/* 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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
/* 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;
}
Beispiel #8
0
/*
 * 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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
/* 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;
}