예제 #1
0
/*
 * Check from Radius if request URI belongs to a local user.
 * User-Name is user@host of request Uri and Service-Type is Call-Check.
 */
int radius_does_uri_exist(struct sip_msg* _m, char* _s1, char* _s2)
{
	static char msg[4096];
	VALUE_PAIR *send, *received;
	UINT4 service;
	char* at, *uri;

	send = received = 0;

	if (parse_sip_msg_uri(_m) < 0) {
		LM_ERR("parsing URI failed\n");
		return -1;
	}
	
	uri = (char*)pkg_malloc(_m->parsed_uri.user.len + _m->parsed_uri.host.len + 2);
	if (!uri) {
		LM_ERR("no more pkg memory\n");
		return -2;
	}

	at = uri;
	memcpy(at, _m->parsed_uri.user.s, _m->parsed_uri.user.len);
	at += _m->parsed_uri.user.len;
	*at = '@';
	at++;
	memcpy(at , _m->parsed_uri.host.s, _m->parsed_uri.host.len);
	at += _m->parsed_uri.host.len;
	*at = '\0';

	if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, uri, -1, 0)) {
		LM_ERR("adding User-Name failed\n");
		rc_avpair_free(send);
		pkg_free(uri);
	 	return -3;
	}

	service = vals[V_CALL_CHECK].v;
	if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) {
		LM_ERR("adding service type failed\n");
		rc_avpair_free(send);
		pkg_free(uri);
	 	return -4;  	
	}
	
	if (rc_auth(rh, 0, send, &received, msg) == OK_RC) {
		LM_DBG("success\n");
		rc_avpair_free(send);
		generate_avps(received);
		rc_avpair_free(received);
		pkg_free(uri);
		return 1;
	} else {
		LM_DBG("failure\n");
		rc_avpair_free(send);
		rc_avpair_free(received);
		pkg_free(uri);
		return -5;
	}
}
예제 #2
0
파일: avp_radius.c 프로젝트: asyn/openvims
static int load_user_attrs(struct sip_msg* msg, unsigned long flags, fparam_t* fp)
{
    static char rad_msg[4096];
    str uid;
    UINT4 service;
    VALUE_PAIR* send, *received;

    send = NULL;
    received = NULL;

    if (get_str_fparam(&uid, msg, (fparam_t*)fp) < 0) {
	ERR("Unable to get UID\n");
	return -1;
    }

    service = vals[V_GET_USER_ATTRS].v;

    if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_USER_NAME].v), 
		       uid.s, uid.len,
		       VENDOR(attrs[A_USER_NAME].v))) {
	ERR("Error while adding A_USER_NAME\n");
	goto error;
    }
    
    if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_SERVICE_TYPE].v), 
		       &vals[V_GET_USER_ATTRS].v, -1, 
		       VENDOR(attrs[A_SER_SERVICE_TYPE].v))) {
	ERR("Error adding A_SERVICE_TYPE\n");
	goto error;
    }


    if (rc_auth(rh, 0, send, &received, rad_msg) != OK_RC) {
	DBG("load_user_attrs: Failure\n");
	goto error;
    }

    DBG("load_user_attrs: Success\n");
    rc_avpair_free(send);

    if (generate_avps(flags, received) < 0) {
	rc_avpair_free(received);
	goto error;
    }

    rc_avpair_free(received);
    return 1;

 error:
    if (send) rc_avpair_free(send);
    if (received) rc_avpair_free(send);
    return -1;
}
예제 #3
0
파일: functions.c 프로젝트: halan/kamailio
/*
 * Check from Radius if URI user given as argument belongs to a local user.
 * If so, loads AVPs based on reply items returned from Radius.
 */
int radius_does_uri_user_exist(struct sip_msg* _m, str user)
{
    static char msg[4096];
    VALUE_PAIR *send, *received;
    uint32_t service;
    int res, extra_cnt, offset, i;
    
    send = received = 0;
    
    if (!rc_avpair_add(rh, &send, uri_attrs[SA_USER_NAME].v,
		       user.s, user.len, 0)) {
	LM_ERR("in adding SA_USER_NAME\n");
	return -1;
    }
    
    service = uri_vals[UV_CALL_CHECK].v;
    if (!rc_avpair_add(rh, &send, uri_attrs[SA_SERVICE_TYPE].v,
		       &service, -1, 0)) {
	LM_ERR("in adding SA_SERVICE_TYPE <%u>\n", service);
	goto error;
    }

    /* Add extra attributes */
    extra_cnt = extra2strar(uri_extra, _m, val_arr);
    if (extra_cnt == -1) {
	LM_ERR("in getting values of group extra attributes\n");
	goto error;
    }
    offset = SA_STATIC_MAX;
    for (i = 0; i < extra_cnt; i++) {
	if (val_arr[i].len == -1) {
	    /* Add integer attribute */
	    ADD_EXTRA_AVPAIR(uri_attrs, offset+i,
			     &(val_arr[i].s), val_arr[i].len );
	} else {
	    /* Add string attribute */
	    ADD_EXTRA_AVPAIR(uri_attrs, offset+i,
			     val_arr[i].s, val_arr[i].len );
	}
    }

    if ((res = rc_auth(rh, 0, send, &received, msg)) == OK_RC) {
	LM_DBG("success\n");
	rc_avpair_free(send);
	generate_avps(uri_attrs, received);
	rc_avpair_free(received);
	return 1;
    } else {
	rc_avpair_free(send);
	rc_avpair_free(received);
#ifdef REJECT_RC
	if (res == REJECT_RC) {
	    LM_DBG("rejected\n");
	    return -1;
	} else {
	    LM_ERR("failure\n");
	    return -2;
	}
#else
	LM_DBG("failure\n");
	return -1;
#endif
    }

 error:
    rc_avpair_free(send);
    return -1;
}
예제 #4
0
파일: functions.c 프로젝트: halan/kamailio
/*
 * Check from Radius if URI, whose user and host parts are given as
 * arguments, exists.  If so, loads AVPs based on reply items returned
 * from Radius.  If use_sip_uri_host module parameter has non-zero value,
 * user is send in SA_USER_NAME attribute and host in SA_SIP_URI_HOST
 * attribute.  If is has zero value, user@host is send in SA_USER_NAME
 * attribute.
 */
