Wed Oct 28 15:47:55 2009

Asterisk developer's documentation


res_osp.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Provide Open Settlement Protocol capability
00022  * 
00023  * \arg See also: \ref chan_sip.c
00024  */
00025 
00026 #include <sys/types.h>
00027 #include <osp.h>
00028 #include <openssl/err.h>
00029 #include <stdio.h>
00030 #include <dirent.h>
00031 #include <string.h>
00032 #include <errno.h>
00033 #include <unistd.h>
00034 #include <fcntl.h>
00035 #include <openssl/bio.h>
00036 #include <openssl/pem.h>
00037 #include <openssl/evp.h>
00038 
00039 #include "asterisk.h"
00040 
00041 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 211526 $")
00042 
00043 #include "asterisk/file.h"
00044 #include "asterisk/channel.h"
00045 #include "asterisk/logger.h"
00046 #include "asterisk/say.h"
00047 #include "asterisk/module.h"
00048 #include "asterisk/options.h"
00049 #include "asterisk/crypto.h"
00050 #include "asterisk/md5.h"
00051 #include "asterisk/cli.h"
00052 #include "asterisk/io.h"
00053 #include "asterisk/lock.h"
00054 #include "asterisk/astosp.h"
00055 #include "asterisk/config.h"
00056 #include "asterisk/utils.h"
00057 #include "asterisk/lock.h"
00058 #include "asterisk/causes.h"
00059 #include "asterisk/callerid.h"
00060 #include "asterisk/pbx.h"
00061 
00062 #define MAX_CERTS 10
00063 #define MAX_SERVICEPOINTS 10
00064 #define OSP_MAX 256
00065 
00066 #define OSP_DEFAULT_MAX_CONNECTIONS 20
00067 #define OSP_DEFAULT_RETRY_DELAY     0
00068 #define OSP_DEFAULT_RETRY_LIMIT     2
00069 #define OSP_DEFAULT_TIMEOUT         500
00070 
00071 static int loadPemCert(unsigned char *FileName, unsigned char *buffer, int *len);
00072 static int loadPemPrivateKey(unsigned char *FileName, unsigned char *buffer, int *len);
00073 
00074 AST_MUTEX_DEFINE_STATIC(osplock);
00075 
00076 static int initialized = 0;
00077 static int hardware = 0;
00078 static unsigned tokenformat = TOKEN_ALGO_SIGNED;
00079 
00080 struct osp_provider {
00081    char name[OSP_MAX];
00082    char localpvtkey[OSP_MAX];
00083    char localcert[OSP_MAX];
00084    char cacerts[MAX_CERTS][OSP_MAX]; 
00085    int cacount;
00086    char servicepoints[MAX_SERVICEPOINTS][OSP_MAX];
00087    char source[OSP_MAX];
00088    int spcount;
00089    int dead;
00090    int maxconnections;
00091    int retrydelay;
00092    int retrylimit;
00093    int timeout;
00094    OSPTPROVHANDLE handle;
00095    struct osp_provider *next;
00096 };
00097 static struct osp_provider *providers;
00098 
00099 static int osp_build(struct ast_config *cfg, char *cat)
00100 {
00101    OSPTCERT TheAuthCert[MAX_CERTS];
00102    unsigned char Reqbuf[4096],LocalBuf[4096],AuthBuf[MAX_CERTS][4096];
00103    struct ast_variable *v;
00104    struct osp_provider *osp;
00105    int x,length,errorcode=0;
00106    int mallocd=0,i;
00107    char *cacerts[MAX_CERTS];
00108    const char *servicepoints[MAX_SERVICEPOINTS];
00109    OSPTPRIVATEKEY privatekey;
00110    OSPTCERT localcert;
00111    OSPTCERT *authCerts[MAX_CERTS];
00112 
00113    
00114    
00115    ast_mutex_lock(&osplock);
00116    osp = providers;
00117    while(osp) {
00118       if (!strcasecmp(osp->name, cat))
00119          break;
00120       osp = osp->next;
00121    }
00122    ast_mutex_unlock(&osplock);
00123    if (!osp) {
00124       mallocd = 1;
00125       osp = malloc(sizeof(struct osp_provider));
00126       if (!osp) {
00127          ast_log(LOG_WARNING, "Out of memory!\n");
00128          return -1;
00129       }
00130       memset(osp, 0, sizeof(struct osp_provider));
00131       osp->handle = -1;
00132    }
00133    ast_copy_string(osp->name, cat, sizeof(osp->name));
00134    snprintf(osp->localpvtkey, sizeof(osp->localpvtkey) ,"%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, cat);
00135    snprintf(osp->localcert, sizeof(osp->localpvtkey), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, cat);
00136    osp->maxconnections=OSP_DEFAULT_MAX_CONNECTIONS;
00137    osp->retrydelay = OSP_DEFAULT_RETRY_DELAY;
00138    osp->retrylimit = OSP_DEFAULT_RETRY_LIMIT;
00139    osp->timeout = OSP_DEFAULT_TIMEOUT;
00140    osp->source[0] = '\0';
00141    ast_log(LOG_DEBUG, "Building OSP Provider '%s'\n", cat);
00142    v = ast_variable_browse(cfg, cat);
00143    while(v) {
00144       if (!strcasecmp(v->name, "privatekey")) {
00145          if (v->value[0] == '/')
00146             ast_copy_string(osp->localpvtkey, v->value, sizeof(osp->localpvtkey));
00147          else
00148             snprintf(osp->localpvtkey, sizeof(osp->localpvtkey), "%s/%s", ast_config_AST_KEY_DIR , v->value);
00149       } else if (!strcasecmp(v->name, "localcert")) {
00150          if (v->value[0] == '/')
00151             ast_copy_string(osp->localcert, v->value, sizeof(osp->localcert));
00152          else
00153             snprintf(osp->localcert, sizeof(osp->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
00154       } else if (!strcasecmp(v->name, "cacert")) {
00155          if (osp->cacount < MAX_CERTS) {
00156             if (v->value[0] == '/')
00157                ast_copy_string(osp->cacerts[osp->cacount], v->value, sizeof(osp->cacerts[0]));
00158             else
00159                snprintf(osp->cacerts[osp->cacount], sizeof(osp->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
00160             osp->cacount++;
00161          } else
00162             ast_log(LOG_WARNING, "Too many CA Certificates at line %d\n", v->lineno);
00163       } else if (!strcasecmp(v->name, "servicepoint")) {
00164          if (osp->spcount < MAX_SERVICEPOINTS) {
00165             ast_copy_string(osp->servicepoints[osp->spcount], v->value, sizeof(osp->servicepoints[0]));
00166             osp->spcount++;
00167          } else
00168             ast_log(LOG_WARNING, "Too many Service points at line %d\n", v->lineno);
00169       } else if (!strcasecmp(v->name, "maxconnections")) {
00170          if ((sscanf(v->value, "%30d", &x) == 1) && (x > 0) && (x <= 1000)) {
00171             osp->maxconnections = x;
00172          } else
00173             ast_log(LOG_WARNING, "maxconnections should be an integer from 1 to 1000, not '%s' at line %d\n", v->value, v->lineno);
00174       } else if (!strcasecmp(v->name, "retrydelay")) {
00175          if ((sscanf(v->value, "%30d", &x) == 1) && (x >= 0) && (x <= 10)) {
00176             osp->retrydelay = x;
00177          } else
00178             ast_log(LOG_WARNING, "retrydelay should be an integer from 0 to 10, not '%s' at line %d\n", v->value, v->lineno);
00179       } else if (!strcasecmp(v->name, "retrylimit")) {
00180          if ((sscanf(v->value, "%30d", &x) == 1) && (x >= 0) && (x <= 100)) {
00181             osp->retrylimit = x;
00182          } else
00183             ast_log(LOG_WARNING, "retrylimit should be an integer from 0 to 100, not '%s' at line %d\n", v->value, v->lineno);
00184       } else if (!strcasecmp(v->name, "timeout")) {
00185          if ((sscanf(v->value, "%30d", &x) == 1) && (x >= 200) && (x <= 10000)) {
00186             osp->timeout = x;
00187          } else
00188             ast_log(LOG_WARNING, "timeout should be an integer from 200 to 10000, not '%s' at line %d\n", v->value, v->lineno);
00189       } else if (!strcasecmp(v->name, "source")) {
00190          ast_copy_string(osp->source, v->value, sizeof(osp->source));
00191       }
00192       v = v->next;
00193    }
00194    if (osp->cacount < 1) {
00195       snprintf(osp->cacerts[osp->cacount], sizeof(osp->cacerts[0]), "%s/%s-cacert.pem", ast_config_AST_KEY_DIR, cat);
00196       osp->cacount++;
00197    }
00198    for (x=0;x<osp->cacount;x++)
00199       cacerts[x] = osp->cacerts[x];
00200    for (x=0;x<osp->spcount;x++)
00201       servicepoints[x] = osp->servicepoints[x];
00202    
00203    ast_mutex_lock(&osplock);
00204    osp->dead = 0;
00205    if (osp->handle > -1) {
00206       ast_log(LOG_DEBUG, "Deleting old handle for '%s'\n", osp->name);
00207       OSPPProviderDelete(osp->handle, 0);
00208    }
00209       
00210 
00211     length = 0;
00212    ast_log(LOG_DEBUG, "Loading private key for '%s' (%s)\n", osp->name, osp->localpvtkey);
00213     errorcode = loadPemPrivateKey(osp->localpvtkey,Reqbuf,&length);
00214     if (errorcode == 0)
00215     {
00216         privatekey.PrivateKeyData = Reqbuf;
00217         privatekey.PrivateKeyLength = length;
00218     }
00219     else
00220     {
00221          return -1;
00222     }
00223 
00224     length = 0;
00225    ast_log(LOG_DEBUG, "Loading local cert for '%s' (%s)\n", osp->name, osp->localcert);
00226     errorcode = loadPemCert(osp->localcert,LocalBuf,&length);
00227     if (errorcode == 0)
00228     {
00229         localcert.CertData = LocalBuf;
00230         localcert.CertDataLength = length;
00231     }
00232     else
00233     {
00234          return -1;
00235     }
00236 
00237     for (i=0;i<osp->cacount;i++)
00238     {
00239         length = 0;
00240       ast_log(LOG_DEBUG, "Loading CA cert %d for '%s' (%s)\n", i + 1, osp->name, osp->cacerts[i]);
00241         errorcode = loadPemCert(osp->cacerts[i],AuthBuf[i],&length);
00242         if (errorcode == 0)
00243         {
00244             TheAuthCert[i].CertData = AuthBuf[i];
00245             TheAuthCert[i].CertDataLength = length;
00246             authCerts[i] = &(TheAuthCert[i]);
00247         }
00248         else
00249         {
00250          return -1;        
00251       }
00252     }
00253    
00254    ast_log(LOG_DEBUG, "Creating provider handle for '%s'\n", osp->name);
00255    
00256    ast_log(LOG_DEBUG, "Service point '%s %d'\n", servicepoints[0], osp->spcount);
00257    
00258    if (OSPPProviderNew(osp->spcount, 
00259                    servicepoints, 
00260                   NULL, 
00261                   "localhost", 
00262                   &privatekey, 
00263                   &localcert, 
00264                   osp->cacount, 
00265                   (const OSPTCERT **)authCerts, 
00266                   1, 
00267                   300, 
00268                   osp->maxconnections, 
00269                   1, 
00270                   osp->retrydelay, 
00271                   osp->retrylimit, 
00272                   osp->timeout, 
00273                   "", 
00274                   "", 
00275                   &osp->handle)) {
00276       ast_log(LOG_WARNING, "Unable to initialize provider '%s'\n", cat);
00277       osp->dead = 1;
00278    }
00279    
00280    if (mallocd) {
00281       osp->next = providers;
00282       providers = osp;
00283    }
00284    ast_mutex_unlock(&osplock);   
00285    return 0;
00286 }
00287 
00288 static int show_osp(int fd, int argc, char *argv[])
00289 {
00290    struct osp_provider *osp;
00291    char *search = NULL;
00292    int x;
00293    int found = 0;
00294    char *tokenalgo;
00295 
00296    if ((argc < 2) || (argc > 3))
00297       return RESULT_SHOWUSAGE;
00298    if (argc > 2)
00299       search = argv[2];
00300    if (!search) {
00301       switch (tokenformat) {
00302          case TOKEN_ALGO_BOTH:
00303             tokenalgo = "Both";
00304             break;
00305          case TOKEN_ALGO_UNSIGNED:
00306             tokenalgo = "Unsigned";
00307             break;
00308          case TOKEN_ALGO_SIGNED:
00309          default:
00310             tokenalgo = "Signed";
00311             break;
00312       }
00313       ast_cli(fd, "OSP: %s %s %s\n", initialized ? "Initialized" : "Uninitialized", hardware ? "Accelerated" : "Normal", tokenalgo);
00314    }
00315 
00316    ast_mutex_lock(&osplock);
00317    osp = providers;
00318    while(osp) {
00319       if (!search || !strcasecmp(osp->name, search)) {
00320          if (found)
00321             ast_cli(fd, "\n");
00322          ast_cli(fd, " == OSP Provider '%s' ==\n", osp->name);
00323          ast_cli(fd, "Local Private Key: %s\n", osp->localpvtkey);
00324          ast_cli(fd, "Local Certificate: %s\n", osp->localcert);
00325          for (x=0;x<osp->cacount;x++)
00326             ast_cli(fd, "CA Certificate %d:  %s\n", x + 1, osp->cacerts[x]);
00327          for (x=0;x<osp->spcount;x++)
00328             ast_cli(fd, "Service Point %d:   %s\n", x + 1, osp->servicepoints[x]);
00329          ast_cli(fd, "Max Connections:   %d\n", osp->maxconnections);
00330          ast_cli(fd, "Retry Delay:       %d seconds\n", osp->retrydelay);
00331          ast_cli(fd, "Retry Limit:       %d\n", osp->retrylimit);
00332          ast_cli(fd, "Timeout:           %d milliseconds\n", osp->timeout);
00333          ast_cli(fd, "Source:            %s\n", strlen(osp->source) ? osp->source : "<unspecified>");
00334          ast_cli(fd, "OSP Handle:        %d\n", osp->handle);
00335          found++;
00336       }
00337       osp = osp->next;
00338    }
00339    ast_mutex_unlock(&osplock);
00340    if (!found) {
00341       if (search) 
00342          ast_cli(fd, "Unable to find OSP provider '%s'\n", search);
00343       else
00344          ast_cli(fd, "No OSP providers configured\n");
00345    }
00346    return RESULT_SUCCESS;
00347 }
00348 
00349 
00350 /*----------------------------------------------*
00351  *               Loads the Certificate          *
00352  *----------------------------------------------*/
00353 static int loadPemCert(unsigned char *FileName, unsigned char *buffer, int *len)
00354 {
00355     int length = 0;
00356     unsigned char *temp;
00357     BIO *bioIn = NULL;
00358     X509 *cert=NULL;
00359     int retVal = OSPC_ERR_NO_ERROR;
00360 
00361     temp = buffer;
00362     bioIn = BIO_new_file((const char*)FileName,"r");
00363     if (bioIn == NULL)
00364     {
00365       ast_log(LOG_WARNING,"Failed to find the File - %s \n",FileName);
00366       return -1;
00367     }
00368     else
00369     {
00370         cert = PEM_read_bio_X509(bioIn,NULL,NULL,NULL);
00371         if (cert == NULL)
00372         {
00373          ast_log(LOG_WARNING,"Failed to parse the Certificate from the File - %s \n",FileName);
00374          return -1;
00375         }
00376         else
00377         {
00378             length = i2d_X509(cert,&temp);
00379             if (cert == 0)
00380             {
00381             ast_log(LOG_WARNING,"Failed to parse the Certificate from the File - %s, Length=0 \n",FileName);
00382             return -1;
00383             }
00384             else
00385          {
00386                *len = length;
00387             }
00388         }
00389     }
00390 
00391     if (bioIn != NULL)
00392     {
00393         BIO_free(bioIn);
00394     }
00395 
00396     if (cert != NULL)
00397     {
00398         X509_free(cert);
00399     }
00400     return retVal;
00401 }
00402 
00403 /*----------------------------------------------*
00404  *               Loads the Private Key          *
00405  *----------------------------------------------*/
00406 static int loadPemPrivateKey(unsigned char *FileName, unsigned char *buffer, int *len)
00407 {
00408     int length = 0;
00409     unsigned char *temp;
00410     BIO *bioIn = NULL;
00411     RSA *pKey = NULL;
00412     int retVal = OSPC_ERR_NO_ERROR;
00413 
00414     temp = buffer;
00415 
00416     bioIn = BIO_new_file((const char*)FileName,"r");
00417     if (bioIn == NULL)
00418     {
00419       ast_log(LOG_WARNING,"Failed to find the File - %s \n",FileName);
00420       return -1;
00421     }
00422     else
00423     {
00424         pKey = PEM_read_bio_RSAPrivateKey(bioIn,NULL,NULL,NULL);
00425         if (pKey == NULL)
00426         {
00427          ast_log(LOG_WARNING,"Failed to parse the Private Key from the File - %s \n",FileName);
00428          return -1;
00429         }
00430         else
00431         {
00432             length = i2d_RSAPrivateKey(pKey,&temp);
00433             if (length == 0)
00434             {
00435             ast_log(LOG_WARNING,"Failed to parse the Private Key from the File - %s, Length=0 \n",FileName);
00436             return -1;
00437             }
00438             else
00439             {
00440                 *len = length;
00441             }
00442         }
00443     }
00444     if (bioIn != NULL)
00445     {
00446         BIO_free(bioIn);
00447     }
00448 
00449     if (pKey != NULL)
00450     {
00451        RSA_free(pKey);
00452     }
00453     return retVal;
00454 }
00455 
00456 int ast_osp_validate(char *provider, char *token, int *handle, unsigned int *timelimit, char *callerid, struct in_addr addr, char *extension)
00457 {
00458    char tmp[256]="", *l, *n;
00459    char iabuf[INET_ADDRSTRLEN];
00460    char source[OSP_MAX] = ""; /* Same length as osp->source */
00461    char *token2;
00462    int tokenlen;
00463    struct osp_provider *osp;
00464    int res = 0;
00465    unsigned int authorised, dummy;
00466 
00467    if (!provider || !strlen(provider))
00468       provider = "default";
00469 
00470    token2 = ast_strdupa(token);
00471    if (!token2)
00472       return -1;
00473    tokenlen = ast_base64decode(token2, token, strlen(token));
00474    *handle = -1;
00475    if (!callerid)
00476       callerid = "";
00477    ast_copy_string(tmp, callerid, sizeof(tmp));
00478    ast_callerid_parse(tmp, &n, &l);
00479    if (!l)
00480       l = "";
00481    else {
00482       ast_shrink_phone_number(l);
00483       if (!ast_isphonenumber(l))
00484          l = "";
00485    }
00486    callerid = l;
00487    ast_mutex_lock(&osplock);
00488    ast_inet_ntoa(iabuf, sizeof(iabuf), addr);
00489    osp = providers;
00490    while(osp) {
00491       if (!strcasecmp(osp->name, provider)) {
00492          if (OSPPTransactionNew(osp->handle, handle)) {
00493             ast_log(LOG_WARNING, "Unable to create OSP Transaction handle!\n");
00494          } else {
00495             ast_copy_string(source, osp->source, sizeof(source));
00496             res = 1;
00497          }
00498          break;
00499       }
00500       osp = osp->next;
00501    }
00502    ast_mutex_unlock(&osplock);
00503    if (res) {
00504       res = 0;
00505       dummy = 0;
00506       if (!OSPPTransactionValidateAuthorisation(*handle, iabuf, source, NULL, NULL, 
00507          callerid, OSPC_E164, extension, OSPC_E164, 0, "", tokenlen, token2, &authorised, timelimit, &dummy, NULL, tokenformat)) {
00508          if (authorised) {
00509             ast_log(LOG_DEBUG, "Validated token for '%s' from '%s@%s'\n", extension, callerid, iabuf);
00510             res = 1;
00511          }
00512       }
00513    }
00514    return res; 
00515 }
00516 
00517 int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, char *callerid, struct ast_osp_result *result)
00518 {
00519    int cres;
00520    int res = 0;
00521    int counts;
00522    int tokenlen;
00523    unsigned int dummy=0;
00524    unsigned int timelimit;
00525    unsigned int callidlen;
00526    char callidstr[OSPC_CALLID_MAXSIZE] = "";
00527    struct osp_provider *osp;
00528    char source[OSP_MAX] = ""; /* Same length as osp->source */
00529    char callednum[2048]="";
00530    char callingnum[2048]="";
00531    char destination[2048]="";
00532    char token[2000];
00533    char tmp[256]="", *l, *n;
00534    OSPE_DEST_PROT prot;
00535    OSPE_DEST_OSP_ENABLED ospenabled;
00536    char *devinfo = NULL;
00537 
00538    result->handle = -1;
00539    result->numresults = 0;
00540    result->tech[0] = '\0';
00541    result->dest[0] = '\0';
00542    result->token[0] = '\0';
00543 
00544    if (!provider || !strlen(provider))
00545       provider = "default";
00546 
00547    if (!callerid)
00548       callerid = "";
00549    ast_copy_string(tmp, callerid, sizeof(tmp));
00550    ast_callerid_parse(tmp, &n, &l);
00551    if (!l)
00552       l = "";
00553    else {
00554       ast_shrink_phone_number(l);
00555       if (!ast_isphonenumber(l))
00556          l = "";
00557    }
00558    callerid = l;
00559 
00560    if (chan) {
00561       cres = ast_autoservice_start(chan);
00562       if (cres < 0)
00563          return cres;
00564    }
00565    ast_mutex_lock(&osplock);
00566    osp = providers;
00567    while(osp) {
00568       if (!strcasecmp(osp->name, provider)) {
00569          if (OSPPTransactionNew(osp->handle, &result->handle)) {
00570             ast_log(LOG_WARNING, "Unable to create OSP Transaction handle!\n");
00571          } else {
00572             ast_copy_string(source, osp->source, sizeof(source));
00573             res = 1;
00574          }
00575          break;
00576       }
00577       osp = osp->next;
00578    }
00579    ast_mutex_unlock(&osplock);
00580    if (res) {
00581       res = 0;
00582       /* No more than 10 back */
00583       counts = 10;
00584       dummy = 0;
00585       devinfo = pbx_builtin_getvar_helper (chan, "OSPPEER");
00586       if (!devinfo) {
00587          devinfo = "";
00588       }
00589       if (!OSPPTransactionRequestAuthorisation(result->handle, source, devinfo, 
00590            callerid,OSPC_E164, extension, OSPC_E164, NULL, 0, NULL, NULL, &counts, &dummy, NULL)) {
00591          if (counts) {
00592             tokenlen = sizeof(token);
00593             result->numresults = counts - 1;
00594             callidlen = sizeof(callidstr);
00595             if (!OSPPTransactionGetFirstDestination(result->handle, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
00596                sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
00597                ast_log(LOG_DEBUG, "Got destination '%s' and called: '%s' calling: '%s' for '%s' (provider '%s')\n",
00598                   destination, callednum, callingnum, extension, provider);
00599                /* Only support OSP server with only one duration limit */
00600                if (ast_channel_cmpwhentohangup (chan, timelimit) < 0) {
00601                   ast_channel_setwhentohangup (chan, timelimit);  
00602                }
00603                do {
00604                   if (!OSPPTransactionIsDestOSPEnabled (result->handle, &ospenabled) && (ospenabled == OSPE_OSP_FALSE)) {
00605                      result->token[0] = 0;
00606                   }
00607                   else {
00608                      ast_base64encode(result->token, token, tokenlen, sizeof(result->token) - 1);
00609                   }
00610                   if ((strlen(destination) > 2) && !OSPPTransactionGetDestProtocol(result->handle, &prot)) {
00611                      res = 1;
00612                      /* Strip leading and trailing brackets */
00613                      destination[strlen(destination) - 1] = '\0';
00614                      switch(prot) {
00615                      case OSPE_DEST_PROT_H323_SETUP:
00616                         ast_copy_string(result->tech, "H323", sizeof(result->tech));
00617                         snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
00618                         break;
00619                      case OSPE_DEST_PROT_SIP:
00620                         ast_copy_string(result->tech, "SIP", sizeof(result->tech));
00621                         snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
00622                         break;
00623                      case OSPE_DEST_PROT_IAX:
00624                         ast_copy_string(result->tech, "IAX", sizeof(result->tech));
00625                         snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
00626                         break;
00627                      default:
00628                         ast_log(LOG_DEBUG, "Unknown destination protocol '%d', skipping...\n", prot);
00629                         res = 0;
00630                      }
00631                      if (!res && result->numresults) {
00632                         result->numresults--;
00633                         callidlen = sizeof(callidstr);
00634                         if (OSPPTransactionGetNextDestination(result->handle, OSPC_FAIL_INCOMPATIBLE_DEST, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
00635                               sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
00636                               break;
00637                         }
00638                      }
00639                   } else {
00640                      ast_log(LOG_DEBUG, "Missing destination protocol\n");
00641                      break;
00642                   }
00643                } while(!res && result->numresults);
00644             }
00645          }
00646          
00647       }
00648       if (!res) {
00649          OSPPTransactionDelete(result->handle);
00650          result->handle = -1;
00651       }
00652       
00653    }
00654    if (!osp) 
00655       ast_log(LOG_NOTICE, "OSP Provider '%s' does not exist!\n", provider);
00656    if (chan) {
00657       cres = ast_autoservice_stop(chan);
00658       if (cres < 0)
00659          return cres;
00660    }
00661    return res;
00662 }
00663 
00664 int ast_osp_next(struct ast_osp_result *result, int cause)
00665 {
00666    int res = 0;
00667    int tokenlen;
00668    unsigned int dummy=0;
00669    unsigned int timelimit;
00670    unsigned int callidlen;
00671    char callidstr[OSPC_CALLID_MAXSIZE] = "";
00672    char callednum[2048]="";
00673    char callingnum[2048]="";
00674    char destination[2048]="";
00675    char token[2000];
00676    OSPE_DEST_PROT prot;
00677    OSPE_DEST_OSP_ENABLED ospenabled;
00678 
00679    result->tech[0] = '\0';
00680    result->dest[0] = '\0';
00681    result->token[0] = '\0';
00682 
00683    if (result->handle > -1) {
00684       dummy = 0;
00685       if (result->numresults) {
00686          tokenlen = sizeof(token);
00687          while(!res && result->numresults) {
00688             result->numresults--;
00689             callidlen = sizeof(callidstr);
00690             if (!OSPPTransactionGetNextDestination(result->handle, OSPC_FAIL_INCOMPATIBLE_DEST, 0, NULL, NULL, &timelimit, &callidlen, callidstr, 
00691                            sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token)) {
00692                if (!OSPPTransactionIsDestOSPEnabled (result->handle, &ospenabled) && (ospenabled == OSPE_OSP_FALSE)) {
00693                   result->token[0] = 0;
00694                }
00695                else {
00696                   ast_base64encode(result->token, token, tokenlen, sizeof(result->token) - 1);
00697                }
00698                if ((strlen(destination) > 2) && !OSPPTransactionGetDestProtocol(result->handle, &prot)) {
00699                   res = 1;
00700                   /* Strip leading and trailing brackets */
00701                   destination[strlen(destination) - 1] = '\0';
00702                   switch(prot) {
00703                   case OSPE_DEST_PROT_H323_SETUP:
00704                      ast_copy_string(result->tech, "H323", sizeof(result->tech));
00705                      snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
00706                      break;
00707                   case OSPE_DEST_PROT_SIP:
00708                      ast_copy_string(result->tech, "SIP", sizeof(result->tech));
00709                      snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
00710                      break;
00711                   case OSPE_DEST_PROT_IAX:
00712                      ast_copy_string(result->tech, "IAX", sizeof(result->tech));
00713                      snprintf(result->dest, sizeof(result->dest), "%s@%s", callednum, destination + 1);
00714                      break;
00715                   default:
00716                      ast_log(LOG_DEBUG, "Unknown destination protocol '%d', skipping...\n", prot);
00717                      res = 0;
00718                   }
00719                } else {
00720                   ast_log(LOG_DEBUG, "Missing destination protocol\n");
00721                   break;
00722                }
00723             }
00724          }
00725          
00726       }
00727       if (!res) {
00728          OSPPTransactionDelete(result->handle);
00729          result->handle = -1;
00730       }
00731       
00732    }
00733    return res;
00734 }
00735 
00736 static enum OSPEFAILREASON cause2reason(int cause)
00737 {
00738    switch(cause) {
00739    case AST_CAUSE_BUSY:
00740       return OSPC_FAIL_USER_BUSY;
00741    case AST_CAUSE_CONGESTION:
00742       return OSPC_FAIL_SWITCHING_EQUIPMENT_CONGESTION;
00743    case AST_CAUSE_UNALLOCATED:
00744       return OSPC_FAIL_UNALLOC_NUMBER;
00745    case AST_CAUSE_NOTDEFINED:
00746       return OSPC_FAIL_NORMAL_UNSPECIFIED;
00747    case AST_CAUSE_NOANSWER:
00748       return OSPC_FAIL_NO_ANSWER_FROM_USER;
00749    case AST_CAUSE_NORMAL:
00750    default:
00751       return OSPC_FAIL_NORMAL_CALL_CLEARING;
00752    }
00753 }
00754 
00755 int ast_osp_terminate(int handle, int cause, time_t start, time_t duration)
00756 {
00757    unsigned int dummy = 0;
00758    int res = -1;
00759    enum OSPEFAILREASON reason;
00760 
00761    time_t endTime = 0;
00762    time_t alertTime = 0;
00763    time_t connectTime = 0;
00764    unsigned isPddInfoPresent = 0;
00765    unsigned pdd = 0;
00766    unsigned releaseSource = 0;
00767    unsigned char *confId = "";
00768    
00769    reason = cause2reason(cause);
00770    if (OSPPTransactionRecordFailure(handle, reason))
00771       ast_log(LOG_WARNING, "Failed to record call termination for handle %d\n", handle);
00772    else if (OSPPTransactionReportUsage(handle, duration, start,
00773                 endTime,alertTime,connectTime,isPddInfoPresent,pdd,releaseSource,confId,
00774                       0, 0, 0, 0, &dummy, NULL))
00775       ast_log(LOG_WARNING, "Failed to report duration for handle %d\n", handle);
00776    else {
00777       ast_log(LOG_DEBUG, "Completed recording handle %d\n", handle);
00778       OSPPTransactionDelete(handle);
00779       res = 0;
00780    }
00781    return res;
00782 }
00783 
00784 static int config_load(void)
00785 {
00786    struct ast_config *cfg;
00787    char *cat;
00788    struct osp_provider *osp, *prev = NULL, *next;
00789    ast_mutex_lock(&osplock);
00790    osp = providers;
00791    while(osp) {
00792       osp->dead = 1;
00793       osp = osp->next;
00794    }
00795    ast_mutex_unlock(&osplock);
00796    cfg = ast_config_load("osp.conf");
00797    if (cfg) {
00798       if (!initialized) {
00799          cat = ast_variable_retrieve(cfg, "general", "accelerate");
00800          if (cat && ast_true(cat))
00801             if (OSPPInit(1)) {
00802                ast_log(LOG_WARNING, "Failed to enable hardware accelleration, falling back to software mode\n");
00803                OSPPInit(0);
00804             } else
00805                hardware = 1;
00806          else
00807             OSPPInit(0);
00808          initialized = 1;
00809       }
00810       cat = ast_variable_retrieve(cfg, "general", "tokenformat");
00811       if (cat) {
00812          if ((sscanf(cat, "%30d", &tokenformat) != 1) || (tokenformat < TOKEN_ALGO_SIGNED) || (tokenformat > TOKEN_ALGO_BOTH)) {
00813             tokenformat = TOKEN_ALGO_SIGNED;
00814             ast_log(LOG_WARNING, "tokenformat should be an integer from 0 to 2, not '%s'\n", cat);
00815          }
00816       }
00817       cat = ast_category_browse(cfg, NULL);
00818       while(cat) {
00819          if (strcasecmp(cat, "general"))
00820             osp_build(cfg, cat);
00821          cat = ast_category_browse(cfg, cat);
00822       }
00823       ast_config_destroy(cfg);
00824    } else
00825       ast_log(LOG_NOTICE, "No OSP configuration found.  OSP support disabled\n");
00826    ast_mutex_lock(&osplock);
00827    osp = providers;
00828    while(osp) {
00829       next = osp->next;
00830       if (osp->dead) {
00831          if (prev)
00832             prev->next = next;
00833          else
00834             providers = next;
00835          /* XXX Cleanup OSP structure first XXX */
00836          free(osp);
00837       } else 
00838          prev = osp;
00839       osp = next;
00840    }
00841    ast_mutex_unlock(&osplock);
00842    return 0;
00843 }
00844 
00845 static char show_osp_usage[] = 
00846 "Usage: show osp\n"
00847 "       Displays information on Open Settlement Protocol\n";
00848 
00849 static struct ast_cli_entry cli_show_osp = 
00850 { { "show", "osp", NULL }, show_osp, "Displays OSP information", show_osp_usage };
00851 
00852 int reload(void)
00853 {
00854    config_load();
00855    ast_log(LOG_NOTICE, "XXX Should reload OSP config XXX\n");
00856    return 0;
00857 }
00858 
00859 int load_module(void)
00860 {
00861    config_load();
00862    ast_cli_register(&cli_show_osp);
00863    return 0;
00864 }
00865 
00866 int unload_module(void)
00867 {
00868    /* Can't unload this once we're loaded */
00869    return -1;
00870 }
00871 
00872 char *description(void)
00873 {
00874    return "Open Settlement Protocol Support";
00875 }
00876 
00877 int usecount(void)
00878 {
00879    /* We should never be unloaded */
00880    return 1;
00881 }
00882 
00883 char *key()
00884 {
00885    return ASTERISK_GPL_KEY;
00886 }

Generated on Wed Oct 28 15:47:55 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6