static int globaltrustrpid = 0;
+#ifdef OSP_SUPPORT
+static int globalospauth = 0;
+#endif
+
static int usecnt =0;
AST_MUTEX_DEFINE_STATIC(usecnt_lock);
int pendingbye; /* Need to send bye after we ack? */
int gotrefer; /* Got a refer? */
#ifdef OSP_SUPPORT
+ int ospauth; /* Allow OSP Authentication */
int osphandle; /* OSP Handle for call */
time_t ospstart; /* OSP Start time */
#endif
int insecure;
int canreinvite;
int capability;
+#ifdef OSP_SUPPORT
+ int ospauth; /* Allow OSP Authentication */
+#endif
int dtmfmode;
int inUse;
int incominglimit;
int rtptimeout;
int rtpholdtimeout;
int insecure;
+#ifdef OSP_SUPPORT
+ int ospauth; /* Allow OSP Authentication */
+#endif
int nat;
int canreinvite;
unsigned int callgroup;
p->dtmfmode = globaldtmfmode;
p->promiscredir = globalpromiscredir;
p->trustrpid = globaltrustrpid;
+#ifdef OSP_SUPPORT
+ p->ospauth = globalospauth;
+#endif
p->rtptimeout = globalrtptimeout;
p->rtpholdtimeout = globalrtpholdtimeout;
p->capability = capability;
char *reqheader = "Proxy-Authorization";
char *respheader = "Proxy-Authenticate";
char *authtoken;
+#ifdef OSP_SUPPORT
+ char *osptoken;
+ unsigned int osptimelimit;
+#endif
/* Always OK if no secret */
- if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret))
+ if (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)
+#ifdef OSP_SUPPORT
+ && !p->ospauth
+#endif
+ )
return 0;
if (!strcasecmp(method, "REGISTER")) {
/* On a REGISTER, we have to use 401 and its family of headers instead of 407 and its family
reqheader = "Authorization";
respheader = "WWW-Authenticate";
}
+#ifdef OSP_SUPPORT
+ else if (p->ospauth) {
+ ast_log(LOG_DEBUG, "Checking OSP Authentication!\n");
+ osptoken = get_header(req, "P-OSP-Auth-Token");
+ /* Check for token existence */
+ if (!strlen(osptoken))
+ return -1;
+ /* Validate token */
+ if (ast_osp_validate(NULL, osptoken, &p->osphandle, &osptimelimit, p->callerid, p->sa.sin_addr, p->exten) < 1)
+ return -1;
+ /* If ospauth is 'exclusive' don't require further authentication */
+ if ((p->ospauth > 1) || (ast_strlen_zero(secret) && ast_strlen_zero(md5secret)))
+ return 0;
+ }
+#endif
authtoken = get_header(req, reqheader);
if (ignore && !ast_strlen_zero(randdata) && ast_strlen_zero(authtoken)) {
/* This is a retransmitted invite/register/etc, don't reconstruct authentication
user = find_user(of);
if (user && ast_apply_ha(user->ha, sin)) {
p->nat = user->nat;
+#ifdef OSP_SUPPORT
+ p->ospauth = user->ospauth;
+#endif
+ p->trustrpid = user->trustrpid;
+ /* replace callerid if rpid found, and not restricted */
+ if(!ast_strlen_zero(rpid_num) && p->trustrpid) {
+ if (*calleridname)
+ sprintf(p->callerid,"\"%s\" <%s>",calleridname,rpid_num);
+ else
+ strncpy(p->callerid, rpid_num, sizeof(p->callerid) - 1);
+ }
+
if (p->rtp) {
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat);
ast_rtp_setnat(p->rtp, p->nat);
strncpy(p->accountcode, user->accountcode, sizeof(p->accountcode) -1);
strncpy(p->language, user->language, sizeof(p->language) -1);
strncpy(p->musicclass, user->musicclass, sizeof(p->musicclass) -1);
- p->trustrpid = user->trustrpid;
p->canreinvite = user->canreinvite;
p->amaflags = user->amaflags;
p->callgroup = user->callgroup;
ast_verbose("Found peer '%s'\n", peer->name);
/* Take the peer */
p->nat = peer->nat;
+ p->trustrpid = peer->trustrpid;
+ /* replace callerid if rpid found, and not restricted */
+ if(!ast_strlen_zero(rpid_num) && p->trustrpid) {
+ if (*calleridname)
+ sprintf(p->callerid,"\"%s\" <%s>",calleridname,rpid_num);
+ else
+ strncpy(p->callerid, rpid_num, sizeof(p->callerid) - 1);
+ }
+#ifdef OSP_SUPPORT
+ p->ospauth = peer->ospauth;
+#endif
if (p->rtp) {
ast_log(LOG_DEBUG, "Setting NAT on RTP to %d\n", p->nat);
ast_rtp_setnat(p->rtp, p->nat);
else
p->noncodeccapability &= ~AST_RTP_DTMF;
}
- p->trustrpid = peer->trustrpid;
-
}
if (peer->temponly) {
if (peer->ha) {
}
- /* replace callerid if rpid found, and not restricted */
- if(!ast_strlen_zero(rpid_num) && p->trustrpid) {
- if (*calleridname)
- sprintf(p->callerid,"\"%s\" <%s>",calleridname,rpid_num);
- else
- strncpy(p->callerid, rpid_num, sizeof(p->callerid) - 1);
- }
-
return res;
}
static int check_user(struct sip_pvt *p, struct sip_request *req, char *cmd, char *uri, int reliable, struct sockaddr_in *sin, int ignore)
user->canreinvite = globalcanreinvite;
user->trustrpid = globaltrustrpid;
+#ifdef OSP_SUPPORT
+ user->ospauth = globalospauth;
+#endif
/* set default context */
strncpy(user->context, context, sizeof(user->context)-1);
strncpy(user->language, language, sizeof(user->language)-1);
} else if (!strcasecmp(v->name, "restrictcid")) {
user->restrictcid = ast_true(v->value);
} else if (!strcasecmp(v->name, "trustrpid")) {
- user->trustrpid = ast_true(v->value);
+ user->trustrpid = ast_true(v->value);
+#ifdef OSP_SUPPORT
+ } else if (!strcasecmp(v->name, "ospauth")) {
+ if (!strcasecmp(v->value, "exclusive")) {
+ user->ospauth = 2;
+ } else if (ast_true(v->value)) {
+ user->ospauth = 1;
+ } else
+ user->ospauth = 0;
+#endif
}
/*else if (strcasecmp(v->name,"type"))
* ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
peer->selfdestruct = 1;
peer->dynamic = 1;
peer->trustrpid = globaltrustrpid;
+#ifdef OSP_SUPPORT
+ peer->ospauth = globalospauth;
+#endif
reg_source_db(peer);
return peer;
}
peer->dtmfmode = 0;
peer->promiscredir = globalpromiscredir;
peer->trustrpid = globaltrustrpid;
+#ifdef OSP_SUPPORT
+ peer->ospauth = globalospauth;
+#endif
while(v) {
if (!strcasecmp(v->name, "secret"))
strncpy(peer->secret, v->value, sizeof(peer->secret)-1);
}
} else if (!strcasecmp(v->name, "trustrpid")) {
peer->trustrpid = ast_true(v->value);
+#ifdef OSP_SUPPORT
+ } else if (!strcasecmp(v->name, "ospauth")) {
+ if (!strcasecmp(v->value, "exclusive")) {
+ peer->ospauth = 2;
+ } else if (ast_true(v->value)) {
+ peer->ospauth = 1;
+ } else
+ peer->ospauth = 0;
+#endif
}
/* else if (strcasecmp(v->name,"type"))
* ast_log(LOG_WARNING, "Ignoring %s\n", v->name);
srvlookup = ast_true(v->value);
} else if (!strcasecmp(v->name, "trustrpid")) {
globaltrustrpid = ast_true(v->value);
+#ifdef OSP_SUPPORT
+ } else if (!strcasecmp(v->name, "ospauth")) {
+ if (!strcasecmp(v->value, "exclusive")) {
+ globalospauth = 2;
+ } else if (ast_true(v->value)) {
+ globalospauth = 1;
+ } else
+ globalospauth = 0;
+#endif
} else if (!strcasecmp(v->name, "pedantic")) {
pedanticsipchecking = ast_true(v->value);
} else if (!strcasecmp(v->name, "canreinvite")) {
--- /dev/null
+;
+; Open Settlement Protocol Sample Configuration File
+;
+;
+; This file contains configuration of providers that
+; are used by the OSP subsystem of Asterisk. The section
+; "general" is reserved for global options. Each other
+; section declares an OSP Provider. The provider "default"
+; is used when no provider is otherwise specified.
+;
+[general]
+;
+; Should hardware accelleration be enabled? May not be changed
+; on a reload.
+;
+;accelerate=yes
+
+;[default]
+;
+; All paths are presumed to be under /var/lib/asterisk/keys unless
+; the path begins with '/'
+;
+; Specify the private keyfile. If unspecified, defaults to the name
+; of the section followed by "-privatekey.pem" (e.g. default-privatekey.pem)
+;
+;privatekey=pkey.pem
+;
+; Specify the local certificate file. If unspecified, defaults to
+; the name of the section followed by "-localcert.pem"
+;
+;localcert=localcert.pem
+;
+; Specify one or more Certificate Authority keys. If none are listed,
+; a single one is added with the name "-cacert.pem"
+;
+;cacert=cacert_0.pem
+;
+; Specific parameters can be tuned as well:
+;
+; maxconnections: Max number of simultaneous connections to the provider (default=20)
+; retrydelay: Extra delay between retries (default=0)
+; retrylimit: Max number of retries before giving up (default=2)
+; timeout: Timeout for response in milliseconds (default=500)
+;
+;maxconnections=20
+;retrydelay=0
+;retrylimit=2
+;timeout=500
+;
+; List all service points for this provider
+;
+;servicepoint=http://osptestserver.transnexus.com:1080/osp
+;
+; Set the "source" for requesting authorization
+;
+;source=foo
return retVal;
}
+int ast_osp_validate(char *provider, char *token, int *handle, unsigned int *timelimit, char *callerid, struct in_addr addr, char *extension)
+{
+ char tmp[256]="", *l, *n;
+ char ip[256];
+ char source[OSP_MAX]; /* Same length as osp->source */
+ char *token2;
+ int tokenlen;
+ struct osp_provider *osp;
+ int res = 0;
+ unsigned int authorised, dummy;
+
+ if (!provider || !strlen(provider))
+ provider = "default";
+
+ token2 = ast_strdupa(token);
+ if (!token2)
+ return -1;
+ tokenlen = ast_base64decode(token2, token, strlen(token));
+ *handle = -1;
+ if (!callerid)
+ callerid = "";
+ strncpy(tmp, callerid, sizeof(tmp) - 1);
+ ast_callerid_parse(tmp, &n, &l);
+ if (!l)
+ l = "";
+ else {
+ ast_shrink_phone_number(l);
+ if (!ast_isphonenumber(l))
+ l = "";
+ }
+ callerid = l;
+ ast_mutex_lock(&osplock);
+ strcpy(ip, inet_ntoa(addr));
+ osp = providers;
+ while(osp) {
+ if (!strcasecmp(osp->name, provider)) {
+ if (OSPPTransactionNew(osp->handle, handle)) {
+ ast_log(LOG_WARNING, "Unable to create OSP Transaction handle!\n");
+ } else {
+ strcpy(source, osp->source);
+ res = 1;
+ }
+ break;
+ }
+ osp = osp->next;
+ }
+ ast_mutex_unlock(&osplock);
+ if (res) {
+ res = 0;
+ dummy = 0;
+ if (!OSPPTransactionValidateAuthorisation(*handle, ip, source, NULL, NULL,
+ callerid, OSPC_E164, extension, OSPC_E164, 0, "", tokenlen, token2, &authorised, timelimit, &dummy, NULL, TOKEN_ALGO_BOTH)) {
+ if (authorised) {
+ ast_log(LOG_DEBUG, "Validated token for '%s' from '%s@%s'\n", extension, callerid, ip);
+ res = 1;
+ }
+ }
+ }
+ return res;
+}
+
int ast_osp_lookup(struct ast_channel *chan, char *provider, char *extension, char *callerid, struct ast_osp_result *result)
{
int cres;