]> git.99rst.org Git - openwrt-packages.git/commitdiff
freeradius3: update to 3.2.10
authorAlexandru Ardelean <redacted>
Tue, 2 Jun 2026 22:48:03 +0000 (01:48 +0300)
committerJosef Schlehofer <redacted>
Wed, 22 Jul 2026 23:10:15 +0000 (01:10 +0200)
Patches:
- Drop 003-freeradius-fix-error-for-expansion-of-macro.patch (upstream
  restructured src/include/threads.h) and add
  003-configure-assume-cross-tls.patch instead: the AC_RUN_IFELSE
  __thread probe cannot run when cross-compiling, so TLS_STORAGE_CLASS
  stays undefined and threads.h hits '#error unsupported' (since 3.2.9).
- Drop 002-disable-session-cache-CVE-2017-9148.patch, 3.2.x is not
  affected per https://nvd.nist.gov/vuln/detail/CVE-2017-9148.
- Replace 004-get-hostname-from-proc-in-radtest.patch with
  004-radtest-nas-name-from-hostname-env.patch: prefer $HOSTNAME and keep
  the upstream `hostname || uname -n` fallback instead of reading
  /proc/sys/kernel/hostname unconditionally.
- Re-do 020-fix-freeradius3-krb5.patch, also sent upstream for review.
- Give the touched patches the git format-patch headers 'git am' needs,
  with the diff bodies unchanged so they still match 'quilt refresh'.

Depend on libopenssl-legacy when built against OpenSSL: with OpenSSL 3.x
tls_global_init() unconditionally does OSSL_PROVIDER_load(NULL, "legacy")
for MD4/MS-CHAP and errors out when it is missing, so radiusd exits during
startup before it ever serves a request.

Add a test.sh covering the freeradius3, -common, -utils and -democerts
packages: radiusd -XC starts the server for real, the config tree it reads
is checked, the dictionaries the master dictionary still $INCLUDEs must
all be packaged, and the demo certificates must be real PEM.

Signed-off-by: Alexandru Ardelean <redacted>
net/freeradius3/Makefile
net/freeradius3/patches/002-disable-session-cache-CVE-2017-9148.patch [deleted file]
net/freeradius3/patches/003-configure-assume-cross-tls.patch [new file with mode: 0644]
net/freeradius3/patches/003-freeradius-fix-error-for-expansion-of-macro.patch [deleted file]
net/freeradius3/patches/004-get-hostname-from-proc-in-radtest.patch [deleted file]
net/freeradius3/patches/004-radtest-nas-name-from-hostname-env.patch [new file with mode: 0644]
net/freeradius3/patches/010-openssl-deprecated.patch
net/freeradius3/patches/020-fix-freeradius3-krb5.patch
net/freeradius3/test.sh [new file with mode: 0755]

index 1e173c1ac9f66831a9ad155c4b4e4fa648c65ea7..4550d60686ba10997561e7eb6f462f6a79f5aa4b 100644 (file)
@@ -8,13 +8,13 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=freeradius3
-PKG_VERSION:=3.2.8
+PKG_VERSION:=3.2.10
 PKG_VERSION_UNDERSCORE:=$(subst .,_,${PKG_VERSION})
 PKG_RELEASE:=1
 
 PKG_SOURCE:=freeradius-server-$(PKG_VERSION).tar.gz
 PKG_SOURCE_URL:=https://github.com/FreeRADIUS/freeradius-server/releases/download/release_$(PKG_VERSION_UNDERSCORE)/
-PKG_HASH:=3846498103d3faf182abd968a440128cb0c5589330bdcdd58c466ef15d9f9fdf
+PKG_HASH:=40e0cdfdcceb22cf0acb79bc29cf7c32995466a61fda09445ce5220608a55afd
 
 PKG_MAINTAINER:=Alexandru Ardelean <ardeleanalex@gmail.com>
 PKG_LICENSE:=GPL-2.0
@@ -63,7 +63,7 @@ endef
 define Package/freeradius3-common
   $(call Package/freeradius3/Default)
   TITLE:=common files
