Exemple #1
0
PJ_DEF(pj_str_t) pj_str_unescape( pj_pool_t *pool, const pj_str_t *src_str)
{
    char *src = src_str->ptr;
    char *end = src + src_str->slen;
    pj_str_t dst_str;
    char *dst;
    
    if (pj_strchr(src_str, '%')==NULL)
	return *src_str;

    dst = dst_str.ptr = (char*) pj_pool_alloc(pool, src_str->slen);

    while (src != end) {
	if (*src == '%' && src < end-2 && pj_isxdigit(*(src+1)) && 
	    pj_isxdigit(*(src+2))) 
	{
	    *dst = (pj_uint8_t) ((pj_hex_digit_to_val(*(src+1)) << 4) + 
				 pj_hex_digit_to_val(*(src+2)));
	    ++dst;
	    src += 3;
	} else {
	    *dst++ = *src++;
	}
    }
    dst_str.slen = dst - dst_str.ptr;
    return dst_str;
}
Exemple #2
0
PJ_DEF(void) pj_scan_get_unescape( pj_scanner *scanner,
				   const pj_cis_t *spec, pj_str_t *out)
{
    register char *s = scanner->curptr;
    char *dst = s;

    pj_assert(pj_cis_match(spec,0)==0);

    /* Must not match character '%' */
    pj_assert(pj_cis_match(spec,'%')==0);

    /* EOF is detected implicitly */
    if (!pj_cis_match(spec, *s) && *s != '%') {
	pj_scan_syntax_err(scanner);
	return;
    }

    out->ptr = s;
    do {
	if (*s == '%') {
	    if (s+3 <= scanner->end && pj_isxdigit(*(s+1)) && 
		pj_isxdigit(*(s+2))) 
	    {
		*dst = (pj_uint8_t) ((pj_hex_digit_to_val(*(s+1)) << 4) +
				      pj_hex_digit_to_val(*(s+2)));
		++dst;
		s += 3;
	    } else {
		*dst++ = *s++;
		*dst++ = *s++;
		break;
	    }
	}
	
	if (pj_cis_match(spec, *s)) {
	    char *start = s;
	    do {
		++s;
	    } while (pj_cis_match(spec, *s));

	    if (dst != start) pj_memmove(dst, start, s-start);
	    dst += (s-start);
	} 
	
    } while (*s == '%');

    scanner->curptr = s;
    out->slen = (dst - out->ptr);

    if (PJ_SCAN_IS_PROBABLY_SPACE(*s) && scanner->skip_ws) {
	pj_scan_skip_whitespace(scanner);    
    }
}
Exemple #3
0
PJ_DEF(unsigned long) pj_strtoul2(const pj_str_t *str, pj_str_t *endptr,
				  unsigned base)
{
    unsigned long value;
    unsigned i;

    PJ_CHECK_STACK();

    value = 0;
    if (base <= 10) {
	for (i=0; i<(unsigned)str->slen; ++i) {
	    unsigned c = (str->ptr[i] - '0');
	    if (c >= base)
		break;
	    value = value * base + c;
	}
    } else if (base == 16) {
	for (i=0; i<(unsigned)str->slen; ++i) {
	    if (!pj_isxdigit(str->ptr[i]))
		break;
	    value = value * 16 + pj_hex_digit_to_val(str->ptr[i]);
	}
    } else {
	pj_assert(!"Unsupported base");
	i = 0;
	value = 0xFFFFFFFFUL;
    }

    if (endptr) {
	endptr->ptr = str->ptr + i;
	endptr->slen = str->slen - i;
    }

    return value;
}
Exemple #4
0
PJ_DEF(pj_str_t*) pj_strcpy_unescape(pj_str_t *dst_str,
				     const pj_str_t *src_str)
{
    const char *src = src_str->ptr;
    const char *end = src + src_str->slen;
    char *dst = dst_str->ptr;
    
    while (src != end) {
	if (*src == '%' && src < end-2) {
	    *dst = (pj_uint8_t) ((pj_hex_digit_to_val(*(src+1)) << 4) + 
				 pj_hex_digit_to_val(*(src+2)));
	    ++dst;
	    src += 3;
	} else {
	    *dst++ = *src++;
	}
    }
    dst_str->slen = dst - dst_str->ptr;
    return dst_str;
}
Exemple #5
0
/* Return 0 if success or the index of the invalid char in the string */
static unsigned parse_quoted_string(struct parse_state *st,
                                    pj_str_t *output)
{
    pj_str_t token;
    char *op, *ip, *iend;

    pj_scan_get_quote(&st->scanner, '"', '"', &token);

    /* Remove the quote characters */
    token.ptr++;
    token.slen-=2;

    if (pj_strchr(&token, '\\') == NULL) {
	*output = token;
	return 0;
    }

    output->ptr = op = pj_pool_alloc(st->pool, token.slen);

    ip = token.ptr;
    iend = token.ptr + token.slen;

    while (ip != iend) {
	if (*ip == '\\') {
	    ++ip;
	    if (ip==iend) {
		goto on_error;
	    }
	    if (*ip == 'u') {
		ip++;
		if (iend - ip < 4) {
		    ip = iend -1;
		    goto on_error;
		}
		/* Only use the last two hext digits because we're on
		 * ASCII */
		*op++ = (char)(pj_hex_digit_to_val(ip[2]) * 16 +
			       pj_hex_digit_to_val(ip[3]));
		ip += 4;
	    } else if (*ip=='"' || *ip=='\\' || *ip=='/') {
		*op++ = *ip++;
	    } else if (*ip=='b') {
		*op++ = '\b';
		ip++;
	    } else if (*ip=='f') {
		*op++ = '\f';
		ip++;
	    } else if (*ip=='n') {
		*op++ = '\n';
		ip++;
	    } else if (*ip=='r') {
		*op++ = '\r';
		ip++;
	    } else if (*ip=='t') {
		*op++ = '\t';
		ip++;
	    } else {
		goto on_error;
	    }
	} else {
	    *op++ = *ip++;
	}
    }

    output->slen = op - output->ptr;
    return 0;

on_error:
    output->slen = op - output->ptr;
    return (unsigned)(ip - token.ptr);
}
Exemple #6
0
pj_status_t user_lookup(pj_pool_t *pool,
                        const pjsip_auth_lookup_cred_param *param,
                        pjsip_cred_info *cred_info,
                        void* av_param)
{
  const pj_str_t* acc_name = &param->acc_name;
  const pj_str_t* realm = &param->realm;
  const pjsip_rx_data* rdata = param->rdata;
  SAS::TrailId trail = get_trail(rdata);

  pj_status_t status = PJSIP_EAUTHACCNOTFOUND;

  // Get the impi and the nonce.  There must be an authorization header otherwise
  // PJSIP wouldn't have called this method.
  std::string impi = PJUtils::pj_str_to_string(acc_name);
  pjsip_authorization_hdr* auth_hdr = (pjsip_authorization_hdr*)
           pjsip_msg_find_hdr(rdata->msg_info.msg, PJSIP_H_AUTHORIZATION, NULL);
  std::string nonce = PJUtils::pj_str_to_string(&auth_hdr->credential.digest.nonce);

  // Get the Authentication Vector from the store.
  Json::Value* av = (Json::Value*)av_param;

  if (av == NULL)
  {
    LOG_WARNING("Received an authentication request for %s with nonce %s, but no matching AV found", impi.c_str(), nonce.c_str());
  }

  if ((av != NULL) &&
      (!verify_auth_vector(av, impi, trail)))
  {
    // Authentication vector is badly formed.
    av = NULL;                                                 // LCOV_EXCL_LINE
  }

  if (av != NULL)
  {
    pj_cstr(&cred_info->scheme, "digest");
    pj_strdup(pool, &cred_info->username, acc_name);
    if (av->isMember("aka"))
    {
      // AKA authentication.  The response in the AV must be used as a
      // plain-text password for the MD5 Digest computation.  Convert the text
      // into binary as this is what PJSIP is expecting.
      std::string response = (*av)["aka"]["response"].asString();
      std::string xres;
      for (size_t ii = 0; ii < response.length(); ii += 2)
      {
        xres.push_back((char)(pj_hex_digit_to_val(response[ii]) * 16 +
                              pj_hex_digit_to_val(response[ii+1])));
      }
      cred_info->data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
      pj_strdup2(pool, &cred_info->data, xres.c_str());
      LOG_DEBUG("Found AKA XRES = %.*s", cred_info->data.slen, cred_info->data.ptr);

      // Use default realm as it isn't specified in the AV.
      pj_strdup(pool, &cred_info->realm, realm);
      status = PJ_SUCCESS;
    }
    else if (av->isMember("digest"))
    {
      if (pj_strcmp2(realm, (*av)["digest"]["realm"].asCString()) == 0)
      {
        // Digest authentication, so ha1 field is hashed password.
        cred_info->data_type = PJSIP_CRED_DATA_DIGEST;
        pj_strdup2(pool, &cred_info->data, (*av)["digest"]["ha1"].asCString());
        cred_info->realm = *realm;
        LOG_DEBUG("Found Digest HA1 = %.*s", cred_info->data.slen, cred_info->data.ptr);
        status = PJ_SUCCESS;
      }
      else
      {
        // These credentials are for a different realm, so no credentials were
        // actually provided for us to check.
        status = PJSIP_EAUTHNOAUTH;
      }
    }

    correlate_branch_from_av(av, trail);
  }

  return status;
}
Exemple #7
0
PJ_DEF(pj_status_t) pj_strtoul3(const pj_str_t *str, unsigned long *value,
				unsigned base)
{
    pj_str_t s;
    unsigned i;

    PJ_CHECK_STACK();

    if (!str || !value) {
        return PJ_EINVAL;
    }

    s = *str;
    pj_strltrim(&s);

    if (s.slen == 0 || s.ptr[0] < '0' ||
	(base <= 10 && (unsigned)s.ptr[0] > ('0' - 1) + base) ||
	(base == 16 && !pj_isxdigit(s.ptr[0])))
    {
        return PJ_EINVAL;
    }

    *value = 0;
    if (base <= 10) {
	for (i=0; i<(unsigned)s.slen; ++i) {
	    unsigned c = s.ptr[i] - '0';
	    if (s.ptr[i] < '0' || (unsigned)s.ptr[i] > ('0' - 1) + base) {
		break;
	    }
	    if (*value > PJ_MAXULONG / base) {
		*value = PJ_MAXULONG;
		return PJ_ETOOBIG;
	    }

	    *value *= base;
	    if ((PJ_MAXULONG - *value) < c) {
		*value = PJ_MAXULONG;
		return PJ_ETOOBIG;
	    }
	    *value += c;
	}
    } else if (base == 16) {
	for (i=0; i<(unsigned)s.slen; ++i) {
	    unsigned c = pj_hex_digit_to_val(s.ptr[i]);
	    if (!pj_isxdigit(s.ptr[i]))
		break;

	    if (*value > PJ_MAXULONG / base) {
		*value = PJ_MAXULONG;
		return PJ_ETOOBIG;
	    }
	    *value *= base;
	    if ((PJ_MAXULONG - *value) < c) {
		*value = PJ_MAXULONG;
		return PJ_ETOOBIG;
	    }
	    *value += c;
	}
    } else {
	pj_assert(!"Unsupported base");
	return PJ_EINVAL;
    }
    return PJ_SUCCESS;
}