int radius_does_uri_user_host_exist(struct sip_msg* _m, str user, str host)
{
    char* at, *user_host;
    VALUE_PAIR *send, *received;
    uint32_t service;
    static char msg[4096];
    int extra_cnt, offset, i, res;

    send = received = 0;
    user_host = 0;

    if (!use_sip_uri_host) {

	/* Send user@host in SA_USER_NAME attr */
	user_host = (char*)pkg_malloc(user.len + host.len + 2);
	if (!user_host) {
	    LM_ERR("no more pkg memory\n");
	    return -1;
	}
	at = user_host;
	memcpy(at, user.s, user.len);
	at += user.len;
	*at = '@';
	at++;
	memcpy(at , host.s, host.len);
	at += host.len;
	*at = '\0';
	if (!rc_avpair_add(rh, &send, uri_attrs[SA_USER_NAME].v, user_host,
			   -1, 0)) {
	    LM_ERR("in adding SA_USER_NAME\n");
	    pkg_free(user_host);
	    return -1;
	}

    } else {

	/* Send user in SA_USER_NAME attribute and host in SA_SIP_URI_HOST
          attribute */
	if (!rc_avpair_add(rh, &send, uri_attrs[SA_USER_NAME].v,
			   user.s, user.len, 0)) {
	    LM_ERR("adding User-Name failed\n");
	    return -1;
	}
	if (!rc_avpair_add(rh, &send, uri_attrs[SA_SIP_URI_HOST].v,
			   host.s, host.len, 0)) {
	    LM_ERR("adding SIP-URI-Host failed\n");
	    goto error;
	}
    }

    service = uri_vals[UV_CALL_CHECK].v;
    if (!rc_avpair_add(rh, &send, uri_attrs[SA_SERVICE_TYPE].v,
		       &service, -1, 0)) {
	LM_ERR("in adding SA_SERVICE_TYPE <%u>\n", service);
	goto error;
    }

    /* Add extra attributes */
    extra_cnt = extra2strar(uri_extra, _m, val_arr);
    if (extra_cnt == -1) {
	LM_ERR("in getting values of group extra attributes\n");
	goto error;
    }
    offset = SA_STATIC_MAX;
    for (i = 0; i < extra_cnt; i++) {
	if (val_arr[i].len == -1) {
	    /* Add integer attribute */
	    ADD_EXTRA_AVPAIR(uri_attrs, offset+i,
			     &(val_arr[i].s), val_arr[i].len );
	} else {
	    /* Add string attribute */
	    ADD_EXTRA_AVPAIR(uri_attrs, offset+i,
			     val_arr[i].s, val_arr[i].len );
	}
    }

    if ((res = rc_auth(rh, 0, send, &received, msg)) == OK_RC) {
	LM_DBG("success\n");
	if (user_host) pkg_free(user_host);
	rc_avpair_free(send);
	generate_avps(uri_attrs, received);
	rc_avpair_free(received);
	return 1;
    } else {
	if (user_host) pkg_free(user_host);
	rc_avpair_free(send);
	rc_avpair_free(received);
#ifdef REJECT_RC
	if (res == REJECT_RC) {
	    LM_DBG("rejected\n");
	    return -1;
	} else {
	    LM_ERR("failure\n");
	    return -2;
	}
#else
	LM_DBG("failure\n");
	return -1;
#endif
    }

 error:
    rc_avpair_free(send);
    if (user_host) pkg_free(user_host);
    return -1;
}
예제 #5
0
파일: functions.c 프로젝트: halan/kamailio
/*
 * Check from Radius if a user belongs to a group. User-Name is given in
 * first string argment that may contain pseudo variables.  SIP-Group is
 * given in second string variable that may not contain pseudo variables.
 * Service-Type is Group-Check.
 */
