Пример #1
0
/* debugging  only, remove */
void check_ser_drift()
{
	time_t t1, t2;
	struct timeval tv1, tv2;
	int r;

	t1=time(0);
	t2=ser_time(0);
	if (t1!=t2)
		BUG("time(0)!=ser_time(0) : %d != %d \n", (unsigned)t1, (unsigned)t2);

	r=gettimeofday(&tv1, 0);
	ser_gettimeofday(&tv2, 0);
	if (tv1.tv_sec!=tv2.tv_sec)
		BUG("gettimeofday seconds!=ser_gettimeofday seconds : %d != %d \n",
				(unsigned)tv1.tv_sec, (unsigned)tv2.tv_sec);
	else if ((tv1.tv_usec > tv2.tv_usec) &&
				(unsigned)(tv1.tv_usec-tv2.tv_usec)>100000)
		BUG("gettimeofday usecs > ser_gettimeofday with > 0.1s : %d ms\n",
			(unsigned)(tv1.tv_usec-tv2.tv_usec)/1000);
	else if ((tv1.tv_usec < tv2.tv_usec) &&
				(unsigned)(tv2.tv_usec-tv1.tv_usec)>100000)
		BUG("gettimeofday usecs < ser_gettimeofday with > 0.1s : %d ms\n",
			(unsigned)(tv2.tv_usec-tv1.tv_usec)/1000);
}
Пример #2
0
void get_act_time(void)
{

	act_time = ser_time(0);
}
Пример #3
0
/**
 * Create and return {WWW,Proxy}-Authenticate header field
 * @param nonce nonce value
 * @param algorithm algorithm value
 * @param qop qop value
 * @return -1 on error, 0 on success
 * 
 * The result is stored in param ahf.
 * If nonce is not null that it is used, instead of call calc_nonce.
 * If algorithm is not null that it is used irrespective of _PRINT_MD5
 * 
 * Major usage of nonce and algorithm params is AKA authentication. 
 */
