radius dynamic module
authorJeremy Harris <jgh146exb@wizmail.org>
Sat, 7 Sep 2024 13:56:11 +0000 (14:56 +0100)
committerJeremy Harris <jgh146exb@wizmail.org>
Sat, 7 Sep 2024 13:57:08 +0000 (14:57 +0100)
16 files changed:
doc/doc-txt/NewStuff
src/OS/Makefile-Base
src/scripts/Configure-Makefile
src/scripts/MakeLinks
src/scripts/drivers-Makefile
src/src/auths/call_radius.c [deleted file]
src/src/config.h.defaults
src/src/exim.h
src/src/expand.c
src/src/functions.h
src/src/miscmods/Makefile
src/src/miscmods/arc.c
src/src/miscmods/dkim.c
src/src/miscmods/dmarc.c
src/src/miscmods/radius.c [new file with mode: 0644]
src/src/miscmods/spf.c

index 5220408e80fc876548f874d1ad132d34ac1c9215..fe94e46c711aa64f4a82333d8c693c45db71e575 100644 (file)
@@ -14,9 +14,9 @@ Version 4.98
 
  3. Events smtp:fail:protocol and smtp:fail:syntax
 
 
  3. Events smtp:fail:protocol and smtp:fail:syntax
 
- 4. JSON and LDAP lookup support, SPF, DKIM, DMARC and ARC support, all the
-    router and authenticator drivers, and all the transport drivers except
-    smtp, can now be built as loadable modules
+ 4. JSON and LDAP lookup support, RADIUS, SPF, DKIM, DMARC and ARC support,
+    all the router and authenticator drivers, and all the transport drivers
+    except smtp, can now be built as loadable modules
 
 Version 4.98
 ------------
 
 Version 4.98
 ------------
index ccbe3ccdd0c7639d55eedf84919c095d3bac5699..ddd7cf5ac56b349cf05c4c661954fc146f5f951c 100644 (file)
@@ -509,7 +509,7 @@ OBJ_LOOKUPS = lf_quote.o lf_check_file.o lf_sqlperform.o
 OBJ_ROUTERS = rf_change_domain.o rf_expand_data.o rf_get_errors_address.o \
        rf_get_munge_headers.o rf_get_transport.o rf_get_ugid.o \
        rf_lookup_hostlist.o rf_queue_add.o rf_self_action.o rf_set_ugid.o
 OBJ_ROUTERS = rf_change_domain.o rf_expand_data.o rf_get_errors_address.o \
        rf_get_munge_headers.o rf_get_transport.o rf_get_ugid.o \
        rf_lookup_hostlist.o rf_queue_add.o rf_self_action.o rf_set_ugid.o
-OBJ_AUTHS = call_pam.o call_pwcheck.o call_radius.o check_serv_cond.o \
+OBJ_AUTHS = call_pam.o call_pwcheck.o check_serv_cond.o \
        get_data.o get_no64_data.o pwcheck.o
 
 OBJ_EXIM = acl.o base64.o child.o crypt16.o daemon.o dbfn.o debug.o deliver.o \
        get_data.o get_no64_data.o pwcheck.o
 
 OBJ_EXIM = acl.o base64.o child.o crypt16.o daemon.o dbfn.o debug.o deliver.o \
@@ -974,9 +974,6 @@ call_pam.o:         auths/call_pam.c
 call_pwcheck.o:     auths/call_pwcheck.c auths/pwcheck.h
        @echo "$(CC) $<"
        $(FE)$(CC) -c $(CFLAGS) -I. $(INCLUDE) $<
 call_pwcheck.o:     auths/call_pwcheck.c auths/pwcheck.h
        @echo "$(CC) $<"
        $(FE)$(CC) -c $(CFLAGS) -I. $(INCLUDE) $<
-call_radius.o:      auths/call_radius.c
-       @echo "$(CC) $<"
-       $(FE)$(CC) -c $(CFLAGS) -I. $(INCLUDE) $<
 check_serv_cond.o:  auths/check_serv_cond.c
        @echo "$(CC) $<"
        $(FE)$(CC) -c $(CFLAGS) -I. $(INCLUDE) $<
 check_serv_cond.o:  auths/check_serv_cond.c
        @echo "$(CC) $<"
        $(FE)$(CC) -c $(CFLAGS) -I. $(INCLUDE) $<
index 1eb79a291bcd6a9f045a909675c40de5ec3c0382..96a6cce22cdffbe9f7595a8cda6d9afec5194130 100755 (executable)
@@ -247,17 +247,6 @@ then
           yes|YES|y|Y)
             echo >&2 "pcre is no longer supported; migrate to pcre2"
             exit 1
           yes|YES|y|Y)
             echo >&2 "pcre is no longer supported; migrate to pcre2"
             exit 1
