aboutsummaryrefslogtreecommitdiffstats
path: root/channels/chan_iax.c
diff options
context:
space:
mode:
authormarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2002-01-07 22:34:22 +0000
committermarkster <markster@f38db490-d61c-443f-a65b-d21fe96a405b>2002-01-07 22:34:22 +0000
commitc3b979e83f03b767eb08b136b652f3297c1aad81 (patch)
tree3b1e56f99b2bd53280774d175cb4d949e440c8e5 /channels/chan_iax.c
parent721f270b252ea78cc6a433f7908a199258cf2786 (diff)
Version 0.1.10 from FTP
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@402 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_iax.c')
-rwxr-xr-xchannels/chan_iax.c512
1 files changed, 347 insertions, 165 deletions
diff --git a/channels/chan_iax.c b/channels/chan_iax.c
index 77c4438a9..679ba65a5 100755
--- a/channels/chan_iax.c
+++ b/channels/chan_iax.c
@@ -24,6 +24,8 @@
#include <asterisk/cli.h>
#include <asterisk/translate.h>
#include <asterisk/md5.h>
+#include <asterisk/cdr.h>
+#include <asterisk/crypto.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -103,6 +105,9 @@ static int use_jitterbuffer = 1;
static int iaxdebug = 0;
+static char accountcode[20];
+static int amaflags = 0;
+
static pthread_t netthreadid;
#define IAX_STATE_STARTED (1 << 0)
@@ -129,6 +134,9 @@ struct iax_user {
char name[80];
char secret[80];
char methods[80];
+ char accountcode[20];
+ char inkeys[80]; /* Key(s) this user can use to authenticate to us */
+ int amaflags;
int hascallerid;
char callerid[AST_MAX_EXTENSION];
struct iax_ha *ha;
@@ -138,8 +146,9 @@ struct iax_user {
struct iax_peer {
char name[80];
- char username[80];
+ char username[80];
char secret[80];
+ char outkey[80]; /* What key we use to talk to this peer */
struct sockaddr_in addr;
int formats;
struct in_addr mask;
@@ -149,6 +158,8 @@ struct iax_peer {
struct sockaddr_in defaddr; /* Default address if there is one */
char challenge[80]; /* Challenge used to authenticate the secret */
char methods[80];
+ char inkeys[80]; /* Key(s) this peer can use to authenticate to us */
+
int hascallerid;
char callerid[AST_MAX_EXTENSION];
int expire; /* Schedule entry for expirey */
@@ -176,7 +187,7 @@ struct iax_peer {
struct iax_registry {
struct sockaddr_in addr; /* Who we connect to for registration purposes */
char username[80];
- char secret[80];
+ char secret[80]; /* Password or key name in []'s */
char random[80];
int expire; /* Sched ID of expiration */
int refresh; /* How often to refresh */
@@ -257,6 +268,8 @@ struct chan_iax_pvt {
char context[80];
/* Caller ID if available */
char callerid[80];
+ /* Hidden Caller ID if appropriate */
+ char hidden_callerid[80];
/* DNID */
char dnid[80];
/* Requested Extension */
@@ -269,6 +282,10 @@ struct chan_iax_pvt {
char methods[80];
/* MD5 challenge */
char challenge[10];
+ /* Public keys permitted keys for incoming authentication */
+ char inkeys[80];
+ /* Private key for outgoing authentication */
+ char outkey[80];
/* Preferred language */
char language[80];
/* Associated registry */
@@ -282,6 +299,9 @@ struct chan_iax_pvt {
struct sockaddr_in transfer;
/* What's the new call number for the transfer */
int transfercallno;
+
+ /* Status of knowledge of peer ADSI capability */
+ int peeradsicpe;
/* Who we are bridged to */
int bridgecallno;
@@ -289,6 +309,8 @@ struct chan_iax_pvt {
int lagid;
int autoid;
char dproot[AST_MAX_EXTENSION];
+ char accountcode[20];
+ int amaflags;
struct iax_dpcache *dpentries;
};
@@ -571,8 +593,8 @@ static struct chan_iax_pvt *new_iax(void)
tmp->pingid = -1;
tmp->lagid = -1;
tmp->autoid = -1;
- /* strncpy(tmp->context, context, sizeof(tmp->context)); */
- strncpy(tmp->exten, "s", sizeof(tmp->exten));
+ /* strncpy(tmp->context, context, sizeof(tmp->context)-1); */
+ strncpy(tmp->exten, "s", sizeof(tmp->exten)-1);
}
return tmp;
}
@@ -730,6 +752,8 @@ static int find_callno(short callno, short dcallno ,struct sockaddr_in *sin, int
iaxs[x]->expirey = expirey;
iaxs[x]->pingid = ast_sched_add(sched, ping_time * 1000, send_ping, (void *)x);
iaxs[x]->lagid = ast_sched_add(sched, lagrq_time * 1000, send_lagrq, (void *)x);
+ iaxs[x]->amaflags = amaflags;
+ strncpy(iaxs[x]->accountcode, accountcode, sizeof(iaxs[x]->accountcode)-1);
} else {
ast_log(LOG_WARNING, "Out of resources\n");
return -1;
@@ -1096,6 +1120,12 @@ static int schedule_delivery(struct ast_iax_frame *fr, int reallydeliver)
update the timestamp appropriately. */
ms -= 65536;
}
+
+ if (ms < -32768) {
+ /* We got this packet out of order. Lets add 65536 to it to bring it into our new
+ time frame */
+ ms += 65536;
+ }
/* Rotate our history queue of "lateness". Don't worry about those initial
zeros because the first entry will always be zero */
@@ -1321,7 +1351,7 @@ static int iax_call(struct ast_channel *c, char *dest, int timeout)
ast_log(LOG_WARNING, "Line is already in use (%s)?\n", c->name);
return -1;
}
- strncpy(host, dest, sizeof(host));
+ strncpy(host, dest, sizeof(host)-1);
strtok(host, "/");
/* If no destination extension specified, use 's' */
rdest = strtok(NULL, "/");
@@ -1355,6 +1385,7 @@ static int iax_call(struct ast_channel *c, char *dest, int timeout)
}
/* Now we build our request string */
#define MYSNPRINTF snprintf(requeststr + strlen(requeststr), sizeof(requeststr) - strlen(requeststr),
+#define MYSNPRINTF2 snprintf(requeststr + strlen(requeststr), reqsize - strlen(requeststr),
MYSNPRINTF "exten=%s;", rdest);
if (c->callerid)
MYSNPRINTF "callerid=%s;", c->callerid);
@@ -1366,11 +1397,20 @@ static int iax_call(struct ast_channel *c, char *dest, int timeout)
MYSNPRINTF "context=%s;", rcontext);
if (username)
MYSNPRINTF "username=%s;", username);
- if (secret)
- strncpy(p->secret, secret, sizeof(p->secret));
+ if (secret) {
+ if (secret[0] == '[') {
+ /* This is an RSA key, not a normal secret */
+ strncpy(p->outkey, secret + 1, sizeof(p->secret)-1);
+ if (strlen(p->outkey)) {
+ p->outkey[strlen(p->outkey) - 1] = '\0';
+ }
+ } else
+ strncpy(p->secret, secret, sizeof(p->secret)-1);
+ }
MYSNPRINTF "formats=%d;", c->nativeformats);
MYSNPRINTF "capability=%d;", p->capability);
MYSNPRINTF "version=%d;", AST_IAX_PROTO_VERSION);
+ MYSNPRINTF "adsicpe=%d;", c->adsicpe);
/* Trim the trailing ";" */
if (strlen(requeststr))
requeststr[strlen(requeststr) - 1] = '\0';
@@ -1616,12 +1656,37 @@ static int iax_indicate(struct ast_channel *c, int condition)
static int iax_write(struct ast_channel *c, struct ast_frame *f);
+static int iax_getpeername(struct sockaddr_in sin, char *host, int len)
+{
+ struct iax_peer *peer;
+ int res = 0;
+ ast_pthread_mutex_lock(&peerl.lock);
+ peer = peerl.peers;
+ while(peer) {
+ if ((peer->addr.sin_addr.s_addr == sin.sin_addr.s_addr) &&
+ (peer->addr.sin_port == sin.sin_port)) {
+ strncpy(host, peer->name, len-1);
+ res = 1;
+ break;
+ }
+ peer = peer->next;
+ }
+ ast_pthread_mutex_unlock(&peerl.lock);
+ return res;
+}
+
static struct ast_channel *ast_iax_new(struct chan_iax_pvt *i, int state, int capability)
{
+ char host[256];
struct ast_channel *tmp;
tmp = ast_channel_alloc();
if (tmp) {
- snprintf(tmp->name, sizeof(tmp->name), "IAX[%s:%d]/%d", inet_ntoa(i->addr.sin_addr), ntohs(i->addr.sin_port), i->callno);
+ if (!iax_getpeername(i->addr, host, sizeof(host)))
+ snprintf(host, sizeof(host), "%s:%d", inet_ntoa(i->addr.sin_addr), ntohs(i->addr.sin_port));
+ if (strlen(i->username))
+ snprintf(tmp->name, sizeof(tmp->name), "IAX[%s@%s]/%d", i->username, host, i->callno);
+ else
+ snprintf(tmp->name, sizeof(tmp->name), "IAX[%s]/%d", host, i->callno);
tmp->type = type;
tmp->fds[0] = i->pipe[0];
/* We can support any format by default, until we get restricted */
@@ -1643,12 +1708,19 @@ static struct ast_channel *ast_iax_new(struct chan_iax_pvt *i, int state, int ca
tmp->pvt->bridge = iax_bridge;
if (strlen(i->callerid))
tmp->callerid = strdup(i->callerid);
+ if (strlen(i->hidden_callerid))
+ tmp->hidden_callerid = strdup(i->hidden_callerid);
if (strlen(i->language))
- strncpy(tmp->language, i->language, sizeof(tmp->language));
+ strncpy(tmp->language, i->language, sizeof(tmp->language)-1);
if (strlen(i->dnid))
tmp->dnid = strdup(i->dnid);
- strncpy(tmp->context, i->context, sizeof(tmp->context));
- strncpy(tmp->exten, i->exten, sizeof(tmp->exten));
+ if (strlen(i->accountcode))
+ strncpy(tmp->accountcode, i->accountcode, sizeof(tmp->accountcode)-1);
+ if (i->amaflags)
+ tmp->amaflags = i->amaflags;
+ strncpy(tmp->context, i->context, sizeof(tmp->context)-1);
+ strncpy(tmp->exten, i->exten, sizeof(tmp->exten)-1);
+ tmp->adsicpe = i->peeradsicpe;
tmp->pvt->fixup = iax_fixup;
i->owner = tmp;
i->capability = capability;
@@ -1839,7 +1911,7 @@ static int iax_show_peers(int fd, int argc, char *argv[])
ast_cli(fd, FORMAT2, "Name", "Username", "Host", " ", "Mask", "Port");
for (peer = peerl.peers;peer;peer = peer->next) {
char nm[20];
- strncpy(nm, inet_ntoa(peer->mask), sizeof(nm));
+ strncpy(nm, inet_ntoa(peer->mask), sizeof(nm)-1);
ast_cli(fd, FORMAT, peer->name,
peer->username ? peer->username : "(Any)",
peer->addr.sin_addr.s_addr ? inet_ntoa(peer->addr.sin_addr) : "(Unspecified)",
@@ -2071,7 +2143,7 @@ static int iax_getformats(int callno, char *orequest)
{
char *var, *value;
char request[256];
- strncpy(request, orequest, sizeof(request));
+ strncpy(request, orequest, sizeof(request)-1);
var = strtok(request, ";");
while(var) {
value = strchr(var, '=');
@@ -2098,7 +2170,7 @@ static int check_access(int callno, struct sockaddr_in *sin, char *orequest, int
struct iax_user *user;
char request[256];
int gotcapability=0;
- strncpy(request, orequest, sizeof(request));
+ strncpy(request, orequest, sizeof(request)-1);
if (!iaxs[callno])
return res;
var = strtok(request, ";");
@@ -2108,19 +2180,21 @@ static int check_access(int callno, struct sockaddr_in *sin, char *orequest, int
*value='\0';
value++;
if (!strcmp(var, "exten"))
- strncpy(iaxs[callno]->exten, value, sizeof(iaxs[callno]->exten));
+ strncpy(iaxs[callno]->exten, value, sizeof(iaxs[callno]->exten)-1);
else if (!strcmp(var, "callerid"))
- strncpy(iaxs[callno]->callerid, value, sizeof(iaxs[callno]->callerid));
+ strncpy(iaxs[callno]->callerid, value, sizeof(iaxs[callno]->callerid)-1);
else if (!strcmp(var, "dnid"))
- strncpy(iaxs[callno]->dnid, value, sizeof(iaxs[callno]->dnid));
+ strncpy(iaxs[callno]->dnid, value, sizeof(iaxs[callno]->dnid)-1);
else if (!strcmp(var, "context"))
- strncpy(iaxs[callno]->context, value, sizeof(iaxs[callno]->context));
+ strncpy(iaxs[callno]->context, value, sizeof(iaxs[callno]->context)-1);
else if (!strcmp(var, "language"))
- strncpy(iaxs[callno]->language, value, sizeof(iaxs[callno]->language));
+ strncpy(iaxs[callno]->language, value, sizeof(iaxs[callno]->language)-1);
else if (!strcmp(var, "username"))
- strncpy(iaxs[callno]->username, value, sizeof(iaxs[callno]->username));
+ strncpy(iaxs[callno]->username, value, sizeof(iaxs[callno]->username)-1);
else if (!strcmp(var, "formats"))
iaxs[callno]->peerformat = atoi(value);
+ else if (!strcmp(var, "adsicpe"))
+ iaxs[callno]->peeradsicpe = atoi(value);
else if (!strcmp(var, "capability")) {
gotcapability = 1;
iaxs[callno]->peercapability = atoi(value);
@@ -2151,21 +2225,30 @@ static int check_access(int callno, struct sockaddr_in *sin, char *orequest, int
/* Store the requested username if not specified */
if (!strlen(iaxs[callno]->username))
- strncpy(iaxs[callno]->username, user->name, sizeof(iaxs[callno]->username));
+ strncpy(iaxs[callno]->username, user->name, sizeof(iaxs[callno]->username)-1);
/* And use the default context */
if (!strlen(iaxs[callno]->context)) {
if (user->contexts)
- strncpy(iaxs[callno]->context, user->contexts->context, sizeof(iaxs[callno]->context));
+ strncpy(iaxs[callno]->context, user->contexts->context, sizeof(iaxs[callno]->context)-1);
else
- strncpy(iaxs[callno]->context, context, sizeof(iaxs[callno]->context));
+ strncpy(iaxs[callno]->context, context, sizeof(iaxs[callno]->context)-1);
}
/* Copy the secret */
- strncpy(iaxs[callno]->secret, user->secret, sizeof(iaxs[callno]->secret));
+ strncpy(iaxs[callno]->secret, user->secret, sizeof(iaxs[callno]->secret)-1);
+ /* And any input keys */
+ strncpy(iaxs[callno]->inkeys, user->inkeys, sizeof(iaxs[callno]->inkeys));
/* And the permitted authentication methods */
- strncpy(iaxs[callno]->methods, user->methods, sizeof(iaxs[callno]->methods));
- /* If they have callerid, override the given caller id */
- if (user->hascallerid && strlen(iaxs[callno]->callerid))
- strncpy(iaxs[callno]->callerid, user->callerid, sizeof(iaxs[callno]->callerid));
+ strncpy(iaxs[callno]->methods, user->methods, sizeof(iaxs[callno]->methods)-1);
+ /* If they have callerid, override the given caller id. Always store the hidden */
+ if (strlen(iaxs[callno]->callerid)) {
+ if (user->hascallerid)
+ strncpy(iaxs[callno]->callerid, user->callerid, sizeof(iaxs[callno]->callerid)-1);
+ strncpy(iaxs[callno]->hidden_callerid, user->callerid, sizeof(iaxs[callno]->hidden_callerid)-1);
+ }
+ if (strlen(user->accountcode))
+ strncpy(iaxs[callno]->accountcode, user->accountcode, sizeof(iaxs[callno]->accountcode)-1);
+ if (user->amaflags)
+ iaxs[callno]->amaflags = user->amaflags;
res = 0;
break;
}
@@ -2196,7 +2279,7 @@ static int authenticate_request(struct chan_iax_pvt *p)
{
char requeststr[256] = "";
MYSNPRINTF "methods=%s;", p->methods);
- if (strstr(p->methods, "md5")) {
+ if (strstr(p->methods, "md5") || strstr(p->methods, "rsa")) {
/* Build the challenge */
snprintf(p->challenge, sizeof(p->challenge), "%d", rand());
MYSNPRINTF "challenge=%s;", p->challenge);
@@ -2213,12 +2296,13 @@ static int authenticate_verify(struct chan_iax_pvt *p, char *orequest)
char *var, *value, request[256];
char md5secret[256] = "";
char secret[256] = "";
+ char rsasecret[256] = "";
int res = -1;
int x;
if (!(p->state & IAX_STATE_AUTHENTICATED))
return res;
- strncpy(request, orequest, sizeof(request));
+ strncpy(request, orequest, sizeof(request)-1);
var = strtok(request, ";");
while(var) {
value = strchr(var, '=');
@@ -2226,15 +2310,32 @@ static int authenticate_verify(struct chan_iax_pvt *p, char *orequest)
*value='\0';
value++;
if (!strcmp(var, "secret"))
- strncpy(secret, value, sizeof(secret));
+ strncpy(secret, value, sizeof(secret)-1);
else if (!strcmp(var, "md5secret"))
- strncpy(md5secret, value, sizeof(md5secret));
- else
+ strncpy(md5secret, value, sizeof(md5secret)-1);
+ else if (!strcmp(var, "rsasecret"))
+ strncpy(rsasecret, value, sizeof(rsasecret)-1);
+ else
ast_log(LOG_WARNING, "Unknown variable '%s' with value '%s'\n", var, value);
}
var = strtok(NULL, ";");
}
- if (strstr(p->methods, "md5")) {
+ if (strstr(p->methods, "rsa") && strlen(rsasecret) && strlen(p->inkeys)) {
+ struct ast_key *key;
+ char *keyn;
+ char tmpkey[256];
+ strncpy(tmpkey, p->inkeys, sizeof(tmpkey));
+ keyn = strtok(tmpkey, ":");
+ while(keyn) {
+ key = ast_key_get(keyn, AST_KEY_PUBLIC);
+ if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
+ res = 0;
+ break;
+ } else if (!key)
+ ast_log(LOG_WARNING, "requested inkey '%s' for RSA authentication does not exist\n");
+ keyn = strtok(NULL, ":");
+ }
+ } else if (strstr(p->methods, "md5")) {
struct MD5Context md5;
unsigned char digest[16];
MD5Init(&md5);
@@ -2259,17 +2360,21 @@ static int register_verify(int callno, struct sockaddr_in *sin, char *orequest)
char requeststr[256] = "";
char peer[256] = "";
char md5secret[256] = "";
+ char rsasecret[256] = "";
char secret[256] = "";
struct iax_peer *p;
+ struct ast_key *key;
char *var;
char *value;
+ char *keyn;
int x;
int expire = 0;
+
iaxs[callno]->state &= ~IAX_STATE_AUTHENTICATED;
strcpy(iaxs[callno]->peer, "");
if (!orequest)
return -1;
- strncpy(request, orequest, sizeof(request));
+ strncpy(request, orequest, sizeof(request)-1);
var = strtok(request, ";");
while(var) {
value = strchr(var, '=');
@@ -2277,11 +2382,13 @@ static int register_verify(int callno, struct sockaddr_in *sin, char *orequest)
*value='\0';
value++;
if (!strcmp(var, "peer"))
- strncpy(peer, value, sizeof(peer));
+ strncpy(peer, value, sizeof(peer)-1);
else if (!strcmp(var, "md5secret"))
- strncpy(md5secret, value, sizeof(md5secret));
+ strncpy(md5secret, value, sizeof(md5secret)-1);
+ else if (!strcmp(var, "rsasecret"))
+ strncpy(rsasecret, value, sizeof(rsasecret)-1);
else if (!strcmp(var, "secret"))
- strncpy(secret, value, sizeof(secret));
+ strncpy(secret, value, sizeof(secret)-1);
else if (!strcmp(var, "refresh"))
expire = atoi(value);
else
@@ -2311,11 +2418,34 @@ static int register_verify(int callno, struct sockaddr_in *sin, char *orequest)
if (apply_ha(p->ha, sin) != IAX_SENSE_ALLOW) {
ast_log(LOG_NOTICE, "Host %s denied access to register peer '%s'\n", inet_ntoa(sin->sin_addr), p->name);
- return -1;
+ return -1;
}
- strncpy(iaxs[callno]->secret, p->secret, sizeof(iaxs[callno]->secret));
+ strncpy(iaxs[callno]->secret, p->secret, sizeof(iaxs[callno]->secret)-1);
+ strncpy(iaxs[callno]->inkeys, p->inkeys, sizeof(iaxs[callno]->inkeys)-1);
/* Check secret against what we have on file */
- if (strlen(secret) && strstr(p->methods, "plaintext")) {
+ if (strlen(rsasecret) && strstr(p->methods, "rsa") && strlen(p->challenge)) {
+ if (strlen(p->inkeys)) {
+ char tmpkeys[256];
+ strncpy(tmpkeys, p->inkeys, sizeof(tmpkeys));
+ keyn = strtok(tmpkeys, ":");
+ while(keyn) {
+ key = ast_key_get(keyn, AST_KEY_PUBLIC);
+ if (key && !ast_check_signature(key, p->challenge, rsasecret)) {
+ iaxs[callno]->state |= IAX_STATE_AUTHENTICATED;
+ break;
+ } else if (!key)
+ ast_log(LOG_WARNING, "requested inkey '%s' does not exist\n", keyn);
+ keyn = strtok(NULL, ":");
+ }
+ if (!keyn) {
+ ast_log(LOG_NOTICE, "Host %s failed RSA authentication with inkeys '%s'\n", peer, p->inkeys);
+ return -1;
+ }
+ } else {
+ ast_log(LOG_NOTICE, "Host '%s' trying to do RSA authentication, but we have no inkeys\n", peer);
+ return -1;
+ }
+ } else if (strlen(secret) && strstr(p->methods, "plaintext")) {
/* They've provided a plain text password and we support that */
if (strcmp(secret, p->secret)) {
ast_log(LOG_NOTICE, "Host %s did not provide proper plaintext password for '%s'\n", inet_ntoa(sin->sin_addr), p->name);
@@ -2340,7 +2470,7 @@ static int register_verify(int callno, struct sockaddr_in *sin, char *orequest)
ast_log(LOG_NOTICE, "Inappropriate authentication received\n");
return -1;
}
- strncpy(iaxs[callno]->peer, peer, sizeof(iaxs[callno]->peer));
+ strncpy(iaxs[callno]->peer, peer, sizeof(iaxs[callno]->peer)-1);
/* Choose lowest expirey number */
if (expire && (expire < iaxs[callno]->expirey))
iaxs[callno]->expirey = expire;
@@ -2348,7 +2478,58 @@ static int register_verify(int callno, struct sockaddr_in *sin, char *orequest)
}
-static int authenticate_reply(struct chan_iax_pvt *p, struct sockaddr_in *sin, char *orequest, char *override)
+static int authenticate(char *challenge, char *secret, char *keyn, char *methods, char *requeststr, int reqsize, struct sockaddr_in *sin)
+{
+ int res = -1;
+ int x;
+ if (keyn && strlen(keyn)) {
+ if (!strstr(methods, "rsa")) {
+ if (!secret || !strlen(secret))
+ ast_log(LOG_NOTICE, "Asked to authenticate to %s with an RSA key, but they don't allow RSA authentication\n", inet_ntoa(sin->sin_addr));
+ } else if (!strlen(challenge)) {
+ ast_log(LOG_NOTICE, "No challenge provided for RSA authentication to %s\n", inet_ntoa(sin->sin_addr));
+ } else {
+ char sig[256];
+ struct ast_key *key;
+ key = ast_key_get(keyn, AST_KEY_PRIVATE);
+ if (!key) {
+ ast_log(LOG_NOTICE, "Unable to find private key '%s'\n", keyn);
+ } else {
+ if (ast_sign(key, challenge, sig)) {
+ ast_log(LOG_NOTICE, "Unable to sign challenge withy key\n");
+ res = -1;
+ } else {
+ MYSNPRINTF2 "rsasecret=%s;", sig);
+ res = 0;
+ }
+ }
+ }
+ }
+ /* Fall back */
+ if (res && secret && strlen(secret)) {
+ if (strstr(methods, "md5") && strlen(challenge)) {
+ struct MD5Context md5;
+ unsigned char digest[16];
+ MD5Init(&md5);
+ MD5Update(&md5, challenge, strlen(challenge));
+ MD5Update(&md5, secret, strlen(secret));
+ MD5Final(digest, &md5);
+ /* If they support md5, authenticate with it. */
+ MYSNPRINTF2 "md5secret=");
+ for (x=0;x<16;x++)
+ MYSNPRINTF2 "%2.2x", digest[x]);
+ MYSNPRINTF2 ";");
+ res = 0;
+ } else if (strstr(methods, "plaintext")) {
+ MYSNPRINTF2 "secret=%s;", secret);
+ res = 0;
+ } else
+ ast_log(LOG_NOTICE, "No way to send secret to peer '%s' (their methods: %s)\n", inet_ntoa(sin->sin_addr), methods);
+ }
+ return res;
+}
+
+static int authenticate_reply(struct chan_iax_pvt *p, struct sockaddr_in *sin, char *orequest, char *override, char *okey)
{
struct iax_peer *peer;
/* Start pessimistic */
@@ -2357,8 +2538,8 @@ static int authenticate_reply(struct chan_iax_pvt *p, struct sockaddr_in *sin, c
char methods[80] = "";
char requeststr[256] = "";
char *var, *value;
- int x;
- strncpy(request, orequest, sizeof(request));
+
+ strncpy(request, orequest, sizeof(request)-1);
var = strtok(request, ";");
while(var) {
value = strchr(var, '=');
@@ -2366,78 +2547,44 @@ static int authenticate_reply(struct chan_iax_pvt *p, struct sockaddr_in *sin, c
*value='\0';
value++;
if (!strcmp(var, "username"))
- strncpy(p->username, value, sizeof(p->username));
+ strncpy(p->username, value, sizeof(p->username)-1);
else if (!strcmp(var, "challenge"))
- strncpy(p->challenge, value, sizeof(p->challenge));
+ strncpy(p->challenge, value, sizeof(p->challenge)-1);
else if (!strcmp(var, "methods"))
- strncpy(methods, value, sizeof(methods));
+ strncpy(methods, value, sizeof(methods)-1);
else
ast_log(LOG_WARNING, "Unknown variable '%s' with value '%s'\n", var, value);
}
var = strtok(NULL, ";");
}
- if (override && strlen(override)) {
- /* If an override password has been specified, use it */
- res = 0;
- if (strstr(methods, "md5")) {
- struct MD5Context md5;
- unsigned char digest[16];
- MD5Init(&md5);
- MD5Update(&md5, p->challenge, strlen(p->challenge));
- MD5Update(&md5, override, strlen(override));
- MD5Final(digest, &md5);
- /* If they support md5, authenticate with it. */
- MYSNPRINTF "md5secret=");
- for (x=0;x<16;x++)
- MYSNPRINTF "%2.2x", digest[x]);
- MYSNPRINTF ";");
- } else if (strstr(methods, "plaintext")) {
- MYSNPRINTF "secret=%s;", override);
- } else
- res = -1;
- if (strlen(requeststr))
- requeststr[strlen(requeststr)-1] = '\0';
- if (!res)
- res = send_command(p, AST_FRAME_IAX, AST_IAX_COMMAND_AUTHREP, 0, requeststr, strlen(requeststr) + 1, -1);
- return res;
- }
- ast_pthread_mutex_lock(&peerl.lock);
- peer = peerl.peers;
- while(peer) {
- if ((!strlen(p->peer) || !strcmp(p->peer, peer->name))
+
+ /* Check for override RSA authentication first */
+ if ((override && strlen(override)) || (okey && strlen(okey))) {
+ /* Normal password authentication */
+ res = authenticate(p->challenge, override, okey, methods, requeststr, sizeof(requeststr), sin);
+ } else {
+ ast_pthread_mutex_lock(&peerl.lock);
+ peer = peerl.peers;
+ while(peer) {
+ if ((!strlen(p->peer) || !strcmp(p->peer, peer->name))
/* No peer specified at our end, or this is the peer */
&& (!strlen(peer->username) || (!strcmp(peer->username, p->username)))
/* No username specified in peer rule, or this is the right username */
&& (!peer->addr.sin_addr.s_addr || ((sin->sin_addr.s_addr & peer->mask.s_addr) == (peer->addr.sin_addr.s_addr & peer->mask.s_addr)))
/* No specified host, or this is our host */
) {
- /* We have a match, authenticate it. */
- res = 0;
- if (strstr(methods, "md5")) {
- struct MD5Context md5;
- unsigned char digest[16];
- MD5Init(&md5);
- MD5Update(&md5, p->challenge, strlen(p->challenge));
- MD5Update(&md5, peer->secret, strlen(peer->secret));
- MD5Final(digest, &md5);
- /* If they support md5, authenticate with it. */
- MYSNPRINTF "md5secret=");
- for (x=0;x<16;x++)
- MYSNPRINTF "%2.2x", digest[x]);
- MYSNPRINTF ";");
- } else if (strstr(methods, "plaintext")) {
- MYSNPRINTF "secret=%s;", peer->secret);
- } else
- res = -1;
- if (strlen(requeststr))
- requeststr[strlen(requeststr)-1] = '\0';
- if (!res)
- res = send_command(p, AST_FRAME_IAX, AST_IAX_COMMAND_AUTHREP, 0, requeststr, strlen(requeststr) + 1, -1);
- break;
+ res = authenticate(p->challenge, peer->secret, peer->outkey, methods, requeststr, sizeof(requeststr), sin);
+ if (!res)
+ break;
+ }
+ peer = peer->next;
}
- peer = peer->next;
+ ast_pthread_mutex_unlock(&peerl.lock);
}
- ast_pthread_mutex_unlock(&peerl.lock);
+ if (strlen(requeststr))
+ requeststr[strlen(requeststr)-1] = '\0';
+ if (!res)
+ res = send_command(p, AST_FRAME_IAX, AST_IAX_COMMAND_AUTHREP, 0, requeststr, strlen(requeststr) + 1, -1);
return res;
}
@@ -2464,7 +2611,7 @@ static int try_transfer(struct chan_iax_pvt *pvt, char *orequest)
if (!orequest)
return -1;
- strncpy(request, orequest, sizeof(request));
+ strncpy(request, orequest, sizeof(request)-1);
var = strtok(request, ";");
while(var) {
value = strchr(var, '=');
@@ -2472,7 +2619,7 @@ static int try_transfer(struct chan_iax_pvt *pvt, char *orequest)
*value='\0';
value++;
if (!strcmp(var, "remip"))
- strncpy(newip, value, sizeof(newip));
+ strncpy(newip, value, sizeof(newip)-1);
else if (!strcmp(var, "remport"))
newport = atoi(value);
else if (!strcmp(var, "remcall"))
@@ -2505,7 +2652,7 @@ static int complete_dpreply(struct chan_iax_pvt *pvt, char *orequest)
int x;
struct iax_dpcache *dp, *prev;
- strncpy(request, orequest, sizeof(request));
+ strncpy(request, orequest, sizeof(request)-1);
var = strtok(request, ";");
while(var) {
value = strchr(var, '=');
@@ -2513,7 +2660,7 @@ static int complete_dpreply(struct chan_iax_pvt *pvt, char *orequest)
*value='\0';
value++;
if (!strcmp(var, "number"))
- strncpy(exten, value, sizeof(exten));
+ strncpy(exten, value, sizeof(exten)-1);
else if (!strcmp(var, "status")) {
if (!strcasecmp(value, "exists"))
status = CACHE_FLAG_EXISTS;
@@ -2571,7 +2718,7 @@ static int complete_transfer(int callno, char *orequest)
if (!orequest)
return -1;
- strncpy(request, orequest, sizeof(request));
+ strncpy(request, orequest, sizeof(request)-1);
var = strtok(request, ";");
while(var) {
value = strchr(var, '=');
@@ -2636,7 +2783,7 @@ static int iax_ack_registry(char *orequest, struct sockaddr_in *sin)
if (!orequest)
return -1;
- strncpy(request, orequest, sizeof(request));
+ strncpy(request, orequest, sizeof(request)-1);
var = strtok(request, ";");
while(var) {
value = strchr(var, '=');
@@ -2644,9 +2791,9 @@ static int iax_ack_registry(char *orequest, struct sockaddr_in *sin)
*value='\0';
value++;
if (!strcmp(var, "yourip"))
- strncpy(ourip, value, sizeof(ourip));
+ strncpy(ourip, value, sizeof(ourip)-1);
else if (!strcmp(var, "peer"))
- strncpy(peer, value, sizeof(peer));
+ strncpy(peer, value, sizeof(peer)-1);
else if (!strcmp(var, "yourport"))
ourport = atoi(value);
else if (!strcmp(var, "refresh"))
@@ -2701,7 +2848,7 @@ static int iax_register(char *value, int lineno)
struct hostent *hp;
if (!value)
return -1;
- strncpy(copy, value, sizeof(copy));
+ strncpy(copy, value, sizeof(copy)-1);
username = strtok(copy, "@");
hostname = strtok(NULL, "@");
if (!hostname) {
@@ -2725,9 +2872,9 @@ static int iax_register(char *value, int lineno)
reg = malloc(sizeof(struct iax_registry));
if (reg) {
memset(reg, 0, sizeof(struct iax_registry));
- strncpy(reg->username, username, sizeof(reg->username));
+ strncpy(reg->username, username, sizeof(reg->username)-1);
if (secret)
- strncpy(reg->secret, secret, sizeof(reg->secret));
+ strncpy(reg->secret, secret, sizeof(reg->secret)-1);
reg->expire = -1;
reg->refresh = AST_DEFAULT_REG_EXPIRE;
reg->addr.sin_family = AF_INET;
@@ -2795,7 +2942,7 @@ static int registry_authrequest(char *name, int callno)
for (p = peerl.peers;p;p = p->next) {
if (!strcasecmp(name, p->name)) {
MYSNPRINTF "methods=%s;", p->methods);
- if (strstr(p->methods, "md5")) {
+ if (strstr(p->methods, "md5") || strstr(p->methods, "rsa")) {
/* Build the challenge */
snprintf(p->challenge, sizeof(p->challenge), "%d", rand());
MYSNPRINTF "challenge=%s;", p->challenge);
@@ -2819,12 +2966,12 @@ static int registry_rerequest(char *orequest, int callno, struct sockaddr_in *si
char methods[256] = "";
char challenge[256] = "";
char *var, *value;
- int x;
+ int res;
if (!orequest)
return -1;
- strncpy(request, orequest, sizeof(request));
+ strncpy(request, orequest, sizeof(request)-1);
var = strtok(request, ";");
while(var) {
value = strchr(var, '=');
@@ -2832,11 +2979,11 @@ static int registry_rerequest(char *orequest, int callno, struct sockaddr_in *si
*value='\0';
value++;
if (!strcmp(var, "methods"))
- strncpy(methods, value, sizeof(methods));
+ strncpy(methods, value, sizeof(methods)-1);
else if (!strcmp(var, "peer"))
- strncpy(peer, value, sizeof(peer));
+ strncpy(peer, value, sizeof(peer)-1);
else if (!strcmp(var, "challenge"))
- strncpy(challenge, value, sizeof(challenge));
+ strncpy(challenge, value, sizeof(challenge)-1);
else
ast_log(LOG_WARNING, "Unknown variable '%s' with value '%s'\n", var, value);
}
@@ -2855,26 +3002,18 @@ static int registry_rerequest(char *orequest, int callno, struct sockaddr_in *si
return -1;
}
MYSNPRINTF "peer=%s;refresh=%d;", reg->username, reg->refresh);
- if (strstr(methods, "md5")) {
- struct MD5Context md5;
- unsigned char digest[16];
- MD5Init(&md5);
- MD5Update(&md5, challenge, strlen(challenge));
- MD5Update(&md5, reg->secret, strlen(reg->secret));
- MD5Final(digest, &md5);
- /* If they support md5, authenticate with it. */
- MYSNPRINTF "md5secret=");
- for (x=0;x<16;x++)
- MYSNPRINTF "%2.2x", digest[x]);
- MYSNPRINTF ";");
- } else if (strstr(methods, "plaintext")) {
- MYSNPRINTF "secret=%s;", reg->secret);
- } else {
- ast_log(LOG_WARNING, "No valid methods suggested by peer '%s'\n", inet_ntoa(sin->sin_addr));
+ if (reg->secret[0] == '[') {
+ char tmpkey[256];
+ strncpy(tmpkey, reg->secret + 1, sizeof(tmpkey) - 1);
+ tmpkey[strlen(tmpkey) - 1] = '\0';
+ res = authenticate(challenge, NULL, tmpkey, methods, requeststr, sizeof(requeststr), sin);
+ } else
+ res = authenticate(challenge, reg->secret, NULL, methods, requeststr, sizeof(requeststr), sin);
+ if (!res) {
+ reg->regstate = REG_STATE_AUTHSENT;
+ return send_command(iaxs[callno], AST_FRAME_IAX, AST_IAX_COMMAND_REGREQ, 0, requeststr, strlen(requeststr) + 1, -1);
+ } else
return -1;
- }
- reg->regstate = REG_STATE_AUTHSENT;
- return send_command(iaxs[callno], AST_FRAME_IAX, AST_IAX_COMMAND_REGREQ, 0, requeststr, strlen(requeststr) + 1, -1);
}
reg = reg->next;
}
@@ -3102,7 +3241,7 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s'\n", inet_ntoa(sin.sin_addr), f.data);
break;
}
- if (!strlen(iaxs[fr.callno]->secret)) {
+ if (!strlen(iaxs[fr.callno]->secret) && !strlen(iaxs[fr.callno]->inkeys)) {
if (strcmp(iaxs[fr.callno]->exten, "TBD") && !ast_exists_extension(NULL, iaxs[fr.callno]->context, iaxs[fr.callno]->exten, 1, iaxs[fr.callno]->callerid)) {
send_command_final(iaxs[fr.callno], AST_FRAME_IAX, AST_IAX_COMMAND_REJECT, 0, "No such context/extension", strlen("No such context/extension"), -1);
ast_log(LOG_NOTICE, "Rejected connect attempt from %s, request '%s@%s' does not exist\n", inet_ntoa(sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context);
@@ -3207,6 +3346,11 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
iaxs[fr.callno]->owner->nativeformats = iaxs[fr.callno]->peerformat;
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Format for call is %d\n", iaxs[fr.callno]->owner->nativeformats);
+ /* Setup read/write formats properly. */
+ if (iaxs[fr.callno]->owner->writeformat)
+ ast_set_write_format(iaxs[fr.callno]->owner, iaxs[fr.callno]->owner->writeformat);
+ if (iaxs[fr.callno]->owner->readformat)
+ ast_set_read_format(iaxs[fr.callno]->owner, iaxs[fr.callno]->owner->readformat);
}
}
ast_pthread_mutex_lock(&dpcache_lock);
@@ -3245,7 +3389,7 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
break;
}
((char *)f.data)[f.datalen] = '\0';
- if (authenticate_reply(iaxs[fr.callno], &iaxs[fr.callno]->addr, (char *)f.data, iaxs[fr.callno]->secret)) {
+ if (authenticate_reply(iaxs[fr.callno], &iaxs[fr.callno]->addr, (char *)f.data, iaxs[fr.callno]->secret, iaxs[fr.callno]->outkey)) {
ast_log(LOG_WARNING,
"I don't know how to authenticate %s to %s\n",
f.data, inet_ntoa(iaxs[fr.callno]->addr.sin_addr));
@@ -3310,7 +3454,7 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
((char *)f.data)[f.datalen] = '\0';
if (iaxs[fr.callno]->state & IAX_STATE_TBD) {
iaxs[fr.callno]->state &= ~IAX_STATE_TBD;
- strncpy(iaxs[fr.callno]->exten, (char *)f.data, sizeof(iaxs[fr.callno]->exten));
+ strncpy(iaxs[fr.callno]->exten, (char *)f.data, sizeof(iaxs[fr.callno]->exten)-1);
if (!ast_exists_extension(NULL, iaxs[fr.callno]->context, iaxs[fr.callno]->exten, 1, iaxs[fr.callno]->callerid)) {
send_command_final(iaxs[fr.callno], AST_FRAME_IAX, AST_IAX_COMMAND_REJECT, 0, "No such context/extension", strlen("No such context/extension"), -1);
ast_log(LOG_NOTICE, "Rejected dial attempt from %s, request '%s@%s' does not exist\n", inet_ntoa(sin.sin_addr), iaxs[fr.callno]->exten, iaxs[fr.callno]->context);
@@ -3343,7 +3487,7 @@ static int socket_read(int *id, int fd, short events, void *cbdata)
send_command_final(iaxs[fr.callno], AST_FRAME_IAX, AST_IAX_COMMAND_REGREJ, 0, "Registration Refused", strlen("Registration Refused"), -1);
break;
}
- if (!strlen(iaxs[fr.callno]->secret) || (iaxs[fr.callno]->state & IAX_STATE_AUTHENTICATED)) {
+ if ((!strlen(iaxs[fr.callno]->secret) && !strlen(iaxs[fr.callno]->inkeys)) || (iaxs[fr.callno]->state & IAX_STATE_AUTHENTICATED)) {
if (update_registry(iaxs[fr.callno]->peer, &sin, fr.callno))
ast_log(LOG_WARNING, "Registry error\n");
break;
@@ -3552,7 +3696,7 @@ static struct ast_channel *iax_request(char *type, int format, void *data)
char *st;
struct ast_channel *c;
int capability = iax_capability;
- strncpy(s, (char *)data, sizeof(s));
+ strncpy(s, (char *)data, sizeof(s)-1);
strtok(s, "/");
strtok(s, "@");
st = strtok(NULL, "@");
@@ -3658,7 +3802,7 @@ static struct iax_context *build_context(char *context)
{
struct iax_context *con = malloc(sizeof(struct iax_context));
if (con) {
- strncpy(con->context, context, sizeof(con->context));
+ strncpy(con->context, context, sizeof(con->context)-1);
con->next = NULL;
}
return con;
@@ -3742,16 +3886,16 @@ static struct iax_peer *build_peer(char *name, struct ast_variable *v)
}
if (peer) {
if (!found) {
- strncpy(peer->name, name, sizeof(peer->name));
+ strncpy(peer->name, name, sizeof(peer->name)-1);
peer->addr.sin_port = htons(AST_DEFAULT_IAX_PORTNO);
peer->expirey = expirey;
}
peer->capability = iax_capability;
while(v) {
if (!strcasecmp(v->name, "secret"))
- strncpy(peer->secret, v->value, sizeof(peer->secret));
+ strncpy(peer->secret, v->value, sizeof(peer->secret)-1);
else if (!strcasecmp(v->name, "auth"))
- strncpy(peer->methods, v->value, sizeof(peer->methods));
+ strncpy(peer->methods, v->value, sizeof(peer->methods)-1);
else if (!strcasecmp(v->name, "host")) {
if (!strcasecmp(v->value, "dynamic")) {
/* They'll register with us */
@@ -3803,7 +3947,7 @@ static struct iax_peer *build_peer(char *name, struct ast_variable *v)
else
peer->addr.sin_port = htons(atoi(v->value));
} else if (!strcasecmp(v->name, "username")) {
- strncpy(peer->username, v->value, sizeof(peer->username));
+ strncpy(peer->username, v->value, sizeof(peer->username)-1);
} else if (!strcasecmp(v->name, "allow")) {
format = ast_getformatbyname(v->value);
if (format < 1)
@@ -3817,8 +3961,12 @@ static struct iax_peer *build_peer(char *name, struct ast_variable *v)
else
peer->capability &= ~format;
} else if (!strcasecmp(v->name, "callerid")) {
- strncpy(peer->callerid, v->value, sizeof(peer->callerid));
+ strncpy(peer->callerid, v->value, sizeof(peer->callerid)-1);
peer->hascallerid=1;
+ } else if (!strcasecmp(v->name, "inkeys")) {
+ strncpy(peer->inkeys, v->value, sizeof(peer->inkeys));
+ } else if (!strcasecmp(v->name, "outkey")) {
+ strncpy(peer->outkey, v->value, sizeof(peer->outkey));
}
v=v->next;
@@ -3835,10 +3983,11 @@ static struct iax_user *build_user(char *name, struct ast_variable *v)
struct iax_user *user;
struct iax_context *con, *conl = NULL;
struct iax_ha *ha, *hal = NULL;
+ int format;
user = (struct iax_user *)malloc(sizeof(struct iax_user));
if (user) {
memset(user, 0, sizeof(struct iax_user));
- strncpy(user->name, name, sizeof(user->name));
+ strncpy(user->name, name, sizeof(user->name)-1);
while(v) {
if (!strcasecmp(v->name, "context")) {
con = build_context(v->value);
@@ -3860,16 +4009,37 @@ static struct iax_user *build_user(char *name, struct ast_variable *v)
hal = ha;
}
} else if (!strcasecmp(v->name, "auth")) {
- strncpy(user->methods, v->value, sizeof(user->methods));
+ strncpy(user->methods, v->value, sizeof(user->methods)-1);
} else if (!strcasecmp(v->name, "secret")) {
- strncpy(user->secret, v->value, sizeof(user->secret));
+ strncpy(user->secret, v->value, sizeof(user->secret)-1);
} else if (!strcasecmp(v->name, "callerid")) {
- strncpy(user->callerid, v->value, sizeof(user->callerid));
+ strncpy(user->callerid, v->value, sizeof(user->callerid)-1);
user->hascallerid=1;
+ } else if (!strcasecmp(v->name, "accountcode")) {
+ strncpy(user->accountcode, v->value, sizeof(user->accountcode)-1);
+ } else if (!strcasecmp(v->name, "amaflags")) {
+ format = ast_cdr_amaflags2int(v->value);
+ if (format < 0) {
+ ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
+ } else {
+ user->amaflags = format;
+ }
+ } else if (!strcasecmp(v->name, "inkeys")) {
+ strncpy(user->inkeys, v->value, sizeof(user->inkeys));
}
v = v->next;
}
}
+ if (!strlen(user->methods)) {
+ if (strlen(user->secret)) {
+ strncpy(user->methods, "md5,plaintext", sizeof(user->methods) - 1);
+ if (strlen(user->inkeys))
+ strncat(user->methods, ",rsa", sizeof(user->methods) - 1);
+ } else if (strlen(user->inkeys)) {
+ strncpy(user->methods, "rsa", sizeof(user->methods) - 1);
+ } else
+ strncpy(user->methods, "md5,plaintext", sizeof(user->methods) -1);
+ }
return user;
}
@@ -4012,6 +4182,15 @@ int set_config(char *config_file, struct sockaddr_in* sin){
tos = 0;
else
ast_log(LOG_WARNING, "Invalid tos value at line %d, should be 'lowdelay', 'throughput', 'reliability', 'mincost', or 'none'\n", v->lineno);
+ } else if (!strcasecmp(v->name, "accountcode")) {
+ strncpy(accountcode, v->value, sizeof(accountcode)-1);
+ } else if (!strcasecmp(v->name, "amaflags")) {
+ format = ast_cdr_amaflags2int(v->value);
+ if (format < 0) {
+ ast_log(LOG_WARNING, "Invalid AMA Flags: %s at line %d\n", v->value, v->lineno);
+ } else {
+ amaflags = format;
+ }
}
v = v->next;
}
@@ -4055,6 +4234,8 @@ static int reload_config(void)
char *config = "iax.conf";
struct iax_registry *reg;
struct sockaddr_in dead_sin;
+ strncpy(accountcode, "", sizeof(accountcode)-1);
+ amaflags = 0;
srand(time(NULL));
delete_users();
set_config(config,&dead_sin);
@@ -4087,7 +4268,7 @@ static int cache_get_callno(char *data)
return x;
}
/* No match found, we need to create a new one */
- strncpy(st, data, sizeof(st));
+ strncpy(st, data, sizeof(st)-1);
/* Grab the host */
s = strchr(st, '/');
if (s) {
@@ -4119,7 +4300,7 @@ static int cache_get_callno(char *data)
ast_pthread_mutex_lock(&iaxs_lock);
callno = find_callno(-1, -1, &sin, NEW_FORCE);
ast_pthread_mutex_unlock(&iaxs_lock);
- strncpy(iaxs[callno]->dproot, data, sizeof(iaxs[callno]->dproot));
+ strncpy(iaxs[callno]->dproot, data, sizeof(iaxs[callno]->dproot)-1);
if (callno < 0) {
ast_log(LOG_WARNING, "Unable to create call\n");
return -1;
@@ -4138,7 +4319,7 @@ static int cache_get_callno(char *data)
requeststr[strlen(requeststr) -1 ] = '\0';
/* Keep password handy */
if (password)
- strncpy(iaxs[callno]->secret, password, sizeof(iaxs[callno]->secret));
+ strncpy(iaxs[callno]->secret, password, sizeof(iaxs[callno]->secret)-1);
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Calling TBD using options '%s'\n", requeststr);
/* Start the call going */
@@ -4153,7 +4334,7 @@ static struct iax_dpcache *find_cache(struct ast_channel *chan, char *data, char
int x;
int com[2];
int timeout;
- int old;
+ int old=0;
int outfd;
int abort;
int callno;
@@ -4198,8 +4379,8 @@ static struct iax_dpcache *find_cache(struct ast_channel *chan, char *data, char
return NULL;
memset(dp, 0, sizeof(struct iax_dpcache));
dp->callno = -1;
- strncpy(dp->peercontext, data, sizeof(dp->peercontext));
- strncpy(dp->exten, exten, sizeof(dp->exten));
+ strncpy(dp->peercontext, data, sizeof(dp->peercontext)-1);
+ strncpy(dp->exten, exten, sizeof(dp->exten)-1);
gettimeofday(&dp->expirey, NULL);
dp->orig = dp->expirey;
/* Expires in 30 mins by default */
@@ -4238,10 +4419,11 @@ static struct iax_dpcache *find_cache(struct ast_channel *chan, char *data, char
/* Temporarily unlock */
ast_pthread_mutex_unlock(&dpcache_lock);
/* Defer any dtmf */
- old = ast_channel_defer_dtmf(chan);
+ if (chan)
+ old = ast_channel_defer_dtmf(chan);
abort = 0;
while(timeout) {
- c = ast_waitfor_nandfds(&chan, 1, &com[0], 1, NULL, &outfd, &timeout);
+ c = ast_waitfor_nandfds(&chan, chan ? 1 : 0, &com[0], 1, NULL, &outfd, &timeout);
if (outfd > -1) {
break;
}
@@ -4266,7 +4448,7 @@ static struct iax_dpcache *find_cache(struct ast_channel *chan, char *data, char
if (abort) {
/* Don't interpret anything, just abort. Not sure what th epoint
of undeferring dtmf on a hung up channel is but hey whatever */
- if (!old)
+ if (!old && chan)
ast_channel_undefer_dtmf(chan);
return NULL;
}
@@ -4286,7 +4468,7 @@ static struct iax_dpcache *find_cache(struct ast_channel *chan, char *data, char
}
}
/* Our caller will obtain the rest */
- if (!old)
+ if (!old && chan)
ast_channel_undefer_dtmf(chan);
}
return dp;
@@ -4352,7 +4534,7 @@ static int iax_exec(struct ast_channel *chan, char *context, char *exten, int pr
dp = find_cache(chan, data, context, exten, priority);
if (dp) {
if (dp->flags & CACHE_FLAG_EXISTS) {
- strncpy(odata, data, sizeof(odata));
+ strncpy(odata, data, sizeof(odata)-1);
ncontext = strchr(odata, '/');
if (ncontext) {
*ncontext = '\0';
@@ -4443,7 +4625,7 @@ int load_module(void)
return -1;
}
if (bind(netsocket,(struct sockaddr *)&sin, sizeof(sin))) {
- ast_log(LOG_ERROR, "Unable to bind to %s port %d\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+ ast_log(LOG_ERROR, "Unable to bind to %s port %d: %s\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), strerror(errno));
return -1;
}