int get_challenge_hf(struct sip_msg* msg, int stale, str* realm,
		str* nonce, str* algorithm, struct qp* qop, int hftype, str *ahf)
{
    char *p;
    str* hfn, hf;
    int nonce_len, l, cfg;
	int t;
#if defined USE_NC || defined USE_OT_NONCE
	unsigned int n_id;
	unsigned char pool;
	unsigned char pool_flags;
#endif

	if(!ahf)
	{
		LM_ERR("invalid output parameter\n");
		return -1;
	}

    if (realm) {
        DEBUG("build_challenge_hf: realm='%.*s'\n", realm->len, realm->s);
    }
    if (nonce) {
        DEBUG("build_challenge_hf: nonce='%.*s'\n", nonce->len, nonce->s);
    }
    if (algorithm) {
        DEBUG("build_challenge_hf: algorithm='%.*s'\n", algorithm->len,
				algorithm->s);
    }
    if (qop && qop->qop_parsed != QOP_UNSPEC) {
        DEBUG("build_challenge_hf: qop='%.*s'\n", qop->qop_str.len,
				qop->qop_str.s);
    }

    if (hftype == HDR_PROXYAUTH_T) {
		hfn = &proxy_challenge_header;
    } else {
		hfn = &www_challenge_header;
    }
    
	cfg = get_auth_checks(msg);

    nonce_len = get_nonce_len(cfg, nc_enabled || otn_enabled);

    hf.len = hfn->len;
    hf.len += DIGEST_REALM_LEN
	+ realm->len
	+ DIGEST_NONCE_LEN;
    if (nonce) {
    	hf.len += nonce->len
    	          + 1; /* '"' */
    }
    else {
    	hf.len += nonce_len
    	          + 1; /* '"' */
    }
	hf.len += ((stale) ? STALE_PARAM_LEN : 0);
    if (algorithm) {
    	hf.len += DIGEST_ALGORITHM_LEN + algorithm->len;
    }
    else {
    	hf.len += 0
#ifdef _PRINT_MD5
	+DIGEST_MD5_LEN
#endif
		;
    }
    
    if (qop && qop->qop_parsed != QOP_UNSPEC) {
		hf.len += QOP_PARAM_START_LEN + qop->qop_str.len + QOP_PARAM_END_LEN;
    }
	hf.len += CRLF_LEN;
    p = hf.s = pkg_malloc(hf.len);
    if (!hf.s) {
		ERR("auth: No memory left (%d bytes)\n", hf.len);
		return -1;
    }
    
    memcpy(p, hfn->s, hfn->len); p += hfn->len;
    memcpy(p, DIGEST_REALM, DIGEST_REALM_LEN); p += DIGEST_REALM_LEN;
    memcpy(p, realm->s, realm->len); p += realm->len;
    memcpy(p, DIGEST_NONCE, DIGEST_NONCE_LEN); p += DIGEST_NONCE_LEN;
    if (nonce) {
        memcpy(p, nonce->s, nonce->len); p += nonce->len;
    }
    else {
        l=nonce_len;
		t=ser_time(0);
#if defined USE_NC || defined USE_OT_NONCE
		if (nc_enabled || otn_enabled){
			pool=nid_get_pool();
			n_id=nid_inc(pool);
			pool_flags=0;
#ifdef USE_NC
			if (nc_enabled){
				nc_new(n_id, pool);
				pool_flags|=  NF_VALID_NC_ID;
			}
#endif
#ifdef USE_OT_NONCE
			if (otn_enabled){
				otn_new(n_id, pool);
				pool_flags|= NF_VALID_OT_ID;
			}
#endif
		}else{
			pool=0;
			pool_flags=0;
			n_id=0;
		}
		if (calc_nonce(p, &l, cfg, t, t + nonce_expire, n_id,
						pool | pool_flags,
						&secret1, &secret2, msg) != 0)
#else  /* USE_NC || USE_OT_NONCE*/
		if (calc_nonce(p, &l, cfg, t, t + nonce_expire, 
						&secret1, &secret2, msg) != 0) 
#endif /* USE_NC || USE_OT_NONCE */
		{
            ERR("auth: calc_nonce failed (len %d, needed %d)\n",
                 nonce_len, l);
            pkg_free(hf.s);
            return -1;
        }
        p += l;
    }
    *p = '"'; p++;

    if (qop && qop->qop_parsed != QOP_UNSPEC) {
		memcpy(p, QOP_PARAM_START, QOP_PARAM_START_LEN);
		p += QOP_PARAM_START_LEN;
		memcpy(p, qop->qop_str.s, qop->qop_str.len);
		p += qop->qop_str.len;
		memcpy(p, QOP_PARAM_END, QOP_PARAM_END_LEN);
		p += QOP_PARAM_END_LEN;
    }
    if (stale) {
		memcpy(p, STALE_PARAM, STALE_PARAM_LEN);
		p += STALE_PARAM_LEN;
    }
	if (algorithm) {
		memcpy(p, DIGEST_ALGORITHM, DIGEST_ALGORITHM_LEN);
		p += DIGEST_ALGORITHM_LEN;
		memcpy(p, algorithm->s, algorithm->len);
		p += algorithm->len;
	}
	else {
#ifdef _PRINT_MD5
    memcpy(p, DIGEST_MD5, DIGEST_MD5_LEN ); p += DIGEST_MD5_LEN;
#endif
	}
    memcpy(p, CRLF, CRLF_LEN); p += CRLF_LEN;
	hf.len=(int)(p-hf.s); /* fix len, it might be smaller due to a smaller
							 nonce */
    
    DBG("auth: '%.*s'\n", hf.len, ZSW(hf.s));
	*ahf = hf;
    return 0;
}
Пример #4
0
/** Check whether the nonce returned by UA is valid.
 * This function checks whether the nonce string returned by UA
 * in digest response is valid. The function checks if the nonce
 * string hasn't expired, it verifies the secret stored in the nonce
 * string with the secret configured on the server. If any of the
 * optional extra integrity checks are enabled then it also verifies
 * whether the corresponding parts in the new SIP requests are same.
 * @param nonce A nonce string to be verified.
 * @param secret1 A secret used for the nonce expires integrity check:
 *                MD5(<expire_time>,, secret1).
 * @param secret2 A secret used for integrity check of the message parts 
 *                selected by auth_extra_checks (if any):
 *                MD5(<msg_parts(auth_extra_checks)>, secret2).
 * @param msg The message which contains the nonce being verified. 
 * @return 0 - success (the nonce was not tampered with and if 
 *             auth_extra_checks are enabled - the selected message fields
 *             have not changes from the time the nonce was generated)
 *         -1 - invalid nonce
 *          1 - nonce length too small
 *          2 - no match
 *          3 - nonce expires ok, but the auth_extra checks failed
 *          4 - stale
 *          5 - invalid nc value (not an unsigned int)
 */
