Beispiel #1
0
/*
 * Remove used credentials from a SIP message header
 */
int consume_credentials(struct sip_msg* msg)
{
	struct hdr_field* h;
	int len;

	/* skip requests that can't be authenticated */
	if (msg->REQ_METHOD & (METHOD_ACK|METHOD_CANCEL|METHOD_PRACK))
		return -1;
	get_authorized_cred(msg->authorization, &h);
	if (!h) {
		get_authorized_cred(msg->proxy_auth, &h);
		if (!h) {
			LOG(L_ERR, "auth:consume_credentials: No authorized "
					"credentials found (error in scripts)\n");
			return -1;
		}
	}

	len = h->len;

	if (del_lump(msg, h->name.s - msg->buf, len, 0) == 0) {
		LOG(L_ERR, "auth:consume_credentials: Can't remove credentials\n");
		return -1;
	}

	return 1;
}
Beispiel #2
0
/*
 * Remove used credentials from a SIP message header
 */
int consume_credentials(struct sip_msg* _m, char* _s1, char* _s2)
{
	struct hdr_field* h;
	int len;

	get_authorized_cred(_m->authorization, &h);
	if (!h) {
		get_authorized_cred(_m->proxy_auth, &h);
		if (!h) { 
			if (_m->REQ_METHOD!=METHOD_ACK 
					&& _m->REQ_METHOD!=METHOD_CANCEL) {
				LM_ERR("no authorized credentials found (error in scripts)\n");
			}
			return -1;
		}
	}

	len=h->len;

	if (del_lump(_m, h->name.s - _m->buf, len, 0) == 0) {
		LM_ERR("can't remove credentials\n");
		return -1;
	}

	return 1;
}
Beispiel #3
0
/*
 * Remove used credentials from a SIP message header
 */
int consume_credentials(struct sip_msg* msg, char* s1, char* s2)
{
    struct hdr_field* h;
    int len;
    
    get_authorized_cred(msg->authorization, &h);
    if (!h) {
		get_authorized_cred(msg->proxy_auth, &h);
		if (!h) { 
			if (msg->REQ_METHOD != METHOD_ACK 
				&& msg->REQ_METHOD != METHOD_CANCEL) {
				LOG(L_ERR, "auth:consume_credentials: No authorized "
					"credentials found (error in scripts)\n");
			}
			return -1;
		}
    }
    
    len = h->len;
    
    if (del_lump(msg, h->name.s - msg->buf, len, 0) == 0) {
		LOG(L_ERR, "auth:consume_credentials: Can't remove credentials\n");
		return -1;
    }
    
    return 1;
}
Beispiel #4
0
/*
 * Create and send a challenge
 */
static inline int challenge(struct sip_msg* _msg, str* _realm, int _qop, 
			    int _code, char* _message, char* _challenge_msg)
{
	int auth_hf_len;
	struct hdr_field* h;
	auth_body_t* cred = 0;
	char *auth_hf;
	int ret, hftype = 0; /* Makes gcc happy */
	struct sip_uri uri;

	switch(_code) {
	case 401: 
		get_authorized_cred(_msg->authorization, &h); 
		hftype = HDR_AUTHORIZATION;
		break;
	case 407: 
		get_authorized_cred(_msg->proxy_auth, &h);
		hftype = HDR_PROXYAUTH;
		break;
	}

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

	if (_realm->len == 0) {
		if (get_realm(_msg, hftype, &uri) < 0) {
			LOG(L_ERR, "challenge(): Error while extracting URI\n");
			if (send_resp(_msg, 400, MESSAGE_400, 0, 0) == -1) {
				LOG(L_ERR, "challenge(): Error while sending response\n");
				return -1;
			}
			return 0;
		}

		_realm = &uri.host;
		strip_realm(_realm);
	}

	auth_hf = build_auth_hf(0, (cred ? cred->stale : 0), _realm, &auth_hf_len, _qop, _challenge_msg);
	if (!auth_hf) {
		LOG(L_ERR, "ERROR: challenge: no mem w/cred\n");
		return -1;
	}
	
	ret = send_resp(_msg, _code, _message, auth_hf, auth_hf_len);
	if (auth_hf) pkg_free(auth_hf);
	if (ret == -1) {
		LOG(L_ERR, "challenge(): Error while sending response\n");
		return -1;
	}
	
	return 0;
}
/* Extract username attribute from authorized credentials */
static inline str* cred_user(struct sip_msg* rq)
{
	struct hdr_field* h;
	auth_body_t* cred;

	get_authorized_cred(rq->proxy_auth, &h);
	if (!h) get_authorized_cred(rq->authorization, &h);
	if (!h) return 0;
	cred = (auth_body_t*)(h->parsed);
	if (!cred || !cred->digest.username.user.len)
		return 0;
	return &cred->digest.username.user;
}
/* Extract realm attribute from authorized credentials */
static inline str* cred_realm(struct sip_msg* rq)
{
	str* realm;
	struct hdr_field* h;
	auth_body_t* cred;

	get_authorized_cred(rq->proxy_auth, &h);
	if (!h) get_authorized_cred(rq->authorization, &h);
	if (!h) return 0;
	cred = (auth_body_t*)(h->parsed);
	if (!cred) return 0;
	realm = GET_REALM(&cred->digest);
	if (!realm->len || !realm->s) {
		return 0;
	}
	return realm;
}
Beispiel #7
0
static inline int get_cred(struct sip_msg *_m, str *_username)
{
	struct hdr_field *h;

	get_authorized_cred(_m->authorization, &h);
	if (!h)
	{
		get_authorized_cred(_m->proxy_auth, &h);
		if (!h)
		{
			LM_ERR("No authorized credentials found\n");
			return -1;
		}
	}

	*_username = ((auth_body_t *) h->parsed)->digest.username.whole;
	return 0;
}
Beispiel #8
0
/*
 * Check if the username matches the username in credentials
 */
