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
23 loops. Then use a mutually-recursive pair as gcc is just getting stupid. */
25 #ifndef RADIUS_CONFIG_FILE
26 static void dummy(int x);
27 static void dummy2(int x) { dummy(x-1); }
28 static void dummy(int x) { dummy2(x-1); }
29 #else /* RADIUS_CONFIG_FILE */
32 /* Two different Radius libraries are supported. The default is radiusclient,
33 using its original API. At release 0.4.0 the API changed. */
35 #ifdef RADIUS_LIB_RADLIB
38 #if !defined(RADIUS_LIB_RADIUSCLIENT) && !defined(RADIUS_LIB_RADIUSCLIENTNEW)
39 #define RADIUS_LIB_RADIUSCLIENT
41 #include <radiusclient.h>
46 /*************************************************
47 * Perform RADIUS authentication *
48 *************************************************/
50 /* This function calls the Radius authentication mechanism, passing over one or
54 s a colon-separated list of strings
55 errptr where to point an error message
57 Returns: OK if authentication succeeded
58 FAIL if authentication failed
59 ERROR some other error condition
63 auth_call_radius(const uschar *s, uschar **errptr)
66 const uschar *radius_args = s;
70 #ifdef RADIUS_LIB_RADLIB
73 #ifdef RADIUS_LIB_RADIUSCLIENTNEW
76 VALUE_PAIR *send = NULL;
78 unsigned int service = PW_AUTHENTICATE_ONLY;
83 user = string_nextinlist(&radius_args, &sep, big_buffer, big_buffer_size);
84 if (user == NULL) user = US"";
86 DEBUG(D_auth) debug_printf("Running RADIUS authentication for user \"%s\" "
87 "and \"%s\"\n", user, radius_args);
92 /* Authenticate using the radiusclient library */
94 #ifndef RADIUS_LIB_RADLIB
98 #ifdef RADIUS_LIB_RADIUSCLIENT
99 if (rc_read_config(RADIUS_CONFIG_FILE) != 0)
100 *errptr = string_sprintf("RADIUS: can't open %s", RADIUS_CONFIG_FILE);
102 else if (rc_read_dictionary(rc_conf_str("dictionary")) != 0)
103 *errptr = string_sprintf("RADIUS: can't read dictionary");
105 else if (rc_avpair_add(&send, PW_USER_NAME, user, 0) == NULL)
106 *errptr = string_sprintf("RADIUS: add user name failed\n");
108 else if (rc_avpair_add(&send, PW_USER_PASSWORD, CS radius_args, 0) == NULL)
109 *errptr = string_sprintf("RADIUS: add password failed\n");
111 else if (rc_avpair_add(&send, PW_SERVICE_TYPE, &service, 0) == NULL)
112 *errptr = string_sprintf("RADIUS: add service type failed\n");
114 #else /* RADIUS_LIB_RADIUSCLIENT unset => RADIUS_LIB_RADIUSCLIENT2 */
116 if ((h = rc_read_config(RADIUS_CONFIG_FILE)) == NULL)
117 *errptr = string_sprintf("RADIUS: can't open %s", RADIUS_CONFIG_FILE);
119 else if (rc_read_dictionary(h, rc_conf_str(h, "dictionary")) != 0)
120 *errptr = string_sprintf("RADIUS: can't read dictionary");
122 else if (rc_avpair_add(h, &send, PW_USER_NAME, user, Ustrlen(user), 0) == NULL)
123 *errptr = string_sprintf("RADIUS: add user name failed\n");
125 else if (rc_avpair_add(h, &send, PW_USER_PASSWORD, CS radius_args,
126 Ustrlen(radius_args), 0) == NULL)
127 *errptr = string_sprintf("RADIUS: add password failed\n");
129 else if (rc_avpair_add(h, &send, PW_SERVICE_TYPE, &service, 0, 0) == NULL)
130 *errptr = string_sprintf("RADIUS: add service type failed\n");
132 #endif /* RADIUS_LIB_RADIUSCLIENT */
136 DEBUG(D_auth) debug_printf("%s\n", *errptr);
140 #ifdef RADIUS_LIB_RADIUSCLIENT
141 result = rc_auth(0, send, &received, msg);
143 result = rc_auth(h, 0, send, &received, msg);
146 DEBUG(D_auth) debug_printf("RADIUS code returned %d\n", result);
157 *errptr = US"RADIUS: timed out";
162 *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
166 #else /* RADIUS_LIB_RADLIB is set */
168 /* Authenticate using the libradius library */
173 *errptr = string_sprintf("RADIUS: can't initialise libradius");
176 if (rad_config(h, RADIUS_CONFIG_FILE) != 0 ||
177 rad_create_request(h, RAD_ACCESS_REQUEST) != 0 ||
178 rad_put_string(h, RAD_USER_NAME, CS user) != 0 ||
179 rad_put_string(h, RAD_USER_PASSWORD, CS radius_args) != 0 ||
180 rad_put_int(h, RAD_SERVICE_TYPE, RAD_AUTHENTICATE_ONLY) != 0 ||
181 rad_put_string(h, RAD_NAS_IDENTIFIER, CS primary_hostname) != 0)
183 *errptr = string_sprintf("RADIUS: %s", rad_strerror(h));
188 result = rad_send_request(h);
192 case RAD_ACCESS_ACCEPT:
196 case RAD_ACCESS_REJECT:
201 *errptr = string_sprintf("RADIUS: %s", rad_strerror(h));
206 *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
212 if (*errptr != NULL) DEBUG(D_auth) debug_printf("%s\n", *errptr);
216 #endif /* RADIUS_LIB_RADLIB */
219 #endif /* RADIUS_CONFIG_FILE */
221 /* End of call_radius.c */