⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 avp_radius.c

📁 性能优秀的SIP Proxy
💻 C
字号:
/* * $Id: avp_radius.c,v 1.11 2006/02/14 16:27:15 dan_pascu Exp $ * * Copyright (C) 2004 Juha Heinanen <jh@tutpro.com> * Copyright (C) 2004 FhG Fokus * * This file is part of openser, a free SIP server. * * openser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * openser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License  * along with this program; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * * History: * ------- * 2005-07-08: Radius AVP may contain any kind of OpenSER AVP - ID/name or *             int/str value (bogdan) */#include <radiusclient-ng.h>#include "../acc/dict.h"#include "../../sr_module.h"#include "../../mem/mem.h"#include "../../parser/digest/digest_parser.h"#include "../../parser/digest/digest.h"#include "../../parser/parse_uri.h"#include "../../parser/parse_from.h"#include "../../usr_avp.h"#include "../../ut.h"#include "../../config.h"MODULE_VERSION#define CALLER_PREFIX "caller_"#define CALLER_PREFIX_LEN (sizeof(CALLER_PREFIX) - 1)#define CALLEE_PREFIX "callee_"#define CALLEE_PREFIX_LEN (sizeof(CALLEE_PREFIX) - 1)typedef enum load_avp_param {	LOAD_CALLER,       /* Use the caller's username and domain as the key */	LOAD_CALLEE,       /* Use the callee's username and domain as the key */	LOAD_DIGEST} load_avp_param_t;static int mod_init(void);static int load_avp_radius(struct sip_msg*, char*, char*);static int load_avp_fixup(void**, int);static char *radius_config = DEFAULT_RADIUSCLEINT_CONF;static int caller_service_type = -1;static int callee_service_type = -1;static str caller_prefix = {CALLER_PREFIX, CALLER_PREFIX_LEN};static str callee_prefix = {CALLEE_PREFIX, CALLEE_PREFIX_LEN};static void *rh;struct attr attrs[A_MAX];struct val vals[V_MAX];/* * Exported functions */static cmd_export_t cmds[] = {	{"avp_load_radius", load_avp_radius, 1, load_avp_fixup, REQUEST_ROUTE | FAILURE_ROUTE},	{0, 0, 0, 0, 0}};/* * Exported parameters */static param_export_t params[] = {	{"radius_config",       STR_PARAM, &radius_config      },	{"caller_service_type", INT_PARAM, &caller_service_type},	{"callee_service_type", INT_PARAM, &callee_service_type},	{0, 0, 0}};	struct module_exports exports = {	"avp_radius", 	cmds,      /* Exported commands */	params,    /* Exported parameters */	0,         /* exported statistics */	mod_init,  /* module initialization function */	0,         /* response function*/	0,         /* destroy function */	0          /* per-child init function */};static int mod_init(void){	DBG("avp_radius - Initializing\n");	memset(attrs, 0, sizeof(attrs));	memset(vals, 0, sizeof(vals));	attrs[A_SERVICE_TYPE].n	  = "Service-Type";	attrs[A_USER_NAME].n	  = "User-Name";	attrs[A_SIP_AVP].n	  = "SIP-AVP";	vals[V_SIP_CALLER_AVPS].n = "SIP-Caller-AVPs";	vals[V_SIP_CALLEE_AVPS].n = "SIP-Callee-AVPs";	/* read config */	if ((rh = rc_read_config(radius_config)) == NULL) {		LOG(L_ERR, "ERROR:avp_radius:init: Error opening radius "			"config file: %s\n", radius_config);		return -1;	}	/* read dictionary */	if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0) {		LOG(L_ERR, "ERROR:avp_radius:init: Error reading radius dictionary\n");		return -1;	}		INIT_AV(rh, attrs, A_MAX, vals, "avp", -1, -1);	if (caller_service_type != -1) {		vals[V_SIP_CALLER_AVPS].v = caller_service_type;	}	if (callee_service_type != -1) {		vals[V_SIP_CALLEE_AVPS].v = callee_service_type;	}	return 0;}static inline int extract_avp(VALUE_PAIR* vp, unsigned short *flags,										int_str *name, int_str *value){	static str names, values;	unsigned int r;	char *p;	char *end;	/* empty? */	if (vp->lvalue==0 || vp->strvalue==0)		goto error;	p = vp->strvalue;	end = vp->strvalue + vp->lvalue;	/* get name */	if (*p!='#') {		/* name AVP */		*flags |= AVP_NAME_STR;		names.s = p;	} else {		names.s = ++p;	}	names.len = 0;	while( p<end && *p!=':' && *p!='#')		p++;	if (names.s==p || p==end) {		LOG(L_ERR,"ERROR:avp_radius:extract_avp: empty AVP name\n");		goto error;	}	names.len = p - names.s;	/* get value */	if (*p!='#') {		/* string value */		*flags |= AVP_VAL_STR;	}	values.s = ++p;	values.len = end-values.s;	if (values.len==0) {		LOG(L_ERR,"ERROR:avp_radius:extract_avp: empty AVP value\n");		goto error;	}	if ( !((*flags)&AVP_NAME_STR) ) {		/* convert name to id*/		if (str2int(&names,&r)!=0 ) {			LOG(L_ERR,"ERROR:avp_radius:extract_avp: invalid AVP ID '%.*s'\n",				names.len,names.s);			goto error;		}		name->n = (int)r;	} else {		name->s = names;	}	if ( !((*flags)&AVP_VAL_STR) ) {		/* convert value to integer */		if (str2int(&values,&r)!=0 ) {			LOG(L_ERR,"ERROR:avp_radius:extract_avp: invalid AVP numrical "				"value '%.*s'\n", values.len,values.s);			goto error;		}		value->n = (int)r;	} else {		value->s = values;	}	return 0;error:	return -1;}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) < 0) {			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;}static int load_avp_radius(struct sip_msg* msg, char* attr, char* _dummy){	switch((load_avp_param_t)attr) {	case LOAD_CALLER:		return load_avp_user(msg, &caller_prefix, LOAD_CALLER);		break;	case LOAD_CALLEE:		return load_avp_user(msg, &callee_prefix, LOAD_CALLEE);		break;			case LOAD_DIGEST:		return load_avp_user(msg, &caller_prefix, LOAD_DIGEST);	default:		LOG(L_ERR, "ERROR:avp_radius:load_avp_radius: "			"Unknown parameter value\n");		return -1;	}}static int load_avp_fixup(void** param, int param_no){	long id = 0;	if (param_no == 1) {		if (!strcasecmp(*param, "caller")) {			id = LOAD_CALLER;		} else if (!strcasecmp(*param, "callee")) {			id = LOAD_CALLEE;		} else if (!strcasecmp(*param, "digest")) {			id = LOAD_DIGEST;		} else {			LOG(L_ERR, "ERROR:avp_radius:load_avp_fixup: Unknown parameter\n");			return -1;		}	}	pkg_free(*param);	*param=(void*)id;	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -