From 059b6a9f597419adc331ca7e1e2b40b090d907a1 Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Sat, 2 Apr 2016 14:44:27 +0200 Subject: add test for SIP with DNS --- test/call.c | 8 +- test/main.c | 3 + test/mock/dnssrv.c | 245 +++++++++++++++++++++++++++++++++++++++++++++++++++++ test/srcs.mk | 1 + test/test.h | 20 +++++ test/ua.c | 177 ++++++++++++++++++++++++++++++++++++-- 6 files changed, 445 insertions(+), 9 deletions(-) create mode 100644 test/mock/dnssrv.c (limited to 'test') diff --git a/test/call.c b/test/call.c index b597f3a..7bf3e26 100644 --- a/test/call.c +++ b/test/call.c @@ -48,6 +48,9 @@ struct fixture { #define fixture_init(f) \ memset(f, 0, sizeof(*f)); \ \ + err = ua_init("test", true, true, true, false); \ + TEST_ERR(err); \ + \ f->magic = MAGIC; \ aucodec_register(&dummy_pcma); \ \ @@ -75,7 +78,10 @@ struct fixture { \ aucodec_unregister(&dummy_pcma); \ \ - uag_event_unregister(event_handler) + uag_event_unregister(event_handler); \ + \ + ua_stop_all(true); \ + ua_close(); static struct aucodec dummy_pcma = { diff --git a/test/main.c b/test/main.c index 9ee4825..5503cbe 100644 --- a/test/main.c +++ b/test/main.c @@ -29,6 +29,7 @@ static const struct test tests[] = { TEST(test_mos), TEST(test_ua_alloc), TEST(test_ua_register), + TEST(test_ua_register_dns), TEST(test_uag_find_param), }; @@ -172,10 +173,12 @@ int main(int argc, char *argv[]) } str_ncpy(config->sip.local, "127.0.0.1:0", sizeof(config->sip.local)); +#if 0 /* XXX: needed for ua tests */ err = ua_init("test", true, true, true, false); if (err) goto out; +#endif if (argc >= (optind + 1)) { diff --git a/test/mock/dnssrv.c b/test/mock/dnssrv.c new file mode 100644 index 0000000..e5ac188 --- /dev/null +++ b/test/mock/dnssrv.c @@ -0,0 +1,245 @@ +/** + * @file mock/dnssrv.c Mock DNS server + * + * Copyright (C) 2010 - 2016 Creytiv.com + */ +#include +#include +#include "../test.h" + + +#define DEBUG_MODULE "mock/dnssrv" +#define DEBUG_LEVEL 5 +#include + + +#define LOCAL_PORT 0 + + +static void dns_server_match(struct dns_server *srv, struct list *rrl, + const char *name, uint16_t type) +{ + struct dnsrr *rr0 = NULL; + struct le *le; + + le = srv->rrl.head; + while (le) { + + struct dnsrr *rr = le->data; + le = le->next; + + if (type == rr->type && 0==str_casecmp(name, rr->name)) { + + if (!rr0) + rr0 = rr; + list_append(rrl, &rr->le_priv, rr); + } + } + + /* If rotation is enabled, then rotate multiple entries + in a deterministic way (no randomness please) */ + if (srv->rotate && rr0) { + list_unlink(&rr0->le); + list_append(&srv->rrl, &rr0->le, rr0); + } +} + + +static void decode_dns_query(struct dns_server *srv, + const struct sa *src, struct mbuf *mb) +{ + struct list rrl = LIST_INIT; + struct dnshdr hdr; + struct le *le; + char *qname = NULL; + size_t start, end; + uint16_t type, dnsclass; + int err = 0; + + start = mb->pos; + end = mb->end; + + if (dns_hdr_decode(mb, &hdr) || hdr.qr || hdr.nq != 1) { + DEBUG_WARNING("unable to decode query header\n"); + return; + } + + err = dns_dname_decode(mb, &qname, start); + if (err) { + DEBUG_WARNING("unable to decode query name\n"); + goto out; + } + + if (mbuf_get_left(mb) < 4) { + err = EBADMSG; + DEBUG_WARNING("unable to decode query type/class\n"); + goto out; + } + + type = ntohs(mbuf_read_u16(mb)); + dnsclass = ntohs(mbuf_read_u16(mb)); + + DEBUG_INFO("dnssrv: type=%s query-name='%s'\n", + dns_rr_typename(type), qname); + + if (dnsclass == DNS_CLASS_IN) { + dns_server_match(srv, &rrl, qname, type); + } + + hdr.qr = true; + hdr.tc = false; + hdr.rcode = DNS_RCODE_OK; + hdr.nq = 1; + hdr.nans = list_count(&rrl); + + mb->pos = start; + + err = dns_hdr_encode(mb, &hdr); + if (err) + goto out; + + mb->pos = end; + + DEBUG_INFO("dnssrv: @@ found %u answers for %s\n", + list_count(&rrl), qname); + + for (le = rrl.head; le; le = le->next) { + struct dnsrr *rr = le->data; + + err = dns_rr_encode(mb, rr, 0, NULL, start); + if (err) + goto out; + } + + mb->pos = start; + + (void)udp_send(srv->us, src, mb); + + out: + list_clear(&rrl); + mem_deref(qname); +} + + +static void udp_recv(const struct sa *src, struct mbuf *mb, void *arg) +{ + struct dns_server *srv = arg; + + decode_dns_query(srv, src, mb); +} + + +static void destructor(void *arg) +{ + struct dns_server *srv = arg; + + list_flush(&srv->rrl); + mem_deref(srv->us); +} + + +int dns_server_alloc(struct dns_server **srvp, bool rotate) +{ + struct dns_server *srv; + int err; + + if (!srvp) + return EINVAL; + + srv = mem_zalloc(sizeof(*srv), destructor); + if (!srv) + return ENOMEM; + + err = sa_set_str(&srv->addr, "127.0.0.1", LOCAL_PORT); + if (err) + goto out; + + err = udp_listen(&srv->us, &srv->addr, udp_recv, srv); + if (err) + goto out; + + err = udp_local_get(srv->us, &srv->addr); + if (err) + goto out; + + srv->rotate = rotate; + + out: + if (err) + mem_deref(srv); + else + *srvp = srv; + + return err; +} + + +int dns_server_add_a(struct dns_server *srv, const char *name, uint32_t addr) +{ + struct dnsrr *rr; + int err; + + if (!srv || !name) + return EINVAL; + + rr = dns_rr_alloc(); + if (!rr) + return ENOMEM; + + err = str_dup(&rr->name, name); + if (err) + goto out; + + rr->type = DNS_TYPE_A; + rr->dnsclass = DNS_CLASS_IN; + rr->ttl = 3600; + rr->rdlen = 0; + + rr->rdata.a.addr = addr; + + list_append(&srv->rrl, &rr->le, rr); + + out: + if (err) + mem_deref(rr); + + return err; +} + + +int dns_server_add_srv(struct dns_server *srv, const char *name, + uint16_t pri, uint16_t weight, uint16_t port, + const char *target) +{ + struct dnsrr *rr; + int err; + + if (!srv || !name || !port || !target) + return EINVAL; + + rr = dns_rr_alloc(); + if (!rr) + return ENOMEM; + + err = str_dup(&rr->name, name); + if (err) + goto out; + + rr->type = DNS_TYPE_SRV; + rr->dnsclass = DNS_CLASS_IN; + rr->ttl = 3600; + rr->rdlen = 0; + + rr->rdata.srv.pri = pri; + rr->rdata.srv.weight = weight; + rr->rdata.srv.port = port; + str_dup(&rr->rdata.srv.target, target); + + list_append(&srv->rrl, &rr->le, rr); + + out: + if (err) + mem_deref(rr); + + return err; +} diff --git a/test/srcs.mk b/test/srcs.mk index 332ba3f..f2d4734 100644 --- a/test/srcs.mk +++ b/test/srcs.mk @@ -18,6 +18,7 @@ TEST_SRCS += mos.c # # Mocks # +TEST_SRCS += mock/dnssrv.c TEST_SRCS += mock/sipsrv.c ifneq ($(USE_TLS),) TEST_SRCS += mock/cert.c diff --git a/test/test.h b/test/test.h index 20ccdcd..c88df56 100644 --- a/test/test.h +++ b/test/test.h @@ -83,12 +83,32 @@ int sip_server_uri(struct sip_server *srv, char *uri, size_t sz, enum sip_transp tp); +/* + * Mock DNS-Server + */ + +struct dns_server { + struct udp_sock *us; + struct sa addr; + struct list rrl; + bool rotate; +}; + +int dns_server_alloc(struct dns_server **srvp, bool rotate); +int dns_server_add_a(struct dns_server *srv, + const char *name, uint32_t addr); +int dns_server_add_srv(struct dns_server *srv, const char *name, + uint16_t pri, uint16_t weight, uint16_t port, + const char *target); + + /* test cases */ int test_cmd(void); int test_ua_alloc(void); int test_uag_find_param(void); int test_ua_register(void); +int test_ua_register_dns(void); int test_mos(void); int test_call_answer(void); diff --git a/test/ua.c b/test/ua.c index c039705..90bfe98 100644 --- a/test/ua.c +++ b/test/ua.c @@ -10,17 +10,31 @@ struct test { - struct sip_server *srv; + struct sip_server *srvv[16]; + size_t srvc; struct ua *ua; int err; unsigned got_register_ok; }; +static void test_reset(struct test *t) +{ + size_t i; + + for (i=0; isrvv); i++) + mem_deref(t->srvv[i]); + mem_deref(t->ua); + + memset(t, 0, sizeof(*t)); +} + + static void ua_event_handler(struct ua *ua, enum ua_event ev, struct call *call, const char *prm, void *arg) { struct test *t = arg; + size_t i; int err = 0; (void)call; (void)prm; @@ -38,7 +52,9 @@ static void ua_event_handler(struct ua *ua, enum ua_event ev, ASSERT_TRUE(ua_isregistered(t->ua)); /* Terminate SIP Server, then De-REGISTER */ - t->srv->terminate = true; + for (i=0; isrvc; i++) + t->srvv[i]->terminate = true; + t->ua = mem_deref(t->ua); } @@ -58,13 +74,13 @@ static int reg(enum sip_transp tp) memset(&t, 0, sizeof t); - err = sip_server_alloc(&t.srv); + err = sip_server_alloc(&t.srvv[0]); if (err) { warning("failed to create sip server (%d/%m)\n", err, err); goto out; } - err = sip_server_uri(t.srv, aor, sizeof(aor), tp); + err = sip_server_uri(t.srvv[0], aor, sizeof(aor), tp); TEST_ERR(err); err = ua_alloc(&t.ua, aor); @@ -82,8 +98,8 @@ static int reg(enum sip_transp tp) if (t.err) err = t.err; - ASSERT_TRUE(t.srv->n_register_req > 0); - ASSERT_EQ(tp, t.srv->tp_last); + ASSERT_TRUE(t.srvv[0]->n_register_req > 0); + ASSERT_EQ(tp, t.srvv[0]->tp_last); ASSERT_TRUE(t.got_register_ok > 0); out: @@ -91,8 +107,7 @@ static int reg(enum sip_transp tp) warning("selftest: ua_register test failed (%m)\n", err); } uag_event_unregister(ua_event_handler); - mem_deref(t.srv); - mem_deref(t.ua); + test_reset(&t); return err; } @@ -102,12 +117,18 @@ int test_ua_register(void) { int err = 0; + err = ua_init("test", true, true, true, false); + TEST_ERR(err); + err |= reg(SIP_TRANSP_UDP); err |= reg(SIP_TRANSP_TCP); #ifdef USE_TLS err |= reg(SIP_TRANSP_TLS); #endif + ua_close(); + + out: return err; } @@ -169,3 +190,143 @@ int test_uag_find_param(void) return err; } + + +#define SERVER_COUNT 1 + + +static const char *_sip_transp_srvid(enum sip_transp tp) +{ + switch (tp) { + + case SIP_TRANSP_UDP: return "_sip._udp"; + case SIP_TRANSP_TCP: return "_sip._tcp"; + case SIP_TRANSP_TLS: return "_sips._tcp"; + default: return "???"; + } +} + + +static int reg_dns(enum sip_transp tp) +{ + struct dns_server *dnssrv = NULL; + struct test t; + const char *domain = "test.invalid"; + char aor[256]; + char srv[256]; + size_t i; + int err; + + memset(&t, 0, sizeof t); + + /* + * Setup server-side mocks: + */ + + err = dns_server_alloc(&dnssrv, true); + TEST_ERR(err); + + info("| DNS-server on %J\n", &dnssrv->addr); + + /* NOTE: must be done before ua_init() */ + err = net_dnssrv_add(&dnssrv->addr); + TEST_ERR(err); + + for (i=0; isip, &sip_addr, tp, NULL); + TEST_ERR(err); + + info("| SIP-server on %J\n", &sip_addr); + + re_snprintf(arec, sizeof(arec), + "alpha%u.%s", i+1, domain); + + re_snprintf(srv, sizeof(srv), + "%s.%s", _sip_transp_srvid(tp), domain); + err = dns_server_add_srv(dnssrv, srv, + 20, 0, sa_port(&sip_addr), + arec); + TEST_ERR(err); + + err = dns_server_add_a(dnssrv, arec, sa_in(&sip_addr)); + TEST_ERR(err); + } + t.srvc = SERVER_COUNT; + + /* NOTE: angel brackets needed to parse ;transport parameter */ + if (re_snprintf(aor, sizeof(aor), "", + domain, sip_transp_name(tp)) < 0) + return ENOMEM; + + /* + * Start SIP client: + */ + + err = ua_init("test", true, true, true, false); + TEST_ERR(err); + + err = ua_alloc(&t.ua, aor); + TEST_ERR(err); + + err = uag_event_register(ua_event_handler, &t); + if (err) + goto out; + + /* run main-loop with timeout, wait for events */ + err = re_main_timeout(5000); + if (err) + goto out; + + if (t.err) + err = t.err; + + /* verify that all SIP requests was sent to the first + * SIP-server. + */ + ASSERT_TRUE(t.srvv[0]->n_register_req > 0); + ASSERT_EQ(tp, t.srvv[0]->tp_last); + ASSERT_TRUE(t.got_register_ok > 0); + + out: + if (err) { + warning("selftest: ua_register test failed (%m)\n", err); + } + uag_event_unregister(ua_event_handler); + + test_reset(&t); + + ua_stop_all(true); + ua_close(); + + mem_deref(dnssrv); + + return err; +} + + +int test_ua_register_dns(void) +{ + int err = 0; + + err |= reg_dns(SIP_TRANSP_UDP); + TEST_ERR(err); + err |= reg_dns(SIP_TRANSP_TCP); + TEST_ERR(err); +#ifdef USE_TLS + err |= reg_dns(SIP_TRANSP_TLS); + TEST_ERR(err); +#endif + + out: + return err; +} -- cgit v1.2.3 From 31baf6937aee6f449a6675e102d6f0831bfb1fbe Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Sun, 3 Apr 2016 17:35:05 +0200 Subject: test: added test-case for authenticated register --- test/main.c | 1 + test/mock/sipsrv.c | 146 ----------------------- test/sip/aor.c | 98 ++++++++++++++++ test/sip/auth.c | 91 +++++++++++++++ test/sip/domain.c | 187 +++++++++++++++++++++++++++++ test/sip/location.c | 188 ++++++++++++++++++++++++++++++ test/sip/sipsrv.c | 329 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test/sip/sipsrv.h | 121 +++++++++++++++++++ test/sip/user.c | 73 ++++++++++++ test/srcs.mk | 9 +- test/test.h | 19 +-- test/ua.c | 92 +++++++++++++++ 12 files changed, 1189 insertions(+), 165 deletions(-) delete mode 100644 test/mock/sipsrv.c create mode 100644 test/sip/aor.c create mode 100644 test/sip/auth.c create mode 100644 test/sip/domain.c create mode 100644 test/sip/location.c create mode 100644 test/sip/sipsrv.c create mode 100644 test/sip/sipsrv.h create mode 100644 test/sip/user.c (limited to 'test') diff --git a/test/main.c b/test/main.c index 5503cbe..a03cf99 100644 --- a/test/main.c +++ b/test/main.c @@ -30,6 +30,7 @@ static const struct test tests[] = { TEST(test_ua_alloc), TEST(test_ua_register), TEST(test_ua_register_dns), + TEST(test_ua_register_auth), TEST(test_uag_find_param), }; diff --git a/test/mock/sipsrv.c b/test/mock/sipsrv.c deleted file mode 100644 index c762f73..0000000 --- a/test/mock/sipsrv.c +++ /dev/null @@ -1,146 +0,0 @@ -/** - * @file mock/sipsrv.c Mock SIP server - * - * Copyright (C) 2010 - 2015 Creytiv.com - */ -#include -#include -#include "../test.h" - - -#define DEBUG_MODULE "mock/sipsrv" -#define DEBUG_LEVEL 5 -#include - - -#define LOCAL_PORT 0 -#define LOCAL_SECURE_PORT 0 - - -static bool sip_msg_handler(const struct sip_msg *msg, void *arg) -{ - struct sip_server *srv = arg; - int err; - -#if 0 - DEBUG_NOTICE("recv %r via %s\n", &msg->met, sip_transp_name(msg->tp)); -#endif - - if (0 == pl_strcmp(&msg->met, "REGISTER")) { - ++srv->n_register_req; - } - else { - DEBUG_NOTICE("method not handled (%r)\n", &msg->met); - return false; - } - - srv->tp_last = msg->tp; - - if (srv->terminate) - err = sip_reply(srv->sip, msg, 503, "Server Error"); - else - err = sip_reply(srv->sip, msg, 200, "OK"); - - if (err) { - DEBUG_WARNING("could not reply: %m\n", err); - } - -#if 1 - if (srv->terminate) - re_cancel(); -#endif - - return true; -} - - -static void destructor(void *arg) -{ - struct sip_server *srv = arg; - - srv->terminate = true; - - sip_close(srv->sip, false); - mem_deref(srv->sip); -} - - -int sip_server_alloc(struct sip_server **srvp) -{ - struct sip_server *srv; - struct sa laddr, laddrs; - struct tls *tls = NULL; - int err; - - if (!srvp) - return EINVAL; - - srv = mem_zalloc(sizeof *srv, destructor); - if (!srv) - return ENOMEM; - - err = sa_set_str(&laddr, "127.0.0.1", LOCAL_PORT); - err |= sa_set_str(&laddrs, "127.0.0.1", LOCAL_SECURE_PORT); - if (err) - goto out; - - err = sip_alloc(&srv->sip, NULL, 16, 16, 16, - "mock SIP server", NULL, NULL); - if (err) - goto out; - - err |= sip_transp_add(srv->sip, SIP_TRANSP_UDP, &laddr); - err |= sip_transp_add(srv->sip, SIP_TRANSP_TCP, &laddr); - if (err) - goto out; - -#ifdef USE_TLS - err = tls_alloc(&tls, TLS_METHOD_SSLV23, NULL, NULL); - if (err) - goto out; - - err = tls_set_certificate(tls, test_certificate, - strlen(test_certificate)); - if (err) - goto out; - - err |= sip_transp_add(srv->sip, SIP_TRANSP_TLS, &laddrs, tls); -#endif - if (err) - goto out; - - err = sip_listen(&srv->lsnr, srv->sip, true, sip_msg_handler, srv); - if (err) - goto out; - - out: - mem_deref(tls); - if (err) - mem_deref(srv); - else - *srvp = srv; - - return err; -} - - -int sip_server_uri(struct sip_server *srv, char *uri, size_t sz, - enum sip_transp tp) -{ - struct sa laddr; - int err; - - if (!srv || !uri || !sz) - return EINVAL; - - err = sip_transp_laddr(srv->sip, &laddr, tp, NULL); - if (err) - return err; - - /* NOTE: angel brackets needed to parse ;transport parameter */ - if (re_snprintf(uri, sz, "", - &laddr, sip_transp_param(tp)) < 0) - return ENOMEM; - - return 0; -} diff --git a/test/sip/aor.c b/test/sip/aor.c new file mode 100644 index 0000000..0d8a317 --- /dev/null +++ b/test/sip/aor.c @@ -0,0 +1,98 @@ +/** + * @file sip/aor.c Mock SIP server -- SIP Address of Record + * + * Copyright (C) 2010 - 2016 Creytiv.com + */ +#include +#include +#include "sipsrv.h" + + +static void destructor(void *arg) +{ + struct aor *aor = arg; + + list_flush(&aor->locl); + hash_unlink(&aor->he); + mem_deref(aor->uri); +} + + +static int uri_canon(char **curip, const struct uri *uri) +{ + if (pl_isset(&uri->user)) + return re_sdprintf(curip, "%r:%H@%r", + &uri->scheme, + uri_user_unescape, &uri->user, + &uri->host); + else + return re_sdprintf(curip, "%r:%r", + &uri->scheme, + &uri->host); +} + + +int aor_create(struct sip_server *srv, struct aor **aorp, + const struct uri *uri) +{ + struct aor *aor; + int err; + + if (!aorp || !uri) + return EINVAL; + + aor = mem_zalloc(sizeof(*aor), destructor); + if (!aor) + return ENOMEM; + + err = uri_canon(&aor->uri, uri); + if (err) + goto out; + + hash_append(srv->ht_aor, hash_joaat_str_ci(aor->uri), &aor->he, aor); + + out: + if (err) + mem_deref(aor); + else + *aorp = aor; + + return err; +} + + +int aor_find(struct sip_server *srv, struct aor **aorp, const struct uri *uri) +{ + struct list *lst; + struct aor *aor; + struct le *le; + char *curi; + int err; + + if (!uri) + return EINVAL; + + err = uri_canon(&curi, uri); + if (err) + return err; + + lst = hash_list(srv->ht_aor, hash_joaat_str_ci(curi)); + + for (le=list_head(lst); le; le=le->next) { + + aor = le->data; + + if (!str_casecmp(curi, aor->uri)) + break; + } + + mem_deref(curi); + + if (!le) + return ENOENT; + + if (aorp) + *aorp = aor; + + return 0; +} diff --git a/test/sip/auth.c b/test/sip/auth.c new file mode 100644 index 0000000..5d3e224 --- /dev/null +++ b/test/sip/auth.c @@ -0,0 +1,91 @@ +/** + * @file sip/auth.c Mock SIP server -- authentication + * + * Copyright (C) 2010 - 2016 Creytiv.com + */ +#include +#include +#include +#include "sipsrv.h" + + +enum { + NONCE_MIN_SIZE = 33, +}; + + +int auth_print(struct re_printf *pf, const struct auth *auth) +{ + uint8_t key[MD5_SIZE]; + uint64_t nv[2]; + + if (!auth) + return EINVAL; + + nv[0] = time(NULL); + nv[1] = auth->srv->secret; + + md5((uint8_t *)nv, sizeof(nv), key); + + return re_hprintf(pf, + "Digest realm=\"%s\", nonce=\"%w%llx\", " + "qop=\"auth\"%s", + auth->realm, + key, sizeof(key), nv[0], + auth->stale ? ", stale=true" : ""); +} + + +int auth_chk_nonce(struct sip_server *srv, + const struct pl *nonce, uint32_t expires) +{ + uint8_t nkey[MD5_SIZE], ckey[MD5_SIZE]; + uint64_t nv[2]; + struct pl pl; + int64_t age; + unsigned i; + + if (!nonce || !nonce->p || nonce->l < NONCE_MIN_SIZE) + return EINVAL; + + pl = *nonce; + + for (i=0; isecret; + + md5((uint8_t *)nv, sizeof(nv), ckey); + + if (memcmp(nkey, ckey, MD5_SIZE)) + return EAUTH; + + age = time(NULL) - nv[0]; + + if (age < 0 || age > expires) + return ETIMEDOUT; + + return 0; +} + + +int auth_set_realm(struct auth *auth, const char *realm) +{ + size_t len; + + if (!auth || !realm) + return EINVAL; + + len = strlen(realm); + if (len >= sizeof(auth->realm)) + return ENOMEM; + + memcpy(auth->realm, realm, len); + auth->realm[len] = '\0'; + + return 0; +} diff --git a/test/sip/domain.c b/test/sip/domain.c new file mode 100644 index 0000000..063e3b9 --- /dev/null +++ b/test/sip/domain.c @@ -0,0 +1,187 @@ +/** + * @file sip/domain.c Mock SIP server -- domain handling + * + * Copyright (C) 2010 - 2016 Creytiv.com + */ +#include +#include "sipsrv.h" + + +#define DEBUG_MODULE "mock/sipsrv" +#define DEBUG_LEVEL 5 +#include + + +enum { + NONCE_EXPIRES = 300, +}; + + +static void destructor(void *arg) +{ + struct domain *dom = arg; + + hash_unlink(&dom->he); + hash_flush(dom->ht_usr); + mem_deref(dom->ht_usr); + mem_deref(dom->name); +} + + +static struct domain *lookup(struct sip_server *srv, const struct pl *name) +{ + struct list *lst; + struct le *le; + + lst = hash_list(srv->ht_dom, hash_joaat_ci(name->p, name->l)); + + for (le=list_head(lst); le; le=le->next) { + + struct domain *dom = le->data; + + if (pl_strcasecmp(name, dom->name)) + continue; + + return dom; + } + + return NULL; +} + + +int domain_add(struct sip_server *srv, const char *name) +{ + struct domain *dom; + int err; + + dom = mem_zalloc(sizeof(*dom), destructor); + if (!dom) + return ENOMEM; + + err = str_dup(&dom->name, name); + if (err) + goto out; + + err = hash_alloc(&dom->ht_usr, 32); + if (err) + return err; + + hash_append(srv->ht_dom, hash_joaat_str_ci(name), &dom->he, dom); + + out: + if (err) + mem_deref(dom); + + return err; +} + + +int domain_find(struct sip_server *srv, const struct uri *uri) +{ + int err = ENOENT; + struct sa addr; + + if (!uri) + return EINVAL; + + if (!sa_set(&addr, &uri->host, uri->port)) { + + if (!uri->port) { + + uint16_t port = SIP_PORT; + + if (!pl_strcasecmp(&uri->scheme, "sips")) + port = SIP_PORT_TLS; + + sa_set_port(&addr, port); + } + + if (sip_transp_isladdr(srv->sip, SIP_TRANSP_NONE, &addr)) + return 0; + + return ENOENT; + } + + err = lookup(srv, &uri->host) ? 0 : ENOENT; + + return err; +} + + +int domain_auth(struct sip_server *srv, + const struct uri *uri, bool user_match, + const struct sip_msg *msg, enum sip_hdrid hdrid, + struct auth *auth) +{ + struct domain *dom; + struct list *lst; + struct le *le; + int err = ENOENT; + + if (!uri || !msg || !auth) + return EINVAL; + + dom = lookup(srv, &uri->host); + if (!dom) { + DEBUG_WARNING("domain not found (%r)\n", &uri->host); + return ENOENT; + } + + err = auth_set_realm(auth, dom->name); + if (err) + return err; + + auth->stale = false; + + lst = hash_list(msg->hdrht, hdrid); + + for (le=list_head(lst); le; le=le->next) { + + const struct sip_hdr *hdr = le->data; + struct httpauth_digest_resp resp; + const struct user *usr; + + if (hdr->id != hdrid) + continue; + + if (httpauth_digest_response_decode(&resp, &hdr->val)) + continue; + + if (pl_strcasecmp(&resp.realm, dom->name)) + continue; + + if (auth_chk_nonce(srv, &resp.nonce, NONCE_EXPIRES)) { + auth->stale = true; + continue; + } + + auth->stale = false; + + usr = user_find(dom->ht_usr, &resp.username); + if (!usr) { + DEBUG_WARNING("user not found (%r)\n", &resp.username); + break; + } + + err = httpauth_digest_response_auth(&resp, &msg->met,usr->ha1); + if (err) + return err; + + if (user_match && pl_cmp(&resp.username, &uri->user)) + return EPERM; + + return 0; + } + + return EAUTH; +} + + +struct domain *domain_lookup(struct sip_server *srv, const char *name) +{ + struct pl pl; + + pl_set_str(&pl, name); + + return lookup(srv, &pl); +} diff --git a/test/sip/location.c b/test/sip/location.c new file mode 100644 index 0000000..be2bd66 --- /dev/null +++ b/test/sip/location.c @@ -0,0 +1,188 @@ +/** + * @file sip/location.c Mock SIP server -- location handling + * + * Copyright (C) 2010 - 2016 Creytiv.com + */ +#include +#include +#include "sipsrv.h" + + +struct loctmp { + struct sa src; + struct uri duri; + char *uri; + char *callid; + uint32_t expires; + uint32_t cseq; + double q; +}; + + +static void destructor_loctmp(void *arg) +{ + struct loctmp *tmp = arg; + + mem_deref(tmp->uri); + mem_deref(tmp->callid); +} + + +static void destructor_location(void *arg) +{ + struct location *loc = arg; + + list_unlink(&loc->le); + mem_deref(loc->uri); + mem_deref(loc->callid); + mem_deref(loc->tmp); +} + + +static bool cmp_handler(struct le *le, void *arg) +{ + struct location *loc = le->data; + + return uri_cmp(&loc->duri, arg); +} + + +int location_update(struct list *locl, const struct sip_msg *msg, + const struct sip_addr *contact, uint32_t expires) +{ + struct location *loc, *loc_new = NULL; + struct loctmp *tmp; + struct pl pl; + int err; + + if (!locl || !msg || !contact) + return EINVAL; + + loc = list_ledata(list_apply(locl, true, cmp_handler, + (void *)&contact->uri)); + if (!loc) { + if (expires == 0) + return 0; + + loc = loc_new = mem_zalloc(sizeof(*loc), destructor_location); + if (!loc) + return ENOMEM; + + list_append(locl, &loc->le, loc); + } + else { + if (!pl_strcmp(&msg->callid, loc->callid) && + msg->cseq.num <= loc->cseq) + return EPROTO; + + if (expires == 0) { + loc->rm = true; + return 0; + } + } + + tmp = mem_zalloc(sizeof(*tmp), destructor_loctmp); + if (!tmp) { + err = ENOMEM; + goto out; + } + + err = pl_strdup(&tmp->uri, &contact->auri); + if (err) + goto out; + + pl_set_str(&pl, tmp->uri); + + if (uri_decode(&tmp->duri, &pl)) { + err = EBADMSG; + goto out; + } + + err = pl_strdup(&tmp->callid, &msg->callid); + if (err) + goto out; + + + if (!msg_param_decode(&contact->params, "q", &pl)) + tmp->q = pl_float(&pl); + else + tmp->q = 1; + + tmp->cseq = msg->cseq.num; + tmp->expires = expires; + tmp->src = msg->src; + + out: + if (err) { + mem_deref(loc_new); + mem_deref(tmp); + } + else { + mem_deref(loc->tmp); + loc->tmp = tmp; + } + + return err; +} + + +void location_commit(struct list *locl) +{ + time_t now = time(NULL); + struct le *le; + + if (!locl) + return; + + for (le=locl->head; le; ) { + + struct location *loc = le->data; + + le = le->next; + + if (loc->rm) { + list_unlink(&loc->le); + mem_deref(loc); + } + else if (loc->tmp) { + + mem_deref(loc->uri); + mem_deref(loc->callid); + + loc->uri = mem_ref(loc->tmp->uri); + loc->callid = mem_ref(loc->tmp->callid); + loc->duri = loc->tmp->duri; + loc->cseq = loc->tmp->cseq; + loc->expires = loc->tmp->expires + now; + loc->src = loc->tmp->src; + loc->q = loc->tmp->q; + + loc->tmp = mem_deref(loc->tmp); + } + } +} + + +void location_rollback(struct list *locl) +{ + struct le *le; + + if (!locl) + return; + + for (le=locl->head; le; ) { + + struct location *loc = le->data; + + le = le->next; + + if (!loc->uri) { + list_unlink(&loc->le); + mem_deref(loc); + } + else { + loc->tmp = mem_deref(loc->tmp); + loc->rm = false; + } + } +} diff --git a/test/sip/sipsrv.c b/test/sip/sipsrv.c new file mode 100644 index 0000000..8d9bd8e --- /dev/null +++ b/test/sip/sipsrv.c @@ -0,0 +1,329 @@ +/** + * @file mock/sipsrv.c Mock SIP server + * + * Copyright (C) 2010 - 2015 Creytiv.com + */ +#include +#include +#include +#include +#include "../test.h" +#include "sipsrv.h" + + +#define DEBUG_MODULE "mock/sipsrv" +#define DEBUG_LEVEL 5 +#include + + +#define LOCAL_PORT 0 +#define LOCAL_SECURE_PORT 0 +#define EXPIRES_MIN 60 +#define EXPIRES_MAX 3600 + + +static int print_contact(struct re_printf *pf, const struct aor *aor) +{ + const uint64_t now = (uint64_t)time(NULL); + struct le *le; + int err = 0; + + for (le=aor->locl.head; le; le=le->next) { + + const struct location *loc = le->data; + + if (loc->expires < now) + continue; + + err |= re_hprintf(pf, "Contact: <%s>;expires=%lli\r\n", + loc->uri, loc->expires - now); + } + + return err; +} + + +static bool handle_register(struct sip_server *srv, const struct sip_msg *msg) +{ + struct auth auth = { srv, "", false }; + struct sip *sip = srv->sip; + struct list *lst; + struct aor *aor; + struct le *le; + int err; + + /* Request URI */ + err = domain_find(srv, &msg->uri); + if (err) { + if (err == ENOENT) { + warning("domain not found\n"); + return false; + } + + sip_reply(sip, msg, 500, strerror(err)); + error("domain find error: %s\n", strerror(err)); + return true; + } + + /* Authorize */ + if (srv->auth_enabled) + err = domain_auth(srv, &msg->to.uri, true, + msg, SIP_HDR_AUTHORIZATION, &auth); + else + err = domain_find(srv, &msg->to.uri); + + if (err && err != EAUTH) { + DEBUG_NOTICE("domain auth/find error: %m\n", err); + } + + switch (err) { + + case 0: + break; + + case EAUTH: + sip_replyf(sip, msg, 401, "Unauthorized", + "WWW-Authenticate: %H\r\n" + "Content-Length: 0\r\n\r\n", + auth_print, &auth); + return true; + + case EPERM: + sip_reply(sip, msg, 403, "Forbidden"); + return true; + + case ENOENT: + sip_reply(sip, msg, 404, "Not Found"); + return true; + + default: + sip_reply(sip, msg, 500, strerror(err)); + error("domain error: %s\n", strerror(err)); + return true; + } + + /* Find AoR */ + err = aor_find(srv, &aor, &msg->to.uri); + if (err) { + if (err != ENOENT) { + sip_reply(sip, msg, 500, strerror(err)); + error("aor find error: %s\n", strerror(err)); + return true; + } + + err = aor_create(srv, &aor, &msg->to.uri); + if (err) { + sip_reply(sip, msg, 500, strerror(err)); + error("aor create error: %s\n", strerror(err)); + return true; + } + } + + /* Process Contacts */ + lst = hash_list(msg->hdrht, SIP_HDR_CONTACT); + + for (le=list_head(lst); le; le=le->next) { + + const struct sip_hdr *hdr = le->data; + struct sip_addr contact; + uint32_t expires; + struct pl pl; + + if (hdr->id != SIP_HDR_CONTACT) + continue; + + err = sip_addr_decode(&contact, &hdr->val); + if (err) { + sip_reply(sip, msg, 400, "Bad Contact"); + goto fail; + } + + if (!msg_param_decode(&contact.params, "expires", &pl)) + expires = pl_u32(&pl); + else if (pl_isset(&msg->expires)) + expires = pl_u32(&msg->expires); + else + expires = 3600; + + if (expires > 0 && expires < EXPIRES_MIN) { + sip_replyf(sip, msg, 423, "Interval Too Brief", + "Min-Expires: %u\r\n" + "Content-Length: 0\r\n\r\n", + EXPIRES_MIN); + goto fail; + } + + expires = min(expires, EXPIRES_MAX); + + err = location_update(&aor->locl, msg, &contact, expires); + if (err) { + sip_reply(sip, msg, 500, strerror(err)); + if (err != EPROTO) + error("location update error: %s\n", + strerror(err)); + goto fail; + } + } + + location_commit(&aor->locl); + + sip_treplyf(NULL, NULL, sip, msg, false, 200, "OK", + "%H" + "Date: %H\r\n" + "Content-Length: 0\r\n\r\n", + print_contact, aor, + fmt_gmtime, NULL); + + return true; + + fail: + location_rollback(&aor->locl); + + return true; +} + + +static bool sip_msg_handler(const struct sip_msg *msg, void *arg) +{ + struct sip_server *srv = arg; + int err = 0; + +#if 0 + DEBUG_NOTICE("recv %r via %s\n", &msg->met, sip_transp_name(msg->tp)); +#endif + + srv->tp_last = msg->tp; + + if (0 == pl_strcmp(&msg->met, "REGISTER")) { + ++srv->n_register_req; + if (handle_register(srv, msg)) + goto out; + + sip_reply(srv->sip, msg, 503, "Server Error"); + } + else { + DEBUG_NOTICE("method not handled (%r)\n", &msg->met); + return false; + } + + if (srv->terminate) + err = sip_reply(srv->sip, msg, 503, "Server Error"); + + if (err) { + DEBUG_WARNING("could not reply: %m\n", err); + } + + out: + if (srv->terminate) + re_cancel(); + + return true; +} + + +static void destructor(void *arg) +{ + struct sip_server *srv = arg; + + srv->terminate = true; + + sip_close(srv->sip, false); + mem_deref(srv->sip); + + hash_flush(srv->ht_aor); + mem_deref(srv->ht_aor); + + hash_flush(srv->ht_dom); + mem_deref(srv->ht_dom); +} + + +int sip_server_alloc(struct sip_server **srvp) +{ + struct sip_server *srv; + struct sa laddr, laddrs; + struct tls *tls = NULL; + int err; + + if (!srvp) + return EINVAL; + + srv = mem_zalloc(sizeof *srv, destructor); + if (!srv) + return ENOMEM; + + err = sa_set_str(&laddr, "127.0.0.1", LOCAL_PORT); + err |= sa_set_str(&laddrs, "127.0.0.1", LOCAL_SECURE_PORT); + if (err) + goto out; + + err = sip_alloc(&srv->sip, NULL, 16, 16, 16, + "mock SIP server", NULL, NULL); + if (err) + goto out; + + err |= sip_transp_add(srv->sip, SIP_TRANSP_UDP, &laddr); + err |= sip_transp_add(srv->sip, SIP_TRANSP_TCP, &laddr); + if (err) + goto out; + +#ifdef USE_TLS + err = tls_alloc(&tls, TLS_METHOD_SSLV23, NULL, NULL); + if (err) + goto out; + + err = tls_set_certificate(tls, test_certificate, + strlen(test_certificate)); + if (err) + goto out; + + err |= sip_transp_add(srv->sip, SIP_TRANSP_TLS, &laddrs, tls); +#endif + if (err) + goto out; + + err = sip_listen(&srv->lsnr, srv->sip, true, sip_msg_handler, srv); + if (err) + goto out; + + srv->secret = rand_u64(); + + err = hash_alloc(&srv->ht_dom, 32); + if (err) + goto out; + + err = hash_alloc(&srv->ht_aor, 32); + if (err) + goto out; + + out: + mem_deref(tls); + if (err) + mem_deref(srv); + else + *srvp = srv; + + return err; +} + + +int sip_server_uri(struct sip_server *srv, char *uri, size_t sz, + enum sip_transp tp) +{ + struct sa laddr; + int err; + + if (!srv || !uri || !sz) + return EINVAL; + + err = sip_transp_laddr(srv->sip, &laddr, tp, NULL); + if (err) + return err; + + /* NOTE: angel brackets needed to parse ;transport parameter */ + if (re_snprintf(uri, sz, "", + &laddr, sip_transp_param(tp)) < 0) + return ENOMEM; + + return 0; +} diff --git a/test/sip/sipsrv.h b/test/sip/sipsrv.h new file mode 100644 index 0000000..4690ffe --- /dev/null +++ b/test/sip/sipsrv.h @@ -0,0 +1,121 @@ +/** + * @file mock/sipsrv.h Mock SIP server -- interface + * + * Copyright (C) 2010 - 2016 Creytiv.com + */ + + +struct auth; + + +/* + * SIP Server + */ + +struct sip_server { + struct sip *sip; + struct sip_lsnr *lsnr; + bool auth_enabled; + bool terminate; + + unsigned n_register_req; + enum sip_transp tp_last; + + uint64_t secret; + struct hash *ht_dom; + struct hash *ht_aor; +}; + +int sip_server_alloc(struct sip_server **srvp); +int sip_server_uri(struct sip_server *srv, char *uri, size_t sz, + enum sip_transp tp); + + +/* + * AoR + */ + +struct aor { + struct le he; + struct list locl; + char *uri; +}; + +int aor_create(struct sip_server *srv, struct aor **aorp, + const struct uri *uri); +int aor_find(struct sip_server *srv, struct aor **aorp, + const struct uri *uri); + + +/* + * Auth + */ + +struct auth { + const struct sip_server *srv; + char realm[256]; + bool stale; +}; + +int auth_print(struct re_printf *pf, const struct auth *auth); +int auth_chk_nonce(struct sip_server *srv, + const struct pl *nonce, uint32_t expires); +int auth_set_realm(struct auth *auth, const char *realm); + + +/* + * Domain + */ + +struct domain { + struct le he; + struct hash *ht_usr; + char *name; +}; + + +int domain_add(struct sip_server *srv, const char *name); +int domain_find(struct sip_server *srv, const struct uri *uri); +int domain_auth(struct sip_server *srv, + const struct uri *uri, bool user_match, + const struct sip_msg *msg, enum sip_hdrid hdrid, + struct auth *auth); +struct domain *domain_lookup(struct sip_server *srv, const char *name); + + +/* + * Location + */ + +struct location { + struct le le; + struct sa src; + struct uri duri; + char *uri; + char *callid; + struct loctmp *tmp; + uint64_t expires; + uint32_t cseq; + double q; + bool rm; +}; + +int location_update(struct list *locl, const struct sip_msg *msg, + const struct sip_addr *contact, uint32_t expires); +void location_commit(struct list *locl); +void location_rollback(struct list *locl); + + +/* + * User + */ + +struct user { + struct le he; + uint8_t ha1[MD5_SIZE]; + char *name; +}; + +int user_add(struct hash *ht, const char *username, const char *password, + const char *realm); +struct user *user_find(struct hash *ht, const struct pl *name); diff --git a/test/sip/user.c b/test/sip/user.c new file mode 100644 index 0000000..99fb47d --- /dev/null +++ b/test/sip/user.c @@ -0,0 +1,73 @@ +/** + * @file sip/user.c Mock SIP server -- user handling + * + * Copyright (C) 2010 - 2016 Creytiv.com + */ +#include +#include "sipsrv.h" + + +static void destructor(void *arg) +{ + struct user *usr = arg; + + hash_unlink(&usr->he); + mem_deref(usr->name); +} + + +int user_add(struct hash *ht, const char *username, const char *password, + const char *realm) +{ + struct user *usr; + int err; + + usr = mem_zalloc(sizeof(*usr), destructor); + if (!usr) { + err = ENOMEM; + goto out; + } + + err = str_dup(&usr->name, username); + if (err) { + goto out; + } + + err = md5_printf(usr->ha1, "%s:%s:%s", username, realm, password); + if (err) { + goto out; + } + + hash_append(ht, hash_joaat_str(username), &usr->he, usr); + + out: + if (err) { + mem_deref(usr); + } + + return err; +} + + +struct user *user_find(struct hash *ht, const struct pl *name) +{ + struct list *lst; + struct le *le; + + if (!ht || !name) + return NULL; + + lst = hash_list(ht, hash_joaat((uint8_t *)name->p, name->l)); + + for (le=list_head(lst); le; le=le->next) { + + struct user *usr = le->data; + + if (pl_strcmp(name, usr->name)) + continue; + + return usr; + } + + return NULL; +} diff --git a/test/srcs.mk b/test/srcs.mk index f2d4734..a68ff94 100644 --- a/test/srcs.mk +++ b/test/srcs.mk @@ -19,7 +19,14 @@ TEST_SRCS += mos.c # Mocks # TEST_SRCS += mock/dnssrv.c -TEST_SRCS += mock/sipsrv.c + +TEST_SRCS += sip/aor.c +TEST_SRCS += sip/auth.c +TEST_SRCS += sip/domain.c +TEST_SRCS += sip/location.c +TEST_SRCS += sip/sipsrv.c +TEST_SRCS += sip/user.c + ifneq ($(USE_TLS),) TEST_SRCS += mock/cert.c endif diff --git a/test/test.h b/test/test.h index c88df56..62904fe 100644 --- a/test/test.h +++ b/test/test.h @@ -65,24 +65,6 @@ extern const char test_certificate[]; #endif -/* - * SIP Server - */ - -struct sip_server { - struct sip *sip; - struct sip_lsnr *lsnr; - bool terminate; - - unsigned n_register_req; - enum sip_transp tp_last; -}; - -int sip_server_alloc(struct sip_server **srvp); -int sip_server_uri(struct sip_server *srv, char *uri, size_t sz, - enum sip_transp tp); - - /* * Mock DNS-Server */ @@ -109,6 +91,7 @@ int test_ua_alloc(void); int test_uag_find_param(void); int test_ua_register(void); int test_ua_register_dns(void); +int test_ua_register_auth(void); int test_mos(void); int test_call_answer(void); diff --git a/test/ua.c b/test/ua.c index 90bfe98..11cd020 100644 --- a/test/ua.c +++ b/test/ua.c @@ -7,6 +7,7 @@ #include #include #include "test.h" +#include "sip/sipsrv.h" struct test { @@ -46,6 +47,8 @@ static void ua_event_handler(struct ua *ua, enum ua_event ev, if (ev == UA_EVENT_REGISTER_OK) { + re_printf("event: Register OK!\n"); + ++t->got_register_ok; /* verify register success */ @@ -57,6 +60,11 @@ static void ua_event_handler(struct ua *ua, enum ua_event ev, t->ua = mem_deref(t->ua); } + else if (ev == UA_EVENT_REGISTER_FAIL) { + + err = EAUTH; + re_cancel(); + } out: if (err) { @@ -243,6 +251,10 @@ static int reg_dns(enum sip_transp tp) goto out; } + err = domain_add(t.srvv[0], domain); + if (err) + goto out; + err = sip_transp_laddr(t.srvv[i]->sip, &sip_addr, tp, NULL); TEST_ERR(err); @@ -330,3 +342,83 @@ int test_ua_register_dns(void) out: return err; } + + +#define USER "alfredh" +#define PASS "password" +#define DOMAIN "localhost" + +int test_ua_register_auth(void) +{ + struct sa laddr; + enum sip_transp tp = SIP_TRANSP_UDP; + struct test t; + char aor[256]; + int err; + + memset(&t, 0, sizeof t); + + err = sip_server_alloc(&t.srvv[0]); + if (err) { + warning("failed to create sip server (%d/%m)\n", err, err); + goto out; + } + + err = domain_add(t.srvv[0], DOMAIN); + TEST_ERR(err); + + err = user_add(domain_lookup(t.srvv[0], DOMAIN)->ht_usr, + "alfredh", "password", DOMAIN); + TEST_ERR(err); + + t.srvv[0]->auth_enabled = true; + + err = sip_transp_laddr(t.srvv[0]->sip, &laddr, tp, NULL); + if (err) + return err; + + /* NOTE: angel brackets needed to parse ;transport parameter */ + if (re_snprintf(aor, sizeof(aor), + ";outbound=\"sip:%J\"", + USER, + PASS, + DOMAIN, + &laddr) < 0) + return ENOMEM; + + err = ua_init("test", true, true, true, false); + TEST_ERR(err); + + err = ua_alloc(&t.ua, aor); + TEST_ERR(err); + + err = uag_event_register(ua_event_handler, &t); + if (err) + goto out; + + /* run main-loop with timeout, wait for events */ + err = re_main_timeout(5000); + if (err) + goto out; + + if (t.err) { + err = t.err; + goto out; + } + + ASSERT_TRUE(t.srvv[0]->n_register_req > 0); + ASSERT_EQ(tp, t.srvv[0]->tp_last); + ASSERT_TRUE(t.got_register_ok > 0); + + out: + if (err) { + warning("selftest: ua_register test failed (%m)\n", err); + } + uag_event_unregister(ua_event_handler); + test_reset(&t); + + ua_stop_all(true); + ua_close(); + + return err; +} -- cgit v1.2.3 From c9f404dd73c4f936aa763e81a4d0f908004b7d2e Mon Sep 17 00:00:00 2001 From: "Alfred E. Heggestad" Date: Sun, 3 Apr 2016 18:13:04 +0200 Subject: auth test: add all transports --- test/sip/sipsrv.c | 2 +- test/sip/sipsrv.h | 2 +- test/ua.c | 33 ++++++++++++++++++++++++++------- 3 files changed, 28 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/test/sip/sipsrv.c b/test/sip/sipsrv.c index 8d9bd8e..686d587 100644 --- a/test/sip/sipsrv.c +++ b/test/sip/sipsrv.c @@ -1,5 +1,5 @@ /** - * @file mock/sipsrv.c Mock SIP server + * @file sip/sipsrv.c Mock SIP server * * Copyright (C) 2010 - 2015 Creytiv.com */ diff --git a/test/sip/sipsrv.h b/test/sip/sipsrv.h index 4690ffe..aa136e0 100644 --- a/test/sip/sipsrv.h +++ b/test/sip/sipsrv.h @@ -1,5 +1,5 @@ /** - * @file mock/sipsrv.h Mock SIP server -- interface + * @file sip/sipsrv.h Mock SIP server -- interface * * Copyright (C) 2010 - 2016 Creytiv.com */ diff --git a/test/ua.c b/test/ua.c index 11cd020..2cfbce8 100644 --- a/test/ua.c +++ b/test/ua.c @@ -348,10 +348,9 @@ int test_ua_register_dns(void) #define PASS "password" #define DOMAIN "localhost" -int test_ua_register_auth(void) +static int reg_auth(enum sip_transp tp) { struct sa laddr; - enum sip_transp tp = SIP_TRANSP_UDP; struct test t; char aor[256]; int err; @@ -379,16 +378,14 @@ int test_ua_register_auth(void) /* NOTE: angel brackets needed to parse ;transport parameter */ if (re_snprintf(aor, sizeof(aor), - ";outbound=\"sip:%J\"", + ";outbound=\"sip:%J;transport=%s\"", USER, PASS, DOMAIN, - &laddr) < 0) + &laddr, + sip_transp_name(tp)) < 0) return ENOMEM; - err = ua_init("test", true, true, true, false); - TEST_ERR(err); - err = ua_alloc(&t.ua, aor); TEST_ERR(err); @@ -417,6 +414,28 @@ int test_ua_register_auth(void) uag_event_unregister(ua_event_handler); test_reset(&t); + + return err; +} + + +int test_ua_register_auth(void) +{ + int err; + + err = ua_init("test", true, true, true, false); + TEST_ERR(err); + + err |= reg_auth(SIP_TRANSP_UDP); + TEST_ERR(err); + err |= reg_auth(SIP_TRANSP_TCP); + TEST_ERR(err); +#ifdef USE_TLS + err |= reg_auth(SIP_TRANSP_TLS); + TEST_ERR(err); +#endif + + out: ua_stop_all(true); ua_close(); -- cgit v1.2.3