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: 211528 $")
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, "%30d", &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, "%30d", &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, "%30d", &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, "%30d", &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, "%30d", &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 static void osp_convert_address(
00407 const char* src,
00408 char* dst,
00409 int buffersize)
00410 {
00411 struct in_addr inp;
00412
00413 if (inet_aton(src, &inp) != 0) {
00414 snprintf(dst, buffersize, "[%s]", src);
00415 } else {
00416 snprintf(dst, buffersize, "%s", src);
00417 }
00418 }
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431 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)
00432 {
00433 int res;
00434 int tokenlen;
00435 unsigned char tokenstr[OSP_TOKSTR_SIZE];
00436 char src[OSP_NORSTR_SIZE];
00437 char dst[OSP_NORSTR_SIZE];
00438 unsigned int authorised;
00439 unsigned int dummy = 0;
00440 int error;
00441
00442 tokenlen = ast_base64decode(tokenstr, token, strlen(token));
00443 osp_convert_address(source, src, sizeof(src));
00444 osp_convert_address(dest, dst, sizeof(dst));
00445 error = OSPPTransactionValidateAuthorisation(
00446 transaction,
00447 src, dst, NULL, NULL,
00448 calling ? calling : "", OSPC_E164,
00449 called, OSPC_E164,
00450 0, NULL,
00451 tokenlen, (char *) tokenstr,
00452 &authorised,
00453 timelimit,
00454 &dummy, NULL,
00455 osp_tokenformat);
00456 if (error != OSPC_ERR_NO_ERROR) {
00457 ast_log(LOG_DEBUG, "OSP: Unable to validate inbound token\n");
00458 res = -1;
00459 } else if (authorised) {
00460 ast_log(LOG_DEBUG, "OSP: Authorised\n");
00461 res = 1;
00462 } else {
00463 ast_log(LOG_DEBUG, "OSP: Unauthorised\n");
00464 res = 0;
00465 }
00466
00467 return res;
00468 }
00469
00470
00471
00472
00473
00474
00475
00476 static unsigned int osp_choose_timelimit(unsigned int in, unsigned int out)
00477 {
00478 if (in == OSP_DEF_TIMELIMIT) {
00479 return out;
00480 } else if (out == OSP_DEF_TIMELIMIT) {
00481 return in;
00482 } else {
00483 return in < out ? in : out;
00484 }
00485 }
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498 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)
00499 {
00500 int res;
00501 OSPE_DEST_OSP_ENABLED enabled;
00502 OSPE_DEST_PROT protocol;
00503 int error;
00504
00505 if (strlen(destination) <= 2) {
00506 ast_log(LOG_DEBUG, "OSP: Wrong destination format '%s'\n", destination);
00507 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
00508 return -1;
00509 }
00510
00511 if ((error = OSPPTransactionIsDestOSPEnabled(result->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
00512 ast_log(LOG_DEBUG, "OSP: Unable to get destination OSP version, error '%d'\n", error);
00513 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
00514 return -1;
00515 }
00516
00517 if (enabled == OSPE_OSP_FALSE) {
00518 result->token[0] = '\0';
00519 } else {
00520 ast_base64encode(result->token, (const unsigned char *) token, tokenlen, sizeof(result->token) - 1);
00521 }
00522
00523 if ((error = OSPPTransactionGetDestProtocol(result->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
00524 ast_log(LOG_DEBUG, "OSP: Unable to get destination protocol, error '%d'\n", error);
00525 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
00526 result->token[0] = '\0';
00527 return -1;
00528 }
00529
00530 res = 1;
00531
00532 destination[strlen(destination) - 1] = '\0';
00533 switch(protocol) {
00534 case OSPE_DEST_PROT_H323_SETUP:
00535 ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
00536 ast_copy_string(result->tech, "H323", sizeof(result->tech));
00537 snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1);
00538 ast_copy_string(result->calling, calling, sizeof(result->calling));
00539 break;
00540 case OSPE_DEST_PROT_SIP:
00541 ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
00542 ast_copy_string(result->tech, "SIP", sizeof(result->tech));
00543 snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1);
00544 ast_copy_string(result->calling, calling, sizeof(result->calling));
00545 break;
00546 case OSPE_DEST_PROT_IAX:
00547 ast_log(LOG_DEBUG, "OSP: protocol '%d'\n", protocol);
00548 ast_copy_string(result->tech, "IAX", sizeof(result->tech));
00549 snprintf(result->dest, sizeof(result->dest), "%s@%s", called, destination + 1);
00550 ast_copy_string(result->calling, calling, sizeof(result->calling));
00551 break;
00552 default:
00553 ast_log(LOG_DEBUG, "OSP: Unknown protocol '%d'\n", protocol);
00554 *reason = OSPC_FAIL_PROTOCOL_ERROR;
00555 result->token[0] = '\0';
00556 res = 0;
00557 }
00558
00559 return res;
00560 }
00561
00562
00563
00564
00565
00566
00567 static enum OSPEFAILREASON asterisk2osp(int cause)
00568 {
00569 return (enum OSPEFAILREASON)cause;
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 static int osp_auth(const char* provider, int* transaction, const char* source, const char* calling, const char* called, const char* token, unsigned int* timelimit)
00584 {
00585 int res;
00586 int policy = OSP_AUTH_YES;
00587 char dest[OSP_NORSTR_SIZE];
00588
00589 *transaction = OSP_INVALID_HANDLE;
00590 *timelimit = OSP_DEF_TIMELIMIT;
00591 res = osp_get_policy(provider, &policy);
00592 if (!res) {
00593 ast_log(LOG_DEBUG, "OSP: Unabe to find OSP authentication policy\n");
00594 return res;
00595 }
00596
00597 switch (policy) {
00598 case OSP_AUTH_NO:
00599 res = 1;
00600 break;
00601 case OSP_AUTH_EXCLUSIVE:
00602 if (ast_strlen_zero(token)) {
00603 res = 0;
00604 } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
00605 ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n");
00606 *transaction = OSP_INVALID_HANDLE;
00607 res = 0;
00608 } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
00609 OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
00610 }
00611 break;
00612 case OSP_AUTH_YES:
00613 default:
00614 if (ast_strlen_zero(token)) {
00615 res = 1;
00616 } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
00617 ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n");
00618 *transaction = OSP_INVALID_HANDLE;
00619 res = 0;
00620 } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
00621 OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
00622 }
00623 break;
00624 }
00625
00626 return res;
00627 }
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638 static int osp_lookup(const char* provider, const char* srcdev, const char* calling, const char* called, struct osp_result* result)
00639 {
00640 int res;
00641 char source[OSP_NORSTR_SIZE];
00642 unsigned int callidlen;
00643 char callid[OSPC_CALLID_MAXSIZE];
00644 char callingnum[OSP_NORSTR_SIZE];
00645 char callednum[OSP_NORSTR_SIZE];
00646 char destination[OSP_NORSTR_SIZE];
00647 unsigned int tokenlen;
00648 char token[OSP_TOKSTR_SIZE];
00649 char src[OSP_NORSTR_SIZE];
00650 char dev[OSP_NORSTR_SIZE];
00651 unsigned int dummy = 0;
00652 enum OSPEFAILREASON reason;
00653 int error;
00654
00655 result->outhandle = OSP_INVALID_HANDLE;
00656 result->tech[0] = '\0';
00657 result->dest[0] = '\0';
00658 result->calling[0] = '\0';
00659 result->token[0] = '\0';
00660 result->numresults = 0;
00661 result->outtimelimit = OSP_DEF_TIMELIMIT;
00662
00663 if ((res = osp_create_transaction(provider, &result->outhandle, sizeof(source), source)) <= 0) {
00664 ast_log(LOG_DEBUG, "OSP: Unable to generate transaction handle\n");
00665 result->outhandle = OSP_INVALID_HANDLE;
00666 if (result->inhandle != OSP_INVALID_HANDLE) {
00667 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00668 }
00669 return -1;
00670 }
00671
00672 osp_convert_address(source, src, sizeof(src));
00673 osp_convert_address(srcdev, dev, sizeof(dev));
00674 result->numresults = OSP_DEF_DESTINATIONS;
00675 error = OSPPTransactionRequestAuthorisation(result->outhandle, src, dev, calling ? calling : "",
00676 OSPC_E164, called, OSPC_E164, NULL, 0, NULL, NULL, &result->numresults, &dummy, NULL);
00677 if (error != OSPC_ERR_NO_ERROR) {
00678 ast_log(LOG_DEBUG, "OSP: Unable to request authorization\n");
00679 result->numresults = 0;
00680 if (result->inhandle != OSP_INVALID_HANDLE) {
00681 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00682 }
00683 return -1;
00684 }
00685
00686 if (!result->numresults) {
00687 ast_log(LOG_DEBUG, "OSP: No more destination\n");
00688 if (result->inhandle != OSP_INVALID_HANDLE) {
00689 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00690 }
00691 return 0;
00692 }
00693
00694 callidlen = sizeof(callid);
00695 tokenlen = sizeof(token);
00696 error = OSPPTransactionGetFirstDestination(result->outhandle, 0, NULL, NULL, &result->outtimelimit, &callidlen, callid,
00697 sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token);
00698 if (error != OSPC_ERR_NO_ERROR) {
00699 ast_log(LOG_DEBUG, "OSP: Unable to get first route\n");
00700 result->numresults = 0;
00701 result->outtimelimit = OSP_DEF_TIMELIMIT;
00702 if (result->inhandle != OSP_INVALID_HANDLE) {
00703 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00704 }
00705 return -1;
00706 }
00707
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
00716 if ((res = osp_check_destination(callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
00717 return 1;
00718 }
00719
00720 if (!result->numresults) {
00721 ast_log(LOG_DEBUG, "OSP: No more destination\n");
00722 result->outtimelimit = OSP_DEF_TIMELIMIT;
00723 OSPPTransactionRecordFailure(result->outhandle, reason);
00724 if (result->inhandle != OSP_INVALID_HANDLE) {
00725 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00726 }
00727 return 0;
00728 }
00729
00730 while(result->numresults) {
00731 callidlen = sizeof(callid);
00732 tokenlen = sizeof(token);
00733 error = OSPPTransactionGetNextDestination(result->outhandle, reason, 0, NULL, NULL, &result->outtimelimit, &callidlen, callid,
00734 sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token);
00735 if (error == OSPC_ERR_NO_ERROR) {
00736 result->numresults--;
00737 result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
00738 ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
00739 ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
00740 ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
00741 ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
00742 ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
00743 if ((res = osp_check_destination(callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
00744 break;
00745 } else if (!result->numresults) {
00746 ast_log(LOG_DEBUG, "OSP: No more destination\n");
00747 OSPPTransactionRecordFailure(result->outhandle, reason);
00748 if (result->inhandle != OSP_INVALID_HANDLE) {
00749 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00750 }
00751 res = 0;
00752 break;
00753 }
00754 } else {
00755 ast_log(LOG_DEBUG, "OSP: Unable to get route, error '%d'\n", error);
00756 result->numresults = 0;
00757 result->outtimelimit = OSP_DEF_TIMELIMIT;
00758 if (result->inhandle != OSP_INVALID_HANDLE) {
00759 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00760 }
00761 res = -1;
00762 break;
00763 }
00764 }
00765 return res;
00766 }
00767
00768
00769
00770
00771
00772
00773
00774 static int osp_next(int cause, struct osp_result* result)
00775 {
00776 int res;
00777 unsigned int callidlen;
00778 char callid[OSPC_CALLID_MAXSIZE];
00779 char callingnum[OSP_NORSTR_SIZE];
00780 char callednum[OSP_NORSTR_SIZE];
00781 char destination[OSP_NORSTR_SIZE];
00782 unsigned int tokenlen;
00783 char token[OSP_TOKSTR_SIZE];
00784 enum OSPEFAILREASON reason;
00785 int error;
00786
00787 result->tech[0] = '\0';
00788 result->dest[0] = '\0';
00789 result->calling[0] = '\0';
00790 result->token[0] = '\0';
00791 result->outtimelimit = OSP_DEF_TIMELIMIT;
00792
00793 if (result->outhandle == OSP_INVALID_HANDLE) {
00794 ast_log(LOG_DEBUG, "OSP: Transaction handle undefined\n");
00795 result->numresults = 0;
00796 if (result->inhandle != OSP_INVALID_HANDLE) {
00797 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00798 }
00799 return -1;
00800 }
00801
00802 reason = asterisk2osp(cause);
00803
00804 if (!result->numresults) {
00805 ast_log(LOG_DEBUG, "OSP: No more destination\n");
00806 OSPPTransactionRecordFailure(result->outhandle, reason);
00807 if (result->inhandle != OSP_INVALID_HANDLE) {
00808 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00809 }
00810 return 0;
00811 }
00812
00813 while(result->numresults) {
00814 callidlen = sizeof(callid);
00815 tokenlen = sizeof(token);
00816 error = OSPPTransactionGetNextDestination(result->outhandle, reason, 0, NULL, NULL, &result->outtimelimit, &callidlen,
00817 callid, sizeof(callednum), callednum, sizeof(callingnum), callingnum, sizeof(destination), destination, 0, NULL, &tokenlen, token);
00818 if (error == OSPC_ERR_NO_ERROR) {
00819 result->numresults--;
00820 result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
00821 ast_log(LOG_DEBUG, "OSP: outtimelimit '%d'\n", result->outtimelimit);
00822 ast_log(LOG_DEBUG, "OSP: called '%s'\n", callednum);
00823 ast_log(LOG_DEBUG, "OSP: calling '%s'\n", callingnum);
00824 ast_log(LOG_DEBUG, "OSP: destination '%s'\n", destination);
00825 ast_log(LOG_DEBUG, "OSP: token size '%d'\n", tokenlen);
00826 if ((res = osp_check_destination(callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
00827 res = 1;
00828 break;
00829 } else if (!result->numresults) {
00830 ast_log(LOG_DEBUG, "OSP: No more destination\n");
00831 OSPPTransactionRecordFailure(result->outhandle, reason);
00832 if (result->inhandle != OSP_INVALID_HANDLE) {
00833 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
00834 }
00835 res = 0;
00836 break;
00837 }
00838 } else {
00839 ast_log(LOG_DEBUG, "OSP: Unable to get route, error '%d'\n", error);
00840 result->token[0] = '\0';
00841 result->numresults = 0;
00842 result->outtimelimit = OSP_DEF_TIMELIMIT;
00843 if (result->inhandle != OSP_INVALID_HANDLE) {
00844 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
00845 }
00846 res = -1;
00847 break;
00848 }
00849 }
00850
00851 return res;
00852 }
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865 static int osp_finish(int handle, int recorded, int cause, time_t start, time_t connect, time_t end, unsigned int release)
00866 {
00867 int res;
00868 enum OSPEFAILREASON reason;
00869 time_t alert = 0;
00870 unsigned isPddInfoPresent = 0;
00871 unsigned pdd = 0;
00872 unsigned int dummy = 0;
00873 int error;
00874
00875 if (handle == OSP_INVALID_HANDLE) {
00876 return 0;
00877 }
00878
00879 if (!recorded) {
00880 reason = asterisk2osp(cause);
00881 OSPPTransactionRecordFailure(handle, reason);
00882 }
00883
00884 error = OSPPTransactionReportUsage(handle, difftime(end, connect), start, end, alert, connect, isPddInfoPresent, pdd,
00885 release, (unsigned char *) "", 0, 0, 0, 0, &dummy, NULL);
00886 if (error == OSPC_ERR_NO_ERROR) {
00887 ast_log(LOG_DEBUG, "OSP: Usage reported\n");
00888 res = 1;
00889 } else {
00890 ast_log(LOG_DEBUG, "OSP: Unable to report usage, error '%d'\n", error);
00891 res = -1;
00892 }
00893 OSPPTransactionDelete(handle);
00894
00895 return res;
00896 }
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906 static int ospauth_exec(struct ast_channel* chan, void* data)
00907 {
00908 int res;
00909 struct ast_module_user *u;
00910 const char* provider = OSP_DEF_PROVIDER;
00911 int priority_jump = 0;
00912 struct varshead *headp;
00913 struct ast_var_t *current;
00914 const char *source = "";
00915 const char *token = "";
00916 int handle;
00917 unsigned int timelimit;
00918 char buffer[OSP_INTSTR_SIZE];
00919 const char *status;
00920 char *tmp;
00921
00922 AST_DECLARE_APP_ARGS(args,
00923 AST_APP_ARG(provider);
00924 AST_APP_ARG(options);
00925 );
00926
00927 u = ast_module_user_add(chan);
00928
00929 if (!(tmp = ast_strdupa(data))) {
00930 ast_log(LOG_ERROR, "Out of memory\n");
00931 ast_module_user_remove(u);
00932 return -1;
00933 }
00934
00935 AST_STANDARD_APP_ARGS(args, tmp);
00936
00937 if (!ast_strlen_zero(args.provider)) {
00938 provider = args.provider;
00939 }
00940 ast_log(LOG_DEBUG, "OSPAuth: provider '%s'\n", provider);
00941
00942 if ((args.options) && (strchr(args.options, 'j'))) {
00943 priority_jump = 1;
00944 }
00945 ast_log(LOG_DEBUG, "OSPAuth: priority jump '%d'\n", priority_jump);
00946
00947 headp = &chan->varshead;
00948 AST_LIST_TRAVERSE(headp, current, entries) {
00949 if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
00950 source = ast_var_value(current);
00951 } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
00952 token = ast_var_value(current);
00953 }
00954 }
00955 ast_log(LOG_DEBUG, "OSPAuth: source '%s'\n", source);
00956 ast_log(LOG_DEBUG, "OSPAuth: token size '%zd'\n", strlen(token));
00957
00958
00959 if ((res = osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit)) > 0) {
00960 status = AST_OSP_SUCCESS;
00961 } else {
00962 timelimit = OSP_DEF_TIMELIMIT;
00963 if (!res) {
00964 status = AST_OSP_FAILED;
00965 } else {
00966 status = AST_OSP_ERROR;
00967 }
00968 }
00969
00970 snprintf(buffer, sizeof(buffer), "%d", handle);
00971 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
00972 ast_log(LOG_DEBUG, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
00973 snprintf(buffer, sizeof(buffer), "%d", timelimit);
00974 pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
00975 ast_log(LOG_DEBUG, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
00976 pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
00977 ast_log(LOG_DEBUG, "OSPAuth: %s\n", status);
00978
00979 if(res <= 0) {
00980 if (priority_jump || ast_opt_priority_jumping) {
00981 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
00982 res = 0;
00983 } else {
00984 res = -1;
00985 }
00986 } else {
00987 res = 0;
00988 }
00989
00990 ast_module_user_remove(u);
00991
00992 return res;
00993 }
00994
00995
00996
00997
00998
00999
01000
01001 static int osplookup_exec(struct ast_channel* chan, void* data)
01002 {
01003 int res, cres;
01004 struct ast_module_user *u;
01005 const char *provider = OSP_DEF_PROVIDER;
01006 int priority_jump = 0;
01007 struct varshead *headp;
01008 struct ast_var_t* current;
01009 const char *srcdev = "";
01010 char buffer[OSP_TOKSTR_SIZE];
01011 struct osp_result result;
01012 const char *status;
01013 char *tmp;
01014
01015 AST_DECLARE_APP_ARGS(args,
01016 AST_APP_ARG(exten);
01017 AST_APP_ARG(provider);
01018 AST_APP_ARG(options);
01019 );
01020
01021 if (ast_strlen_zero(data)) {
01022 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[|provider[|options]])\n");
01023 return -1;
01024 }
01025
01026 u = ast_module_user_add(chan);
01027
01028 if (!(tmp = ast_strdupa(data))) {
01029 ast_log(LOG_ERROR, "Out of memory\n");
01030 ast_module_user_remove(u);
01031 return -1;
01032 }
01033
01034 AST_STANDARD_APP_ARGS(args, tmp);
01035
01036 ast_log(LOG_DEBUG, "OSPLookup: exten '%s'\n", args.exten);
01037
01038 if (!ast_strlen_zero(args.provider)) {
01039 provider = args.provider;
01040 }
01041 ast_log(LOG_DEBUG, "OSPlookup: provider '%s'\n", provider);
01042
01043 if ((args.options) && (strchr(args.options, 'j'))) {
01044 priority_jump = 1;
01045 }
01046 ast_log(LOG_DEBUG, "OSPLookup: priority jump '%d'\n", priority_jump);
01047
01048 result.inhandle = OSP_INVALID_HANDLE;
01049 result.intimelimit = OSP_DEF_TIMELIMIT;
01050
01051 headp = &chan->varshead;
01052 AST_LIST_TRAVERSE(headp, current, entries) {
01053 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
01054 if (sscanf(ast_var_value(current), "%30d", &result.inhandle) != 1) {
01055 result.inhandle = OSP_INVALID_HANDLE;
01056 }
01057 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
01058 if (sscanf(ast_var_value(current), "%30d", &result.intimelimit) != 1) {
01059 result.intimelimit = OSP_DEF_TIMELIMIT;
01060 }
01061 } else if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
01062 srcdev = ast_var_value(current);
01063 }
01064 }
01065 ast_log(LOG_DEBUG, "OSPLookup: OSPINHANDLE '%d'\n", result.inhandle);
01066 ast_log(LOG_DEBUG, "OSPLookup: OSPINTIMELIMIT '%d'\n", result.intimelimit);
01067 ast_log(LOG_DEBUG, "OSPLookup: source device '%s'\n", srcdev);
01068
01069 if ((cres = ast_autoservice_start(chan)) < 0) {
01070 ast_module_user_remove(u);
01071 return -1;
01072 }
01073
01074 if ((res = osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, &result)) > 0) {
01075 status = AST_OSP_SUCCESS;
01076 } else {
01077 result.tech[0] = '\0';
01078 result.dest[0] = '\0';
01079 result.calling[0] = '\0';
01080 result.token[0] = '\0';
01081 result.numresults = 0;
01082 result.outtimelimit = OSP_DEF_TIMELIMIT;
01083 if (!res) {
01084 status = AST_OSP_FAILED;
01085 } else {
01086 status = AST_OSP_ERROR;
01087 }
01088 }
01089
01090 snprintf(buffer, sizeof(buffer), "%d", result.outhandle);
01091 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
01092 ast_log(LOG_DEBUG, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
01093 pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
01094 ast_log(LOG_DEBUG, "OSPLookup: OSPTECH '%s'\n", result.tech);
01095 pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
01096 ast_log(LOG_DEBUG, "OSPLookup: OSPDEST '%s'\n", result.dest);
01097 pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
01098 ast_log(LOG_DEBUG, "OSPLookup: OSPCALLING '%s'\n", result.calling);
01099 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
01100 ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
01101 snprintf(buffer, sizeof(buffer), "%d", result.numresults);
01102 pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
01103 ast_log(LOG_DEBUG, "OSPLookup: OSPRESULTS '%s'\n", buffer);
01104 snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
01105 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
01106 ast_log(LOG_DEBUG, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
01107 pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
01108 ast_log(LOG_DEBUG, "OSPLookup: %s\n", status);
01109
01110 if (!strcasecmp(result.tech, "SIP")) {
01111 if (!ast_strlen_zero(result.token)) {
01112 snprintf(buffer, sizeof(buffer), "P-OSP-Auth-Token: %s", result.token);
01113 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
01114 ast_log(LOG_DEBUG, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
01115 }
01116 } else if (!strcasecmp(result.tech, "H323")) {
01117 } else if (!strcasecmp(result.tech, "IAX")) {
01118 }
01119
01120 if ((cres = ast_autoservice_stop(chan)) < 0) {
01121 ast_module_user_remove(u);
01122 return -1;
01123 }
01124
01125 if(res <= 0) {
01126 if (priority_jump || ast_opt_priority_jumping) {
01127 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
01128 res = 0;
01129 } else {
01130 res = -1;
01131 }
01132 } else {
01133 res = 0;
01134 }
01135
01136 ast_module_user_remove(u);
01137
01138 return res;
01139 }
01140
01141
01142
01143
01144
01145
01146
01147 static int ospnext_exec(struct ast_channel* chan, void* data)
01148 {
01149 int res;
01150 struct ast_module_user *u;
01151 int priority_jump = 0;
01152 int cause = 0;
01153 struct varshead* headp;
01154 struct ast_var_t* current;
01155 struct osp_result result;
01156 char buffer[OSP_TOKSTR_SIZE];
01157 const char* status;
01158 char* tmp;
01159
01160 AST_DECLARE_APP_ARGS(args,
01161 AST_APP_ARG(cause);
01162 AST_APP_ARG(options);
01163 );
01164
01165 if (ast_strlen_zero(data)) {
01166 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[|options])\n");
01167 return -1;
01168 }
01169
01170 u = ast_module_user_add(chan);
01171
01172 if (!(tmp = ast_strdupa(data))) {
01173 ast_log(LOG_ERROR, "Out of memory\n");
01174 ast_module_user_remove(u);
01175 return -1;
01176 }
01177
01178 AST_STANDARD_APP_ARGS(args, tmp);
01179
01180 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
01181 cause = 0;
01182 }
01183 ast_log(LOG_DEBUG, "OSPNext: cause '%d'\n", cause);
01184
01185 if ((args.options) && (strchr(args.options, 'j'))) {
01186 priority_jump = 1;
01187 }
01188 ast_log(LOG_DEBUG, "OSPNext: priority jump '%d'\n", priority_jump);
01189
01190 result.inhandle = OSP_INVALID_HANDLE;
01191 result.outhandle = OSP_INVALID_HANDLE;
01192 result.intimelimit = OSP_DEF_TIMELIMIT;
01193 result.numresults = 0;
01194
01195 headp = &chan->varshead;
01196 AST_LIST_TRAVERSE(headp, current, entries) {
01197 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
01198 if (sscanf(ast_var_value(current), "%30d", &result.inhandle) != 1) {
01199 result.inhandle = OSP_INVALID_HANDLE;
01200 }
01201 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
01202 if (sscanf(ast_var_value(current), "%30d", &result.outhandle) != 1) {
01203 result.outhandle = OSP_INVALID_HANDLE;
01204 }
01205 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
01206 if (sscanf(ast_var_value(current), "%30d", &result.intimelimit) != 1) {
01207 result.intimelimit = OSP_DEF_TIMELIMIT;
01208 }
01209 } else if (!strcasecmp(ast_var_name(current), "OSPRESULTS")) {
01210 if (sscanf(ast_var_value(current), "%30d", &result.numresults) != 1) {
01211 result.numresults = 0;
01212 }
01213 }
01214 }
01215 ast_log(LOG_DEBUG, "OSPNext: OSPINHANDLE '%d'\n", result.inhandle);
01216 ast_log(LOG_DEBUG, "OSPNext: OSPOUTHANDLE '%d'\n", result.outhandle);
01217 ast_log(LOG_DEBUG, "OSPNext: OSPINTIMELIMIT '%d'\n", result.intimelimit);
01218 ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%d'\n", result.numresults);
01219
01220 if ((res = osp_next(cause, &result)) > 0) {
01221 status = AST_OSP_SUCCESS;
01222 } else {
01223 result.tech[0] = '\0';
01224 result.dest[0] = '\0';
01225 result.calling[0] = '\0';
01226 result.token[0] = '\0';
01227 result.numresults = 0;
01228 result.outtimelimit = OSP_DEF_TIMELIMIT;
01229 if (!res) {
01230 status = AST_OSP_FAILED;
01231 } else {
01232 status = AST_OSP_ERROR;
01233 }
01234 }
01235
01236 pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
01237 ast_log(LOG_DEBUG, "OSPNext: OSPTECH '%s'\n", result.tech);
01238 pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
01239 ast_log(LOG_DEBUG, "OSPNext: OSPDEST '%s'\n", result.dest);
01240 pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
01241 ast_log(LOG_DEBUG, "OSPNext: OSPCALLING '%s'\n", result.calling);
01242 pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
01243 ast_log(LOG_DEBUG, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
01244 snprintf(buffer, sizeof(buffer), "%d", result.numresults);
01245 pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
01246 ast_log(LOG_DEBUG, "OSPNext: OSPRESULTS '%s'\n", buffer);
01247 snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
01248 pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
01249 ast_log(LOG_DEBUG, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
01250 pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
01251 ast_log(LOG_DEBUG, "OSPNext: %s\n", status);
01252
01253 if (!strcasecmp(result.tech, "SIP")) {
01254 if (!ast_strlen_zero(result.token)) {
01255 snprintf(buffer, sizeof(buffer), "P-OSP-Auth-Token: %s", result.token);
01256 pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
01257 ast_log(LOG_DEBUG, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
01258 }
01259 } else if (!strcasecmp(result.tech, "H323")) {
01260 } else if (!strcasecmp(result.tech, "IAX")) {
01261 }
01262
01263 if(res <= 0) {
01264 if (priority_jump || ast_opt_priority_jumping) {
01265 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
01266 res = 0;
01267 } else {
01268 res = -1;
01269 }
01270 } else {
01271 res = 0;
01272 }
01273
01274 ast_module_user_remove(u);
01275
01276 return res;
01277 }
01278
01279
01280
01281
01282
01283
01284
01285 static int ospfinished_exec(struct ast_channel* chan, void* data)
01286 {
01287 int res = 1;
01288 struct ast_module_user *u;
01289 int priority_jump = 0;
01290 int cause = 0;
01291 struct varshead *headp;
01292 struct ast_var_t *current;
01293 int inhandle = OSP_INVALID_HANDLE;
01294 int outhandle = OSP_INVALID_HANDLE;
01295 int recorded = 0;
01296 time_t start, connect, end;
01297 unsigned int release;
01298 char buffer[OSP_INTSTR_SIZE];
01299 const char *status;
01300 char *tmp;
01301
01302 AST_DECLARE_APP_ARGS(args,
01303 AST_APP_ARG(cause);
01304 AST_APP_ARG(options);
01305 );
01306
01307 u = ast_module_user_add(chan);
01308
01309 if (!(tmp = ast_strdupa(data))) {
01310 ast_log(LOG_ERROR, "Out of memory\n");
01311 ast_module_user_remove(u);
01312 return -1;
01313 }
01314
01315 AST_STANDARD_APP_ARGS(args, tmp);
01316
01317 if ((args.options) && (strchr(args.options, 'j'))) {
01318 priority_jump = 1;
01319 }
01320 ast_log(LOG_DEBUG, "OSPFinish: priority jump '%d'\n", priority_jump);
01321
01322 headp = &chan->varshead;
01323 AST_LIST_TRAVERSE(headp, current, entries) {
01324 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
01325 if (sscanf(ast_var_value(current), "%30d", &inhandle) != 1) {
01326 inhandle = OSP_INVALID_HANDLE;
01327 }
01328 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
01329 if (sscanf(ast_var_value(current), "%30d", &outhandle) != 1) {
01330 outhandle = OSP_INVALID_HANDLE;
01331 }
01332 } else if (!recorded &&
01333 (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
01334 !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
01335 !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS")))
01336 {
01337 if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
01338 recorded = 1;
01339 }
01340 }
01341 }
01342 ast_log(LOG_DEBUG, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
01343 ast_log(LOG_DEBUG, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
01344 ast_log(LOG_DEBUG, "OSPFinish: recorded '%d'\n", recorded);
01345
01346 if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%30d", &cause) != 1) {
01347 cause = 0;
01348 }
01349 ast_log(LOG_DEBUG, "OSPFinish: cause '%d'\n", cause);
01350
01351 if (chan->cdr) {
01352 start = chan->cdr->start.tv_sec;
01353 connect = chan->cdr->answer.tv_sec;
01354 if (connect) {
01355 end = time(NULL);
01356 } else {
01357 end = connect;
01358 }
01359 } else {
01360 start = 0;
01361 connect = 0;
01362 end = 0;
01363 }
01364 ast_log(LOG_DEBUG, "OSPFinish: start '%ld'\n", start);
01365 ast_log(LOG_DEBUG, "OSPFinish: connect '%ld'\n", connect);
01366 ast_log(LOG_DEBUG, "OSPFinish: end '%ld'\n", end);
01367
01368 release = chan->_softhangup ? 0 : 1;
01369
01370 if (osp_finish(outhandle, recorded, cause, start, connect, end, release) <= 0) {
01371 ast_log(LOG_DEBUG, "OSPFinish: Unable to report usage for outbound call\n");
01372 }
01373 switch (cause) {
01374 case AST_CAUSE_NORMAL_CLEARING:
01375 break;
01376 default:
01377 cause = AST_CAUSE_NO_ROUTE_DESTINATION;
01378 break;
01379 }
01380 if (osp_finish(inhandle, recorded, cause, start, connect, end, release) <= 0) {
01381 ast_log(LOG_DEBUG, "OSPFinish: Unable to report usage for inbound call\n");
01382 }
01383 snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
01384 pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
01385 pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
01386
01387 if (res > 0) {
01388 status = AST_OSP_SUCCESS;
01389 } else if (!res) {
01390 status = AST_OSP_FAILED;
01391 } else {
01392 status = AST_OSP_ERROR;
01393 }
01394 pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
01395
01396 if(!res) {
01397 if (priority_jump || ast_opt_priority_jumping) {
01398 ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101);
01399 res = 0;
01400 } else {
01401 res = -1;
01402 }
01403 } else {
01404 res = 0;
01405 }
01406
01407 ast_module_user_remove(u);
01408
01409 return res;
01410 }
01411
01412
01413
01414 static int osp_load(void)
01415 {
01416 const char* t;
01417 unsigned int v;
01418 struct ast_config* cfg;
01419 int error = OSPC_ERR_NO_ERROR;
01420
01421 cfg = ast_config_load(OSP_CONFIG_FILE);
01422 if (cfg) {
01423 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate");
01424 if (t && ast_true(t)) {
01425 if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
01426 ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
01427 OSPPInit(0);
01428 } else {
01429 osp_hardware = 1;
01430 }
01431 } else {
01432 OSPPInit(0);
01433 }
01434 ast_log(LOG_DEBUG, "OSP: osp_hardware '%d'\n", osp_hardware);
01435
01436 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat");
01437 if (t) {
01438 if ((sscanf(t, "%30d", &v) == 1) &&
01439 ((v == TOKEN_ALGO_SIGNED) || (v == TOKEN_ALGO_UNSIGNED) || (v == TOKEN_ALGO_BOTH)))
01440 {
01441 osp_tokenformat = v;
01442 } else {
01443 ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
01444 TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, t);
01445 }
01446 }
01447 ast_log(LOG_DEBUG, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
01448
01449 t = ast_category_browse(cfg, NULL);
01450 while(t) {
01451 if (strcasecmp(t, OSP_GENERAL_CAT)) {
01452 osp_create_provider(cfg, t);
01453 }
01454 t = ast_category_browse(cfg, t);
01455 }
01456
01457 osp_initialized = 1;
01458
01459 ast_config_destroy(cfg);
01460 } else {
01461 ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
01462 return 0;
01463 }
01464 ast_log(LOG_DEBUG, "OSP: osp_initialized '%d'\n", osp_initialized);
01465
01466 return 1;
01467 }
01468
01469 static int osp_unload(void)
01470 {
01471 struct osp_provider* p;
01472 struct osp_provider* next;
01473
01474 if (osp_initialized) {
01475 ast_mutex_lock(&osplock);
01476 p = ospproviders;
01477 while(p) {
01478 next = p->next;
01479 OSPPProviderDelete(p->handle, 0);
01480 free(p);
01481 p = next;
01482 }
01483 ospproviders = NULL;
01484 ast_mutex_unlock(&osplock);
01485
01486 OSPPCleanup();
01487
01488 osp_tokenformat = TOKEN_ALGO_SIGNED;
01489 osp_hardware = 0;
01490 osp_initialized = 0;
01491 }
01492 return 0;
01493 }
01494
01495 static int osp_show(int fd, int argc, char* argv[])
01496 {
01497 int i;
01498 int found = 0;
01499 struct osp_provider* p;
01500 const char* provider = NULL;
01501 const char* tokenalgo;
01502
01503 if ((argc < 2) || (argc > 3)) {
01504 return RESULT_SHOWUSAGE;
01505 }
01506 if (argc > 2) {
01507 provider = argv[2];
01508 }
01509 if (!provider) {
01510 switch (osp_tokenformat) {
01511 case TOKEN_ALGO_BOTH:
01512 tokenalgo = "Both";
01513 break;
01514 case TOKEN_ALGO_UNSIGNED:
01515 tokenalgo = "Unsigned";
01516 break;
01517 case TOKEN_ALGO_SIGNED:
01518 default:
01519 tokenalgo = "Signed";
01520 break;
01521 }
01522 ast_cli(fd, "OSP: %s %s %s\n",
01523 osp_initialized ? "Initialized" : "Uninitialized", osp_hardware ? "Accelerated" : "Normal", tokenalgo);
01524 }
01525
01526 ast_mutex_lock(&osplock);
01527 p = ospproviders;
01528 while(p) {
01529 if (!provider || !strcasecmp(p->name, provider)) {
01530 if (found) {
01531 ast_cli(fd, "\n");
01532 }
01533 ast_cli(fd, " == OSP Provider '%s' == \n", p->name);
01534 ast_cli(fd, "Local Private Key: %s\n", p->privatekey);
01535 ast_cli(fd, "Local Certificate: %s\n", p->localcert);
01536 for (i = 0; i < p->cacount; i++) {
01537 ast_cli(fd, "CA Certificate %d: %s\n", i + 1, p->cacerts[i]);
01538 }
01539 for (i = 0; i < p->spcount; i++) {
01540 ast_cli(fd, "Service Point %d: %s\n", i + 1, p->srvpoints[i]);
01541 }
01542 ast_cli(fd, "Max Connections: %d\n", p->maxconnections);
01543 ast_cli(fd, "Retry Delay: %d seconds\n", p->retrydelay);
01544 ast_cli(fd, "Retry Limit: %d\n", p->retrylimit);
01545 ast_cli(fd, "Timeout: %d milliseconds\n", p->timeout);
01546 ast_cli(fd, "Source: %s\n", strlen(p->source) ? p->source : "<unspecified>");
01547 ast_cli(fd, "Auth Policy %d\n", p->authpolicy);
01548 ast_cli(fd, "OSP Handle: %d\n", p->handle);
01549 found++;
01550 }
01551 p = p->next;
01552 }
01553 ast_mutex_unlock(&osplock);
01554
01555 if (!found) {
01556 if (provider) {
01557 ast_cli(fd, "Unable to find OSP provider '%s'\n", provider);
01558 } else {
01559 ast_cli(fd, "No OSP providers configured\n");
01560 }
01561 }
01562 return RESULT_SUCCESS;
01563 }
01564
01565 static const char* app1= "OSPAuth";
01566 static const char* synopsis1 = "OSP authentication";
01567 static const char* descrip1 =
01568 " OSPAuth([provider[|options]]): Authenticate a SIP INVITE by OSP and sets\n"
01569 "the variables:\n"
01570 " ${OSPINHANDLE}: The inbound call transaction handle\n"
01571 " ${OSPINTIMELIMIT}: The inbound call duration limit in seconds\n"
01572 "\n"
01573 "The option string may contain the following character:\n"
01574 " 'j' -- jump to n+101 priority if the authentication was NOT successful\n"
01575 "This application sets the following channel variable upon completion:\n"
01576 " OSPAUTHSTATUS The status of the OSP Auth attempt as a text string, one of\n"
01577 " SUCCESS | FAILED | ERROR\n";
01578
01579 static const char* app2= "OSPLookup";
01580 static const char* synopsis2 = "Lookup destination by OSP";
01581 static const char* descrip2 =
01582 " OSPLookup(exten[|provider[|options]]): Looks up an extension via OSP and sets\n"
01583 "the variables, where 'n' is the number of the result beginning with 1:\n"
01584 " ${OSPOUTHANDLE}: The OSP Handle for anything remaining\n"
01585 " ${OSPTECH}: The technology to use for the call\n"
01586 " ${OSPDEST}: The destination to use for the call\n"
01587 " ${OSPCALLING}: The calling number to use for the call\n"
01588 " ${OSPOUTTOKEN}: The actual OSP token as a string\n"
01589 " ${OSPOUTTIMELIMIT}: The outbound call duration limit in seconds\n"
01590 " ${OSPRESULTS}: The number of OSP results total remaining\n"
01591 "\n"
01592 "The option string may contain the following character:\n"
01593 " 'j' -- jump to n+101 priority if the lookup was NOT successful\n"
01594 "This application sets the following channel variable upon completion:\n"
01595 " OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n"
01596 " SUCCESS | FAILED | ERROR\n";
01597
01598 static const char* app3 = "OSPNext";
01599 static const char* synopsis3 = "Lookup next destination by OSP";
01600 static const char* descrip3 =
01601 " OSPNext(cause[|options]): Looks up the next OSP Destination for ${OSPOUTHANDLE}\n"
01602 "See OSPLookup for more information\n"
01603 "\n"
01604 "The option string may contain the following character:\n"
01605 " 'j' -- jump to n+101 priority if the lookup was NOT successful\n"
01606 "This application sets the following channel variable upon completion:\n"
01607 " OSPNEXTSTATUS The status of the OSP Next attempt as a text string, one of\n"
01608 " SUCCESS | FAILED |ERROR\n";
01609
01610 static const char* app4 = "OSPFinish";
01611 static const char* synopsis4 = "Record OSP entry";
01612 static const char* descrip4 =
01613 " OSPFinish([status[|options]]): Records call state for ${OSPINHANDLE}, according to\n"
01614 "status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
01615 "or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
01616 "\n"
01617 "The option string may contain the following character:\n"
01618 " 'j' -- jump to n+101 priority if the finish attempt was NOT successful\n"
01619 "This application sets the following channel variable upon completion:\n"
01620 " OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n"
01621 " SUCCESS | FAILED |ERROR \n";
01622
01623 static const char osp_usage[] =
01624 "Usage: osp show\n"
01625 " Displays information on Open Settlement Protocol support\n";
01626
01627 static struct ast_cli_entry cli_osp[] = {
01628 { { "osp", "show", NULL},
01629 osp_show, "Displays OSP information",
01630 osp_usage },
01631 };
01632
01633 static int load_module(void)
01634 {
01635 int res;
01636
01637 if(!osp_load())
01638 return AST_MODULE_LOAD_DECLINE;
01639
01640 ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
01641 res = ast_register_application(app1, ospauth_exec, synopsis1, descrip1);
01642 res |= ast_register_application(app2, osplookup_exec, synopsis2, descrip2);
01643 res |= ast_register_application(app3, ospnext_exec, synopsis3, descrip3);
01644 res |= ast_register_application(app4, ospfinished_exec, synopsis4, descrip4);
01645
01646 return res;
01647 }
01648
01649 static int unload_module(void)
01650 {
01651 int res;
01652
01653 res = ast_unregister_application(app4);
01654 res |= ast_unregister_application(app3);
01655 res |= ast_unregister_application(app2);
01656 res |= ast_unregister_application(app1);
01657 ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
01658 osp_unload();
01659
01660 ast_module_user_hangup_all();
01661
01662 return res;
01663 }
01664
01665 static int reload(void)
01666 {
01667 osp_unload();
01668 osp_load();
01669
01670 return 0;
01671 }
01672
01673 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
01674 .load = load_module,
01675 .unload = unload_module,
01676 .reload = reload,
01677 );