示例#1
0
/*
 * Calculate the response and compare with the given response string
 * Authorization is successful if this two strings are same
 */
int auth_check_response(dig_cred_t* cred, str* method, char* ha1)
{
	HASHHEX resp, hent;

	/*
	 * First, we have to verify that the response received has
	 * the same length as responses created by us
	 */
	if (cred->response.len != 32) {
		DBG("check_response: Receive response len != 32\n");
		return BAD_CREDENTIALS;
	}

	/*
	 * Now, calculate our response from parameters received
	 * from the user agent
	 */
	calc_response(ha1, &(cred->nonce),
				  &(cred->nc), &(cred->cnonce),
				  &(cred->qop.qop_str), cred->qop.qop_parsed == QOP_AUTHINT,
				  method, &(cred->uri), hent, resp);

	DBG("check_response: Our result = \'%s\'\n", resp);

	/*
	 * And simply compare the strings, the user is
	 * authorized if they match
	 */
	if (!memcmp(resp, cred->response.s, 32)) {
		DBG("check_response: Authorization is OK\n");
		return AUTHENTICATED;
	} else {
		DBG("check_response: Authorization failed\n");
		return NOT_AUTHENTICATED;
	}
}
示例#2
0
/*
 * Calculate the response and compare with the given response string
 * Authorization is successful if this two strings are same
 */
