From 2880b1df66d522a3074402f1e0915c28a3dbada7 Mon Sep 17 00:00:00 2001 From: markster Date: Fri, 25 Jun 2004 05:52:55 +0000 Subject: Add sample config file, implement verification git-svn-id: http://svn.digium.com/svn/asterisk/trunk@3300 f38db490-d61c-443f-a65b-d21fe96a405b --- channels/chan_sip.c | 111 ++++++++++++++++++++++++++++++++++++++++------ configs/osp.conf.sample | 56 +++++++++++++++++++++++ include/asterisk/astosp.h | 3 ++ res/res_osp.c | 61 +++++++++++++++++++++++++ 4 files changed, 218 insertions(+), 13 deletions(-) create mode 100755 configs/osp.conf.sample diff --git a/channels/chan_sip.c b/channels/chan_sip.c index 3bc39b703..cf7462a82 100755 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -158,6 +158,10 @@ static int globalrtpholdtimeout = 0; static int globaltrustrpid = 0; +#ifdef OSP_SUPPORT +static int globalospauth = 0; +#endif + static int usecnt =0; AST_MUTEX_DEFINE_STATIC(usecnt_lock); @@ -318,6 +322,7 @@ static struct sip_pvt { int pendingbye; /* Need to send bye after we ack? */ int gotrefer; /* Got a refer? */ #ifdef OSP_SUPPORT + int ospauth; /* Allow OSP Authentication */ int osphandle; /* OSP Handle for call */ time_t ospstart; /* OSP Start time */ #endif @@ -384,6 +389,9 @@ struct sip_user { int insecure; int canreinvite; int capability; +#ifdef OSP_SUPPORT + int ospauth; /* Allow OSP Authentication */ +#endif int dtmfmode; int inUse; int incominglimit; @@ -422,6 +430,9 @@ struct sip_peer { int rtptimeout; int rtpholdtimeout; int insecure; +#ifdef OSP_SUPPORT + int ospauth; /* Allow OSP Authentication */ +#endif int nat; int canreinvite; unsigned int callgroup; @@ -2216,6 +2227,9 @@ static struct sip_pvt *sip_alloc(char *callid, struct sockaddr_in *sin, int useg p->dtmfmode = globaldtmfmode; p->promiscredir = globalpromiscredir; p->trustrpid = globaltrustrpid; +#ifdef OSP_SUPPORT + p->ospauth = globalospauth; +#endif p->rtptimeout = globalrtptimeout; p->rtpholdtimeout = globalrtpholdtimeout; p->capability = capability; @@ -4322,8 +4336,16 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata char *reqheader = "Proxy-Authorization"; char *respheader = "Proxy-Authenticate"; char *authtoken; +#ifdef OSP_SUPPORT + char *osptoken; + unsigned int osptimelimit; +#endif /* Always OK if no secret */ - if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)) + if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret) +#ifdef OSP_SUPPORT + && !p->ospauth +#endif + ) return 0; if (!strcasecmp(method, "REGISTER")) { /* On a REGISTER, we have to use 401 and its family of headers instead of 407 and its family @@ -4333,6 +4355,21 @@ static int check_auth(struct sip_pvt *p, struct sip_request *req, char *randdata reqheader = "Authorization"; respheader = "WWW-Authenticate"; } +#ifdef OSP_SUPPORT + else if (p->ospauth) { + ast_log(LOG_DEBUG, "Checking OSP Authentication!\n"); + osptoken = get_header(req, "P-OSP-Auth-Token"); + /* Check for token existence */ + if (!strlen(osptoken)) + return -1; + /* Validate token */ + if (ast_osp_validate(NULL, osptoken, &p->osphandle, &osptimelimit, p->callerid, p->sa.sin_addr, p->exten) < 1) + return -1; + /* If ospauth is 'exclusive' don't require further authentication */ + if ((p->ospauth > 1) || (ast_strlen_zero(secret) && ast_strlen_zero(md5secret))) + return 0; + } +#endif authtoken = get_header(req, reqheader); if (ignore && !ast_strlen_zero(randdata) && ast_strlen_zero(authtoken)) { /* This is a retransmitted invite/register/etc, don't reconstruct authentication @@ -4984,6 +5021,18 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd user = find_user(of); if (user && ast_apply_ha(user->ha, sin)) { p->nat = user->nat; +#ifdef OSP_SUPPORT + p->ospauth = user->ospauth; +#endif + p->trustrpid = user->trustrpid; + /* replace callerid if rpid found, and not restricted */ + if(!ast_strlen_zero(rpid_num) && p->trustrpid) { + if (*calleridname) + sprintf(p->callerid,"\"%s\" <%s>",calleridname,rpid_num); + else + strncpy(p->callerid, rpid_num, sizeof(p->callerid) - 1); + } + if (p->rtp) { ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat); ast_rtp_setnat(p->rtp, p->nat); @@ -5004,7 +5053,6 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd strncpy(p->accountcode, user->accountcode, sizeof(p->accountcode) -1); strncpy(p->language, user->language, sizeof(p->language) -1); strncpy(p->musicclass, user->musicclass, sizeof(p->musicclass) -1); - p->trustrpid = user->trustrpid; p->canreinvite = user->canreinvite; p->amaflags = user->amaflags; p->callgroup = user->callgroup; @@ -5046,6 +5094,17 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd ast_verbose("Found peer '%s'\n", peer->name); /* Take the peer */ p->nat = peer->nat; + p->trustrpid = peer->trustrpid; + /* replace callerid if rpid found, and not restricted */ + if(!ast_strlen_zero(rpid_num) && p->trustrpid) { + if (*calleridname) + sprintf(p->callerid,"\"%s\" <%s>",calleridname,rpid_num); + else + strncpy(p->callerid, rpid_num, sizeof(p->callerid) - 1); + } +#ifdef OSP_SUPPORT + p->ospauth = peer->ospauth; +#endif if (p->rtp) { ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat); ast_rtp_setnat(p->rtp, p->nat); @@ -5087,8 +5146,6 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd else p->noncodeccapability &= ~AST_RTP_DTMF; } - p->trustrpid = peer->trustrpid; - } if (peer->temponly) { if (peer->ha) { @@ -5103,14 +5160,6 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, char *cmd } - /* replace callerid if rpid found, and not restricted */ - if(!ast_strlen_zero(rpid_num) && p->trustrpid) { - if (*calleridname) - sprintf(p->callerid,"\"%s\" <%s>",calleridname,rpid_num); - else - strncpy(p->callerid, rpid_num, sizeof(p->callerid) - 1); - } - return res; } static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, char *uri, int reliable, struct sockaddr_in *sin, int ignore) @@ -7489,6 +7538,9 @@ static struct sip_user *build_user(char *name, struct ast_variable *v) user->canreinvite = globalcanreinvite; user->trustrpid = globaltrustrpid; +#ifdef OSP_SUPPORT + user->ospauth = globalospauth; +#endif /* set default context */ strncpy(user->context, context, sizeof(user->context)-1); strncpy(user->language, language, sizeof(user->language)-1); @@ -7568,7 +7620,16 @@ static struct sip_user *build_user(char *name, struct ast_variable *v) } else if (!strcasecmp(v->name, "restrictcid")) { user->restrictcid = ast_true(v->value); } else if (!strcasecmp(v->name, "trustrpid")) { - user->trustrpid = ast_true(v->value); + user->trustrpid = ast_true(v->value); +#ifdef OSP_SUPPORT + } else if (!strcasecmp(v->name, "ospauth")) { + if (!strcasecmp(v->value, "exclusive")) { + user->ospauth = 2; + } else if (ast_true(v->value)) { + user->ospauth = 1; + } else + user->ospauth = 0; +#endif } /*else if (strcasecmp(v->name,"type")) * ast_log(LOG_WARNING, "Ignoring %s\n", v->name); @@ -7607,6 +7668,9 @@ static struct sip_peer *temp_peer(char *name) peer->selfdestruct = 1; peer->dynamic = 1; peer->trustrpid = globaltrustrpid; +#ifdef OSP_SUPPORT + peer->ospauth = globalospauth; +#endif reg_source_db(peer); return peer; } @@ -7668,6 +7732,9 @@ static struct sip_peer *build_peer(char *name, struct ast_variable *v) peer->dtmfmode = 0; peer->promiscredir = globalpromiscredir; peer->trustrpid = globaltrustrpid; +#ifdef OSP_SUPPORT + peer->ospauth = globalospauth; +#endif while(v) { if (!strcasecmp(v->name, "secret")) strncpy(peer->secret, v->value, sizeof(peer->secret)-1); @@ -7795,6 +7862,15 @@ static struct sip_peer *build_peer(char *name, struct ast_variable *v) } } else if (!strcasecmp(v->name, "trustrpid")) { peer->trustrpid = ast_true(v->value); +#ifdef OSP_SUPPORT + } else if (!strcasecmp(v->name, "ospauth")) { + if (!strcasecmp(v->value, "exclusive")) { + peer->ospauth = 2; + } else if (ast_true(v->value)) { + peer->ospauth = 1; + } else + peer->ospauth = 0; +#endif } /* else if (strcasecmp(v->name,"type")) * ast_log(LOG_WARNING, "Ignoring %s\n", v->name); @@ -7913,6 +7989,15 @@ static int reload_config(void) srvlookup = ast_true(v->value); } else if (!strcasecmp(v->name, "trustrpid")) { globaltrustrpid = ast_true(v->value); +#ifdef OSP_SUPPORT + } else if (!strcasecmp(v->name, "ospauth")) { + if (!strcasecmp(v->value, "exclusive")) { + globalospauth = 2; + } else if (ast_true(v->value)) { + globalospauth = 1; + } else + globalospauth = 0; +#endif } else if (!strcasecmp(v->name, "pedantic")) { pedanticsipchecking = ast_true(v->value); } else if (!strcasecmp(v->name, "canreinvite")) { diff --git a/configs/osp.conf.sample b/configs/osp.conf.sample new file mode 100755 index 000000000..b963cd3eb --- /dev/null +++ b/configs/osp.conf.sample @@ -0,0 +1,56 @@ +; +; Open Settlement Protocol Sample Configuration File +; +; +; This file contains configuration of providers that +; are used by the OSP subsystem of Asterisk. The section +; "general" is reserved for global options. Each other +; section declares an OSP Provider. The provider "default" +; is used when no provider is otherwise specified. +; +[general] +; +; Should hardware accelleration be enabled? May not be changed +; on a reload. +; +;accelerate=yes + +;[default] +; +; All paths are presumed to be under /var/lib/asterisk/keys unless +; the path begins with '/' +; +; Specify the private keyfile. If unspecified, defaults to the name +; of the section followed by "-privatekey.pem" (e.g. default-privatekey.pem) +; +;privatekey=pkey.pem +; +; Specify the local certificate file. If unspecified, defaults to +; the name of the section followed by "-localcert.pem" +; +;localcert=localcert.pem +; +; Specify one or more Certificate Authority keys. If none are listed, +; a single one is added with the name "-cacert.pem" +; +;cacert=cacert_0.pem +; +; Specific parameters can be tuned as well: +; +; maxconnections: Max number of simultaneous connections to the provider (default=20) +; retrydelay: Extra delay between retries (default=0) +; retrylimit: Max number of retries before giving up (default=2) +; timeout: Timeout for response in milliseconds (default=500) +; +;maxconnections=20 +;retrydelay=0 +;retrylimit=2 +;timeout=500 +; +; List all service points for this provider +; +;servicepoint=http://osptestserver.transnexus.com:1080/osp +; +; Set the "source" for requesting authorization +; +;source=foo diff --git a/include/asterisk/astosp.h b/include/asterisk/astosp.h index 92eeab82f..4a5b59c2e 100755 --- a/include/asterisk/astosp.h +++ b/include/asterisk/astosp.h @@ -14,6 +14,7 @@ #ifndef _ASTERISK_OSP_H #define _ASTERISK_OSP_H #include +#include #include struct ast_osp_result { @@ -32,4 +33,6 @@ int ast_osp_next(struct ast_osp_result *result, int cause); int ast_osp_terminate(int handle, int cause, time_t start, time_t duration); +int ast_osp_validate(char *provider, char *token, int *handle, unsigned int *timeout, char *callerid, struct in_addr addr, char *extension); + #endif diff --git a/res/res_osp.c b/res/res_osp.c index 6270c4a72..c62735ede 100755 --- a/res/res_osp.c +++ b/res/res_osp.c @@ -420,6 +420,67 @@ static int loadPemPrivateKey(unsigned char *FileName, unsigned char *buffer, int return retVal; } +int ast_osp_validate(char *provider, char *token, int *handle, unsigned int *timelimit, char *callerid, struct in_addr addr, char *extension) +{ + char tmp[256]="", *l, *n; + char ip[256]; + char source[OSP_MAX]; /* Same length as osp->source */ + char *token2; + int tokenlen; + struct osp_provider *osp; + int res = 0; + unsigned int authorised, dummy; + + if (!provider || !strlen(provider)) + provider = "default"; + + token2 = ast_strdupa(token); + if (!token2) + return -1; + tokenlen = ast_base64decode(token2, token, strlen(token)); + *handle = -1; + if (!callerid) + callerid = ""; + strncpy(tmp, callerid, sizeof(tmp) - 1); + ast_callerid_parse(tmp, &n, &l); + if (!l) + l = ""; + else { + ast_shrink_phone_number(l); + if (!ast_isphonenumber(l)) + l = ""; + } + callerid = l; + ast_mutex_lock(&osplock); + strcpy(ip, inet_ntoa(addr)); + osp = providers; + while(osp) { + if (!strcasecmp(osp->name, provider)) { + if (OSPPTransactionNew(osp->handle, handle)) { + ast_log(LOG_WARNING, "Unable to create OSP Transaction handle!\n"); + } else { + strcpy(source, osp->source); + res = 1; + } + break; + } + osp = osp->next; + } + ast_mutex_unlock(&osplock); + if (res) { + res = 0; + dummy = 0; + if (!OSPPTransactionValidateAuthorisation(*handle, ip, source, NULL, NULL, + callerid, OSPC_E164, extension, OSPC_E164, 0, "", tokenlen, token2, &authorised, timelimit, &dummy, NULL, TOKEN_ALGO_BOTH)) { + if (authorised) { + ast_log(LOG_DEBUG, "Validated token for '%s' from '%s@%s'\n", extension, callerid, ip); + res = 1; + } + } + } + return res; +} + int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, char *callerid, struct ast_osp_result *result) { int cres; -- cgit v1.2.3