int nua_subscribe_server_preprocess(nua_server_request_t *sr) { nua_handle_t *nh = sr->sr_owner; nua_dialog_state_t *ds = nh->nh_ds; nua_dialog_usage_t *du; struct notifier_usage *nu; sip_t const *sip = sr->sr_request.sip; sip_event_t *o = sip->sip_event; char const *event = o ? o->o_type : NULL; /* Maximum expiration time */ unsigned long expires = sip->sip_expires ? sip->sip_expires->ex_delta : 3600; sip_time_t now = sip_now(); sip_allow_events_t *appl_event = NH_PGET(nh, appl_event); assert(nh && nh->nh_nua->nua_dhandle != nh); du = nua_dialog_usage_get(ds, nua_notify_usage, o); if (du == NULL) { /* Create a new subscription */ du = nua_dialog_usage_add(nh, ds, nua_notify_usage, o); if (du == NULL) return SR_STATUS1(sr, SIP_500_INTERNAL_SERVER_ERROR); } else if (!msg_header_find_param((void *)appl_event, event)) { unsigned max_expires; /* Refresh existing subscription */ if (su_strmatch(event, "refer")) max_expires = NH_PGET(nh, refer_expires); else max_expires = NH_PGET(nh, sub_expires); if (expires >= max_expires) expires = max_expires; SR_STATUS1(sr, SIP_200_OK); } nu = nua_dialog_usage_private(du); if (now + expires >= now) nu->nu_requested = now + expires; else nu->nu_requested = SIP_TIME_MAX - 1; #if SU_HAVE_EXPERIMENTAL nu->nu_etags = sip_suppress_body_if_match(sip) || sip_suppress_notify_if_match(sip) || sip_has_feature(sr->sr_request.sip->sip_supported, "etags"); #endif sr->sr_usage = du; return sr->sr_status <= 100 ? 0 : sr->sr_status; }
int nua_publish_server_init(nua_server_request_t *sr) { sip_allow_events_t *allow_events = NH_PGET(sr->sr_owner, allow_events); sip_event_t *o = sr->sr_request.sip->sip_event; char const *event = o ? o->o_type : NULL; if (!allow_events) return SR_STATUS1(sr, SIP_501_NOT_IMPLEMENTED); else if (!event || !msg_header_find_param(allow_events->k_common, event)) return SR_STATUS1(sr, SIP_489_BAD_EVENT); return 0; }
int nua_subscribe_server_init(nua_server_request_t *sr) { nua_handle_t *nh = sr->sr_owner; nua_dialog_state_t *ds = nh->nh_ds; sip_allow_events_t const *allow_events = NH_PGET(nh, allow_events); sip_t const *sip = sr->sr_request.sip; sip_event_t *o = sip->sip_event; char const *event = o ? o->o_type : NULL; if (sr->sr_initial || !nua_dialog_usage_get(ds, nua_notify_usage, o)) { if (su_strmatch(event, "refer")) /* refer event subscription should be initiated with REFER */ return SR_STATUS1(sr, SIP_403_FORBIDDEN); /* XXX - event is case-sensitive, should use msg_header_find_item() */ if (!event || !msg_header_find_param(allow_events->k_common, event)) return SR_STATUS1(sr, SIP_489_BAD_EVENT); } return 0; }
/** Find a credential header with matching scheme and realm. */ msg_auth_t *auth_mod_credentials(msg_auth_t *auth, char const *scheme, char const *realm) { char const *arealm; for (; auth; auth = auth->au_next) { if (!su_casematch(auth->au_scheme, scheme)) continue; if (!realm) return auth; arealm = msg_header_find_param(auth->au_common, "realm="); if (!arealm) continue; if (arealm[0] == '"') { /* Compare quoted arealm with unquoted realm */ int i, j; for (i = 1, j = 0; arealm[i] != 0; i++, j++) { if (arealm[i] == '"' && realm[j] == 0) return auth; if (arealm[i] == '\\' && arealm[i + 1] != '\0') i++; if (arealm[i] != realm[j]) break; } } else { if (strcmp(arealm, realm) == 0) return auth; } } return NULL; }
/** Convert "gruu" parameter returned by registrar to Contact header. */ int outbound_gruuize(outbound_t *ob, sip_t const *sip) { sip_contact_t *m = NULL; char *gruu; if (!ob) return 0; if (ob->ob_rcontact == NULL) return -1; if (!ob->ob_prefs.gruuize && ob->ob_instance) { char const *my_instance, *my_reg_id = NULL; char const *instance, *reg_id; m = ob->ob_rcontact; my_instance = msg_header_find_param(m->m_common, "+sip.instance="); if (my_instance) my_reg_id = msg_header_find_param(m->m_common, "reg-id="); for (m = sip->sip_contact; m; m = m->m_next) { if (my_instance) { instance = msg_header_find_param(m->m_common, "+sip.instance="); if (!instance || strcmp(instance, my_instance)) continue; if (my_reg_id) { reg_id = msg_header_find_param(m->m_common, "reg-id="); if (!reg_id || strcmp(reg_id, my_reg_id)) continue; } } if (url_cmp_all(ob->ob_rcontact->m_url, m->m_url) == 0) break; } } if (m == NULL) { if (ob->ob_gruu) msg_header_free(ob->ob_home, (void *)ob->ob_gruu), ob->ob_gruu = NULL; return 0; } gruu = (char *)msg_header_find_param(m->m_common, "pub-gruu="); if (gruu == NULL || gruu[0] == '\0') gruu = (char *)msg_header_find_param(m->m_common, "gruu="); if (gruu == NULL || gruu[0] == '\0') return 0; gruu = msg_unquote_dup(NULL, gruu); m = gruu ? sip_contact_format(ob->ob_home, "<%s>", gruu) : NULL; su_free(NULL, gruu); if (!m) return -1; if (ob->ob_gruu) msg_header_free(ob->ob_home, (void *)ob->ob_gruu); ob->ob_gruu = m; return 0; }
/** Find a Digest credential header with matching realm and opaque. */ msg_auth_t *auth_digest_credentials(msg_auth_t *auth, char const *realm, char const *opaque) { char const *arealm, *aopaque; for (; auth; auth = auth->au_next) { if (!su_casematch(auth->au_scheme, "Digest")) continue; if (realm) { int cmp = 1; arealm = msg_header_find_param(auth->au_common, "realm="); if (!arealm) continue; if (arealm[0] == '"') { /* Compare quoted arealm with unquoted realm */ int i, j; for (i = 1, j = 0, cmp = 1; arealm[i] != 0; i++, j++) { if (arealm[i] == '"' && realm[j] == 0) { cmp = 0; break; } if (arealm[i] == '\\' && arealm[i + 1] != '\0') i++; if (arealm[i] != realm[j]) break; } } else { cmp = strcmp(arealm, realm); } if (cmp) continue; } if (opaque) { int cmp = 1; aopaque = msg_header_find_param(auth->au_common, "opaque="); if (!aopaque) continue; if (aopaque[0] == '"') { /* Compare quoted aopaque with unquoted opaque */ int i, j; for (i = 1, j = 0, cmp = 1; aopaque[i] != 0; i++, j++) { if (aopaque[i] == '"' && opaque[j] == 0) { cmp = 0; break; } if (aopaque[i] == '\\' && aopaque[i + 1] != '\0') i++; if (aopaque[i] != opaque[j]) break; } } else { cmp = strcmp(aopaque, opaque); } if (cmp) continue; } return auth; } return NULL; }