int radius_is_user_in(struct sip_msg* _m, char* _user, char* _group)
{
    str user, *group;
    VALUE_PAIR *send, *received;
    uint32_t service;
    static char msg[4096];
    int extra_cnt, offset, i, res;

    send = received = 0;

    if ((_user == NULL) ||
	(fixup_get_svalue(_m, (gparam_p)_user, &user) != 0)) {
	LM_ERR("invalid user parameter");
	return -1;
    }

    if (!rc_avpair_add(rh, &send, group_attrs[SA_USER_NAME].v,
		       user.s, user.len, 0)) {
	LM_ERR("in adding SA_USER_NAME\n");
	return -1;
    }

    group = (str*)_group;
    if ((group == NULL) || (group->len == 0)) {
	LM_ERR("invalid group parameter");
	goto error;
    }
    if (!rc_avpair_add(rh, &send, group_attrs[SA_SIP_GROUP].v,
		       group->s, group->len, 0)) {
	LM_ERR("in adding SA_SIP_GROUP\n");
	goto error;
    }

    service = group_vals[GV_GROUP_CHECK].v;
    if (!rc_avpair_add(rh, &send, group_attrs[SA_SERVICE_TYPE].v,
		       &service, -1, 0)) {
	LM_ERR("in adding SA_SERVICE_TYPE <%u>\n", service);
	goto error;
    }

    /* Add extra attributes */
    extra_cnt = extra2strar(group_extra, _m, val_arr);
    if (extra_cnt == -1) {
	LM_ERR("in getting values of group extra attributes\n");
	goto error;
    }
    offset = SA_STATIC_MAX;
    for (i = 0; i < extra_cnt; i++) {
	if (val_arr[i].len == -1) {
	    /* Add integer attribute */
	    ADD_EXTRA_AVPAIR(group_attrs, offset+i,
			     &(val_arr[i].s), val_arr[i].len );
	} else {
	    /* Add string attribute */
	    ADD_EXTRA_AVPAIR(group_attrs, offset+i,
			     val_arr[i].s, val_arr[i].len );
	}
    }

    if ((res = rc_auth(rh, 0, send, &received, msg)) == OK_RC) {
	LM_DBG("success\n");
	rc_avpair_free(send);
	generate_avps(group_attrs, received);
	rc_avpair_free(received);
	return 1;
    } else {
	rc_avpair_free(send);
	rc_avpair_free(received);
#ifdef REJECT_RC
	if (res == REJECT_RC) {
	    LM_DBG("rejected\n");
	    return -1;
	} else {
	    LM_ERR("failure\n");
	    return -2;
	}
#else
	LM_DBG("failure\n");
	return -1;
#endif
    }

 error:
    rc_avpair_free(send);
    return -1;
}
예제 #6
0
파일: functions.c 프로젝트: halan/kamailio
/*
 * Loads from Radius callee's AVPs based on pvar argument.
 * Returns 1 if Radius request succeeded and -1 otherwise.
 */
int radius_load_callee_avps(struct sip_msg* _m, char* _callee, char* _s2)
{
    str user;
    VALUE_PAIR *send, *received;
    uint32_t service;
    static char msg[4096];
    int extra_cnt, offset, i, res;

    send = received = 0;

    if ((_callee == NULL) ||
	(fixup_get_svalue(_m, (gparam_p)_callee, &user) != 0)) {
	LM_ERR("invalid callee parameter");
	return -1;
    }

    if (!rc_avpair_add(rh, &send, callee_attrs[SA_USER_NAME].v,
		       user.s, user.len, 0)) {
	LM_ERR("in adding SA_USER_NAME\n");
	return -1;
    }

    service = callee_vals[EV_SIP_CALLEE_AVPS].v;
    if (!rc_avpair_add(rh, &send, callee_attrs[SA_SERVICE_TYPE].v,
		       &service, -1, 0)) {
	LM_ERR("in adding SA_SERVICE_TYPE <%u>\n", service);
	goto error;
    }

    /* Add extra attributes */
    extra_cnt = extra2strar(callee_extra, _m, val_arr);
    if (extra_cnt == -1) {
	LM_ERR("in getting values of callee extra attributes\n");
	goto error;
    }
    offset = SA_STATIC_MAX;
    for (i = 0; i < extra_cnt; i++) {
	if (val_arr[i].len == -1) {
	    /* Add integer attribute */
	    ADD_EXTRA_AVPAIR(callee_attrs, offset+i,
			     &(val_arr[i].s), val_arr[i].len );
	} else {
	    /* Add string attribute */
	    ADD_EXTRA_AVPAIR(callee_attrs, offset+i,
			     val_arr[i].s, val_arr[i].len );
	}
    }

    if ((res = rc_auth(rh, 0, send, &received, msg)) == OK_RC) {
	LM_DBG("success\n");
	rc_avpair_free(send);
	generate_avps(callee_attrs, received);
	rc_avpair_free(received);
	return 1;
    } else {
	rc_avpair_free(send);
	rc_avpair_free(received);
#ifdef REJECT_RC
	if (res == REJECT_RC) {
	    LM_DBG("rejected\n");
	    return -1;
	} else {
	    LM_ERR("failure\n");
	    return -2;
	}
#else
	LM_DBG("failure\n");
	return -1;
#endif
    }

 error:
    rc_avpair_free(send);
    return -1;
}
예제 #7
0
파일: avp_radius.c 프로젝트: asyn/openvims
static int load_uri_attrs(struct sip_msg* msg, unsigned long flags, fparam_t* fp)
{
    static char rad_msg[4096];
    struct sip_uri puri;
    str uri, did, scheme;
    UINT4 service;
    VALUE_PAIR* send, *received;

    send = NULL;
    received = NULL;

    if (get_str_fparam(&uri, msg, (fparam_t*)fp) != 0) {
	ERR("Unable to get URI\n");
	return -1;
    }

    if (parse_uri(uri.s, uri.len, &puri) < 0) {
	ERR("Error while parsing URI '%.*s'\n", uri.len, uri.s);
	return -1;
    }

    if (puri.host.len) {
	/* domain name is present */
	if (dm_get_did(&did, &puri.host) < 0) {
		DBG("Cannot lookup DID for domain %.*s, using default value\n", puri.host.len, ZSW(puri.host.s));
		did.s = DEFAULT_DID;
		did.len = sizeof(DEFAULT_DID) - 1;
	}
    } else {
	/* domain name is missing -- can be caused by tel: URI */
	DBG("There is no domain name, using default value\n");
	did.s = DEFAULT_DID;
	did.len = sizeof(DEFAULT_DID) - 1;
    }

    uri_type_to_str(puri.type, &scheme);
    service = vals[V_GET_URI_ATTRS].v;

    if (scheme.len) {
	if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_URI_SCHEME].v), 
			   scheme.s, scheme.len,
			   VENDOR(attrs[A_SER_URI_SCHEME].v))) {
	    ERR("Error while adding A_SER_URI_SCHEME\n");
	    goto error;
	}
    }

    if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_USER_NAME].v), 
		       puri.user.s, puri.user.len,
		       VENDOR(attrs[A_USER_NAME].v))) {
	ERR("Error while adding A_USER_NAME\n");
	goto error;
    }

    if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_DID].v), 
		       did.s, did.len,
		       VENDOR(attrs[A_SER_DID].v))) {
	ERR("Error while adding A_SER_DID\n");
	goto error;
    }
    
    if (!rc_avpair_add(rh, &send, ATTRID(attrs[A_SER_SERVICE_TYPE].v), 
		       &vals[V_GET_URI_ATTRS].v, -1,
		       VENDOR(attrs[A_SER_SERVICE_TYPE].v))) {
	ERR("Error adding A_SERVICE_TYPE\n");
	goto error;
    }

    if (rc_auth(rh, 0, send, &received, rad_msg) != OK_RC) {
	DBG("load_uri_attrs: Failure\n");
	goto error;
    }

    DBG("load_uri_attrs: Success\n");
    rc_avpair_free(send);

    if (generate_avps(flags, received) < 0) {
	rc_avpair_free(received);
	goto error;
    }

    rc_avpair_free(received);
    return 1;

 error:
    if (send) rc_avpair_free(send);
    if (received) rc_avpair_free(send);
    return -1;
}
예제 #8
0
/*
 * Authorize digest credentials
 */
