00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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: 7221 $")
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, "%d", &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, "%d", &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, "%d", &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, "%d", &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
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
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] = "";
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] = "";
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
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
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
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
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, "%d", &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
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
00869 return -1;
00870 }
00871
00872 char *description(void)
00873 {
00874 return "Open Settlement Protocol Support";
00875 }
00876
00877 int usecount(void)
00878 {
00879
00880 return 1;
00881 }
00882
00883 char *key()
00884 {
00885 return ASTERISK_GPL_KEY;
00886 }