From 1c1631cebfefc3460fc69a9bd349ed66c79262cd Mon Sep 17 00:00:00 2001 From: Brad Watkins Date: Fri, 17 Dec 2010 17:26:31 +0000 Subject: [PATCH] Fix parsing of mwi => lines in sip.conf Reworking parsing of mwi => lines to resolve a segfault. Also add a set of unit tests for the function that does the parsing. (closes issue #18350) Reported by: gbour Tested by: Marquis, gbour Review: https://reviewboard.asterisk.org/r/1053/ git-svn-id: https://origsvn.digium.com/svn/asterisk/branches/1.8@298773 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- channels/chan_sip.c | 184 +++++++++++++++++++++++++++++++++++++--- configs/sip.conf.sample | 7 +- 2 files changed, 175 insertions(+), 16 deletions(-) diff --git a/channels/chan_sip.c b/channels/chan_sip.c index c9b0592586..6043e468be 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -7571,36 +7571,39 @@ static int sip_subscribe_mwi(const char *value, int lineno) int portnum = 0; enum sip_transport transport = SIP_TRANSPORT_UDP; char buf[256] = ""; - char *username = NULL, *hostname = NULL, *secret = NULL, *authuser = NULL, *porta = NULL, *mailbox = NULL; - + char *username = NULL, *hostname = NULL, *secret = NULL, *authuser = NULL, *porta = NULL, *mailbox = NULL, *at = NULL; + if (!value) { return -1; } - + ast_copy_string(buf, value, sizeof(buf)); - sip_parse_host(buf, lineno, &username, &portnum, &transport); - - if ((hostname = strrchr(username, '@'))) { + if (!(at = strstr(buf, "@"))) { + return -1; + } + + if ((hostname = strrchr(buf, '@'))) { *hostname++ = '\0'; + username = buf; } - + if ((secret = strchr(username, ':'))) { *secret++ = '\0'; if ((authuser = strchr(secret, ':'))) { *authuser++ = '\0'; } } - + if ((mailbox = strchr(hostname, '/'))) { *mailbox++ = '\0'; } if (ast_strlen_zero(username) || ast_strlen_zero(hostname) || ast_strlen_zero(mailbox)) { - ast_log(LOG_WARNING, "Format for MWI subscription is user[:secret[:authuser]]@host[:port][/mailbox] at line %d\n", lineno); + ast_log(LOG_WARNING, "Format for MWI subscription is user[:secret[:authuser]]@host[:port]/mailbox at line %d\n", lineno); return -1; } - + if ((porta = strchr(hostname, ':'))) { *porta++ = '\0'; if (!(portnum = atoi(porta))) { @@ -7608,11 +7611,11 @@ static int sip_subscribe_mwi(const char *value, int lineno) return -1; } } - + if (!(mwi = ast_calloc_with_stringfields(1, struct sip_subscription_mwi, 256))) { return -1; } - + ASTOBJ_INIT(mwi); ast_string_field_set(mwi, username, username); if (secret) { @@ -7626,10 +7629,10 @@ static int sip_subscribe_mwi(const char *value, int lineno) mwi->resub = -1; mwi->portno = portnum; mwi->transport = transport; - + ASTOBJ_CONTAINER_LINK(&submwil, mwi); ASTOBJ_UNREF(mwi, sip_subscribe_mwi_destroy); - + return 0; } @@ -28291,6 +28294,157 @@ static void sip_unregister_tests(void) } #ifdef TEST_FRAMEWORK +AST_TEST_DEFINE(test_sip_mwi_subscribe_parse) +{ + int found = 0; + enum ast_test_result_state res = AST_TEST_PASS; + const char *mwi1 = "1234@mysipprovider.com/1234"; + const char *mwi2 = "1234:password@mysipprovider.com/1234"; + const char *mwi3 = "1234:password@mysipprovider.com:5061/1234"; + const char *mwi4 = "1234:password:authuser@mysipprovider.com/1234"; + const char *mwi5 = "1234:password:authuser@mysipprovider.com:5061/1234"; + const char *mwi6 = "1234:password"; + + switch (cmd) { + case TEST_INIT: + info->name = "sip_mwi_subscribe_parse_test"; + info->category = "/channels/chan_sip/"; + info->summary = "SIP MWI subscribe line parse unit test"; + info->description = + "Tests the parsing of mwi subscription lines (e.g., mwi => from sip.conf)"; + return AST_TEST_NOT_RUN; + case TEST_EXECUTE: + break; + } + + if (sip_subscribe_mwi(mwi1, 1)) { + res = AST_TEST_FAIL; + } else { + found = 0; + res = AST_TEST_FAIL; + ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do { + ASTOBJ_WRLOCK(iterator); + if ( + !strcmp(iterator->hostname, "mysipprovider.com") && + !strcmp(iterator->username, "1234") && + !strcmp(iterator->secret, "") && + !strcmp(iterator->authuser, "") && + !strcmp(iterator->mailbox, "1234") && + iterator->portno == 0) { + found = 1; + res = AST_TEST_PASS; + } + ASTOBJ_UNLOCK(iterator); + } while(0)); + if (!found) { + ast_test_status_update(test, "sip_subscribe_mwi test 1 failed\n"); + } + } + + if (sip_subscribe_mwi(mwi2, 1)) { + res = AST_TEST_FAIL; + } else { + found = 0; + res = AST_TEST_FAIL; + ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do { + ASTOBJ_WRLOCK(iterator); + if ( + !strcmp(iterator->hostname, "mysipprovider.com") && + !strcmp(iterator->username, "1234") && + !strcmp(iterator->secret, "password") && + !strcmp(iterator->authuser, "") && + !strcmp(iterator->mailbox, "1234") && + iterator->portno == 0) { + found = 1; + res = AST_TEST_PASS; + } + ASTOBJ_UNLOCK(iterator); + } while(0)); + if (!found) { + ast_test_status_update(test, "sip_subscribe_mwi test 2 failed\n"); + } + } + + if (sip_subscribe_mwi(mwi3, 1)) { + res = AST_TEST_FAIL; + } else { + found = 0; + res = AST_TEST_FAIL; + ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do { + ASTOBJ_WRLOCK(iterator); + if ( + !strcmp(iterator->hostname, "mysipprovider.com") && + !strcmp(iterator->username, "1234") && + !strcmp(iterator->secret, "password") && + !strcmp(iterator->authuser, "") && + !strcmp(iterator->mailbox, "1234") && + iterator->portno == 5061) { + found = 1; + res = AST_TEST_PASS; + } + ASTOBJ_UNLOCK(iterator); + } while(0)); + if (!found) { + ast_test_status_update(test, "sip_subscribe_mwi test 3 failed\n"); + } + } + + if (sip_subscribe_mwi(mwi4, 1)) { + res = AST_TEST_FAIL; + } else { + found = 0; + res = AST_TEST_FAIL; + ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do { + ASTOBJ_WRLOCK(iterator); + if ( + !strcmp(iterator->hostname, "mysipprovider.com") && + !strcmp(iterator->username, "1234") && + !strcmp(iterator->secret, "password") && + !strcmp(iterator->authuser, "authuser") && + !strcmp(iterator->mailbox, "1234") && + iterator->portno == 0) { + found = 1; + res = AST_TEST_PASS; + } + ASTOBJ_UNLOCK(iterator); + } while(0)); + if (!found) { + ast_test_status_update(test, "sip_subscribe_mwi test 4 failed\n"); + } + } + + if (sip_subscribe_mwi(mwi5, 1)) { + res = AST_TEST_FAIL; + } else { + found = 0; + res = AST_TEST_FAIL; + ASTOBJ_CONTAINER_TRAVERSE(&submwil, 1, do { + ASTOBJ_WRLOCK(iterator); + if ( + !strcmp(iterator->hostname, "mysipprovider.com") && + !strcmp(iterator->username, "1234") && + !strcmp(iterator->secret, "password") && + !strcmp(iterator->authuser, "authuser") && + !strcmp(iterator->mailbox, "1234") && + iterator->portno == 5061) { + found = 1; + res = AST_TEST_PASS; + } + ASTOBJ_UNLOCK(iterator); + } while(0)); + if (!found) { + ast_test_status_update(test, "sip_subscribe_mwi test 5 failed\n"); + } + } + + if (sip_subscribe_mwi(mwi6, 1)) { + res = AST_TEST_PASS; + } else { + res = AST_TEST_FAIL; + } + return res; +} + AST_TEST_DEFINE(test_sip_peers_get) { struct sip_peer *peer; @@ -28567,6 +28721,7 @@ static int load_module(void) #ifdef TEST_FRAMEWORK AST_TEST_REGISTER(test_sip_peers_get); + AST_TEST_REGISTER(test_sip_mwi_subscribe_parse); #endif /* Register AstData providers */ @@ -28677,6 +28832,7 @@ static int unload_module(void) #ifdef TEST_FRAMEWORK AST_TEST_UNREGISTER(test_sip_peers_get); + AST_TEST_UNREGISTER(test_sip_mwi_subscribe_parse); #endif /* Unregister all the AstData providers */ ast_data_unregister(NULL); diff --git a/configs/sip.conf.sample b/configs/sip.conf.sample index 3208956696..03008b146a 100644 --- a/configs/sip.conf.sample +++ b/configs/sip.conf.sample @@ -680,12 +680,15 @@ srvlookup=yes ; Enable DNS SRV lookups on outbound calls ;----------------------------------------- OUTBOUND MWI SUBSCRIPTIONS ------------------------- ; Asterisk can subscribe to receive the MWI from another SIP server and store it locally for retrieval -; by other phones. +; by other phones. At this time, you can only subscribe using UDP as the transport. ; Format for the mwi register statement is: -; mwi => user[:secret[:authuser]]@host[:port][/mailbox] +; mwi => user[:secret[:authuser]]@host[:port]/mailbox ; ; Examples: ;mwi => 1234:password@mysipprovider.com/1234 +;mwi => 1234:password@myportprovider.com:6969/1234 +;mwi => 1234:password:authuser@myauthprovider.com/1234 +;mwi => 1234:password:authuser@myauthportprovider.com:6969/1234 ; ; MWI received will be stored in the 1234 mailbox of the SIP_Remote context. It can be used by other phones by following the below: ; mailbox=1234@SIP_Remote