int is_user(struct sip_msg* _m, char* _user, char* _str2)
{
	str s;
	struct hdr_field* h;
	auth_body_t* c;

	if (get_str_fparam(&s, _m, (fparam_t *)_user) < 0) {
		ERR("is_user: failed to recover parameter.\n");
		return -1;
	}

	get_authorized_cred(_m->authorization, &h);
	if (!h) {
		get_authorized_cred(_m->proxy_auth, &h);
		if (!h) {
			LOG(L_ERR, "is_user(): No authorized credentials found (error in scripts)\n");
			LOG(L_ERR, "is_user(): Call {www,proxy}_authorize before calling is_user function !\n");
			return -1;
		}
	}

	c = (auth_body_t*)(h->parsed);

	if (!c->digest.username.user.len) {
		DBG("is_user(): Username not found in credentials\n");
		return -1;
	}

	if (s.len != c->digest.username.user.len) {
		DBG("is_user(): Username length does not match\n");
		return -1;
	}

	if (!memcmp(s.s, c->digest.username.user.s, s.len)) {
		DBG("is_user(): Username matches\n");
		return 1;
	} else {
		DBG("is_user(): Username differs\n");
		return -1;
	}
}
Beispiel #9
0
/*
 * Check if the username matches the username in credentials
 */
int is_user(struct sip_msg* _m, char* _user, char* _str2)
{
	str* s;
	struct hdr_field* h;
	auth_body_t* c;

	s = (str*)_user;

	get_authorized_cred(_m->authorization, &h);
	if (!h) {
		get_authorized_cred(_m->proxy_auth, &h);
		if (!h) {
			LM_ERR("no authorized credentials found (error in scripts)\n");
			LM_ERR("Call {www,proxy}_authorize before calling is_user function !\n");
			return -1;
		}
	}

	c = (auth_body_t*)(h->parsed);

	if (!c->digest.username.user.len) {
		LM_DBG("username not found in credentials\n");
		return -1;
	}

	if (s->len != c->digest.username.user.len) {
		LM_DBG("username length does not match\n");
		return -1;
	}

	if (!memcmp(s->s, c->digest.username.user.s, s->len)) {
		LM_DBG("username matches\n");
		return 1;
	} else {
		LM_DBG("username differs\n");
		return -1;
	}
}
Beispiel #10
0
static str
get_diverter(struct sip_msg *msg)
{
    struct hdr_field *header;
    dig_cred_t *credentials;
    int_str avpname, avpvalue;
    static str diverter;

    diverter.s   = "None";
    diverter.len = 4;

    avpname.n = diverter_avp_id;

    if (search_first_avp(AVP_VAL_STR, avpname, &avpvalue, NULL)) {
        // have a diverted call
        diverter = avpvalue.s;
    } else {
        get_authorized_cred(msg->proxy_auth, &header);
        if (header) {
            credentials = &((auth_body_t*)(header->parsed))->digest;
        } else {
            if (parse_headers(msg, HDR_PROXYAUTH_F, 0) == -1) {
                LOG(L_ERR, "cannot parse Proxy-Authorization header\n");
                return diverter;
            }
            if (!msg->proxy_auth)
                return diverter;
            if (parse_credentials(msg->proxy_auth) != 0) {
                LOG(L_ERR, "cannot parse credentials\n");
                return diverter;
            }
            credentials = &((auth_body_t*)(msg->proxy_auth->parsed))->digest;
        }

        if (credentials->username.user.len > 0 &&
            credentials->username.domain.len > 0 &&
            credentials->realm.len == 0 &&
            credentials->nonce.len == 0 &&
            credentials->response.len == 0) {
            // this is a call diverted from the failure route
            // and sent back to proxy with append_pa_hf()
            diverter = credentials->username.whole;
        }
    }

    return diverter;
}
Beispiel #11
0
/*
 * Check from Radius if a user belongs to a group. User-Name is digest
 * username or digest username@realm, SIP-Group is group, and Service-Type
 * is Group-Check.  SIP-Group is SER specific attribute and Group-Check is
 * SER specific service type value.
 */