-
-#            cflags=`pcre-config --cflags`
-#            if [ $? -ne 0 ]; then
-#              echo >&2 "*** Missing pcre-config for regular expression support"
-#              exit 1
-#            fi
-#            libs=`pcre-config --libs`
-#            if [ ".$cflags" != "." ]; then
-#              echo "INCLUDE += $cflags"
-#            fi
-#            echo "PCRE_LIBS=$libs"
             ;;
         esac
         ;;
             ;;
         esac
         ;;
@@ -295,23 +284,32 @@ then
 fi
 rm -f $mftt
 
 fi
 rm -f $mftt
 
+#XXX look for RADIUS in $mft; add a SUPPORT_
+if $egrep -q "^RADIUS_CONFIG_FILE" $mft; then
+  echo "# radius fixup"
+  $egrep -q "^SUPPORT_RADIUS" $mft || echo "SUPPORT_RADIUS=yes" >> $mft
+fi
+
+
 # make the lookups Makefile with the definitions
 # the auxiliary script generates $look_mf_post from $look_mf_pre
 
 cp ../src/lookups/Makefile $look_mf_pre
 ../scripts/lookups-Makefile
 
 # make the lookups Makefile with the definitions
 # the auxiliary script generates $look_mf_post from $look_mf_pre
 
 cp ../src/lookups/Makefile $look_mf_pre
 ../scripts/lookups-Makefile
 
+# make the Makefiles for routers, transports, auths and miscmods
+#
 while read class classdef names
 do
   cp ../src/$class/Makefile $class/Makefile.predynamic
 while read class classdef names
 do
   cp ../src/$class/Makefile $class/Makefile.predynamic
-  CLASS=$class CLASSDEF=$classdef DRNAMES="$names" ../scripts/drivers-Makefile
+  CLASS=$class CLASSDEF=$classdef DRNAMES="$names" EGREP="$egrep" ../scripts/drivers-Makefile
   mv $class/Makefile.postdynamic $class/Makefile
   rm $class/Makefile.predynamic
 done <<-END
  routers    ROUTER     ACCEPT DNSLOOKUP IPLITERAL IPLOOKUP MANUALROUTE QUERYPROGRAM REDIRECT
  transports TRANSPORT  APPENDFILE AUTOREPLY LMTP PIPE QUEUEFILE SMTP
  auths     AUTH        CRAM_MD5 CYRUS_SASL DOVECOT EXTERNAL GSASL HEIMDAL_GSSAPI PLAINTEXT SPA TLS
   mv $class/Makefile.postdynamic $class/Makefile
   rm $class/Makefile.predynamic
 done <<-END
  routers    ROUTER     ACCEPT DNSLOOKUP IPLITERAL IPLOOKUP MANUALROUTE QUERYPROGRAM REDIRECT
  transports TRANSPORT  APPENDFILE AUTOREPLY LMTP PIPE QUEUEFILE SMTP
  auths     AUTH        CRAM_MD5 CYRUS_SASL DOVECOT EXTERNAL GSASL HEIMDAL_GSSAPI PLAINTEXT SPA TLS
- miscmods   SUPPORT    ARC _DKIM DMARC SPF
+ miscmods   SUPPORT    ARC _DKIM DMARC RADIUS SPF
 END
 
 # See if there is a definition of EXIM_PERL in what we have built so far.
 END
 
 # See if there is a definition of EXIM_PERL in what we have built so far.
index 481f36fe3fe5d8d3f575cf0f746f87608d360b78..1b272a5c9afd16d2b1a97b41f4152f2cc1bdf733 100755 (executable)
@@ -79,7 +79,7 @@ mkdir $d
 cd $d
 # Makefile is generated
 for f in README call_pam.c call_pwcheck.c \
 cd $d
 # Makefile is generated
 for f in README call_pam.c call_pwcheck.c \
-  call_radius.c check_serv_cond.c cyrus_sasl.c cyrus_sasl.h gsasl.c \
+  check_serv_cond.c cyrus_sasl.c cyrus_sasl.h gsasl.c \
   gsasl.h get_data.c get_no64_data.c heimdal_gssapi.c heimdal_gssapi.h \
   cram_md5.c cram_md5.h plaintext.c plaintext.h \
   pwcheck.c pwcheck.h auth-spa.c auth-spa.h dovecot.c dovecot.h spa.c \
   gsasl.h get_data.c get_no64_data.c heimdal_gssapi.c heimdal_gssapi.h \
   cram_md5.c cram_md5.h plaintext.c plaintext.h \
   pwcheck.c pwcheck.h auth-spa.c auth-spa.h dovecot.c dovecot.h spa.c \
@@ -102,6 +102,7 @@ for f in dummy.c \
        pdkim/crypt_ver.h pdkim/pdkim.c pdkim/pdkim.h \
        pdkim/pdkim_hash.h pdkim/signing.c pdkim/signing.h \
        dmarc.c dmarc.h dmarc_api.h \
        pdkim/crypt_ver.h pdkim/pdkim.c pdkim/pdkim.h \
        pdkim/pdkim_hash.h pdkim/signing.c pdkim/signing.h \
        dmarc.c dmarc.h dmarc_api.h \
