X-Git-Url: https://git.exim.org/exim.git/blobdiff_plain/0756eb3cb50d73a77b486e47528f7cb1bffdb299..1d28cc061677bd07d9bed48dd84bd5c590247043:/src/src/auths/call_radius.c diff --git a/src/src/auths/call_radius.c b/src/src/auths/call_radius.c index 5cfcd4eb6..65882c108 100644 --- a/src/src/auths/call_radius.c +++ b/src/src/auths/call_radius.c @@ -1,11 +1,11 @@ -/* $Cambridge: exim/src/src/auths/call_radius.c,v 1.1 2004/10/07 13:10:01 ph10 Exp $ */ - /************************************************* * Exim - an Internet mail transport agent * *************************************************/ -/* Copyright (c) University of Cambridge 1995 - 2004 */ +/* 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,22 +22,31 @@ 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 */ -/* Two different Radius libraries are supported. The default is radiusclient. */ +/* 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 +# include #else - #ifndef RADIUS_LIB_RADIUSCLIENT - #define RADIUS_LIB_RADIUSCLIENT - #endif - #include +# 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 +# else +# include +# endif #endif @@ -59,25 +68,27 @@ 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; #ifdef RADIUS_LIB_RADLIB -struct rad_handle *h; + struct rad_handle *h; #else -VALUE_PAIR *send = NULL; -VALUE_PAIR *received; -unsigned int service = PW_AUTHENTICATE_ONLY; -char msg[4096]; + #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 -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); @@ -87,58 +98,84 @@ DEBUG(D_auth) debug_printf("Running RADIUS authentication for user \"%s\" " /* Authenticate using the radiusclient library */ -#ifdef RADIUS_LIB_RADIUSCLIENT +#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 = 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)) + *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(&send, PW_USER_NAME, user, 0) == NULL) - *errptr = string_sprintf("RADIUS: add user name 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(&send, PW_USER_PASSWORD, CS radius_args, 0) == NULL) - *errptr = string_sprintf("RADIUS: add password failed\n"); +else if (!rc_avpair_add(h, &send, PW_SERVICE_TYPE, &service, 0, 0)) + *errptr = US"RADIUS: add service type failed"; -else if (rc_avpair_add(&send, PW_SERVICE_TYPE, &service, 0) == NULL) - *errptr = string_sprintf("RADIUS: add service type failed\n"); +#endif /* RADIUS_LIB_RADIUSCLIENT */ -if (*errptr != NULL) +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; + 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_RADIUSCLIENT not set => RADIUS_LIB_RADLIB is set */ +#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; @@ -147,38 +184,35 @@ 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_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 - { - 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;