int radius_is_user_in(struct sip_msg* _m, char* _hf, char* _group)
{
	str *grp, user_name, user, domain, uri;
	dig_cred_t* cred = 0;
	int hf_type;
	UINT4 service;
	VALUE_PAIR *send, *received;
	static char msg[4096];
	struct hdr_field* h;
	struct sip_uri puri;

	grp = (str*)_group; /* via fixup */
	send = received = 0;

	hf_type = (int)(long)_hf;

	uri.s = 0;
	uri.len = 0;

	switch(hf_type) {
	case 1: /* Request-URI */
		if (get_request_uri(_m, &uri) < 0) {
			LOG(L_ERR, "radius_is_user_in(): Error while extracting Request-URI\n");
			return -1;
		}
		break;

	case 2: /* To */
		if (get_to_uri(_m, &uri) < 0) {
			LOG(L_ERR, "radius_is_user_in(): Error while extracting To\n");
			return -2;
		}
		break;

	case 3: /* From */
		if (get_from_uri(_m, &uri) < 0) {
			LOG(L_ERR, "radius_is_user_in(): Error while extracting From\n");
			return -3;
		}
		break;

	case 4: /* Credentials */
		get_authorized_cred(_m->authorization, &h);
		if (!h) {
			get_authorized_cred(_m->proxy_auth, &h);
			if (!h) {
				LOG(L_ERR, "radius_is_user_in(): No authorized credentials found (error in scripts)\n");
				return -4;
			}
		}
		cred = &((auth_body_t*)(h->parsed))->digest;
		break;
	}

	if (hf_type != 4) {
		if (parse_uri(uri.s, uri.len, &puri) < 0) {
			LOG(L_ERR, "radius_is_user_in(): Error while parsing URI\n");
			return -5;
		}
		user = puri.user;
		domain = puri.host;
	} else {
		user = cred->username.user;
		domain = *GET_REALM(cred);
	}
		

	if (use_domain) {
		user_name.len = user.len + domain.len + 1;
		user_name.s = (char*)pkg_malloc(user_name.len);
		if (!user_name.s) {
			LOG(L_ERR, "radius_is_user_in(): No memory left\n");
			return -6;
		}
		
		memcpy(user_name.s, user.s, user.len);
		user_name.s[user.len] = '@';
		memcpy(user_name.s + user.len + 1, domain.s, domain.len);
	} else {
		user_name = user;
	}

	if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v, user_name.s, user_name.len, 0)) {
		LOG(L_ERR, "radius_is_user_in(): Error adding User-Name attribute\n");
		rc_avpair_free(send);
		if (use_domain) pkg_free(user_name.s);
		return -7;
	}

	if (use_domain) pkg_free(user_name.s);

	if (!rc_avpair_add(rh, &send, attrs[A_SIP_GROUP].v, grp->s, grp->len, 0)) {
		LOG(L_ERR, "radius_is_user_in(): Error adding Sip-Group attribute\n");
	 	return -8;  	
	}

	service = vals[V_GROUP_CHECK].v;
	if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) {
		LOG(L_ERR, "radius_is_user_in(): Error adding Service-Type attribute\n");
		rc_avpair_free(send);
	 	return -9;  	
	}

	if (rc_auth(rh, 0, send, &received, msg) == OK_RC) {
		DBG("radius_is_user_in(): Success\n");
		rc_avpair_free(send);
		rc_avpair_free(received);
		return 1;
	} else {
		DBG("radius_is_user_in(): Failure\n");
		rc_avpair_free(send);
		rc_avpair_free(received);
		return -11;
	}
}
Beispiel #12
0
/*!
 * \brief Extract the username and domain from the SIP message
 *
 * Set the username and domain depending on the value of the SIP
 * message and the group check structure.
 * \param msg SIP message
 * \param gcp group check structure
 * \param username stored username
 * \param domain stored domain
 * \return 0 on success, -1 on failure
 */
int get_username_domain(struct sip_msg *msg, group_check_p gcp,
											str *username, str *domain)
{
	struct sip_uri puri;
	struct sip_uri *turi;
	struct hdr_field* h;
	struct auth_body* c = 0;
	pv_value_t value;

	turi = NULL;

	switch(gcp->id) {
		case 1: /* Request-URI */
			if(parse_sip_msg_uri(msg)<0) {
				LM_ERR("failed to get Request-URI\n");
				return -1;
			}
			turi = &msg->parsed_uri;
			break;

		case 2: /* To */
			if((turi=parse_to_uri(msg))==NULL) {
				LM_ERR("failed to get To URI\n");
				return -1;
			}
			break;

		case 3: /* From */
			if((turi=parse_from_uri(msg))==NULL) {
				LM_ERR("failed to get From URI\n");
				return -1;
			}
			break;

		case 4: /* Credentials */
			get_authorized_cred( msg->authorization, &h);
			if (!h) {
				get_authorized_cred( msg->proxy_auth, &h);
				if (!h) {
					LM_ERR("no authorized credentials found "
							"(error in scripts)\n");
					return -1;
				}
			}
			c = (auth_body_t*)(h->parsed);
			break;

		case 5: /* AVP spec */
			if(pv_get_spec_value( msg, &gcp->sp, &value)!=0 
				|| value.flags&PV_VAL_NULL || value.rs.len<=0)
			{
				LM_ERR("no AVP found (error in scripts)\n");
				return -1;
			}
			if (parse_uri(value.rs.s, value.rs.len, &puri) < 0) {
				LM_ERR("failed to parse URI <%.*s>\n",value.rs.len, value.rs.s);
				return -1;
			}
			turi = &puri;
			break;
		default: {
			LM_ERR("incorrect check id %d\n", gcp->id);
			return -1;
		}
	}

	if (gcp->id != 4) {
		*username = turi->user;
		*domain = turi->host;
	} else {
		*username = c->digest.username.user;
		*domain = *(GET_REALM(&c->digest));
	}
	return 0;
}
Beispiel #13
0
static int load_avp_user(struct sip_msg* msg, str* prefix, load_avp_param_t type)
{
	static char rad_msg[4096];
	str user_domain, buffer;
	str* user, *domain, *uri;
	struct hdr_field* h;
	dig_cred_t* cred = 0;
	int_str name, val;
	unsigned short flags;

	VALUE_PAIR* send, *received, *vp;
	UINT4 service;
	struct sip_uri puri;
	
	send = received = 0;
	user_domain.s = 0;

	switch(type) {
	case LOAD_CALLER:
		     /* Use From header field */
		if (parse_from_header(msg) < 0) {
			LOG(L_ERR, "ERROR:avp_radius:load_avp_user: Error while "
				"parsing From header field\n");
			return -1;
		}

		uri = &get_from(msg)->uri;
		if (parse_uri(uri->s, uri->len, &puri) == -1) {
			LOG(L_ERR, "ERROR:avp_radius:load_avp_user: Error while "
				"parsing From URI\n");
			return -1;
		}

		user = &puri.user;
		domain = &puri.host;
		service = vals[V_SIP_CALLER_AVPS].v;
		break;

	case LOAD_CALLEE:
		     /* Use the Request-URI */
		if (parse_sip_msg_uri(msg) < 0) {
			LOG(L_ERR, "ERROR:avp_radius:load_avp_user: Error while "
				"parsing Request-URI\n");
			return -1;
		}

		if (msg->parsed_uri.user.len == 0) {
			LOG(L_ERR, "ERROR:avp_radius:load_avp_user: Request-URI user "
				"is missing\n");
			return -1;
		}
		
		user = &msg->parsed_uri.user; 
		domain = &msg->parsed_uri.host;
		service = vals[V_SIP_CALLEE_AVPS].v;
		break;

	case LOAD_DIGEST:
		     /* Use digest credentials */
		get_authorized_cred(msg->proxy_auth, &h);
		if (!h) {
			LOG(L_ERR, "ERROR:avp_radius:load_avp_user: No authoried "
				"credentials\n");
			return -1;
		}

		cred = &((auth_body_t*)(h->parsed))->digest;
		user = &cred->username.user;
		domain = &cred->realm;
		service = vals[V_SIP_CALLER_AVPS].v;
		break;

	default:
		LOG(L_ERR, "ERROR:avp_radius:avp_load_user: Unknown user type\n");
		return -1;
		
	}

	user_domain.len = user->len + 1 + domain->len;
	user_domain.s = (char*)pkg_malloc(user_domain.len);
	if (!user_domain.s) {
		LOG(L_ERR, "ERROR:avp_radius:avp_load_user: No pkg memory left\n");
		return -1;
	}

	memcpy(user_domain.s, user->s, user->len);
	user_domain.s[user->len] = '@';
	memcpy(user_domain.s + user->len + 1, domain->s, domain->len);

	if (!rc_avpair_add(rh, &send, attrs[A_USER_NAME].v,
			user_domain.s, user_domain.len, 0)) {
		LOG(L_ERR, "ERROR:avp_radius:avp_load_user: Error adding "
			"PW_USER_NAME\n");
		goto error;
	}

	if (!rc_avpair_add(rh, &send, attrs[A_SERVICE_TYPE].v, &service, -1, 0)) {
		LOG(L_ERR, "ERROR:avp_radius:avp_load_user: Error adding "
			"PW_SERVICE_TYPE\n");
		goto error;
	}

	if (rc_auth(rh, 0, send, &received, rad_msg) == OK_RC) {
		DBG("DEBUG:avp_radius:avp_load_user: rc_auth Success\n");
		rc_avpair_free(send);
		pkg_free(user_domain.s);

		vp = received;
		for( ; (vp=rc_avpair_get(vp,attrs[A_SIP_AVP].v,0)) ; vp=vp->next) {
			flags = 0;
			if (extract_avp( vp, &flags, &name, &val)!=0 )
				continue;

			/* append prefix only if AVP has name */
			if (flags&AVP_NAME_STR) {
				buffer.len = prefix->len + name.s->len;
				buffer.s = (char*)pkg_malloc(buffer.len);
				if (!buffer.s) {
					LOG(L_ERR, "ERROR:avp_radius:avp_load_user: "******"No pkg memory left\n");
					return -1;
				}
				memcpy(buffer.s, prefix->s, prefix->len);
				memcpy(buffer.s + prefix->len, name.s->s, name.s->len);
				name.s = &buffer;
			} else {
				buffer.s = 0;
			}

			if (add_avp( flags, name, val) < 0) {
				LOG(L_ERR, "ERROR:avp_radius:avp_load_user: Unable to create "
					"a new AVP\n");
			} else {
				DBG("DEBUG:avp_radius:generate_avps: "
					"AVP '%.*s'/%d='%.*s'/%d has been added\n",
					(flags&AVP_NAME_STR)?name.s->len:4,
					(flags&AVP_NAME_STR)?name.s->s:"null",
					(flags&AVP_NAME_STR)?0:name.n,
					(flags&AVP_VAL_STR)?val.s->len:4,
					(flags&AVP_VAL_STR)?val.s->s:"null",
					(flags&AVP_VAL_STR)?0:val.n );
			}

			if (buffer.s) 
				pkg_free(buffer.s);
		}

		rc_avpair_free(received);
		return 1;
	} else {
		LOG(L_ERR,"ERROR:avp_radius:avp_load_user: rc_auth failed\n");
	}

error:
	if (send) rc_avpair_free(send);
	if (received) rc_avpair_free(received);
	if (user_domain.s) pkg_free(user_domain.s);
	return -1;
}
Beispiel #14
0
/*
 * Check if username in specified header field is in a table
 */