+       radius.c radius_api.h \
        spf.c spf.h spf_api.h
 do
   ln -s ../../src/$d/$f `basename $f`
        spf.c spf.h spf_api.h
 do
   ln -s ../../src/$d/$f `basename $f`
index 085eedbda968fbf24b66713c73b20520886d6add..de3c239a6199d42ca8df012debf97748fef36c4f 100755 (executable)
@@ -6,6 +6,7 @@
 class=${CLASS:?}
 classdef=${CLASSDEF:?}
 drnames="${DRNAMES:?}"
 class=${CLASS:?}
 classdef=${CLASSDEF:?}
 drnames="${DRNAMES:?}"
+egrep="${EGREP:?}"
 
 # We turn the configure-built build-$foo/$class/Makefile.predynamic into Makefile.
 # This is used for router and transport drivers, called from scripts/Configure-Makefile.
 
 # We turn the configure-built build-$foo/$class/Makefile.predynamic into Makefile.
 # This is used for router and transport drivers, called from scripts/Configure-Makefile.
@@ -97,19 +98,18 @@ fi
 want_dynamic() {
   local dyn_name="${1#_}"
   local re="(${classdef}|EXPERIMENTAL)_${dyn_name}[ $tab]*=[ $tab]*2"
 want_dynamic() {
   local dyn_name="${1#_}"
   local re="(${classdef}|EXPERIMENTAL)_${dyn_name}[ $tab]*=[ $tab]*2"
-  #XXX Solaris does not support -E on grep.  Must use egrep.
-  env | grep -E -q "^$re"
+  env | ${egrep} -q "^$re"
   if [ $? -eq 0 ]; then return 0; fi
   if [ $? -eq 0 ]; then return 0; fi
-  grep -E -q "^[ $tab]*$re" "$defs_source"
+  ${egrep} -q "^[ $tab]*$re" "$defs_source"
 }
 
 want_not_disabled() {
   local want_name="${1#_}"
   [ "$local_want_name" = "$1" ] && return 0;
   local re="DISABLED_${want_name}[ $tab]*=[ $tab]*."
 }
 
 want_not_disabled() {
   local want_name="${1#_}"
   [ "$local_want_name" = "$1" ] && return 0;
   local re="DISABLED_${want_name}[ $tab]*=[ $tab]*."
-  env | grep -E -q "^$re"
+  env | ${egrep} -q "^$re"
   [ $? -ne 0 ] && return 0
   [ $? -ne 0 ] && return 0
-  grep -E -q "^[ $tab]*$re" "$defs_source"
+  ${egrep} -q "^[ $tab]*$re" "$defs_source"
   [ $? -ne 0 ] && return 0
   return 1
 }
   [ $? -ne 0 ] && return 0
   return 1
 }
