Example #1
0
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;
}
Example #2
0
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;
}
Example #3
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;
}
Example #4
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;
}
Example #5
0
/** 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;
}
Example #6
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;
}