int is_user_in(struct sip_msg* _msg, char* _hf, char* _grp)
{
	db_key_t keys[3];
	db_val_t vals[3];
	db_key_t col[1];
	db_res_t* res;
	str uri;
	long hf_type;
	struct sip_uri puri;
	struct hdr_field* h;
	struct auth_body* c = 0; /* Makes gcc happy */
	group_check_p gcp=NULL;
	xl_value_t value;
	
	keys[0] = user_column.s;
	keys[1] = group_column.s;
	keys[2] = domain_column.s;
	col[0] = group_column.s;
	
	gcp = (group_check_p)_hf;
	hf_type = (long)gcp->id;

	uri.s = 0;
	uri.len = 0;

	switch(hf_type) {
	case 1: /* Request-URI */
		if (get_request_uri(_msg, &uri) < 0) {
			LOG(L_ERR, "is_user_in(): Error while obtaining username from Request-URI\n");
			return -1;
		}
		break;

	case 2: /* To */
		if (get_to_uri(_msg, &uri) < 0) {
			LOG(L_ERR, "is_user_in(): Error while extracting To username\n");
			return -2;
		}
		break;

	case 3: /* From */
		if (get_from_uri(_msg, &uri) < 0) {
			LOG(L_ERR, "is_user_in(): Error while extracting From username\n");
			return -3;
		}
		break;

	case 4: /* Credentials */
		get_authorized_cred(_msg->authorization, &h);
		if (!h) {
			get_authorized_cred(_msg->proxy_auth, &h);
			if (!h) {
				LOG(L_ERR, "is_user_in(): No authorized credentials found (error in scripts)\n");
				return -1;
			}
		}
	
		c = (auth_body_t*)(h->parsed);
		break;
	case 5: /* AVP spec */
		if(xl_get_spec_value(_msg, &gcp->sp, &value)!=0 
				|| value.flags&XL_VAL_NULL || value.rs.len<=0)
		{
			LOG(L_ERR,
				"is_user_in(): no AVP found (error in scripts)\n");
			return -1;
		}
		uri.s = value.rs.s;
		uri.len = value.rs.len;
		break;
	}

	if (hf_type != 4) {
		if (parse_uri(uri.s, uri.len, &puri) < 0) {
			LOG(L_ERR, "is_user_in(): Error while parsing URI\n");
			return -5;
		}

		VAL_STR(vals) = puri.user;
		VAL_STR(vals + 2) = puri.host;
	} else {
		VAL_STR(vals) = c->digest.username.user;
		VAL_STR(vals + 2) = *(GET_REALM(&c->digest));
	}
	
	VAL_TYPE(vals) = VAL_TYPE(vals + 1) = VAL_TYPE(vals + 2) = DB_STR;
	VAL_NULL(vals) = VAL_NULL(vals + 1) = VAL_NULL(vals + 2) = 0;

	VAL_STR(vals + 1) = *((str*)_grp);
	
	if (group_dbf.use_table(db_handle, table.s) < 0) {
		LOG(L_ERR, "is_user_in(): Error in use_table\n");
		return -5;
	}

	if (group_dbf.query(db_handle, keys, 0, vals, col, (use_domain) ? (3): (2),
				1, 0, &res) < 0) {
		LOG(L_ERR, "is_user_in(): Error while querying database\n");
		return -5;
	}
	
	if (RES_ROW_N(res) == 0) {
		DBG("is_user_in(): User is not in group '%.*s'\n", 
		    ((str*)_grp)->len, ZSW(((str*)_grp)->s));
		group_dbf.free_result(db_handle, res);
		return -6;
	} else {
		DBG("is_user_in(): User is in group '%.*s'\n", 
		    ((str*)_grp)->len, ZSW(((str*)_grp)->s));
		group_dbf.free_result(db_handle, res);
		return 1;
	}
}
Beispiel #15
0
/*
 * Create and send a challenge
 */
