From patchwork Tue Sep 17 02:33:21 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 823 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director10.mail.ord1d.rsapps.net ([172.31.255.6]) by backend30.mail.ord1d.rsapps.net with LMTP id wEs4DPrSgF3QPQAAIUCqbw for ; Tue, 17 Sep 2019 08:35:06 -0400 Received: from proxy5.mail.iad3b.rsapps.net ([172.31.255.6]) by director10.mail.ord1d.rsapps.net with LMTP id wJZ8CfrSgF3JJwAApN4f7A ; Tue, 17 Sep 2019 08:35:06 -0400 Received: from smtp12.gate.iad3b ([172.31.255.6]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy5.mail.iad3b.rsapps.net with LMTP id aOGPA/rSgF28bwAA13hMnw ; Tue, 17 Sep 2019 08:35:06 -0400 X-Spam-Threshold: 95 X-Spam-Score: 0 X-Spam-Flag: NO X-Virus-Scanned: OK X-Orig-To: openvpnslackdevel@openvpn.net X-Originating-Ip: [216.105.38.7] Authentication-Results: smtp12.gate.iad3b.rsapps.net; iprev=pass policy.iprev="216.105.38.7"; spf=pass smtp.mailfrom="openvpn-devel-bounces@lists.sourceforge.net" smtp.helo="lists.sourceforge.net"; dkim=fail (signature verification failed) header.d=sourceforge.net; dkim=fail (signature verification failed) header.d=sf.net; dmarc=none (p=nil; dis=none) header.from=rfc2549.org X-Suspicious-Flag: YES X-Classification-ID: 932f0fa4-d947-11e9-8062-525400ae1f9d-1-1 Received: from [216.105.38.7] ([216.105.38.7:42442] helo=lists.sourceforge.net) by smtp12.gate.iad3b.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id F8/12-28521-9F2D08D5; Tue, 17 Sep 2019 08:35:05 -0400 Received: from [127.0.0.1] (helo=sfs-ml-2.v29.lw.sourceforge.com) by sfs-ml-2.v29.lw.sourceforge.com with esmtp (Exim 4.90_1) (envelope-from ) id 1iACfk-0002ay-AL; Tue, 17 Sep 2019 12:33:32 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-2.v29.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) (envelope-from ) id 1iACfi-0002aq-GI for openvpn-devel@lists.sourceforge.net; Tue, 17 Sep 2019 12:33:30 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:MIME-Version:Content-Type:Content-Transfer-Encoding: Content-ID:Content-Description:Resent-Date:Resent-From:Resent-Sender: Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help:List-Unsubscribe: List-Subscribe:List-Post:List-Owner:List-Archive; bh=kNGipD6VZC1XE68GEE56rwTa+BxJOHFN9l5+4dUqlcM=; b=BtpJWphXlQ7kz/guq3mOpakGVZ TazlwFAapvgNx2BY5UWRBxdgG5bBw6AqI/NnlbO7WlezYJGWjClZTj5QruUBipt82qd01DtWX2oU4 4UE0p/wub4yGekLVPQMGjBXWRLVXzv6YUtajj29odF32rRWvpVWxL4EQBPyqpR4Fe3sY=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From:Sender:Reply-To :MIME-Version:Content-Type:Content-Transfer-Encoding:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=kNGipD6VZC1XE68GEE56rwTa+BxJOHFN9l5+4dUqlcM=; b=Ugb81H0xBwyInLVZ/lBZKTytA+ 9ue4GwcNImwTAUZXfy4FJLMJiTv62/ufIto2agWDL3SmCuYb+9p+rZSSRAQR3jz4WKSa1Op/fV0OY 0sZQwcbhXKlt5T/NEREb6CgxlbeAF6vwQREx2p6Ryre4ztovfYYIVgEpko6nqlxHJV9g=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLSv1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.90_1) id 1iACfg-001Ezs-PZ for openvpn-devel@lists.sourceforge.net; Tue, 17 Sep 2019 12:33:30 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.92.2 (FreeBSD)) (envelope-from ) id 1iACfZ-000J2L-Sx; Tue, 17 Sep 2019 14:33:21 +0200 Received: (nullmailer pid 16038 invoked by uid 10006); Tue, 17 Sep 2019 12:33:21 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Tue, 17 Sep 2019 14:33:21 +0200 Message-Id: <20190917123321.15993-1-arne@rfc2549.org> X-Mailer: git-send-email 2.17.1 In-Reply-To: <4ae4ef50-efbe-c744-7133-7f926052be0a@sf.lists.topphemmelig.net> References: <4ae4ef50-efbe-c744-7133-7f926052be0a@sf.lists.topphemmelig.net> X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. 0.0 URIBL_BLOCKED ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [URIs: makefile.am] 0.2 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail domains are different 0.0 SPF_NONE SPF: sender does not publish an SPF Record 0.0 SPF_HELO_NONE SPF: HELO does not publish an SPF Record 0.3 AWL AWL: Adjusted score from AWL reputation of From: address X-Headers-End: 1iACfg-001Ezs-PZ Subject: [Openvpn-devel] [PATCH v7 7/7] Implement unit tests for auth-gen-token X-BeenThere: openvpn-devel@lists.sourceforge.net X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Arne Schwabe MIME-Version: 1.0 Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox From: Arne Schwabe The unit test is breaking the 80 char limit in some places but the remaining lines it breaks the limit I feel forcing the 80 char limit will impair readibility Patch V2: adapt unit tests to other V2 patches Patch V4: Resolve rebase conflicts Patch V5: Add \ lost in rebase that broke compilation Patch V7: Fix unit test failure, try to stay below 80 Acked-By: David Sommerseth --- tests/unit_tests/openvpn/Makefile.am | 18 +- tests/unit_tests/openvpn/test_auth_token.c | 394 +++++++++++++++++++++ 2 files changed, 411 insertions(+), 1 deletion(-) create mode 100644 tests/unit_tests/openvpn/test_auth_token.c diff --git a/tests/unit_tests/openvpn/Makefile.am b/tests/unit_tests/openvpn/Makefile.am index d015b293..60e84639 100644 --- a/tests/unit_tests/openvpn/Makefile.am +++ b/tests/unit_tests/openvpn/Makefile.am @@ -6,7 +6,7 @@ if HAVE_LD_WRAP_SUPPORT test_binaries += argv_testdriver buffer_testdriver endif -test_binaries += crypto_testdriver packet_id_testdriver +test_binaries += crypto_testdriver packet_id_testdriver auth_token_testdriver if HAVE_LD_WRAP_SUPPORT test_binaries += tls_crypt_testdriver endif @@ -94,3 +94,19 @@ networking_testdriver_SOURCES = test_networking.c mock_msg.c \ $(openvpn_srcdir)/packet_id.c \ $(openvpn_srcdir)/platform.c endif + +auth_token_testdriver_CFLAGS = @TEST_CFLAGS@ \ + -I$(openvpn_includedir) -I$(compat_srcdir) -I$(openvpn_srcdir) \ + $(OPTIONAL_CRYPTO_CFLAGS) +auth_token_testdriver_LDFLAGS = @TEST_LDFLAGS@ \ + $(OPTIONAL_CRYPTO_LIBS) + +auth_token_testdriver_SOURCES = test_auth_token.c mock_msg.c \ + $(openvpn_srcdir)/buffer.c \ + $(openvpn_srcdir)/crypto.c \ + $(openvpn_srcdir)/crypto_mbedtls.c \ + $(openvpn_srcdir)/crypto_openssl.c \ + $(openvpn_srcdir)/otime.c \ + $(openvpn_srcdir)/packet_id.c \ + $(openvpn_srcdir)/platform.c \ + $(openvpn_srcdir)/base64.c diff --git a/tests/unit_tests/openvpn/test_auth_token.c b/tests/unit_tests/openvpn/test_auth_token.c new file mode 100644 index 00000000..6b30dfbd --- /dev/null +++ b/tests/unit_tests/openvpn/test_auth_token.c @@ -0,0 +1,394 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2016-2018 Fox Crypto B.V. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#elif defined(_MSC_VER) +#include "config-msvc.h" +#endif + +#include "syshead.h" + +#include +#include +#include +#include +#include +#include +#include + +#include "auth_token.c" + +#include "mock_msg.h" + +struct test_context { + struct tls_multi multi; + struct key_type kt; + struct user_pass up; + struct tls_session session; +}; + +/* Dummy functions that do nothing to mock the functionality */ +void +send_push_reply_auth_token(struct tls_multi *multi) +{ +} + +void +auth_set_client_reason(struct tls_multi *multi, const char *reason) +{ + +} + +static const char *now0key0 = "SESS_ID_AT_0123456789abcdefAAAAAAAAAAAAAAAAAAAAAE5JsQJOVfo8jnI3RL3tBaR5NkE4yPfcylFUHmHSc5Bu"; + +static const char *zeroinline = "-----BEGIN OpenVPN auth-token server key-----\n" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=\n" + "-----END OpenVPN auth-token server key-----"; + +static const char *allx01inline = "-----BEGIN OpenVPN auth-token server key-----\n" + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB\n" + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB\n" + "AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQE=\n" + "-----END OpenVPN auth-token server key-----"; + +static const char *random_key = "-----BEGIN OpenVPN auth-token server key-----\n" + "+mmmf7IQ5cymtMVjKYTWk8IOcYanRlpQmV9Tb3EjkHYxueBVDg3yqRgzeBlVGzNLD//rAPiOVhau\n" + "3NDBjNOQB8951bfs7Cc2mYfay92Bh2gRJ5XEM/DMfzCWN+7uU6NWoTTHr4FuojnIQtjtqVAj/JS9\n" + "w+dTSp/vYHl+c7uHd19uVRu/qLqV85+rm4tUGIjO7FfYuwyPqwmhuIsi3hs9QkSimh888FmBpoKY\n" + "/tbKVTJZmSERKti9KEwtV2eVAR0znN5KW7lCB3mHVAhN7bUpcoDjfCzYIFARxwswTFu9gFkwqUMY\n" + "I1KUOgIsVNs4llACioeXplYekWETR+YkJwDc/A==\n" + "-----END OpenVPN auth-token server key-----"; + +static const char *random_token = "SESS_ID_AT_ThhRItzOKNKrh3dfAAAAAFwzHpwAAAAAXDMenDdrq0RoH3dkA1f7O3wO+7kZcx2DusVZrRmFlWQM9HOb"; + + +static int +setup(void **state) +{ + struct test_context *ctx = calloc(1, sizeof(*ctx)); + *state = ctx; + + struct key key = { 0 }; + + ctx->kt = auth_token_kt(); + if (!ctx->kt.digest) + { + return 0; + } + ctx->multi.opt.auth_token_generate = true; + ctx->multi.opt.auth_token_lifetime = 3000; + + ctx->session.opt = calloc(1, sizeof(struct tls_options)); + ctx->session.opt->renegotiate_seconds = 120; + ctx->session.opt->auth_token_lifetime = 3000; + + strcpy(ctx->up.username, "test user name"); + strcpy(ctx->up.password, "ignored"); + + init_key_ctx(&ctx->multi.opt.auth_token_key, &key, &ctx->kt, false, "TEST"); + + now = 0; + return 0; +} + +static int +teardown(void **state) +{ + struct test_context *ctx = (struct test_context *) *state; + + free_key_ctx(&ctx->multi.opt.auth_token_key); + wipe_auth_token(&ctx->multi); + + free(ctx->session.opt); + free(ctx); + + return 0; +} + +static void +auth_token_basic_test(void **state) +{ + struct test_context *ctx = (struct test_context *) *state; + + generate_auth_token(&ctx->up, &ctx->multi); + strcpy(ctx->up.password, ctx->multi.auth_token); + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK); +} + +static void +auth_token_fail_invalid_key(void **state) +{ + struct test_context *ctx = (struct test_context *) *state; + + generate_auth_token(&ctx->up, &ctx->multi); + strcpy(ctx->up.password, ctx->multi.auth_token); + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK); + + /* Change auth-token key */ + struct key key; + memset(&key, '1', sizeof(key)); + free_key_ctx(&ctx->multi.opt.auth_token_key); + init_key_ctx(&ctx->multi.opt.auth_token_key, &key, &ctx->kt, false, "TEST"); + + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), 0); + + /* Load original test key again */ + memset(&key, 0, sizeof(key)); + free_key_ctx(&ctx->multi.opt.auth_token_key); + init_key_ctx(&ctx->multi.opt.auth_token_key, &key, &ctx->kt, false, "TEST"); + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK); + +} + +static void +auth_token_test_timeout(void **state) +{ + struct test_context *ctx = (struct test_context *) *state; + + now = 100000; + generate_auth_token(&ctx->up, &ctx->multi); + strcpy(ctx->up.password, ctx->multi.auth_token); + + /* No time has passed */ + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK); + + /* Token before validity, should be rejected */ + now = 100000 - 100; + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK|AUTH_TOKEN_EXPIRED); + + /* Token still in validity, should be accepted */ + now = 100000 + 2*ctx->session.opt->renegotiate_seconds - 20; + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK); + + /* Token past validity, should be rejected */ + now = 100000 + 2*ctx->session.opt->renegotiate_seconds + 20; + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK|AUTH_TOKEN_EXPIRED); + + /* Check if the mode for a client that never updates its token works */ + ctx->multi.auth_token_initial = strdup(ctx->up.password); + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK); + + /* But not when we reached our timeout */ + now = 100000 + ctx->session.opt->auth_token_lifetime + 1; + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK|AUTH_TOKEN_EXPIRED); + + free(ctx->multi.auth_token_initial); + ctx->multi.auth_token_initial = NULL; + + /* regenerate the token util it hits the expiry */ + now = 100000; + while (now < 100000 + ctx->session.opt->auth_token_lifetime + 1) + { + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK); + generate_auth_token(&ctx->up, &ctx->multi); + strcpy(ctx->up.password, ctx->multi.auth_token); + now += ctx->session.opt->renegotiate_seconds; + } + + + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK|AUTH_TOKEN_EXPIRED); + ctx->multi.opt.auth_token_lifetime = 0; + + /* Non expiring token should be fine */ + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK); +} + +static void +zerohmac(char *token) +{ + char *hmacstart = token + AUTH_TOKEN_SESSION_ID_LEN + + strlen(SESSION_ID_PREFIX) + 2*sizeof(uint64_t); + memset(hmacstart, 0x8d, strlen(hmacstart)); +} + +static void +auth_token_test_known_keys(void **state) +{ + struct test_context *ctx = (struct test_context *) *state; + + now = 0; + /* Preload the session id so the same session id is used here */ + ctx->multi.auth_token = strdup(now0key0); + + /* Zero the hmac part to ensure we have a newly generated token */ + zerohmac(ctx->multi.auth_token); + + generate_auth_token(&ctx->up, &ctx->multi); + + assert_string_equal(now0key0, ctx->multi.auth_token); + + strcpy(ctx->up.password, ctx->multi.auth_token); + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK); +} + +static const char *lastsesion_statevalue; +void +setenv_str(struct env_set *es, const char *name, const char *value) +{ + if (streq(name, "session_state")) + { + lastsesion_statevalue = value; + } +} + +static void +auth_token_test_empty_user(void **state) +{ + struct test_context *ctx = (struct test_context *) *state; + + CLEAR(ctx->up.username); + now = 0; + + generate_auth_token(&ctx->up, &ctx->multi); + strcpy(ctx->up.password, ctx->multi.auth_token); + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK); + + now = 100000; + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK|AUTH_TOKEN_EXPIRED); + strcpy(ctx->up.username, "test user name"); + + now = 0; + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK|AUTH_TOKEN_VALID_EMPTYUSER); + + strcpy(ctx->up.username, "test user name"); + now = 100000; + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + AUTH_TOKEN_HMAC_OK|AUTH_TOKEN_EXPIRED|AUTH_TOKEN_VALID_EMPTYUSER); + + zerohmac(ctx->up.password); + assert_int_equal(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session), + 0); +} + +static void +auth_token_test_env(void **state) +{ + struct test_context *ctx = (struct test_context *) *state; + + ctx->multi.auth_token_state_flags = 0; + ctx->multi.auth_token = NULL; + add_session_token_env(&ctx->session, &ctx->multi, &ctx->up); + assert_string_equal(lastsesion_statevalue, "Initial"); + + ctx->multi.auth_token_state_flags = 0; + strcpy(ctx->up.password, now0key0); + add_session_token_env(&ctx->session, &ctx->multi, &ctx->up); + assert_string_equal(lastsesion_statevalue, "Invalid"); + + ctx->multi.auth_token_state_flags = AUTH_TOKEN_HMAC_OK; + add_session_token_env(&ctx->session, &ctx->multi, &ctx->up); + assert_string_equal(lastsesion_statevalue, "Authenticated"); + + ctx->multi.auth_token_state_flags = AUTH_TOKEN_HMAC_OK|AUTH_TOKEN_EXPIRED; + add_session_token_env(&ctx->session, &ctx->multi, &ctx->up); + assert_string_equal(lastsesion_statevalue, "Expired"); + + ctx->multi.auth_token_state_flags = AUTH_TOKEN_HMAC_OK|AUTH_TOKEN_VALID_EMPTYUSER; + add_session_token_env(&ctx->session, &ctx->multi, &ctx->up); + assert_string_equal(lastsesion_statevalue, "AuthenticatedEmptyUser"); + + ctx->multi.auth_token_state_flags = AUTH_TOKEN_HMAC_OK|AUTH_TOKEN_EXPIRED|AUTH_TOKEN_VALID_EMPTYUSER; + add_session_token_env(&ctx->session, &ctx->multi, &ctx->up); + assert_string_equal(lastsesion_statevalue, "ExpiredEmptyUser"); +} + +static void +auth_token_test_random_keys(void **state) +{ + struct test_context *ctx = (struct test_context *) *state; + + now = 0x5c331e9c; + /* Preload the session id so the same session id is used here */ + ctx->multi.auth_token = strdup(random_token); + + free_key_ctx(&ctx->multi.opt.auth_token_key); + auth_token_init_secret(&ctx->multi.opt.auth_token_key, INLINE_FILE_TAG, random_key); + + /* Zero the hmac part to ensure we have a newly generated token */ + zerohmac(ctx->multi.auth_token); + + generate_auth_token(&ctx->up, &ctx->multi); + + assert_string_equal(random_token, ctx->multi.auth_token); + + strcpy(ctx->up.password, ctx->multi.auth_token); + assert_true(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session)); +} + + +static void +auth_token_test_key_load(void **state) +{ + struct test_context *ctx = (struct test_context *) *state; + + free_key_ctx(&ctx->multi.opt.auth_token_key); + auth_token_init_secret(&ctx->multi.opt.auth_token_key, INLINE_FILE_TAG, zeroinline); + strcpy(ctx->up.password, now0key0); + assert_true(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session)); + + free_key_ctx(&ctx->multi.opt.auth_token_key); + auth_token_init_secret(&ctx->multi.opt.auth_token_key, INLINE_FILE_TAG, allx01inline); + assert_false(verify_auth_token(&ctx->up, &ctx->multi, &ctx->session)); +} + +int +main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup_teardown(auth_token_basic_test, setup, teardown), + cmocka_unit_test_setup_teardown(auth_token_fail_invalid_key, setup, teardown), + cmocka_unit_test_setup_teardown(auth_token_test_known_keys, setup, teardown), + cmocka_unit_test_setup_teardown(auth_token_test_empty_user, setup, teardown), + cmocka_unit_test_setup_teardown(auth_token_test_env, setup, teardown), + cmocka_unit_test_setup_teardown(auth_token_test_random_keys, setup, teardown), + cmocka_unit_test_setup_teardown(auth_token_test_key_load, setup, teardown), + cmocka_unit_test_setup_teardown(auth_token_test_timeout, setup, teardown), + }; + +#if defined(ENABLE_CRYPTO_OPENSSL) + OpenSSL_add_all_algorithms(); +#endif + + int ret = cmocka_run_group_tests_name("auth-token tests", tests, NULL, NULL); + + return ret; +}