@@ -117,9 +117,9 @@ want_not_disabled() {
 want_at_all() {
   local want_name="$1"
   local re="(${classdef}|EXPERIMENTAL)_${want_name}[ $tab]*=[ $tab]*."
 want_at_all() {
   local want_name="$1"
   local re="(${classdef}|EXPERIMENTAL)_${want_name}[ $tab]*=[ $tab]*."
-  env | grep -E -q "^$re"
+  env | ${egrep} -q "^$re"
   if [ $? -eq 0 ]; then return 0; fi
   if [ $? -eq 0 ]; then return 0; fi
-  grep -E -q "^[ $tab]*$re" "$defs_source"
+  ${egrep} -q "^[ $tab]*$re" "$defs_source"
 }
 
 # The values of these variables will be emitted into the Makefile.
 }
 
 # The values of these variables will be emitted into the Makefile.
diff --git a/src/src/auths/call_radius.c b/src/src/auths/call_radius.c
deleted file mode 100644 (file)
index 65882c1..0000000
+++ /dev/null
@@ -1,224 +0,0 @@
-/*************************************************
-*     Exim - an Internet mail transport agent    *
-*************************************************/
-
-/* Copyright (c) The Exim Maintainers 2020 - 2022 */
-/* Copyright (c) University of Cambridge 1995 - 2016 */
-/* See the file NOTICE for conditions of use and distribution. */
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-
-/* This file was originally supplied by Ian Kirk. The libradius support came
-from Alex Kiernan. */
-
-#include "../exim.h"
-
-/* This module contains functions that call the Radius authentication
-mechanism.
-
-We can't just compile this code and allow the library mechanism to omit the
-functions if they are not wanted, because we need to have the Radius headers
-available for compiling. Therefore, compile these functions only if
-RADIUS_CONFIG_FILE is defined. However, some compilers don't like compiling
-empty modules, so keep them happy with a dummy when skipping the rest. Make it
-reference itself to stop picky compilers complaining that it is unused, and put
-in a dummy argument to stop even pickier compilers complaining about infinite
-loops. Then use a mutually-recursive pair as gcc is just getting stupid. */
-
-#ifndef RADIUS_CONFIG_FILE
-static void dummy(int x);
-static void dummy2(int x) { dummy(x-1); }
-static void dummy(int x) { dummy2(x-1); }
-#else  /* RADIUS_CONFIG_FILE */
-
-
-/* Two different Radius libraries are supported. The default is radiusclient,
-using its original API. At release 0.4.0 the API changed. */
-
-#ifdef RADIUS_LIB_RADLIB
-# include <radlib.h>
-#else
-# if !defined(RADIUS_LIB_RADIUSCLIENT) && !defined(RADIUS_LIB_RADIUSCLIENTNEW)
-#  define RADIUS_LIB_RADIUSCLIENT
-# endif
-
-# ifdef RADIUS_LIB_RADIUSCLIENTNEW
-#  define ENV FREERADIUSCLIENT_ENV     /* Avoid clash with Berkeley DB */
-#  include <freeradius-client.h>
-# else
-#  include <radiusclient.h>
-# endif
-#endif
-
-
-
-/*************************************************
-*              Perform RADIUS authentication     *
-*************************************************/
-
-/* This function calls the Radius authentication mechanism, passing over one or
-more data strings.
-
-Arguments:
-  s        a colon-separated list of strings
-  errptr   where to point an error message
-
-Returns:   OK if authentication succeeded
-           FAIL if authentication failed
-           ERROR some other error condition
-*/
-
-int
-auth_call_radius(const uschar *s, uschar **errptr)
-{
-uschar *user;
-const uschar *radius_args = s;
-int result;
-int sep = 0;
-
-#ifdef RADIUS_LIB_RADLIB
-  struct rad_handle *h;
-#else
-  #ifdef RADIUS_LIB_RADIUSCLIENTNEW
-    rc_handle *h;
-  #endif
-  VALUE_PAIR *send = NULL;
-  VALUE_PAIR *received;
-  unsigned int service = PW_AUTHENTICATE_ONLY;
-  char msg[4096];
-#endif
-
-
-if (!(user = string_nextinlist(&radius_args, &sep, NULL, 0))) user = US"";
-
-DEBUG(D_auth) debug_printf("Running RADIUS authentication for user \"%s\" "
-               "and \"%s\"\n", user, radius_args);
-
-*errptr = NULL;
-
-
-/* Authenticate using the radiusclient library */
-
-#ifndef RADIUS_LIB_RADLIB
-
-rc_openlog("exim");
-
-#ifdef RADIUS_LIB_RADIUSCLIENT
-if (rc_read_config(RADIUS_CONFIG_FILE) != 0)
-  *errptr = string_sprintf("RADIUS: can't open %s", RADIUS_CONFIG_FILE);
-
-else if (rc_read_dictionary(rc_conf_str("dictionary")) != 0)
-  *errptr = US"RADIUS: can't read dictionary";
-
-else if (!rc_avpair_add(&send, PW_USER_NAME, user, 0))
-  *errptr = US"RADIUS: add user name failed";
-
-else if (!rc_avpair_add(&send, PW_USER_PASSWORD, CS radius_args, 0))
-  *errptr = US"RADIUS: add password failed");
-
-else if (!rc_avpair_add(&send, PW_SERVICE_TYPE, &service, 0))
-  *errptr = US"RADIUS: add service type failed";
-
-#else  /* RADIUS_LIB_RADIUSCLIENT unset => RADIUS_LIB_RADIUSCLIENT2 */
-
-if (!(h = rc_read_config(RADIUS_CONFIG_FILE)))
-  *errptr = string_sprintf("RADIUS: can't open %s", RADIUS_CONFIG_FILE);
-
-else if (rc_read_dictionary(h, rc_conf_str(h, "dictionary")) != 0)
-  *errptr = US"RADIUS: can't read dictionary";
-
-else if (!rc_avpair_add(h, &send, PW_USER_NAME, user, Ustrlen(user), 0))
-  *errptr = US"RADIUS: add user name failed";
-
-else if (!rc_avpair_add(h, &send, PW_USER_PASSWORD, CS radius_args,
-    Ustrlen(radius_args), 0))
-  *errptr = US"RADIUS: add password failed";
-
-else if (!rc_avpair_add(h, &send, PW_SERVICE_TYPE, &service, 0, 0))
-  *errptr = US"RADIUS: add service type failed";
-
-#endif  /* RADIUS_LIB_RADIUSCLIENT */
-
-if (*errptr)
-  {
-  DEBUG(D_auth) debug_printf("%s\n", *errptr);
-  return ERROR;
-  }
-
-#ifdef RADIUS_LIB_RADIUSCLIENT
-result = rc_auth(0, send, &received, msg);
-#else
-result = rc_auth(h, 0, send, &received, msg);
-#endif
-
-DEBUG(D_auth) debug_printf("RADIUS code returned %d\n", result);
-
-switch (result)
-  {
-  case OK_RC:
-    return OK;
-
-  case REJECT_RC:
-  case ERROR_RC:
-    return FAIL;
-
-  case TIMEOUT_RC:
-    *errptr = US"RADIUS: timed out";
-    return ERROR;
-
-  case BADRESP_RC:
-  default:
-    *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
-    return ERROR;
-  }
-
-#else  /* RADIUS_LIB_RADLIB is set */
-
-/* Authenticate using the libradius library */
-
-if (!(h = rad_auth_open()))
-  {
-  *errptr = string_sprintf("RADIUS: can't initialise libradius");
-  return ERROR;
-  }
-if (rad_config(h, RADIUS_CONFIG_FILE) != 0 ||
-    rad_create_request(h, RAD_ACCESS_REQUEST) != 0 ||
-    rad_put_string(h, RAD_USER_NAME, CS user) != 0 ||
-    rad_put_string(h, RAD_USER_PASSWORD, CS radius_args) != 0 ||
-    rad_put_int(h, RAD_SERVICE_TYPE, RAD_AUTHENTICATE_ONLY) != 0 ||
-    rad_put_string(h, RAD_NAS_IDENTIFIER, CS primary_hostname) != 0)
-  {
-  *errptr = string_sprintf("RADIUS: %s", rad_strerror(h));
-  result = ERROR;
-  }
-else
-  switch (result = rad_send_request(h))
-    {
-    case RAD_ACCESS_ACCEPT:
-      result = OK;
-      break;
-
-    case RAD_ACCESS_REJECT:
-      result = FAIL;
-      break;
-
-    case -1:
-      *errptr = string_sprintf("RADIUS: %s", rad_strerror(h));
-      result = ERROR;
-      break;
-
-    default:
-      *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
-      result= ERROR;
-      break;
-    }
-
-if (*errptr) DEBUG(D_auth) debug_printf("%s\n", *errptr);
-rad_close(h);
-return result;
-
-#endif  /* RADIUS_LIB_RADLIB */
-}
-
-#endif  /* RADIUS_CONFIG_FILE */
-
-/* End of call_radius.c */
index 20a288d66f6abee0a245b06c8671b39931ff7f8b..60aacee5b319e6c251e3f7dda35f37c408f79777 100644 (file)
@@ -168,8 +168,9 @@ Do not put spaces between # and the 'define'.
 #define SUPPORT_TRANSLATE_IP_ADDRESS
 
 /* Required to support dynamic-module build */
 #define SUPPORT_TRANSLATE_IP_ADDRESS
 
 /* Required to support dynamic-module build */