static inline int challenge(struct sip_msg* _msg, gparam_p _realm, int _qop,
						int _code, char* _message, char* _challenge_msg)
{
	int auth_hf_len;
	struct hdr_field* h;
	auth_body_t* cred = 0;
	char *auth_hf;
	int ret;
	hdr_types_t hftype = 0; /* Makes gcc happy */
	struct sip_uri *uri;
	str realm;
	str reason;

	switch(_code) {
	case 401:
		get_authorized_cred(_msg->authorization, &h); 
		hftype = HDR_AUTHORIZATION_T;
		break;
	case 407:
		get_authorized_cred(_msg->proxy_auth, &h);
		hftype = HDR_PROXYAUTH_T;
		break;
	}

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

	if(fixup_get_svalue(_msg, _realm, &realm)!=0)
	{
		LM_ERR("invalid realm parameter");
		if (send_resp(_msg, 500, &auth_500_err, 0, 0)==-1)
			return -1;
		else
			return 0;
	}
	if (realm.len == 0) {
		if (get_realm(_msg, hftype, &uri) < 0) {
			LM_ERR("failed to extract URI\n");
			if (send_resp(_msg, 400, &auth_400_err, 0, 0) == -1) {
				LM_ERR("failed to send the response\n");
				return -1;
			}
			return 0;
		}

		realm = uri->host;
		strip_realm(&realm);
	}

	auth_hf = build_auth_hf(0, (cred ? cred->stale : 0), &realm, 
			&auth_hf_len, _qop, _challenge_msg);
	if (!auth_hf) {
		LM_ERR("failed to generate nonce\n");
		return -1;
	}

	reason.s = _message;
	reason.len = strlen(_message);
	ret = send_resp(_msg, _code, &reason, auth_hf, auth_hf_len);
	if (auth_hf) pkg_free(auth_hf);
	if (ret == -1) {
		LM_ERR("failed to send the response\n");
		return -1;
	}
	
	return 0;
}
Beispiel #16
0
int get_username_domain(struct sip_msg *msg, str *hf_s,
											str *username, str *domain)
{
	struct sip_uri puri;
	struct sip_uri *turi;
	struct hdr_field* h;
	struct auth_body* c = 0; /* Makes gcc happy */

	turi = NULL;

	switch( hf_type(hf_s) ) {
		case 1: /* Request-URI */
			if(parse_sip_msg_uri(msg)<0) {
				LM_ERR("failed to get Request-URI\n");
				return -1;
			}
			turi = &msg->parsed_uri;
			break;

		case 2: /* To */
			if((turi=parse_to_uri(msg))==NULL) {
				LM_ERR("failed to get To URI\n");
				return -1;
			}
			break;

		case 3: /* From */
			if((turi=parse_from_uri(msg))==NULL) {
				LM_ERR("failed to get From URI\n");
				return -1;
			}
			break;

		case 4: /* Credentials */
			get_authorized_cred( msg->authorization, &h);
			if (!h) {
				get_authorized_cred( msg->proxy_auth, &h);
				if (!h) {
					LM_ERR("no authorized credentials found "
							"(error in scripts)\n");
					return -1;
				}
			}
			c = (auth_body_t*)(h->parsed);
			break;

		default: /* string */
			if (parse_uri(hf_s->s, hf_s->len, &puri) < 0) {
				LM_ERR("failed to parse URI <%.*s>\n",hf_s->len, hf_s->s);
				return -1;
			}
			turi = &puri;
			break;
	}

	if ( c==NULL ) {
		*username = turi->user;
		*domain = turi->host;
	} else {
		*username = c->digest.username.user;
		*domain = *(GET_REALM(&c->digest));
	}
	return 0;
}
Beispiel #17
0
/*
 * Check from AAA server if a user belongs to a group. User-Name is digest
 * username or digest username@realm, SIP-Group is group, and Service-Type
 * is Group-Check.  SIP-Group is SER specific attribute and Group-Check is
 * SER specific service type value.
 */
