Radcli library 2.0.0
A simple radius library -- legacy API reference
Loading...
Searching...
No Matches
buildreq.c
1/*
2 * Copyright (C) 1995,1997 Lars Fenneberg
3 *
4 * See the file COPYRIGHT for the respective terms and conditions.
5 * If the file is missing contact me at lf@elemental.net
6 * and I'll send you a copy.
7 *
8 */
9#include <config.h>
10#include <includes.h>
11#include <radcli/radcli.h>
12#include "util.h"
13#include "rc-random.h"
14#include "options.h"
15
22
38void rc_buildreq(rc_handle const *rh, SEND_DATA * data, int code, char *server,
39 unsigned short port, char *secret, int timeout, int retries)
40{
41 data->server = server;
42 data->secret = secret;
43 data->svc_port = port;
44 data->seq_nbr = rc_get_random_byte();
45 data->timeout = timeout;
46 data->retries = retries;
47 data->code = code;
48}
49
50/*- Select the server list and rc_type for a request, based on transport
51 * and request type. Internal helper shared by rc_aaa_ctx() and
52 * rc_acct_async().
53 *
54 * @param rh a handle to parsed configuration.
55 * @param aaaserver receives the selected SERVER list from configuration.
56 * @param type receives AUTH or ACCT, matching the selected server list.
57 * @param request_type one of the standard RADIUS codes (e.g., PW_ACCESS_REQUEST).
58 * @return OK_RC (0) on success, ERROR_RC if no matching servers are configured.
59 -*/
60static int rc_select_aaa_server(rc_handle *rh, SERVER **aaaserver,
61 rc_type *type, rc_standard_codes request_type)
62{
63 if (rh->so_type == RC_SOCKET_TLS || rh->so_type == RC_SOCKET_DTLS ||
64 request_type != PW_ACCOUNTING_REQUEST) {
65 *aaaserver = rc_conf_srv(rh, "authserver");
66 *type = AUTH;
67 } else {
68 *aaaserver = rc_conf_srv(rh, "acctserver");
69 *type = ACCT;
70 }
71
72 if (*aaaserver == NULL)
73 return ERROR_RC;
74
75 return OK_RC;
76}
77
78/*- Fill in NAS-Port and Acct-Delay-Time on a request being built.
79 * Internal helper shared by rc_aaa_ctx_server() and
80 * rc_aaa_ctx_server_async().
81 *
82 * @param rh a handle to parsed configuration.
83 * @param data the request being built; send_pairs is extended in place.
84 * @param nas_port the physical NAS port number to include (may be zero).
85 * @param add_nas_port if non-zero, PW_NAS_PORT is added to the sent pairs.
86 * @param request_type one of the standard RADIUS codes (e.g., PW_ACCESS_REQUEST).
87 * @param adt_vp receives the Acct-Delay-Time pair when request_type is
88 * PW_ACCOUNTING_REQUEST, so the caller can update it on each retransmission.
89 * @param start_time receives the time the delay is measured from.
90 * @return OK_RC (0) on success, ERROR_RC on failure.
91 -*/
92static int rc_fill_acct_pairs(rc_handle const *rh, SEND_DATA *data,
93 uint32_t nas_port, int add_nas_port,
94 rc_standard_codes request_type,
95 VALUE_PAIR **adt_vp, double *start_time)
96{
97 time_t dtime;
98 double now;
99
100 if (add_nas_port != 0
101 && rc_avpair_get(data->send_pairs, PW_NAS_PORT, 0) == NULL) {
102 /*
103 * Fill in NAS-Port
104 */
105 if (rc_avpair_add(rh, &(data->send_pairs), PW_NAS_PORT,
106 &nas_port, 0, 0) == NULL)
107 return ERROR_RC;
108 }
109
110 if (request_type == PW_ACCOUNTING_REQUEST) {
111 /*
112 * Fill in Acct-Delay-Time
113 */
114 dtime = 0;
115 now = rc_getmtime();
116 *adt_vp = rc_avpair_get(data->send_pairs, PW_ACCT_DELAY_TIME, 0);
117 if (*adt_vp == NULL) {
118 *adt_vp = rc_avpair_add(rh, &(data->send_pairs),
119 PW_ACCT_DELAY_TIME, &dtime, 0,
120 0);
121 if (*adt_vp == NULL)
122 return ERROR_RC;
123 *start_time = now;
124 } else {
125 *start_time = now - (*adt_vp)->lvalue;
126 }
127 }
128
129 return OK_RC;
130}
131
156int rc_aaa_ctx(rc_handle * rh, RC_AAA_CTX ** ctx, uint32_t nas_port,
157 VALUE_PAIR * send, VALUE_PAIR ** received, char *msg,
158 int add_nas_port, rc_standard_codes request_type)
159{
160 SERVER *aaaserver;
161 rc_type type;
162
163 if (rc_select_aaa_server(rh, &aaaserver, &type, request_type) != OK_RC)
164 return ERROR_RC;
165
166 return rc_aaa_ctx_server(rh, ctx, aaaserver, type,
167 nas_port, send, received, msg,
168 add_nas_port, request_type);
169}
170
195int rc_aaa_ctx_server(rc_handle * rh, RC_AAA_CTX ** ctx, SERVER * aaaserver,
196 rc_type type,
197 uint32_t nas_port,
198 VALUE_PAIR * send, VALUE_PAIR ** received,
199 char *msg, int add_nas_port,
200 rc_standard_codes request_type)
201{
202 SEND_DATA data;
203 VALUE_PAIR *adt_vp = NULL;
204 int result;
205 int timeout = rc_conf_int_id(rh, OPT_RADIUS_TIMEOUT);
206 int retries = rc_conf_int_id(rh, OPT_RADIUS_RETRIES);
207 double start_time = 0;
208 time_t dtime;
209 int servernum;
210
211 data.send_pairs = send;
212 data.receive_pairs = NULL;
213
214 if (rc_fill_acct_pairs(rh, &data, nas_port, add_nas_port, request_type,
215 &adt_vp, &start_time) != OK_RC)
216 return ERROR_RC;
217
218 if (data.receive_pairs != NULL) {
220 data.receive_pairs = NULL;
221 }
222
223 servernum = 0;
224 do {
225 rc_buildreq(rh, &data, request_type, aaaserver->name[servernum],
226 aaaserver->port[servernum],
227 aaaserver->secret[servernum], timeout, retries);
228
229 if (request_type == PW_ACCOUNTING_REQUEST) {
230 dtime = rc_getmtime() - start_time;
231 rc_avpair_assign(adt_vp, &dtime, 0);
232 }
233
234 result = rc_send_server_ctx(rh, ctx, &data, msg, type, 0);
235
236 if ((result == OK_RC) || (result == CHALLENGE_RC) || (result == REJECT_RC)) {
237 if (request_type != PW_ACCOUNTING_REQUEST) {
238 *received = data.receive_pairs;
239 } else {
241 }
242
243 DEBUG(rh, LOG_INFO,
244 "rc_send_server_ctx returned success for server %u", servernum);
245 return result;
246 }
247
249 data.receive_pairs = NULL;
250
251 DEBUG(rh, LOG_INFO, "rc_send_server_ctx returned error (%d) for server %u: (remaining: %d)",
252 result, servernum, aaaserver->max-servernum);
253 servernum++;
254 } while (servernum < aaaserver->max && ((result == TIMEOUT_RC) || (result == NETUNREACH_RC)));
255
256 return result;
257}
258
273int rc_aaa(rc_handle * rh, uint32_t nas_port, VALUE_PAIR * send,
274 VALUE_PAIR ** received, char *msg, int add_nas_port,
275 rc_standard_codes request_type)
276{
277 return rc_aaa_ctx(rh, NULL, nas_port, send, received, msg,
278 add_nas_port, request_type);
279}
280
293int rc_auth(rc_handle * rh, uint32_t nas_port, VALUE_PAIR * send,
294 VALUE_PAIR ** received, char *msg)
295{
296
297 return rc_aaa(rh, nas_port, send, received, msg, 1,
298 PW_ACCESS_REQUEST);
299}
300
315int rc_auth_proxy(rc_handle * rh, VALUE_PAIR * send, VALUE_PAIR ** received,
316 char *msg)
317{
318 return rc_aaa(rh, 0, send, received, msg, 0, PW_ACCESS_REQUEST);
319}
320
332int rc_acct(rc_handle * rh, uint32_t nas_port, VALUE_PAIR * send)
333{
334 return rc_aaa(rh, nas_port, send, NULL, NULL, 1,
335 PW_ACCOUNTING_REQUEST);
336}
337
345int rc_acct_proxy(rc_handle * rh, VALUE_PAIR * send)
346{
347
348 return rc_aaa(rh, 0, send, NULL, NULL, 0, PW_ACCOUNTING_REQUEST);
349}
350
351/*- Send an accounting request to every server in aaaserver without
352 * waiting for a reply. Internal helper behind rc_acct_async().
353 *
354 * @param rh a handle to parsed configuration.
355 * @param aaaserver a non-NULL SERVER describing the target server(s).
356 * @param type AUTH or ACCT, selects the destination port.
357 * @param nas_port the physical NAS port number to include (may be zero).
358 * @param send VALUE_PAIR list of attributes to send.
359 * @return OK_RC (0) if the packet was handed to the socket layer for at
360 * least one server, ERROR_RC on failure.
361 -*/
362static int rc_aaa_ctx_server_async(rc_handle * rh, SERVER * aaaserver,
363 rc_type type, uint32_t nas_port,
364 VALUE_PAIR * send)
365{
366 SEND_DATA data;
367 VALUE_PAIR *adt_vp = NULL;
368 double start_time = 0;
369 time_t dtime;
370 int timeout = rc_conf_int_id(rh, OPT_RADIUS_TIMEOUT);
371 int retries = rc_conf_int_id(rh, OPT_RADIUS_RETRIES);
372 int servernum;
373 int result;
374 int sent = 0;
375
376 data.send_pairs = send;
377 data.receive_pairs = NULL;
378
379 if (rc_fill_acct_pairs(rh, &data, nas_port, 1, PW_ACCOUNTING_REQUEST,
380 &adt_vp, &start_time) != OK_RC)
381 return ERROR_RC;
382
383 for (servernum = 0; servernum < aaaserver->max; servernum++) {
384 dtime = rc_getmtime() - start_time;
385 rc_avpair_assign(adt_vp, &dtime, 0);
386
387 /* timeout/retries are not consulted by rc_send_server_ctx()
388 * when no_wait is set below; passed through unchanged only
389 * so SEND_DATA/DEBUG output reflect the real configuration. */
390 rc_buildreq(rh, &data, PW_ACCOUNTING_REQUEST,
391 aaaserver->name[servernum],
392 aaaserver->port[servernum],
393 aaaserver->secret[servernum], timeout, retries);
394
395 result = rc_send_server_ctx(rh, NULL, &data, NULL, type, 1);
396
397 if (data.receive_pairs != NULL) {
399 data.receive_pairs = NULL;
400 }
401
402 if (result == OK_RC) {
403 sent++;
404 } else {
405 DEBUG(rh, LOG_INFO,
406 "rc_send_server_ctx returned error (%d) for server %u",
407 result, servernum);
408 }
409 }
410
411 return sent > 0 ? OK_RC : ERROR_RC;
412}
413
432int rc_acct_async(rc_handle * rh, uint32_t nas_port, VALUE_PAIR * send)
433{
434 SERVER *aaaserver;
435 rc_type type;
436
437 if (rc_select_aaa_server(rh, &aaaserver, &type, PW_ACCOUNTING_REQUEST) != OK_RC)
438 return ERROR_RC;
439
440 return rc_aaa_ctx_server_async(rh, aaaserver, type, nas_port, send);
441}
442
453int rc_check(rc_handle * rh, char *host, char *secret, unsigned short port,
454 char *msg)
455{
456 SEND_DATA data;
457 int result;
458 uint32_t service_type;
459 int timeout = rc_conf_int_id(rh, OPT_RADIUS_TIMEOUT);
460 int retries = rc_conf_int_id(rh, OPT_RADIUS_RETRIES);
461 rc_type type;
462
463 data.send_pairs = data.receive_pairs = NULL;
464
465 if (rh->so_type == RC_SOCKET_TLS || rh->so_type == RC_SOCKET_DTLS)
466 type = AUTH;
467 else
468 type = ACCT;
469
470 /*
471 * Fill in Service-Type
472 */
473
474 service_type = PW_ADMINISTRATIVE;
475 rc_avpair_add(rh, &(data.send_pairs), PW_SERVICE_TYPE, &service_type, 0,
476 0);
477
478 rc_buildreq(rh, &data, PW_STATUS_SERVER, host, port, secret, timeout,
479 retries);
480 result = rc_send_server(rh, &data, msg, type);
481
483
484 return result;
485}
486
int rc_acct(rc_handle *rh, uint32_t nas_port, VALUE_PAIR *send)
Builds an accounting request for port id nas_port with the value_pairs at send.
Definition buildreq.c:332
rc_type
Definition radcli.h:81
int rc_auth_proxy(rc_handle *rh, VALUE_PAIR *send, VALUE_PAIR **received, char *msg)
Builds an authentication request for proxying.
Definition buildreq.c:315
int rc_auth(rc_handle *rh, uint32_t nas_port, VALUE_PAIR *send, VALUE_PAIR **received, char *msg)
Builds an authentication request for port id nas_port with the value_pairs send and submits it to a s...
Definition buildreq.c:293
struct rc_aaa_ctx_st RC_AAA_CTX
Definition radcli.h:295
void rc_buildreq(rc_handle const *rh, SEND_DATA *data, int code, char *server, unsigned short port, char *secret, int timeout, int retries)
Build a skeleton RADIUS request using information from the config file.
Definition buildreq.c:38
int rc_acct_proxy(rc_handle *rh, VALUE_PAIR *send)
Builds an accounting request with the value_pairs at send.
Definition buildreq.c:345
void rc_avpair_free(VALUE_PAIR *pair)
Frees all value_pairs in the list.
Definition avpair.c:569
int rc_aaa_ctx(rc_handle *rh, RC_AAA_CTX **ctx, uint32_t nas_port, VALUE_PAIR *send, VALUE_PAIR **received, char *msg, int add_nas_port, rc_standard_codes request_type)
Builds an authentication/accounting request and submits it to a server, optionally returning context.
Definition buildreq.c:156
int rc_aaa(rc_handle *rh, uint32_t nas_port, VALUE_PAIR *send, VALUE_PAIR **received, char *msg, int add_nas_port, rc_standard_codes request_type)
Builds an authentication/accounting request for port id nas_port with the value_pairs send and submit...
Definition buildreq.c:273
int rc_avpair_assign(VALUE_PAIR *vp, void const *pval, int len)
Assigns the given value to an attribute-value pair.
Definition avpair.c:136
int rc_send_server(rc_handle *rh, SEND_DATA *data, char *msg, rc_type type)
Sends a request to a RADIUS server and waits for the reply.
Definition send.c:238
int rc_acct_async(rc_handle *rh, uint32_t nas_port, VALUE_PAIR *send)
Sends an accounting request to every configured accounting server without waiting for a reply.
Definition buildreq.c:432
int rc_aaa_ctx_server(rc_handle *rh, RC_AAA_CTX **ctx, SERVER *aaaserver, rc_type type, uint32_t nas_port, VALUE_PAIR *send, VALUE_PAIR **received, char *msg, int add_nas_port, rc_standard_codes request_type)
Builds an authentication/accounting request and submits it to a specific server.
Definition buildreq.c:195
int rc_check(rc_handle *rh, char *host, char *secret, unsigned short port, char *msg)
Asks the server hostname on the specified port for a status message.
Definition buildreq.c:453
rc_standard_codes
Definition radcli.h:139
VALUE_PAIR * rc_avpair_add(rc_handle const *rh, VALUE_PAIR **list, uint32_t attrid, void const *pval, int len, uint32_t vendorspec)
Adds an attribute-value pair to the given list.
Definition avpair.c:47
VALUE_PAIR * rc_avpair_get(VALUE_PAIR *vp, uint32_t attrid, uint32_t vendorspec)
Find the first attribute value-pair (which matches the given attribute) from the specified value-pair...
Definition avpair.c:465
@ ACCT
Request for accounting server.
Definition radcli.h:83
@ AUTH
Request for authentication server.
Definition radcli.h:82
@ RC_SOCKET_DTLS
DTLS socket.
Definition radcli.h:115
@ RC_SOCKET_TLS
TLS socket.
Definition radcli.h:114
int timeout
Session timeout in seconds.
Definition radcli.h:277
char * secret
Shared secret of RADIUS server.
Definition radcli.h:276
uint8_t seq_nbr
Packet sequence number.
Definition radcli.h:273
int svc_port
RADIUS protocol destination port.
Definition radcli.h:275
char * server
Name/address of RADIUS server.
Definition radcli.h:274
VALUE_PAIR * send_pairs
More a/v pairs to send.
Definition radcli.h:279
VALUE_PAIR * receive_pairs
Where to place received a/v pairs.
Definition radcli.h:280
uint8_t code
RADIUS packet code.
Definition radcli.h:272