static inline int digest_authenticate(struct sip_msg* msg, fparam_t* realm,
									char* tname, hdr_types_t hftype)
{
	char ha1[256];
	int res;
	struct hdr_field* h;
	auth_body_t* cred;
	str domain, table;
	db1_res_t* result = NULL;
	int ret;

	cred = 0;
	ret = AUTH_ERROR;

	if(!tname) {
		LM_ERR("invalid table parameter\n");
		return AUTH_ERROR;
	}

	table.s = tname;
	table.len = strlen(tname);

	if (get_str_fparam(&domain, msg, realm) < 0) {
		LM_ERR("failed to get realm value\n");
		goto end;
	}

	if (domain.len==0)
	{
		LM_ERR("invalid realm parameter - empty value\n");
		goto end;
	}
	LM_DBG("realm value [%.*s]\n", domain.len, domain.s);

	ret = auth_api.pre_auth(msg, &domain, hftype, &h, NULL);
	switch(ret) {
		case ERROR:
		case BAD_CREDENTIALS:
			LM_DBG("error or bad credentials\n");
			ret = AUTH_ERROR;
			goto end;
		case CREATE_CHALLENGE:
			LM_ERR("CREATE_CHALLENGE is not a valid state\n");
			ret = AUTH_ERROR;
			goto end;
		case DO_RESYNCHRONIZATION:
			LM_ERR("DO_RESYNCHRONIZATION is not a valid state\n");
			ret = AUTH_ERROR;
			goto end;
		case NOT_AUTHENTICATED:
			LM_DBG("not authenticated\n");
			ret = AUTH_ERROR;
			goto end;
		case DO_AUTHENTICATION:
			break;
		case AUTHENTICATED:
			ret = AUTH_OK;
			goto end;
	}

	cred = (auth_body_t*)h->parsed;

	res = get_ha1(&cred->digest.username, &domain, &table, ha1, &result);
	if (res < 0) {
		/* Error while accessing the database */
		ret = AUTH_ERROR;
		goto end;
	}
	if (res > 0) {
		/* Username not found in the database */
		ret = AUTH_USER_UNKNOWN;
		goto end;
	}

	/* Recalculate response, it must be same to authorize successfully */
	ret = auth_api.check_response(&(cred->digest),
				&msg->first_line.u.request.method, ha1);
	if(ret==AUTHENTICATED) {
		ret = AUTH_OK;
		switch(auth_api.post_auth(msg, h)) {
			case AUTHENTICATED:
				generate_avps(result);
				break;
			default:
				ret = AUTH_ERROR;
				break;
		}
	} else {
		if(ret==NOT_AUTHENTICATED)
			ret = AUTH_INVALID_PASSWORD;
		else
			ret = AUTH_ERROR;
	}

end:
	if(result)
		auth_dbf.free_result(auth_db_handle, result);
	return ret;
}
예제 #9
0
/*
 * Authorize digest credentials
 */