-  DEPENDS:= +USE_GLIBC:libcrypt-compat +USE_GLIBC:libpthread +USE_GLIBC:libbsd +FREERADIUS3_OPENSSL:libopenssl +libcap +libpcap +libncurses +libreadline +libtalloc +libatomic
+  DEPENDS:=+USE_GLIBC:libcrypt-compat +USE_GLIBC:libpthread +USE_GLIBC:libbsd +FREERADIUS3_OPENSSL:libopenssl +FREERADIUS3_OPENSSL:libopenssl-legacy +libcap +libpcap +libncurses +libreadline +libtalloc +libatomic
 endef
 
 define Package/freeradius3-default
diff --git a/net/freeradius3/patches/002-disable-session-cache-CVE-2017-9148.patch b/net/freeradius3/patches/002-disable-session-cache-CVE-2017-9148.patch
deleted file mode 100644 (file)
index 9fd7a32..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-Description: disable session caching in the server (as opposed to in the
- config, which would be way harder to get right) to address
- https://security-tracker.debian.org/tracker/CVE-2017-9148
-Author: Michael Stapelberg <stapelberg@debian.org>
-Forwarded: not-needed
-Last-Update: 2020-04-28
-
----
-
---- a/src/main/tls.c
-+++ b/src/main/tls.c
-@@ -860,7 +860,7 @@ after_chain:
-       }
-       if (vp) vp->vp_integer = state->mtu;
--      if (conf->session_cache_enable) state->allow_session_resumption = true; /* otherwise it's false */
-+      if (/*conf->session_cache_enable*/0) state->allow_session_resumption = true; /* otherwise it's false */
-       return state;
- }
-@@ -4520,7 +4520,7 @@ post_ca:
-       /*
-        *      Callbacks, etc. for session resumption.
-        */
--      if (conf->session_cache_enable) {
-+      if (/*conf->session_cache_enable*/0) {
-               /*
-                *      Cache sessions on disk if requested.
-                */
-@@ -4600,7 +4600,7 @@ post_ca:
-       /*
-        *      Setup session caching
-        */
--      if (conf->session_cache_enable) {
-+      if (/*conf->session_cache_enable*/0) {
-               /*
-                *      Create a unique context Id per EAP-TLS configuration.
-                */
-@@ -4890,7 +4890,7 @@ fr_tls_server_conf_t *tls_server_conf_pa
-               goto error;
-       }
--      if (conf->session_cache_enable) {
-+      if (/*conf->session_cache_enable*/0) {
-               CONF_SECTION    *subcs;
-               CONF_ITEM       *ci;
diff --git a/net/freeradius3/patches/003-configure-assume-cross-tls.patch b/net/freeradius3/patches/003-configure-assume-cross-tls.patch
new file mode 100644 (file)
index 0000000..590711b
--- /dev/null
@@ -0,0 +1,23 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Alexandru Ardelean <alex@shruggie.ro>
+Date: Wed, 3 Jun 2026 01:48:03 +0300
+Subject: [PATCH] configure: assume __thread TLS works when cross-compiling
+
+OpenWrt cross-compiles with gcc on musl, which supports __thread. The
+AC_RUN_IFELSE check in fr_tls.m4 defaults to "no" for cross builds, so
+TLS_STORAGE_CLASS is never defined, __THREAD is never set, and threads.h
+falls through to '#error unsupported' (added in 3.2.9).
+
+Signed-off-by: Alexandru Ardelean <alex@shruggie.ro>
+---
+--- a/configure
++++ b/configure
+@@ -12625,7 +12625,7 @@ fi
+ printf %s "checking for __thread support in compiler... " >&6; }
+   if test "$cross_compiling" = yes
+ then :
+-  have_tls=no
++  have_tls=yes
+ else $as_nop
+   cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ /* end confdefs.h.  */
diff --git a/net/freeradius3/patches/003-freeradius-fix-error-for-expansion-of-macro.patch b/net/freeradius3/patches/003-freeradius-fix-error-for-expansion-of-macro.patch
deleted file mode 100644 (file)
index 0155187..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
---- a/src/include/threads.h
-+++ b/src/include/threads.h
-@@ -92,7 +92,7 @@ static _t __fr_thread_local_init_##_n(pt
- #  define fr_thread_local_get(_n) _n
- #elif defined(HAVE_PTHREAD_H)
- #  include <pthread.h>
--#  define fr_thread_local_setup(_t, _n) \
-+#  define fr_thread_local_setup(_t, _n) static __thread _t _n;\
- static pthread_key_t __fr_thread_local_key_##_n;\
- static pthread_once_t __fr_thread_local_once_##_n = PTHREAD_ONCE_INIT;\
- static pthread_destructor_t __fr_thread_local_destructor_##_n = NULL;\
-@@ -103,17 +103,17 @@ static void __fr_thread_local_destroy_##
- static void __fr_thread_local_key_init_##_n(void)\
- {\
-       (void) pthread_key_create(&__fr_thread_local_key_##_n, __fr_thread_local_destroy_##_n);\
--      (void) pthread_setspecific(__fr_thread_local_key_##_n, &(_n));\
- }\
- static _t __fr_thread_local_init_##_n(pthread_destructor_t func)\
- {\
-       __fr_thread_local_destructor_##_n = func;\
-       if (_n) return _n; \
-       (void) pthread_once(&__fr_thread_local_once_##_n, __fr_thread_local_key_init_##_n);\
-+      (void) pthread_setspecific(__fr_thread_local_key_##_n, &(_n));\
-       return _n;\
- }
--#  define fr_thread_local_init(_n, _f)                        __fr_thread_local_init_##_n(_f)
--#  define fr_thread_local_set(_n, _v)                 __fr_thread_local_set_##_n(_v)
--#  define fr_thread_local_get(_n)                     __fr_thread_local_get_##_n()
-+#  define fr_thread_local_init(_n, _f)        __fr_thread_local_init_##_n(_f)
-+#  define fr_thread_local_set(_n, _v) ((int)!((_n = _v) || 1))
-+#  define fr_thread_local_get(_n) _n
- #endif
- #endif
diff --git a/net/freeradius3/patches/004-get-hostname-from-proc-in-radtest.patch b/net/freeradius3/patches/004-get-hostname-from-proc-in-radtest.patch
deleted file mode 100644 (file)
index ac7186a..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/src/main/radtest.in
-+++ b/src/main/radtest.in
-@@ -117,7 +117,7 @@ if [ "$7" ]
- then
-       nas=$7
- else
--      nas=`(hostname || uname -n) 2>/dev/null | sed 1q`
-+      nas=$(cat /proc/sys/kernel/hostname)
- fi
- (
diff --git a/net/freeradius3/patches/004-radtest-nas-name-from-hostname-env.patch b/net/freeradius3/patches/004-radtest-nas-name-from-hostname-env.patch
new file mode 100644 (file)
index 0000000..2b96348
--- /dev/null
@@ -0,0 +1,28 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Alexandru Ardelean <alex@shruggie.ro>
+Date: Wed, 3 Jun 2026 01:48:03 +0300
+Subject: [PATCH] radtest: use $HOSTNAME for the NAS name when it is set
+
+radtest derives the NAS name from `hostname` or `uname -n`, neither of
+which is guaranteed to be present in a minimal image. Prefer the
+$HOSTNAME environment variable when the shell exports it, and keep the
+original command substitution as the fallback.
+
+Signed-off-by: Alexandru Ardelean <alex@shruggie.ro>
+---
+--- a/src/main/radtest.in
++++ b/src/main/radtest.in
+@@ -117,7 +117,12 @@ if [ "$7" ]
+ then
+       nas=$7
+ else
+-      nas=`(hostname || uname -n) 2>/dev/null | sed 1q`
++      if [ -n "$HOSTNAME" ]
++      then
++              nas=$HOSTNAME
++      else
++              nas=`(hostname || uname -n) 2>/dev/null | sed 1q`
++      fi
+ fi
+ (
index d600925c460424d9d5be62f1cf0f35d9a3548568..7c5b1c32330da3e1631c9674dfadf7e24320a5e8 100644 (file)
@@ -1,6 +1,19 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Rosen Penev <rosenp@gmail.com>
+Date: Sun, 2 Aug 2020 15:07:47 -0700
+Subject: [PATCH] fix compilation without deprecated OpenSSL APIs
+
+Guard the OpenSSL 1.0 locking callbacks and the explicit library
+init/cleanup calls behind a version check, switch X509_get_notAfter() and
+X509_get_notBefore() to their X509_get0_* replacements, replace the
+SSLeay() aliases with OpenSSL_version_num()/OpenSSL_version(), and
+include <openssl/dh.h> explicitly.
+
+Signed-off-by: Rosen Penev <rosenp@gmail.com>
+---
 --- a/src/main/threads.c
 +++ b/src/main/threads.c
-@@ -275,6 +275,7 @@ static void ssl_locking_function(int mod
+@@ -257,6 +257,7 @@ static void ssl_locking_function(int mod
   */
  int tls_mutexes_init(void)
  {
@@ -8,7 +21,7 @@
        int i, num;
  
        rad_assert(ssl_mutexes == NULL);
-@@ -292,6 +293,7 @@ int tls_mutexes_init(void)
+@@ -274,6 +275,7 @@ int tls_mutexes_init(void)
        }
  
        CRYPTO_set_locking_callback(ssl_locking_function);
@@ -26,7 +39,7 @@
  
  #if OPENSSL_VERSION_NUMBER >= 0x30000000L
  #  include <openssl/provider.h>
-@@ -2943,7 +2944,7 @@ int cbtls_verify(int ok, X509_STORE_CTX
+@@ -2985,7 +2986,7 @@ int cbtls_verify(int ok, X509_STORE_CTX
        int             my_ok = ok;
  
        ASN1_INTEGER    *sn = NULL;
@@ -35,7 +48,7 @@
        VALUE_PAIR      **certs;
        char **identity;
  #ifdef HAVE_OPENSSL_OCSP_H
-@@ -3035,7 +3036,7 @@ int cbtls_verify(int ok, X509_STORE_CTX
+@@ -3077,7 +3078,7 @@ int cbtls_verify(int ok, X509_STORE_CTX
         *      Get the Expiration Date
         */
        buf[0] = '\0';
@@ -44,7 +57,7 @@
        if (certs && (lookup <= 1) && asn_time &&
            (asn_time->length < (int) sizeof(buf))) {
                memcpy(buf, (char*) asn_time->data, asn_time->length);
-@@ -3048,7 +3049,7 @@ int cbtls_verify(int ok, X509_STORE_CTX
+@@ -3090,7 +3091,7 @@ int cbtls_verify(int ok, X509_STORE_CTX
         *      Get the Valid Since Date
         */
        buf[0] = '\0';
@@ -53,7 +66,7 @@
        if (certs && (lookup <= 1) && asn_time &&
            (asn_time->length < (int) sizeof(buf))) {
                memcpy(buf, (char*) asn_time->data, asn_time->length);
-@@ -3655,10 +3656,12 @@ static int set_ecdh_curve(SSL_CTX *ctx,
+@@ -3697,10 +3698,12 @@ static int set_ecdh_curve(SSL_CTX *ctx,
   */
  int tls_global_init(TLS_UNUSED bool spawn_flag, TLS_UNUSED bool check)
  {
@@ -66,7 +79,7 @@
  
  #if OPENSSL_VERSION_NUMBER >= 0x30000000L
        EVP_set_default_properties(NULL, "-fips");
-@@ -3762,6 +3765,7 @@ int tls_global_version_check(char const
+@@ -3806,6 +3809,7 @@ int tls_global_version_check(char const
   */
  void tls_global_cleanup(void)
  {
@@ -74,7 +87,7 @@
  #if OPENSSL_VERSION_NUMBER < 0x10000000L
        ERR_remove_state(0);
  #elif OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
-@@ -3787,6 +3791,7 @@ void tls_global_cleanup(void)
+@@ -3833,6 +3837,7 @@ void tls_global_cleanup(void)
        ERR_free_strings();
        EVP_cleanup();
        CRYPTO_cleanup_all_ex_data();
index 14562f8300a46a0026d57c79c9d3472cad877b29..9ee07e93860c371f670d70dd58e952b92d8a9793 100644 (file)
@@ -1,23 +1,43 @@
+From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
+From: Alexandru Ardelean <alex@shruggie.ro>
+Date: Mon, 13 Jul 2026 22:18:27 +0300
+Subject: [PATCH] rlm_krb5: assume thread-safety when cross-compiling
+
+The autoconf probe for krb5_is_thread_safe() has no action-if-cross-compiling
+argument, so once libkrb5 provides the symbol configure aborts outright with
+"cannot run test program while cross compiling".
+
+Add the missing argument: warn that the probe was skipped, and assume
+thread-safety, which is correct for all modern krb5 builds.
+
+Signed-off-by: Alexandru Ardelean <alex@shruggie.ro>
+---
 --- a/src/modules/rlm_krb5/configure
 +++ b/src/modules/rlm_krb5/configure
-@@ -4003,12 +4003,6 @@ if test "x$smart_lib" != "x"; then
- fi
+@@ -4004,10 +4004,9 @@ fi
  
        if test "x$ac_cv_lib_krb5_krb5_is_thread_safe" = xyes; then
--              if test "$cross_compiling" = yes; then :
+               if test "$cross_compiling" = yes; then :
 -  { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
 -$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
 -as_fn_error $? "cannot run test program while cross compiling
 -See \`config.log' for more details" "$LINENO" 5; }
--else
++  { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cross compiling: not checking" >&5
++$as_echo "$as_me: WARNING: cross compiling: not checking" >&2;}
++                       krb5threadsafe="-DKRB5_IS_THREAD_SAFE"
+ else
    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
  /* end confdefs.h.  */
- #include <krb5.h>
-@@ -4028,7 +4022,6 @@ $as_echo "$as_me: WARNING: libkrb5 is no
- fi
- rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
-   conftest.$ac_objext conftest.beam conftest.$ac_ext
--fi
+--- a/src/modules/rlm_krb5/configure.ac
++++ b/src/modules/rlm_krb5/configure.ac
+@@ -143,7 +143,9 @@ if test "$krb5threadsafe" != "no"; then
+       FR_SMART_CHECK_LIB(krb5, krb5_is_thread_safe)
+       if test "x$ac_cv_lib_krb5_krb5_is_thread_safe" = xyes; then
+               AC_RUN_IFELSE([AC_LANG_PROGRAM([[#include <krb5.h>]], [[return krb5_is_thread_safe() ? 0 : 1]])],
+-                      [krb5threadsafe="-DKRB5_IS_THREAD_SAFE"], [AC_MSG_WARN([[libkrb5 is not threadsafe]])])
++                      [krb5threadsafe="-DKRB5_IS_THREAD_SAFE"], [AC_MSG_WARN([[libkrb5 is not threadsafe]])],
++                      [AC_MSG_WARN(cross compiling: not checking)
++                       krb5threadsafe="-DKRB5_IS_THREAD_SAFE"])
        fi
  else
+       krb5threadsafe=""
diff --git a/net/freeradius3/test.sh b/net/freeradius3/test.sh
new file mode 100755 (executable)
index 0000000..2c0058b
--- /dev/null
@@ -0,0 +1,109 @@
+#!/bin/sh
+
+FR_ETC="/etc/freeradius3"
+FR_LIB="/usr/lib/freeradius3"
+FR_SHARE="/usr/share/freeradius3"
+
+case "$1" in
+freeradius3)
+       [ -x /usr/sbin/radiusd ] || { echo "FAIL: /usr/sbin/radiusd not installed"; exit 1; }
+
+       for f in radiusd.conf clients.conf proxy.conf \
+                policy.d/accounting policy.d/filter \
+                sites-available/default sites-enabled/default; do
+               [ -s "$FR_ETC/$f" ] || { echo "FAIL: $FR_ETC/$f missing or empty"; exit 1; }
+       done
+
+       # radiusd derives every other config path from raddbdir.
+       grep -q "^raddbdir = $FR_ETC\$" "$FR_ETC/radiusd.conf" || {
+               echo "FAIL: radiusd.conf does not set raddbdir to $FR_ETC"
+               grep -n '^raddbdir' "$FR_ETC/radiusd.conf"
+               exit 1
+       }
+
+       [ -x /etc/init.d/radiusd ] || { echo "FAIL: /etc/init.d/radiusd not installed"; exit 1; }
+       ;;
+
+freeradius3-default)
+       # Pulls in the modules radiusd.conf expects in mods-enabled/, so this is
+       # the first package where the server can start. -XC reads the whole
+       # config, loads every module and initialises OpenSSL, then exits.
+       radiusd -XC || {
+               echo "FAIL: 'radiusd -XC' could not start the server"
+               exit 1
+       }
+       ;;
+
+freeradius3-common)
+       for l in dhcp eap radius server; do
+               [ -s "$FR_LIB/libfreeradius-$l.so" ] || {
+                       echo "FAIL: $FR_LIB/libfreeradius-$l.so not installed"; exit 1; }
+       done
+
+       [ -s "$FR_ETC/dictionary" ] || { echo "FAIL: $FR_ETC/dictionary missing or empty"; exit 1; }
+       [ -s "$FR_SHARE/dictionary" ] || { echo "FAIL: $FR_SHARE/dictionary missing or empty"; exit 1; }
+
+       # The Makefile packages only PKG_DICTIONARIES; a still-active $INCLUDE
+       # without a file behind it stops radiusd from starting.
+       includes=$(sed -n 's/^\$INCLUDE[[:space:]][[:space:]]*\(dictionary\.[^[:space:]]*\).*/\1/p' \
+               "$FR_SHARE/dictionary")
+       [ -n "$includes" ] || {
+               echo "FAIL: no active \$INCLUDE lines in $FR_SHARE/dictionary"; exit 1; }
+
+       missing=
+       for d in $includes; do
+               [ -f "$FR_SHARE/$d" ] || missing="$missing $d"
+       done
+       [ -z "$missing" ] || {
+               echo "FAIL: \$INCLUDE with no dictionary file behind it:$missing"; exit 1; }
+       ;;
+
+freeradius3-utils)
+       for t in radclient radeapclient radwho; do
+               [ -x "/usr/bin/$t" ] || { echo "FAIL: /usr/bin/$t not installed"; exit 1; }
+               "/usr/bin/$t" -h 2>&1 | grep -q "Usage: $t" || {
+                       echo "FAIL: '$t -h' did not print its usage"
+                       "/usr/bin/$t" -h 2>&1 | head -n 5
+                       exit 1
+               }
+       done
+
+       [ -x /usr/bin/radtest ] || { echo "FAIL: /usr/bin/radtest not installed"; exit 1; }
+       radtest 2>&1 | grep -q "Usage: radtest" || {
+               echo "FAIL: 'radtest' did not print its usage"
+               radtest 2>&1 | head -n 5
+               exit 1
+       }
+
+       # Use a TEST-NET HOSTNAME with no NAS name to verify patch 004 passes it
+       # as NAS-IP-Address; capture xtrace and stop radclient with no server.
+       nas_ip="192.0.2.77"
+       radtest_out="/tmp/radtest-hostname.$$"
+       HOSTNAME="$nas_ip" sh -x /usr/bin/radtest u p 127.0.0.1:1812 0 testing123 \
+               >"$radtest_out" 2>&1 &
+       radtest_pid=$!
+       sleep 3
+       kill "$radtest_pid" 2>/dev/null
+       killall radclient 2>/dev/null
+       grep -q "NAS-IP-Address = $nas_ip" "$radtest_out" || {
+               echo "FAIL: radtest did not use \$HOSTNAME ($nas_ip) for NAS-IP-Address"
+               grep -E 'nas=|NAS-IP-Address' "$radtest_out" | head -n 10
+               rm -f "$radtest_out"
+               exit 1
+       }
+       rm -f "$radtest_out"
+       ;;
+
+freeradius3-democerts)
+       for f in ca.pem server.pem; do
+               [ -s "$FR_ETC/certs/$f" ] || { echo "FAIL: $FR_ETC/certs/$f missing or empty"; exit 1; }
+               grep -q "BEGIN CERTIFICATE" "$FR_ETC/certs/$f" || {
+                       echo "FAIL: $FR_ETC/certs/$f holds no certificate"; exit 1; }
+       done
+
+       grep -q "BEGIN .*PRIVATE KEY" "$FR_ETC/certs/server.pem" || {
+               echo "FAIL: $FR_ETC/certs/server.pem holds no private key"; exit 1; }
+       ;;
+esac
+
+exit 0
git clone https://git.99rst.org/PROJECT