int check_nonce(auth_body_t* auth, str* secret1, str* secret2,
					struct sip_msg* msg)
{
	str * nonce;
	int since, b_nonce2_len, b_nonce_len, cfg;
	union bin_nonce b_nonce;
	union bin_nonce b_nonce2;
	time_t t;
#if defined USE_NC || defined USE_OT_NONCE
	unsigned int n_id;
	unsigned char pf;
#endif /* USE_NC || USE_OT_NONCE */
#ifdef USE_NC
	unsigned int nc;
#endif

	cfg = get_auth_checks(msg);
	nonce=&auth->digest.nonce;

	if (unlikely(nonce->s == 0)) {
		return -1;  /* Invalid nonce */
	}
	
	if (unlikely(nonce->len<MIN_NONCE_LEN)){ 
		return 1; /* length musth be >= then minimum length */
	}
	
#if defined USE_NC || defined USE_OT_NONCE
	/* clear all possible nonce flags positions prior to decoding,
	 * to make sure they can be used even if the nonce is shorter */
	b_nonce.n.nid_pf=0;
	b_nonce.n_small.nid_pf=0;
#endif /* USE_NC || USE_OT_NONCE */
	
	/* decode nonce */
	b_nonce_len=base64_dec((unsigned char*)nonce->s, nonce->len,
							&b_nonce.raw[0], sizeof(b_nonce));
	if (unlikely(b_nonce_len < MIN_BIN_NONCE_LEN)){
		DBG("auth: check_nonce: base64_dec failed\n");
		return -1; /* error decoding the nonce (invalid nonce since we checked
		              the len of the base64 enc. nonce above)*/
	}
	
	since = get_bin_nonce_since(&b_nonce);
	if (unlikely(since < up_since)) {
		/* if valid_since time is time pointing before ser was started 
		 * then we consider nonce as stalled. 
		   It may be the nonce generated by previous ser instance having
		   different length (for example because of different auth.
		   checks)..  Therefore we force credentials to be rebuilt by UAC
		   without prompting for password */
		return 4;
	}
	t=ser_time(0);
	if (unlikely((since > t) && ((since-t) > nonce_auth_max_drift) )){
		/* the nonce comes from the future, either because of an external
		 * time adjustment, or because it was generated by another host
		 * which has the time slightly unsynchronized */
		return 4; /* consider it stale */
	}
	b_nonce2=b_nonce; /*pre-fill it with the values from the received nonce*/
	b_nonce2.n.expire=b_nonce.n.expire;
	b_nonce2.n.since=b_nonce.n.since;
#if defined USE_NC || defined USE_OT_NONCE
	if (cfg){
		b_nonce2.n.nid_i=b_nonce.n.nid_i;
		b_nonce2.n.nid_pf=b_nonce.n.nid_pf;
		pf=b_nonce.n.nid_pf;
		n_id=ntohl(b_nonce.n.nid_i);
	}else{
		b_nonce2.n_small.nid_i=b_nonce.n_small.nid_i;
		b_nonce2.n_small.nid_pf=b_nonce.n_small.nid_pf;
		pf=b_nonce.n_small.nid_pf;
		n_id=ntohl(b_nonce.n_small.nid_i);
	}
#ifdef UE_NC
	if (unlikely(nc_enabled && !(pf & NF_VALID_NC_ID)) )
		/* nounce count enabled, but nonce is not marked as nonce count ready
		 * or is too short => either an old nonce (should
		 * be caught by the ser start time  check) or truncated nonce  */
		return 4; /* return stale for now */
	}