static inline int authenticate(struct sip_msg* msg, str* realm,
			       hdr_types_t hftype)
{
	int res;
	auth_result_t ret;
	struct hdr_field* h;
	auth_body_t* cred;
	str* uri;
	struct sip_uri puri;
	str user, did;
	VALUE_PAIR* received;

	cred = 0;
	ret = -1;
	user.s = 0;
	received = NULL;

	switch(auth_api.pre_auth(msg, realm, hftype, &h, NULL)) {
	default:
		BUG("unexpected reply '%d'.\n", auth_api.pre_auth(msg, realm, hftype,
				&h, NULL));
#ifdef EXTRA_DEBUG
		abort();
#endif
	case ERROR:
	case BAD_CREDENTIALS:
	    ret = -3;
	    goto end;

	case NOT_AUTHENTICATED:
	    ret = -1;
	    goto end;

	case DO_AUTHENTICATION:
	    break;

	case AUTHENTICATED:
	    ret = 1;
	    goto end;
	}

	cred = (auth_body_t*)h->parsed;

	if (use_did) {
	    if (msg->REQ_METHOD == METHOD_REGISTER) {
			ret = get_to_did(&did, msg);
	    } else {
			ret = get_from_did(&did, msg);
	    }
	    if (ret == 0) {
			did.s = DEFAULT_DID;
			did.len = sizeof(DEFAULT_DID) - 1;
	    }
	} else {
	    did.len = 0;
	    did.s = 0;
	}

	if (get_uri(msg, &uri) < 0) {
		LOG(L_ERR, "authorize(): From/To URI not found\n");
		ret = -1;
		goto end;
	}
	
	if (parse_uri(uri->s, uri->len, &puri) < 0) {
		LOG(L_ERR, "authorize(): Error while parsing From/To URI\n");
		ret = -1;
		goto end;
	}

	user.s = (char *)pkg_malloc(puri.user.len);
	if (user.s == NULL) {
		LOG(L_ERR, "authorize: No memory left\n");
		ret = -1;
		goto end;
	}
	un_escape(&(puri.user), &user);

	res = radius_authorize_sterman(&received, msg, &cred->digest, &msg->first_line.u.request.method, &user);
	if (res == 1) {
	    switch(auth_api.post_auth(msg, h)) {
	    case ERROR:             
	    case BAD_CREDENTIALS:
		ret = -2;
		break;

	    case NOT_AUTHENTICATED:
		ret = -1;
		break;

	    case AUTHENTICATED:
		if (generate_avps(received) < 0) {
		    ret = -1;
		    break;
		}
		ret = 1;
		break;

	    default:
		ret = -1;
		break;
	    }
	} else {
	    ret = -1;
	}

 end:
	if (received) rc_avpair_free(received);
	if (user.s) pkg_free(user.s);
	if (ret < 0) {
	    if (auth_api.build_challenge(msg, (cred ? cred->stale : 0), realm, NULL, NULL, hftype) < 0) {
		ERR("Error while creating challenge\n");
		ret = -2;
	    }
	}
	return ret;
}
예제 #10
0
/*
 * This function creates and submits radius authentication request as per
 * draft-sterman-aaa-sip-00.txt.  In addition, _user parameter is included
 * in the request as value of a SER specific attribute type SIP-URI-User,
 * which can be be used as a check item in the request.  Service type of
 * the request is Authenticate-Only.
 */