int aaa_is_user_in(struct sip_msg* _m, char* _hf, char* _group)
{
	str *grp, user_name, user, domain;
	dig_cred_t* cred = 0;
	int hf_type;
	uint32_t service;

	aaa_message *send = NULL, *received = NULL;

	struct hdr_field* h;
	struct sip_uri *turi;

	grp = (str*)_group; /* via fixup */

	hf_type = (int)(long)_hf;

	turi = 0;

	switch(hf_type) {
		case 1: /* Request-URI */
			if(parse_sip_msg_uri(_m)<0) {
				LM_ERR("failed to get Request-URI\n");
				return -1;
			}
			turi = &_m->parsed_uri;
			break;

		case 2: /* To */
			if((turi=parse_to_uri(_m))==NULL) {
				LM_ERR("failed to get To URI\n");
				return -1;
			}
			break;

		case 3: /* From */
			if((turi=parse_from_uri(_m))==NULL) {
				LM_ERR("failed to get From URI\n");
				return -1;
			}
			break;

		case 4: /* Credentials */
			get_authorized_cred(_m->authorization, &h);
			if (!h) {
				get_authorized_cred(_m->proxy_auth, &h);
				if (!h) {
				LM_ERR("no authorized"
							" credentials found (error in scripts)\n");
					return -4;
				}
			}
			cred = &((auth_body_t*)(h->parsed))->digest;
			break;
	}

	if (hf_type != 4) {
		user = turi->user;
		domain = turi->host;
	} else {
		user = cred->username.user;
		domain = *GET_REALM(cred);
	}

	if (user.s == NULL || user.len == 0) {
		LM_DBG("no username part\n");
		return -1;
	}

	if (use_domain) {
		user_name.len = user.len + domain.len + 1;
		user_name.s = (char*)pkg_malloc(user_name.len);
		if (!user_name.s) {
			LM_ERR("no pkg memory left\n");
			return -6;
		}

		memcpy(user_name.s, user.s, user.len);
		user_name.s[user.len] = '@';
		memcpy(user_name.s + user.len + 1, domain.s, domain.len);
	} else {
		user_name = user;
	}

	if ((send = proto.create_aaa_message(conn, AAA_AUTH)) == NULL) {
		LM_ERR("failed to create new aaa message for auth \n");
		return -1;
	}

	if (proto.avp_add(conn, send, &attrs[A_USER_NAME], user_name.s, user_name.len, 0)) {
		proto.destroy_aaa_message(conn, send);
		if (use_domain) pkg_free(user_name.s);
		return -7;
	}

	if (use_domain) pkg_free(user_name.s);


	if (proto.avp_add(conn, send, &attrs[A_SIP_GROUP], grp->s, grp->len, 0)) {
		proto.destroy_aaa_message(conn, send);
		LM_ERR("failed to add Sip-Group attribute\n");
		return -8;
	}

	service = vals[V_GROUP_CHECK].value;

	if (proto.avp_add(conn, send, &attrs[A_SERVICE_TYPE], &service, -1, 0)) {
		proto.destroy_aaa_message(conn, send);
		LM_ERR("failed to add Service-Type attribute\n");
		return -8;
	}

	/* Add CALL-ID in Acct-Session-Id Attribute */
	if ((parse_headers(_m, HDR_CALLID_F, 0) == -1 || _m->callid == NULL) &&
		 _m->callid == NULL) {
		proto.destroy_aaa_message(conn, send);
		LM_ERR("msg parsing failed or callid not present");
		return -10;
	}

	if (proto.avp_add(conn, send, &attrs[A_ACCT_SESSION_ID], _m->callid->body.s,
	_m->callid->body.len, 0)) {
		proto.destroy_aaa_message(conn, send);
		LM_ERR("unable to add CALL-ID attribute\n");
		return -11;
	}

	if (!proto.send_aaa_request(conn, send, &received)) {
		LM_DBG("Success\n");
		proto.destroy_aaa_message(conn, send);
		proto.destroy_aaa_message(conn, received);
		return 1;
	} else {
		LM_DBG("Failure\n");
		proto.destroy_aaa_message(conn, send);
		proto.destroy_aaa_message(conn, received);
		return -12;
	}
}
Beispiel #18
0
/*
 * Check if a header field contains the same username
 * as digest credentials
 */
static inline int check_username(struct sip_msg* _m, struct sip_uri *_uri)
{
	static db_ps_t my_ps = NULL;
	struct hdr_field* h;
	auth_body_t* c;
	db_key_t keys[3];
	db_val_t vals[3];
	db_key_t cols[1];
	db_res_t* res = NULL;

	if (_uri == NULL) {
		LM_ERR("Bad parameter\n");
		return ERR_INTERNAL;
	}

	/* Get authorized digest credentials */
	get_authorized_cred(_m->authorization, &h);
	if (h == NULL) {
		get_authorized_cred(_m->proxy_auth, &h);
		if (h == NULL) {
			LM_ERR("No authorized credentials found (error in scripts)\n");
			LM_ERR("Call {www,proxy}_authorize before calling check_* functions!\n");
			update_stat(negative_checks, 1);
			return ERR_CREDENTIALS;
		}
	}

	c = (auth_body_t*)(h->parsed);

	/* Parse To/From URI */
	/* Make sure that the URI contains username */
	if (_uri->user.len == 0) {
		LM_ERR("Username not found in URI\n");
		return ERR_USERNOTFOUND;
	}

	/* If use_uri_table is set, use URI table to determine if Digest username
	 * and To/From username match. URI table is a table enumerating all allowed
	 * usernames for a single, thus a user can have several different usernames
	 * (which are different from digest username and it will still match)
	 */
	if (use_uri_table != 0) {
		keys[0] = &uridb_user_col;
		keys[1] = &uridb_domain_col;
		keys[2] = &uridb_uriuser_col;
		cols[0] = &uridb_user_col;

		/* The whole fields are type DB_STR, and not null */
		VAL_TYPE(vals) = VAL_TYPE(vals + 1) = VAL_TYPE(vals + 2) = DB_STR;
		VAL_NULL(vals) = VAL_NULL(vals + 1) = VAL_NULL(vals + 2) = 0;

		VAL_STR(vals) = c->digest.username.user;
		VAL_STR(vals + 1) = *GET_REALM(&c->digest);
		VAL_STR(vals + 2) = _uri->user;

		uridb_dbf.use_table(db_handle, &db_table);
		CON_PS_REFERENCE(db_handle) = &my_ps;

		if (uridb_dbf.query(db_handle, keys, 0, vals, cols, 3, 1, 0, &res) < 0)
		{
			LM_ERR("Error while querying database\n");
			return ERR_DBQUERY;
		}

		/* If the previous function returns at least one row, it means
		 * there is an entry for given digest username and URI username
		 * and thus this combination is allowed and the function will match
		 */
		if (RES_ROW_N(res) == 0) {
			LM_DBG("From/To user '%.*s' is spoofed\n",
				   _uri->user.len, ZSW(_uri->user.s));
			uridb_dbf.free_result(db_handle, res);
			update_stat(negative_checks, 1);
			return ERR_SPOOFEDUSER;
		} else {
			LM_DBG("From/To user '%.*s' and auth user match\n",
				   _uri->user.len, ZSW(_uri->user.s));
			uridb_dbf.free_result(db_handle, res);
			update_stat(positive_checks, 1);
			return OK;
		}
	} else {
		/* URI table not used, simply compare digest username and From/To
		 * username, the comparison is case insensitive
		 */
		if (_uri->user.len == c->digest.username.user.len) {
			if (!strncasecmp(_uri->user.s, c->digest.username.user.s,
			_uri->user.len)) {
				LM_DBG("Digest username and URI username match\n");
				update_stat(positive_checks, 1);
				return OK;
			}
		}

		LM_DBG("Digest username and URI username do NOT match\n");
		update_stat(negative_checks, 1);
		return ERR_NOMATCH;
	}
}
Beispiel #19
0
/*
 * Check if a header field contains the same username
 * as digest credentials
 */