static inline int check_response(dig_cred_t* _cred, str* _method, char* _ha1)
{
	HASHHEX resp, hent;

	/*
	 * First, we have to verify that the response received has
	 * the same length as responses created by us
	 */
	if (_cred->response.len != 32) {
		DBG("check_response(): Receive response len != 32\n");
		return 1;
	}

	/*
	 * Now, calculate our response from parameters received
	 * from the user agent
	 */
	calc_response(_ha1, &(_cred->nonce),
		&(_cred->nc), &(_cred->cnonce),
		&(_cred->qop.qop_str), _cred->qop.qop_parsed == QOP_AUTHINT,
		_method, &(_cred->uri), hent, resp);
	
	DBG("check_response(): Our result = \'%s\'\n", resp);
	
	/*
	 * And simply compare the strings, the user is
	 * authorized if they match
	 */
	if (!memcmp(resp, _cred->response.s, 32)) {
		DBG("check_response(): Authorization is OK\n");
		return 0;
	} else {
		DBG("check_response(): Authorization failed\n");
		return 2;
	}
}
示例#3
0
void async_cdp_callback(int is_timeout, void *param, AAAMessage *maa, long elapsed_msecs) {
    int i, j;
    int rc = -1, experimental_rc = -1;
    saved_transaction_t* data = (saved_transaction_t*) param;
    struct cell *t = 0;
    int result = CSCF_RETURN_TRUE;
    int sip_number_auth_items;
    struct auth_data_item_list *adi_list = 0;
    AAA_AVP *auth_data;
    auth_data = 0;
    int item_number;
    str authenticate = {0, 0}, authorization2 = {0, 0}, ck = {0, 0}, ik = {0, 0}, ip = {0, 0}, ha1 = {0, 0};
    str line_identifier = {0, 0};
    str response_auth = {0, 0}, digest_realm = {0, 0};
    auth_vector *av = 0, **avlist = 0;
    HASHHEX ha1_hex;
    HASHHEX result_hex;
    str etsi_nonce = {0, 0};
    str private_identity, public_identity;
    str algorithm;

    if (is_timeout) {
    	update_stat(stat_mar_timeouts, 1);
        LM_ERR("Transaction timeout - did not get MAA\n");
        result = CSCF_RETURN_ERROR;
        goto error;
    }
    if (!maa) {
        LM_ERR("Error sending message via CDP\n");
        result = CSCF_RETURN_ERROR;
        goto error;
    }

    update_stat(mar_replies_received, 1);
    update_stat(mar_replies_response_time, elapsed_msecs);

    if (tmb.t_lookup_ident(&t, data->tindex, data->tlabel) < 0) {
        LM_ERR("t_continue: transaction not found\n");
        result = CSCF_RETURN_ERROR;
        goto error;
    }

    /* get the private_identity */
    private_identity = get_private_identity(t->uas.request, data->realm, data->is_proxy_auth);
    if (!private_identity.len) {
        LM_ERR("No private identity specified (Authorization: username)\n");
        stateful_request_reply_async(t, t->uas.request, 403, MSG_403_NO_PRIVATE);
        result = CSCF_RETURN_FALSE;
        goto error;
    }
    /* get the public_identity */
    public_identity = get_public_identity(t->uas.request);
    if (!public_identity.len) {
        LM_ERR("No public identity specified (To:)\n");
        stateful_request_reply_async(t, t->uas.request, 403, MSG_403_NO_PUBLIC);
        result = CSCF_RETURN_FALSE;
        goto error;
    }

    //get each individual element from the MAA
    cxdx_get_result_code(maa, &rc);
    cxdx_get_experimental_result_code(maa, &experimental_rc);
    cxdx_get_sip_number_auth_items(maa, &sip_number_auth_items);

    //now assign the auth_data_item elements
    //there can be many of these in the MAA
    struct auth_data_item *adi;
    int adi_len;
    char *p;
    while ((cxdx_get_auth_data_item_answer(maa, &auth_data, &item_number,
            &algorithm, &authenticate, &authorization2,
            &ck, &ik,
            &ip,
            &ha1, &response_auth, &digest_realm,
            &line_identifier))) {

        //create an auth_data_item for each entry in the MAA
        adi_len = sizeof (struct auth_data_item) +authenticate.len + authorization2.len + ck.len + ik.len + ip.len + ha1.len + line_identifier.len + response_auth.len + digest_realm.len + algorithm.len;
        adi = (struct auth_data_item*) shm_malloc(adi_len);
        if (!adi) {
            LM_CRIT("Out of memory!\n");
            result = CSCF_RETURN_ERROR;
            goto done;
        }

        memset(adi, 0, adi_len);

        //put all elements in the auth_data_item entry
        p = (char*) (adi + 1);

        adi->authenticate.s = p;
        adi->authenticate.len = authenticate.len;
        memcpy(p, authenticate.s, authenticate.len);
        p += authenticate.len;

        adi->authorization.s = p;
        adi->authorization.len = authorization2.len;
        memcpy(p, authorization2.s, authorization2.len);
        p += authorization2.len;

        adi->auth_scheme.s = p;
        adi->auth_scheme.len = algorithm.len;
        memcpy(p, algorithm.s, algorithm.len);
        p += algorithm.len;

        adi->ck.s = p;
        adi->ck.len = ck.len;
        memcpy(p, ck.s, ck.len);
        p += ck.len;

        adi->ik.s = p;
        adi->ik.len = ik.len;
        memcpy(p, ik.s, ik.len);
        p += ik.len;

        adi->ip.s = p;
        adi->ip.len = ip.len;
        memcpy(p, ip.s, ip.len);
        p += ip.len;

        adi->ha1.s = p;
        adi->ha1.len = ha1.len;
        memcpy(p, ha1.s, ha1.len);
        p += ha1.len;

        adi->line_identifier.s = p;
        adi->line_identifier.len = line_identifier.len;
        memcpy(p, line_identifier.s, line_identifier.len);
        p += line_identifier.len;

        adi->response_auth.s = p;
        adi->response_auth.len = response_auth.len;
        memcpy(p, response_auth.s, response_auth.len);
        p += response_auth.len;

        adi->digest_realm.s = p;
        adi->digest_realm.len = digest_realm.len;
        memcpy(p, digest_realm.s, digest_realm.len);
        p += digest_realm.len;

        if (p != (((char*) adi) + adi_len)) {
            LM_CRIT("buffer overflow\n");
            shm_free(adi);
            adi = 0;
            result = CSCF_RETURN_ERROR;
            goto done;
        }
        auth_data->code = -auth_data->code;
        adi->item_number = item_number;

        int len = sizeof (struct auth_data_item_list);
        adi_list = (struct auth_data_item_list*) shm_malloc(len);
        memset(adi_list, 0, len);

        if (adi_list->first == 0) {
            adi_list->first = adi_list->last = adi;
        } else {
            adi_list->last->next = adi;
            adi->previous = adi_list->last;
            adi_list->last = adi;
        }
    }

    if (!(rc) && !(experimental_rc)) {
        stateful_request_reply_async(t, t->uas.request, 480, MSG_480_DIAMETER_MISSING_AVP);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    switch (rc) {
        case -1:
            switch (experimental_rc) {
                case RC_IMS_DIAMETER_ERROR_USER_UNKNOWN:
                    stateful_request_reply_async(t, t->uas.request, 403, MSG_403_USER_UNKNOWN);
                    result = CSCF_RETURN_FALSE;
                    break;
                case RC_IMS_DIAMETER_ERROR_IDENTITIES_DONT_MATCH:
                    stateful_request_reply_async(t, t->uas.request, 403, MSG_403_IDENTITIES_DONT_MATCH);
                    result = CSCF_RETURN_FALSE;
                    break;
                case RC_IMS_DIAMETER_ERROR_AUTH_SCHEME_NOT_SUPPORTED:
                    stateful_request_reply_async(t, t->uas.request, 403, MSG_403_AUTH_SCHEME_UNSOPPORTED);
                    result = CSCF_RETURN_FALSE;
                    break;

                default:
                    stateful_request_reply_async(t, t->uas.request, 403, MSG_403_UNKOWN_EXPERIMENTAL_RC);
                    result = CSCF_RETURN_FALSE;
            }
            break;

        case AAA_UNABLE_TO_COMPLY:
            stateful_request_reply_async(t, t->uas.request, 403, MSG_403_UNABLE_TO_COMPLY);
            result = CSCF_RETURN_FALSE;
            break;

        case AAA_SUCCESS:
            goto success;
            break;

        default:
            stateful_request_reply_async(t, t->uas.request, 403, MSG_403_UNKOWN_RC);
            result = CSCF_RETURN_FALSE;
    }

    goto done;

success:

    if (!sip_number_auth_items) {
        stateful_request_reply_async(t, t->uas.request, 403, MSG_403_NO_AUTH_DATA);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    avlist = shm_malloc(sizeof (auth_vector *) * sip_number_auth_items);
    if (!avlist) {
        stateful_request_reply_async(t, t->uas.request, 403, MSG_480_HSS_ERROR);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    sip_number_auth_items = 0;

    struct auth_data_item *tmp;
    tmp = adi_list->first;

    while (tmp) {

        if (tmp->ip.len)
            av = new_auth_vector(tmp->item_number, tmp->auth_scheme, empty_s,
                tmp->ip, empty_s, empty_s);
        else if (tmp->line_identifier.len)
            av = new_auth_vector(tmp->item_number, tmp->auth_scheme, empty_s,
                line_identifier, empty_s, empty_s);
        else if (tmp->ha1.len) {
            if (tmp->response_auth.len) //HSS check
            {
                memset(ha1_hex, 0, HASHHEXLEN + 1);
                memcpy(ha1_hex, tmp->ha1.s,
                        tmp->ha1.len > HASHHEXLEN ? 32 : tmp->ha1.len);

                etsi_nonce.len = tmp->authenticate.len / 2;
                etsi_nonce.s = pkg_malloc(etsi_nonce.len);
                if (!etsi_nonce.s) {
                    LM_ERR("error allocating %d bytes\n", etsi_nonce.len);
                    goto done;
                }
                etsi_nonce.len = base16_to_bin(tmp->authenticate.s,
                        tmp->authenticate.len, etsi_nonce.s);

                calc_response(ha1_hex, &etsi_nonce, &empty_s, &empty_s,
                        &empty_s, 0, &(t->uas.request->first_line.u.request.method),
                        &scscf_name_str, 0, result_hex);
                pkg_free(etsi_nonce.s);

                if (!tmp->response_auth.len == 32
                        || strncasecmp(tmp->response_auth.s, result_hex, 32)) {
                    LM_ERR("The HSS' Response-Auth is different from what we compute locally!\n"
                            " BUT! If you sent an MAR with auth scheme unknown (HSS-Selected Authentication), this is normal.\n"
                            "HA1=\t|%s|\nNonce=\t|%.*s|\nMethod=\t|%.*s|\nuri=\t|%.*s|\nxresHSS=\t|%.*s|\nxresSCSCF=\t|%s|\n",
                            ha1_hex,
                            tmp->authenticate.len, tmp->authenticate.s,
                            t->uas.request->first_line.u.request.method.len, t->uas.request->first_line.u.request.method.s,
                            scscf_name_str.len, scscf_name_str.s,
                            tmp->response_auth.len, tmp->response_auth.s,
                            result_hex);
                    //stateful_register_reply(msg,514,MSG_514_HSS_AUTH_FAILURE);
                    //goto done;
                }
            }
            av = new_auth_vector(tmp->item_number, tmp->auth_scheme,
                    tmp->authenticate, tmp->ha1, empty_s, empty_s);
        } else
            av = new_auth_vector(tmp->item_number, tmp->auth_scheme,
                tmp->authenticate, tmp->authorization, tmp->ck, tmp->ik);

        if (sip_number_auth_items == 0)
            avlist[sip_number_auth_items++] = av;
        else {
            i = sip_number_auth_items;
            while (i > 0 && avlist[i - 1]->item_number > av->item_number)
                i--;
            for (j = sip_number_auth_items; j > i; j--)
                avlist[j] = avlist[j - 1];
            avlist[i] = av;
            sip_number_auth_items++;
        }

        //TODO need to confirm that removing this has done no problems
        //tmp->auth_data->code = -tmp->auth_data->code;

	LM_DBG("Added new auth-vector.\n");

        tmp = tmp->next;
    }

    //MAA returns a whole list of av! Which should we use?
    //right now we take the first and put the rest in the AV queue
    //then we use the first one and then add it to the queue as sent!

    for (i = 1; i < sip_number_auth_items; i++)
        if (!add_auth_vector(private_identity, public_identity, avlist[i]))
            free_auth_vector(avlist[i]);

    if (!pack_challenge(t->uas.request, data->realm, avlist[0], data->is_proxy_auth)) {
        stateful_request_reply_async(t, t->uas.request, 500, MSG_500_PACK_AV);
        result = CSCF_RETURN_FALSE;
        goto done;
    }

    if (data->is_proxy_auth)
        stateful_request_reply_async(t, t->uas.request, 407, MSG_407_CHALLENGE);
    else
        stateful_request_reply_async(t, t->uas.request, 401, MSG_401_CHALLENGE);

done:
    if (avlist) {
        start_reg_await_timer(avlist[0]); //start the timer to remove stale or unused Auth Vectors

        //now we add it to the queue as sent as we have already sent the challenge and used it and set the status to SENT
        if (!add_auth_vector(private_identity, public_identity, avlist[0]))
            free_auth_vector(avlist[0]);
    }

    //free memory
    if (maa) cdpb.AAAFreeMessage(&maa);
    if (avlist) {
        shm_free(avlist);
        avlist = 0;
    }

    if (adi_list) {
        struct auth_data_item *tmp1 = adi_list->first;
        while (tmp1) {
            struct auth_data_item *tmp2 = tmp1->next;
            shm_free(tmp1);
            tmp1 = tmp2;
        }
        shm_free(adi_list);
        adi_list = 0;
    }

    LM_DBG("DBG:UAR Async CDP callback: ... Done resuming transaction\n");
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_URI, &t->uri_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_URI, &t->uri_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_USER, &t->user_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_USER, &t->user_avps_to);
    set_avp_list(AVP_TRACK_FROM | AVP_CLASS_DOMAIN, &t->domain_avps_from);
    set_avp_list(AVP_TRACK_TO | AVP_CLASS_DOMAIN, &t->domain_avps_to);

    //make sure we delete any private lumps we created
    create_return_code(result);
    if (t) {
        del_nonshm_lump_rpl(&t->uas.request->reply_lump);
        tmb.unref_cell(t);
    }
    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_transaction_data(data);
    return;

error:
    //don't need to set result code as by default it is ERROR!

    if (t) {
        del_nonshm_lump_rpl(&t->uas.request->reply_lump);
        tmb.unref_cell(t);
    }
    tmb.t_continue(data->tindex, data->tlabel, data->act);
    free_saved_transaction_data(data);
}
/***
void CPocketSMDlg::OnButtonDeleteContact() 
{
	// TODO: Add your control notification handler code here
	int nIndex = m_ctlComboTo.GetCurSel();	
	if(nIndex == CB_ERR)
	{
		AfxMessageBox(_T("No contact selected from the list."));
		return;
	}

	if(m_ctlComboTo.DeleteString(nIndex) == CB_ERR)
	{
		AfxMessageBox(_T("The contact could not be deleted."));
		return;
	}
	m_ctlComboTo.SetCurSel(0);
	
}
***/
int CPocketSMDlg::computeAuthHeader( CString sipRepl )
{
	CString  wwwAuth;
	CString  authHdr;
	CString  newSipReq;
	int h,t,l,n;
	int quote;
	CString  s;
	CString strTmp;
	CString  par;
	CString  cnonce = "SAIDF3W2R8FAETR329FAHSDF34";
	/* header params */
	CString  param[]={"realm","nonce","opaque","algorithm","qop","stale"};
	CString  vals[]={"","","","","",""};
	CString  strURI = "sip:";
	int     quoted[]={1,1,1,0,1,0};
	HASHHEX hashHex1;
	HASHHEX hashHex2;
	str strMethod = {"REGISTER", 8};
	char userBuf[30], passwdBuf[30], nonceBuf[50], cnonceBuf[50], uriBuf[50], realmBuf[50];
	str sUser = {userBuf, 30}, sPasswd = {passwdBuf, 30}, sRealm = {realmBuf, 50},
		sNonce = {nonceBuf, 50}, sCnonce = {cnonceBuf, 50}, sURI = {uriBuf, 50};

	m_strAuthHdr = "";
	strURI += m_strSrvPart;

	//AddInfoMessage(sipRepl);
	//UpdateDisplayedMessage();

	/* get the www-auth header from reply */
	h = sipRepl.Find(_T("WWW-Authenticate"));
	if (h==-1)
		return -1;

	strTmp = sipRepl.Right(sipRepl.GetLength()-h);
	t = strTmp.Find('\n');
	if(strTmp.GetAt(t-1) == '\r')
		t--;
	wwwAuth = sipRepl.Mid(h,t);

	/* parse the www_auth header */
	s = wwwAuth;
	h = s.Find(_T("Digest"));
	if (h==-1)
		return -2;
	h += 6;
	/* comput the length of useful part */
	l = s.GetLength();
	while (s.GetAt(l-1)=='\n' || s.GetAt(l-1)=='\r')
		l--;
	/* look for all the params */
	while(h<l) {
		/* search the begining of the next param */
		while( h<l && (s.GetAt(h)==' ' || s.GetAt(h)=='\t') )
			h++;
		if (h==l)
			return -3;
		/* get the param name */
		t = h;
		while( t<l && s.GetAt(t)!=' ' && s.GetAt(t)!='=')
			t++;
		if (t==l || t==h)
			return -4;
		par = s.Mid(h,t-h);
		h=t;
		/* are we looking for this parameter? */
		for(n=0; n<6; n++)
			if(!param[n].CompareNoCase(par))
				break;
		if(n==6)
			n = -1;

		/* eat spaces */
		while( h<l && (s.GetAt(h)==' ' || s.GetAt(h)=='\t') )
			h++;
		/* do we have a "="? */
		if (h==l || s.GetAt(h)!='=' || ++h==l)
			return -5;
		/* eat spaces */
		while( h<l && (s.GetAt(h)==' ' || s.GetAt(h)=='\t') )
			h++;
		/* param's value */
		if ( n!=-1 && ( (quoted[n]==1 && s.GetAt(h)!='"') ||
			(quoted[n]==0 && s.GetAt(h)=='"')) )
			return -6;
		if(n!=-1 && quoted[n]==1)
			h++;
		quote=(n==-1&&s.GetAt(h)=='"')||(n!=-1&&quoted[n]==1)?1:0;
		/* look for the end of value */
		t = h;
		while( t<l && (quote && s.GetAt(t)!='"' ||
			!quote && s.GetAt(t)!=' ' && s.GetAt(t)!=',') )
			t++;
		if (t==h)
			return -7;
		if (n!=-1) {
			vals[n] = s.Mid(h,t-h);
		}
		h = t + (quote?1:0);
		/* eat spaces */
		while( h<l && (s.GetAt(h)==' ' || s.GetAt(h)=='\t') )
			h++;
		if (h==l)  break;
		/* here must be a ',' */
		if (s.GetAt(h)!=',' || ++h==l)
			return -8;
	}
	/* some checkings */
	if (vals[0]=="")
		return -9;
	if (vals[1]=="")
		return -10;
	/* comput the authentication */
	translateToStr(m_strUserPart, &sUser);
	translateToStr(m_strPassword, &sPasswd);
	translateToStr(vals[0], &sRealm);
	translateToStr(vals[1], &sNonce);
	translateToStr(cnonce, &sCnonce);
	translateToStr(strURI, &sURI);

	calc_HA1(HA_MD5, &sUser, &sRealm, &sPasswd, &sNonce, &sCnonce, hashHex1);

	calc_response(hashHex1, &sNonce, NULL, &sCnonce, NULL, 0, &strMethod, &sURI, NULL, hashHex2);

	/* build authorization header */
	m_strAuthHdr = "Authorization: Digest";
	/* add username */
	m_strAuthHdr += " username=\""+m_strUserPart+"\"";
	/* add realm */
	m_strAuthHdr += ", realm=\""+vals[0]+"\"";
	/* add uri */
	m_strAuthHdr += ", uri=\"";
	m_strAuthHdr += strURI;
	m_strAuthHdr += "\"";
	/* add algorithm */
	if(vals[3].GetLength() > 0)
		m_strAuthHdr += ", algorithm=\""+vals[3]+"\"";
	else
		m_strAuthHdr += ", algorithm=\"md5\"";
	/* add nonce */
	m_strAuthHdr += ", nonce=\""+vals[1]+"\"";
	/* add opaque, if needed */
	if (vals[2]!="")
		m_strAuthHdr += ", opaque=\""+vals[2]+"\"";
	/* add qop, if needed */
	if (vals[4]!="") {
		m_strAuthHdr += ", qop=\""+vals[4]+"\"";
		m_strAuthHdr += ", cnonce=\""+cnonce+"\"";
	}
	/* add response */
	m_strAuthHdr += ", response=\"";
	m_strAuthHdr += hashHex2;
	m_strAuthHdr += "\"";
	return 0;
}