Beispiel #1
0
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();
}
Beispiel #3
0
/** 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;
}
Beispiel #5
0
/** 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);
}
Beispiel #6
0
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);
}