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
00027
00028
00029
00030
00031
00032
00033 #include "asterisk.h"
00034
00035 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
00036
00037 #include <sys/types.h>
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <unistd.h>
00041 #include <errno.h>
00042 #include <osp/osp.h>
00043 #include <osp/osputils.h>
00044
00045 #include "asterisk/lock.h"
00046 #include "asterisk/config.h"
00047 #include "asterisk/utils.h"
00048 #include "asterisk/causes.h"
00049 #include "asterisk/channel.h"
00050 #include "asterisk/app.h"
00051 #include "asterisk/module.h"
00052 #include "asterisk/pbx.h"
00053 #include "asterisk/options.h"
00054 #include "asterisk/cli.h"
00055 #include "asterisk/logger.h"
00056 #include "asterisk/astosp.h"
00057
00058
00059 #define OSP_INTSTR_SIZE ((unsigned int)16)
00060 #define OSP_NORSTR_SIZE ((unsigned int)256)
00061 #define OSP_TOKSTR_SIZE ((unsigned int)4096)
00062
00063
00064 #define OSP_INVALID_HANDLE ((int)-1)
00065 #define OSP_CONFIG_FILE ((const char*)"osp.conf")
00066 #define OSP_GENERAL_CAT ((const char*)"general")
00067 #define OSP_DEF_PROVIDER ((const char*)"default")
00068 #define OSP_MAX_CERTS ((unsigned int)10)
00069 #define OSP_MAX_SRVS ((unsigned int)10)
00070 #define OSP_DEF_MAXCONNECTIONS ((unsigned int)20)
00071 #define OSP_MIN_MAXCONNECTIONS ((unsigned int)1)
00072 #define OSP_MAX_MAXCONNECTIONS ((unsigned int)1000)
00073 #define OSP_DEF_RETRYDELAY ((unsigned int)0)
00074 #define OSP_MIN_RETRYDELAY ((unsigned int)0)
00075 #define OSP_MAX_RETRYDELAY ((unsigned int)10)
00076 #define OSP_DEF_RETRYLIMIT ((unsigned int)2)
00077 #define OSP_MIN_RETRYLIMIT ((unsigned int)0)
00078 #define OSP_MAX_RETRYLIMIT ((unsigned int)100)
00079 #define OSP_DEF_TIMEOUT ((unsigned int)500)
00080 #define OSP_MIN_TIMEOUT ((unsigned int)200)
00081 #define OSP_MAX_TIMEOUT ((unsigned int)10000)
00082 #define OSP_DEF_AUTHPOLICY ((enum osp_authpolicy)OSP_AUTH_YES)
00083 #define OSP_AUDIT_URL ((const char*)"localhost")
00084 #define OSP_LOCAL_VALIDATION ((int)1)
00085 #define OSP_SSL_LIFETIME ((unsigned int)300)
00086 #define OSP_HTTP_PERSISTENCE ((int)1)
00087 #define OSP_CUSTOMER_ID ((const char*)"")
00088 #define OSP_DEVICE_ID ((const char*)"")
00089 #define OSP_DEF_DESTINATIONS ((unsigned int)5)
00090 #define OSP_DEF_TIMELIMIT ((unsigned int)0)
00091
00092
00093 enum osp_authpolicy {
00094 OSP_AUTH_NO,
00095 OSP_AUTH_YES,
00096 OSP_AUTH_EXCLUSIVE
00097 };
00098
00099
00100 struct osp_provider {
00101 char name[OSP_NORSTR_SIZE];
00102 char privatekey[OSP_NORSTR_SIZE];
00103 char localcert[OSP_NORSTR_SIZE];
00104 unsigned int cacount;
00105 char cacerts[OSP_MAX_CERTS][OSP_NORSTR_SIZE];
00106 unsigned int spcount;
00107 char srvpoints[OSP_MAX_SRVS][OSP_NORSTR_SIZE];
00108 int maxconnections;
00109 int retrydelay;
00110 int retrylimit;
00111 int timeout;
00112 char source[OSP_NORSTR_SIZE];
00113 enum osp_authpolicy authpolicy;
00114 OSPTPROVHANDLE handle;
00115 struct osp_provider* next;
00116 };
00117
00118
00119 struct osp_result {
00120 int inhandle;
00121 int outhandle;
00122 unsigned int intimelimit;
00123 unsigned int outtimelimit;
00124 char tech[20];
00125 char dest[OSP_NORSTR_SIZE];
00126 char calling[OSP_NORSTR_SIZE];
00127 char token[OSP_TOKSTR_SIZE];
00128 unsigned int numresults;
00129 };
00130
00131
00132 AST_MUTEX_DEFINE_STATIC(osplock);
00133 static int osp_initialized = 0;
00134 static int osp_hardware = 0;
00135 static struct osp_provider* ospproviders = NULL;
00136 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED;
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 static int osp_create_provider(struct ast_config* cfg, const char* provider)
00147 {
00148 int res;
00149 unsigned int t, i, j;
00150 struct osp_provider* p;
00151 struct ast_variable* v;
00152 OSPTPRIVATEKEY privatekey;
00153 OSPTCERT localcert;
00154 const char* psrvpoints[OSP_MAX_SRVS];
00155 OSPTCERT cacerts[OSP_MAX_CERTS];
00156 const OSPTCERT* pcacerts[OSP_MAX_CERTS];
00157 int error = OSPC_ERR_NO_ERROR;
00158
00159 if (!(p = ast_calloc(1, sizeof(*p)))) {
00160 ast_log(LOG_ERROR, "Out of memory\n");
00161 return -1;
00162 }
00163
00164 ast_copy_string(p->name, provider, sizeof(p->name));
00165 snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, provider);
00166 snprintf(p->localcert, sizeof(p->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, provider);
00167 p->maxconnections = OSP_DEF_MAXCONNECTIONS;
00168 p->retrydelay = OSP_DEF_RETRYDELAY;
00169 p->retrylimit = OSP_DEF_RETRYLIMIT;
00170 p->timeout = OSP_DEF_TIMEOUT;
00171 p->authpolicy = OSP_DEF_AUTHPOLICY;
00172 p->handle = OSP_INVALID_HANDLE;
00173
00174 v = ast_variable_browse(cfg, provider);
00175 while(v) {
00176 if (!strcasecmp(v->name, "privatekey")) {
00177 if (v->value[0] == '/') {
00178 ast_copy_string(p->privatekey, v->value, sizeof(p->privatekey));
00179 } else {
00180 snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s", ast_config_AST_KEY_DIR, v->value);
00181 }
00182 ast_log(LOG_DEBUG, "OSP: privatekey '%s'\n", p->privatekey);
00183 } else if (!strcasecmp(v->name, "localcert")) {
00184 if (v->value[0] == '/') {
00185 ast_copy_string(p->localcert, v->value, sizeof(p->localcert));
00186 } else {
00187 snprintf(p->localcert, sizeof(p->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
00188 }
00189 ast_log(LOG_DEBUG, "OSP: localcert '%s'\n", p->localcert);
00190 } else if (!strcasecmp(v->name, "cacert")) {
00191 if (p->cacount < OSP_MAX_CERTS) {
00192 if (v->value[0] == '/') {
00193 ast_copy_string(p->cacerts[p->cacount], v->value, sizeof(p->cacerts[0]));
00194 } else {
00195 snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
00196 }
00197 ast_log(LOG_DEBUG, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
00198 p->cacount++;
00199 } else {
00200 ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", v->lineno);
00201 }
00202 } else if (!strcasecmp(v->name, "servicepoint")) {
00203 if (p->spcount < OSP_MAX_SRVS) {
00204 ast_copy_string(p->srvpoints[p->spcount], v->value, sizeof(p->srvpoints[0]));
00205 ast_log(LOG_DEBUG, "OSP: servicepoint[%d]: '%s'\n", p->spcount, p->srvpoints[p->spcount]);
00206 p->spcount++;
00207 } else {
00208 ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", v->lineno);
00209 }
00210 } else if (!strcasecmp(v->name, "maxconnections")) {
00211 if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_MAXCONNECTIONS) && (t <= OSP_MAX_MAXCONNECTIONS)) {
00212 p->maxconnections = t;
00213 ast_log(LOG_DEBUG, "OSP: maxconnections '%d'\n", t);
00214 } else {
00215 ast_log(LOG_WARNING, "OSP: maxconnections should be an integer from %d to %d, not '%s' at line %d\n",
00216 OSP_MIN_MAXCONNECTIONS, OSP_MAX_MAXCONNECTIONS, v->value, v->lineno);
00217 }
00218 } else if (!strcasecmp(v->name, "retrydelay")) {
00219 if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYDELAY) && (t <= OSP_MAX_RETRYDELAY)) {
00220 p->retrydelay = t;
00221 ast_log(LOG_DEBUG, "OSP: retrydelay '%d'\n", t);
00222 } else {
00223 ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
00224 OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, v->value, v->lineno);
00225 }
00226 } else if (!strcasecmp(v->name, "retrylimit")) {
00227 if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYLIMIT) && (t <= OSP_MAX_RETRYLIMIT)) {
00228 p->retrylimit = t;
00229 ast_log(LOG_DEBUG, "OSP: retrylimit '%d'\n", t);
00230 } else {
00231 ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
00232 OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, v->value, v->lineno);
00233 }
00234 } else if (!strcasecmp(v->name, "timeout")) {
00235 if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_TIMEOUT) && (t <= OSP_MAX_TIMEOUT)) {
00236 p->timeout = t;
00237 ast_log(LOG_DEBUG, "OSP: timeout '%d'\n", t);
00238 } else {
00239 ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
00240 OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, v->value, v->lineno);
00241 }
00242 } else if (!strcasecmp(v->name, "source")) {
00243 ast_copy_string(p->source, v->value, sizeof(p->source));
00244 ast_log(LOG_DEBUG, "OSP: source '%s'\n", p->source);
00245 } else if (!strcasecmp(v->name, "authpolicy")) {
00246 if ((sscanf(v->value, "%d", &t) == 1) && ((t == OSP_AUTH_NO) || (t == OSP_AUTH_YES) || (t == OSP_AUTH_EXCLUSIVE))) {
00247 p->authpolicy = t;
00248 ast_log(LOG_DEBUG, "OSP: authpolicy '%d'\n", t);
00249 } else {
00250 ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
00251 OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXCLUSIVE, v->value, v->lineno);
00252 }
00253 }
00254 v = v->next;
00255 }
00256
00257 error = OSPPUtilLoadPEMPrivateKey((unsigned char *) p->privatekey, &privatekey);
00258 if (error != OSPC_ERR_NO_ERROR) {
00259 ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", p->privatekey, error);
00260 free(p);
00261 return 0;
00262 }
00263
00264 error = OSPPUtilLoadPEMCert((unsigned char *) p->localcert, &localcert);
00265 if (error != OSPC_ERR_NO_ERROR) {
00266 ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", p->localcert, error);
00267 if (privatekey.PrivateKeyData) {
00268 free(privatekey.PrivateKeyData);
00269 }
00270 free(p);
00271 return 0;
00272 }
00273
00274 if (p->cacount < 1) {
00275 snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s-cacert.pem", ast_config_AST_KEY_DIR, provider);
00276 ast_log(LOG_DEBUG, "OSP: cacert[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
00277 p->cacount++;
00278 }
00279 for (i = 0; i < p->cacount; i++) {
00280 error = OSPPUtilLoadPEMCert((unsigned char *) p->cacerts[i], &cacerts[i]);
00281 if (error != OSPC_ERR_NO_ERROR) {
00282 ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", p->cacerts[i], error);
00283 for (j = 0; j < i; j++) {
00284 if (cacerts[j].CertData) {
00285 free(cacerts[j].CertData);
00286 }
00287 }
00288 if (localcert.CertData) {
00289 free(localcert.CertData);
00290 }
00291 if (privatekey.PrivateKeyData) {
00292 free(privatekey.PrivateKeyData);
00293 }
00294 free(p);
00295 return 0;
00296 }
00297 pcacerts[i] = &cacerts[i];
00298 }
00299
00300 for (i = 0; i < p->spcount; i++) {
00301 psrvpoints[i] = p->srvpoints[i];
00302 }
00303
00304 error = OSPPProviderNew(p->spcount, psrvpoints, NULL, OSP_AUDIT_URL, &privatekey, &localcert, p->cacount, pcacerts, OSP_LOCAL_VALIDATION,
00305 OSP_SSL_LIFETIME, p->maxconnections, OSP_HTTP_PERSISTENCE, p->retrydelay, p->retrylimit,p->timeout, OSP_CUSTOMER_ID,
00306 OSP_DEVICE_ID, &p->handle);
00307 if (error != OSPC_ERR_NO_ERROR) {
00308 ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", provider, error);
00309 free(p);
00310 res = -1;
00311 } else {
00312 ast_log(LOG_DEBUG, "OSP: provider '%s'\n", provider);
00313 ast_mutex_lock(&osplock);
00314 p->next = ospproviders;
00315 ospproviders = p;
00316 ast_mutex_unlock(&osplock);
00317 res = 1;
00318 }
00319
00320 for (i = 0; i < p->cacount; i++) {
00321 if (cacerts[i].CertData) {
00322 free(cacerts[i].CertData);
00323 }
00324 }
00325 if (localcert.CertData) {
00326 free(localcert.CertData);
00327 }
00328 if (privatekey.PrivateKeyData) {
00329 free(privatekey.PrivateKeyData);
00330 }
00331
00332 return res;
00333 }
00334
00335
00336
00337
00338
00339
00340
00341 static int osp_get_policy(const char* provider, int* policy)
00342 {
00343 int res = 0;
00344 struct osp_provider* p;
00345
00346 ast_mutex_lock(&osplock);
00347 p = ospproviders;
00348 while(p) {
00349 if (!strcasecmp(p->name, provider)) {
00350 *policy = p->authpolicy;
00351 ast_log(LOG_DEBUG, "OSP: authpolicy '%d'\n", *policy);
00352 res = 1;
00353 break;
00354 }
00355 p = p->next;
00356 }
00357 ast_mutex_unlock(&osplock);
00358
00359 return res;
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 static int osp_create_transaction(const char* provider, int* transaction, unsigned int sourcesize, char* source)
00371 {
00372 int res = 0;
00373 struct osp_provider* p;
00374 int error;
00375
00376 ast_mutex_lock(&osplock);
00377 p = ospproviders;
00378 while(p) {
00379 if (!strcasecmp(p->name, provider)) {
00380 error = OSPPTransactionNew(p->handle, transaction);
00381 if (error == OSPC_ERR_NO_ERROR) {
00382 ast_log(LOG_DEBUG, "OSP: transaction '%d'\n", *transaction);
00383 ast_copy_string(source, p->source, sourcesize);
00384 ast_log(LOG_DEBUG, "OSP: source '%s'\n", source);
00385 res = 1;
00386 } else {
00387 *transaction = OSP_INVALID_HANDLE;
00388 ast_log(LOG_DEBUG, "OSP: Unable to create transaction handle, error '%d'\n", error);
00389 res = -1;
00390 }
00391 break;
00392 }
00393 p = p->next;
00394 }
00395 ast_mutex_unlock(&osplock);
00396
00397 return res;
00398 }
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 static int osp_validate_token(int transaction, const char* source, const char* dest, const char* calling, const char* called, const char* token, unsigned int* timelimit)
00412 {
00413 int res;
00414 int tokenlen;
00415 unsigned char tokenstr[OSP_TOKSTR_SIZE];
00416 unsigned int authorised;
00417 unsigned int dummy = 0;
00418 int error;
00419
00420 tokenlen = ast_base64decode(tokenstr, token, strlen(token));
00421 error = OSPPTransactionValidateAuthorisation(
00422 transaction,
00423 source, dest, NULL, NULL,
00424 calling ? calling : "", OSPC_E164,
00425 called, OSPC_E164,
00426 0, NULL,
00427 tokenlen, (char *) tokenstr,
00428 &authorised,
00429 timelimit,
00430 &dummy, NULL,
00431 osp_tokenformat);
00432 if (error != OSPC_ERR_NO_ERROR) {
00433 ast_log(LOG_DEBUG, "OSP: Unable to validate inbound token\n");
00434 res = -1;
00435 } else if (authorised) {
00436 ast_log(LOG_DEBUG, "OSP: Authorised\n");
00437 res = 1;
00438 } else {
00439 ast_log(LOG_DEBUG, "OSP: Unauthorised\n");
00440 res = 0;
00441 }
00442
00443 return res;
00444 }
00445
00446
00447
00448
00449
00450
00451
00452 static unsigned int osp_choose_timelimit(unsigned int in, unsigned int out)
00453 {
00454 if (in == OSP_DEF_TIMELIMIT) {
00455 return out;
00456 } else if (out == OSP_DEF_TIMELIMIT) {
00457 return in;
00458 } else {
00459 return in < out ? in : out;
00460 }
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474 static int osp_check_destination(const char* called, const char* calling, char* destination, unsigned int tokenlen, const char* token, enum OSPEFAILREASON* reason, struct osp_result* result)
00475 {
00476 int res;
00477 OSPE_DEST_OSP_ENABLED enabled;
00478 OSPE_DEST_PROT protocol;
00479 int error;
00480
00481 if (strlen(destination) <= 2) {
00482 ast_log(LOG_DEBUG, "OSP: Wrong destination format '%s'\n", destination);
00483 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
00484 return -1;
00485 }
00486
00487 if ((error = OSPPTransactionIsDestOSPEnabled(result->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
00488 ast_log(LOG_DEBUG, "OSP: Unable to get destination OSP version, error '%d'\n", error);
00489 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
00490 return -1;
00491 }
00492
00493 if (enabled == OSPE_OSP_FALSE) {
00494 result->token[0] = '\0';
00495 } else {
00496 ast_base64encode(result->token, (const unsigned char *) token, tokenlen, sizeof(result->token) - 1);
00497 }
00498
00499 if ((error = OSPPTransactionGetDestProtocol(result->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
00500 ast_log(LOG_DEBUG, "OSP: Unable to get destination protocol, error '%d'\n", error);
00501 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
00502 result->token[0] = '\0';
00503 return -1;
00504 }
00505
00506 res = 1;
00507
00508 destination[strlen(destination) - 1] = '\0';
00509 switch(protocol) {
00510 case OSPE_DEST_PROT_H323_SETUP:
00511 ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
00512 ast_copy_string(result->tech, "H323", sizeof(result->tech));
00513 snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1);
00514 ast_copy_string(result->calling, calling, sizeof(result->calling));
00515 break;
00516 case OSPE_DEST_PROT_SIP:
00517 ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
00518 ast_copy_string(result->tech, "SIP", sizeof(result->tech));
00519 snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1);
00520 ast_copy_string(result->calling, calling, sizeof(result->calling));
00521 break;
00522 case OSPE_DEST_PROT_IAX:
00523 ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
00524 ast_copy_string(result->tech, "IAX", sizeof(result->tech));
00525 snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1);
00526 ast_copy_string(result->calling, calling, sizeof(result->calling));
00527 break;
00528 default:
00529 ast_log(LOG_DEBUG, "OSP: Unknown protocol '%d'\n", protocol);
00530 *reason = OSPC_FAIL_PROTOCOL_ERROR;
00531 result->token[0] = '\0';
00532 res = 0;
00533 }
00534
00535 return res;
00536 }
00537
00538
00539
00540
00541
00542
00543 static enum OSPEFAILREASON asterisk2osp(int cause)
00544 {
00545 return (enum OSPEFAILREASON)cause;
00546 }
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559 static int osp_auth(const char* provider, int* transaction, const char* source, const char* calling, const char* called, const char* token, unsigned int* timelimit)
00560 {
00561 int res;
00562 int policy = OSP_AUTH_YES;
00563 char dest[OSP_NORSTR_SIZE];
00564
00565 *transaction = OSP_INVALID_HANDLE;
00566 *timelimit = OSP_DEF_TIMELIMIT;
00567 res = osp_get_policy(provider, &policy);
00568 if (!res) {
00569 ast_log(LOG_DEBUG, "OSP: Unabe to find OSP authentication policy\n");
00570 return res;
00571 }
00572
00573 switch (policy) {
00574 case OSP_AUTH_NO:
00575 res = 1;
00576 break;
00577 case OSP_AUTH_EXCLUSIVE:
00578 if (ast_strlen_zero(token)) {
00579 res = 0;
00580 } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
00581 ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n");
00582 *transaction = OSP_INVALID_HANDLE;
00583 res = 0;
00584 } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
00585 OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
00586 }
00587 break;
00588 case OSP_AUTH_YES:
00589 default:
00590 if (ast_strlen_zero(token)) {
00591 res = 1;
00592 } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
00593 ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n");
00594 *transaction = OSP_INVALID_HANDLE;
00595 res = 0;
00596 } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
00597 OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
00598 }
00599 break;
00600 }
00601
00602 return res;
00603 }
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 static int osp_lookup(const char* provider, const char* srcdev, const char* calling, const char* called, struct osp_result* result)
00615 {
00616 int res;
00617 char source[OSP_NORSTR_SIZE];
00618 unsigned int callidlen;
00619 char callid[OSPC_CALLID_MAXSIZE];
00620 char callingnum[OSP_NORSTR_SIZE];
00621 char callednum[OSP_NORSTR_SIZE];
00622 char destination[OSP_NORSTR_SIZE];
00623 unsigned int tokenlen;
00624 char token[OSP_TOKSTR_SIZE];
00625 unsigned int dummy = 0;
00626 enum OSPEFAILREASON reason;
00627 int error;
00628
00629 result->outhandle = OSP_INVALID_HANDLE;
00630 result->tech[0] = '\0';
00631 result->dest[0] = '\0';
00632 result->calling[0] = '\0';
00633 result->token[0] = '\0';
00634 result->numresults = 0;
00635 result->outtimelimit = OSP_DEF_TIMELIMIT;
00636
00637 if ((res = osp_create_transaction(provider, &result->outhandle, sizeof(source), source)) <= 0) {
00638 ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n");
00639 result->outhandle = OSP_INVALID_HANDLE;
00640 if (result->inhandle != OSP_INVALID_HANDLE) {
00641 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00642 }
00643 return -1;
00644 }
00645
00646 result->numresults = OSP_DEF_DESTINATIONS;
00647 error = OSPPTransactionRequestAuthorisation(result->outhandle, source, srcdev, calling ? calling : "",
00648 OSPC_E164, called, OSPC_E164, NULL, 0, NULL, NULL, &result->numresults, &dummy, NULL);
00649 if (error != OSPC_ERR_NO_ERROR) {
00650 ast_log(LOG_DEBUG, "OSP: Unable to request authorization\n");
00651 result->numresults = 0;
00652 if (result->inhandle != OSP_INVALID_HANDLE) {
00653 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00654 }
00655 return -1;
00656 }
00657
00658 if (!result->numresults) {
00659 ast_log(LOG_DEBUG, "OSP: No more destination\n");
00660 if (result->inhandle != OSP_INVALID_HANDLE) {
00661 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00662 }
00663 return 0;
00664 }
00665
00666 callidlen = sizeof(callid);
00667 tokenlen = sizeof(token);
00668 error = OSPPTransactionGetFirstDestination(result->outhandle, 0, NULL, NULL, &result->outtimelimit, &callidlen, callid,
00669 sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token);
00670 if (error != OSPC_ERR_NO_ERROR) {
00671 ast_log(LOG_DEBUG, "OSP: Unable to get first route\n");
00672 result->numresults = 0;
00673 result->outtimelimit = OSP_DEF_TIMELIMIT;
00674 if (result->inhandle != OSP_INVALID_HANDLE) {
00675 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00676 }
00677 return -1;
00678 }
00679
00680 result->numresults--;
00681 result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
00682 ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
00683 ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
00684 ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
00685 ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
00686 ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
00687
00688 if ((res = osp_check_destination(callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
00689 return 1;
00690 }
00691
00692 if (!result->numresults) {
00693 ast_log(LOG_DEBUG, "OSP: No more destination\n");
00694 result->outtimelimit = OSP_DEF_TIMELIMIT;
00695 OSPPTransactionRecordFailure(result->outhandle, reason);
00696 if (result->inhandle != OSP_INVALID_HANDLE) {
00697 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00698 }
00699 return 0;
00700 }
00701
00702 while(result->numresults) {
00703 callidlen = sizeof(callid);
00704 tokenlen = sizeof(token);
00705 error = OSPPTransactionGetNextDestination(result->outhandle, reason, 0, NULL, NULL, &result->outtimelimit, &callidlen, callid,
00706 sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token);
00707 if (error == OSPC_ERR_NO_ERROR) {
00708 result->numresults--;
00709 result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
00710 ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
00711 ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
00712 ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
00713 ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
00714 ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
00715 if ((res = osp_check_destination(callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
00716 break;
00717 } else if (!result->numresults) {
00718 ast_log(LOG_DEBUG, "OSP: No more destination\n");
00719 OSPPTransactionRecordFailure(result->outhandle, reason);
00720 if (result->inhandle != OSP_INVALID_HANDLE) {
00721 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00722 }
00723 res = 0;
00724 break;
00725 }
00726 } else {
00727 ast_log(LOG_DEBUG, "OSP: Unable to get route, error '%d'\n", error);
00728 result->numresults = 0;
00729 result->outtimelimit = OSP_DEF_TIMELIMIT;
00730 if (result->inhandle != OSP_INVALID_HANDLE) {
00731 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00732 }
00733 res = -1;
00734 break;
00735 }
00736 }
00737 return res;
00738 }
00739
00740
00741
00742
00743
00744
00745
00746 static int osp_next(int cause, struct osp_result* result)
00747 {
00748 int res;
00749 unsigned int callidlen;
00750 char callid[OSPC_CALLID_MAXSIZE];
00751 char callingnum[OSP_NORSTR_SIZE];
00752 char callednum[OSP_NORSTR_SIZE];
00753 char destination[OSP_NORSTR_SIZE];
00754 unsigned int tokenlen;
00755 char token[OSP_TOKSTR_SIZE];
00756 enum OSPEFAILREASON reason;
00757 int error;
00758
00759 result->tech[0] = '\0';
00760 result->dest[0] = '\0';
00761 result->calling[0] = '\0';
00762 result->token[0] = '\0';
00763 result->outtimelimit = OSP_DEF_TIMELIMIT;
00764
00765 if (result->outhandle == OSP_INVALID_HANDLE) {
00766 ast_log(LOG_DEBUG, "OSP: Transaction handle undefined\n");
00767 result->numresults = 0;
00768 if (result->inhandle != OSP_INVALID_HANDLE) {
00769 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00770 }
00771 return -1;
00772 }
00773
00774 reason = asterisk2osp(cause);
00775
00776 if (!result->numresults) {
00777 ast_log(LOG_DEBUG, "OSP: No more destination\n");
00778 OSPPTransactionRecordFailure(result->outhandle, reason);
00779 if (result->inhandle != OSP_INVALID_HANDLE) {
00780 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00781 }
00782 return 0;
00783 }
00784
00785 while(result->numresults) {
00786 callidlen = sizeof(callid);
00787 tokenlen = sizeof(token);
00788 error = OSPPTransactionGetNextDestination(result->outhandle, reason, 0, NULL, NULL, &result->outtimelimit, &callidlen,
00789 callid, sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token);
00790 if (error == OSPC_ERR_NO_ERROR) {
00791 result->numresults--;
00792 result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
00793 ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
00794 ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
00795 ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
00796 ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
00797 ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
00798 if ((res = osp_check_destination(callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
00799 res = 1;
00800 break;
00801 } else if (!result->numresults) {
00802 ast_log(LOG_DEBUG, "OSP: No more destination\n");
00803 OSPPTransactionRecordFailure(result->outhandle, reason);
00804 if (result->inhandle != OSP_INVALID_HANDLE) {
00805 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00806 }
00807 res = 0;
00808 break;
00809 }
00810 } else {
00811 ast_log(LOG_DEBUG, "OSP: Unable to get route, error '%d'\n", error);
00812 result->token[0] = '\0';
00813 result->numresults = 0;
00814 result->outtimelimit = OSP_DEF_TIMELIMIT;
00815 if (result->inhandle != OSP_INVALID_HANDLE) {
00816 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00817 }
00818 res = -1;
00819 break;
00820 }
00821 }
00822
00823 return res;
00824 }
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837 static int osp_finish(int handle, int recorded, int cause, time_t start, time_t connect, time_t end, unsigned int release)
00838 {
00839 int res;
00840 enum OSPEFAILREASON reason;
00841 time_t alert = 0;
00842 unsigned isPddInfoPresent = 0;
00843 unsigned pdd = 0;
00844 unsigned int dummy = 0;
00845 int error;
00846
00847 if (handle == OSP_INVALID_HANDLE) {
00848 return 0;
00849 }
00850
00851 if (!recorded) {
00852 reason = asterisk2osp(cause);
00853 OSPPTransactionRecordFailure(handle, reason);
00854 }
00855
00856 error = OSPPTransactionReportUsage(handle, difftime(end, connect), start, end, alert, connect, isPddInfoPresent, pdd,
00857 release, (unsigned char *) "", 0, 0, 0, 0, &dummy, NULL);
00858 if (error == OSPC_ERR_NO_ERROR) {
00859 ast_log(LOG_DEBUG, "OSP: Usage reported\n");
00860 res = 1;
00861 } else {
00862 ast_log(LOG_DEBUG, "OSP: Unable to report usage, error '%d'\n", error);
00863 res = -1;
00864 }
00865 OSPPTransactionDelete(handle);
00866
00867 return res;
00868 }
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878 static int ospauth_exec(struct ast_channel* chan, void* data)
00879 {
00880 int res;
00881 struct ast_module_user *u;
00882 const char* provider = OSP_DEF_PROVIDER;
00883 int priority_jump = 0;
00884 struct varshead *headp;
00885 struct ast_var_t *current;
00886 const char *source = "";
00887 const char *token = "";
00888 int handle;
00889 unsigned int timelimit;
00890 char buffer[OSP_INTSTR_SIZE];
00891 const char *status;
00892 char *tmp;
00893
00894 AST_DECLARE_APP_ARGS(args,
00895 AST_APP_ARG(provider);
00896 AST_APP_ARG(options);
00897 );
00898
00899 u = ast_module_user_add(chan);
00900
00901 if (!(tmp = ast_strdupa(data))) {
00902 ast_log(LOG_ERROR, "Out of memory\n");
00903 ast_module_user_remove(u);
00904 return -1;
00905 }
00906
00907 AST_STANDARD_APP_ARGS(args, tmp);
00908
00909 if (!ast_strlen_zero(args.provider)) {
00910 provider = args.provider;
00911 }
00912 ast_log(LOG_DEBUG, "OSPAuth: provider '%s'\n", provider);
00913
00914 if ((args.options) && (strchr(args.options, 'j'))) {
00915 priority_jump = 1;
00916 }
00917 ast_log(LOG_DEBUG, "OSPAuth: priority jump '%d'\n", priority_jump);
00918
00919 headp = &chan->varshead;
00920 AST_LIST_TRAVERSE(headp, current, entries) {
00921 if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
00922 source = ast_var_value(current);
00923 } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
00924 token = ast_var_value(current);
00925 }
00926 }
00927 ast_log(LOG_DEBUG, "OSPAuth: source '%s'\n", source);
00928 ast_log(LOG_DEBUG, "OSPAuth: token size '%zd'\n", strlen(token));
00929
00930
00931 if ((res = osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit)) > 0) {
00932 status = AST_OSP_SUCCESS;
00933 } else {
00934 timelimit = OSP_DEF_TIMELIMIT;
00935 if (!res) {
00936 status = AST_OSP_FAILED;
00937 } else {
00938 status = AST_OSP_ERROR;
00939 }
00940 }
00941
00942 snprintf(buffer, sizeof(buffer), "%d", handle);
00943 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
00944 ast_log(LOG_DEBUG, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
00945 snprintf(buffer, sizeof(buffer), "%d", timelimit);
00946 pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
00947 ast_log(LOG_DEBUG, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
00948 pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
00949 ast_log(LOG_DEBUG, "OSPAuth: %s\n", status);
00950
00951 if(res <= 0) {
00952 if (priority_jump || ast_opt_priority_jumping) {
00953 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
00954 res = 0;
00955 } else {
00956 res = -1;
00957 }
00958 } else {
00959 res = 0;
00960 }
00961
00962 ast_module_user_remove(u);
00963
00964 return res;
00965 }
00966
00967
00968
00969
00970
00971
00972
00973 static int osplookup_exec(struct ast_channel* chan, void* data)
00974 {
00975 int res, cres;
00976 struct ast_module_user *u;
00977 const char *provider = OSP_DEF_PROVIDER;
00978 int priority_jump = 0;
00979 struct varshead *headp;
00980 struct ast_var_t* current;
00981 const char *srcdev = "";
00982 char buffer[OSP_TOKSTR_SIZE];
00983 struct osp_result result;
00984 const char *status;
00985 char *tmp;
00986
00987 AST_DECLARE_APP_ARGS(args,
00988 AST_APP_ARG(exten);
00989 AST_APP_ARG(provider);
00990 AST_APP_ARG(options);
00991 );
00992
00993 if (ast_strlen_zero(data)) {
00994 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[|provider[|options]])\n");
00995 return -1;
00996 }
00997
00998 u = ast_module_user_add(chan);
00999
01000 if (!(tmp = ast_strdupa(data))) {
01001 ast_log(LOG_ERROR, "Out of memory\n");
01002 ast_module_user_remove(u);
01003 return -1;
01004 }
01005
01006 AST_STANDARD_APP_ARGS(args, tmp);
01007
01008 ast_log(LOG_DEBUG, "OSPLookup: exten '%s'\n", args.exten);
01009
01010 if (!ast_strlen_zero(args.provider)) {
01011 provider = args.provider;
01012 }
01013 ast_log(LOG_DEBUG, "OSPlookup: provider '%s'\n", provider);
01014
01015 if ((args.options) && (strchr(args.options, 'j'))) {
01016 priority_jump = 1;
01017 }
01018 ast_log(LOG_DEBUG, "OSPLookup: priority jump '%d'\n", priority_jump);
01019
01020 result.inhandle = OSP_INVALID_HANDLE;
01021 result.intimelimit = OSP_DEF_TIMELIMIT;
01022
01023 headp = &chan->varshead;
01024 AST_LIST_TRAVERSE(headp, current, entries) {
01025 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
01026 if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
01027 result.inhandle = OSP_INVALID_HANDLE;
01028 }
01029 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
01030 if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
01031 result.intimelimit = OSP_DEF_TIMELIMIT;
01032 }
01033 } else if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
01034 srcdev = ast_var_value(current);
01035 }
01036 }
01037 ast_log(LOG_DEBUG, "OSPLookup: OSPINHANDLE '%d'\n", result.inhandle);
01038 ast_log(LOG_DEBUG, "OSPLookup: OSPINTIMELIMIT '%d'\n", result.intimelimit);
01039 ast_log(LOG_DEBUG, "OSPLookup: source device '%s'\n", srcdev);
01040
01041 if ((cres = ast_autoservice_start(chan)) < 0) {
01042 ast_module_user_remove(u);
01043 return -1;
01044 }
01045
01046 if ((res = osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, &result)) > 0) {
01047 status = AST_OSP_SUCCESS;
01048 } else {
01049 result.tech[0] = '\0';
01050 result.dest[0] = '\0';
01051 result.calling[0] = '\0';
01052 result.token[0] = '\0';
01053 result.numresults = 0;
01054 result.outtimelimit = OSP_DEF_TIMELIMIT;
01055 if (!res) {
01056 status = AST_OSP_FAILED;
01057 } else {
01058 status = AST_OSP_ERROR;
01059 }
01060 }
01061
01062 snprintf(buffer, sizeof(buffer), "%d", result.outhandle);
01063 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
01064 ast_log(LOG_DEBUG, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
01065 pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
01066 ast_log(LOG_DEBUG, "OSPLookup: OSPTECH '%s'\n", result.tech);
01067 pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
01068 ast_log(LOG_DEBUG, "OSPLookup: OSPDEST '%s'\n", result.dest);
01069 pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
01070 ast_log(LOG_DEBUG, "OSPLookup: OSPCALLING '%s'\n", result.calling);
01071 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
01072 ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
01073 snprintf(buffer, sizeof(buffer), "%d", result.numresults);
01074 pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
01075 ast_log(LOG_DEBUG, "OSPLookup: OSPRESULTS '%s'\n", buffer);
01076 snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
01077 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
01078 ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
01079 pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
01080 ast_log(LOG_DEBUG, "OSPLookup: %s\n", status);
01081
01082 if (!strcasecmp(result.tech, "SIP")) {
01083 if (!ast_strlen_zero(result.token)) {
01084 snprintf(buffer, sizeof(buffer), "P-OSP-Auth-Token: %s", result.token);
01085 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
01086 ast_log(LOG_DEBUG, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
01087 }
01088 } else if (!strcasecmp(result.tech, "H323")) {
01089 } else if (!strcasecmp(result.tech, "IAX")) {
01090 }
01091
01092 if ((cres = ast_autoservice_stop(chan)) < 0) {
01093 ast_module_user_remove(u);
01094 return -1;
01095 }
01096
01097 if(res <= 0) {
01098 if (priority_jump || ast_opt_priority_jumping) {
01099 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
01100 res = 0;
01101 } else {
01102 res = -1;
01103 }
01104 } else {
01105 res = 0;
01106 }
01107
01108 ast_module_user_remove(u);
01109
01110 return res;
01111 }
01112
01113
01114
01115
01116
01117
01118
01119 static int ospnext_exec(struct ast_channel* chan, void* data)
01120 {
01121 int res;
01122 struct ast_module_user *u;
01123 int priority_jump = 0;
01124 int cause = 0;
01125 struct varshead* headp;
01126 struct ast_var_t* current;
01127 struct osp_result result;
01128 char buffer[OSP_TOKSTR_SIZE];
01129 const char* status;
01130 char* tmp;
01131
01132 AST_DECLARE_APP_ARGS(args,
01133 AST_APP_ARG(cause);
01134 AST_APP_ARG(options);
01135 );
01136
01137 if (ast_strlen_zero(data)) {
01138 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[|options])\n");
01139 return -1;
01140 }
01141
01142 u = ast_module_user_add(chan);
01143
01144 if (!(tmp = ast_strdupa(data))) {
01145 ast_log(LOG_ERROR, "Out of memory\n");
01146 ast_module_user_remove(u);
01147 return -1;
01148 }
01149
01150 AST_STANDARD_APP_ARGS(args, tmp);
01151
01152 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%d", &cause) != 1) {
01153 cause = 0;
01154 }
01155 ast_log(LOG_DEBUG, "OSPNext: cause '%d'\n", cause);
01156
01157 if ((args.options) && (strchr(args.options, 'j'))) {
01158 priority_jump = 1;
01159 }
01160 ast_log(LOG_DEBUG, "OSPNext: priority jump '%d'\n", priority_jump);
01161
01162 result.inhandle = OSP_INVALID_HANDLE;
01163 result.outhandle = OSP_INVALID_HANDLE;
01164 result.intimelimit = OSP_DEF_TIMELIMIT;
01165 result.numresults = 0;
01166
01167 headp = &chan->varshead;
01168 AST_LIST_TRAVERSE(headp, current, entries) {
01169 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
01170 if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
01171 result.inhandle = OSP_INVALID_HANDLE;
01172 }
01173 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
01174 if (sscanf(ast_var_value(current), "%d", &result.outhandle) != 1) {
01175 result.outhandle = OSP_INVALID_HANDLE;
01176 }
01177 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
01178 if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
01179 result.intimelimit = OSP_DEF_TIMELIMIT;
01180 }
01181 } else if (!strcasecmp(ast_var_name(current), "OSPRESULTS")) {
01182 if (sscanf(ast_var_value(current), "%d", &result.numresults) != 1) {
01183 result.numresults = 0;
01184 }
01185 }
01186 }
01187 ast_log(LOG_DEBUG, "OSPNext: OSPINHANDLE '%d'\n", result.inhandle);
01188 ast_log(LOG_DEBUG, "OSPNext: OSPOUTHANDLE '%d'\n", result.outhandle);
01189 ast_log(LOG_DEBUG, "OSPNext: OSPINTIMELIMIT '%d'\n", result.intimelimit);
01190 ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%d'\n", result.numresults);
01191
01192 if ((res = osp_next(cause, &result)) > 0) {
01193 status = AST_OSP_SUCCESS;
01194 } else {
01195 result.tech[0] = '\0';
01196 result.dest[0] = '\0';
01197 result.calling[0] = '\0';
01198 result.token[0] = '\0';
01199 result.numresults = 0;
01200 result.outtimelimit = OSP_DEF_TIMELIMIT;
01201 if (!res) {
01202 status = AST_OSP_FAILED;
01203 } else {
01204 status = AST_OSP_ERROR;
01205 }
01206 }
01207
01208 pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
01209 ast_log(LOG_DEBUG, "OSPNext: OSPTECH '%s'\n", result.tech);
01210 pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
01211 ast_log(LOG_DEBUG, "OSPNext: OSPDEST '%s'\n", result.dest);
01212 pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
01213 ast_log(LOG_DEBUG, "OSPNext: OSPCALLING '%s'\n", result.calling);
01214 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
01215 ast_log(LOG_DEBUG, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
01216 snprintf(buffer, sizeof(buffer), "%d", result.numresults);
01217 pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
01218 ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%s'\n", buffer);
01219 snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
01220 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
01221 ast_log(LOG_DEBUG, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
01222 pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
01223 ast_log(LOG_DEBUG, "OSPNext: %s\n", status);
01224
01225 if (!strcasecmp(result.tech, "SIP")) {
01226 if (!ast_strlen_zero(result.token)) {
01227 snprintf(buffer, sizeof(buffer), "P-OSP-Auth-Token: %s", result.token);
01228 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
01229 ast_log(LOG_DEBUG, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
01230 }
01231 } else if (!strcasecmp(result.tech, "H323")) {
01232 } else if (!strcasecmp(result.tech, "IAX")) {
01233 }
01234
01235 if(res <= 0) {
01236 if (priority_jump || ast_opt_priority_jumping) {
01237 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
01238 res = 0;
01239 } else {
01240 res = -1;
01241 }
01242 } else {
01243 res = 0;
01244 }
01245
01246 ast_module_user_remove(u);
01247
01248 return res;
01249 }
01250
01251
01252
01253
01254
01255
01256
01257 static int ospfinished_exec(struct ast_channel* chan, void* data)
01258 {
01259 int res = 1;
01260 struct ast_module_user *u;
01261 int priority_jump = 0;
01262 int cause = 0;
01263 struct varshead *headp;
01264 struct ast_var_t *current;
01265 int inhandle = OSP_INVALID_HANDLE;
01266 int outhandle = OSP_INVALID_HANDLE;
01267 int recorded = 0;
01268 time_t start, connect, end;
01269 unsigned int release;
01270 char buffer[OSP_INTSTR_SIZE];
01271 const char *status;
01272 char *tmp;
01273
01274 AST_DECLARE_APP_ARGS(args,
01275 AST_APP_ARG(cause);
01276 AST_APP_ARG(options);
01277 );
01278
01279 u = ast_module_user_add(chan);
01280
01281 if (!(tmp = ast_strdupa(data))) {
01282 ast_log(LOG_ERROR, "Out of memory\n");
01283 ast_module_user_remove(u);
01284 return -1;
01285 }
01286
01287 AST_STANDARD_APP_ARGS(args, tmp);
01288
01289 if ((args.options) && (strchr(args.options, 'j'))) {
01290 priority_jump = 1;
01291 }
01292 ast_log(LOG_DEBUG, "OSPFinish: priority jump '%d'\n", priority_jump);
01293
01294 headp = &chan->varshead;
01295 AST_LIST_TRAVERSE(headp, current, entries) {
01296 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
01297 if (sscanf(ast_var_value(current), "%d", &inhandle) != 1) {
01298 inhandle = OSP_INVALID_HANDLE;
01299 }
01300 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
01301 if (sscanf(ast_var_value(current), "%d", &outhandle) != 1) {
01302 outhandle = OSP_INVALID_HANDLE;
01303 }
01304 } else if (!recorded &&
01305 (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
01306 !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
01307 !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS")))
01308 {
01309 if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
01310 recorded = 1;
01311 }
01312 }
01313 }
01314 ast_log(LOG_DEBUG, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
01315 ast_log(LOG_DEBUG, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
01316 ast_log(LOG_DEBUG, "OSPFinish: recorded '%d'\n", recorded);
01317
01318 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%d", &cause) != 1) {
01319 cause = 0;
01320 }
01321 ast_log(LOG_DEBUG, "OSPFinish: cause '%d'\n", cause);
01322
01323 if (chan->cdr) {
01324 start = chan->cdr->start.tv_sec;
01325 connect = chan->cdr->answer.tv_sec;
01326 if (connect) {
01327 end = time(NULL);
01328 } else {
01329 end = connect;
01330 }
01331 } else {
01332 start = 0;
01333 connect = 0;
01334 end = 0;
01335 }
01336 ast_log(LOG_DEBUG, "OSPFinish: start '%ld'\n", start);
01337 ast_log(LOG_DEBUG, "OSPFinish: connect '%ld'\n", connect);
01338 ast_log(LOG_DEBUG, "OSPFinish: end '%ld'\n", end);
01339
01340 release = chan->_softhangup ? 0 : 1;
01341
01342 if (osp_finish(outhandle, recorded, cause, start, connect, end, release) <= 0) {
01343 ast_log(LOG_DEBUG, "OSPFinish: Unable to report usage for outbound call\n");
01344 }
01345 switch (cause) {
01346 case AST_CAUSE_NORMAL_CLEARING:
01347 break;
01348 default:
01349 cause = AST_CAUSE_NO_ROUTE_DESTINATION;
01350 break;
01351 }
01352 if (osp_finish(inhandle, recorded, cause, start, connect, end, release) <= 0) {
01353 ast_log(LOG_DEBUG, "OSPFinish: Unable to report usage for inbound call\n");
01354 }
01355 snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
01356 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
01357 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
01358
01359 if (res > 0) {
01360 status = AST_OSP_SUCCESS;
01361 } else if (!res) {
01362 status = AST_OSP_FAILED;
01363 } else {
01364 status = AST_OSP_ERROR;
01365 }
01366 pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
01367
01368 if(!res) {
01369 if (priority_jump || ast_opt_priority_jumping) {
01370 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
01371 res = 0;
01372 } else {
01373 res = -1;
01374 }
01375 } else {
01376 res = 0;
01377 }
01378
01379 ast_module_user_remove(u);
01380
01381 return res;
01382 }
01383
01384
01385
01386 static int osp_load(void)
01387 {
01388 const char* t;
01389 unsigned int v;
01390 struct ast_config* cfg;
01391 int error = OSPC_ERR_NO_ERROR;
01392
01393 cfg = ast_config_load(OSP_CONFIG_FILE);
01394 if (cfg) {
01395 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate");
01396 if (t && ast_true(t)) {
01397 if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
01398 ast_log(LOG_WARNING, "OSP: Unable to enable hardware acceleration\n");
01399 OSPPInit(0);
01400 } else {
01401 osp_hardware = 1;
01402 }
01403 } else {
01404 OSPPInit(0);
01405 }
01406 ast_log(LOG_DEBUG, "OSP: osp_hardware '%d'\n", osp_hardware);
01407
01408 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat");
01409 if (t) {
01410 if ((sscanf(t, "%d", &v) == 1) &&
01411 ((v == TOKEN_ALGO_SIGNED) || (v == TOKEN_ALGO_UNSIGNED) || (v == TOKEN_ALGO_BOTH)))
01412 {
01413 osp_tokenformat = v;
01414 } else {
01415 ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
01416 TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, t);
01417 }
01418 }
01419 ast_log(LOG_DEBUG, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
01420
01421 t = ast_category_browse(cfg, NULL);
01422 while(t) {
01423 if (strcasecmp(t, OSP_GENERAL_CAT)) {
01424 osp_create_provider(cfg, t);
01425 }
01426 t = ast_category_browse(cfg, t);
01427 }
01428
01429 osp_initialized = 1;
01430
01431 ast_config_destroy(cfg);
01432 } else {
01433 ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
01434 return 0;
01435 }
01436 ast_log(LOG_DEBUG, "OSP: osp_initialized '%d'\n", osp_initialized);
01437
01438 return 1;
01439 }
01440
01441 static int osp_unload(void)
01442 {
01443 struct osp_provider* p;
01444 struct osp_provider* next;
01445
01446 if (osp_initialized) {
01447 ast_mutex_lock(&osplock);
01448 p = ospproviders;
01449 while(p) {
01450 next = p->next;
01451 OSPPProviderDelete(p->handle, 0);
01452 free(p);
01453 p = next;
01454 }
01455 ospproviders = NULL;
01456 ast_mutex_unlock(&osplock);
01457
01458 OSPPCleanup();
01459
01460 osp_tokenformat = TOKEN_ALGO_SIGNED;
01461 osp_hardware = 0;
01462 osp_initialized = 0;
01463 }
01464 return 0;
01465 }
01466
01467 static int osp_show(int fd, int argc, char* argv[])
01468 {
01469 int i;
01470 int found = 0;
01471 struct osp_provider* p;
01472 const char* provider = NULL;
01473 const char* tokenalgo;
01474
01475 if ((argc < 2) || (argc > 3)) {
01476 return RESULT_SHOWUSAGE;
01477 }
01478 if (argc > 2) {
01479 provider = argv[2];
01480 }
01481 if (!provider) {
01482 switch (osp_tokenformat) {
01483 case TOKEN_ALGO_BOTH:
01484 tokenalgo = "Both";
01485 break;
01486 case TOKEN_ALGO_UNSIGNED:
01487 tokenalgo = "Unsigned";
01488 break;
01489 case TOKEN_ALGO_SIGNED:
01490 default:
01491 tokenalgo = "Signed";
01492 break;
01493 }
01494 ast_cli(fd, "OSP: %s %s %s\n",
01495 osp_initialized ? "Initialized" : "Uninitialized", osp_hardware ? "Accelerated" : "Normal", tokenalgo);
01496 }
01497
01498 ast_mutex_lock(&osplock);
01499 p = ospproviders;
01500 while(p) {
01501 if (!provider || !strcasecmp(p->name, provider)) {
01502 if (found) {
01503 ast_cli(fd, "\n");
01504 }
01505 ast_cli(fd, " == OSP Provider '%s' == \n", p->name);
01506 ast_cli(fd, "Local Private Key: %s\n", p->privatekey);
01507 ast_cli(fd, "Local Certificate: %s\n", p->localcert);
01508 for (i = 0; i < p->cacount; i++) {
01509 ast_cli(fd, "CA Certificate %d: %s\n", i + 1, p->cacerts[i]);
01510 }
01511 for (i = 0; i < p->spcount; i++) {
01512 ast_cli(fd, "Service Point %d: %s\n", i + 1, p->srvpoints[i]);
01513 }
01514 ast_cli(fd, "Max Connections: %d\n", p->maxconnections);
01515 ast_cli(fd, "Retry Delay: %d seconds\n", p->retrydelay);
01516 ast_cli(fd, "Retry Limit: %d\n", p->retrylimit);
01517 ast_cli(fd, "Timeout: %d milliseconds\n", p->timeout);
01518 ast_cli(fd, "Source: %s\n", strlen(p->source) ? p->source : "<unspecified>");
01519 ast_cli(fd, "Auth Policy %d\n", p->authpolicy);
01520 ast_cli(fd, "OSP Handle: %d\n", p->handle);
01521 found++;
01522 }
01523 p = p->next;
01524 }
01525 ast_mutex_unlock(&osplock);
01526
01527 if (!found) {
01528 if (provider) {
01529 ast_cli(fd, "Unable to find OSP provider '%s'\n", provider);
01530 } else {
01531 ast_cli(fd, "No OSP providers configured\n");
01532 }
01533 }
01534 return RESULT_SUCCESS;
01535 }
01536
01537 static const char* app1= "OSPAuth";
01538 static const char* synopsis1 = "OSP authentication";
01539 static const char* descrip1 =
01540 " OSPAuth([provider[|options]]): Authenticate a SIP INVITE by OSP and sets\n"
01541 "the variables:\n"
01542 " ${OSPINHANDLE}: The inbound call transaction handle\n"
01543 " ${OSPINTIMELIMIT}: The inbound call duration limit in seconds\n"
01544 "\n"
01545 "The option string may contain the following character:\n"
01546 " 'j' -- jump to n+101 priority if the authentication was NOT successful\n"
01547 "This application sets the following channel variable upon completion:\n"
01548 " OSPAUTHSTATUS The status of the OSP Auth attempt as a text string, one of\n"
01549 " SUCCESS | FAILED | ERROR\n";
01550
01551 static const char* app2= "OSPLookup";
01552 static const char* synopsis2 = "Lookup destination by OSP";
01553 static const char* descrip2 =
01554 " OSPLookup(exten[|provider[|options]]): Looks up an extension via OSP and sets\n"
01555 "the variables, where 'n' is the number of the result beginning with 1:\n"
01556 " ${OSPOUTHANDLE}: The OSP Handle for anything remaining\n"
01557 " ${OSPTECH}: The technology to use for the call\n"
01558 " ${OSPDEST}: The destination to use for the call\n"
01559 " ${OSPCALLING}: The calling number to use for the call\n"
01560 " ${OSPOUTTOKEN}: The actual OSP token as a string\n"
01561 " ${OSPOUTTIMELIMIT}: The outbound call duration limit in seconds\n"
01562 " ${OSPRESULTS}: The number of OSP results total remaining\n"
01563 "\n"
01564 "The option string may contain the following character:\n"
01565 " 'j' -- jump to n+101 priority if the lookup was NOT successful\n"
01566 "This application sets the following channel variable upon completion:\n"
01567 " OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n"
01568 " SUCCESS | FAILED | ERROR\n";
01569
01570 static const char* app3 = "OSPNext";
01571 static const char* synopsis3 = "Lookup next destination by OSP";
01572 static const char* descrip3 =
01573 " OSPNext(cause[|options]): Looks up the next OSP Destination for ${OSPOUTHANDLE}\n"
01574 "See OSPLookup for more information\n"
01575 "\n"
01576 "The option string may contain the following character:\n"
01577 " 'j' -- jump to n+101 priority if the lookup was NOT successful\n"
01578 "This application sets the following channel variable upon completion:\n"
01579 " OSPNEXTSTATUS The status of the OSP Next attempt as a text string, one of\n"
01580 " SUCCESS | FAILED |ERROR\n";
01581
01582 static const char* app4 = "OSPFinish";
01583 static const char* synopsis4 = "Record OSP entry";
01584 static const char* descrip4 =
01585 " OSPFinish([status[|options]]): Records call state for ${OSPINHANDLE}, according to\n"
01586 "status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
01587 "or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
01588 "\n"
01589 "The option string may contain the following character:\n"
01590 " 'j' -- jump to n+101 priority if the finish attempt was NOT successful\n"
01591 "This application sets the following channel variable upon completion:\n"
01592 " OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n"
01593 " SUCCESS | FAILED |ERROR \n";
01594
01595 static const char osp_usage[] =
01596 "Usage: osp show\n"
01597 " Displays information on Open Settlement Protocol support\n";
01598
01599 static struct ast_cli_entry cli_osp[] = {
01600 { { "osp", "show", NULL},
01601 osp_show, "Displays OSP information",
01602 osp_usage },
01603 };
01604
01605 static int load_module(void)
01606 {
01607 int res;
01608
01609 if(!osp_load())
01610 return AST_MODULE_LOAD_DECLINE;
01611
01612 ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
01613 res = ast_register_application(app1, ospauth_exec, synopsis1, descrip1);
01614 res |= ast_register_application(app2, osplookup_exec, synopsis2, descrip2);
01615 res |= ast_register_application(app3, ospnext_exec, synopsis3, descrip3);
01616 res |= ast_register_application(app4, ospfinished_exec, synopsis4, descrip4);
01617
01618 return res;
01619 }
01620
01621 static int unload_module(void)
01622 {
01623 int res;
01624
01625 res = ast_unregister_application(app4);
01626 res |= ast_unregister_application(app3);
01627 res |= ast_unregister_application(app2);
01628 res |= ast_unregister_application(app1);
01629 ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
01630 osp_unload();
01631
01632 ast_module_user_hangup_all();
01633
01634 return res;
01635 }
01636
01637 static int reload(void)
01638 {
01639 osp_unload();
01640 osp_load();
01641
01642 return 0;
01643 }
01644
01645 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
01646 .load = load_module,
01647 .unload = unload_module,
01648 .reload = reload,
01649 );