/* TODO: digest-challenge tken has no order preference?? verify many situations (extra SP....) */ int osip_authorization_parse (osip_authorization_t * auth, const char *hvalue) { const char *space; const char *next = NULL; int i; space = strchr (hvalue, ' '); /* SEARCH FOR SPACE */ if (space == NULL) return OSIP_SYNTAXERROR; if (space - hvalue < 1) return OSIP_SYNTAXERROR; auth->auth_type = (char *) osip_malloc (space - hvalue + 1); if (auth->auth_type==NULL) return OSIP_NOMEM; osip_strncpy (auth->auth_type, hvalue, space - hvalue); for (;;) { int parse_ok = 0; i = __osip_quoted_string_set ("username", space, &(auth->username), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("realm", space, &(auth->realm), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("nonce", space, &(auth->nonce), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("uri", space, &(auth->uri), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("response", space, &(auth->response), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("digest", space, &(auth->digest), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_token_set ("algorithm", space, &(auth->algorithm), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("cnonce", space, &(auth->cnonce), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("opaque", space, &(auth->opaque), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_token_set ("qop", space, &(auth->message_qop), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_token_set ("nc", space, &(auth->nonce_count), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } /* nothing was recognized: here, we should handle a list of unknown tokens where: token1 = ( token2 | quoted_text ) */ /* TODO */ if (0 == parse_ok) { const char *quote1, *quote2, *tmp; /* CAUTION */ /* parameter not understood!!! I'm too lazy to handle IT */ /* let's simply bypass it */ if (strlen (space) < 1) return OSIP_SUCCESS; tmp = strchr (space + 1, ','); if (tmp == NULL) /* it was the last header */ return OSIP_SUCCESS; quote1 = __osip_quote_find (space); if ((quote1 != NULL) && (quote1 < tmp)) /* this may be a quoted string! */ { quote2 = __osip_quote_find (quote1 + 1); if (quote2 == NULL) return OSIP_SYNTAXERROR; /* bad header format... */ if (tmp < quote2) /* the comma is inside the quotes! */ space = strchr (quote2, ','); else space = tmp; if (space == NULL) /* it was the last header */ return OSIP_SUCCESS; } else space = tmp; /* continue parsing... */ } } return OSIP_SUCCESS; /* ok */ }
int __osip_quoted_string_set (const char *name, const char *str, char **result, const char **next) { *next = str; if (*result != NULL) return OSIP_SUCCESS; /* already parsed */ *next = NULL; while ((' ' == *str) || ('\t' == *str) || (',' == *str)) if (*str) str++; else return OSIP_SYNTAXERROR; /* bad header format */ if (osip_strncasecmp (name, str, strlen (name)) == 0) { const char *quote1; const char *quote2; const char *tmp; const char *hack = strchr (str, '='); if (hack == NULL) return OSIP_SYNTAXERROR; while (' ' == *(hack - 1)) /* get rid of extra spaces */ hack--; if ((size_t) (hack - str) != strlen (name)) { *next = str; return OSIP_SUCCESS; } quote1 = __osip_quote_find (str); if (quote1 == NULL) return OSIP_SYNTAXERROR; /* bad header format... */ quote2 = __osip_quote_find (quote1 + 1); if (quote2 == NULL) return OSIP_SYNTAXERROR; /* bad header format... */ if (quote2 - quote1 == 1) { /* this is a special case! The quote contains nothing! */ /* example: Digest opaque="",cnonce="" */ /* in this case, we just forget the parameter... this */ /* this should prevent from user manipulating empty */ /* strings */ tmp = quote2 + 1; /* next element start here */ for (; *tmp == ' ' || *tmp == '\t'; tmp++) { } for (; *tmp == '\n' || *tmp == '\r'; tmp++) { } /* skip LWS */ *next = NULL; if (*tmp == '\0') /* end of header detected */ return OSIP_SUCCESS; if (*tmp != '\t' && *tmp != ' ') /* LWS here ? */ *next = tmp; else { /* it is: skip it... */ for (; *tmp == ' ' || *tmp == '\t'; tmp++) { } if (*tmp == '\0') /* end of header detected */ return OSIP_SUCCESS; *next = tmp; } return OSIP_SUCCESS; } *result = (char *) osip_malloc (quote2 - quote1 + 3); if (*result == NULL) return OSIP_NOMEM; osip_strncpy (*result, quote1, quote2 - quote1 + 1); tmp = quote2 + 1; /* next element start here */ for (; *tmp == ' ' || *tmp == '\t'; tmp++) { } for (; *tmp == '\n' || *tmp == '\r'; tmp++) { } /* skip LWS */ *next = NULL; if (*tmp == '\0') /* end of header detected */ return OSIP_SUCCESS; if (*tmp != '\t' && *tmp != ' ') /* LWS here ? */ *next = tmp; else { /* it is: skip it... */ for (; *tmp == ' ' || *tmp == '\t'; tmp++) { } if (*tmp == '\0') /* end of header detected */ return OSIP_SUCCESS; *next = tmp; } } else *next = str; /* wrong header asked! */ return OSIP_SUCCESS; }
/* TODO: digest-challenge tken has no order preference?? verify many situations (extra SP....) */ int osip_www_authenticate_parse (osip_www_authenticate_t * wwwa, const char *hvalue) { const char *space; const char *next = NULL; int i; space = strchr (hvalue, ' '); /* SEARCH FOR SPACE */ if (space == NULL) return OSIP_SYNTAXERROR; if (space - hvalue + 1 < 2) return OSIP_SYNTAXERROR; wwwa->auth_type = (char *) osip_malloc (space - hvalue + 1); if (wwwa->auth_type == NULL) return OSIP_NOMEM; osip_strncpy (wwwa->auth_type, hvalue, space - hvalue); for (;;) { int parse_ok = 0; i = __osip_quoted_string_set ("realm", space, &(wwwa->realm), &next); if (i != 0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("domain", space, &(wwwa->domain), &next); if (i != 0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("nonce", space, &(wwwa->nonce), &next); if (i != 0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("opaque", space, &(wwwa->opaque), &next); if (i != 0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_token_set ("stale", space, &(wwwa->stale), &next); if (i != 0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_token_set ("algorithm", space, &(wwwa->algorithm), &next); if (i != 0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("qop", space, &(wwwa->qop_options), &next); if (i != 0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_token_set ("version", space, &(wwwa->version), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("targetname", space, &(wwwa->targetname), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } i = __osip_quoted_string_set ("gssapi-data", space, &(wwwa->gssapi_data), &next); if (i!=0) return i; if (next == NULL) return OSIP_SUCCESS; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } if (0 == parse_ok) { const char *quote1, *quote2, *tmp; /* CAUTION */ /* parameter not understood!!! I'm too lazy to handle IT */ /* let's simply bypass it */ if (strlen (space) < 1) return OSIP_SUCCESS; tmp = strchr (space + 1, ','); if (tmp == NULL) /* it was the last header */ return OSIP_SUCCESS; quote1 = __osip_quote_find (space); if ((quote1 != NULL) && (quote1 < tmp)) { /* this may be a quoted string! */ quote2 = __osip_quote_find (quote1 + 1); if (quote2 == NULL) return OSIP_SYNTAXERROR; /* bad header format... */ if (tmp < quote2) /* the comma is inside the quotes! */ space = strchr (quote2, ','); else space = tmp; if (space == NULL) /* it was the last header */ return OSIP_SUCCESS; } else space = tmp; /* continue parsing... */ } } return OSIP_SUCCESS; /* ok */ }
/* TODO: digest-challenge tken has no order preference?? verify many situations (extra SP....) */ int osip_authentication_info_parse (osip_authentication_info_t * ainfo, const char *hvalue) { const char *space; const char *next = NULL; space = hvalue; for (;;) { int parse_ok = 0; if (__osip_quoted_string_set ("nextnonce", space, &(ainfo->nextnonce), &next)) return -1; if (next == NULL) return 0; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } if (__osip_quoted_string_set ("cnonce", space, &(ainfo->cnonce), &next)) return -1; if (next == NULL) return 0; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } if (__osip_quoted_string_set ("rspauth", space, &(ainfo->rspauth), &next)) return -1; if (next == NULL) return 0; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } if (__osip_token_set ("nc", space, &(ainfo->nonce_count), &next)) return -1; if (next == NULL) return 0; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } if (__osip_token_set ("qop", space, &(ainfo->qop_options), &next)) return -1; if (next == NULL) return 0; /* end of header detected! */ else if (next != space) { space = next; parse_ok++; } if (0 == parse_ok) { char *quote1, *quote2, *tmp; /* CAUTION */ /* parameter not understood!!! I'm too lazy to handle IT */ /* let's simply bypass it */ if (strlen (space) < 1) return 0; tmp = strchr (space + 1, ','); if (tmp == NULL) /* it was the last header */ return 0; quote1 = __osip_quote_find (space); if ((quote1 != NULL) && (quote1 < tmp)) /* this may be a quoted string! */ { quote2 = __osip_quote_find (quote1 + 1); if (quote2 == NULL) return -1; /* bad header format... */ if (tmp < quote2) /* the comma is inside the quotes! */ space = strchr (quote2, ','); else space = tmp; if (space == NULL) /* it was the last header */ return 0; } else space = tmp; /* continue parsing... */ } } return 0; /* ok */ }
int osip_message_set_multiple_header(osip_message_t * sip, char *hname, char *hvalue) { int i; char *ptr; /* current location of the search */ char *comma; /* This is the separator we are elooking for */ char *beg; /* beg of a header */ char *end; /* end of a header */ char *quote1; /* first quote of a pair of quotes */ char *quote2; /* second quuote of a pair of quotes */ size_t hname_len; /* Find header based upon lowercase comparison */ osip_tolower(hname); if (hvalue == NULL) { i = osip_message_set__header(sip, hname, hvalue); if (i != 0) return i; return OSIP_SUCCESS; } ptr = hvalue; comma = strchr(ptr, ','); hname_len = strlen(hname); if (comma == NULL || (hname_len == 4 && strncmp(hname, "date", 4) == 0) || (hname_len == 2 && strncmp(hname, "to", 2) == 0) || (hname_len == 4 && strncmp(hname, "from", 4) == 0) || (hname_len == 7 && strncmp(hname, "call-id", 7) == 0) || (hname_len == 4 && strncmp(hname, "cseq", 4) == 0) || (hname_len == 7 && strncmp(hname, "subject", 7) == 0) || (hname_len == 7 && strncmp(hname, "expires", 7) == 0) || (hname_len == 6 && strncmp(hname, "server", 6) == 0) || (hname_len == 10 && strncmp(hname, "user-agent", 10) == 0) || (hname_len == 16 && strncmp(hname, "www-authenticate", 16) == 0) || (hname_len == 19 && strncmp(hname, "authentication-info", 19) == 0) || (hname_len == 18 && strncmp(hname, "proxy-authenticate", 18) == 0) || (hname_len == 19 && strncmp(hname, "proxy-authorization", 19) == 0) || (hname_len == 25 && strncmp(hname, "proxy-authentication-info", 25) == 0) || (hname_len == 12 && strncmp(hname, "organization", 12) == 0) || (hname_len == 13 && strncmp(hname, "authorization", 13) == 0)) /* there is no multiple header! likely */ /* to happen most of the time... */ /* or hname is a TEXT-UTF8-TRIM and may */ /* contain a comma. this is not a separator */ /* THIS DOES NOT WORK FOR UNKNOWN HEADER!!!! */ { i = osip_message_set__header(sip, hname, hvalue); if (i != 0) return i; return OSIP_SUCCESS; } beg = hvalue; end = NULL; quote2 = NULL; while (comma != NULL) { quote1 = __osip_quote_find(ptr); if (quote1 != NULL) { quote2 = __osip_quote_find(quote1 + 1); if (quote2 == NULL) return OSIP_SYNTAXERROR; /* quotes comes by pair */ ptr = quote2 + 1; } if ((quote1 == NULL) || (quote1 > comma)) { /* We must search for the next comma which is not within quotes! */ end = comma; if (quote1 != NULL && quote1 > comma) { /* comma may be within the quotes */ /* ,<sip:[email protected]>;methods=\"INVITE,BYE,OPTIONS,ACK,CANCEL\",<sip:[email protected]> */ /* we want the next comma after the quotes */ char *tmp_comma; char *tmp_quote1; char *tmp_quote2; tmp_quote1 = quote1; tmp_quote2 = quote2; tmp_comma = strchr(comma + 1, ','); while (1) { if (tmp_comma < tmp_quote1) break; /* ok (before to quotes) */ if (tmp_comma < tmp_quote2) { tmp_comma = strchr(tmp_quote2 + 1, ','); } tmp_quote1 = __osip_quote_find(tmp_quote2 + 1); if (tmp_quote1 == NULL) break; tmp_quote2 = __osip_quote_find(tmp_quote1 + 1); if (tmp_quote2 == NULL) break; /* probably a malformed message? */ } comma = tmp_comma; /* this one is not enclosed within quotes */ } else comma = strchr(comma + 1, ','); if (comma != NULL) ptr = comma + 1; } else if ((quote1 < comma) && (quote2 < comma)) { /* quotes are located before the comma, */ /* continue the search for next quotes */ ptr = quote2 + 1; } else if ((quote1 < comma) && (comma < quote2)) { /* if comma is inside the quotes... */ /* continue with the next comma. */ ptr = quote2 + 1; comma = strchr(ptr, ','); if (comma == NULL) /* this header last at the end of the line! */ { /* this one does not need an allocation... */ #if 0 if (strlen(beg) < 2) return OSIP_SUCCESS; /* empty header */ #else if (beg[0] == '\0' || beg[1] == '\0') return OSIP_SUCCESS; /* empty header */ #endif osip_clrspace(beg); i = osip_message_set__header(sip, hname, beg); if (i != 0) return i; return OSIP_SUCCESS; } } if (end != NULL) { char *avalue; if (end - beg + 1 < 2) return OSIP_SYNTAXERROR; avalue = (char *) osip_malloc(end - beg + 1); if (avalue == NULL) return OSIP_NOMEM; osip_clrncpy(avalue, beg, end - beg); /* really store the header in the sip structure */ i = osip_message_set__header(sip, hname, avalue); osip_free(avalue); if (i != 0) return i; beg = end + 1; end = NULL; if (comma == NULL) /* this header last at the end of the line! */ { /* this one does not need an allocation... */ #if 0 if (strlen(beg) < 2) return OSIP_SUCCESS; /* empty header */ #else if (beg[0] == '\0' || beg[1] == '\0') return OSIP_SUCCESS; /* empty header */ #endif osip_clrspace(beg); i = osip_message_set__header(sip, hname, beg); if (i != 0) return i; return OSIP_SUCCESS; } } } return OSIP_SYNTAXERROR; /* if comma is NULL, we should have already return 0 */ }
/* returns -1 on error. */ int osip_from_parse (osip_from_t * from, const char *hvalue) { const char *displayname; const char *url; const char *url_end; const char *gen_params; /* How to parse: we'll place the pointers: displayname => beginning of displayname url => beginning of url url_end => end of url gen_params => beginning of params examples: jack <sip:[email protected]>;tag=34erZ ^ ^ ^ ^ sip:[email protected];tag=34erZ ^ ^^ */ displayname = strchr (hvalue, '"'); url = strchr (hvalue, '<'); if (url != NULL) { url_end = strchr (url, '>'); if (url_end == NULL) return -1; } /* SIPit day2: this case was not supported first '"' is placed after '<' and after '>' <sip:[email protected];method=INVITE>;description="OPEN";expires=28800 if the fisrt quote is after '<' then this is not a quote for a displayname. */ if (displayname != NULL) { if (displayname > url) displayname = NULL; } if ((displayname == NULL) && (url != NULL)) { /* displayname IS A '*token' (not a quoted-string) */ if (hvalue != url) /* displayname exists */ { if (url - hvalue + 1 < 2) return -1; from->displayname = (char *) osip_malloc (url - hvalue + 1); if (from->displayname == NULL) return -1; osip_clrncpy (from->displayname, hvalue, url - hvalue); } url++; /* place pointer on the beginning of url */ } else { if ((displayname != NULL) && (url != NULL)) { /* displayname IS A quoted-string (not a '*token') */ const char *first; const char *second=NULL; /* search for quotes */ first = __osip_quote_find (hvalue); if (first == NULL) return -1; /* missing quote */ second = __osip_quote_find (first + 1); if (second == NULL) return -1; /* missing quote */ if ((first > url)) return -1; if (second - first + 2 >= 2) { from->displayname = (char *) osip_malloc (second - first + 2); if (from->displayname == NULL) return -1; osip_strncpy (from->displayname, first, second - first + 1); /* osip_clrspace(from->displayname); *//*should we do that? */ /* special case: "<sip:[email protected]>" <sip:[email protected]> */ } /* else displayname is empty? */ url = strchr (second + 1, '<'); if (url == NULL) return -1; /* '<' MUST exist */ url++; } else url = hvalue; /* field does not contains '<' and '>' */ } /* DISPLAY-NAME SET */ /* START of URL KNOWN */ url_end = strchr (url, '>'); if (url_end == NULL) /* sip:[email protected];tag=023 */ { /* We are sure ';' is the delimiter for from-parameters */ char *host = strchr (url, '@'); if (host != NULL) gen_params = strchr (host, ';'); else gen_params = strchr (url, ';'); if (gen_params != NULL) url_end = gen_params - 1; else url_end = url + strlen (url); } else /* jack <sip:[email protected];user=phone>;tag=azer */ { gen_params = strchr (url_end, ';'); url_end--; /* place pointer on the beginning of url */ } if (gen_params != NULL) /* now we are sure a param exist */ if (__osip_generic_param_parseall (&from->gen_params, gen_params) == -1) { return -1; } /* set the url */ { char *tmp; int i; if (url_end - url + 2 < 7) return -1; i = osip_uri_init (&(from->url)); if (i != 0) return -1; tmp = (char *) osip_malloc (url_end - url + 2); if (tmp == NULL) return -1; osip_strncpy (tmp, url, url_end - url + 1); i = osip_uri_parse (from->url, tmp); osip_free (tmp); if (i != 0) return -1; } return 0; }