New OS/os.c-cygwin from the maintainer.
[exim.git] / src / src / auths / call_radius.c
CommitLineData
c988f1f4 1/* $Cambridge: exim/src/src/auths/call_radius.c,v 1.2 2005/01/04 10:00:43 ph10 Exp $ */
0756eb3c
PH
2
3/*************************************************
4* Exim - an Internet mail transport agent *
5*************************************************/
6
c988f1f4 7/* Copyright (c) University of Cambridge 1995 - 2005 */
0756eb3c
PH
8/* See the file NOTICE for conditions of use and distribution. */
9
10/* This file was originally supplied by Ian Kirk. The libradius support came
11from Alex Kiernan. */
12
13#include "../exim.h"
14
15/* This module contains functions that call the Radius authentication
16mechanism.
17
18We can't just compile this code and allow the library mechanism to omit the
19functions if they are not wanted, because we need to have the Radius headers
20available for compiling. Therefore, compile these functions only if
21RADIUS_CONFIG_FILE is defined. However, some compilers don't like compiling
22empty modules, so keep them happy with a dummy when skipping the rest. Make it
23reference itself to stop picky compilers complaining that it is unused, and put
24in a dummy argument to stop even pickier compilers complaining about infinite
25loops. */
26
27#ifndef RADIUS_CONFIG_FILE
28static void dummy(int x) { dummy(x-1); }
29#else /* RADIUS_CONFIG_FILE */
30
31
32/* Two different Radius libraries are supported. The default is radiusclient. */
33
34#ifdef RADIUS_LIB_RADLIB
35 #include <radlib.h>
36#else
37 #ifndef RADIUS_LIB_RADIUSCLIENT
38 #define RADIUS_LIB_RADIUSCLIENT
39 #endif
40 #include <radiusclient.h>
41#endif
42
43
44
45/*************************************************
46* Perform RADIUS authentication *
47*************************************************/
48
49/* This function calls the Radius authentication mechanism, passing over one or
50more data strings.
51
52Arguments:
53 s a colon-separated list of strings
54 errptr where to point an error message
55
56Returns: OK if authentication succeeded
57 FAIL if authentication failed
58 ERROR some other error condition
59*/
60
61int
62auth_call_radius(uschar *s, uschar **errptr)
63{
64uschar *user;
65uschar *radius_args = s;
66int result;
67int sep = 0;
68
69#ifdef RADIUS_LIB_RADLIB
70struct rad_handle *h;
71#else
72VALUE_PAIR *send = NULL;
73VALUE_PAIR *received;
74unsigned int service = PW_AUTHENTICATE_ONLY;
75char msg[4096];
76#endif
77
78
79user = string_nextinlist(&radius_args, &sep, big_buffer, big_buffer_size);
80if (user == NULL) user = US"";
81
82DEBUG(D_auth) debug_printf("Running RADIUS authentication for user \"%s\" "
83 "and \"%s\"\n", user, radius_args);
84
85*errptr = NULL;
86
87
88/* Authenticate using the radiusclient library */
89
90#ifdef RADIUS_LIB_RADIUSCLIENT
91
92rc_openlog("exim");
93
94if (rc_read_config(RADIUS_CONFIG_FILE) != 0)
95 *errptr = string_sprintf("RADIUS: can't open %s", RADIUS_CONFIG_FILE);
96
97else if (rc_read_dictionary(rc_conf_str("dictionary")) != 0)
98 *errptr = string_sprintf("RADIUS: can't read dictionary");
99
100else if (rc_avpair_add(&send, PW_USER_NAME, user, 0) == NULL)
101 *errptr = string_sprintf("RADIUS: add user name failed\n");
102
103else if (rc_avpair_add(&send, PW_USER_PASSWORD, CS radius_args, 0) == NULL)
104 *errptr = string_sprintf("RADIUS: add password failed\n");
105
106else if (rc_avpair_add(&send, PW_SERVICE_TYPE, &service, 0) == NULL)
107 *errptr = string_sprintf("RADIUS: add service type failed\n");
108
109if (*errptr != NULL)
110 {
111 DEBUG(D_auth) debug_printf("%s\n", *errptr);
112 return ERROR;
113 }
114
115result = rc_auth(0, send, &received, msg);
116DEBUG(D_auth) debug_printf("RADIUS code returned %d\n", result);
117
118switch (result)
119 {
120 case OK_RC:
121 return OK;
122
123 case ERROR_RC:
124 return FAIL;
125
126 case TIMEOUT_RC:
127 *errptr = US"RADIUS: timed out";
128 return ERROR;
129
130 default:
131 case BADRESP_RC:
132 *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
133 return ERROR;
134 }
135
136#else /* RADIUS_LIB_RADIUSCLIENT not set => RADIUS_LIB_RADLIB is set */
137
138/* Authenticate using the libradius library */
139
140h = rad_auth_open();
141if (h == NULL)
142 {
143 *errptr = string_sprintf("RADIUS: can't initialise libradius");
144 return ERROR;
145 }
146if (rad_config(h, RADIUS_CONFIG_FILE) != 0 ||
147 rad_create_request(h, RAD_ACCESS_REQUEST) != 0 ||
148 rad_put_string(h, RAD_USER_NAME, CS user) != 0 ||
149 rad_put_string(h, RAD_USER_PASSWORD, CS radius_args) != 0 ||
150 rad_put_int(h, RAD_SERVICE_TYPE, RAD_AUTHENTICATE_ONLY) != 0)
151 {
152 *errptr = string_sprintf("RADIUS: %s", rad_strerror(h));
153 result = ERROR;
154 }
155else
156 {
157 result = rad_send_request(h);
158
159 switch(result)
160 {
161 case RAD_ACCESS_ACCEPT:
162 result = OK;
163 break;
164
165 case RAD_ACCESS_REJECT:
166 result = FAIL;
167 break;
168
169 case -1:
170 *errptr = string_sprintf("RADIUS: %s", rad_strerror(h));
171 result = ERROR;
172 break;
173
174 default:
175 *errptr = string_sprintf("RADIUS: unexpected response (%d)", result);
176 result= ERROR;
177 break;
178 }
179 }
180
181if (*errptr != NULL) DEBUG(D_auth) debug_printf("%s\n", *errptr);
182rad_close(h);
183return result;
184
185#endif /* RADIUS_LIB_RADLIB */
186}
187
188#endif /* RADIUS_CONFIG_FILE */
189
190/* End of call_radius.c */