1 /*
2 * $Id: buildreq.c,v 1.1 2004/11/14 07:26:26 paulus Exp $
3 *
4 * Copyright (C) 1995,1997 Lars Fenneberg
5 *
6 * See the file COPYRIGHT for the respective terms and conditions.
7 * If the file is missing contact me at lf@elemental.net
8 * and I'll send you a copy.
9 *
10 */
11
12 #include <includes.h>
13 #include <radiusclient.h>
14
15 unsigned char rc_get_seqnbr(void);
16
17 /*
18 * Function: rc_get_nas_id
19 *
20 * Purpose: fills in NAS-Identifier or NAS-IP-Address in request
21 *
22 */
23
rc_get_nas_id(VALUE_PAIR ** sendpairs)24 int rc_get_nas_id(VALUE_PAIR **sendpairs)
25 {
26 UINT4 client_id;
27 char *nasid;
28
29 nasid = rc_conf_str("nas_identifier");
30 if (strlen(nasid)) {
31 /*
32 * Fill in NAS-Identifier
33 */
34 if (rc_avpair_add(sendpairs, PW_NAS_IDENTIFIER, nasid, 0,
35 VENDOR_NONE) == NULL)
36 return (ERROR_RC);
37
38 return (OK_RC);
39
40 } else {
41 /*
42 * Fill in NAS-IP-Address
43 */
44 if ((client_id = rc_own_ipaddress()) == 0)
45 return (ERROR_RC);
46
47 if (rc_avpair_add(sendpairs, PW_NAS_IP_ADDRESS, &client_id,
48 0, VENDOR_NONE) == NULL)
49 return (ERROR_RC);
50 }
51
52 return (OK_RC);
53 }
54
55 /*
56 * Function: rc_buildreq
57 *
58 * Purpose: builds a skeleton RADIUS request using information from the
59 * config file.
60 *
61 */
62
rc_buildreq(SEND_DATA * data,int code,char * server,unsigned short port,int timeout,int retries)63 void rc_buildreq(SEND_DATA *data, int code, char *server, unsigned short port,
64 int timeout, int retries)
65 {
66 data->server = server;
67 data->svc_port = port;
68 data->seq_nbr = rc_get_seqnbr();
69 data->timeout = timeout;
70 data->retries = retries;
71 data->code = code;
72 }
73
74 /*
75 * Function: rc_guess_seqnbr
76 *
77 * Purpose: return a random sequence number
78 *
79 */
80
rc_guess_seqnbr(void)81 static unsigned char rc_guess_seqnbr(void)
82 {
83 return (unsigned char)(magic() & UCHAR_MAX);
84 }
85
86 /*
87 * Function: rc_get_seqnbr
88 *
89 * Purpose: generate a sequence number
90 *
91 */
92
rc_get_seqnbr(void)93 unsigned char rc_get_seqnbr(void)
94 {
95 FILE *sf;
96 int tries = 1;
97 int seq_nbr, pos;
98 char *seqfile = rc_conf_str("seqfile");
99
100 if ((sf = fopen(seqfile, "a+")) == NULL)
101 {
102 error("rc_get_seqnbr: couldn't open sequence file %s: %s", seqfile, strerror(errno));
103 /* well, so guess a sequence number */
104 return rc_guess_seqnbr();
105 }
106
107 while (do_lock_exclusive(fileno(sf))!= 0)
108 {
109 if (errno != EWOULDBLOCK) {
110 error("rc_get_seqnbr: flock failure: %s: %s", seqfile, strerror(errno));
111 fclose(sf);
112 return rc_guess_seqnbr();
113 }
114 tries++;
115 if (tries <= 10)
116 rc_mdelay(500);
117 else
118 break;
119 }
120
121 if (tries > 10) {
122 error("rc_get_seqnbr: couldn't get lock after %d tries: %s", tries-1, seqfile);
123 fclose(sf);
124 return rc_guess_seqnbr();
125 }
126
127 pos = ftell(sf);
128 rewind(sf);
129 if (fscanf(sf, "%d", &seq_nbr) != 1) {
130 if (pos != ftell(sf)) {
131 /* file was not empty */
132 error("rc_get_seqnbr: fscanf failure: %s", seqfile);
133 }
134 seq_nbr = rc_guess_seqnbr();
135 }
136
137 rewind(sf);
138 ftruncate(fileno(sf),0);
139 fprintf(sf,"%d\n", (seq_nbr+1) & UCHAR_MAX);
140
141 fflush(sf); /* fflush because a process may read it between the do_unlock and fclose */
142
143 if (do_unlock(fileno(sf)) != 0)
144 error("rc_get_seqnbr: couldn't release lock on %s: %s", seqfile, strerror(errno));
145
146 fclose(sf);
147
148 return (unsigned char)seq_nbr;
149 }
150
151 /*
152 * Function: rc_auth
153 *
154 * Purpose: Builds an authentication request for port id client_port
155 * with the value_pairs send and submits it to a server
156 *
157 * Returns: received value_pairs in received, messages from the server in msg
158 * and 0 on success, negative on failure as return value
159 *
160 */
161
rc_auth(UINT4 client_port,VALUE_PAIR * send,VALUE_PAIR ** received,char * msg,REQUEST_INFO * info)162 int rc_auth(UINT4 client_port, VALUE_PAIR *send, VALUE_PAIR **received,
163 char *msg, REQUEST_INFO *info)
164 {
165 SERVER *authserver = rc_conf_srv("authserver");
166
167 if (!authserver) {
168 return (ERROR_RC);
169 }
170 return rc_auth_using_server(authserver, client_port, send, received,
171 msg, info);
172 }
173
174 /*
175 * Function: rc_auth_using_server
176 *
177 * Purpose: Builds an authentication request for port id client_port
178 * with the value_pairs send and submits it to a server. You
179 * explicitly supply a server list.
180 *
181 * Returns: received value_pairs in received, messages from the server in msg
182 * and 0 on success, negative on failure as return value
183 *
184 */
185
rc_auth_using_server(SERVER * authserver,UINT4 client_port,VALUE_PAIR * send,VALUE_PAIR ** received,char * msg,REQUEST_INFO * info)186 int rc_auth_using_server(SERVER *authserver,
187 UINT4 client_port,
188 VALUE_PAIR *send,
189 VALUE_PAIR **received,
190 char *msg, REQUEST_INFO *info)
191 {
192 SEND_DATA data;
193 int result;
194 int i;
195 int timeout = rc_conf_int("radius_timeout");
196 int retries = rc_conf_int("radius_retries");
197
198 data.send_pairs = send;
199 data.receive_pairs = NULL;
200
201 /*
202 * Fill in NAS-IP-Address or NAS-Identifier
203 */
204
205 if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC)
206 return (ERROR_RC);
207
208 /*
209 * Fill in NAS-Port
210 */
211
212 if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL)
213 return (ERROR_RC);
214
215 result = ERROR_RC;
216 for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC)
217 ; i++)
218 {
219 if (data.receive_pairs != NULL) {
220 rc_avpair_free(data.receive_pairs);
221 data.receive_pairs = NULL;
222 }
223 rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i],
224 authserver->port[i], timeout, retries);
225
226 result = rc_send_server (&data, msg, info);
227 }
228
229 *received = data.receive_pairs;
230
231 return result;
232 }
233
234 /*
235 * Function: rc_auth_proxy
236 *
237 * Purpose: Builds an authentication request
238 * with the value_pairs send and submits it to a server.
239 * Works for a proxy; does not add IP address, and does
240 * does not rely on config file.
241 *
242 * Returns: received value_pairs in received, messages from the server in msg
243 * and 0 on success, negative on failure as return value
244 *
245 */
246
rc_auth_proxy(VALUE_PAIR * send,VALUE_PAIR ** received,char * msg)247 int rc_auth_proxy(VALUE_PAIR *send, VALUE_PAIR **received, char *msg)
248 {
249 SEND_DATA data;
250 int result;
251 int i;
252 SERVER *authserver = rc_conf_srv("authserver");
253 int timeout = rc_conf_int("radius_timeout");
254 int retries = rc_conf_int("radius_retries");
255
256 data.send_pairs = send;
257 data.receive_pairs = NULL;
258
259 result = ERROR_RC;
260 for(i=0; (i<authserver->max) && (result != OK_RC) && (result != BADRESP_RC)
261 ; i++)
262 {
263 if (data.receive_pairs != NULL) {
264 rc_avpair_free(data.receive_pairs);
265 data.receive_pairs = NULL;
266 }
267 rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i],
268 authserver->port[i], timeout, retries);
269
270 result = rc_send_server (&data, msg, NULL);
271 }
272
273 *received = data.receive_pairs;
274
275 return result;
276 }
277
278
279 /*
280 * Function: rc_acct_using_server
281 *
282 * Purpose: Builds an accounting request for port id client_port
283 * with the value_pairs send. You explicitly supply server list.
284 *
285 * Remarks: NAS-Identifier/NAS-IP-Address, NAS-Port and Acct-Delay-Time get
286 * filled in by this function, the rest has to be supplied.
287 */
288
rc_acct_using_server(SERVER * acctserver,UINT4 client_port,VALUE_PAIR * send)289 int rc_acct_using_server(SERVER *acctserver,
290 UINT4 client_port,
291 VALUE_PAIR *send)
292 {
293 SEND_DATA data;
294 VALUE_PAIR *adt_vp;
295 int result;
296 time_t start_time, dtime;
297 char msg[4096];
298 int i;
299 int timeout = rc_conf_int("radius_timeout");
300 int retries = rc_conf_int("radius_retries");
301
302 data.send_pairs = send;
303 data.receive_pairs = NULL;
304
305 /*
306 * Fill in NAS-IP-Address or NAS-Identifier
307 */
308
309 if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC)
310 return (ERROR_RC);
311
312 /*
313 * Fill in NAS-Port
314 */
315
316 if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL)
317 return (ERROR_RC);
318
319 /*
320 * Fill in Acct-Delay-Time
321 */
322
323 dtime = 0;
324 if ((adt_vp = rc_avpair_add(&(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, VENDOR_NONE)) == NULL)
325 return (ERROR_RC);
326
327 start_time = time(NULL);
328 result = ERROR_RC;
329 for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
330 ; i++)
331 {
332 if (data.receive_pairs != NULL) {
333 rc_avpair_free(data.receive_pairs);
334 data.receive_pairs = NULL;
335 }
336 rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
337 acctserver->port[i], timeout, retries);
338
339 dtime = time(NULL) - start_time;
340 rc_avpair_assign(adt_vp, &dtime, 0);
341
342 result = rc_send_server (&data, msg, NULL);
343 }
344
345 rc_avpair_free(data.receive_pairs);
346
347 return result;
348 }
349
350 /*
351 * Function: rc_acct
352 *
353 * Purpose: Builds an accounting request for port id client_port
354 * with the value_pairs send
355 *
356 * Remarks: NAS-Identifier/NAS-IP-Address, NAS-Port and Acct-Delay-Time get
357 * filled in by this function, the rest has to be supplied.
358 */
359
rc_acct(UINT4 client_port,VALUE_PAIR * send)360 int rc_acct(UINT4 client_port, VALUE_PAIR *send)
361 {
362 SERVER *acctserver = rc_conf_srv("acctserver");
363 if (!acctserver) return (ERROR_RC);
364
365 return rc_acct_using_server(acctserver, client_port, send);
366 }
367
368 /*
369 * Function: rc_acct_proxy
370 *
371 * Purpose: Builds an accounting request with the value_pairs send
372 *
373 */
374
rc_acct_proxy(VALUE_PAIR * send)375 int rc_acct_proxy(VALUE_PAIR *send)
376 {
377 SEND_DATA data;
378 int result;
379 char msg[4096];
380 int i;
381 SERVER *acctserver = rc_conf_srv("authserver");
382 int timeout = rc_conf_int("radius_timeout");
383 int retries = rc_conf_int("radius_retries");
384
385 data.send_pairs = send;
386 data.receive_pairs = NULL;
387
388 result = ERROR_RC;
389 for(i=0; (i<acctserver->max) && (result != OK_RC) && (result != BADRESP_RC)
390 ; i++)
391 {
392 if (data.receive_pairs != NULL) {
393 rc_avpair_free(data.receive_pairs);
394 data.receive_pairs = NULL;
395 }
396 rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i],
397 acctserver->port[i], timeout, retries);
398
399 result = rc_send_server (&data, msg, NULL);
400 }
401
402 rc_avpair_free(data.receive_pairs);
403
404 return result;
405 }
406
407 /*
408 * Function: rc_check
409 *
410 * Purpose: ask the server hostname on the specified port for a
411 * status message
412 *
413 */
414
rc_check(char * host,unsigned short port,char * msg)415 int rc_check(char *host, unsigned short port, char *msg)
416 {
417 SEND_DATA data;
418 int result;
419 UINT4 service_type;
420 int timeout = rc_conf_int("radius_timeout");
421 int retries = rc_conf_int("radius_retries");
422
423 data.send_pairs = data.receive_pairs = NULL;
424
425 /*
426 * Fill in NAS-IP-Address or NAS-Identifier,
427 * although it isn't neccessary
428 */
429
430 if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC)
431 return (ERROR_RC);
432
433 /*
434 * Fill in Service-Type
435 */
436
437 service_type = PW_ADMINISTRATIVE;
438 rc_avpair_add(&(data.send_pairs), PW_SERVICE_TYPE, &service_type, 0, VENDOR_NONE);
439
440 rc_buildreq(&data, PW_STATUS_SERVER, host, port, timeout, retries);
441 result = rc_send_server (&data, msg, NULL);
442
443 rc_avpair_free(data.receive_pairs);
444
445 return result;
446 }
447