int radius_authorize_sterman(struct sip_msg* _msg, dig_cred_t* _cred, str* _method, str* _user) 
{
	static char msg[4096];
	VALUE_PAIR *send, *received;
	uint32_t service;
	str method, user, user_name;
	str *ruri;
	int extra_cnt, offset, i;
		
	send = received = 0;

	if (!(_cred && _method && _user)) {
		LM_ERR("invalid parameter value\n");
		return -1;
	}

	method = *_method;
	user = *_user;
	
	/*
	 * Add all the user digest parameters according to the qop defined.
	 * Most devices tested only offer support for the simplest digest.
	 */
	if (_cred->username.domain.len || !append_realm_to_username) {
		if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, _cred->username.whole.s, _cred->username.whole.len, 0)) {
			LM_ERR("unable to add User-Name attribute\n");
			goto err;
		}
	} else {
		user_name.len = _cred->username.user.len + _cred->realm.len + 1;
		user_name.s = pkg_malloc(user_name.len);
		if (!user_name.s) {
			LM_ERR("no pkg memory left\n");
			return -3;
		}
		memcpy(user_name.s, _cred->username.whole.s, _cred->username.whole.len);
		user_name.s[_cred->username.whole.len] = '@';
		memcpy(user_name.s + _cred->username.whole.len + 1, _cred->realm.s,
			_cred->realm.len);
		if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, user_name.s,
		user_name.len, 0)) {
			LM_ERR("unable to add User-Name attribute\n");
			pkg_free(user_name.s);
			goto err;
		}
		pkg_free(user_name.s);
	}

	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_USER_NAME].v, 
	_cred->username.whole.s, _cred->username.whole.len, 0)) {
		LM_ERR("unable to add Digest-User-Name attribute\n");
		goto err;
	}

	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_REALM].v, _cred->realm.s,
	_cred->realm.len, 0)) {
		LM_ERR("unable to add Digest-Realm attribute\n");
		goto err;
	}
	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE].v, _cred->nonce.s,
	_cred->nonce.len, 0)) {
		LM_ERR("unable to add Digest-Nonce attribute\n");
		goto err;
	}

	if (use_ruri_flag < 0 || isflagset(_msg, use_ruri_flag) != 1) {
		ruri = &_cred->uri;
	} else {
		ruri = GET_RURI(_msg);
	}
	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_URI].v, ruri->s,
	ruri->len, 0)) {
		LM_ERR("unable to add Digest-URI attribute\n");
		goto err;
	}

	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_METHOD].v, method.s,
	method.len, 0)) {
		LM_ERR("unable to add Digest-Method attribute\n");
		goto err;
	}
	
	/* 
	 * Add the additional authentication fields according to the QOP.
	 */
	if (_cred->qop.qop_parsed == QOP_AUTH) {
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_QOP].v, "auth", 4, 0)) {
			LM_ERR("unable to add Digest-QOP attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE_COUNT].v, 
		_cred->nc.s, _cred->nc.len, 0)) {
			LM_ERR("unable to add Digest-CNonce-Count attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_CNONCE].v, 
		_cred->cnonce.s, _cred->cnonce.len, 0)) {
			LM_ERR("unable to add Digest-CNonce attribute\n");
			goto err;
		}
	} else if (_cred->qop.qop_parsed == QOP_AUTHINT) {
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_QOP].v,
		"auth-int", 8, 0)) {
			LM_ERR("unable to add Digest-QOP attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_NONCE_COUNT].v,
		_cred->nc.s, _cred->nc.len, 0)) {
			LM_ERR("unable to add Digest-Nonce-Count attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_CNONCE].v,
		_cred->cnonce.s, _cred->cnonce.len, 0)) {
			LM_ERR("unable to add Digest-CNonce attribute\n");
			goto err;
		}
		if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_BODY_DIGEST].v, 
		_cred->opaque.s, _cred->opaque.len, 0)) {
			LM_ERR("unable to add Digest-Body-Digest attribute\n");
			goto err;
		}
		
	} else  {
		/* send nothing for qop == "" */
	}

	/* Add the response... What to calculate against... */
	if (!rc_avpair_add(rh, &send, attrs[A_DIGEST_RESPONSE].v, 
	_cred->response.s, _cred->response.len, 0)) {
		LM_ERR("unable to add Digest-Response attribute\n");
		goto err;
	}

	/* Indicate the service type, Authenticate only in our case */
	service = vals[V_SIP_SESSION].v;
	if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) {
		LM_ERR("unable to add Service-Type attribute\n");
		goto err;
	}

	/* Add SIP URI as a check item */
	if (!rc_avpair_add(rh,&send,attrs[A_SIP_URI_USER].v,user.s,user.len,0)) {
		LM_ERR("unable to add Sip-URI-User attribute\n");
		goto err;
	}

	if (attrs[A_CISCO_AVPAIR].n != NULL) {
		if (add_cisco_vsa(&send, _msg)) {
			goto err;
		}
	}

	/* Add extra attributes */
	extra_cnt = extra2strar(auth_extra, _msg, val_arr);
	if (extra_cnt == -1) {
	    LM_ERR("in getting values of extra attributes\n");
	    goto err;
	}
	offset = A_MAX;
	for (i = 0; i < extra_cnt; i++) {
	    if (val_arr[i].len == -1) {
		/* Add integer attribute */
		ADD_EXTRA_AVPAIR(attrs, offset+i,
				 &(val_arr[i].s), val_arr[i].len );
	    } else {
		/* Add string attribute */
		ADD_EXTRA_AVPAIR(attrs, offset+i,
				 val_arr[i].s, val_arr[i].len );
	    }
	}

	/* Send request */
	if ((i = rc_auth(rh, SIP_PORT, send, &received, msg)) == OK_RC) {
		LM_DBG("Success\n");
		rc_avpair_free(send);
		send = 0;

		generate_avps(received);

		rc_avpair_free(received);
		return 1;
	} else {
#ifdef REJECT_RC
                if (i == REJECT_RC) {
                        LM_DBG("Failure\n");
                        goto err;
                }
#endif 
		LM_ERR("authorization failed. RC auth returned %d\n", i);
	}

 err:
	if (send) rc_avpair_free(send);
	if (received) rc_avpair_free(received);
	return -1;
}
예제 #11
0
/*
 * Authorize digest credentials and set the pointer to used hdr
 */
static int digest_authenticate_hdr(sip_msg_t* msg, str *realm,
				str *table, hdr_types_t hftype, str *method, hdr_field_t **ahdr)
{
	char ha1[256];
	int res;
	struct hdr_field* h;
	auth_body_t* cred;
	db1_res_t* result = NULL;
	int ret;

	cred = 0;
	ret = AUTH_ERROR;

	ret = auth_api.pre_auth(msg, realm, hftype, &h, NULL);
	switch(ret) {
		case NONCE_REUSED:
			LM_DBG("nonce reused");
			ret = AUTH_NONCE_REUSED;
			goto end;
		case STALE_NONCE:
			LM_DBG("stale nonce\n");
			ret = AUTH_STALE_NONCE;
			goto end;
		case NO_CREDENTIALS:
			LM_DBG("no credentials\n");
			ret = AUTH_NO_CREDENTIALS;
			goto end;
		case ERROR:
		case BAD_CREDENTIALS:
			LM_DBG("error or bad credentials\n");
			ret = AUTH_ERROR;
			goto end;
		case CREATE_CHALLENGE:
			LM_ERR("CREATE_CHALLENGE is not a valid state\n");
			ret = AUTH_ERROR;
			goto end;
		case DO_RESYNCHRONIZATION:
			LM_ERR("DO_RESYNCHRONIZATION is not a valid state\n");
			ret = AUTH_ERROR;
			goto end;
		case NOT_AUTHENTICATED:
			LM_DBG("not authenticated\n");
			ret = AUTH_ERROR;
			goto end;
		case DO_AUTHENTICATION:
			break;
		case AUTHENTICATED:
			ret = AUTH_OK;
			goto end;
	}

	cred = (auth_body_t*)h->parsed;
	if(ahdr!=NULL) *ahdr = h;

	res = get_ha1(&cred->digest.username, realm, table, ha1, &result);
	if (res < 0) {
		/* Error while accessing the database */
		ret = AUTH_ERROR;
		goto end;
	}
	if (res > 0) {
		/* Username not found in the database */
		ret = AUTH_USER_UNKNOWN;
		goto end;
	}

	/* Recalculate response, it must be same to authorize successfully */
	ret = auth_api.check_response(&(cred->digest), method, ha1);
	if(ret==AUTHENTICATED) {
		ret = AUTH_OK;
		switch(auth_api.post_auth(msg, h, ha1)) {
			case AUTHENTICATED:
				generate_avps(msg, result);
				break;
			default:
				ret = AUTH_ERROR;
				break;
		}
	} else {
		if(ret==NOT_AUTHENTICATED)
			ret = AUTH_INVALID_PASSWORD;
		else
			ret = AUTH_ERROR;
	}

end:
	if(result)
		auth_dbf.free_result(auth_db_handle, result);
	return ret;
}
예제 #12
0
/*
 * Authorize digest credentials
 */
