Merge branch '4.next'
[exim.git] / src / src / auths / call_radius.c
index 90e2e68806d7fc3b36656d778fc4fb1eb372ed80..65882c1089a1af6a5d6be7d42f37a646090d7dab 100644 (file)
@@ -1,11 +1,11 @@
-/* $Cambridge: exim/src/src/auths/call_radius.c,v 1.6 2006/06/28 13:59:13 ph10 Exp $ */
-
 /*************************************************
 *     Exim - an Internet mail transport agent    *
 *************************************************/
 
-/* Copyright (c) University of Cambridge 1995 - 2006 */
+/* 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. */
@@ -22,10 +22,12 @@ 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. */
+loops. Then use a mutually-recursive pair as gcc is just getting stupid. */
 
 #ifndef RADIUS_CONFIG_FILE
-static void dummy(int x) { dummy(x-1); }
+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 */
 
 
@@ -33,12 +35,18 @@ static void dummy(int x) { dummy(x-1); }
 using its original API. At release 0.4.0 the API changed. */
 
 #ifdef RADIUS_LIB_RADLIB
-  #include <radlib.h>
+include <radlib.h>
 #else
-  #if !defined(RADIUS_LIB_RADIUSCLIENT) && !defined(RADIUS_LIB_RADIUSCLIENTNEW)
-  #define RADIUS_LIB_RADIUSCLIENT
-  #endif
-  #include <radiusclient.h>
+# 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
 
 
@@ -60,10 +68,10 @@ Returns:   OK if authentication succeeded
 */
 
 int
-auth_call_radius(uschar *s, uschar **errptr)
+auth_call_radius(const uschar *s, uschar **errptr)
 {
 uschar *user;
-uschar *radius_args = s;
+const uschar *radius_args = s;
 int result;
 int sep = 0;
 
@@ -80,8 +88,7 @@ int sep = 0;
 #endif
 
 
-user = string_nextinlist(&radius_args, &sep, big_buffer, big_buffer_size);
-if (user == NULL) user = US"";
+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);
@@ -100,38 +107,38 @@ 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 = string_sprintf("RADIUS: can't read dictionary");
+  *errptr = US"RADIUS: can't read dictionary";
 
-else if (rc_avpair_add(&send, PW_USER_NAME, user, 0) == NULL)
-  *errptr = string_sprintf("RADIUS: add user name failed\n");
+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) == NULL)
-  *errptr = string_sprintf("RADIUS: add password failed\n");
+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) == NULL)
-  *errptr = string_sprintf("RADIUS: add service type failed\n");
+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)) == NULL)
+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 = string_sprintf("RADIUS: can't read dictionary");
+  *errptr = US"RADIUS: can't read dictionary";
 
-else if (rc_avpair_add(h, &send, PW_USER_NAME, user, Ustrlen(user), 0) == NULL)
-  *errptr = string_sprintf("RADIUS: add user name failed\n");
+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) == NULL)
-  *errptr = string_sprintf("RADIUS: add password failed\n");
+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) == NULL)
-  *errptr = string_sprintf("RADIUS: add service type failed\n");
+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 != NULL)
+if (*errptr)
   {
   DEBUG(D_auth) debug_printf("%s\n", *errptr);
   return ERROR;
@@ -148,27 +155,27 @@ DEBUG(D_auth) debug_printf("RADIUS code returned %d\n", result);
 switch (result)
   {
   case OK_RC:
-  return OK;
+    return OK;
 
+  case REJECT_RC:
   case ERROR_RC:
-  return FAIL;
+    return FAIL;
 
   case TIMEOUT_RC:
-  *errptr = US"RADIUS: timed out";
-  return ERROR;
+    *errptr = US"RADIUS: timed out";
+    return ERROR;
 
-  default:
   case BADRESP_RC:
-  *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
-  return ERROR;
+  default:
+    *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
+    return ERROR;
   }
 
 #else  /* RADIUS_LIB_RADLIB is set */
 
 /* Authenticate using the libradius library */
 
-h = rad_auth_open();
-if (h == NULL)
+if (!(h = rad_auth_open()))
   {
   *errptr = string_sprintf("RADIUS: can't initialise libradius");
   return ERROR;
@@ -184,32 +191,28 @@ if (rad_config(h, RADIUS_CONFIG_FILE) != 0 ||
   result = ERROR;
   }
 else
-  {
-  result = rad_send_request(h);
-
-  switch(result)
+  switch (result = rad_send_request(h))
     {
     case RAD_ACCESS_ACCEPT:
-    result = OK;
-    break;
+      result = OK;
+      break;
 
     case RAD_ACCESS_REJECT:
-    result = FAIL;
-    break;
+      result = FAIL;
+      break;
 
     case -1:
-    *errptr = string_sprintf("RADIUS: %s", rad_strerror(h));
-    result = ERROR;
-    break;
+      *errptr = string_sprintf("RADIUS: %s", rad_strerror(h));
+      result = ERROR;
+      break;
 
     default:
-    *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
-    result= ERROR;
-    break;
+      *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
+      result= ERROR;
+      break;
     }
-  }
 
-if (*errptr != NULL) DEBUG(D_auth) debug_printf("%s\n", *errptr);
+if (*errptr) DEBUG(D_auth) debug_printf("%s\n", *errptr);
 rad_close(h);
 return result;