Const-ify the world (or at least a good part of it)
[asterisk/asterisk.git] / apps / app_osplookup.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  * \brief Open Settlement Protocol (OSP) Applications
22  *
23  * \author Mark Spencer <markster@digium.com>
24  *
25  * \extref The OSP Toolkit: http://www.transnexus.com
26  * \extref OpenSSL http://www.openssl.org
27  *
28  * \ingroup applications
29  */
30
31 /*** MODULEINFO
32         <depend>osptk</depend>
33         <depend>openssl</depend>
34  ***/
35
36 #include "asterisk.h"
37
38 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
39
40 #include <osp/osp.h>
41 #include <osp/osputils.h>
42 #include <osp/ospb64.h>
43
44 #include "asterisk/paths.h"
45 #include "asterisk/lock.h"
46 #include "asterisk/config.h"
47 #include "asterisk/utils.h"
48 #include "asterisk/causes.h"
49 #include "asterisk/channel.h"
50 #include "asterisk/app.h"
51 #include "asterisk/module.h"
52 #include "asterisk/pbx.h"
53 #include "asterisk/cli.h"
54 #include "asterisk/astosp.h"
55
56 /* OSP Buffer Sizes */
57 #define OSP_INTSTR_SIZE         ((unsigned int)16)              /* OSP signed/unsigned int string buffer size */
58 #define OSP_NORSTR_SIZE         ((unsigned int)256)             /* OSP normal string buffer size */
59 #define OSP_KEYSTR_SIZE         ((unsigned int)1024)    /* OSP certificate string buffer size */
60 #define OSP_TOKSTR_SIZE         ((unsigned int)4096)    /* OSP token string buffer size */
61 #define OSP_TECHSTR_SIZE        ((unsigned int)32)              /* OSP signed/unsigned int string buffer size */
62 #define OSP_UUID_SIZE           ((unsigned int)16)              /* UUID size */
63 #define OSP_UUIDSTR_SIZE        ((unsigned int)36)              /* UUID string size */
64
65 /* OSP Authentication Policy */
66 enum osp_authpolicy {
67         OSP_AUTH_NO,            /* Accept any call */
68         OSP_AUTH_YES,           /* Accept call with valid OSP token or without OSP token */
69         OSP_AUTH_EXCLUSIVE      /* Only accept call with valid OSP token */
70 };
71
72 /* Call ID type*/
73 #define OSP_CALLID_UNDEFINED    ((unsigned int)0)                       /* UNDEFINED */
74 #define OSP_CALLID_H323                 ((unsigned int)(1 << 0))        /* H.323 */
75 #define OSP_CALLID_SIP                  ((unsigned int)(1 << 1))        /* SIP */
76 #define OSP_CALLID_IAX                  ((unsigned int)(1 << 2))        /* IAX2 */
77 #define OSP_CALLID_MAXNUM               ((unsigned int)3)                       /* Max number of call ID type */
78
79 /* OSP Supported Destination Protocols */
80 #define OSP_PROT_H323                   ((char*)"H323")                         /* H323 Q931 protocol name*/
81 #define OSP_PROT_SIP                    ((char*)"SIP")                          /* SIP protocol name */
82 #define OSP_PROT_IAX                    ((char*)"IAX")                          /* IAX protocol name */
83 #define OSP_PROT_OTHER                  ((char*)"OTHER")                        /* Other protocol name */
84
85 /* OSP supported Destination Tech */
86 #if 0
87 #define OSP_TECH_H323                   ((char*)"OOH323")                       /* OOH323 tech name */
88 #endif
89 #define OSP_TECH_H323                   ((char*)"H323")                         /* OH323 tech name */
90 #define OSP_TECH_SIP                    ((char*)"SIP")                          /* SIP tech name */
91 #define OSP_TECH_IAX                    ((char*)"IAX2")                         /* IAX2 tech name */
92
93 /* SIP OSP header field name */
94 #define OSP_SIP_HEADER                  ((char*)"P-OSP-Auth-Token: ")
95
96 /* OSP Constants */
97 #define OSP_INVALID_HANDLE              ((int)-1)                                       /* Invalid OSP handle, provider, transaction etc. */
98 #define OSP_CONFIG_FILE                 ((const char*)"osp.conf")       /* OSP configuration file name */
99 #define OSP_GENERAL_CAT                 ((const char*)"general")        /* OSP global configuration context name */
100 #define OSP_DEF_PROVIDER                ((const char*)"default")        /* OSP default provider context name */
101 #define OSP_MAX_CERTS                   ((unsigned int)10)                      /* OSP max number of cacerts */
102 #define OSP_MAX_SRVS                    ((unsigned int)10)                      /* OSP max number of service points */
103 #define OSP_DEF_MAXCONNECTIONS  ((unsigned int)20)                      /* OSP default max_connections */
104 #define OSP_MIN_MAXCONNECTIONS  ((unsigned int)1)                       /* OSP min max_connections */
105 #define OSP_MAX_MAXCONNECTIONS  ((unsigned int)1000)            /* OSP max max_connections */
106 #define OSP_DEF_RETRYDELAY              ((unsigned int)0)                       /* OSP default retry delay */
107 #define OSP_MIN_RETRYDELAY              ((unsigned int)0)                       /* OSP min retry delay */
108 #define OSP_MAX_RETRYDELAY              ((unsigned int)10)                      /* OSP max retry delay */
109 #define OSP_DEF_RETRYLIMIT              ((unsigned int)2)                       /* OSP default retry times */
110 #define OSP_MIN_RETRYLIMIT              ((unsigned int)0)                       /* OSP min retry times */
111 #define OSP_MAX_RETRYLIMIT              ((unsigned int)100)                     /* OSP max retry times */
112 #define OSP_DEF_TIMEOUT                 ((unsigned int)500)                     /* OSP default timeout in ms */
113 #define OSP_MIN_TIMEOUT                 ((unsigned int)200)                     /* OSP min timeout in ms */
114 #define OSP_MAX_TIMEOUT                 ((unsigned int)10000)           /* OSP max timeout in ms */
115 #define OSP_DEF_AUTHPOLICY              ((enum osp_authpolicy)OSP_AUTH_YES)
116 #define OSP_AUDIT_URL                   ((const char*)"localhost")      /* OSP default Audit URL */
117 #define OSP_LOCAL_VALIDATION    ((int)1)                                        /* Validate OSP token locally */
118 #define OSP_SSL_LIFETIME                ((unsigned int)300)                     /* SSL life time, in seconds */
119 #define OSP_HTTP_PERSISTENCE    ((int)1)                                        /* In seconds */
120 #define OSP_CUSTOMER_ID                 ((const char*)"")                       /* OSP customer ID */
121 #define OSP_DEVICE_ID                   ((const char*)"")                       /* OSP device ID */
122 #define OSP_DEF_DESTINATIONS    ((unsigned int)5)                       /* OSP default max number of destinations */
123 #define OSP_DEF_TIMELIMIT               ((unsigned int)0)                       /* OSP default duration limit, no limit */
124 #define OSP_DEF_PROTOCOL                OSP_PROT_SIP                            /* OSP default destination protocol, SIP */
125
126 /* OSP Provider */
127 struct osp_provider {
128         char name[OSP_NORSTR_SIZE];                                             /* OSP provider context name */
129         char privatekey[OSP_NORSTR_SIZE];                               /* OSP private key file name */
130         char localcert[OSP_NORSTR_SIZE];                                /* OSP local cert file name */
131         unsigned int cacount;                                                   /* Number of cacerts */
132         char cacerts[OSP_MAX_CERTS][OSP_NORSTR_SIZE];   /* Cacert file names */
133         unsigned int spcount;                                                   /* Number of service points */
134         char srvpoints[OSP_MAX_SRVS][OSP_NORSTR_SIZE];  /* Service point URLs */
135         int maxconnections;                                                             /* Max number of connections */
136         int retrydelay;                                                                 /* Retry delay */
137         int retrylimit;                                                                 /* Retry limit */
138         int timeout;                                                                    /* Timeout in ms */
139         char source[OSP_NORSTR_SIZE];                                   /* IP of self */
140         enum osp_authpolicy authpolicy;                                 /* OSP authentication policy */
141         char* defaultprotocol;                                                  /* OSP default destination protocol */
142         OSPTPROVHANDLE handle;                                                  /* OSP provider handle */
143         struct osp_provider* next;                                              /* Pointer to next OSP provider */
144 };
145
146 /* Call ID */
147 struct osp_callid {
148         unsigned char buf[OSPC_CALLID_MAXSIZE];         /* Call ID string */
149         unsigned int len;                                                       /* Call ID length */
150 };
151
152 /* OSP Application In/Output Results */
153 struct osp_result {
154         int inhandle;                                           /* Inbound transaction handle */
155         int outhandle;                                          /* Outbound transaction handle */
156         unsigned int intimelimit;                       /* Inbound duration limit */
157         unsigned int outtimelimit;                      /* Outbound duration limit */
158         char tech[OSP_TECHSTR_SIZE];            /* Outbound Asterisk TECH string */
159         char dest[OSP_NORSTR_SIZE];                     /* Outbound destination IP address */
160         char called[OSP_NORSTR_SIZE];           /* Outbound called number, may be translated */
161         char calling[OSP_NORSTR_SIZE];          /* Outbound calling number, may be translated */
162         char token[OSP_TOKSTR_SIZE];            /* Outbound OSP token */
163         char networkid[OSP_NORSTR_SIZE];        /* Outbound network ID */
164         unsigned int numresults;                        /* Number of remain outbound destinations */
165         struct osp_callid outcallid;            /* Outbound call ID */
166 };
167
168 /* OSP Module Global Variables */
169 AST_MUTEX_DEFINE_STATIC(osplock);                                                       /* Lock of OSP provider list */
170 static int osp_initialized = 0;                                                         /* Init flag */
171 static int osp_hardware = 0;                                                            /* Hardware accelleration flag */
172 static int osp_security = 0;                                                            /* Using security features flag */
173 static struct osp_provider* ospproviders = NULL;                        /* OSP provider list */
174 static unsigned int osp_tokenformat = TOKEN_ALGO_SIGNED;        /* Token format supported */
175
176 /* OSP default certificates */
177 const char* B64PKey = "MIIBOgIBAAJBAK8t5l+PUbTC4lvwlNxV5lpl+2dwSZGW46dowTe6y133XyVEwNiiRma2YNk3xKs/TJ3Wl9Wpns2SYEAJsFfSTukCAwEAAQJAPz13vCm2GmZ8Zyp74usTxLCqSJZNyMRLHQWBM0g44Iuy4wE3vpi7Wq+xYuSOH2mu4OddnxswCP4QhaXVQavTAQIhAOBVCKXtppEw9UaOBL4vW0Ed/6EA/1D8hDW6St0h7EXJAiEAx+iRmZKhJD6VT84dtX5ZYNVk3j3dAcIOovpzUj9a0CECIEduTCapmZQ5xqAEsLXuVlxRtQgLTUD4ZxDElPn8x0MhAiBE2HlcND0+qDbvtwJQQOUzDgqg5xk3w8capboVdzAlQQIhAMC+lDL7+gDYkNAft5Mu+NObJmQs4Cr+DkDFsKqoxqrm";
178 const char* B64LCert = "MIIBeTCCASMCEHqkOHVRRWr+1COq3CR/xsowDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTA1MDYyMzAwMjkxOFoXDTA2MDYyNDAwMjkxOFowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCvLeZfj1G0wuJb8JTcVeZaZftncEmRluOnaME3ustd918lRMDYokZmtmDZN8SrP0yd1pfVqZ7NkmBACbBX0k7pAgMBAAEwDQYJKoZIhvcNAQEEBQADQQDnV8QNFVVJx/+7IselU0wsepqMurivXZzuxOmTEmTVDzCJx1xhA8jd3vGAj7XDIYiPub1PV23eY5a2ARJuw5w9";
179 const char* B64CACert = "MIIBYDCCAQoCAQEwDQYJKoZIhvcNAQEEBQAwOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMB4XDTAyMDIwNDE4MjU1MloXDTEyMDIwMzE4MjU1MlowOzElMCMGA1UEAxMcb3NwdGVzdHNlcnZlci50cmFuc25leHVzLmNvbTESMBAGA1UEChMJT1NQU2VydmVyMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAPGeGwV41EIhX0jEDFLRXQhDEr50OUQPq+f55VwQd0TQNts06BP29+UiNdRW3c3IRHdZcJdC1Cg68ME9cgeq0h8CAwEAATANBgkqhkiG9w0BAQQFAANBAGkzBSj1EnnmUxbaiG1N4xjIuLAWydun7o3bFk2tV8dBIhnuh445obYyk1EnQ27kI7eACCILBZqi2MHDOIMnoN0=";
180
181 /* OSP Client Wrapper APIs */
182
183 /*!
184  * \brief Create OSP provider handle according to configuration
185  * \param cfg OSP configuration
186  * \param provider OSP provider context name
187  * \return 1 Success, 0 Failed, -1 Error
188  */
189 static int osp_create_provider(
190         struct ast_config* cfg,
191         const char* provider)
192 {
193         int res = 0;
194         struct ast_variable* v;
195         struct osp_provider* p;
196         OSPTPRIVATEKEY privatekey;
197         OSPT_CERT localcert;
198         OSPT_CERT cacerts[OSP_MAX_CERTS];
199         const OSPT_CERT* pcacerts[OSP_MAX_CERTS];
200         const char* psrvpoints[OSP_MAX_SRVS];
201         unsigned char privatekeydata[OSP_KEYSTR_SIZE];
202         unsigned char localcertdata[OSP_KEYSTR_SIZE];
203         unsigned char cacertdata[OSP_KEYSTR_SIZE];
204         int i, t, error = OSPC_ERR_NO_ERROR;
205
206         if (!(p = ast_calloc(1, sizeof(*p)))) {
207                 ast_log(LOG_ERROR, "Out of memory\n");
208                 return -1;
209         }
210
211         /* ast_calloc has set 0 in p */
212         ast_copy_string(p->name, provider, sizeof(p->name));
213         snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s-privatekey.pem", ast_config_AST_KEY_DIR, provider);
214         snprintf(p->localcert, sizeof(p->localcert), "%s/%s-localcert.pem", ast_config_AST_KEY_DIR, provider);
215         snprintf(p->cacerts[0], sizeof(p->cacerts[0]), "%s/%s-cacert_0.pem", ast_config_AST_KEY_DIR, provider);
216         p->maxconnections = OSP_DEF_MAXCONNECTIONS;
217         p->retrydelay = OSP_DEF_RETRYDELAY;
218         p->retrylimit = OSP_DEF_RETRYLIMIT;
219         p->timeout = OSP_DEF_TIMEOUT;
220         p->authpolicy = OSP_DEF_AUTHPOLICY;
221         p->defaultprotocol = OSP_DEF_PROTOCOL;
222         p->handle = OSP_INVALID_HANDLE;
223
224         v = ast_variable_browse(cfg, provider);
225         while(v) {
226                 if (!strcasecmp(v->name, "privatekey")) {
227                         if (osp_security) {
228                                 if (v->value[0] == '/') {
229                                         ast_copy_string(p->privatekey, v->value, sizeof(p->privatekey));
230                                 } else {
231                                         snprintf(p->privatekey, sizeof(p->privatekey), "%s/%s", ast_config_AST_KEY_DIR, v->value);
232                                 }
233                                 ast_debug(1, "OSP: privatekey '%s'\n", p->privatekey);
234                         }
235                 } else if (!strcasecmp(v->name, "localcert")) {
236                         if (osp_security) {
237                                 if (v->value[0] == '/') {
238                                         ast_copy_string(p->localcert, v->value, sizeof(p->localcert));
239                                 } else {
240                                         snprintf(p->localcert, sizeof(p->localcert), "%s/%s", ast_config_AST_KEY_DIR, v->value);
241                                 }
242                                 ast_debug(1, "OSP: localcert '%s'\n", p->localcert);
243                         }
244                 } else if (!strcasecmp(v->name, "cacert")) {
245                         if (osp_security) {
246                                 if (p->cacount < OSP_MAX_CERTS) {
247                                         if (v->value[0] == '/') {
248                                                 ast_copy_string(p->cacerts[p->cacount], v->value, sizeof(p->cacerts[0]));
249                                         } else {
250                                                 snprintf(p->cacerts[p->cacount], sizeof(p->cacerts[0]), "%s/%s", ast_config_AST_KEY_DIR, v->value);
251                                         }
252                                         ast_debug(1, "OSP: cacerts[%d]: '%s'\n", p->cacount, p->cacerts[p->cacount]);
253                                         p->cacount++;
254                                 } else {
255                                         ast_log(LOG_WARNING, "OSP: Too many CA Certificates at line %d\n", v->lineno);
256                                 }
257                         }
258                 } else if (!strcasecmp(v->name, "servicepoint")) {
259                         if (p->spcount < OSP_MAX_SRVS) {
260                                 ast_copy_string(p->srvpoints[p->spcount], v->value, sizeof(p->srvpoints[0]));
261                                 ast_debug(1, "OSP: servicepoint[%d]: '%s'\n", p->spcount, p->srvpoints[p->spcount]);
262                                 p->spcount++;
263                         } else {
264                                 ast_log(LOG_WARNING, "OSP: Too many Service Points at line %d\n", v->lineno);
265                         }
266                 } else if (!strcasecmp(v->name, "maxconnections")) {
267                         if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_MAXCONNECTIONS) && (t <= OSP_MAX_MAXCONNECTIONS)) {
268                                 p->maxconnections = t;
269                                 ast_debug(1, "OSP: maxconnections '%d'\n", t);
270                         } else {
271                                 ast_log(LOG_WARNING, "OSP: maxconnections should be an integer from %d to %d, not '%s' at line %d\n",
272                                         OSP_MIN_MAXCONNECTIONS, OSP_MAX_MAXCONNECTIONS, v->value, v->lineno);
273                         }
274                 } else if (!strcasecmp(v->name, "retrydelay")) {
275                         if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYDELAY) && (t <= OSP_MAX_RETRYDELAY)) {
276                                 p->retrydelay = t;
277                                 ast_debug(1, "OSP: retrydelay '%d'\n", t);
278                         } else {
279                                 ast_log(LOG_WARNING, "OSP: retrydelay should be an integer from %d to %d, not '%s' at line %d\n",
280                                         OSP_MIN_RETRYDELAY, OSP_MAX_RETRYDELAY, v->value, v->lineno);
281                         }
282                 } else if (!strcasecmp(v->name, "retrylimit")) {
283                         if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_RETRYLIMIT) && (t <= OSP_MAX_RETRYLIMIT)) {
284                                 p->retrylimit = t;
285                                 ast_debug(1, "OSP: retrylimit '%d'\n", t);
286                         } else {
287                                 ast_log(LOG_WARNING, "OSP: retrylimit should be an integer from %d to %d, not '%s' at line %d\n",
288                                         OSP_MIN_RETRYLIMIT, OSP_MAX_RETRYLIMIT, v->value, v->lineno);
289                         }
290                 } else if (!strcasecmp(v->name, "timeout")) {
291                         if ((sscanf(v->value, "%d", &t) == 1) && (t >= OSP_MIN_TIMEOUT) && (t <= OSP_MAX_TIMEOUT)) {
292                                 p->timeout = t;
293                                 ast_debug(1, "OSP: timeout '%d'\n", t);
294                         } else {
295                                 ast_log(LOG_WARNING, "OSP: timeout should be an integer from %d to %d, not '%s' at line %d\n",
296                                         OSP_MIN_TIMEOUT, OSP_MAX_TIMEOUT, v->value, v->lineno);
297                         }
298                 } else if (!strcasecmp(v->name, "source")) {
299                         ast_copy_string(p->source, v->value, sizeof(p->source));
300                         ast_debug(1, "OSP: source '%s'\n", p->source);
301                 } else if (!strcasecmp(v->name, "authpolicy")) {
302                         if ((sscanf(v->value, "%d", &t) == 1) && ((t == OSP_AUTH_NO) || (t == OSP_AUTH_YES) || (t == OSP_AUTH_EXCLUSIVE))) {
303                                 p->authpolicy = t;
304                                 ast_debug(1, "OSP: authpolicy '%d'\n", t);
305                         } else {
306                                 ast_log(LOG_WARNING, "OSP: authpolicy should be %d, %d or %d, not '%s' at line %d\n",
307                                         OSP_AUTH_NO, OSP_AUTH_YES, OSP_AUTH_EXCLUSIVE, v->value, v->lineno);
308                         }
309                 } else if (!strcasecmp(v->name, "defaultprotocol")) {
310                         if (!strcasecmp(v->value, OSP_PROT_SIP)) {
311                                 p->defaultprotocol = OSP_PROT_SIP;
312                                 ast_debug(1, "OSP: default protocol '%s'\n", p->defaultprotocol);
313                         } else if (!strcasecmp(v->value, OSP_PROT_H323)) {
314                                 p->defaultprotocol = OSP_PROT_H323;
315                                 ast_debug(1, "OSP: default protocol '%s'\n", p->defaultprotocol);
316                         } else if (!strcasecmp(v->value, OSP_PROT_IAX)) {
317                                 p->defaultprotocol = OSP_PROT_IAX;
318                                 ast_debug(1, "OSP: default protocol '%s'\n", p->defaultprotocol);
319                         } else {
320                                 ast_log(LOG_WARNING, "OSP: default protocol should be %s, %s, %s, or %s not '%s' at line %d\n",
321                                         OSP_PROT_SIP, OSP_PROT_H323, OSP_PROT_IAX, OSP_PROT_OTHER, v->value, v->lineno);
322                         }
323                 }
324                 v = v->next;
325         }
326
327         if (p->cacount == 0) {
328                 p->cacount = 1;
329         }
330
331         for (i = 0; i < p->spcount; i++) {
332                 psrvpoints[i] = p->srvpoints[i];
333         }
334
335         if (osp_security) {
336                 privatekey.PrivateKeyData = NULL;
337                 privatekey.PrivateKeyLength = 0;
338
339                 localcert.CertData = NULL;
340                 localcert.CertDataLength = 0;
341
342                 for (i = 0; i < p->cacount; i++) {
343                         cacerts[i].CertData = NULL;
344                         cacerts[i].CertDataLength = 0;
345                 }
346
347                 if ((error = OSPPUtilLoadPEMPrivateKey((unsigned char*)p->privatekey, &privatekey)) != OSPC_ERR_NO_ERROR) {
348                         ast_log(LOG_WARNING, "OSP: Unable to load privatekey '%s', error '%d'\n", p->privatekey, error);
349                 } else if ((error = OSPPUtilLoadPEMCert((unsigned char*)p->localcert, &localcert)) != OSPC_ERR_NO_ERROR) {
350                         ast_log(LOG_WARNING, "OSP: Unable to load localcert '%s', error '%d'\n", p->localcert, error);
351                 } else {
352                         for (i = 0; i < p->cacount; i++) {
353                                 if ((error = OSPPUtilLoadPEMCert((unsigned char*)p->cacerts[i], &cacerts[i])) != OSPC_ERR_NO_ERROR) {
354                                         ast_log(LOG_WARNING, "OSP: Unable to load cacert '%s', error '%d'\n", p->cacerts[i], error);
355                                         break;
356                                 } else {
357                                         pcacerts[i] = &cacerts[i];
358                                 }
359                         }
360                 }
361         } else {
362                 privatekey.PrivateKeyData = privatekeydata;
363                 privatekey.PrivateKeyLength = sizeof(privatekeydata);
364
365                 localcert.CertData = localcertdata;
366                 localcert.CertDataLength = sizeof(localcertdata);
367
368                 cacerts[0].CertData = cacertdata;
369                 cacerts[0].CertDataLength = sizeof(cacertdata);
370                 pcacerts[0] = &cacerts[0];
371
372                 if ((error = OSPPBase64Decode(B64PKey, strlen(B64PKey), privatekey.PrivateKeyData, &privatekey.PrivateKeyLength)) != OSPC_ERR_NO_ERROR) {
373                         ast_log(LOG_WARNING, "OSP: Unable to decode private key, error '%d'\n", error);
374                 } else if ((error = OSPPBase64Decode(B64LCert, strlen(B64LCert), localcert.CertData, &localcert.CertDataLength)) != OSPC_ERR_NO_ERROR) {
375                         ast_log(LOG_WARNING, "OSP: Unable to decode local cert, error '%d'\n", error);
376                 } else if ((error = OSPPBase64Decode(B64CACert, strlen(B64CACert), cacerts[0].CertData, &cacerts[0].CertDataLength)) != OSPC_ERR_NO_ERROR) {
377                         ast_log(LOG_WARNING, "OSP: Unable to decode cacert, error '%d'\n", error);
378                 }
379         }
380
381         if (error == OSPC_ERR_NO_ERROR) {
382                 error = OSPPProviderNew(
383                         p->spcount,
384                         psrvpoints,
385                         NULL,
386                         OSP_AUDIT_URL,
387                         &privatekey,
388                         &localcert,
389                         p->cacount,
390                         pcacerts,
391                         OSP_LOCAL_VALIDATION,
392                         OSP_SSL_LIFETIME,
393                         p->maxconnections,
394                         OSP_HTTP_PERSISTENCE,
395                         p->retrydelay,
396                         p->retrylimit,
397                         p->timeout,
398                         OSP_CUSTOMER_ID,
399                         OSP_DEVICE_ID,
400                         &p->handle);
401                 if (error != OSPC_ERR_NO_ERROR) {
402                         ast_log(LOG_WARNING, "OSP: Unable to create provider '%s', error '%d'\n", provider, error);
403                         res = -1;
404                 } else {
405                         ast_debug(1, "OSP: provider '%s'\n", provider);
406                         ast_mutex_lock(&osplock);
407                         p->next = ospproviders;
408                         ospproviders = p;
409                         ast_mutex_unlock(&osplock);
410                         res = 1;
411                 }
412         }
413
414         if (osp_security) {
415                 for (i = 0; i < p->cacount; i++) {
416                         if (cacerts[i].CertData) {
417                                 ast_free(cacerts[i].CertData);
418                         }
419                 }
420                 if (localcert.CertData) {
421                         ast_free(localcert.CertData);
422                 }
423                 if (privatekey.PrivateKeyData) {
424                         ast_free(privatekey.PrivateKeyData);
425                 }
426         }
427
428         if (res != 1) {
429                 ast_free(p);
430         }
431
432         return res;
433 }
434
435 /*!
436  * \brief Get OSP provider by name
437  * \param name OSP provider context name
438  * \param provider OSP provider structure
439  * \return 1 Success, 0 Failed, -1 Error
440  */
441 static int osp_get_provider(
442         const char* name,
443         struct osp_provider** provider)
444 {
445         int res = 0;
446         struct osp_provider* p;
447
448         ast_mutex_lock(&osplock);
449         p = ospproviders;
450         while(p) {
451                 if (!strcasecmp(p->name, name)) {
452                         *provider = p;
453                         ast_debug(1, "OSP: find provider '%s'\n", name);
454                         res = 1;
455                         break;
456                 }
457                 p = p->next;
458         }
459         ast_mutex_unlock(&osplock);
460
461         return res;
462 }
463
464 /*!
465  * \brief Create OSP transaction handle
466  * \param provider OSP provider context name
467  * \param transaction OSP transaction handle, output
468  * \param sourcesize Size of source buffer, in/output
469  * \param source Source of provider, output
470  * \return 1 Success, 0 Failed, -1 Error
471  */
472 static int osp_create_transaction(
473         const char* provider,
474         int* transaction,
475         unsigned int sourcesize,
476         char* source)
477 {
478         int res = 0;
479         struct osp_provider* p;
480         int error;
481
482         ast_mutex_lock(&osplock);
483         p = ospproviders;
484         while(p) {
485                 if (!strcasecmp(p->name, provider)) {
486                         error = OSPPTransactionNew(p->handle, transaction);
487                         if (error == OSPC_ERR_NO_ERROR) {
488                                 ast_debug(1, "OSP: transaction '%d'\n", *transaction);
489                                 ast_copy_string(source, p->source, sourcesize);
490                                 ast_debug(1, "OSP: source '%s'\n", source);
491                                 res = 1;
492                         } else {
493                                 *transaction = OSP_INVALID_HANDLE;
494                                 ast_debug(1, "OSP: Unable to create transaction handle, error '%d'\n", error);
495                                 res = -1;
496                         }
497                         break;
498                 }
499                 p = p->next;
500         }
501         ast_mutex_unlock(&osplock);
502
503         return res;
504 }
505
506 /*!
507  * \brief Convert address to "[x.x.x.x]" or "host.domain" format
508  * \param src Source address string
509  * \param dst Destination address string
510  * \param buffersize Size of dst buffer
511  */
512 static void osp_convert_address(
513         const char* src,
514         char* dst,
515         int buffersize)
516 {
517         struct in_addr inp;
518
519         if (inet_aton(src, &inp) != 0) {
520                 snprintf(dst, buffersize, "[%s]", src);
521         } else {
522                 snprintf(dst, buffersize, "%s", src);
523         }
524 }
525
526 /*!
527  * \brief Validate OSP token of inbound call
528  * \param transaction OSP transaction handle
529  * \param source Source of inbound call
530  * \param destination Destination of inbound call
531  * \param calling Calling number
532  * \param called Called number
533  * \param token OSP token, may be empty
534  * \param timelimit Call duration limit, output
535  * \return 1 Success, 0 Failed, -1 Error
536  */
537 static int osp_validate_token(
538         int transaction,
539         const char* source,
540         const char* destination,
541         const char* calling,
542         const char* called,
543         const char* token,
544         unsigned int* timelimit)
545 {
546         int res;
547         int tokenlen;
548         unsigned char tokenstr[OSP_TOKSTR_SIZE];
549         char src[OSP_NORSTR_SIZE];
550         char dst[OSP_NORSTR_SIZE];
551         unsigned int authorised;
552         unsigned int dummy = 0;
553         int error;
554
555         tokenlen = ast_base64decode(tokenstr, token, strlen(token));
556         osp_convert_address(source, src, sizeof(src));
557         osp_convert_address(destination, dst, sizeof(dst));
558         error = OSPPTransactionValidateAuthorisation(
559                 transaction,
560                 src,
561                 dst,
562                 NULL,
563                 NULL,
564                 calling ? calling : "",
565                 OSPC_NFORMAT_E164,
566                 called,
567                 OSPC_NFORMAT_E164,
568                 0,
569                 NULL,
570                 tokenlen,
571                 (char*)tokenstr,
572                 &authorised,
573                 timelimit,
574                 &dummy,
575                 NULL,
576                 osp_tokenformat);
577         if (error != OSPC_ERR_NO_ERROR) {
578                 ast_debug(1, "OSP: Unable to validate inbound token, error '%d'\n", error);
579                 res = -1;
580         } else if (authorised) {
581                 ast_debug(1, "OSP: Authorised\n");
582                 res = 1;
583         } else {
584                 ast_debug(1, "OSP: Unauthorised\n");
585                 res = 0;
586         }
587
588         return res;
589 }
590
591 /*!
592  * \brief Choose min duration limit
593  * \param in Inbound duration limit
594  * \param out Outbound duration limit
595  * \return min duration limit
596  */
597 static unsigned int osp_choose_timelimit(
598         unsigned int in,
599         unsigned int out)
600 {
601         if (in == OSP_DEF_TIMELIMIT) {
602                 return out;
603         } else if (out == OSP_DEF_TIMELIMIT) {
604                 return in;
605         } else {
606                 return in < out ? in : out;
607         }
608 }
609
610 /*!
611  * \brief Choose min duration limit
612  * \param provider OSP provider
613  * \param called Called number
614  * \param calling Calling number
615  * \param destination Destination IP in '[x.x.x.x]' format
616  * \param tokenlen OSP token length
617  * \param token OSP token
618  * \param reason Failure reason, output
619  * \param result OSP lookup results, in/output
620  * \return 1 Success, 0 Failed, -1 Error
621  */
622 static int osp_check_destination(
623         struct osp_provider* provider,
624         const char* called,
625         const char* calling,
626         char* destination,
627         unsigned int tokenlen,
628         const char* token,
629         OSPEFAILREASON* reason,
630         struct osp_result* result)
631 {
632         int res;
633         OSPE_DEST_OSPENABLED enabled;
634         OSPE_DEST_PROTOCOL protocol;
635         int error;
636
637         if (strlen(destination) <= 2) {
638                 ast_debug(1, "OSP: Wrong destination format '%s'\n", destination);
639                 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
640                 return -1;
641         }
642
643         if ((error = OSPPTransactionIsDestOSPEnabled(result->outhandle, &enabled)) != OSPC_ERR_NO_ERROR) {
644                 ast_debug(1, "OSP: Unable to get destination OSP version, error '%d'\n", error);
645                 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
646                 return -1;
647         }
648
649         if (enabled == OSPC_DOSP_FALSE) {
650                 result->token[0] = '\0';
651         } else {
652                 ast_base64encode(result->token, (const unsigned char*)token, tokenlen, sizeof(result->token) - 1);
653         }
654
655         if ((error = OSPPTransactionGetDestNetworkId(result->outhandle, result->networkid)) != OSPC_ERR_NO_ERROR) {
656                 ast_debug(1, "OSP: Unable to get destination network ID, error '%d'\n", error);
657                 result->networkid[0] = '\0';
658         }
659
660         if ((error = OSPPTransactionGetDestProtocol(result->outhandle, &protocol)) != OSPC_ERR_NO_ERROR) {
661                 ast_debug(1, "OSP: Unable to get destination protocol, error '%d'\n", error);
662                 *reason = OSPC_FAIL_NORMAL_UNSPECIFIED;
663                 result->token[0] = '\0';
664                 result->networkid[0] = '\0';
665                 return -1;
666         }
667
668         res = 1;
669         /* Strip leading and trailing brackets */
670         destination[strlen(destination) - 1] = '\0';
671         switch(protocol) {
672         case OSPC_DPROT_Q931:
673                 ast_debug(1, "OSP: protocol '%s'\n", OSP_PROT_H323);
674                 ast_copy_string(result->tech, OSP_TECH_H323, sizeof(result->tech));
675                 ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
676                 ast_copy_string(result->called, called, sizeof(result->called));
677                 ast_copy_string(result->calling, calling, sizeof(result->calling));
678                 break;
679         case OSPC_DPROT_SIP:
680                 ast_debug(1, "OSP: protocol '%s'\n", OSP_PROT_SIP);
681                 ast_copy_string(result->tech, OSP_TECH_SIP, sizeof(result->tech));
682                 ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
683                 ast_copy_string(result->called, called, sizeof(result->called));
684                 ast_copy_string(result->calling, calling, sizeof(result->calling));
685                 break;
686         case OSPC_DPROT_IAX:
687                 ast_debug(1, "OSP: protocol '%s'\n", OSP_PROT_IAX);
688                 ast_copy_string(result->tech, OSP_TECH_IAX, sizeof(result->tech));
689                 ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
690                 ast_copy_string(result->called, called, sizeof(result->called));
691                 ast_copy_string(result->calling, calling, sizeof(result->calling));
692                 break;
693         case OSPC_DPROT_UNDEFINED:
694         case OSPC_DPROT_UNKNOWN:
695                 ast_debug(1, "OSP: unknown/undefined protocol '%d'\n", protocol);
696                 ast_debug(1, "OSP: use default protocol '%s'\n", provider->defaultprotocol);
697
698                 ast_copy_string(result->tech, provider->defaultprotocol, sizeof(result->tech));
699                 ast_copy_string(result->dest, destination + 1, sizeof(result->dest));
700                 ast_copy_string(result->called, called, sizeof(result->called));
701                 ast_copy_string(result->calling, calling, sizeof(result->calling));
702                 break;
703         case OSPC_DPROT_LRQ:
704         default:
705                 ast_log(LOG_WARNING, "OSP: unsupported protocol '%d'\n", protocol);
706                 *reason = OSPC_FAIL_PROTOCOL_ERROR;
707                 result->token[0] = '\0';
708                 result->networkid[0] = '\0';
709                 res = 0;
710                 break;
711         }
712
713         return res;
714 }
715
716 /*!
717  * \brief Convert Asterisk status to TC code
718  * \param cause Asterisk hangup cause
719  * \return OSP TC code
720  */
721 static OSPEFAILREASON asterisk2osp(
722         int cause)
723 {
724         return (OSPEFAILREASON)cause;
725 }
726
727 /*!
728  * \brief OSP Authentication function
729  * \param provider OSP provider context name
730  * \param transaction OSP transaction handle, output
731  * \param source Source of inbound call
732  * \param calling Calling number
733  * \param called Called number
734  * \param token OSP token, may be empty
735  * \param timelimit Call duration limit, output
736  * \return 1 Authenricated, 0 Unauthenticated, -1 Error
737  */
738 static int osp_auth(
739         const char* provider,
740         int* transaction,
741         const char* source,
742         const char* calling,
743         const char* called,
744         const char* token,
745         unsigned int* timelimit)
746 {
747         int res;
748         struct osp_provider* p = NULL;
749         char dest[OSP_NORSTR_SIZE];
750
751         *transaction = OSP_INVALID_HANDLE;
752         *timelimit = OSP_DEF_TIMELIMIT;
753
754         if ((res = osp_get_provider(provider, &p)) <= 0) {
755                 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", provider);
756                 return res;
757         }
758
759         switch (p->authpolicy) {
760         case OSP_AUTH_NO:
761                 res = 1;
762                 break;
763         case OSP_AUTH_EXCLUSIVE:
764                 if (ast_strlen_zero(token)) {
765                         res = 0;
766                 } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
767                         ast_debug(1, "OSP: Unable to generate transaction handle\n");
768                         *transaction = OSP_INVALID_HANDLE;
769                         res = 0;
770                 } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
771                         OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
772                 }
773                 break;
774         case OSP_AUTH_YES:
775         default:
776                 if (ast_strlen_zero(token)) {
777                         res = 1;
778                 } else if ((res = osp_create_transaction(provider, transaction, sizeof(dest), dest)) <= 0) {
779                         ast_debug(1, "OSP: Unable to generate transaction handle\n");
780                         *transaction = OSP_INVALID_HANDLE;
781                         res = 0;
782                 } else if((res = osp_validate_token(*transaction, source, dest, calling, called, token, timelimit)) <= 0) {
783                         OSPPTransactionRecordFailure(*transaction, OSPC_FAIL_CALL_REJECTED);
784                 }
785                 break;
786         }
787
788         return res;
789 }
790
791 /*!
792  * \brief Create a UUID
793  * \param uuid UUID buffer
794  * \param buffersize UUID buffer size
795  * \return 1 Created, -1 Error
796  */
797 static int osp_create_uuid(
798         unsigned char* uuid,
799         unsigned int* buffersize)
800 {
801         int i, res;
802         long int* tmp;
803
804         if (*buffersize >= OSP_UUID_SIZE) {
805                 tmp = (long int*)uuid;
806                 for (i = 0; i < OSP_UUID_SIZE / sizeof(long int); i++) {
807                         tmp[i] = ast_random();
808                 }
809                 *buffersize = OSP_UUID_SIZE;
810                 res = 1;
811         } else {
812                 res = -1;
813         }
814
815         return res;
816 }
817
818 /*!
819  * \brief UUID to string
820  * \param uuid UUID
821  * \param buffer String buffer
822  * \param buffersize String buffer size
823  * \return 1 Successed, -1 Error
824  */
825 static int osp_uuid2str(
826         unsigned char* uuid,
827         char* buffer,
828         unsigned int buffersize)
829 {
830         int res;
831
832         if (buffersize > OSP_UUIDSTR_SIZE) {
833                 snprintf(buffer, buffersize, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
834                         uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], uuid[7],
835                         uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]);
836                 res = 1;
837         } else {
838                 res = -1;
839         }
840
841         return res;
842 }
843
844 /*!
845  * \brief Create a call ID according to the type
846  * \param type Call ID type
847  * \param callid Call ID buffer
848  * \return 1 Created, 0 Not create, -1 Error
849  */
850 static int osp_create_callid(
851         unsigned int type,
852         struct osp_callid* callid)
853 {
854         int res;
855
856         callid->len = sizeof(callid->buf);
857         switch (type) {
858         case OSP_CALLID_H323:
859                 res = osp_create_uuid(callid->buf, &callid->len);
860                 break;
861         case OSP_CALLID_SIP:
862         case OSP_CALLID_IAX:
863                 res = 0;
864         default:
865                 res = -1;
866                 break;
867         }
868
869         if ((res != 1) && (callid->len != 0)) {
870                 callid->buf[0] = '\0';
871                 callid->len = 0;
872         }
873
874         return res;
875 }
876
877 /*!
878  * \brief OSP Lookup function
879  * \param provider OSP provider context name
880  * \param srcdev Source device of outbound call
881  * \param calling Calling number
882  * \param called Called number
883  * \param snetid Source network ID
884  * \param rnumber Routing number
885  * \param callidtypes Call ID types
886  * \param result Lookup results
887  * \return 1 Found , 0 No route, -1 Error
888  */
889 static int osp_lookup(
890         const char* provider,
891         const char* srcdev,
892         const char* calling,
893         const char* called,
894         const char* snetid,
895         const char* rnumber,
896         unsigned int callidtypes,
897         struct osp_result* result)
898 {
899         int res;
900         struct osp_provider* p = NULL;
901         char source[OSP_NORSTR_SIZE];
902         char callingnum[OSP_NORSTR_SIZE];
903         char callednum[OSP_NORSTR_SIZE];
904         char destination[OSP_NORSTR_SIZE];
905         unsigned int tokenlen;
906         char token[OSP_TOKSTR_SIZE];
907         char src[OSP_NORSTR_SIZE];
908         char dev[OSP_NORSTR_SIZE];
909         unsigned int i, type;
910         struct osp_callid callid;
911         unsigned int callidnum;
912         OSPT_CALL_ID* callids[OSP_CALLID_MAXNUM];
913         unsigned int dummy = 0;
914         OSPEFAILREASON reason;
915         int error;
916
917         result->outhandle = OSP_INVALID_HANDLE;
918         result->tech[0] = '\0';
919         result->dest[0] = '\0';
920         result->called[0] = '\0';
921         result->calling[0] = '\0';
922         result->token[0] = '\0';
923         result->networkid[0] = '\0';
924         result->numresults = 0;
925         result->outtimelimit = OSP_DEF_TIMELIMIT;
926
927         if ((res = osp_get_provider(provider, &p)) <= 0) {
928                 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", provider);
929                 return res;
930         }
931
932         if ((res = osp_create_transaction(provider, &result->outhandle, sizeof(source), source)) <= 0) {
933                 ast_debug(1, "OSP: Unable to generate transaction handle\n");
934                 result->outhandle = OSP_INVALID_HANDLE;
935                 if (result->inhandle != OSP_INVALID_HANDLE) {
936                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
937                 }
938                 return -1;
939         }
940
941         if (!ast_strlen_zero(snetid)) {
942                 OSPPTransactionSetNetworkIds(result->outhandle, snetid, "");
943         }
944
945         if (!ast_strlen_zero(rnumber)) {
946                 OSPPTransactionSetRoutingNumber(result->outhandle, rnumber);
947         }
948
949         callidnum = 0;
950         callids[0] = NULL;
951         for (i = 0; i < OSP_CALLID_MAXNUM; i++) {
952                 type = 1 << i;
953                 if (callidtypes & type) {
954                         error = osp_create_callid(type, &callid);
955                         if (error == 1) {
956                                 callids[callidnum] = OSPPCallIdNew(callid.len, callid.buf);
957                                 callidnum++;
958                         }
959                 }
960         }
961
962         osp_convert_address(source, src, sizeof(src));
963         osp_convert_address(srcdev, dev, sizeof(dev));
964         result->numresults = OSP_DEF_DESTINATIONS;
965         error = OSPPTransactionRequestAuthorisation(
966                 result->outhandle,
967                 src,
968                 dev,
969                 calling ? calling : "",
970                 OSPC_NFORMAT_E164,
971                 called,
972                 OSPC_NFORMAT_E164,
973                 NULL,
974                 callidnum,
975                 callids,
976                 NULL,
977                 &result->numresults,
978                 &dummy,
979                 NULL);
980
981         for (i = 0; i < callidnum; i++) {
982                 OSPPCallIdDelete(&callids[i]);
983         }
984
985         if (error != OSPC_ERR_NO_ERROR) {
986                 ast_debug(1, "OSP: Unable to request authorization, error '%d'\n", error);
987                 result->numresults = 0;
988                 if (result->inhandle != OSP_INVALID_HANDLE) {
989                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
990                 }
991                 return -1;
992         }
993
994         if (!result->numresults) {
995                 ast_debug(1, "OSP: No more destination\n");
996                 if (result->inhandle != OSP_INVALID_HANDLE) {
997                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
998                 }
999                 return 0;
1000         }
1001
1002         result->outcallid.len = sizeof(result->outcallid.buf);
1003         tokenlen = sizeof(token);
1004         error = OSPPTransactionGetFirstDestination(
1005                 result->outhandle,
1006                 0,
1007                 NULL,
1008                 NULL,
1009                 &result->outtimelimit,
1010                 &result->outcallid.len,
1011                 result->outcallid.buf,
1012                 sizeof(callednum),
1013                 callednum,
1014                 sizeof(callingnum),
1015                 callingnum,
1016                 sizeof(destination),
1017                 destination,
1018                 0,
1019                 NULL,
1020                 &tokenlen,
1021                 token);
1022         if (error != OSPC_ERR_NO_ERROR) {
1023                 ast_debug(1, "OSP: Unable to get first route, error '%d'\n", error);
1024                 result->numresults = 0;
1025                 result->outtimelimit = OSP_DEF_TIMELIMIT;
1026                 if (result->inhandle != OSP_INVALID_HANDLE) {
1027                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1028                 }
1029                 return -1;
1030         }
1031
1032         result->numresults--;
1033         result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
1034         ast_debug(1, "OSP: outtimelimit '%d'\n", result->outtimelimit);
1035         ast_debug(1, "OSP: called '%s'\n", callednum);
1036         ast_debug(1, "OSP: calling '%s'\n", callingnum);
1037         ast_debug(1, "OSP: destination '%s'\n", destination);
1038         ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1039
1040         if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
1041                 return 1;
1042         }
1043
1044         if (!result->numresults) {
1045                 ast_debug(1, "OSP: No more destination\n");
1046                 result->outtimelimit = OSP_DEF_TIMELIMIT;
1047                 OSPPTransactionRecordFailure(result->outhandle, reason);
1048                 if (result->inhandle != OSP_INVALID_HANDLE) {
1049                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1050                 }
1051                 return 0;
1052         }
1053
1054         while(result->numresults) {
1055                 result->outcallid.len = sizeof(result->outcallid.buf);
1056                 tokenlen = sizeof(token);
1057                 error = OSPPTransactionGetNextDestination(
1058                         result->outhandle,
1059                         reason,
1060                         0,
1061                         NULL,
1062                         NULL,
1063                         &result->outtimelimit,
1064                         &result->outcallid.len,
1065                         result->outcallid.buf,
1066                         sizeof(callednum),
1067                         callednum,
1068                         sizeof(callingnum),
1069                         callingnum,
1070                         sizeof(destination),
1071                         destination,
1072                         0,
1073                         NULL,
1074                         &tokenlen,
1075                         token);
1076                 if (error == OSPC_ERR_NO_ERROR) {
1077                         result->numresults--;
1078                         result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
1079                         ast_debug(1, "OSP: outtimelimit '%d'\n", result->outtimelimit);
1080                         ast_debug(1, "OSP: called '%s'\n", callednum);
1081                         ast_debug(1, "OSP: calling '%s'\n", callingnum);
1082                         ast_debug(1, "OSP: destination '%s'\n", destination);
1083                         ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1084
1085                         if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
1086                                 break;
1087                         } else if (!result->numresults) {
1088                                 ast_debug(1, "OSP: No more destination\n");
1089                                 OSPPTransactionRecordFailure(result->outhandle, reason);
1090                                 if (result->inhandle != OSP_INVALID_HANDLE) {
1091                                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1092                                 }
1093                                 res = 0;
1094                                 break;
1095                         }
1096                 } else {
1097                         ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
1098                         result->numresults = 0;
1099                         result->outtimelimit = OSP_DEF_TIMELIMIT;
1100                         if (result->inhandle != OSP_INVALID_HANDLE) {
1101                                 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1102                         }
1103                         res = -1;
1104                         break;
1105                 }
1106         }
1107         return res;
1108 }
1109
1110 /*!
1111  * \brief OSP Lookup Next function
1112  * \param provider OSP provider name
1113  * \param cause Asterisk hangup cuase
1114  * \param result Lookup results, in/output
1115  * \return 1 Found , 0 No route, -1 Error
1116  */
1117 static int osp_next(
1118         const char* provider,
1119         int cause,
1120         struct osp_result* result)
1121 {
1122         int res;
1123         struct osp_provider* p = NULL;
1124         char callingnum[OSP_NORSTR_SIZE];
1125         char callednum[OSP_NORSTR_SIZE];
1126         char destination[OSP_NORSTR_SIZE];
1127         unsigned int tokenlen;
1128         char token[OSP_TOKSTR_SIZE];
1129         OSPEFAILREASON reason;
1130         int error;
1131
1132         result->tech[0] = '\0';
1133         result->dest[0] = '\0';
1134         result->called[0] = '\0';
1135         result->calling[0] = '\0';
1136         result->token[0] = '\0';
1137         result->networkid[0] = '\0';
1138         result->outtimelimit = OSP_DEF_TIMELIMIT;
1139
1140         if ((res = osp_get_provider(provider, &p)) <= 0) {
1141                 ast_debug(1, "OSP: Unabe to find OSP provider '%s'\n", provider);
1142                 return res;
1143         }
1144
1145         if (result->outhandle == OSP_INVALID_HANDLE) {
1146                 ast_debug(1, "OSP: Transaction handle undefined\n");
1147                 result->numresults = 0;
1148                 if (result->inhandle != OSP_INVALID_HANDLE) {
1149                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1150                 }
1151                 return -1;
1152         }
1153
1154         reason = asterisk2osp(cause);
1155
1156         if (!result->numresults) {
1157                 ast_debug(1, "OSP: No more destination\n");
1158                 OSPPTransactionRecordFailure(result->outhandle, reason);
1159                 if (result->inhandle != OSP_INVALID_HANDLE) {
1160                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1161                 }
1162                 return 0;
1163         }
1164
1165         while(result->numresults) {
1166                 result->outcallid.len = sizeof(result->outcallid.buf);
1167                 tokenlen = sizeof(token);
1168                 error = OSPPTransactionGetNextDestination(
1169                         result->outhandle,
1170                         reason,
1171                         0,
1172                         NULL,
1173                         NULL,
1174                         &result->outtimelimit,
1175                         &result->outcallid.len,
1176                         result->outcallid.buf,
1177                         sizeof(callednum),
1178                         callednum,
1179                         sizeof(callingnum),
1180                         callingnum,
1181                         sizeof(destination),
1182                         destination,
1183                         0,
1184                         NULL,
1185                         &tokenlen,
1186                         token);
1187                 if (error == OSPC_ERR_NO_ERROR) {
1188                         result->numresults--;
1189                         result->outtimelimit = osp_choose_timelimit(result->intimelimit, result->outtimelimit);
1190                         ast_debug(1, "OSP: outtimelimit '%d'\n", result->outtimelimit);
1191                         ast_debug(1, "OSP: called '%s'\n", callednum);
1192                         ast_debug(1, "OSP: calling '%s'\n", callingnum);
1193                         ast_debug(1, "OSP: destination '%s'\n", destination);
1194                         ast_debug(1, "OSP: token size '%d'\n", tokenlen);
1195
1196                         if ((res = osp_check_destination(p, callednum, callingnum, destination, tokenlen, token, &reason, result)) > 0) {
1197                                 res = 1;
1198                                 break;
1199                         } else if (!result->numresults) {
1200                                 ast_debug(1, "OSP: No more destination\n");
1201                                 OSPPTransactionRecordFailure(result->outhandle, reason);
1202                                 if (result->inhandle != OSP_INVALID_HANDLE) {
1203                                         OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NO_ROUTE_TO_DEST);
1204                                 }
1205                                 res = 0;
1206                                 break;
1207                         }
1208                 } else {
1209                         ast_debug(1, "OSP: Unable to get route, error '%d'\n", error);
1210                         result->token[0] = '\0';
1211                         result->numresults = 0;
1212                         result->outtimelimit = OSP_DEF_TIMELIMIT;
1213                         if (result->inhandle != OSP_INVALID_HANDLE) {
1214                                 OSPPTransactionRecordFailure(result->inhandle, OSPC_FAIL_NORMAL_UNSPECIFIED);
1215                         }
1216                         res = -1;
1217                         break;
1218                 }
1219         }
1220
1221         return res;
1222 }
1223
1224 /*!
1225  * \brief OSP Finish function
1226  * \param handle OSP in/outbound transaction handle
1227  * \param recorded If failure reason has been recorded
1228  * \param cause Asterisk hangup cause
1229  * \param start Call start time
1230  * \param connect Call connect time
1231  * \param end Call end time
1232  * \param release Who release first, 0 source, 1 destination
1233  * \return 1 Success, 0 Failed, -1 Error
1234  */
1235 static int osp_finish(
1236         int handle,
1237         int recorded,
1238         int cause,
1239         time_t start,
1240         time_t connect,
1241         time_t end,
1242         unsigned int release)
1243 {
1244         int res;
1245         OSPEFAILREASON reason;
1246         time_t alert = 0;
1247         unsigned isPddInfoPresent = 0;
1248         unsigned pdd = 0;
1249         unsigned int dummy = 0;
1250         int error;
1251
1252         if (handle == OSP_INVALID_HANDLE) {
1253                 return 0;
1254         }
1255
1256         if (!recorded) {
1257                 reason = asterisk2osp(cause);
1258                 OSPPTransactionRecordFailure(handle, reason);
1259         }
1260
1261         error = OSPPTransactionReportUsage(
1262                 handle,
1263                 difftime(end, connect),
1264                 start,
1265                 end,
1266                 alert,
1267                 connect,
1268                 isPddInfoPresent,
1269                 pdd,
1270                 release,
1271                 NULL,
1272                 -1,
1273                 -1,
1274                 -1,
1275                 -1,
1276                 &dummy,
1277                 NULL);
1278         if (error == OSPC_ERR_NO_ERROR) {
1279                 ast_debug(1, "OSP: Usage reported\n");
1280                 res = 1;
1281         } else {
1282                 ast_debug(1, "OSP: Unable to report usage, error '%d'\n", error);
1283                 res = -1;
1284         }
1285         OSPPTransactionDelete(handle);
1286
1287         return res;
1288 }
1289
1290 /* OSP Application APIs */
1291
1292 /*!
1293  * \brief OSP Application OSPAuth
1294  * \param chan Channel
1295  * \param data Parameter
1296  * \return 0 Success, -1 Failed
1297  */
1298 static int ospauth_exec(
1299         struct ast_channel *chan,
1300         const char *data)
1301 {
1302         int res;
1303         const char* provider = OSP_DEF_PROVIDER;
1304         struct varshead* headp;
1305         struct ast_var_t* current;
1306         const char* source = "";
1307         const char* token = "";
1308         int handle;
1309         unsigned int timelimit;
1310         char buffer[OSP_INTSTR_SIZE];
1311         const char* status;
1312         char* tmp;
1313
1314         AST_DECLARE_APP_ARGS(args,
1315                 AST_APP_ARG(provider);
1316                 AST_APP_ARG(options);
1317         );
1318
1319         if (!(tmp = ast_strdupa(data))) {
1320                 ast_log(LOG_ERROR, "Out of memory\n");
1321                 return -1;
1322         }
1323
1324         AST_STANDARD_APP_ARGS(args, tmp);
1325
1326         if (!ast_strlen_zero(args.provider)) {
1327                 provider = args.provider;
1328         }
1329         ast_debug(1, "OSPAuth: provider '%s'\n", provider);
1330
1331         headp = &chan->varshead;
1332         AST_LIST_TRAVERSE(headp, current, entries) {
1333                 if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
1334                         source = ast_var_value(current);
1335                 } else if (!strcasecmp(ast_var_name(current), "OSPINTOKEN")) {
1336                         token = ast_var_value(current);
1337                 }
1338         }
1339
1340         ast_debug(1, "OSPAuth: source '%s'\n", source);
1341         ast_debug(1, "OSPAuth: token size '%zd'\n", strlen(token));
1342
1343         if ((res = osp_auth(provider, &handle, source, chan->cid.cid_num, chan->exten, token, &timelimit)) > 0) {
1344                 status = AST_OSP_SUCCESS;
1345         } else {
1346                 timelimit = OSP_DEF_TIMELIMIT;
1347                 if (!res) {
1348                         status = AST_OSP_FAILED;
1349                 } else {
1350                         status = AST_OSP_ERROR;
1351                 }
1352         }
1353
1354         snprintf(buffer, sizeof(buffer), "%d", handle);
1355         pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
1356         ast_debug(1, "OSPAuth: OSPINHANDLE '%s'\n", buffer);
1357         snprintf(buffer, sizeof(buffer), "%d", timelimit);
1358         pbx_builtin_setvar_helper(chan, "OSPINTIMELIMIT", buffer);
1359         ast_debug(1, "OSPAuth: OSPINTIMELIMIT '%s'\n", buffer);
1360         pbx_builtin_setvar_helper(chan, "OSPAUTHSTATUS", status);
1361         ast_debug(1, "OSPAuth: %s\n", status);
1362
1363         if(res <= 0) {
1364                 res = -1;
1365         } else {
1366                 res = 0;
1367         }
1368
1369         return res;
1370 }
1371
1372 /*!
1373  * \brief OSP Application OSPLookup
1374  * \param chan Channel
1375  * \param data Parameter
1376  * \return 0 Success, -1 Failed
1377  */
1378 static int osplookup_exec(
1379         struct ast_channel* chan,
1380         const void* data)
1381 {
1382         int res, cres;
1383         const char* provider = OSP_DEF_PROVIDER;
1384         struct varshead* headp;
1385         struct ast_var_t* current;
1386         const char* srcdev = "";
1387         const char* snetid = "";
1388         const char* rnumber = "";
1389         char buffer[OSP_TOKSTR_SIZE];
1390         unsigned int callidtypes = OSP_CALLID_UNDEFINED;
1391         struct osp_result result;
1392         const char* status;
1393         char* tmp;
1394
1395         AST_DECLARE_APP_ARGS(args,
1396                 AST_APP_ARG(exten);
1397                 AST_APP_ARG(provider);
1398                 AST_APP_ARG(options);
1399         );
1400
1401         if (ast_strlen_zero(data)) {
1402                 ast_log(LOG_WARNING, "OSPLookup: Arg required, OSPLookup(exten[|provider[|options]])\n");
1403                 return -1;
1404         }
1405
1406         if (!(tmp = ast_strdupa(data))) {
1407                 ast_log(LOG_ERROR, "Out of memory\n");
1408                 return -1;
1409         }
1410
1411         AST_STANDARD_APP_ARGS(args, tmp);
1412
1413         ast_debug(1, "OSPLookup: exten '%s'\n", args.exten);
1414
1415         if (!ast_strlen_zero(args.provider)) {
1416                 provider = args.provider;
1417         }
1418         ast_debug(1, "OSPlookup: provider '%s'\n", provider);
1419
1420         if (args.options) {
1421                 if (strchr(args.options, 'h')) {
1422                         callidtypes |= OSP_CALLID_H323;
1423                 }
1424                 if (strchr(args.options, 's')) {
1425                         callidtypes |= OSP_CALLID_SIP;
1426                 }
1427                 if (strchr(args.options, 'i')) {
1428                         callidtypes |= OSP_CALLID_IAX;
1429                 }
1430         }
1431         ast_debug(1, "OSPLookup: call id types '%d'\n", callidtypes);
1432
1433         result.inhandle = OSP_INVALID_HANDLE;
1434         result.intimelimit = OSP_DEF_TIMELIMIT;
1435
1436         headp = &chan->varshead;
1437         AST_LIST_TRAVERSE(headp, current, entries) {
1438                 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
1439                         if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
1440                                 result.inhandle = OSP_INVALID_HANDLE;
1441                         }
1442                 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
1443                         if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
1444                                 result.intimelimit = OSP_DEF_TIMELIMIT;
1445                         }
1446                 } else if (!strcasecmp(ast_var_name(current), "OSPINNETWORKID")) {
1447                         snetid = ast_var_value(current);
1448                 } else if (!strcasecmp(ast_var_name(current), "OSPROUTINGNUMBER")) {
1449                         rnumber = ast_var_value(current);
1450                 } else if (!strcasecmp(ast_var_name(current), "OSPPEERIP")) {
1451                         srcdev = ast_var_value(current);
1452                 }
1453         }
1454         ast_debug(1, "OSPLookup: OSPINHANDLE '%d'\n", result.inhandle);
1455         ast_debug(1, "OSPLookup: OSPINTIMELIMIT '%d'\n", result.intimelimit);
1456         ast_debug(1, "OSPLookup: OSPINNETWORKID '%s'\n", snetid);
1457         ast_debug(1, "OSPLookup: OSPROUTINGNUMBER '%s'\n", rnumber);
1458         ast_debug(1, "OSPLookup: source device '%s'\n", srcdev);
1459
1460         if ((cres = ast_autoservice_start(chan)) < 0) {
1461                 return -1;
1462         }
1463
1464         if ((res = osp_lookup(provider, srcdev, chan->cid.cid_num, args.exten, snetid, rnumber, callidtypes, &result)) > 0) {
1465                 status = AST_OSP_SUCCESS;
1466         } else {
1467                 result.tech[0] = '\0';
1468                 result.dest[0] = '\0';
1469                 result.called[0] = '\0';
1470                 result.calling[0] = '\0';
1471                 result.token[0] = '\0';
1472                 result.networkid[0] = '\0';
1473                 result.numresults = 0;
1474                 result.outtimelimit = OSP_DEF_TIMELIMIT;
1475                 result.outcallid.buf[0] = '\0';
1476                 result.outcallid.len = 0;
1477                 if (!res) {
1478                         status = AST_OSP_FAILED;
1479                 } else {
1480                         status = AST_OSP_ERROR;
1481                 }
1482         }
1483
1484         snprintf(buffer, sizeof(buffer), "%d", result.outhandle);
1485         pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
1486         ast_debug(1, "OSPLookup: OSPOUTHANDLE '%s'\n", buffer);
1487         pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
1488         ast_debug(1, "OSPLookup: OSPTECH '%s'\n", result.tech);
1489         pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
1490         ast_debug(1, "OSPLookup: OSPDEST '%s'\n", result.dest);
1491         pbx_builtin_setvar_helper(chan, "OSPCALLED", result.called);
1492         ast_debug(1, "OSPLookup: OSPCALLED '%s'\n", result.called);
1493         pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
1494         ast_debug(1, "OSPLookup: OSPCALLING '%s'\n", result.calling);
1495         pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", result.networkid);
1496         ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", result.networkid);
1497         pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
1498         ast_debug(1, "OSPLookup: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
1499         snprintf(buffer, sizeof(buffer), "%d", result.numresults);
1500         pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
1501         ast_debug(1, "OSPLookup: OSPRESULTS '%s'\n", buffer);
1502         snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
1503         pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
1504         ast_debug(1, "OSPLookup: OSPOUTTIMELIMIT '%s'\n", buffer);
1505         snprintf(buffer, sizeof(buffer), "%d", callidtypes);
1506         pbx_builtin_setvar_helper(chan, "OSPOUTCALLIDTYPES", buffer);
1507         ast_debug(1, "OSPLookup: OSPOUTCALLIDTYPES '%s'\n", buffer);
1508         pbx_builtin_setvar_helper(chan, "OSPLOOKUPSTATUS", status);
1509         ast_debug(1, "OSPLookup: %s\n", status);
1510
1511         if (!strcasecmp(result.tech, OSP_TECH_H323)) {
1512                 if ((callidtypes & OSP_CALLID_H323) && (result.outcallid.len != 0)) {
1513                         osp_uuid2str(result.outcallid.buf, buffer, sizeof(buffer));
1514                 } else {
1515                         buffer[0] = '\0';
1516                 }
1517                 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
1518                 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
1519                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1520         } else if (!strcasecmp(result.tech, OSP_TECH_SIP)) {
1521                 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
1522                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1523                 if (!ast_strlen_zero(result.token)) {
1524                         snprintf(buffer, sizeof(buffer), "%s%s", OSP_SIP_HEADER, result.token);
1525                         pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
1526                         ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
1527                 }
1528         } else if (!strcasecmp(result.tech, OSP_TECH_IAX)) {
1529                 snprintf(buffer, sizeof(buffer), "%s/%s/%s", result.tech, result.dest, result.called);
1530                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1531         }
1532
1533         if ((cres = ast_autoservice_stop(chan)) < 0) {
1534                 return -1;
1535         }
1536
1537         if(res <= 0) {
1538                 res = -1;
1539         } else {
1540                 res = 0;
1541         }
1542
1543         return res;
1544 }
1545
1546 /*!
1547  * \brief OSP Application OSPNext
1548  * \param chan Channel
1549  * \param data Parameter
1550  * \return 0 Success, -1 Failed
1551  */
1552 static int ospnext_exec(
1553         struct ast_channel* chan,
1554         const void* data)
1555 {
1556         int res;
1557         const char* provider = OSP_DEF_PROVIDER;
1558         int cause = 0;
1559         struct varshead* headp;
1560         struct ast_var_t* current;
1561         struct osp_result result;
1562         char buffer[OSP_TOKSTR_SIZE];
1563         unsigned int callidtypes = OSP_CALLID_UNDEFINED;
1564         const char* status;
1565         char* tmp;
1566
1567         AST_DECLARE_APP_ARGS(args,
1568                 AST_APP_ARG(cause);
1569                 AST_APP_ARG(provider);
1570                 AST_APP_ARG(options);
1571         );
1572
1573         if (ast_strlen_zero(data)) {
1574                 ast_log(LOG_WARNING, "OSPNext: Arg required, OSPNext(cause[|provider[|options]])\n");
1575                 return -1;
1576         }
1577
1578         if (!(tmp = ast_strdupa(data))) {
1579                 ast_log(LOG_ERROR, "Out of memory\n");
1580                 return -1;
1581         }
1582
1583         AST_STANDARD_APP_ARGS(args, tmp);
1584
1585         if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%d", &cause) != 1) {
1586                 cause = 0;
1587         }
1588         ast_debug(1, "OSPNext: cause '%d'\n", cause);
1589
1590         if (!ast_strlen_zero(args.provider)) {
1591                 provider = args.provider;
1592         }
1593         ast_debug(1, "OSPlookup: provider '%s'\n", provider);
1594
1595         result.inhandle = OSP_INVALID_HANDLE;
1596         result.outhandle = OSP_INVALID_HANDLE;
1597         result.intimelimit = OSP_DEF_TIMELIMIT;
1598         result.numresults = 0;
1599
1600         headp = &chan->varshead;
1601         AST_LIST_TRAVERSE(headp, current, entries) {
1602                 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
1603                         if (sscanf(ast_var_value(current), "%d", &result.inhandle) != 1) {
1604                                 result.inhandle = OSP_INVALID_HANDLE;
1605                         }
1606                 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
1607                         if (sscanf(ast_var_value(current), "%d", &result.outhandle) != 1) {
1608                                 result.outhandle = OSP_INVALID_HANDLE;
1609                         }
1610                 } else if (!strcasecmp(ast_var_name(current), "OSPINTIMELIMIT")) {
1611                         if (sscanf(ast_var_value(current), "%d", &result.intimelimit) != 1) {
1612                                 result.intimelimit = OSP_DEF_TIMELIMIT;
1613                         }
1614                 } else if (!strcasecmp(ast_var_name(current), "OSPOUTCALLIDTYPES")) {
1615                         if (sscanf(ast_var_value(current), "%d", &callidtypes) != 1) {
1616                                 callidtypes = OSP_CALLID_UNDEFINED;
1617                         }
1618                 } else if (!strcasecmp(ast_var_name(current), "OSPRESULTS")) {
1619                         if (sscanf(ast_var_value(current), "%d", &result.numresults) != 1) {
1620                                 result.numresults = 0;
1621                         }
1622                 }
1623         }
1624         ast_debug(1, "OSPNext: OSPINHANDLE '%d'\n", result.inhandle);
1625         ast_debug(1, "OSPNext: OSPOUTHANDLE '%d'\n", result.outhandle);
1626         ast_debug(1, "OSPNext: OSPINTIMELIMIT '%d'\n", result.intimelimit);
1627         ast_debug(1, "OSPNext: OSPOUTCALLIDTYPES '%d'\n", callidtypes);
1628         ast_debug(1, "OSPNext: OSPRESULTS '%d'\n", result.numresults);
1629
1630         if ((res = osp_next(provider, cause, &result)) > 0) {
1631                 status = AST_OSP_SUCCESS;
1632         } else {
1633                 result.tech[0] = '\0';
1634                 result.dest[0] = '\0';
1635                 result.called[0] = '\0';
1636                 result.calling[0] = '\0';
1637                 result.token[0] = '\0';
1638                 result.networkid[0] = '\0';
1639                 result.numresults = 0;
1640                 result.outtimelimit = OSP_DEF_TIMELIMIT;
1641                 result.outcallid.buf[0] = '\0';
1642                 result.outcallid.len = 0;
1643                 if (!res) {
1644                         status = AST_OSP_FAILED;
1645                 } else {
1646                         status = AST_OSP_ERROR;
1647                 }
1648         }
1649
1650         pbx_builtin_setvar_helper(chan, "OSPTECH", result.tech);
1651         ast_debug(1, "OSPNext: OSPTECH '%s'\n", result.tech);
1652         pbx_builtin_setvar_helper(chan, "OSPDEST", result.dest);
1653         ast_debug(1, "OSPNext: OSPDEST '%s'\n", result.dest);
1654         pbx_builtin_setvar_helper(chan, "OSPCALLED", result.called);
1655         ast_debug(1, "OSPNext: OSPCALLED'%s'\n", result.called);
1656         pbx_builtin_setvar_helper(chan, "OSPCALLING", result.calling);
1657         ast_debug(1, "OSPNext: OSPCALLING '%s'\n", result.calling);
1658         pbx_builtin_setvar_helper(chan, "OSPOUTNETWORKID", result.networkid);
1659         ast_debug(1, "OSPLookup: OSPOUTNETWORKID '%s'\n", result.networkid);
1660         pbx_builtin_setvar_helper(chan, "OSPOUTTOKEN", result.token);
1661         ast_debug(1, "OSPNext: OSPOUTTOKEN size '%zd'\n", strlen(result.token));
1662         snprintf(buffer, sizeof(buffer), "%d", result.numresults);
1663         pbx_builtin_setvar_helper(chan, "OSPRESULTS", buffer);
1664         ast_debug(1, "OSPNext: OSPRESULTS '%s'\n", buffer);
1665         snprintf(buffer, sizeof(buffer), "%d", result.outtimelimit);
1666         pbx_builtin_setvar_helper(chan, "OSPOUTTIMELIMIT", buffer);
1667         ast_debug(1, "OSPNext: OSPOUTTIMELIMIT '%s'\n", buffer);
1668         pbx_builtin_setvar_helper(chan, "OSPNEXTSTATUS", status);
1669         ast_debug(1, "OSPNext: %s\n", status);
1670
1671         if (!strcasecmp(result.tech, OSP_TECH_H323)) {
1672                 if ((callidtypes & OSP_CALLID_H323) && (result.outcallid.len != 0)) {
1673                         osp_uuid2str(result.outcallid.buf, buffer, sizeof(buffer));
1674                 } else {
1675                         buffer[0] = '\0';
1676                 }
1677                 pbx_builtin_setvar_helper(chan, "OSPOUTCALLID", buffer);
1678                 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
1679                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1680         } else if (!strcasecmp(result.tech, OSP_TECH_SIP)) {
1681                 snprintf(buffer, sizeof(buffer), "%s/%s@%s", result.tech, result.called, result.dest);
1682                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1683                 if (!ast_strlen_zero(result.token)) {
1684                         snprintf(buffer, sizeof(buffer), "%s%s", OSP_SIP_HEADER, result.token);
1685                         pbx_builtin_setvar_helper(chan, "_SIPADDHEADER", buffer);
1686                         ast_debug(1, "OSPLookup: SIPADDHEADER size '%zd'\n", strlen(buffer));
1687                 }
1688         } else if (!strcasecmp(result.tech, OSP_TECH_IAX)) {
1689                 snprintf(buffer, sizeof(buffer), "%s/%s/%s", result.tech, result.dest, result.called);
1690                 pbx_builtin_setvar_helper(chan, "OSPDIALSTR", buffer);
1691         }
1692
1693         if(res <= 0) {
1694                 res = -1;
1695         } else {
1696                 res = 0;
1697         }
1698
1699         return res;
1700 }
1701
1702 /*!
1703  * \brief OSP Application OSPFinish
1704  * \param chan Channel
1705  * \param data Parameter
1706  * \return 0 Success, -1 Failed
1707  */
1708 static int ospfinished_exec(
1709         struct ast_channel* chan,
1710         const void* data)
1711 {
1712         int res = 1;
1713         int cause = 0;
1714         struct varshead* headp;
1715         struct ast_var_t* current;
1716         int inhandle = OSP_INVALID_HANDLE;
1717         int outhandle = OSP_INVALID_HANDLE;
1718         int recorded = 0;
1719         time_t start, connect, end;
1720         unsigned int release;
1721         char buffer[OSP_INTSTR_SIZE];
1722         const char* status;
1723         char* tmp;
1724
1725         AST_DECLARE_APP_ARGS(args,
1726                 AST_APP_ARG(cause);
1727                 AST_APP_ARG(options);
1728         );
1729
1730         if (!(tmp = ast_strdupa(data))) {
1731                 ast_log(LOG_ERROR, "Out of memory\n");
1732                 return -1;
1733         }
1734
1735         AST_STANDARD_APP_ARGS(args, tmp);
1736
1737         headp = &chan->varshead;
1738         AST_LIST_TRAVERSE(headp, current, entries) {
1739                 if (!strcasecmp(ast_var_name(current), "OSPINHANDLE")) {
1740                         if (sscanf(ast_var_value(current), "%d", &inhandle) != 1) {
1741                                 inhandle = OSP_INVALID_HANDLE;
1742                         }
1743                 } else if (!strcasecmp(ast_var_name(current), "OSPOUTHANDLE")) {
1744                         if (sscanf(ast_var_value(current), "%d", &outhandle) != 1) {
1745                                 outhandle = OSP_INVALID_HANDLE;
1746                         }
1747                 } else if (!recorded &&
1748                         (!strcasecmp(ast_var_name(current), "OSPAUTHSTATUS") ||
1749                         !strcasecmp(ast_var_name(current), "OSPLOOKUPSTATUS") ||
1750                         !strcasecmp(ast_var_name(current), "OSPNEXTSTATUS")))
1751                 {
1752                         if (strcasecmp(ast_var_value(current), AST_OSP_SUCCESS)) {
1753                                 recorded = 1;
1754                         }
1755                 }
1756         }
1757         ast_debug(1, "OSPFinish: OSPINHANDLE '%d'\n", inhandle);
1758         ast_debug(1, "OSPFinish: OSPOUTHANDLE '%d'\n", outhandle);
1759         ast_debug(1, "OSPFinish: recorded '%d'\n", recorded);
1760
1761         if (!ast_strlen_zero(args.cause) && sscanf(args.cause, "%d", &cause) != 1) {
1762                 cause = 0;
1763         }
1764         ast_debug(1, "OSPFinish: cause '%d'\n", cause);
1765
1766         if (chan->cdr) {
1767                 start = chan->cdr->start.tv_sec;
1768                 connect = chan->cdr->answer.tv_sec;
1769                 if (connect) {
1770                         end = time(NULL);
1771                 } else {
1772                         end = connect;
1773                 }
1774         } else {
1775                 start = 0;
1776                 connect = 0;
1777                 end = 0;
1778         }
1779         ast_debug(1, "OSPFinish: start '%ld'\n", start);
1780         ast_debug(1, "OSPFinish: connect '%ld'\n", connect);
1781         ast_debug(1, "OSPFinish: end '%ld'\n", end);
1782
1783         release = ast_check_hangup(chan) ? 0 : 1;
1784
1785         if (osp_finish(outhandle, recorded, cause, start, connect, end, release) <= 0) {
1786                 ast_debug(1, "OSPFinish: Unable to report usage for outbound call\n");
1787         }
1788         switch (cause) {
1789         case AST_CAUSE_NORMAL_CLEARING:
1790                 break;
1791         default:
1792                 cause = AST_CAUSE_NO_ROUTE_DESTINATION;
1793                 break;
1794         }
1795         if (osp_finish(inhandle, recorded, cause, start, connect, end, release) <= 0) {
1796                 ast_debug(1, "OSPFinish: Unable to report usage for inbound call\n");
1797         }
1798         snprintf(buffer, sizeof(buffer), "%d", OSP_INVALID_HANDLE);
1799         pbx_builtin_setvar_helper(chan, "OSPOUTHANDLE", buffer);
1800         pbx_builtin_setvar_helper(chan, "OSPINHANDLE", buffer);
1801
1802         if (res > 0) {
1803                 status = AST_OSP_SUCCESS;
1804         } else if (!res) {
1805                 status = AST_OSP_FAILED;
1806         } else {
1807                 status = AST_OSP_ERROR;
1808         }
1809         pbx_builtin_setvar_helper(chan, "OSPFINISHSTATUS", status);
1810
1811         if(!res) {
1812                 res = -1;
1813         } else {
1814                 res = 0;
1815         }
1816
1817         return res;
1818 }
1819
1820 /* OSP Module APIs */
1821
1822 static int osp_unload(void);
1823 static int osp_load(int reload)
1824 {
1825         const char* t;
1826         unsigned int v;
1827         struct ast_config* cfg;
1828         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1829         int error = OSPC_ERR_NO_ERROR;
1830
1831         if ((cfg = ast_config_load(OSP_CONFIG_FILE, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
1832                 return 0;
1833         } else if (cfg == CONFIG_STATUS_FILEINVALID) {
1834                 ast_log(LOG_ERROR, "Config file %s is in an invalid format.  Aborting.\n", OSP_CONFIG_FILE);
1835                 return 0;
1836         }
1837
1838         if (cfg) {
1839                 if (reload)
1840                         osp_unload();
1841
1842                 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "accelerate");
1843                 if (t && ast_true(t)) {
1844                         if ((error = OSPPInit(1)) != OSPC_ERR_NO_ERROR) {
1845                                 ast_log(LOG_WARNING, "OSP: Unable to enable hardware accelleration\n");
1846                                 OSPPInit(0);
1847                         } else {
1848                                 osp_hardware = 1;
1849                         }
1850                 } else {
1851                         OSPPInit(0);
1852                 }
1853                 ast_debug(1, "OSP: osp_hardware '%d'\n", osp_hardware);
1854
1855                 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "securityfeatures");
1856                 if (t && ast_true(t)) {
1857                         osp_security = 1;
1858                 }
1859                 ast_debug(1, "OSP: osp_security '%d'\n", osp_security);
1860
1861                 t = ast_variable_retrieve(cfg, OSP_GENERAL_CAT, "tokenformat");
1862                 if (t) {
1863                         if ((sscanf(t, "%d", &v) == 1) &&
1864                                 ((v == TOKEN_ALGO_SIGNED) || (v == TOKEN_ALGO_UNSIGNED) || (v == TOKEN_ALGO_BOTH)))
1865                         {
1866                                 osp_tokenformat = v;
1867                         } else {
1868                                 ast_log(LOG_WARNING, "tokenformat should be an integer from %d, %d or %d, not '%s'\n",
1869                                         TOKEN_ALGO_SIGNED, TOKEN_ALGO_UNSIGNED, TOKEN_ALGO_BOTH, t);
1870                         }
1871                 }
1872                 ast_debug(1, "OSP: osp_tokenformat '%d'\n", osp_tokenformat);
1873
1874                 t = ast_category_browse(cfg, NULL);
1875                 while(t) {
1876                         if (strcasecmp(t, OSP_GENERAL_CAT)) {
1877                                 osp_create_provider(cfg, t);
1878                         }
1879                         t = ast_category_browse(cfg, t);
1880                 }
1881
1882                 osp_initialized = 1;
1883
1884                 ast_config_destroy(cfg);
1885         } else {
1886                 ast_log(LOG_WARNING, "OSP: Unable to find configuration. OSP support disabled\n");
1887                 return 0;
1888         }
1889         ast_debug(1, "OSP: osp_initialized '%d'\n", osp_initialized);
1890
1891         return 1;
1892 }
1893
1894 static int osp_unload(void)
1895 {
1896         struct osp_provider* p;
1897         struct osp_provider* next;
1898
1899         if (osp_initialized) {
1900                 ast_mutex_lock(&osplock);
1901                 p = ospproviders;
1902                 while(p) {
1903                         next = p->next;
1904                         OSPPProviderDelete(p->handle, 0);
1905                         ast_free(p);
1906                         p = next;
1907                 }
1908                 ospproviders = NULL;
1909                 ast_mutex_unlock(&osplock);
1910
1911                 OSPPCleanup();
1912
1913                 osp_tokenformat = TOKEN_ALGO_SIGNED;
1914                 osp_security = 0;
1915                 osp_hardware = 0;
1916                 osp_initialized = 0;
1917         }
1918         return 0;
1919 }
1920
1921 static char *handle_cli_osp_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1922 {
1923         int i;
1924         int found = 0;
1925         struct osp_provider* p;
1926         const char* provider = NULL;
1927         const char* tokenalgo;
1928
1929         switch (cmd) {
1930         case CLI_INIT:
1931                 e->command = "osp show";
1932                 e->usage =
1933                         "Usage: osp show\n"
1934                         "       Displays information on Open Settlement Protocol support\n";
1935                 return NULL;
1936         case CLI_GENERATE:
1937                 return NULL;
1938         }
1939
1940         if ((a->argc < 2) || (a->argc > 3))
1941                 return CLI_SHOWUSAGE;
1942         if (a->argc > 2) 
1943                 provider = a->argv[2];
1944         if (!provider) {
1945                 switch (osp_tokenformat) {
1946                 case TOKEN_ALGO_BOTH:
1947                         tokenalgo = "Both";
1948                         break;
1949                 case TOKEN_ALGO_UNSIGNED:
1950                         tokenalgo = "Unsigned";
1951                         break;
1952                 case TOKEN_ALGO_SIGNED:
1953                 default:
1954                         tokenalgo = "Signed";
1955                         break;
1956                 }
1957                 ast_cli(a->fd, "OSP: %s/%s/%s/%s\n",
1958                         osp_initialized ? "Initialized" : "Uninitialized", 
1959                         osp_hardware ? "Accelerated" : "Normal", 
1960                         osp_security ? "Enabled" : "Disabled", 
1961                         tokenalgo);
1962         }
1963
1964         ast_mutex_lock(&osplock);
1965         p = ospproviders;
1966         while(p) {
1967                 if (!provider || !strcasecmp(p->name, provider)) {
1968                         if (found) {
1969                                 ast_cli(a->fd, "\n");
1970                         }
1971                         ast_cli(a->fd, " == OSP Provider '%s' == \n", p->name);
1972                         if (osp_security) {
1973                                 ast_cli(a->fd, "Local Private Key: %s\n", p->privatekey);
1974                                 ast_cli(a->fd, "Local Certificate: %s\n", p->localcert);
1975                                 for (i = 0; i < p->cacount; i++) {
1976                                         ast_cli(a->fd, "CA Certificate %d:  %s\n", i + 1, p->cacerts[i]);
1977                                 }
1978                         }
1979                         for (i = 0; i < p->spcount; i++) {
1980                                 ast_cli(a->fd, "Service Point %d:   %s\n", i + 1, p->srvpoints[i]);
1981                         }
1982                         ast_cli(a->fd, "Max Connections:   %d\n", p->maxconnections);
1983                         ast_cli(a->fd, "Retry Delay:       %d seconds\n", p->retrydelay);
1984                         ast_cli(a->fd, "Retry Limit:       %d\n", p->retrylimit);
1985                         ast_cli(a->fd, "Timeout:           %d milliseconds\n", p->timeout);
1986                         ast_cli(a->fd, "Source:            %s\n", strlen(p->source) ? p->source : "<unspecified>");
1987                         ast_cli(a->fd, "Auth Policy        %d\n", p->authpolicy);
1988                         ast_cli(a->fd, "Default protocol   %s\n", p->defaultprotocol);
1989                         ast_cli(a->fd, "OSP Handle:        %d\n", p->handle);
1990                         found++;
1991                 }
1992                 p = p->next;
1993         }
1994         ast_mutex_unlock(&osplock);
1995
1996         if (!found) {
1997                 if (provider) {
1998                         ast_cli(a->fd, "Unable to find OSP provider '%s'\n", provider);
1999                 } else {
2000                         ast_cli(a->fd, "No OSP providers configured\n");
2001                 }
2002         }
2003         return CLI_SUCCESS;
2004 }
2005
2006 static const char* app1= "OSPAuth";
2007 static const char* synopsis1 = "OSP authentication";
2008 static const char* descrip1 =
2009 "  OSPAuth([provider[,options]]):  Authenticate a SIP INVITE by OSP and sets\n"
2010 "the variables:\n"
2011 " ${OSPINHANDLE}:  The inbound call transaction handle\n"
2012 " ${OSPINTIMELIMIT}:  The inbound call duration limit in seconds\n"
2013 "\n"
2014 "This application sets the following channel variable upon completion:\n"
2015 "       OSPAUTHSTATUS   The status of the OSP Auth attempt as a text string, one of\n"
2016 "               SUCCESS | FAILED | ERROR\n";
2017
2018 static const char* app2= "OSPLookup";
2019 static const char* synopsis2 = "Lookup destination by OSP";
2020 static const char* descrip2 =
2021 "  OSPLookup(exten[,provider[,options]]):  Looks up an extension via OSP and sets\n"
2022 "the variables, where 'n' is the number of the result beginning with 1:\n"
2023 " ${OSPOUTHANDLE}:  The OSP Handle for anything remaining\n"
2024 " ${OSPTECH}:  The technology to use for the call\n"
2025 " ${OSPDEST}:  The destination to use for the call\n"
2026 " ${OSPCALLED}:  The called number to use for the call\n"
2027 " ${OSPCALLING}:  The calling number to use for the call\n"
2028 " ${OSPDIALSTR}:  The dial command string\n"
2029 " ${OSPOUTTOKEN}:  The actual OSP token as a string\n"
2030 " ${OSPOUTTIMELIMIT}:  The outbound call duration limit in seconds\n"
2031 " ${OSPOUTCALLIDTYPES}:  The outbound call id types\n"
2032 " ${OSPOUTCALLID}:  The outbound call id\n"
2033 " ${OSPRESULTS}:  The number of OSP results total remaining\n"
2034 "\n"
2035 "The option string may contain the following character:\n"
2036 "       'h' -- generate H323 call id for the outbound call\n"
2037 "       's' -- generate SIP call id for the outbound call. Have not been implemented\n"
2038 "       'i' -- generate IAX call id for the outbound call. Have not been implemented\n"
2039 "This application sets the following channel variable upon completion:\n"
2040 "       OSPLOOKUPSTATUS The status of the OSP Lookup attempt as a text string, one of\n"
2041 "               SUCCESS | FAILED | ERROR\n";
2042
2043 static const char* app3 = "OSPNext";
2044 static const char* synopsis3 = "Lookup next destination by OSP";
2045 static const char* descrip3 =
2046 "  OSPNext(cause[,provider[,options]]):  Looks up the next OSP Destination for ${OSPOUTHANDLE}\n"
2047 "See OSPLookup for more information\n"
2048 "\n"
2049 "This application sets the following channel variable upon completion:\n"
2050 "       OSPNEXTSTATUS The status of the OSP Next attempt as a text string, one of\n"
2051 "               SUCCESS | FAILED | ERROR\n";
2052
2053 static const char* app4 = "OSPFinish";
2054 static const char* synopsis4 = "Record OSP entry";
2055 static const char* descrip4 =
2056 "  OSPFinish([status[,options]]):  Records call state for ${OSPINHANDLE}, according to\n"
2057 "status, which should be one of BUSY, CONGESTION, ANSWER, NOANSWER, or CHANUNAVAIL\n"
2058 "or coincidentally, just what the Dial application stores in its ${DIALSTATUS}.\n"
2059 "\n"
2060 "This application sets the following channel variable upon completion:\n"
2061 "       OSPFINISHSTATUS The status of the OSP Finish attempt as a text string, one of\n"
2062 "               SUCCESS | FAILED | ERROR \n";
2063
2064 static struct ast_cli_entry cli_osp[] = {
2065         AST_CLI_DEFINE(handle_cli_osp_show, "Displays OSF information")
2066 };
2067
2068 static int load_module(void)
2069 {
2070         int res;
2071
2072         if (!osp_load(0))
2073                 return AST_MODULE_LOAD_DECLINE;
2074
2075         ast_cli_register_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
2076         res = ast_register_application(app1, ospauth_exec, synopsis1, descrip1);
2077         res |= ast_register_application(app2, osplookup_exec, synopsis2, descrip2);
2078         res |= ast_register_application(app3, ospnext_exec, synopsis3, descrip3);
2079         res |= ast_register_application(app4, ospfinished_exec, synopsis4, descrip4);
2080
2081         return res;
2082 }
2083
2084 static int unload_module(void)
2085 {
2086         int res;
2087
2088         res = ast_unregister_application(app4);
2089         res |= ast_unregister_application(app3);
2090         res |= ast_unregister_application(app2);
2091         res |= ast_unregister_application(app1);
2092         ast_cli_unregister_multiple(cli_osp, sizeof(cli_osp) / sizeof(struct ast_cli_entry));
2093         osp_unload();
2094
2095         return res;
2096 }
2097
2098 static int reload(void)
2099 {
2100         osp_load(1);
2101
2102         return 0;
2103 }
2104
2105 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Open Settlement Protocol Applications",
2106         .load = load_module,
2107         .unload = unload_module,
2108         .reload = reload,
2109 );