static inline int authorize(struct sip_msg* _m, str* _realm, char* _table,
														hdr_types_t _hftype)
{
	char ha1[256];
	int res;
	struct hdr_field* h;
	auth_body_t* cred;
	auth_result_t ret;
	str domain;
	db_res_t* result;

	domain = *_realm;

	ret = auth_api.pre_auth(_m, &domain, _hftype, &h);

	switch(ret) {
		case ERROR:            return 0;
		case NOT_AUTHORIZED:   return -1;
		case DO_AUTHORIZATION: break;
		case AUTHORIZED:       return 1;
	}

	cred = (auth_body_t*)h->parsed;

	res = get_ha1(&cred->digest.username, &domain, _table, ha1, &result);
	if (res < 0) {
		/* Error while accessing the database */
		if (sl_reply(_m, (char*)500, MESSAGE_500) == -1) {
			LOG(L_ERR, "authorize(): Error while sending 500 reply\n");
		}
		return 0;
	}
	if (res > 0) {
		/* Username not found in the database */
		auth_dbf.free_result(auth_db_handle, result);
		return -1;
	}

	/* Recalculate response, it must be same to authorize successfully */
	if (!check_response(&(cred->digest),&_m->first_line.u.request.method,ha1)) {
		ret = auth_api.post_auth(_m, h);
		switch(ret) {
		case ERROR:
			auth_dbf.free_result(auth_db_handle, result);
			return 1;

		case NOT_AUTHORIZED:
			auth_dbf.free_result(auth_db_handle, result);
			return -1;

		case AUTHORIZED:
			generate_avps(result);
			auth_dbf.free_result(auth_db_handle, result);
			return 1;

		default:
			auth_dbf.free_result(auth_db_handle, result);
			return -1;
		}
	}

	auth_dbf.free_result(auth_db_handle, result);
	return -1;
}
예제 #13
0
파일: authorize.c 프로젝트: ryzhov/ATS0
/*
 * Authorize digest credentials
 */
static inline int authorize(struct sip_msg* _m, gparam_p _realm,
									char* _table, hdr_types_t _hftype)
{
	char ha1[256];
	int res;
	struct hdr_field* h;
	auth_body_t* cred;
	auth_result_t ret;
	str domain, table;
	db_res_t* result = NULL;

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

	table.s = _table;
	table.len = strlen(_table);

	if(fixup_get_svalue(_m, _realm, &domain)!=0)
	{
		LM_ERR("invalid realm parameter\n");
		return AUTH_ERROR;
	}

	if (domain.len==0)
		domain.s = 0;

	ret = auth_api.pre_auth(_m, &domain, _hftype, &h);

	if (ret != DO_AUTHORIZATION)
		return ret;

	cred = (auth_body_t*)h->parsed;

	res = get_ha1(&cred->digest.username, &domain, &table, ha1, &result);
	if (res < 0) {
		/* Error while accessing the database */
		if (sigb.reply(_m, 500, &auth_500_err, NULL) == -1) {
			LM_ERR("failed to send 500 reply\n");
		}
		return ERROR;
	}
	if (res > 0) {
		/* Username not found in the database */
		auth_dbf.free_result(auth_db_handle, result);
		return USER_UNKNOWN;
	}

	/* Recalculate response, it must be same to authorize successfully */
	if (!auth_api.check_response(&(cred->digest),
				&_m->first_line.u.request.method, ha1)) {
		ret = auth_api.post_auth(_m, h);
		if (ret == AUTHORIZED)
			generate_avps(result);
		auth_dbf.free_result(auth_db_handle, result);
		return ret;
	}

	auth_dbf.free_result(auth_db_handle, result);
	return INVALID_PASSWORD;
}
예제 #14
0
/*
 * Authenticate digest credentials
 * Returns:
 *      -3 -- Bad Request
 *      -2 -- Error while checking credentials (such as malformed message or database problem)
 *      -1 -- Authentication failed
 *       1 -- Authentication successful
 */