-#define SUPPORT_DKIM
 #define SUPPORT_ARC
 #define SUPPORT_ARC
+#define SUPPORT_DKIM
+#define SUPPORT_RADIUS
 
 #define SYSLOG_LOG_PID
 #define SYSLOG_LONG_LINES
 
 #define SYSLOG_LOG_PID
 #define SYSLOG_LONG_LINES
index f5043aea9857d8db2575cbea3b9af82e8c69de53..550f1a7bdec909da03d8ad68b514756fe05b24d6 100644 (file)
@@ -558,6 +558,9 @@ config.h, mytypes.h, and store.h, so we don't need to mention them explicitly.
 #ifdef EXPERIMENTAL_ARC
 # include "miscmods/arc_api.h"
 #endif
 #ifdef EXPERIMENTAL_ARC
 # include "miscmods/arc_api.h"
 #endif
+#ifdef RADIUS_CONFIG_FILE
+# include "miscmods/radius_api.h"
+#endif
 
 /* The following stuff must follow the inclusion of config.h because it
 requires various things that are set therein. */
 
 /* The following stuff must follow the inclusion of config.h because it
 requires various things that are set therein. */
index a41ba98cfce168a13bf28e942ff90b357e9e543f..521a30d4958e8cac56f6b04e95292e3617b78da5 100644 (file)
@@ -2775,12 +2775,19 @@ switch(cond_type = identify_operator(&s, &opname))
     #endif  /* SUPPORT_PAM */
 
     case ECOND_RADIUS:
     #endif  /* SUPPORT_PAM */
 
     case ECOND_RADIUS:
-    #ifdef RADIUS_CONFIG_FILE
-    rc = auth_call_radius(sub[0], &expand_string_message);
-    goto END_AUTH;
-    #else
-    goto COND_FAILED_NOT_COMPILED;
-    #endif  /* RADIUS_CONFIG_FILE */
+#ifdef RADIUS_CONFIG_FILE
+      {
+      const misc_module_info * mi = misc_mod_find(US"radius", NULL);
+      typedef int (*fn_t)(const uschar *, uschar **);
+      if (!mi)
+       goto COND_FAILED_NOT_COMPILED;
+      rc = (((fn_t *) mi->functions)[RADIUS_AUTH_CALL])
+                                         (sub[0], &expand_string_message);
+      goto END_AUTH;
+      }
+#else
+      goto COND_FAILED_NOT_COMPILED;
+#endif  /* RADIUS_CONFIG_FILE */
 
     case ECOND_LDAPAUTH:
     #ifdef LOOKUP_LDAP
 
     case ECOND_LDAPAUTH:
     #ifdef LOOKUP_LDAP
