Add sample config file, implement verification
authorMark Spencer <markster@digium.com>
Fri, 25 Jun 2004 05:52:55 +0000 (05:52 +0000)
committerMark Spencer <markster@digium.com>
Fri, 25 Jun 2004 05:52:55 +0000 (05:52 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@3300 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/chan_sip.c
configs/osp.conf.sample [new file with mode: 0755]
include/asterisk/astosp.h
res/res_osp.c

index 3bc39b7..cf7462a 100755 (executable)
@@ -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 (executable)
index 0000000..b963cd3
--- /dev/null
@@ -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
index 92eeab8..4a5b59c 100755 (executable)
@@ -14,6 +14,7 @@
 #ifndef _ASTERISK_OSP_H
 #define _ASTERISK_OSP_H
 #include <asterisk/channel.h>
+#include <netinet/in.h>
 #include <time.h>
 
 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
index 6270c4a..c62735e 100755 (executable)
@@ -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;