static inline int authenticate(struct sip_msg* msg, str* realm, authdb_table_info_t *table, hdr_types_t hftype)
{
	char ha1[256];
	int res, ret;
	db_rec_t *row;
	struct hdr_field* h;
	auth_body_t* cred;
	db_res_t* result;
	str did;
    
	cred = 0;
	result = 0;
	ret = -1;
    
	switch(auth_api.pre_auth(msg, realm, hftype, &h, NULL)) {
	case ERROR:
	case BAD_CREDENTIALS:
		ret = -3;
		goto end;
	case CREATE_CHALLENGE:
		ERR("auth_db:authenticate: CREATE_CHALLENGE is not a valid state\n");
		ret = -2;
		goto end;
	case DO_RESYNCHRONIZATION:
		ERR("auth_db:authenticate: DO_RESYNCHRONIZATION is not a valid state\n");
		ret = -2;
		goto end;
		
	case NOT_AUTHENTICATED: 
		ret = -1;
		goto end;
		
	case DO_AUTHENTICATION: 
		break;
		
	case AUTHENTICATED:
		ret = 1; 
		goto end;
	}
    
	cred = (auth_body_t*)h->parsed;
	
	if (use_did) {
		if (msg->REQ_METHOD == METHOD_REGISTER) {
			ret = get_to_did(&did, msg);
		} else {
			ret = get_from_did(&did, msg);
		}
		if (ret == 0) {
			did.s = DEFAULT_DID;
			did.len = sizeof(DEFAULT_DID) - 1;
		}
	} else {
		did.len = 0;
		did.s = 0;
	}	
    

	if (check_all) {
		res = check_all_ha1(msg, h, &(cred->digest), &msg->first_line.u.request.method, &did, realm, table, &result);
		if (res < 0) {
			ret = -2;
			goto end;
		}
		else if (res > 0) {
			ret = -1;
			goto end;
		}
		else {
			ret = 1;
			goto end;
		}
    	} else {
		res = get_ha1(&cred->digest.username, &did, realm, table, ha1, &result, &row);
		if (res < 0) {
			ret = -2;
			goto end;
		}
		if (res > 0) {
			/* Username not found in the database */
			ret = -1;
			goto end;
        	}
    	}
    
	/* Recalculate response, it must be same to authorize successfully */
	if (!check_response(&(cred->digest), &msg->first_line.u.request.method, ha1)) {
		switch(auth_api.post_auth(msg, h)) {
		case ERROR:
		case BAD_CREDENTIALS:
			ret = -2; 
			break;
			
		case NOT_AUTHENTICATED: 
			ret = -1; 
			break;
			
		case AUTHENTICATED:
			generate_avps(result, row);
			ret = 1;
			break;
			
		default:
			ret = -1;
			break;
		}
	} else {
		ret = -1;
	}

 end:
	if (result) db_res_free(result);
	if (ret < 0) {
		if (auth_api.build_challenge(msg, (cred ? cred->stale : 0), realm, NULL, NULL, hftype) < 0) {
			ERR("Error while creating challenge\n");
			ret = -2;
		}
	}
	return ret;
}
예제 #15
0
/* this is a dirty work around to check the credentials of all users,
 * if the database query returned more then one result
 *
 * Fills res (which must be db_free'd afterwards if the call was succesfull)
 * returns  0 on success, 1 on no match (?)
 *          and -1 on error (memory, db a.s.o).
 * WARNING: if -1 is returned res _must_ _not_ be freed (it's empty)
 *
 */
static inline int check_all_ha1(struct sip_msg* msg, struct hdr_field* hdr, 
		dig_cred_t* dig, str* method, str* did, str* realm, 
		authdb_table_info_t *table_info, db_res_t** res) 
{
	char ha1[256];
	db_rec_t *row;
	str result;
	db_cmd_t *q;
   
	if (calc_ha1) {
		q = table_info->query_password;
		DBG("querying plain password\n");
	}
	else {
	    if (dig->username.domain.len) {
			q = table_info->query_pass2;
			DBG("querying ha1b\n");
		}
		else {
			q = table_info->query_pass;
			DBG("querying ha1\n");
		}
	}
    
	q->match[0].v.lstr = dig->username.user;
	if (dig->username.domain.len) 
		q->match[1].v.lstr = dig->username.domain;
	else
		q->match[1].v.lstr = *realm;

	if (use_did) q->match[2].v.lstr = *did;

	if (db_exec(res, q) < 0 ) {
		ERR("Error while querying database\n");
	}

	if (*res) row = db_first(*res);
	else row = NULL;
	while (row) {
		if (IS_NULL(row->fld[0]) || IS_NULL(row->fld[1])) {
			LOG(L_ERR, "auth_db:check_all_ha1: Credentials for '%.*s'@'%.*s' contain NULL value, skipping\n",
			    dig->username.user.len, ZSW(dig->username.user.s), realm->len, ZSW(realm->s));
		}
		else {
			if (row->fld[1].v.int4 & DB_DISABLED) {
				/* disabled rows ignored */
			}
			else {
				if (row->fld[1].v.int4 & DB_LOAD_SER) {
					result.s = row->fld[0].v.cstr;
					result.len = strlen(result.s);
					if (calc_ha1) {
						 /* Only plaintext passwords are stored in database,
						  * we have to calculate HA1 */
						auth_api.calc_HA1(HA_MD5, &(dig->username.whole), realm, &result, 0, 0, ha1);
						DBG("auth_db:check_all_ha1: HA1 string calculated: %s\n", ha1);
					} else {
						memcpy(ha1, result.s, result.len);
						ha1[result.len] = '\0';
					}

					if (!check_response(dig, method, ha1)) {
						if (auth_api.post_auth(msg, hdr) == AUTHENTICATED) {
							generate_avps(*res, row);
							return 0;
						}
					}
				}
			}
		}
		row = db_next(*res);
	}

	if (!row) {
		DBG("auth_db:check_all_ha1: Credentials for '%.*s'@'%.*s' not found",
		    dig->username.user.len, ZSW(dig->username.user.s), realm->len, ZSW(realm->s));
	}		
	return 1;


}