diff --git a/.github/workflows/run-on-arch.yml b/.github/workflows/run-on-arch.yml new file mode 100644 index 000000000..6be3488ce --- /dev/null +++ b/.github/workflows/run-on-arch.yml @@ -0,0 +1,39 @@ +on: [push, pull_request] + +jobs: + build_job: + # The host should always be linux + runs-on: ubuntu-20.04 + name: Build on ${{ matrix.distro }} ${{ matrix.arch }} + + strategy: + matrix: + include: + - arch: aarch64 + distro: bullseye + + steps: + - uses: actions/checkout@v4 + + - uses: uraimo/run-on-arch-action@v2 + name: Build artifact + id: build + with: + arch: ${{ matrix.arch }} + distro: ${{ matrix.distro }} + + # Not required, but speeds up builds + githubToken: ${{ github.token }} + + install: | + case "${{ matrix.distro }}" in + ubuntu*|jessie|stretch|buster|bullseye) + apt-get update -q -y + apt-get install -q -y cmake gcc g++ libssl-dev ninja-build + ;; + esac + + run: | + cmake -G Ninja -B build -DCMAKE_C_FLAGS="-Werror" + cmake --build build -j --target retest + ./build/test/retest -r -v diff --git a/CMakeLists.txt b/CMakeLists.txt index 117e2c7b7..355355ec0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -656,6 +656,9 @@ if(LIBRE_BUILD_STATIC) if(MSVC) set_target_properties(re PROPERTIES OUTPUT_NAME "re-static") + if(NOT LIBRE_BUILD_SHARED) + set(PC_LIBNAME "re-static") + endif() endif() endif() @@ -668,6 +671,28 @@ if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) add_subdirectory(packaging) endif() +if(NOT PC_LIBNAME) + set(PC_LIBNAME "re") +endif() +set(PC_REQUIRES "") +set(PC_LINKLIBS "") +foreach(item IN LISTS RE_LIBS) + if(item STREQUAL "Threads::Threads") + list(APPEND PC_LINKLIBS ${CMAKE_THREADS_LIBS_INIT}) + elseif(item STREQUAL "OpenSSL::Crypto") + list(APPEND PC_REQUIRES "libcrypto") + elseif(item STREQUAL "OpenSSL::SSL") + list(APPEND PC_REQUIRES "libssl") + elseif(item STREQUAL "ZLIB::ZLIB") + list(APPEND PC_REQUIRES "zlib") + elseif(item MATCHES "^-|/") + list(APPEND PC_LINKLIBS "${item}") + else() + list(APPEND PC_LINKLIBS "-l${item}") + endif() +endforeach() +list(JOIN PC_LINKLIBS " " PC_LINKLIBS) +list(JOIN PC_REQUIRES " " PC_REQUIRES) configure_file(packaging/libre.pc.in libre.pc @ONLY) diff --git a/include/re_httpauth.h b/include/re_httpauth.h index 758a90862..d548e874e 100644 --- a/include/re_httpauth.h +++ b/include/re_httpauth.h @@ -70,6 +70,12 @@ struct httpauth_digest_resp { struct pl cnonce; struct pl qop; + struct pl algorithm; + struct pl charset; + struct pl userhash; + void (*hashh)(const uint8_t *, size_t, uint8_t *); + size_t hash_length; + struct mbuf *mb; }; @@ -117,6 +123,9 @@ int httpauth_digest_response_full(struct httpauth_digest_enc_resp **presp, const struct httpauth_digest_chall *chall, const struct pl *method, const char *uri, const char *user, const char *passwd, const char *qop, const char *entitybody, const char *charset, const bool userhash); +int httpauth_digest_verify(struct httpauth_digest_chall_req *req, + const struct pl *hval, const struct pl *method, const char *etag, + const char *user, const char *passwd, const char *entitybody); int httpauth_digest_chall_req_print(struct re_printf *pf, const struct httpauth_digest_chall_req *req); @@ -127,7 +136,6 @@ int httpauth_digest_chall_request_full(struct httpauth_digest_chall_req **preq, const char *opaque, const bool stale, const char *algo, const char *qop, const char *charset, const bool userhash); - struct httpauth_basic *httpauth_basic_alloc(void); int httpauth_basic_decode(struct httpauth_basic *basic, const struct pl *hval); diff --git a/include/re_tmr.h b/include/re_tmr.h index 17173f34f..ef9d0a6ce 100644 --- a/include/re_tmr.h +++ b/include/re_tmr.h @@ -6,6 +6,7 @@ #include "re_thread.h" +#include "re_atomic.h" /** * Defines the timeout handler @@ -19,7 +20,8 @@ struct tmrl; /** Defines a timer */ struct tmr { struct le le; /**< Linked list element */ - mtx_t *lock; /**< Mutex lock */ + RE_ATOMIC bool active; /**< Timer is active */ + mtx_t *llock; /**< List Mutex lock */ tmr_h *th; /**< Timeout handler */ void *arg; /**< Handler argument */ uint64_t jfs; /**< Jiffies for timeout */ diff --git a/packaging/libre.pc.in b/packaging/libre.pc.in index 5817066f0..2df8f6c6a 100644 --- a/packaging/libre.pc.in +++ b/packaging/libre.pc.in @@ -7,6 +7,7 @@ Name: libre Description: @CMAKE_PROJECT_DESCRIPTION@ Version: @PROJECT_VERSION@ URL: @CMAKE_PROJECT_HOMEPAGE_URL@ -Libs: -L${libdir} -lre -Libs.private: -L${libdir} -lre -ldl -lssl -lcrypto -lz -lpthread +Libs: -L${libdir} -l@PC_LIBNAME@ +Libs.private: @PC_LINKLIBS@ +Requires.private: @PC_REQUIRES@ Cflags: -I${includedir} diff --git a/src/httpauth/digest.c b/src/httpauth/digest.c index 2c3d04ccf..43f7c0f0e 100644 --- a/src/httpauth/digest.c +++ b/src/httpauth/digest.c @@ -6,6 +6,7 @@ */ #include #include +#include #include #include #include @@ -70,6 +71,21 @@ static void challenge_decode(const struct pl *name, const struct pl *val, } +static void algorithm_decode(struct httpauth_digest_resp *resp, + const struct pl *val) +{ + resp->algorithm = *val; + if (pl_strstr(val, "SHA-256")) { + resp->hashh = &sha256; + resp->hash_length = SHA256_DIGEST_LENGTH; + } + else { + resp->hashh = &md5; + resp->hash_length = MD5_SIZE; + } +} + + static void response_decode(const struct pl *name, const struct pl *val, void *arg) { @@ -91,6 +107,12 @@ static void response_decode(const struct pl *name, const struct pl *val, resp->cnonce = *val; else if (!pl_casecmp(name, ¶m_qop)) resp->qop = *val; + else if (!pl_casecmp(name, ¶m_algorithm)) + algorithm_decode(resp, val); + else if (!pl_casecmp(name, ¶m_charset)) + resp->charset = *val; + else if (!pl_casecmp(name, ¶m_userhash)) + resp->userhash = *val; } @@ -243,7 +265,7 @@ int httpauth_digest_response_auth(const struct httpauth_digest_resp *resp, } -static uint32_t nc = 1; +static RE_ATOMIC uint32_t nc = 1; int httpauth_digest_make_response(struct httpauth_digest_resp **presp, const struct httpauth_digest_chall *chall, @@ -277,7 +299,7 @@ int httpauth_digest_make_response(struct httpauth_digest_resp **presp, pl_set_str(&resp->uri, path); resp->qop = chall->qop; - err = mbuf_printf(mb, "%x", nc); + err = mbuf_printf(mb, "%x", re_atomic_rlx(&nc)); err |= mbuf_write_u8(mb, 0); if (err) goto out; @@ -348,7 +370,8 @@ int httpauth_digest_make_response(struct httpauth_digest_resp **presp, 0 == pl_strcmp(&resp->qop, "auth")) { /* response = MD5(HA1:nonce:nonceCount:cnonce:qop:HA2) */ err = mbuf_printf(mb, "%w:%r:%x:%x:%r:%w", - ha1, sizeof(ha1), &resp->nonce, nc, cnonce, + ha1, sizeof(ha1), &resp->nonce, + re_atomic_rlx(&nc), cnonce, &resp->qop, ha2, sizeof(ha2)); } else { @@ -370,7 +393,7 @@ int httpauth_digest_make_response(struct httpauth_digest_resp **presp, if (err) goto out; - ++nc; + re_atomic_rlx_add(&nc, 1); mbuf_set_pos(mb, 0); pl_set_str(&resp->nc, (const char*) mbuf_buf(mb)); mbuf_set_pos(mb, p1); @@ -389,7 +412,7 @@ int httpauth_digest_make_response(struct httpauth_digest_resp **presp, int httpauth_digest_response_encode(const struct httpauth_digest_resp *resp, - struct mbuf *mb) + struct mbuf *mb) { int err; size_t s; @@ -488,6 +511,165 @@ static int generate_nonce(char **pnonce, const time_t ts, } +static int check_nonce(const char *req_nonce, const struct pl *resp_nonce, + const char *etag) +{ + struct pl pl = PL_INIT; + time_t ts; + char *renonce = NULL; + int err = 0; + + if (!req_nonce || !resp_nonce || !etag) + return EINVAL; + + pl = *resp_nonce; + pl.p = pl.p + (pl.l - 16); + pl.l = 16; + ts = (time_t) pl_x64(&pl); + + if (time(NULL) - ts > 300) { + err = ETIMEDOUT; + goto out; + } + + err = generate_nonce(&renonce, ts, etag, NULL); + if (err) + goto out; + + if (str_casecmp(req_nonce, renonce)) + err = EAUTH; + +out: + mem_deref(renonce); + return err; +} + + +static int digest_verify(struct httpauth_digest_chall_req *req, + struct httpauth_digest_resp *resp, const struct pl *method, + const char *user, const char *passwd, const char *entitybody) +{ + uint8_t *hash1 = NULL; + uint8_t *hash2 = NULL; + struct mbuf *mb = NULL; + int err = 0; + + mb = mbuf_alloc(str_len(user) + str_len(passwd) + + str_len(req->realm) + 2); + hash1 = mem_zalloc(resp->hash_length, NULL); + hash2 = mem_zalloc(resp->hash_length, NULL); + if (!mb || !hash1 || !hash2) { + err = ENOMEM; + goto out; + } + + /* HASH H2 */ + if (pl_strstr(&resp->qop, "auth-int")) { + if (!str_isset(entitybody)) + resp->hashh((uint8_t *)"", str_len(""), hash1); + else + resp->hashh((uint8_t *)entitybody, str_len(entitybody), + hash1); + + err = mbuf_printf(mb, "%r:%r:%w", method, &resp->uri, hash1, + resp->hash_length); + } + else { + err = mbuf_printf(mb, "%r:%r", method, &resp->uri); + } + + if (err) + goto out; + + resp->hashh(mb->buf, mb->end, hash2); + mbuf_rewind(mb); + + /* HASH H1 */ + if (pl_strcmp(&resp->username, user) != 0) { + err = EACCES; + goto out; + } + + err = mbuf_printf(mb, "%s:%r:%s", user, &resp->realm, passwd); + if (err) + goto out; + + resp->hashh(mb->buf, mb->end, hash1); + mbuf_rewind(mb); + + if (pl_strstr(&resp->algorithm, "-sess")) { + err = mbuf_printf(mb, "%w:%r:%r", + hash1, resp->hash_length, &resp->nonce, &resp->cnonce); + if (err) + goto out; + + resp->hashh(mb->buf, mb->end, hash1); + mbuf_rewind(mb); + } + + /* DIGEST */ + if (pl_isset(&resp->qop)) { + err = mbuf_printf(mb, "%w:%r:%r:%r:%r:%w", hash1, + resp->hash_length, &resp->nonce, &resp->nc, + &resp->cnonce, &resp->qop, hash2, resp->hash_length); + } + else { + err = mbuf_printf(mb, "%w:%r:%w", hash1, resp->hash_length, + &resp->nonce, hash2, resp->hash_length); + } + + if (err) + goto out; + + resp->hashh(mb->buf, mb->end, hash1); + mbuf_rewind(mb); + + /* VERIFICATION */ + err = pl_hex(&resp->response, hash2, resp->hash_length); + if (err) + goto out; + + err = mem_seccmp(hash1, hash2, resp->hash_length) == 0 ? 0 : EACCES; + +out: + mem_deref(hash1); + mem_deref(hash2); + mem_deref(mb); + + return err; +} + + +int httpauth_digest_verify(struct httpauth_digest_chall_req *req, + const struct pl *hval, const struct pl *method, const char *etag, + const char *user, const char *passwd, const char *entitybody) +{ + struct httpauth_digest_resp resp; + int err = 0; + + if (!req || !hval || !method || !user || !passwd) + return EINVAL; + + err = httpauth_digest_response_decode(&resp, hval); + if (err) + return err; + + if (pl_strcasecmp(&resp.realm, req->realm)) + return EINVAL; + + err = check_nonce(req->nonce, &resp.nonce, etag); + if (err == ETIMEDOUT || err == EAUTH) { + req->stale = true; + return EAUTH; + } + else if (err) { + return err; + } + + return digest_verify(req, &resp, method, user, passwd, entitybody); +} + + /** * Prints / encodes an HTTP digest request challenge * @@ -889,7 +1071,7 @@ int httpauth_digest_response_full(struct httpauth_digest_enc_resp **presp, /* create cnonce & nonce count */ resp->cnonce = rand_u32(); - resp->nc = nc++; + resp->nc = (uint32_t) re_atomic_rlx_add(&nc, 1); /* copy fields */ err = pl_strdup(&resp->realm, &chall->realm); diff --git a/src/rtp/sess.c b/src/rtp/sess.c index 4d6e5f565..78a0bb54a 100644 --- a/src/rtp/sess.c +++ b/src/rtp/sess.c @@ -56,9 +56,9 @@ struct rtcp_sess { uint32_t srate_tx; /**< Transmit sampling rate */ uint32_t srate_rx; /**< Receive sampling rate */ uint32_t interval; /**< RTCP interval in [ms] */ + mtx_t *lock; /**< Lock for rtcp_sess */ /* stats */ - mtx_t *lock; /**< Lock for txstat */ struct txstat txstat; /**< Local transmit statistics */ }; @@ -219,6 +219,7 @@ void rtcp_handler(struct rtcp_sess *sess, struct rtcp_msg *msg) if (!sess || !msg) return; + mtx_lock(sess->lock); switch (msg->hdr.pt) { case RTCP_SR: @@ -236,6 +237,8 @@ void rtcp_handler(struct rtcp_sess *sess, struct rtcp_msg *msg) default: break; } + + mtx_unlock(sess->lock); } @@ -303,8 +306,10 @@ void rtcp_set_srate(struct rtp_sock *rs, uint32_t srate_tx, uint32_t srate_rx) if (!sess) return; + mtx_lock(sess->lock); sess->srate_tx = srate_tx; sess->srate_rx = srate_rx; + mtx_unlock(sess->lock); } @@ -336,7 +341,9 @@ void rtcp_set_srate_rx(struct rtp_sock *rs, uint32_t srate_rx) if (!sess) return; + mtx_lock(sess->lock); sess->srate_rx = srate_rx; + mtx_unlock(sess->lock); } @@ -347,8 +354,10 @@ int rtcp_enable(struct rtcp_sess *sess, bool enabled, const char *cname) if (!sess) return EINVAL; + mtx_lock(sess->lock); sess->cname = mem_deref(sess->cname); err = str_dup(&sess->cname, cname); + mtx_unlock(sess->lock); if (err) return err; @@ -571,10 +580,11 @@ void rtcp_sess_rx_rtp(struct rtcp_sess *sess, struct rtp_header *hdr, if (!sess) return; + mtx_lock(sess->lock); mbr = get_member(sess, hdr->ssrc); if (!mbr) { DEBUG_NOTICE("could not add member: 0x%08x\n", hdr->ssrc); - return; + goto out; } if (!mbr->s) { @@ -582,7 +592,7 @@ void rtcp_sess_rx_rtp(struct rtcp_sess *sess, struct rtp_header *hdr, if (!mbr->s) { DEBUG_NOTICE("could not add sender: 0x%08x\n", hdr->ssrc); - return; + goto out; } /* first packet - init sequence number */ @@ -612,6 +622,8 @@ void rtcp_sess_rx_rtp(struct rtcp_sess *sess, struct rtp_header *hdr, mbr->s->last_rtp_ts = hdr->ts; mbr->s->rtp_rx_bytes += payload_size; +out: + mtx_unlock(sess->lock); } @@ -628,17 +640,19 @@ int rtcp_stats(struct rtp_sock *rs, uint32_t ssrc, struct rtcp_stats *stats) { const struct rtcp_sess *sess = rtp_rtcp_sess(rs); struct rtp_member *mbr; + int err = 0; if (!sess || !stats) return EINVAL; + mtx_lock(sess->lock); mbr = member_find(sess->members, ssrc); - if (!mbr) - return ENOENT; + if (!mbr) { + err = ENOENT; + goto out; + } - mtx_lock(sess->lock); stats->tx.sent = sess->txstat.psent; - mtx_unlock(sess->lock); stats->tx.lost = mbr->cum_lost; stats->tx.jit = mbr->jit; @@ -647,7 +661,7 @@ int rtcp_stats(struct rtp_sock *rs, uint32_t ssrc, struct rtcp_stats *stats) if (!mbr->s) { memset(&stats->rx, 0, sizeof(stats->rx)); - return 0; + goto out; } stats->rx.sent = mbr->s->received; @@ -655,24 +669,26 @@ int rtcp_stats(struct rtp_sock *rs, uint32_t ssrc, struct rtcp_stats *stats) stats->rx.jit = sess->srate_rx ? 1000000 * (mbr->s->jitter>>4) / sess->srate_rx : 0; - return 0; +out: + mtx_unlock(sess->lock); + return err; } static bool debug_handler(struct le *le, void *arg) { const struct rtp_member *mbr = le->data; - struct re_printf *pf = arg; + struct mbuf *mb = arg; int err; - err = re_hprintf(pf, " member 0x%08x: lost=%d Jitter=%.1fms" + err = mbuf_printf(mb, " member 0x%08x: lost=%d Jitter=%.1fms" " RTT=%.1fms\n", mbr->src, mbr->cum_lost, (double)mbr->jit/1000, (double)mbr->rtt/1000); if (mbr->s) { - err |= re_hprintf(pf, - " IP=%J psent=%u rcvd=%u\n", - &mbr->s->rtp_peer, mbr->s->psent, - mbr->s->received); + err |= mbuf_printf(mb, + " IP=%J psent=%u rcvd=%u\n", + &mbr->s->rtp_peer, mbr->s->psent, + mbr->s->received); } return err != 0; @@ -690,23 +706,35 @@ static bool debug_handler(struct le *le, void *arg) int rtcp_debug(struct re_printf *pf, const struct rtp_sock *rs) { const struct rtcp_sess *sess = rtp_rtcp_sess(rs); + struct mbuf *mb; int err = 0; if (!sess) return 0; - err |= re_hprintf(pf, "----- RTCP Session: -----\n"); - err |= re_hprintf(pf, " cname=%s SSRC=0x%08x/%u rx=%uHz\n", + mb = mbuf_alloc(64); + if (!mb) + return ENOMEM; + + err |= mbuf_printf(mb, "----- RTCP Session: -----\n"); + mtx_lock(sess->lock); + err |= mbuf_printf(mb, " cname=%s SSRC=0x%08x/%u rx=%uHz\n", sess->cname, rtp_sess_ssrc(sess->rs), rtp_sess_ssrc(sess->rs), sess->srate_rx); - hash_apply(sess->members, debug_handler, pf); + hash_apply(sess->members, debug_handler, mb); - mtx_lock(sess->lock); - err |= re_hprintf(pf, " TX: packets=%u, octets=%u\n", + err |= mbuf_printf(mb, " TX: packets=%u, octets=%u\n", sess->txstat.psent, sess->txstat.osent); mtx_unlock(sess->lock); + if (err) + goto out; + + err = re_hprintf(pf, "%b", mb->buf, mb->pos); + +out: + mem_deref(mb); return err; } diff --git a/src/tmr/tmr.c b/src/tmr/tmr.c index 3c1bdc780..2d53970b0 100644 --- a/src/tmr/tmr.c +++ b/src/tmr/tmr.c @@ -393,10 +393,16 @@ static void tmr_startcont_dbg(struct tmr *tmr, uint64_t delay, bool syncnow, if (!tmr || !tmrl) return; - if (!tmr->lock || !tmr->le.list) - lock = tmrl->lock; + /* Prevent multiple cancel race conditions */ + if (!re_atomic_acq(&tmr->active) && !th) + return; + + re_atomic_rls_set(&tmr->active, false); + + if (!tmr->llock || !tmr->le.list) + lock = tmrl->lock; /* use current list lock */ else - lock = tmr->lock; /* use old lock for unlinking */ + lock = tmr->llock; /* use old list lock for unlinking */ mtx_lock(lock); @@ -413,10 +419,10 @@ static void tmr_startcont_dbg(struct tmr *tmr, uint64_t delay, bool syncnow, tmr->arg = arg; tmr->file = file; tmr->line = line; - tmr->lock = tmrl->lock; + tmr->llock = tmrl->lock; if (!th) { - tmr->lock = NULL; + tmr->llock = NULL; mtx_unlock(lock); return; } @@ -445,6 +451,8 @@ static void tmr_startcont_dbg(struct tmr *tmr, uint64_t delay, bool syncnow, } } + re_atomic_rls_set(&tmr->active, true); + mtx_unlock(lock); } diff --git a/test/aulength.c b/test/aulength.c index 2b4f8f5b2..d61329bb4 100644 --- a/test/aulength.c +++ b/test/aulength.c @@ -23,8 +23,7 @@ int test_aulength(void) re_snprintf(path, sizeof(path), "%s/beep.wav", test_datapath()); int err = aufile_open(&af, &prm, path, AUFILE_READ); - if (err) - TEST_ERR(err); + TEST_ERR(err); size_t length = aufile_get_length(af, &prm); TEST_EQUALS(67, length); diff --git a/test/fmt.c b/test/fmt.c index 6eb9ef807..7b82deebb 100644 --- a/test/fmt.c +++ b/test/fmt.c @@ -622,10 +622,8 @@ int test_fmt_snprintf(void) const uint8_t v[] = {0xfa, 0xce, 0xb0, 0x0c}; struct sa sa4; const char addr4[] = "1.2.3.4"; -#ifdef HAVE_INET6 struct sa sa6; const char addr6[] = "2001:5c0:8fff:ffff::d"; -#endif char buf[128], sbuf[8]; int n, err; @@ -646,26 +644,22 @@ int test_fmt_snprintf(void) DEBUG_WARNING("sa_set_str4: %m\n", err); goto out; } -#ifdef HAVE_INET6 err = sa_set_str(&sa6, addr6, 0); if (err) { DEBUG_WARNING("sa_set_str6: %m\n", err); goto out; } -#endif (void)re_snprintf(buf, sizeof(buf), "%j", &sa4); if (0 != strcmp(buf, addr4)) { err = EINVAL; goto out; } -#ifdef HAVE_INET6 (void)re_snprintf(buf, sizeof(buf), "%j", &sa6); if (0 != strcmp(buf, addr6)) { err = EINVAL; goto out; } -#endif /* Overflow */ n = re_snprintf(buf, 3, "12"); diff --git a/test/httpauth.c b/test/httpauth.c index cc0c91ec4..950b7c64e 100644 --- a/test/httpauth.c +++ b/test/httpauth.c @@ -171,8 +171,8 @@ int test_httpauth_resp(void) PL("sip:creytiv.com;transport=udp"), PL("00000002"), PL("66a7a21e46ad8edd"), - PL("auth"), - NULL}, + PL("auth"), PL_INIT, PL_INIT, + PL_INIT, NULL, 0, NULL}, PL("REGISTER"), "\x1c\x0a\x98\x61\x5b\x7b\x37\xc6" "\x94\x51\xae\xb6\x4b\x2f\x11\x02", @@ -180,8 +180,9 @@ int test_httpauth_resp(void) }, { "Digest bogus tull", - {PL_INIT, PL_INIT, PL_INIT, PL_INIT, - PL_INIT, PL_INIT, PL_INIT, PL_INIT, NULL}, + {PL_INIT, PL_INIT, PL_INIT, PL_INIT, PL_INIT, + PL_INIT, PL_INIT, PL_INIT, PL_INIT, PL_INIT, + PL_INIT, NULL, 0 , NULL}, PL_INIT, "", EBADMSG @@ -420,7 +421,7 @@ int test_httpauth_digest_request(void) mb_printed = mbuf_alloc(512); if (!mb_refval || !mb_printed) { err = ENOMEM; - goto for_out; + goto out; } err = httpauth_digest_chall_request_full(&req, testv[i].realm, @@ -428,7 +429,7 @@ int test_httpauth_digest_request(void) testv[i].stale, testv[i].algorithm, testv[i].qop, testv[i].charset, testv[i].userhash); if (err == ENOMEM) { - goto for_out; + goto out; } else if (err != testv[i].err) { DEBUG_WARNING("[%d]" @@ -443,7 +444,7 @@ int test_httpauth_digest_request(void) if (err) { DEBUG_WARNING("[%d]" " No reference created %m\n", i, err); - goto for_out; + goto out; } err = mbuf_printf(mb_printed, "%H", @@ -451,14 +452,14 @@ int test_httpauth_digest_request(void) if (err) { DEBUG_WARNING("[%d]" " Digest request print error %m\n", i, err); - goto for_out; + goto out; } if (mb_refval->end != mb_printed->end) { DEBUG_WARNING("[%d] Expected header len %d, got %d\n", i, mb_refval->end, mb_printed->end); err = EINVAL; - goto for_out; + goto out; } if (memcmp(mb_refval->buf, mb_printed->buf, mb_refval->end)) { @@ -466,7 +467,7 @@ int test_httpauth_digest_request(void) mb_refval->buf, mb_refval->end, mb_printed->buf, mb_printed->end); err = EINVAL; - goto for_out; + goto out; } for_continue: @@ -475,7 +476,7 @@ int test_httpauth_digest_request(void) mem_deref(mb_printed); continue; -for_out: +out: mem_deref(req); mem_deref(mb_refval); mem_deref(mb_printed); @@ -590,7 +591,7 @@ int test_httpauth_digest_response(void) }, }; - int err; + int err = 0; for (size_t i = 0; i < RE_ARRAY_SIZE(testv); i++) { struct httpauth_digest_enc_resp *resp = NULL; @@ -599,7 +600,7 @@ int test_httpauth_digest_response(void) mb_printed = mbuf_alloc(512); if (!mb_printed) { err = ENOMEM; - goto for_out; + goto out; } err = httpauth_digest_response_full(&resp, &testv[i].chall, @@ -607,12 +608,12 @@ int test_httpauth_digest_response(void) testv[i].passwd, testv[i].qop, testv[i].entitybody, NULL, false); if (err == ENOMEM) { - goto for_out; + goto out; } else if (err) { DEBUG_WARNING("[%d]" " Could not generate response %m\n", i, err); - goto for_out; + goto out; } err = httpauth_digest_response_set_cnonce(resp, @@ -622,13 +623,13 @@ int test_httpauth_digest_response(void) if (err) { DEBUG_WARNING("[%d]" " Response recalculation failed %m\n", i, err); - goto for_out; + goto out; } err = mbuf_printf(mb_printed, "%H", httpauth_digest_response_print, resp); if (err) - goto for_out; + goto out; if (str_casecmp(resp->response, testv[i].precalc_digest) != 0) { @@ -637,7 +638,7 @@ int test_httpauth_digest_response(void) " Expected response %s, got %w\n", i, testv[i].precalc_digest, resp->response, resp->hash_length); - goto for_out; + goto out; } if (memcmp(testv[i].resp_hval, @@ -647,14 +648,14 @@ int test_httpauth_digest_response(void) " Expected header %s, got %b\n", i, testv[i].resp_hval, mb_printed->buf, mb_printed->end); - goto for_out; + goto out; } mb_printed = mem_deref (mb_printed); resp = mem_deref(resp); continue; -for_out: +out: mb_printed = mem_deref (mb_printed); resp = mem_deref(resp); break; @@ -662,3 +663,184 @@ int test_httpauth_digest_response(void) return err; } + + +int test_httpauth_digest_verification(void) +{ + static const struct { + const char *realm; + const char *domain; + const char *opaque; + const bool stale; + const char *algorithm; + const char *qop; + const char *charset; + const bool userhash; + + const char *etag; + const char *entitybody; + + const char *user; + const char *passwd; + const char *uri; + const struct pl method; + const char *huser; + } testv [] = { + /* qop=auth & normal algorithm */ + { + "/my/home", "example.com", + "185803523d335c8fe52cf633391d47f7", + false, "MD5", "auth", NULL, false, + "localhost:5060", NULL, "retest", "sec_passwd", + "example.com/my/home/something", PL("GET"), NULL, + }, + { + "/my/home", "example.com", + "185803523d335c8fe52cf633391d47f7", + false, "SHA-256", "auth", NULL, false, + "localhost:5060", NULL, "retest", "sec_passed", + "example.com/my/home/something", PL("GET"), NULL + }, + /* qop=auth & session algorithm */ + { + "/my/home", "example.com", + "185803523d335c8fe52cf633391d47f7", + false, "MD5-sess", "auth", NULL, false, + "localhost:5060", NULL, "retest", "sec_passed", + "example.com/my/home/something", PL("GET"), NULL + }, + { + "/my/home", "example.com", + "185803523d335c8fe52cf633391d47f7", + false, "SHA-256-sess", "auth", NULL, false, + "localhost:5060", NULL, "retest", "sec_passed", + "example.com/my/home/something", PL("GET"), NULL + }, + /* qop=auth-int & normal algorithm */ + { + "/my/home", "example.com", + "185803523d335c8fe52cf633391d47f7", + false, "MD5", "auth-int", NULL, false, + "localhost:5060", NULL, "retest", "sec_passed", + "example.com/my/home/something", PL("GET"), NULL + }, + { + "/my/home", "example.com", + "185803523d335c8fe52cf633391d47f7", + false, "SHA-256", "auth-int", NULL, false, + "localhost:5060", "Strange body with content", + "retest", "sec_passed", + "example.com/my/home/something", PL("GET"), NULL + }, + /* qop=auth-int & session algorithm */ + { + "/my/home", "example.com", + "185803523d335c8fe52cf633391d47f7", + false, "MD5-sess", "auth-int", NULL, false, + "localhost:5060", "NOT NULL", "retest", "sec_passed", + "example.com/my/home/something", PL("GET"), NULL + }, + { + "/my/home", "example.com", + "185803523d335c8fe52cf633391d47f7", + false, "SHA-256-sess", "auth-int", NULL, false, + "localhost:5060", "NULL as String :D", + "retest", "sec_passed", + "example.com/my/home/something", PL("GET"), NULL + }, + }; + + int err = 0; + for (size_t i = 0; i < RE_ARRAY_SIZE(testv); i++) { + struct httpauth_digest_chall_req *req = NULL; + struct httpauth_digest_enc_resp *resp = NULL; + struct httpauth_digest_chall chall; + struct mbuf *mb_req = NULL; + struct mbuf *mb_resp = NULL; + struct pl plreq; + struct pl plresp; + + mb_req = mbuf_alloc(512); + mb_resp = mbuf_alloc(512); + if (!mb_req || !mb_resp) { + err = ENOMEM; + DEBUG_WARNING("[%d]" + " Could not allocate memory buffers \n", i); + goto out; + } + + err = httpauth_digest_chall_request_full(&req, testv[i].realm, + testv[i].domain, testv[i].etag, testv[i].opaque, + testv[i].stale, testv[i].algorithm, testv[i].qop, + testv[i].charset, testv[i].userhash); + if (err) { + DEBUG_WARNING("[%d]" + " Could not generate request (%m)\n", i, err); + goto out; + } + + err = mbuf_printf(mb_req, "%H", + httpauth_digest_chall_req_print, req); + if (err) { + DEBUG_WARNING("[%d]" + " Could not write digest request (%m)", + i, err); + goto out; + } + + mbuf_set_pos(mb_req, 0); + pl_set_mbuf(&plreq, mb_req); + err = httpauth_digest_challenge_decode(&chall, &plreq); + if (err) { + DEBUG_WARNING("[%d] Could not" + " decode \"received\" challenge (%m)", + i, err); + goto out; + } + + err = httpauth_digest_response_full(&resp, &chall, + &testv[i].method, testv[i].uri, testv[i].user, + testv[i].passwd, testv[i].qop, testv[i].entitybody, + testv[i].charset, testv[i].userhash); + if (err) { + DEBUG_WARNING("[%d]" + " Could not generate response (%m)\n", i, err); + goto out; + } + + err = mbuf_printf(mb_resp, "%H", + httpauth_digest_response_print, resp); + if (err) { + DEBUG_WARNING("[%d] Could not" + " decode \"received\" response (%m)\n", + i, err); + goto out; + } + + mbuf_set_pos(mb_resp, 0); + pl_set_mbuf(&plresp, mb_resp); + err = httpauth_digest_verify(req, &plresp, + &testv[i].method, testv[i].etag, + testv[i].user, testv[i].passwd, testv[i].entitybody); + if (err) { + DEBUG_WARNING("[%d]" + " Verification failed (%m)\n", i, err); + goto out; + } + + mem_deref(req); + mem_deref(resp); + mem_deref(mb_req); + mem_deref(mb_resp); + continue; + +out: + mem_deref(req); + mem_deref(resp); + mem_deref(mb_req); + mem_deref(mb_resp); + break; + } + + return err; +} diff --git a/test/ice.c b/test/ice.c index df73ec9ec..078edff30 100644 --- a/test/ice.c +++ b/test/ice.c @@ -855,12 +855,10 @@ static const char *testv[] = { "6 1 TCP 1692401663 192.0.2.3 45687 typ srflx raddr" " 10.0.1.1 rport 8999 tcptype so", -#ifdef HAVE_INET6 "H76f0ae12 1 UDP 2130706431 fda8:de2d:e95f:4811::1 6054 typ host", "3113280040 1 UDP 2122255103 2001:aaaa:5ef5:79fb:1847:2c0d:a230:23ab 53329" " typ host", -#endif }; diff --git a/test/rtp.c b/test/rtp.c index 9e6305b7e..ca67f2d81 100644 --- a/test/rtp.c +++ b/test/rtp.c @@ -320,21 +320,17 @@ static const uint8_t rtcp_sdes[] = ""; -static int test_rtcp_decode_badmsg(void) +int test_rtcp_decode_badmsg(void) { struct rtcp_msg *msg = NULL; uint32_t ssrc = 0xcafebabe; - struct mbuf *mb; - int err = 0; - mb = mbuf_alloc(128); - if (!mb) { - err = ENOMEM; - goto out; - } + struct mbuf *mb = mbuf_alloc(128); + if (!mb) + return ENOMEM; - err = rtcp_encode(mb, RTCP_PSFB, RTCP_PSFB_SLI, - ssrc, ssrc, NULL, NULL); + int err = rtcp_encode(mb, RTCP_PSFB, RTCP_PSFB_SLI, + ssrc, ssrc, NULL, NULL); if (err) goto out; @@ -344,7 +340,8 @@ static int test_rtcp_decode_badmsg(void) mb->pos = 0; - if (EBADMSG != rtcp_decode(&msg, mb)) { + int ret = rtcp_decode(&msg, mb); + if (EBADMSG != ret && ret != ENOMEM) { err = EBADMSG; goto out; } @@ -413,10 +410,6 @@ int test_rtcp_decode(void) if (err) goto out; - err = test_rtcp_decode_badmsg(); - if (err) - return err; - out: mem_deref(msg); mem_deref(mb); diff --git a/test/sa.c b/test/sa.c index 5b2ea8037..8af178b6a 100644 --- a/test/sa.c +++ b/test/sa.c @@ -44,7 +44,6 @@ int test_sa_cmp(void) "1.2.3.4", 12344, false }, -#ifdef HAVE_INET6 { "0:0:0:0:0:0:0:0", 123, "::", 123, @@ -90,7 +89,6 @@ int test_sa_cmp(void) "fe80:0000:0000:0000:1215:58ff:fe2d:90ab", 3333, false }, -#endif }; size_t i; int err = 0; @@ -133,12 +131,10 @@ int test_sa_decode(void) {0, AF_INET, "1.2.3.4:0", "1.2.3.4", 0}, {EINVAL, AF_INET, "1.2.3.4", "", 0}, {EINVAL, AF_INET, "1.2.3.4.:1234", "", 0}, -#ifdef HAVE_INET6 {0, AF_INET6, "[::1]:1", "::1", 1}, {0, AF_INET6, "[fe80::215:58ff:fe2d:90ab]:3333", "fe80::215:58ff:fe2d:90ab", 3333}, {EINVAL, AF_INET6, "[::1]", "", 0}, -#endif }; uint32_t i; int err = 0; @@ -204,12 +200,10 @@ int test_sa_class(void) {true, false, false, "127.0.0.1"}, {true, false, false, "127.3.0.3"}, {false, true, false, "169.254.1.2"}, -#ifdef HAVE_INET6 {false, false, true, "::"}, {true, false, false, "::1"}, {false, true, false, "fe80::215:58ff:fe2d:90ab"}, {false, false, false, "2610:a0:c779:b::d1ad:35b4"} -#endif }; uint32_t i; int err = 0; @@ -279,11 +273,9 @@ int test_sa_ntop(void) {AF_INET, "0.0.0.0"}, {AF_INET, "1.2.3.4"}, {AF_INET, "255.254.253.128"}, -#ifdef HAVE_INET6 {AF_INET6, "::1"}, {AF_INET6, "fe80::215:58ff:fe2d:90ab"}, {AF_INET6, "2610:a0:c779:b::d1ad:35b4"} -#endif }; uint32_t i; int err = 0; diff --git a/test/sip.c b/test/sip.c index 1808a973c..2e6b8646e 100644 --- a/test/sip.c +++ b/test/sip.c @@ -86,11 +86,9 @@ int test_sip_addr(void) "\"Agmund Bolt\" " ";tag=foo123;bar=9d7j3", -#ifdef HAVE_INET6 /* RFC 5118 - SIP Torture Test Messages for IPv6 */ "\"Caller\" ", "\"Caller\" ", -#endif /* gruu */ "\"hei\" " @@ -165,11 +163,9 @@ int test_sip_via(void) {SIP_TRANSP_UDP, "1.2.3.4", 1234, "z9ghkdkasd"}, {SIP_TRANSP_TCP, "123.123.123.123", 0, "b0ajsd01abcdef918"}, {SIP_TRANSP_TCP, "myhost.com", 0, "b0ajsd01ab2838475"}, -#ifdef HAVE_INET6 {SIP_TRANSP_TCP, "fe80::215:58ff:fe2d:90ab", 5060, "b0ajs01cde38475"}, {SIP_TRANSP_TLS, "fe80::215:58ff:fe2d:90ab", 0, "47daasd5"} -#endif }; struct sip_msg *msg = NULL; struct mbuf *mb; @@ -198,11 +194,9 @@ int test_sip_via(void) ipaddr = !sa_set_str(&addr, testv[i].host, testv[i].port); -#ifdef HAVE_INET6 if (ipaddr && AF_INET6 == sa_af(&addr)) err = mbuf_printf(mb, "[%s]", testv[i].host); else -#endif err = mbuf_printf(mb, "%s", testv[i].host); if (err) goto out; diff --git a/test/stun.c b/test/stun.c index 378231189..903767c13 100644 --- a/test/stun.c +++ b/test/stun.c @@ -57,7 +57,6 @@ static const unsigned char respv4[] = "\x80\x28\x00\x04" "\xc0\x7d\x4c\x96"; -#ifdef HAVE_INET6 static const unsigned char respv6[] = "\x01\x01\x00\x48" "\x21\x12\xa4\x42" @@ -73,7 +72,6 @@ static const unsigned char respv6[] = "\x82\x92\xc2\x75\xbf\xe3\xed\x41" "\x80\x28\x00\x04" "\xc8\xfb\x0b\x4c"; -#endif static const uint32_t ice_prio = 0x6e0001ff; @@ -242,7 +240,6 @@ int test_stun_resp(void) if (err) return err; -#ifdef HAVE_INET6 resp.p = (char *)respv6; resp.l = sizeof(respv6) - 1; err = sa_set_str(&maddr, "2001:db8:1234:5678:11:2233:4455:6677", @@ -250,7 +247,6 @@ int test_stun_resp(void) if (err) return err; err = test_resp(&resp, &maddr); -#endif return err; } diff --git a/test/test.c b/test/test.c index cb23ed030..261c1d96f 100644 --- a/test/test.c +++ b/test/test.c @@ -125,6 +125,7 @@ static const struct test tests[] = { TEST(test_httpauth_basic_request), TEST(test_httpauth_digest_request), TEST(test_httpauth_digest_response), + TEST(test_httpauth_digest_verification), TEST(test_ice_cand), TEST(test_ice_loop), TEST(test_json), @@ -158,6 +159,7 @@ static const struct test tests[] = { TEST(test_rtcp_encode), TEST(test_rtcp_encode_afb), TEST(test_rtcp_decode), + TEST(test_rtcp_decode_badmsg), TEST(test_rtcp_packetloss), TEST(test_rtcp_twcc), TEST(test_sa_class), diff --git a/test/test.h b/test/test.h index 8b8c06e58..68a681e2c 100644 --- a/test/test.h +++ b/test/test.h @@ -229,6 +229,7 @@ int test_httpauth_resp(void); int test_httpauth_basic_request(void); int test_httpauth_digest_request(void); int test_httpauth_digest_response(void); +int test_httpauth_digest_verification(void); int test_ice_loop(void); int test_ice_cand(void); int test_json(void); @@ -268,6 +269,7 @@ int test_rtpext(void); int test_rtcp_encode(void); int test_rtcp_encode_afb(void); int test_rtcp_decode(void); +int test_rtcp_decode_badmsg(void); int test_rtcp_packetloss(void); int test_rtcp_twcc(void); int test_sa_class(void); diff --git a/test/uri.c b/test/uri.c index 83c4785c4..ccf93d952 100644 --- a/test/uri.c +++ b/test/uri.c @@ -37,7 +37,6 @@ int test_uri(void) "sip:atlanta.com;method=REGISTER?to=alice%40atlanta.com", "sip:alice;day=tuesday@atlanta.com", -#ifdef HAVE_INET6 /* IPv6 */ "sip:[::1];transport=udp", "sip:[::1]:1234;transport=udp", @@ -53,7 +52,6 @@ int test_uri(void) "sip:[2001:db8::10:5070]", "sip:[2001:db8::10]:5070", "sip:user@[2001:db8::10]", -#endif }; struct uri uri; struct mbuf mb; @@ -124,7 +122,6 @@ int test_uri_encode(void) PL("")}, "sip:user:pass@host:443/wss/;transport=wss" }, -#ifdef HAVE_INET6 {{PL("sip"), PL("user"), PL(""), @@ -135,7 +132,6 @@ int test_uri_encode(void) PL("")}, "sip:user@[::1]:1234;transport=udp" } -#endif }; struct mbuf mb; int err = EINVAL;