index deec54590bc8cd4c3e22b3404b56bd92ff291856..ac0c310970a941c83a7134ccc42029b6486b7213 100644 (file)
@@ -113,7 +113,6 @@ extern void    add_driver_info(driver_info **, const driver_info *, size_t);
 extern void    assert_no_variables(void *, int, const char *, int);
 extern int     auth_call_pam(const uschar *, uschar **);
 extern int     auth_call_pwcheck(uschar *, uschar **);
 extern void    assert_no_variables(void *, int, const char *, int);
 extern int     auth_call_pam(const uschar *, uschar **);
 extern int     auth_call_pwcheck(uschar *, uschar **);
-extern int     auth_call_radius(const uschar *, uschar **);
 extern int     auth_call_saslauthd(const uschar *, const uschar *,
                 const uschar *, const uschar *, uschar **);
 extern int     auth_check_serv_cond(auth_instance *);
 extern int     auth_call_saslauthd(const uschar *, const uschar *,
                 const uschar *, const uschar *, uschar **);
 extern int     auth_check_serv_cond(auth_instance *);
index a4ffcfc92c31e1c4d4b50ca628efb93e10db3919..a15fd9b380a058dffc31d2e6f043134013115b80 100644 (file)
@@ -41,13 +41,14 @@ spf.o   spf.so:             $(HDRS) spf.h spf.c
 
 dkim.o:
                @echo "$(CC) dkim.c dkim_transport.c pdkim.c signing.c"
 
 dkim.o:
                @echo "$(CC) dkim.c dkim_transport.c pdkim.c signing.c"
-               $(FE)$(CC) -r $(LDFLAGS_PARTIAL) $(CFLAGS) $(INCLUDE) \
-                       dkim.c dkim_transport.c pdkim.c signing.c -o $@
+               $(FE)$(CC) -r $(LDFLAGS_PARTIAL) -o $@ $(CFLAGS) $(INCLUDE) \
+                       dkim.c dkim_transport.c pdkim.c signing.c
 
 dkim.so:
                @echo "$(CC) -shared dkim.c dkim_transport.c pdkim.c signing.c"
 
 dkim.so:
                @echo "$(CC) -shared dkim.c dkim_transport.c pdkim.c signing.c"
-               $(FE)$(CC) $(SUPPORT_$*_INCLUDE) $(SUPPORT_$*_LIBS) \
-                       -DDYNLOOKUP $(CFLAGS_DYNAMIC) $(CFLAGS) $(INCLUDE) \
-                       $(DLFLAGS) dkim.c dkim_transport.c pdkim.c signing.c -o $@
+               $(FE)$(CC) -DDYNLOOKUP $(CFLAGS_DYNAMIC) -o $@ \
+                       $(SUPPORT_$*_INCLUDE) $(SUPPORT_$*_LIBS) \
+                       $(CFLAGS) $(INCLUDE) $(DLFLAGS) \
+                       dkim.c dkim_transport.c pdkim.c signing.c
 
 # End
 
 # End
