int s2_save_register(struct message *rm) { sip_contact_t *contact, *m, **m_prev; sip_expires_t const *ex; sip_date_t const *date; sip_time_t now = rm->when.tv_sec, expires; msg_header_free_all(s2->home, (msg_header_t *)s2->registration->aor); msg_header_free_all(s2->home, (msg_header_t *)s2->registration->contact); tport_unref(s2->registration->tport); s2->registration->aor = NULL; s2->registration->contact = NULL; s2->registration->tport = NULL; if (rm == NULL) return 0; assert(rm && rm->sip && rm->sip->sip_request); assert(rm->sip->sip_request->rq_method == sip_method_register); ex = rm->sip->sip_expires; date = rm->sip->sip_date; contact = sip_contact_dup(s2->home, rm->sip->sip_contact); for (m_prev = &contact; *m_prev;) { m = *m_prev; expires = sip_contact_expires(m, ex, date, s2_default_registration_duration, now); if (expires) { char *p = su_sprintf(s2->home, "expires=%lu", (unsigned long)expires); msg_header_add_param(s2->home, m->m_common, p); m_prev = &m->m_next; } else { *m_prev = m->m_next; m->m_next = NULL; msg_header_free(s2->home, (msg_header_t *)m); } } if (contact == NULL) return 0; s2->registration->aor = sip_to_dup(s2->home, rm->sip->sip_to); s2->registration->contact = contact; s2->registration->tport = tport_ref(rm->tport); s2sip->sut.aor = s2->registration->aor; s2sip->sut.contact = s2->registration->contact; s2sip->sut.tport = s2->registration->tport; return 0; }
static int test_sprintf(char const *fmt, ...) { BEGIN(); su_home_t home[1] = { SU_HOME_INIT(home) }; va_list va; TEST_S(su_sprintf(home, "foo%s", "bar"), "foobar"); va_start(va, fmt); TEST_S(su_vsprintf(home, fmt, va), "foo.bar"); TEST_S(su_sprintf(home, "foo%200s", "bar"), "foo " " " " " " bar"); su_home_deinit(home); END(); }
/** Create a new outbound object */ outbound_t * outbound_new(outbound_owner_t *owner, outbound_owner_vtable const *owner_methods, su_root_t *root, nta_agent_t *agent, char const *instance) { outbound_t *ob; if (!owner || !owner_methods || !root || !agent) return NULL; ob = su_home_clone((su_home_t *)owner, sizeof *ob); if (ob) { su_md5_t md5[1]; uint8_t digest[SU_MD5_DIGEST_SIZE]; su_guid_t guid[1]; ob->ob_owner = owner; ob->ob_oo = owner_methods; ob->ob_root = root; ob->ob_nta = agent; if (instance) ob->ob_instance = su_sprintf(ob->ob_home, "+sip.instance=\"<%s>\"", instance); ob->ob_reg_id = 0; outbound_peer_info(ob, NULL); /* Generate a random cookie (used as Call-ID) for us */ su_md5_init(md5); su_guid_generate(guid); if (instance) su_md5_update(md5, (void *)instance, strlen(instance)); su_md5_update(md5, (void *)guid, sizeof guid); su_md5_digest(md5, digest); token64_e(ob->ob_cookie, sizeof ob->ob_cookie, digest, sizeof digest); if (instance && !ob->ob_instance) su_home_unref(ob->ob_home), ob = NULL; } return ob; }
/* Return Via that looks very natted */ static sip_via_t *natted_via(struct message *m, const char *receive_natted) { su_home_t *h; sip_via_t *via; h = msg_home(m->msg); via = sip_via_dup(h, m->sip->sip_via); msg_header_replace_param(h, via->v_common, receive_natted); if (via->v_protocol == sip_transport_udp) msg_header_replace_param(h, via->v_common, "rport=9"); if (via->v_protocol == sip_transport_tcp && via->v_rport) { tp_name_t const *tpn = tport_name(m->tport); char *rport = su_sprintf(h, "rport=%s", tpn->tpn_port); msg_header_replace_param(h, via->v_common, rport); } return via; }
/** Authenticate user. * * The function auth_mod_method() invokes scheme-specific authentication * operation where the user's credentials are checked using scheme-specific * method. The authentication result along with an optional challenge header * is stored in the @a as structure. * * @param am pointer to authentication module object [in] * @param as pointer to authentication status structure [in/out] * @param credentials pointer to a header with user's credentials [in] * @param ach pointer to a structure describing challenge [in] * * The @a ach structure defines what kind of response and challenge header * is returned to the user. For example, a server authentication is * implemented with 401 response code and phrase along with WWW-Authenticate * header template in the @a ach structure. * * The auth_mod_method() returns the authentication result in the * #auth_mod_t @a as structure. The @a as->as_status describes the result * as follows: * - <i>as->as_status == 0</i> authentication is successful * - <i>as->as_status == 100</i> authentication is pending * - <i>as->as_status >= 400</i> authentication fails, * return as_status as an error code to client * * When the authentication is left pending, the client must set the * as_callback pointer in @a as structure to an appropriate callback * function. The callback is invoked when the authentication is completed, * either successfully or with an error. * * Note that the authentication module may generate a new challenge each * time authentication is used (e.g., Digest using MD5 algorithm). Such a * challenge header is stored in the @a as->as_response return-value field. * * @note The authentication plugin may use the given reference to @a as, @a * credentials and @a ach structures until the asynchronous authentication * completes. Therefore, they should not be allocated from stack unless * application uses strictly synchronous authentication schemes only (Basic * and Digest). * * @note This function should be called auth_mod_check(). */ void auth_mod_verify(auth_mod_t *am, auth_status_t *as, msg_auth_t *credentials, auth_challenger_t const *ach) { char const *wildcard, *host; if (!am || !as || !ach) return; wildcard = strchr(am->am_realm, '*'); host = as->as_domain; /* Initialize per-request realm */ if (as->as_realm) ; else if (!wildcard) { as->as_realm = am->am_realm; } else if (!host) { return; /* Internal error */ } else if (strcmp(am->am_realm, "*") == 0) { as->as_realm = host; } else { /* Replace * with hostpart */ as->as_realm = su_sprintf(as->as_home, "%.*s%s%s", (int)(wildcard - am->am_realm), am->am_realm, host, wildcard + 1); } am->am_scheme->asch_check(am, as, credentials, ach); }
static int tport_ws_init_primary_secure(tport_primary_t *pri, tp_name_t tpn[1], su_addrinfo_t *ai, tagi_t const *tags, char const **return_culprit) { tport_ws_primary_t *wspri = (tport_ws_primary_t *)pri; const char *cert = "/ssl.pem"; const char *key = "/ssl.pem"; char *homedir; char *tbf = NULL; su_home_t autohome[SU_HOME_AUTO_SIZE(1024)]; char const *path = NULL; int ret = -1; su_home_auto(autohome, sizeof autohome); tl_gets(tags, TPTAG_CERTIFICATE_REF(path), TAG_END()); if (!path) { homedir = getenv("HOME"); if (!homedir) homedir = ""; path = tbf = su_sprintf(autohome, "%s/.sip/auth", homedir); } if (path) { key = su_sprintf(autohome, "%s/%s", path, "wss.key"); if (access(key, R_OK) != 0) key = NULL; cert = su_sprintf(autohome, "%s/%s", path, "wss.crt"); if (access(cert, R_OK) != 0) cert = NULL; if ( !key ) key = su_sprintf(autohome, "%s/%s", path, "wss.pem"); if ( !cert ) cert = su_sprintf(autohome, "%s/%s", path, "wss.pem"); if (access(key, R_OK) != 0) key = NULL; if (access(cert, R_OK) != 0) cert = NULL; } init_ssl(); // OpenSSL_add_all_algorithms(); /* load & register cryptos */ // SSL_load_error_strings(); /* load all error messages */ wspri->ssl_method = SSLv23_server_method(); /* create server instance */ wspri->ssl_ctx = SSL_CTX_new((SSL_METHOD *)wspri->ssl_method); /* create context */ SSL_CTX_sess_set_remove_cb(wspri->ssl_ctx, NULL); wspri->ws_secure = 1; if ( !wspri->ssl_ctx ) goto done; /* set the local certificate from CertFile */ SSL_CTX_use_certificate_file(wspri->ssl_ctx, cert, SSL_FILETYPE_PEM); /* set the private key from KeyFile */ SSL_CTX_use_PrivateKey_file(wspri->ssl_ctx, key, SSL_FILETYPE_PEM); /* verify private key */ if ( !SSL_CTX_check_private_key(wspri->ssl_ctx) ) { goto done; } SSL_CTX_set_cipher_list(wspri->ssl_ctx, "HIGH:!DSS:!aNULL@STRENGTH"); ret = tport_ws_init_primary(pri, tpn, ai, tags, return_culprit); done: su_home_zap(autohome); return ret; }
static int nua_notify_client_request(nua_client_request_t *cr, msg_t *msg, sip_t *sip, tagi_t const *tags) { nua_dialog_usage_t *du = cr->cr_usage; struct notifier_usage *nu = nua_dialog_usage_private(du); su_home_t *home = msg_home(msg); sip_time_t now = sip_now(); sip_subscription_state_t *ss = sip->sip_subscription_state; char const *expires; if (du == NULL) /* Subscription has been terminated */ return nua_client_return(cr, SIP_481_NO_TRANSACTION, msg); assert(du && nu); if (du && nua_client_bind(cr, du) < 0) return -1; if (nu->nu_requested) nu->nu_expires = nu->nu_requested; nu->nu_requested = 0; if (nu->nu_expires <= now || du->du_shutdown) { nu->nu_substate = nua_substate_terminated; expires = "expires=0"; } else { expires = su_sprintf(home, "expires=%lu", nu->nu_expires - now); } if (ss == NULL || nua_substate_make(ss->ss_substate) != nu->nu_substate) { if (nu->nu_substate == nua_substate_terminated) expires = nu->nu_expires > now ? "reason=noresource" : "reason=timeout"; ss = sip_subscription_state_format(home, "%s;%s", nua_substate_name(nu->nu_substate), expires); msg_header_insert(msg, (void *)sip, (void *)ss); } else if (nu->nu_substate != nua_substate_terminated) { msg_header_replace_param(home, ss->ss_common, expires); } #if SU_HAVE_EXPERIMENTAL if (nu->nu_tag && !sip->sip_etag) msg_header_add_make(msg, (void *)sip, sip_etag_class, nu->nu_tag); if (nu->nu_no_body) { nu->nu_no_body = 0; msg_header_remove(msg, (void *)sip, (void *)sip->sip_payload); msg_header_remove(msg, (void *)sip, (void *)sip->sip_content_length); } #endif if (nu->nu_substate == nua_substate_terminated) nua_client_set_terminating(cr, 1); if (cr->cr_terminating) { nua_server_request_t *sr; for (sr = du->du_dialog->ds_sr; sr; sr = sr->sr_next) { if (sr->sr_usage == du) { /* If subscribe has not been responded, don't terminate usage by NOTIFY */ sr->sr_terminating = 1; nua_client_set_terminating(cr, 0); break; } } } if (du->du_event && !sip->sip_event) sip_add_dup(cr->cr_msg, sip, (sip_header_t *)du->du_event); return nua_base_client_request(cr, msg, sip, tags); }