1 /*************************************************
2 * Exim - an Internet mail transport agent *
3 *************************************************/
5 /* Copyright (c) University of Cambridge 1995 - 2009 */
6 /* See the file NOTICE for conditions of use and distribution. */
8 /* This file was originally supplied by Ian Kirk. The libradius support came
13 /* This module contains functions that call the Radius authentication
16 We can't just compile this code and allow the library mechanism to omit the
17 functions if they are not wanted, because we need to have the Radius headers
18 available for compiling. Therefore, compile these functions only if
19 RADIUS_CONFIG_FILE is defined. However, some compilers don't like compiling
20 empty modules, so keep them happy with a dummy when skipping the rest. Make it
21 reference itself to stop picky compilers complaining that it is unused, and put
22 in a dummy argument to stop even pickier compilers complaining about infinite
25 #ifndef RADIUS_CONFIG_FILE
26 static void dummy(int x) { dummy(x-1); }
27 #else /* RADIUS_CONFIG_FILE */
30 /* Two different Radius libraries are supported. The default is radiusclient,
31 using its original API. At release 0.4.0 the API changed. */
33 #ifdef RADIUS_LIB_RADLIB
36 #if !defined(RADIUS_LIB_RADIUSCLIENT) && !defined(RADIUS_LIB_RADIUSCLIENTNEW)
37 #define RADIUS_LIB_RADIUSCLIENT
39 #include <radiusclient.h>
44 /*************************************************
45 * Perform RADIUS authentication *
46 *************************************************/
48 /* This function calls the Radius authentication mechanism, passing over one or
52 s a colon-separated list of strings
53 errptr where to point an error message
55 Returns: OK if authentication succeeded
56 FAIL if authentication failed
57 ERROR some other error condition
61 auth_call_radius(uschar *s, uschar **errptr)
64 uschar *radius_args = s;
68 #ifdef RADIUS_LIB_RADLIB
71 #ifdef RADIUS_LIB_RADIUSCLIENTNEW
74 VALUE_PAIR *send = NULL;
76 unsigned int service = PW_AUTHENTICATE_ONLY;
81 user = string_nextinlist(&radius_args, &sep, big_buffer, big_buffer_size);
82 if (user == NULL) user = US"";
84 DEBUG(D_auth) debug_printf("Running RADIUS authentication for user \"%s\" "
85 "and \"%s\"\n", user, radius_args);
90 /* Authenticate using the radiusclient library */
92 #ifndef RADIUS_LIB_RADLIB
96 #ifdef RADIUS_LIB_RADIUSCLIENT
97 if (rc_read_config(RADIUS_CONFIG_FILE) != 0)
98 *errptr = string_sprintf("RADIUS: can't open %s", RADIUS_CONFIG_FILE);
100 else if (rc_read_dictionary(rc_conf_str("dictionary")) != 0)
101 *errptr = string_sprintf("RADIUS: can't read dictionary");
103 else if (rc_avpair_add(&send, PW_USER_NAME, user, 0) == NULL)
104 *errptr = string_sprintf("RADIUS: add user name failed\n");
106 else if (rc_avpair_add(&send, PW_USER_PASSWORD, CS radius_args, 0) == NULL)
107 *errptr = string_sprintf("RADIUS: add password failed\n");
109 else if (rc_avpair_add(&send, PW_SERVICE_TYPE, &service, 0) == NULL)
110 *errptr = string_sprintf("RADIUS: add service type failed\n");
112 #else /* RADIUS_LIB_RADIUSCLIENT unset => RADIUS_LIB_RADIUSCLIENT2 */
114 if ((h = rc_read_config(RADIUS_CONFIG_FILE)) == NULL)
115 *errptr = string_sprintf("RADIUS: can't open %s", RADIUS_CONFIG_FILE);
117 else if (rc_read_dictionary(h, rc_conf_str(h, "dictionary")) != 0)
118 *errptr = string_sprintf("RADIUS: can't read dictionary");
120 else if (rc_avpair_add(h, &send, PW_USER_NAME, user, Ustrlen(user), 0) == NULL)
121 *errptr = string_sprintf("RADIUS: add user name failed\n");
123 else if (rc_avpair_add(h, &send, PW_USER_PASSWORD, CS radius_args,
124 Ustrlen(radius_args), 0) == NULL)
125 *errptr = string_sprintf("RADIUS: add password failed\n");
127 else if (rc_avpair_add(h, &send, PW_SERVICE_TYPE, &service, 0, 0) == NULL)
128 *errptr = string_sprintf("RADIUS: add service type failed\n");
130 #endif /* RADIUS_LIB_RADIUSCLIENT */
134 DEBUG(D_auth) debug_printf("%s\n", *errptr);
138 #ifdef RADIUS_LIB_RADIUSCLIENT
139 result = rc_auth(0, send, &received, msg);
141 result = rc_auth(h, 0, send, &received, msg);
144 DEBUG(D_auth) debug_printf("RADIUS code returned %d\n", result);
155 *errptr = US"RADIUS: timed out";
160 *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
164 #else /* RADIUS_LIB_RADLIB is set */
166 /* Authenticate using the libradius library */
171 *errptr = string_sprintf("RADIUS: can't initialise libradius");
174 if (rad_config(h, RADIUS_CONFIG_FILE) != 0 ||
175 rad_create_request(h, RAD_ACCESS_REQUEST) != 0 ||
176 rad_put_string(h, RAD_USER_NAME, CS user) != 0 ||
177 rad_put_string(h, RAD_USER_PASSWORD, CS radius_args) != 0 ||
178 rad_put_int(h, RAD_SERVICE_TYPE, RAD_AUTHENTICATE_ONLY) != 0 ||
179 rad_put_string(h, RAD_NAS_IDENTIFIER, CS primary_hostname) != 0)
181 *errptr = string_sprintf("RADIUS: %s", rad_strerror(h));
186 result = rad_send_request(h);
190 case RAD_ACCESS_ACCEPT:
194 case RAD_ACCESS_REJECT:
199 *errptr = string_sprintf("RADIUS: %s", rad_strerror(h));
204 *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
210 if (*errptr != NULL) DEBUG(D_auth) debug_printf("%s\n", *errptr);
214 #endif /* RADIUS_LIB_RADLIB */
217 #endif /* RADIUS_CONFIG_FILE */
219 /* End of call_radius.c */