index db546e1ab36fe160960777f44b08ab41fce952ae..a48d1987b1e428f971b9886699412dd7285e0500 100644 (file)
@@ -2151,7 +2151,7 @@ static var_entry arc_variables[] = {
 misc_module_info arc_module_info =
 {
   .name =              US"arc",
 misc_module_info arc_module_info =
 {
   .name =              US"arc",
-# if SUPPORT_SPF==2
+# ifdef DYNLOOKUP
   .dyn_magic =         MISC_MODULE_MAGIC,
 # endif
   .init =              arc_init,
   .dyn_magic =         MISC_MODULE_MAGIC,
 # endif
   .init =              arc_init,
index 632ff4813df4c86d18ab495d9743b058d23869aa..40339d100af146d329653686e2b803ad204aa82f 100644 (file)
@@ -1359,7 +1359,7 @@ static var_entry dkim_variables[] = {
 
 misc_module_info dkim_module_info = {
   .name =              US"dkim",
 
 misc_module_info dkim_module_info = {
   .name =              US"dkim",
-# if SUPPORT_DKIM==2
+# ifdef DYNLOOKUP
   .dyn_magic =         MISC_MODULE_MAGIC,
 # endif
   .init =              dkim_exim_init,
   .dyn_magic =         MISC_MODULE_MAGIC,
 # endif
   .init =              dkim_exim_init,
index e192bda1b958f94007295e031c6613fff15285ac..161bfeececb97a95df7e01993fc074220988a4db 100644 (file)
@@ -806,7 +806,7 @@ static var_entry dmarc_variables[] = {
 misc_module_info dmarc_module_info =
 {
   .name =              US"dmarc",
 misc_module_info dmarc_module_info =
 {
   .name =              US"dmarc",
-# if SUPPORT_SPF==2
+# ifdef DYNLOOKUP
   .dyn_magic =         MISC_MODULE_MAGIC,
 # endif
   .init =              dmarc_init,
   .dyn_magic =         MISC_MODULE_MAGIC,
 # endif
   .init =              dmarc_init,
diff --git a/src/src/miscmods/radius.c b/src/src/miscmods/radius.c
new file mode 100644 (file)
index 0000000..61ca6ea
--- /dev/null
@@ -0,0 +1,244 @@
+/*************************************************
+*     Exim - an Internet mail transport agent    *
+*************************************************/
+
+/* Copyright (c) The Exim Maintainers 2020 - 2022 */
+/* Copyright (c) University of Cambridge 1995 - 2016 */
+/* See the file NOTICE for conditions of use and distribution. */
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* This file was originally supplied by Ian Kirk. The libradius support came
+from Alex Kiernan. */
+
+#include "../exim.h"
+
+/* This module contains functions that call the Radius authentication
+mechanism.
+
+We can't just compile this code and allow the library mechanism to omit the
+functions if they are not wanted, because we need to have the Radius headers
+available for compiling. Therefore, compile these functions only if
+RADIUS_CONFIG_FILE is defined. However, some compilers don't like compiling
+empty modules, so keep them happy with a dummy when skipping the rest. Make it
+reference itself to stop picky compilers complaining that it is unused, and put
+in a dummy argument to stop even pickier compilers complaining about infinite
+loops. Then use a mutually-recursive pair as gcc is just getting stupid. */
+
+#ifndef RADIUS_CONFIG_FILE
+static void dummy(int x);
+static void dummy2(int x) { dummy(x-1); }
+static void dummy(int x) { dummy2(x-1); }
+#else  /* RADIUS_CONFIG_FILE */
+
+
+/* Two different Radius libraries are supported. The default is radiusclient,
+using its original API. At release 0.4.0 the API changed. */
+
+#ifdef RADIUS_LIB_RADLIB
+# include <radlib.h>
+#else
+# if !defined(RADIUS_LIB_RADIUSCLIENT) && !defined(RADIUS_LIB_RADIUSCLIENTNEW)
+#  define RADIUS_LIB_RADIUSCLIENT
+# endif
+
+# ifdef RADIUS_LIB_RADIUSCLIENTNEW
+#  define ENV FREERADIUSCLIENT_ENV     /* Avoid clash with Berkeley DB */
+#  include <freeradius-client.h>
+# else
+#  include <radiusclient.h>
+# endif
+#endif
+
+
+
+/*************************************************
+*              Perform RADIUS authentication     *
+*************************************************/
+
+/* This function calls the Radius authentication mechanism, passing over one or
+more data strings.
+
+Arguments:
+  s        a colon-separated list of strings
+  errptr   where to point an error message
+
+Returns:   OK if authentication succeeded
+           FAIL if authentication failed
+           ERROR some other error condition
+*/
+
+static int
+auth_call_radius(const uschar *s, uschar **errptr)
+{
+uschar *user;
+const uschar *radius_args = s;
+int result;
+int sep = 0;
+
+#ifdef RADIUS_LIB_RADLIB
+  struct rad_handle *h;
+#else
+  #ifdef RADIUS_LIB_RADIUSCLIENTNEW
+    rc_handle *h;
+  #endif
+  VALUE_PAIR *send = NULL;
+  VALUE_PAIR *received;
+  unsigned int service = PW_AUTHENTICATE_ONLY;
+  char msg[4096];
+#endif
+
+
+if (!(user = string_nextinlist(&radius_args, &sep, NULL, 0))) user = US"";
+
+DEBUG(D_auth) debug_printf("Running RADIUS authentication for user \"%s\" "
+               "and \"%s\"\n", user, radius_args);
+
+*errptr = NULL;
+
+
+/* Authenticate using the radiusclient library */
+
+#ifndef RADIUS_LIB_RADLIB
+
+rc_openlog("exim");
+
+#ifdef RADIUS_LIB_RADIUSCLIENT
+if (rc_read_config(RADIUS_CONFIG_FILE) != 0)
+  *errptr = string_sprintf("RADIUS: can't open %s", RADIUS_CONFIG_FILE);
+
+else if (rc_read_dictionary(rc_conf_str("dictionary")) != 0)
+  *errptr = US"RADIUS: can't read dictionary";
+
+else if (!rc_avpair_add(&send, PW_USER_NAME, user, 0))
+  *errptr = US"RADIUS: add user name failed";
+
+else if (!rc_avpair_add(&send, PW_USER_PASSWORD, CS radius_args, 0))
+  *errptr = US"RADIUS: add password failed");
+
+else if (!rc_avpair_add(&send, PW_SERVICE_TYPE, &service, 0))
+  *errptr = US"RADIUS: add service type failed";
+
+#else  /* RADIUS_LIB_RADIUSCLIENT unset => RADIUS_LIB_RADIUSCLIENT2 */
+
+if (!(h = rc_read_config(RADIUS_CONFIG_FILE)))
+  *errptr = string_sprintf("RADIUS: can't open %s", RADIUS_CONFIG_FILE);
+
+else if (rc_read_dictionary(h, rc_conf_str(h, "dictionary")) != 0)
+  *errptr = US"RADIUS: can't read dictionary";
+
+else if (!rc_avpair_add(h, &send, PW_USER_NAME, user, Ustrlen(user), 0))
+  *errptr = US"RADIUS: add user name failed";
+
+else if (!rc_avpair_add(h, &send, PW_USER_PASSWORD, CS radius_args,
+    Ustrlen(radius_args), 0))
+  *errptr = US"RADIUS: add password failed";
+
+else if (!rc_avpair_add(h, &send, PW_SERVICE_TYPE, &service, 0, 0))
+  *errptr = US"RADIUS: add service type failed";
+
+#endif  /* RADIUS_LIB_RADIUSCLIENT */
+
+if (*errptr)
+  {
+  DEBUG(D_auth) debug_printf("%s\n", *errptr);
+  return ERROR;
+  }
+
+#ifdef RADIUS_LIB_RADIUSCLIENT
+result = rc_auth(0, send, &received, msg);
+#else
+result = rc_auth(h, 0, send, &received, msg);
+#endif
+
+DEBUG(D_auth) debug_printf("RADIUS code returned %d\n", result);
+
+switch (result)
+  {
+  case OK_RC:
+    return OK;
+
+  case REJECT_RC:
+  case ERROR_RC:
+    return FAIL;
+
+  case TIMEOUT_RC:
+    *errptr = US"RADIUS: timed out";
+    return ERROR;
+
+  case BADRESP_RC:
+  default:
+    *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
+    return ERROR;
+  }
+
+#else  /* RADIUS_LIB_RADLIB is set */
+
+/* Authenticate using the libradius library */
+
+if (!(h = rad_auth_open()))
+  {
+  *errptr = string_sprintf("RADIUS: can't initialise libradius");
+  return ERROR;
+  }
+if (rad_config(h, RADIUS_CONFIG_FILE) != 0 ||
+    rad_create_request(h, RAD_ACCESS_REQUEST) != 0 ||
+    rad_put_string(h, RAD_USER_NAME, CS user) != 0 ||
+    rad_put_string(h, RAD_USER_PASSWORD, CS radius_args) != 0 ||
+    rad_put_int(h, RAD_SERVICE_TYPE, RAD_AUTHENTICATE_ONLY) != 0 ||
+    rad_put_string(h, RAD_NAS_IDENTIFIER, CS primary_hostname) != 0)
+  {
+  *errptr = string_sprintf("RADIUS: %s", rad_strerror(h));
+  result = ERROR;
+  }
+else
+  switch (result = rad_send_request(h))
+    {
+    case RAD_ACCESS_ACCEPT:
+      result = OK;
+      break;
+
+    case RAD_ACCESS_REJECT:
+      result = FAIL;
+      break;
+
+    case -1:
+      *errptr = string_sprintf("RADIUS: %s", rad_strerror(h));
+      result = ERROR;
+      break;
+
+    default:
+      *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
+      result= ERROR;
+      break;
+    }
+
+if (*errptr) DEBUG(D_auth) debug_printf("%s\n", *errptr);
+rad_close(h);
+return result;
+
+#endif  /* RADIUS_LIB_RADLIB */
+}
+
+
+
+/******************************************************************************/
+/* Module API */
+
+static void * rad_functions[] = {
+  [RADIUS_AUTH_CALL] = auth_call_radius,
+};
+
+misc_module_info rad_module_info =
+{
+  .name =              US"radius",
+# ifdef DYNLOOKUP
+  .dyn_magic =         MISC_MODULE_MAGIC,
+# endif
+
+  .functions =         rad_functions,
+  .functions_count =   nelem(rad_functions),
+};
+
+#endif  /* RADIUS_CONFIG_FILE */
+
+/* End of call_radius.c */
index 14937e7999fe1bc9e6931994ac7b06e124cb11c5..17c1a3602e5af5ade22fec853204078182c2a477 100644 (file)
@@ -585,7 +585,7 @@ static var_entry spf_variables[] = {
 misc_module_info spf_module_info =
 {
   .name =              US"spf",
 misc_module_info spf_module_info =
 {
   .name =              US"spf",
-# if SUPPORT_SPF==2
+# ifdef DYNLOOKUP
   .dyn_magic =         MISC_MODULE_MAGIC,
 # endif
   .init =              spf_init,
   .dyn_magic =         MISC_MODULE_MAGIC,
 # endif
   .init =              spf_init,