diff --git a/libs/sofia-sip/.update b/libs/sofia-sip/.update index 7aefc860d6..9c8dbe8654 100644 --- a/libs/sofia-sip/.update +++ b/libs/sofia-sip/.update @@ -1 +1 @@ -Wed Jul 17 14:35:37 EDT 2019 +Thu Aug 8 15:09:57 CDT 2019 diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c b/libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c index d2e1c0875e..85f4aa2328 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sip_basic.c @@ -2797,3 +2797,122 @@ char const *sip_via_port(sip_via_t const *v, int *using_rport) else return SIP_DEFAULT_SERV; /* 5060 */ } + +/**@SIP_HEADER sip_identity Identity Header + * + * The Identity header field specifies the "logical" recipient of the + * request. It is defined in @RFC8224 with semantics shown below, + * though for now it's parsed to a single 'value' field. + * + * @code + * Identity = "Identity" HCOLON signed-identity-digest SEMI + * ident-info *( SEMI ident-info-params ) + * signed-identity-digest = 1*(base64-char / ".") + * ident-info = "info" EQUAL ident-info-uri + * ident-info-uri = LAQUOT absoluteURI RAQUOT + * ident-info-params = ident-info-alg / ident-type / + * ident-info-extension + * ident-info-alg = "alg" EQUAL token + * ident-type = "ppt" EQUAL token + * ident-info-extension = generic-param + * + * base64-char = ALPHA / DIGIT / "/" / "+" + * @endcode + * + * The parsed Identity header is stored in #sip_identity_t structure. + */ + +/**@ingroup sip_identity + * @typedef typedef struct sip_identity_s sip_identity_t; + * + * The structure #sip_identity_t contains representation of @Identity header. + * + * The #sip_identity_t is defined as follows: + * @code + * typedef struct { + * sip_common_t id_common[1]; // Common fragment info + * sip_error_t *id_next; // Link to next (dummy) + * char const *id_value; // Identity + * char const *id_info; // Info param containing URL of the cert, with no '<','>' + * } sip_identity_t; + * @endcode + * + */ + +static msg_xtra_f sip_identity_dup_xtra; +static msg_dup_f sip_identity_dup_one; +static msg_update_f sip_identity_update; + +msg_hclass_t sip_identity_class[] = +SIP_HEADER_CLASS(identity, "Identity", "", id_common, single, identity); + +issize_t sip_identity_d(su_home_t *home, sip_header_t *h, char *s, isize_t slen) +{ + sip_identity_t *id = (sip_identity_t *)h; + char const *p = NULL, *pp = NULL, *ppp = NULL, *ib = NULL, *ie = NULL; + size_t len = 0; + + id->id_value = strdup(s); + id->id_info = NULL; + + p = strstr(s, "info="); + if (p) { + ib = p + 5; + ie = strchr(p, ';'); + pp = strchr(p, '<'); + + if (!ie) return 0; + + if (pp && pp < ie) { + + // info= with opening '<' + // must contain closing '>' before ';' + ppp = strchr(pp, '>'); + if (!ppp || ppp > ie) { + return 0; + } else { + ib = pp + 1; + ie = ppp - 1; + } + } + + len = ie - ib + 1; + id->id_info = strndup(ib, len); + } + + return 0; +} + +issize_t sip_identity_e(char b[], isize_t bsiz, sip_header_t const *h, int flags) +{ + sip_identity_t const *id = (sip_identity_t *)h; + + return snprintf(b, bsiz, "%s", id->id_value); +} + +isize_t sip_identity_dup_xtra(sip_header_t const *h, isize_t offset) +{ + sip_identity_t const *id = (sip_identity_t *)h; + return offset + MSG_STRING_SIZE(id->id_value); +} + +char *sip_identity_dup_one(sip_header_t *dst, sip_header_t const *src, + char *b, isize_t xtra) +{ + sip_identity_t *id = (sip_identity_t *)dst; + sip_identity_t const *o = (sip_identity_t *)src; + + MSG_STRING_DUP(b, id->id_value, o->id_value); + + return b; +} + +static int sip_identity_update(msg_common_t *h, + char const *name, isize_t namelen, + char const *value) +{ + sip_identity_t *id = (sip_identity_t *)h; + + id->id_value = strdup(value); + return 0; +} diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip.h b/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip.h index 37ae836598..aef7baae0f 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip.h +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip.h @@ -215,6 +215,9 @@ typedef msg_list_t sip_allow_events_t; /* RFC 3323 - @Privacy */ typedef struct sip_privacy_s sip_privacy_t; +/* SIP Identity Header, e.g. STIR-Shaken SIP Identity Header, RFC 8224 */ +typedef struct sip_identity_s sip_identity_t; + /* RFC 3327 - @Path */ typedef struct sip_route_s sip_path_t; @@ -259,6 +262,7 @@ struct sip_s { sip_to_t *sip_to; /**< To (t) */ sip_call_id_t *sip_call_id; /**< Call-ID (i) */ sip_cseq_t *sip_cseq; /**< CSeq */ + sip_identity_t *sip_identity; /**< Identity */ sip_contact_t *sip_contact; /**< Contact (m) */ sip_rseq_t *sip_rseq; /**< RSeq */ sip_rack_t *sip_rack; /**< RAck */ @@ -474,6 +478,17 @@ struct sip_cseq_s char const *cs_method_name; /**< Method name */ }; +/**@ingroup sip_identity + * @brief Structure for @Identity SIP header. + */ +struct sip_identity_s +{ + sip_common_t id_common[1]; /**< Common fragment info */ + sip_error_t *id_next; /**< Link to next (dummy) */ + char const *id_value; /**< Identity text as shown in SIP Header */ + char const *id_info; /**< Info param containing URL of the cert */ +}; + /**@ingroup sip_contact * @brief Structure for @Contact header field. */ @@ -920,6 +935,7 @@ union sip_header_u sip_separator_t sh_separator[1]; sip_payload_t sh_payload[1]; + sip_identity_t sh_identity[1]; }; SOFIA_END_DECLS diff --git a/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_header.h b/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_header.h index 8e212b11f3..78d6de525d 100644 --- a/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_header.h +++ b/libs/sofia-sip/libsofia-sip-ua/sip/sofia-sip/sip_header.h @@ -224,6 +224,10 @@ SOFIAPUBFUN sip_call_id_t *sip_call_id_create(su_home_t *home, SOFIAPUBFUN sip_cseq_t *sip_cseq_create(su_home_t *, uint32_t seq, unsigned method, char const *name); +/** Create a @Identity header object. */ +SOFIAPUBFUN sip_identity_t *sip_identity_create(su_home_t *, uint32_t seq, + unsigned method, char const *name); + /** Create a @Contact header object. */ SOFIAPUBFUN sip_contact_t * sip_contact_create(su_home_t *, url_string_t const *url,