static inline int check_username(struct sip_msg* _m, str* _uri)
{
	struct hdr_field* h;
	auth_body_t* c;
	struct sip_uri puri;
	db_key_t keys[3];
	db_val_t vals[3];
	db_key_t cols[1];
	db_res_t* res;

	if (!_uri) {
		LOG(L_ERR, "check_username(): Bad parameter\n");
		return -1;
	}

	     /* Get authorized digest credentials */
	get_authorized_cred(_m->authorization, &h);
	if (!h) {
		get_authorized_cred(_m->proxy_auth, &h);
		if (!h) {
			LOG(L_ERR, "check_username(): No authorized credentials found (error in scripts)\n");
			LOG(L_ERR, "check_username(): Call {www,proxy}_authorize before calling check_* function !\n");
			return -2;
		}
	}

	c = (auth_body_t*)(h->parsed);

	     /* Parse To/From URI */
	if (parse_uri(_uri->s, _uri->len, &puri) < 0) {
		LOG(L_ERR, "check_username(): Error while parsing URI\n");
		return -3;
	}
	
	     /* Make sure that the URI contains username */
 	if (!puri.user.len) {
		LOG(L_ERR, "check_username(): Username not found in URI\n");
		return -4;
	}

	     /* If use_uri_table is set, use URI table to determine if Digest username
	      * and To/From username match. URI table is a table enumerating all allowed
	      * usernames for a single, thus a user can have several different usernames
	      * (which are different from digest username and it will still match)
	      */
	if (use_uri_table) {
		     /* Make sure that From/To URI domain and digest realm are equal
		      * FIXME: Should we move this outside this condition and make it general ?
		      */
		if (puri.host.len != c->digest.realm.len) {
			LOG(L_ERR, "check_username(): Digest realm and URI domain do not match\n");
			return -5;
		}

		if (strncasecmp(puri.host.s, c->digest.realm.s, puri.host.len) != 0) {
			DBG("check_username(): Digest realm and URI domain do not match\n");
			return -6;
		}

		if (db_use_table(db_handle, uri_table) < 0) {
			LOG(L_ERR, "check_username(): Error while trying to use uri table\n");
		}

		keys[0] = uri_user_col;
		keys[1] = uri_domain_col;
		keys[2] = uri_uriuser_col;
		cols[0] = uri_user_col;

		VAL_TYPE(vals) = VAL_TYPE(vals + 1) = VAL_TYPE(vals + 2) = DB_STR;
		VAL_NULL(vals) = VAL_NULL(vals + 1) = VAL_NULL(vals + 2) = 0;
    
		VAL_STR(vals) = c->digest.username.user;
    		VAL_STR(vals + 1) = c->digest.realm;
		VAL_STR(vals + 2) = puri.user;

		if (db_query(db_handle, keys, 0, vals, cols, 3, 1, 0, &res) < 0) {
			LOG(L_ERR, "check_username(): Error while querying database\n");
			return -7;
		}

		     /* If the previous function returns at least one row, it means
		      * there is an entry for given digest username and URI username
		      * and thus this combination is allowed and the function will match
		      */
		if (RES_ROW_N(res) == 0) {
			DBG("check_username(): From/To user '%.*s' is spoofed\n", 
			    puri.user.len, ZSW(puri.user.s));
			db_free_query(db_handle, res);
			return -8;
		} else {
			DBG("check_username(): From/To user '%.*s' and auth user match\n", 
			    puri.user.len, ZSW(puri.user.s));
			db_free_query(db_handle, res);
			return 1;
		}
	} else {
		     /* URI table not used, simply compare digest username and From/To
		      * username, the comparison is case insensitive
		      */
		if (puri.user.len == c->digest.username.user.len) {
			if (!strncasecmp(puri.user.s, c->digest.username.user.s, puri.user.len)) {
				DBG("check_username(): Digest username and URI username match\n");
				return 1;
			}
		}
	
		DBG("check_username(): Digest username and URI username do NOT match\n");
		return -9;
	}
}
Beispiel #20
0
/* it checks if a user is member of a group */
int diameter_is_user_in(struct sip_msg* _m, char* _hf, char* _group)
{
	str *grp, user_name, user, domain, uri;
	dig_cred_t* cred = 0;
	int hf_type;
	struct hdr_field* h;
	struct sip_uri puri;
	AAAMessage *req;
	AAA_AVP *avp; 
	int ret;
	unsigned int tmp;

	grp = (str*)_group; /* via fixup */

	hf_type = (int)(long)_hf;

	uri.s = 0;
	uri.len = 0;

	/* extract the uri according with the _hf parameter */
	switch(hf_type) 
	{
		case 1: /* Request-URI */
			uri = *(GET_RURI(_m));
		break;

		case 2: /* To */
			if (get_to_uri(_m, &uri) < 0) 
			{
				LM_ERR("failed to extract To\n");
				return -2;
			}
			break;

		case 3: /* From */
			if (get_from_uri(_m, &uri) < 0) 
			{
				LM_ERR("failed to extract From URI\n");
				return -3;
			}
			break;

		case 4: /* Credentials */
			get_authorized_cred(_m->authorization, &h);
			if (!h) 	
			{
				get_authorized_cred(_m->proxy_auth, &h);
				if (!h) 
				{
					LM_ERR("no authorized credentials found "
							"(error in scripts)\n");
					return -4;
				}
			}
			cred = &((auth_body_t*)(h->parsed))->digest;
			break;
	}

	if (hf_type != 4) 
	{
		if (parse_uri(uri.s, uri.len, &puri) < 0) 
		{
			LM_ERR("failed to parse URI\n");
			return -5;
		}
		user = puri.user;
		domain = puri.host;
	} 
	else
	{
		user = cred->username.user;
		domain = cred->realm;
	}
	
	/* user@domain mode */
	if (use_domain)
	{
		user_name.s = 0;
		user_name.len = user.len + domain.len;
		if(user_name.len>0)
		{
			user_name.len++;
			user_name.s = (char*)pkg_malloc(user_name.len);
			if (!user_name.s) 
			{
				LM_ERR("no pkg memory left\n");
				return -6;
			}
		
			memcpy(user_name.s, user.s, user.len);
			if(user.len>0)
			{
				user_name.s[user.len] = '@';
				memcpy(user_name.s + user.len + 1, domain.s, domain.len);
			}
			else
				memcpy(user_name.s, domain.s, domain.len);
		}
	} 
	else 
		user_name = user;
	
	
	if ( (req=AAAInMessage(AA_REQUEST, AAA_APP_NASREQ))==NULL)
	{
		LM_ERR("can't create new AAA message!\n");
		return -1;
	}
	
	/* Username AVP */
	if( (avp=AAACreateAVP(AVP_User_Name, 0, 0, user_name.s,
				user_name.len, AVP_DUPLICATE_DATA)) == 0)
	{
		LM_ERR("no more pkg memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LM_ERR("avp not added \n");
		goto error1;
	}

	/* Usergroup AVP */
	if( (avp=AAACreateAVP(AVP_User_Group, 0, 0, grp->s,
				grp->len, AVP_DUPLICATE_DATA)) == 0)
	{
		LM_ERR("no more pkg memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LM_ERR("avp not added \n");
		goto error1;
	}

	/* SIP_MSGID AVP */
	LM_DBG("******* m_id=%d\n", _m->id);
	tmp = _m->id;
	if( (avp=AAACreateAVP(AVP_SIP_MSGID, 0, 0, (char*)(&tmp), 
				sizeof(tmp), AVP_DUPLICATE_DATA)) == 0)
	{
		LM_ERR("no more pkg memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LM_ERR("avp not added \n");
		goto error1;
	}

	
	/* ServiceType AVP */
	if( (avp=AAACreateAVP(AVP_Service_Type, 0, 0, SIP_GROUP_CHECK, 
				SERVICE_LEN, AVP_DUPLICATE_DATA)) == 0)
	{
		LM_ERR("no more pkg memory!\n");
		goto error;
	}
	if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LM_ERR("avp not added \n");
		goto error1;
	}
	

	/* Destination-Realm AVP */
	uri = *(GET_RURI(_m));
	parse_uri(uri.s, uri.len, &puri);
	if( (avp=AAACreateAVP(AVP_Destination_Realm, 0, 0, puri.host.s,
						puri.host.len, AVP_DUPLICATE_DATA)) == 0)
	{
		LM_ERR("no more pkg memory!\n");
		goto error;
	}
	
	if( AAAAddAVPToMessage(req, avp, 0)!= AAA_ERR_SUCCESS)
	{
		LM_ERR("avp not added \n");
		goto error1;
	}
	
#ifdef DEBUG
	AAAPrintMessage(req);
#endif

	/* build a AAA message buffer */
	if(AAABuildMsgBuffer(req) != AAA_ERR_SUCCESS)
	{
		LM_ERR("message buffer not created\n");
		goto error;
	}

	if(sockfd==AAA_NO_CONNECTION)
	{
		sockfd = init_mytcp(diameter_client_host, diameter_client_port);
		if(sockfd==AAA_NO_CONNECTION)
		{
			LM_ERR("failed to reconnect to Diameter client\n");
			goto error;
		}
	}

	ret =tcp_send_recv(sockfd, req->buf.s, req->buf.len, rb, _m->id);

	if(ret == AAA_CONN_CLOSED)
	{
		LM_NOTICE("connection to Diameter client closed."
				"It will be reopened by the next request\n");
		close(sockfd);
		sockfd = AAA_NO_CONNECTION;
		goto error;
	}
	if(ret != AAA_USER_IN_GROUP)
	{
		LM_ERR("message sending to the DIAMETER backend authorization server"
				"failed or user is not in group\n");
		goto error;
	}
	
	AAAFreeMessage(&req);
	return 1;

error1:
	AAAFreeAVP(&avp);
error:
	AAAFreeMessage(&req);
	return -1;

}