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

📄 authorize.c

📁 用来作为linux中SIP SERVER,完成VOIP网络电话中服务器的功能
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: authorize.c,v 1.5.2.1 2005/07/20 17:11:50 andrei Exp $ * * Digest Authentication - Diameter support * * Copyright (C) 2001-2003 FhG Fokus * * This file is part of ser, a free SIP server. * * ser 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 *  * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: *    info@iptel.org * * ser 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: * ------- * 2003-09-11: updated to new build_lump_rpl() interface (bogdan) * 2003-11-11: build_lump_rpl() removed, add_lump_rpl() has flags  (bogdan) */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <netdb.h> #include <string.h>/* memory management */#include "../../mem/mem.h"#include "../../mem/shm_mem.h"/* printing messages, dealing with strings and other utils */#include "../../dprint.h"#include "../../str.h"#include "../../ut.h"/* digest parser headers */#include "../../parser/digest/digest.h"#include "../../parser/parse_uri.h"#include "../../parser/parse_from.h"#include "../../parser/parse_to.h"/* necessary when dealing with lumps */#include "../../data_lump_rpl.h"/* headers defined by this module */#include "diameter_msg.h"#include "auth_diameter.h"#include "defs.h"#include "authorize.h"#include "tcp_comm.h"/* Extract URI depending on the request from To or From header */int get_uri(struct sip_msg* m, str** uri){	if ((REQ_LINE(m).method.len == 8) && 					(memcmp(REQ_LINE(m).method.s, "REGISTER", 8) == 0)) 	{			/* REGISTER */		if (!m->to && ((parse_headers(m, HDR_TO, 0) == -1)|| (!m->to))) 		{			LOG(L_ERR, M_NAME":get_uri(): To header field not found or "				"malformed\n");						/* it was a REGISTER and an error appeared when parsing TO header*/			return -1;		}		*uri = &(get_to(m)->uri);	} 	else 	{		if (parse_from_header(m) == -1) 		{			LOG(L_ERR, M_NAME":get_uri(): Error while parsing FROM header\n");			/* an error appeared when parsing FROM header */			return -1;		}		*uri = &(get_from(m)->uri);	}    /* success */	return 0;}/* Return parsed To or From host part of the parsed uri (that is realm) */int get_realm(struct sip_msg* m, int hftype, struct sip_uri* u){	str uri;	/* extracting the uri */	if ((REQ_LINE(m).method.len==8)					&& !memcmp(REQ_LINE(m).method.s, "REGISTER", 8) 					&& (hftype == HDR_AUTHORIZATION) ) 	{ 		/* REGISTER */		if (!m->to && ((parse_headers(m, HDR_TO, 0) == -1) || (!m->to))) 		{			LOG(L_ERR, M_NAME":get_realm(): Error while parsing TO header\n");			/* signal the error */			return -1;		}			    /* Body of To header field is parsed automatically */		uri = get_to(m)->uri; 	} 	else 	{		if (parse_from_header(m)<0) 		{			LOG(L_ERR, M_NAME":get_realm(): Error while parsing FROM header\n");			/* signal the error */			return -1;		}		uri = get_from(m)->uri;	}		/* parsing the uri */	if (parse_uri(uri.s, uri.len, u) < 0) 	{		LOG(L_ERR, M_NAME":get_realm(): Error while parsing URI\n");		return -1;	}		/* everything was OK */	return 0;}/* Find credentials with given realm in a SIP message header */int find_credentials(struct sip_msg* _m, str* _realm, int _hftype, 				struct hdr_field** _h){	struct hdr_field** hook, *ptr, *prev;	int res;	str* r;      	switch(_hftype) 	{		case HDR_AUTHORIZATION: hook = &(_m->authorization); break;		case HDR_PROXYAUTH:     hook = &(_m->proxy_auth);    break;		default:                hook = &(_m->authorization); break;	}	          /* If the credentials haven't been parsed yet, do it now */	if (*hook == 0) 		if (parse_headers(_m, _hftype, 0) == -1) 		{			LOG(L_ERR, M_NAME":find_credentials(): Error while parsing headers\n");			return -1;		}		ptr = *hook;	/* Iterate through the credentials of the message to find 		credentials with given realm 	*/	while(ptr) 	{		res = parse_credentials(ptr);		if (res < 0) 		{			LOG(L_ERR, M_NAME":find_credentials(): Error while parsing "				"credentials\n");			return (res == -1) ? -2 : -3;		}		else 			if (res == 0) 			{				r = &(((auth_body_t*)(ptr->parsed))->digest.realm);					if (r->len == _realm->len) 				{					if (!strncasecmp(_realm->s, r->s, r->len)) 					{						*_h = ptr;						return 0;					}				}			}						prev = ptr;			if (parse_headers(_m, _hftype, 1) == -1) 			{				LOG(L_ERR, M_NAME":find_credentials(): Error while parsing"					" headers\n");				return -4;			}			else 			{					if (prev != _m->last_header) 				{					if (_m->last_header->type == _hftype) ptr = _m->last_header;					else break;				} 				else break;			}	}	          /* Credentials with given realm not found */	return 1;}auth_result_t pre_auth(struct sip_msg* _m, str* _realm, int _hftype, struct hdr_field** _h){	int ret;	struct sip_uri uri;	if ((_m->REQ_METHOD == METHOD_ACK) ||  (_m->REQ_METHOD == METHOD_CANCEL))		return AUTHORIZED;	/* if no realm supplied, find out now */	if (_realm==0 || _realm->len == 0) 	{		if (get_realm(_m, _hftype, &uri) < 0) 		{			LOG(L_ERR, M_NAME":pre_auth(): Error while extracting realm\n");			if (send_resp(_m, 400, MESSAGE_400, 0, 0) == -1) 			{				LOG(L_ERR, M_NAME":pre_auth(): Error while sending 400 reply\n");			}			return ERROR;		}				*_realm = uri.host;	}	ret = find_credentials(_m, _realm, _hftype, _h);	if (ret < 0) 	{		LOG(L_ERR, M_NAME":pre_auth(): Error while looking for credentials\n");		if (send_resp(_m, (ret == -2) ? 500 : 400, 			      (ret == -2) ? MESSAGE_500 : MESSAGE_400, 0, 0) == -1) 		{			LOG(L_ERR, M_NAME":pre_auth(): Error while sending 400 reply\n");		}		return ERROR;	} 	else 		if (ret > 0) 		{			LOG(L_ERR, M_NAME":pre_auth(): Credentials with given realm not "				"found\n");			return NO_CREDENTIALS;		}		return DO_AUTHORIZATION;}/* Authorize digest credentials */int authorize(struct sip_msg* msg, str* realm, int hftype){	auth_result_t ret;	struct hdr_field* h;	auth_body_t* cred = NULL;	str* uri;	struct sip_uri puri;	str  domain;	domain = *realm;	/* see what is to do after a first look at the message */	ret = pre_auth(msg, &domain, hftype, &h);		switch(ret) 	{		case ERROR:            return 0;			   		case AUTHORIZED:       return 1;		case NO_CREDENTIALS:   cred = NULL;							   break;		case DO_AUTHORIZATION: cred = (auth_body_t*)h->parsed;							   break;	}	if (get_uri(msg, &uri) < 0) 	{		LOG(L_ERR, M_NAME":authorize(): From/To URI not found\n");		return -1;	}		if (parse_uri(uri->s, uri->len, &puri) < 0) 	{		LOG(L_ERR, M_NAME":authorize(): Error while parsing From/To URI\n");		return -1;	}//	user.s = (char *)pkg_malloc(puri.user.len);//	un_escape(&(puri.user), &user);		/* parse the ruri, if not yet */	if(msg->parsed_uri_ok==0 && parse_sip_msg_uri(msg)<0)	{		LOG(L_ERR,M_NAME":authorize(): ERROR while parsing the Request-URI\n");		return -1;	}		/* preliminary check */	if(cred)	{		if (puri.host.len != cred->digest.realm.len) 		{			DBG(M_NAME":authorize(): Credentials realm and URI host do not "				"match\n");  			return -1;		}			if (strncasecmp(puri.host.s, cred->digest.realm.s, puri.host.len) != 0) 		{			DBG(M_NAME":authorize(): Credentials realm and URI host do not "				"match\n");			return -1;		}	}		if( diameter_authorize(cred?h:NULL, &msg->first_line.u.request.method,					puri, msg->parsed_uri, msg->id, rb) != 1)	{		send_resp(msg, 500, "Internal Server Error", NULL, 0);			return -1;	}		if( srv_response(msg, rb, hftype) != 1 )		return -1;	mark_authorized_cred(msg, h);	return 1;}/* * This function creates and submits diameter authentication request as per * draft-srinivas-aaa-basic-digest-00.txt.  * Service type of the request is Authenticate-Only. * Returns: * 		 1 - success * 		-1 - error * 			 */int diameter_authorize(struct hdr_field* hdr, str* p_method, struct sip_uri uri,						struct sip_uri ruri, unsigned int m_id, rd_buf_t* rb){	str method, user_name;	AAAMessage *req;	AAA_AVP *avp, *position; 	int name_flag, port_flag;	dig_cred_t* cred;	unsigned int tmp;	user_name.s=0; /* fixes gcc 4.0 warning */		if ( !p_method )	{		LOG(L_ERR, M_NAME":diameter_authorize(): Invalid parameter value\n");		return -1;

⌨️ 快捷键说明

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