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

📄 authorize.c

📁 性能优秀的SIP Proxy
💻 C
字号:
/* * $Id: authorize.c,v 1.9 2006/05/25 18:10:19 bogdan_iancu Exp $ * * Digest Authentication - Database support * * Copyright (C) 2001-2003 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: * --------- * 2003-02-28 scratchpad compatibility abandoned * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri) * 2004-06-06 updated to the new DB api, added auth_db_{init,bind,close,ver} *             (andrei) * 2005-05-31 general definition of AVPs in credentials now accepted - ID AVP, *            STRING AVP, AVP aliases (bogdan) * 2006-03-01 pseudo variables support for domain name (bogdan) */#include <string.h>#include "../../ut.h"#include "../../str.h"#include "../../db/db.h"#include "../../dprint.h"#include "../../parser/digest/digest.h"#include "../../parser/hf.h"#include "../../parser/parser_f.h"#include "../../usr_avp.h"#include "../../items.h"#include "../../mem/mem.h"#include "../auth/aaa_avps.h"#include "authdb_mod.h"#include "rfc2617.h"#define MESSAGE_500 "Server Internal Error"static inline int get_ha1(struct username* _username, str* _domain,			  char* _table, char* _ha1, db_res_t** res){	struct aaa_avp *cred;	db_key_t keys[2];	db_val_t vals[2];	db_key_t *col;	str result;	int n, nc;	col = pkg_malloc(sizeof(*col) * (credentials_n + 1));	if (col == NULL) {		LOG(L_ERR, "get_ha1(): Error while allocating memory\n");		return -1;	}	keys[0] = user_column.s;	keys[1] = domain_column.s;	col[0] = (_username->domain.len && !calc_ha1) ?		(pass_column_2.s) : (pass_column.s);	for (n = 0, cred=credentials; cred ; n++, cred=cred->next) {		col[1 + n] = cred->attr_name.s;	}	VAL_TYPE(vals) = VAL_TYPE(vals + 1) = DB_STR;	VAL_NULL(vals) = VAL_NULL(vals + 1) = 0;	VAL_STR(vals).s = _username->user.s;	VAL_STR(vals).len = _username->user.len;	if (_username->domain.len) {		VAL_STR(vals + 1) = _username->domain;	} else {		VAL_STR(vals + 1) = *_domain;	}	n = (use_domain ? 2 : 1);	nc = 1 + credentials_n;	if (auth_dbf.use_table(auth_db_handle, _table) < 0) {		LOG(L_ERR, "get_ha1(): Error in use_table\n");		pkg_free(col);		return -1;	}	if (auth_dbf.query(auth_db_handle, keys, 0, vals, col, n, nc, 0, res) < 0) {		LOG(L_ERR, "get_ha1(): Error while querying database\n");		pkg_free(col);		return -1;	}	pkg_free(col);	if (RES_ROW_N(*res) == 0) {		DBG("get_ha1(): no result for user \'%.*s@%.*s\'\n",			_username->user.len, ZSW(_username->user.s),			(use_domain ? (_domain->len) : 0), ZSW(_domain->s));		return 1;	}	result.s = (char*)ROW_VALUES(RES_ROWS(*res))[0].val.string_val;	result.len = strlen(result.s);	if (calc_ha1) {		/* Only plaintext passwords are stored in database,		 * we have to calculate HA1 */		calc_HA1(HA_MD5, &_username->whole, _domain, &result, 0, 0, _ha1);		DBG("HA1 string calculated: %s\n", _ha1);	} else {		memcpy(_ha1, result.s, result.len);		_ha1[result.len] = '\0';	}	return 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;	}}/* * Generate AVPs from the database result */static int generate_avps(db_res_t* result){	struct aaa_avp *cred;	int_str ivalue;	int i;	for (cred=credentials, i=1; cred; cred=cred->next, i++) {		switch (result->col.types[i]) {		case DB_STR:			ivalue.s = VAL_STR(&(result->rows[0].values[i]));			if (VAL_NULL(&(result->rows[0].values[i])) ||			ivalue.s.s == NULL || ivalue.s.len==0)				continue;			if (add_avp(cred->avp_type|AVP_VAL_STR,cred->avp_name,ivalue)!=0){				LOG(L_ERR,"ERROR:auth_db:generate_avps: failed to add AVP\n");				return -1;			}			DBG("generate_avps: set string AVP \"%s\"/%d = \"%.*s\"\n",				(cred->avp_type&AVP_NAME_STR)?cred->avp_name.s.s:"",				(cred->avp_type&AVP_NAME_STR)?0:cred->avp_name.n,				ivalue.s.len, ZSW(ivalue.s.s));			break;		case DB_STRING:			ivalue.s.s = (char*)VAL_STRING(&(result->rows[0].values[i]));			if (VAL_NULL(&(result->rows[0].values[i])) ||			ivalue.s.s == NULL || (ivalue.s.len=strlen(ivalue.s.s))==0 )				continue;			if (add_avp(cred->avp_type|AVP_VAL_STR,cred->avp_name,ivalue)!=0){				LOG(L_ERR,"ERROR:auth_db:generate_avps: failed to add AVP\n");				return -1;			}			DBG("generate_avps: set string AVP \"%s\"/%d = \"%.*s\"\n",				(cred->avp_type&AVP_NAME_STR)?cred->avp_name.s.s:"",				(cred->avp_type&AVP_NAME_STR)?0:cred->avp_name.n,				ivalue.s.len, ZSW(ivalue.s.s));			break;		case DB_INT:			if (VAL_NULL(&(result->rows[0].values[i])))				continue;			ivalue.n = (int)VAL_INT(&(result->rows[0].values[i]));			if (add_avp(cred->avp_type, cred->avp_name, ivalue)!=0) {				LOG(L_ERR,"ERROR:auth_db:generate_avps: failed to add AVP\n");				return -1;			}			DBG("generate_avps: set int AVP \"%s\"/%d = %d\n",				(cred->avp_type&AVP_NAME_STR)?cred->avp_name.s.s:"",				(cred->avp_type&AVP_NAME_STR)?0:cred->avp_name.n,				ivalue.n);			break;		default:			LOG(L_ERR, "ERROR:auth_db:generate_avps: subscriber table "				"column `%s' has unsuported type. Only string/str or int "				"columns are supported by load_credentials.\n",				result->col.names[i]);			break;		}	}	return 0;}/* * Authorize digest credentials */static inline int authorize(struct sip_msg* _m, xl_elem_t* _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;	if (_realm) {		if (xl_printf_s(_m, _realm, &domain)!=0) {			LOG(L_ERR, "ERROR:auth_db:authorize: xl_printf_s failed\n");			return -1;		}	} else {		domain.len = 0;		domain.s = 0;	}	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;}/* * Authorize using Proxy-Authorize header field */int proxy_authorize(struct sip_msg* _m, char* _realm, char* _table){	return authorize(_m, (xl_elem_t*)_realm, _table, HDR_PROXYAUTH_T);}/* * Authorize using WWW-Authorize header field */int www_authorize(struct sip_msg* _m, char* _realm, char* _table){	return authorize(_m, (xl_elem_t*)_realm, _table, HDR_AUTHORIZATION_T);}

⌨️ 快捷键说明

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