From patchwork Wed Aug 24 02:58:58 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arne Schwabe X-Patchwork-Id: 2720 Return-Path: Delivered-To: patchwork@openvpn.net Delivered-To: patchwork@openvpn.net Received: from director15.mail.ord1d.rsapps.net ([172.27.255.7]) by backend30.mail.ord1d.rsapps.net with LMTP id eF6dNtQgBmOfEgAAIUCqbw (envelope-from ) for ; Wed, 24 Aug 2022 09:00:04 -0400 Received: from proxy5.mail.iad3a.rsapps.net ([172.27.255.7]) by director15.mail.ord1d.rsapps.net with LMTP id YJRrNtQgBmNTLwAAIcMcQg (envelope-from ) for ; Wed, 24 Aug 2022 09:00:04 -0400 Received: from smtp20.gate.iad3a ([172.27.255.7]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) by proxy5.mail.iad3a.rsapps.net with LMTPS id 4BK1L9QgBmPEKQAAhn5joQ (envelope-from ) for ; Wed, 24 Aug 2022 09:00:04 -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: smtp20.gate.iad3a.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: ab5b823a-23ac-11ed-bc86-525400aab2f3-1-1 Received: from [216.105.38.7] ([216.105.38.7:34432] helo=lists.sourceforge.net) by smtp20.gate.iad3a.rsapps.net (envelope-from ) (ecelerity 4.2.38.62370 r(:)) with ESMTPS (cipher=DHE-RSA-AES256-GCM-SHA384) id 70/FD-29901-3D026036; Wed, 24 Aug 2022 09:00:04 -0400 Received: from [127.0.0.1] (helo=sfs-ml-4.v29.lw.sourceforge.com) by sfs-ml-4.v29.lw.sourceforge.com with esmtp (Exim 4.95) (envelope-from ) id 1oQpyR-0000ZX-0o; Wed, 24 Aug 2022 12:59:11 +0000 Received: from [172.30.20.202] (helo=mx.sourceforge.net) by sfs-ml-4.v29.lw.sourceforge.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.95) (envelope-from ) id 1oQpyP-0000ZQ-6h for openvpn-devel@lists.sourceforge.net; Wed, 24 Aug 2022 12:59:09 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sourceforge.net; s=x; h=Content-Transfer-Encoding:MIME-Version:References: In-Reply-To:Message-Id:Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: 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=MLeFo0TfYI4XFRmN48+Nn6lnSlEM5wD+RgeoZD9MpnI=; b=bqyxvd6kRfLB311s/W5LGuX19X xAvzb0k9mlHkC5N3ch3j1BMOtRJF4+gt8E8RN0ydAZEKLGZ1G3WG3G3oF4UVDGDILhCtNRyUtAsve 9Q8B0ECgdbOwu5veeqIadUD9qivp4kAvS6EYJoC0RCtthElP2D8o2AGAO/27fS3ZsRaE=; DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=sf.net; s=x ; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To:Message-Id: Date:Subject:To:From:Sender:Reply-To:Cc:Content-Type: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=MLeFo0TfYI4XFRmN48+Nn6lnSlEM5wD+RgeoZD9MpnI=; b=Ly0Ob+oeEPOJpmmyPFibolcSfS iMaf8cAiA7Z04UXlzl11IcwvPwPr/2EdWHZYictAPAG9Sj8O0N18qcDIY4LA6bYpTcv8J0K7DHvJv KnOb7X4ICs+yfFF8Bkpjkew5gBnjd8VNNQYXem52PSbylyflqtAm6BKDp27JoMAVtxxI=; Received: from mail.blinkt.de ([192.26.174.232]) by sfi-mx-1.v28.lw.sourceforge.com with esmtps (TLS1.2:ECDHE-RSA-AES256-GCM-SHA384:256) (Exim 4.95) id 1oQpyM-00FiUE-Vx for openvpn-devel@lists.sourceforge.net; Wed, 24 Aug 2022 12:59:08 +0000 Received: from kamera.blinkt.de ([2001:638:502:390:20c:29ff:fec8:535c]) by mail.blinkt.de with smtp (Exim 4.95 (FreeBSD)) (envelope-from ) id 1oQpyE-0004nz-4I for openvpn-devel@lists.sourceforge.net; Wed, 24 Aug 2022 14:58:58 +0200 Received: (nullmailer pid 81931 invoked by uid 10006); Wed, 24 Aug 2022 12:58:58 -0000 From: Arne Schwabe To: openvpn-devel@lists.sourceforge.net Date: Wed, 24 Aug 2022 14:58:58 +0200 Message-Id: <20220824125858.81885-1-arne@rfc2549.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20220520213250.3126372-1-arne@rfc2549.org> References: <20220520213250.3126372-1-arne@rfc2549.org> MIME-Version: 1.0 X-Spam-Report: Spam detection software, running on the system "util-spamd-1.v13.lw.sourceforge.com", has NOT identified this incoming email as spam. The original message has been attached to this so you can view it or label similar future email. If you have any questions, see the administrator of that system for details. Content preview: This allows a server to indicate a temporary problem on the server and allows the server to indicate how to proceed (i.e. move to the next server, retry the same server, wait a certain time, ...) This adds options_utils.c/h to be able to unit test the new function. Content analysis details: (0.3 points, 6.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- 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 X-Headers-End: 1oQpyM-00FiUE-Vx Subject: [Openvpn-devel] [PATCH v3] Implement AUTH_FAIL, TEMP message support 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: , Errors-To: openvpn-devel-bounces@lists.sourceforge.net X-getmail-retrieved-from-mailbox: Inbox This allows a server to indicate a temporary problem on the server and allows the server to indicate how to proceed (i.e. move to the next server, retry the same server, wait a certain time,...) This adds options_utils.c/h to be able to unit test the new function. Patch v2: Improve documentation, format man page better, comment that protocol-flags is not a user usable option. Patch v3: cleanup parse_auth_failed_temp to use a simple const string instead of a buffer Signed-off-by: Arne Schwabe Acked-by: Heiko Hund --- doc/man-sections/script-options.rst | 36 ++++++++++ src/openvpn/Makefile.am | 1 + src/openvpn/init.c | 9 ++- src/openvpn/openvpn.vcxproj | 2 + src/openvpn/openvpn.vcxproj.filters | 3 + src/openvpn/options.h | 9 ++- src/openvpn/options_util.c | 102 +++++++++++++++++++++++++++ src/openvpn/options_util.h | 33 +++++++++ src/openvpn/push.c | 33 +++++---- src/openvpn/ssl.c | 13 ++-- src/openvpn/ssl.h | 3 + tests/unit_tests/openvpn/Makefile.am | 1 + tests/unit_tests/openvpn/test_misc.c | 40 +++++++++++ 13 files changed, 267 insertions(+), 18 deletions(-) create mode 100644 src/openvpn/options_util.c create mode 100644 src/openvpn/options_util.h diff --git a/doc/man-sections/script-options.rst b/doc/man-sections/script-options.rst index 74c6a1fc6..be718ef26 100644 --- a/doc/man-sections/script-options.rst +++ b/doc/man-sections/script-options.rst @@ -102,6 +102,42 @@ SCRIPT HOOKS the authentication, a :code:`1` or :code:`0` must be written to the file specified by the :code:`auth_control_file`. + If the file specified by :code:`auth_failed_reason` exists and has non-empty + content, the content of this file will be used as AUTH_FAILED message. To + avoid race conditions, this file should be written before + :code:`auth_control_file`. + + This auth fail reason can be something simple like "User has been permanently + disabled" but there are also some special auth failed messages. + + The ``TEMP`` message indicates that the authentication + temporarily failed and that the client should continue to retry to connect. + The server can optionally give a user readable message and hint the client a + behavior how to proceed. The keywords of the ``AUTH_FAILED,TEMP`` message + are comma separated keys/values and provide a hint to the client how to + proceed. Currently defined keywords are: + + ``backoff`` :code:`s` + instructs the client to wait at least :code:`s` seconds before the next + connection attempt. If the client already uses a higher delay for + reconnection attempt, the delay will not be shortened. + + ``advance addr`` + Instructs the client to reconnect to the next (IP) address of the + current server. + + ``advance remote`` + Instructs the client to skip the remaining IP addresses of the current + server and instead connect to the next server specified in the + configuration file. + + ``advance no`` + Instructs the client to retry connecting to the same server again. + + For example, the message ``TEMP[backoff 42,advance no]: No free IP addresses`` + indicates that the VPN connection can currently not succeed and instructs + the client to retry in 42 seconds again. + When deferred authentication is in use, the script can also request pending authentication by writing to the file specified by the :code:`auth_pending_file`. The first line must be the timeout in diff --git a/src/openvpn/Makefile.am b/src/openvpn/Makefile.am index 5dbff4c6c..957494b10 100644 --- a/src/openvpn/Makefile.am +++ b/src/openvpn/Makefile.am @@ -102,6 +102,7 @@ openvpn_SOURCES = \ pkcs11_mbedtls.c \ openvpn.c openvpn.h \ options.c options.h \ + options_util.c options_util.h \ otime.c otime.h \ packet_id.c packet_id.h \ perf.c perf.h \ diff --git a/src/openvpn/init.c b/src/openvpn/init.c index 977f0f96c..f400495f0 100644 --- a/src/openvpn/init.c +++ b/src/openvpn/init.c @@ -484,13 +484,15 @@ next_connection_entry(struct context *c) /* Check if there is another resolved address to try for * the current connection */ if (c->c1.link_socket_addr.current_remote - && c->c1.link_socket_addr.current_remote->ai_next) + && c->c1.link_socket_addr.current_remote->ai_next + && !c->options.advance_next_remote) { c->c1.link_socket_addr.current_remote = c->c1.link_socket_addr.current_remote->ai_next; } else { + c->options.advance_next_remote = false; /* FIXME (schwabe) fix the persist-remote-ip option for real, * this is broken probably ever since connection lists and multiple * remote existed @@ -2528,6 +2530,11 @@ socket_restart_pause(struct context *c) /* sec is less than 2^16; we can left shift it by up to 15 bits without overflow */ sec = max_int(sec, 1) << min_int(backoff, 15); } + if (c->options.server_backoff_time) + { + sec = max_int(sec, c->options.server_backoff_time); + c->options.server_backoff_time = 0; + } if (sec > c->options.ce.connect_retry_seconds_max) { diff --git a/src/openvpn/openvpn.vcxproj b/src/openvpn/openvpn.vcxproj index ccd29cd87..04dda0edb 100644 --- a/src/openvpn/openvpn.vcxproj +++ b/src/openvpn/openvpn.vcxproj @@ -309,6 +309,7 @@ + @@ -402,6 +403,7 @@ + diff --git a/src/openvpn/openvpn.vcxproj.filters b/src/openvpn/openvpn.vcxproj.filters index bf0ba7082..9c53c01ab 100644 --- a/src/openvpn/openvpn.vcxproj.filters +++ b/src/openvpn/openvpn.vcxproj.filters @@ -416,6 +416,9 @@ Header Files + + Header Files + Header Files diff --git a/src/openvpn/options.h b/src/openvpn/options.h index a9015e121..9f98184fe 100644 --- a/src/openvpn/options.h +++ b/src/openvpn/options.h @@ -275,10 +275,17 @@ struct options struct connection_list *connection_list; struct remote_list *remote_list; - /* Do not advanced the connection or remote addr list*/ + /* Do not advance the connection or remote addr list*/ bool no_advance; + /* Advance directly to the next remote, skipping remaining addresses of the + * current remote */ + bool advance_next_remote; /* Counts the number of unsuccessful connection attempts */ unsigned int unsuccessful_attempts; + /* the server can suggest a backoff time to the client, it + * will still be capped by the max timeout between connections + * (300s by default) */ + int server_backoff_time; #if ENABLE_MANAGEMENT struct http_proxy_options *http_proxy_override; diff --git a/src/openvpn/options_util.c b/src/openvpn/options_util.c new file mode 100644 index 000000000..ff5ff6cb1 --- /dev/null +++ b/src/openvpn/options_util.c @@ -0,0 +1,102 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2022 OpenVPN Inc + * Copyright (C) 2010-2021 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 "options_util.h" + +const char * +parse_auth_failed_temp(struct options *o, const char *reason) +{ + struct gc_arena gc = gc_new(); + /* skip TEMP */ + const char *message = reason + strlen("TEMP"); + char *m = string_alloc(message, &gc); + + /* Check if the message uses the TEMP[flags]: message format*/ + char *endofflags = strstr(m, "]"); + + /* Temporary failure from the server */ + if (m[0] == '[' && endofflags) + { + message = strstr(reason, "]") + 1; + /* null terminate the substring to only looks for flags between [ and ] */ + *endofflags = '\x00'; + const char *token = strtok(m, "[,"); + while (token) + { + if (!strncmp(token, "backoff ", strlen("backoff "))) + { + if (sscanf(token, "backoff %d", &o->server_backoff_time) != 1) + { + msg(D_PUSH, "invalid AUTH_FAIL,TEMP flag: %s", token); + o->server_backoff_time = 0; + } + } + else if (!strncmp(token, "advance ", strlen("advance "))) + { + token += strlen("advance "); + if (!strcmp(token, "no")) + { + o->no_advance = true; + } + else if (!strcmp(token, "remote")) + { + o->advance_next_remote = true; + o->no_advance = false; + } + else if (!strcmp(token, "addr")) + { + /* Go on to the next remote */ + o->no_advance = false; + } + } + else + { + msg(D_PUSH_ERRORS, "WARNING: unknown AUTH_FAIL,TEMP flag: %s", token); + } + token = strtok(NULL, "[,"); + } + } + + /* Look for the message in the original buffer to safely be + * able to return it */ + if (!message || message[0] != ':') + { + message = ""; + } + else + { + /* Skip the : at the beginning */ + message += 1; + } + gc_free(&gc); + return message; +} diff --git a/src/openvpn/options_util.h b/src/openvpn/options_util.h new file mode 100644 index 000000000..17d62047b --- /dev/null +++ b/src/openvpn/options_util.h @@ -0,0 +1,33 @@ +/* + * OpenVPN -- An application to securely tunnel IP networks + * over a single TCP/UDP port, with support for SSL/TLS-based + * session authentication and key exchange, + * packet encryption, packet authentication, and + * packet compression. + * + * Copyright (C) 2002-2022 OpenVPN Inc + * Copyright (C) 2010-2021 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. + */ + +#ifndef OPTIONS_UTIL_H_ +#define OPTIONS_UTIL_H_ + +#include "options.h" + +const char * +parse_auth_failed_temp(struct options *o, const char *reason); + +#endif diff --git a/src/openvpn/push.c b/src/openvpn/push.c index 27a9e0a79..0a66902a8 100644 --- a/src/openvpn/push.c +++ b/src/openvpn/push.c @@ -38,6 +38,7 @@ #include "memdbg.h" #include "ssl_util.h" +#include "options_util.h" static char push_reply_cmd[] = "PUSH_REPLY"; @@ -58,15 +59,34 @@ receive_auth_failed(struct context *c, const struct buffer *buffer) return; } + struct buffer buf = *buffer; + + /* If the AUTH_FAIL message ends with a , it is an extended message that + * contains further flags */ + bool authfail_extended = buf_string_compare_advance(&buf, "AUTH_FAILED,"); + + const char *reason = NULL; + if (authfail_extended && BLEN(&buf)) + { + reason = BSTR(&buf); + } + + if (authfail_extended && buf_string_match_head_str(&buf, "TEMP")) + { + parse_auth_failed_temp(&c->options, reason); + c->sig->signal_received = SIGUSR1; + c->sig->signal_text = "auth-temp-failure (server temporary reject)"; + } /* Before checking how to react on AUTH_FAILED, first check if the * failed auth might be the result of an expired auth-token. * Note that a server restart will trigger a generic AUTH_FAILED * instead an AUTH_FAILED,SESSION so handle all AUTH_FAILED message * identical for this scenario */ - if (ssl_clean_auth_token()) + else if (ssl_clean_auth_token()) { c->sig->signal_received = SIGUSR1; /* SOFT-SIGUSR1 -- Auth failure error */ c->sig->signal_text = "auth-failure (auth-token)"; + c->options.no_advance = true; } else { @@ -89,19 +109,8 @@ receive_auth_failed(struct context *c, const struct buffer *buffer) c->sig->signal_text = "auth-failure"; } #ifdef ENABLE_MANAGEMENT - struct buffer buf = *buffer; - - /* If the AUTH_FAIL message ends with a , it is an extended message that - * contains further flags */ - bool authfail_extended = buf_string_compare_advance(&buf, "AUTH_FAILED,"); - if (management) { - const char *reason = NULL; - if (authfail_extended && BLEN(&buf)) - { - reason = BSTR(&buf); - } management_auth_failure(management, UP_TYPE_AUTH, reason); } /* diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c index 0dd723f30..f7c8d6f4c 100644 --- a/src/openvpn/ssl.c +++ b/src/openvpn/ssl.c @@ -1972,17 +1972,22 @@ push_peer_info(struct buffer *buf, struct tls_session *session) /* support for exit notify via control channel */ iv_proto |= IV_PROTO_CC_EXIT_NOTIFY; - /* support for receiving push_reply before sending - * push request, also signal that the client wants - * to get push-reply messages without without requiring a round - * trip for a push request message*/ if (session->opt->pull) { + /* support for receiving push_reply before sending + * push request, also signal that the client wants + * to get push-reply messages without requiring a round + * trip for a push request message*/ iv_proto |= IV_PROTO_REQUEST_PUSH; + + /* Support keywords in the AUTH_PENDING control message */ iv_proto |= IV_PROTO_AUTH_PENDING_KW; /* support for tun-mtu as part of the push message */ buf_printf(&out, "IV_MTU=%d\n", session->opt->frame.tun_max_mtu); + + /* support for AUTH_FAIL,TEMP control message */ + iv_proto |= IV_PROTO_AUTH_FAIL_TEMP; } /* support for Negotiable Crypto Parameters */ diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h index 12ffd44d7..8ca4c4aa8 100644 --- a/src/openvpn/ssl.h +++ b/src/openvpn/ssl.h @@ -100,6 +100,9 @@ * This also includes support for the protocol-flags pushed option */ #define IV_PROTO_CC_EXIT_NOTIFY (1<<7) +/** Support for AUTH_FAIL,TEMP messages */ +#define IV_PROTO_AUTH_FAIL_TEMP (1<<8) + /* Default field in X509 to be username */ #define X509_USERNAME_FIELD_DEFAULT "CN" diff --git a/tests/unit_tests/openvpn/Makefile.am b/tests/unit_tests/openvpn/Makefile.am index 63b53a6ac..65cf9549c 100644 --- a/tests/unit_tests/openvpn/Makefile.am +++ b/tests/unit_tests/openvpn/Makefile.am @@ -176,5 +176,6 @@ misc_testdriver_LDFLAGS = @TEST_LDFLAGS@ misc_testdriver_SOURCES = test_misc.c mock_msg.c \ mock_get_random.c \ $(openvpn_srcdir)/buffer.c \ + $(openvpn_srcdir)/options_util.c \ $(openvpn_srcdir)/ssl_util.c \ $(openvpn_srcdir)/platform.c diff --git a/tests/unit_tests/openvpn/test_misc.c b/tests/unit_tests/openvpn/test_misc.c index 636fc45d6..589b0bcd2 100644 --- a/tests/unit_tests/openvpn/test_misc.c +++ b/tests/unit_tests/openvpn/test_misc.c @@ -37,6 +37,7 @@ #include #include "ssl_util.h" +#include "options_util.h" static void test_compat_lzo_string(void **state) @@ -72,8 +73,47 @@ test_compat_lzo_string(void **state) gc_free(&gc); } +static void +test_auth_fail_temp_no_flags(void **state) +{ + struct options o; + + const char *teststr = "TEMP:There are no flags here [really not]"; + + const char *msg = parse_auth_failed_temp(&o, teststr); + assert_string_equal(msg, "There are no flags here [really not]"); +} + +static void +test_auth_fail_temp_flags(void **state) +{ + struct options o; + + const char *teststr = "TEMP[backoff 42,advance no]"; + + const char *msg = parse_auth_failed_temp(&o, teststr); + assert_string_equal(msg, ""); + assert_int_equal(o.server_backoff_time, 42); + assert_int_equal(o.no_advance, true); +} + +static void +test_auth_fail_temp_flags_msg(void **state) +{ + struct options o; + + const char *teststr = "TEMP[advance remote,backoff 77]:go round and round"; + + const char *msg = parse_auth_failed_temp(&o, teststr); + assert_string_equal(msg, "go round and round"); + assert_int_equal(o.server_backoff_time, 77); +} + const struct CMUnitTest misc_tests[] = { cmocka_unit_test(test_compat_lzo_string), + cmocka_unit_test(test_auth_fail_temp_no_flags), + cmocka_unit_test(test_auth_fail_temp_flags), + cmocka_unit_test(test_auth_fail_temp_flags_msg), }; int