diff options
author | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2004-10-08 23:20:02 +0000 |
---|---|---|
committer | markster <markster@f38db490-d61c-443f-a65b-d21fe96a405b> | 2004-10-08 23:20:02 +0000 |
commit | accdda1a95ed7f3ba99e86990b47aba5edb8eee8 (patch) | |
tree | c07c2f429fd4e51369a9dbf71dc3d209bef4cded /channels/chan_iax2.c | |
parent | c930a4479cb2c64fb6478a71eccd1254c0850bc2 (diff) |
IAX2 authentication improvements
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@3954 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels/chan_iax2.c')
-rwxr-xr-x | channels/chan_iax2.c | 123 |
1 files changed, 96 insertions, 27 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 7158f5154..811ffde28 100755 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -186,6 +186,7 @@ struct iax2_context { struct iax2_user { char name[80]; char secret[80]; + char dbsecret[80]; int authmethods; char accountcode[20]; char inkeys[80]; /* Key(s) this user can use to authenticate to us */ @@ -209,6 +210,7 @@ struct iax2_peer { char name[80]; char username[80]; char secret[80]; + char dbsecret[80]; char outkey[80]; /* What key we use to talk to this peer */ char context[AST_MAX_EXTENSION]; /* For transfers only */ char regexten[AST_MAX_EXTENSION]; /* Extension to register (if regcontext is used) */ @@ -2123,8 +2125,6 @@ static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, i *capability = p->capability; if (username) strncpy(username, p->username, usernlen); - if (secret) - strncpy(secret, p->secret, seclen); /* safe */ if (p->addr.sin_addr.s_addr) { sin->sin_addr = p->addr.sin_addr; sin->sin_port = p->addr.sin_port; @@ -2136,6 +2136,26 @@ static int create_addr(struct sockaddr_in *sin, int *capability, int *sendani, i *notransfer=p->notransfer; if (usejitterbuf) *usejitterbuf=p->usejitterbuf; + if (secret) { + if (!ast_strlen_zero(p->dbsecret)) { + char *family, *key=NULL; + family = ast_strdupa(p->dbsecret); + if (family) { + key = strchr(family, '/'); + if (key) { + *key = '\0'; + key++; + } + } + if (!family || !key || ast_db_get(family, key, secret, seclen)) { + ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", p->dbsecret); + if (p->temponly) + destroy_peer(p); + p = NULL; + } + } else + strncpy(secret, p->secret, seclen); /* safe */ + } } else { if (p->temponly) destroy_peer(p); @@ -3656,8 +3676,6 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies else strncpy(iaxs[callno]->context, context, sizeof(iaxs[callno]->context)-1); } - /* Copy the 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) - 1); /* And the permitted authentication methods */ @@ -3683,6 +3701,26 @@ static int check_access(int callno, struct sockaddr_in *sin, struct iax_ies *ies strncpy(iaxs[callno]->language, user->language, sizeof(iaxs[callno]->language)-1); iaxs[callno]->notransfer = user->notransfer; iaxs[callno]->usejitterbuf = user->usejitterbuf; + /* Keep this check last */ + if (!ast_strlen_zero(user->dbsecret)) { + char *family, *key=NULL; + family = ast_strdupa(user->dbsecret); + if (family) { + key = strchr(family, '/'); + if (key) { + *key = '\0'; + key++; + } + } + if (!family || !key || ast_db_get(family, key, iaxs[callno]->secret, sizeof(iaxs[callno]->secret))) { + ast_log(LOG_WARNING, "Unable to retrieve database password for family/key '%s'!\n", user->dbsecret); + if (user->temponly) { + destroy_user(user); + user = NULL; + } + } + } else + strncpy(iaxs[callno]->secret, user->secret, sizeof(iaxs[callno]->secret) - 1); res = 0; } iaxs[callno]->trunk = iax2_getpeertrunk(*sin); @@ -3758,15 +3796,23 @@ static int authenticate_verify(struct chan_iax2_pvt *p, struct iax_ies *ies) } else if (p->authmethods & IAX_AUTH_MD5) { struct MD5Context md5; unsigned char digest[16]; - MD5Init(&md5); - MD5Update(&md5, p->challenge, strlen(p->challenge)); - MD5Update(&md5, p->secret, strlen(p->secret)); - MD5Final(digest, &md5); - /* If they support md5, authenticate with it. */ - for (x=0;x<16;x++) - sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ - if (!strcasecmp(requeststr, md5secret)) - res = 0; + char *tmppw, *stringp; + + tmppw = ast_strdupa(p->secret); + stringp = tmppw; + while((tmppw = strsep(&stringp, ";"))) { + MD5Init(&md5); + MD5Update(&md5, p->challenge, strlen(p->challenge)); + MD5Update(&md5, tmppw, strlen(tmppw)); + MD5Final(digest, &md5); + /* If they support md5, authenticate with it. */ + for (x=0;x<16;x++) + sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ + if (!strcasecmp(requeststr, md5secret)) { + res = 0; + break; + } + } } else if (p->authmethods & IAX_AUTH_PLAINTEXT) { if (!strcmp(secret, p->secret)) res = 0; @@ -3881,20 +3927,30 @@ static int register_verify(int callno, struct sockaddr_in *sin, struct iax_ies * } else if (!ast_strlen_zero(md5secret) && (p->authmethods & IAX_AUTH_MD5) && !ast_strlen_zero(iaxs[callno]->challenge)) { struct MD5Context md5; unsigned char digest[16]; - MD5Init(&md5); - MD5Update(&md5, iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); - MD5Update(&md5, p->secret, strlen(p->secret)); - MD5Final(digest, &md5); - for (x=0;x<16;x++) - sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ - if (strcasecmp(requeststr, md5secret)) { + char *tmppw, *stringp; + + tmppw = ast_strdupa(p->secret); + stringp = tmppw; + while((tmppw = strsep(&stringp, ";"))) { + printf("Trying '%s'!\n", tmppw); + MD5Init(&md5); + MD5Update(&md5, iaxs[callno]->challenge, strlen(iaxs[callno]->challenge)); + MD5Update(&md5, tmppw, strlen(tmppw)); + MD5Final(digest, &md5); + for (x=0;x<16;x++) + sprintf(requeststr + (x << 1), "%2.2x", digest[x]); /* safe */ + if (!strcasecmp(requeststr, md5secret)) + break; + } + if (tmppw) { + iaxs[callno]->state |= IAX_STATE_AUTHENTICATED; + } else { if (authdebug) ast_log(LOG_NOTICE, "Host %s failed MD5 authentication for '%s' (%s != %s)\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin->sin_addr), p->name, requeststr, md5secret); if (p->temponly) destroy_peer(p); return -1; - } else - iaxs[callno]->state |= IAX_STATE_AUTHENTICATED; + } } else if (!ast_strlen_zero(md5secret) || !ast_strlen_zero(secret)) { if (authdebug) ast_log(LOG_NOTICE, "Inappropriate authentication received\n"); @@ -6345,6 +6401,7 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v) if (peer) { peer->messagedetail = globalmessagedetail; peer->usejitterbuf = globalusejitterbuf; + peer->secret[0] = '\0'; if (!found) { strncpy(peer->name, name, sizeof(peer->name)-1); peer->addr.sin_port = htons(IAX_DEFAULT_PORTNO); @@ -6352,10 +6409,16 @@ static struct iax2_peer *build_peer(const char *name, struct ast_variable *v) } peer->capability = iax2_capability; while(v) { - if (!strcasecmp(v->name, "secret")) - strncpy(peer->secret, v->value, sizeof(peer->secret)-1); - else if (!strcasecmp(v->name, "mailbox")) + if (!strcasecmp(v->name, "secret")) { + if (!ast_strlen_zero(peer->secret)) { + strncpy(peer->secret + strlen(peer->secret), ";", sizeof(peer->secret)-strlen(peer->secret) - 1); + strncpy(peer->secret + strlen(peer->secret), v->value, sizeof(peer->secret)-strlen(peer->secret) - 1); + } else + strncpy(peer->secret, v->value, sizeof(peer->secret)-1); + } else if (!strcasecmp(v->name, "mailbox")) { strncpy(peer->mailbox, v->value, sizeof(peer->mailbox) - 1); + } else if (!strcasecmp(v->name, "dbsecret")) + strncpy(peer->dbsecret, v->value, sizeof(peer->dbsecret)-1); else if (!strcasecmp(v->name, "mailboxdetail")) peer->messagedetail = ast_true(v->value); else if (!strcasecmp(v->name, "trunk")) { @@ -6552,15 +6615,21 @@ static struct iax2_user *build_user(const char *name, struct ast_variable *v) user->notransfer = ast_true(v->value); } else if (!strcasecmp(v->name, "jitterbuffer")) { user->usejitterbuf = ast_true(v->value); + } else if (!strcasecmp(v->name, "dbsecret")) { + strncpy(user->dbsecret, v->value, sizeof(user->dbsecret)-1); } else if (!strcasecmp(v->name, "secret")) { - strncpy(user->secret, v->value, sizeof(user->secret)-1); + if (!ast_strlen_zero(user->secret)) { + strncpy(user->secret + strlen(user->secret), ";", sizeof(user->secret) - strlen(user->secret) - 1); + strncpy(user->secret + strlen(user->secret), v->value, sizeof(user->secret) - strlen(user->secret) - 1); + } else + strncpy(user->secret, v->value, sizeof(user->secret)-1); } else if (!strcasecmp(v->name, "callerid")) { ast_callerid_split(v->value, user->cid_name, sizeof(user->cid_name), user->cid_num, sizeof(user->cid_num)); user->hascallerid=1; } else if (!strcasecmp(v->name, "accountcode")) { strncpy(user->accountcode, v->value, sizeof(user->accountcode)-1); } else if (!strcasecmp(v->name, "language")) { - strncpy(user->language, v->value, sizeof(user->language)-1); + strncpy(user->language, v->value, sizeof(user->language)-1); } else if (!strcasecmp(v->name, "amaflags")) { format = ast_cdr_amaflags2int(v->value); if (format < 0) { |