2 * $Id: buildreq.c,v 1.5 2003/04/25 08:10:46 fcusack Exp $
4 * Copyright (C) 1995,1997 Lars Fenneberg
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.
14 #include <radiusclient.h>
16 unsigned char rc_get_seqnbr(void);
19 * Function: rc_get_nas_id
21 * Purpose: fills in NAS-Identifier or NAS-IP-Address in request
25 int rc_get_nas_id(VALUE_PAIR
**sendpairs
)
30 nasid
= rc_conf_str("nas_identifier");
33 * Fill in NAS-Identifier
35 if (rc_avpair_add(sendpairs
, PW_NAS_IDENTIFIER
, nasid
, 0,
43 * Fill in NAS-IP-Address
45 if ((client_id
= rc_own_ipaddress()) == 0)
48 if (rc_avpair_add(sendpairs
, PW_NAS_IP_ADDRESS
, &client_id
,
49 0, VENDOR_NONE
) == NULL
)
57 * Function: rc_buildreq
59 * Purpose: builds a skeleton RADIUS request using information from the
64 void rc_buildreq(SEND_DATA
*data
, int code
, char *server
, unsigned short port
,
65 int timeout
, int retries
)
67 data
->server
= server
;
68 data
->svc_port
= port
;
69 data
->seq_nbr
= rc_get_seqnbr();
70 data
->timeout
= timeout
;
71 data
->retries
= retries
;
76 * Function: rc_guess_seqnbr
78 * Purpose: return a random sequence number
82 static unsigned char rc_guess_seqnbr(void)
84 srandom((unsigned int)(time(NULL
)+getpid()));
85 return (unsigned char)(random() & UCHAR_MAX
);
89 * Function: rc_get_seqnbr
91 * Purpose: generate a sequence number
95 unsigned char rc_get_seqnbr(void)
100 char *seqfile
= rc_conf_str("seqfile");
102 if ((sf
= fopen(seqfile
, "a+")) == NULL
)
104 rc_log(LOG_ERR
,"rc_get_seqnbr: couldn't open sequence file %s: %s", seqfile
, strerror(errno
));
105 /* well, so guess a sequence number */
106 return rc_guess_seqnbr();
109 while (do_lock_exclusive(fileno(sf
))!= 0)
111 if (errno
!= EWOULDBLOCK
) {
112 rc_log(LOG_ERR
, "rc_get_seqnbr: flock failure: %s: %s", seqfile
, strerror(errno
));
114 return rc_guess_seqnbr();
124 rc_log(LOG_ERR
,"rc_get_seqnbr: couldn't get lock after %d tries: %s", tries
-1, seqfile
);
126 return rc_guess_seqnbr();
131 if (fscanf(sf
, "%d", &seq_nbr
) != 1) {
132 if (pos
!= ftell(sf
)) {
133 /* file was not empty */
134 rc_log(LOG_ERR
,"rc_get_seqnbr: fscanf failure: %s", seqfile
);
136 seq_nbr
= rc_guess_seqnbr();
140 ftruncate(fileno(sf
),0);
141 fprintf(sf
,"%d\n", (seq_nbr
+1) & UCHAR_MAX
);
143 fflush(sf
); /* fflush because a process may read it between the do_unlock and fclose */
145 if (do_unlock(fileno(sf
)) != 0)
146 rc_log(LOG_ERR
, "rc_get_seqnbr: couldn't release lock on %s: %s", seqfile
, strerror(errno
));
150 return (unsigned char)seq_nbr
;
156 * Purpose: Builds an authentication request for port id client_port
157 * with the value_pairs send and submits it to a server
159 * Returns: received value_pairs in received, messages from the server in msg
160 * and 0 on success, negative on failure as return value
164 int rc_auth(UINT4 client_port
, VALUE_PAIR
*send
, VALUE_PAIR
**received
,
165 char *msg
, REQUEST_INFO
*info
)
167 SERVER
*authserver
= rc_conf_srv("authserver");
172 return rc_auth_using_server(authserver
, client_port
, send
, received
,
177 * Function: rc_auth_using_server
179 * Purpose: Builds an authentication request for port id client_port
180 * with the value_pairs send and submits it to a server. You
181 * explicitly supply a server list.
183 * Returns: received value_pairs in received, messages from the server in msg
184 * and 0 on success, negative on failure as return value
188 int rc_auth_using_server(SERVER
*authserver
,
191 VALUE_PAIR
**received
,
192 char *msg
, REQUEST_INFO
*info
)
197 int timeout
= rc_conf_int("radius_timeout");
198 int retries
= rc_conf_int("radius_retries");
200 data
.send_pairs
= send
;
201 data
.receive_pairs
= NULL
;
204 * Fill in NAS-IP-Address or NAS-Identifier
207 if (rc_get_nas_id(&(data
.send_pairs
)) == ERROR_RC
)
214 if (rc_avpair_add(&(data
.send_pairs
), PW_NAS_PORT
, &client_port
, 0, VENDOR_NONE
) == NULL
)
218 for(i
=0; (i
<authserver
->max
) && (result
!= OK_RC
) && (result
!= BADRESP_RC
)
221 if (data
.receive_pairs
!= NULL
) {
222 rc_avpair_free(data
.receive_pairs
);
223 data
.receive_pairs
= NULL
;
225 rc_buildreq(&data
, PW_ACCESS_REQUEST
, authserver
->name
[i
],
226 authserver
->port
[i
], timeout
, retries
);
228 result
= rc_send_server (&data
, msg
, info
);
231 *received
= data
.receive_pairs
;
237 * Function: rc_auth_proxy
239 * Purpose: Builds an authentication request
240 * with the value_pairs send and submits it to a server.
241 * Works for a proxy; does not add IP address, and does
242 * does not rely on config file.
244 * Returns: received value_pairs in received, messages from the server in msg
245 * and 0 on success, negative on failure as return value
249 int rc_auth_proxy(VALUE_PAIR
*send
, VALUE_PAIR
**received
, char *msg
)
254 SERVER
*authserver
= rc_conf_srv("authserver");
255 int timeout
= rc_conf_int("radius_timeout");
256 int retries
= rc_conf_int("radius_retries");
258 data
.send_pairs
= send
;
259 data
.receive_pairs
= NULL
;
262 for(i
=0; (i
<authserver
->max
) && (result
!= OK_RC
) && (result
!= BADRESP_RC
)
265 if (data
.receive_pairs
!= NULL
) {
266 rc_avpair_free(data
.receive_pairs
);
267 data
.receive_pairs
= NULL
;
269 rc_buildreq(&data
, PW_ACCESS_REQUEST
, authserver
->name
[i
],
270 authserver
->port
[i
], timeout
, retries
);
272 result
= rc_send_server (&data
, msg
, NULL
);
275 *received
= data
.receive_pairs
;
282 * Function: rc_acct_using_server
284 * Purpose: Builds an accounting request for port id client_port
285 * with the value_pairs send. You explicitly supply server list.
287 * Remarks: NAS-Identifier/NAS-IP-Address, NAS-Port and Acct-Delay-Time get
288 * filled in by this function, the rest has to be supplied.
291 int rc_acct_using_server(SERVER
*acctserver
,
298 time_t start_time
, dtime
;
301 int timeout
= rc_conf_int("radius_timeout");
302 int retries
= rc_conf_int("radius_retries");
304 data
.send_pairs
= send
;
305 data
.receive_pairs
= NULL
;
308 * Fill in NAS-IP-Address or NAS-Identifier
311 if (rc_get_nas_id(&(data
.send_pairs
)) == ERROR_RC
)
318 if (rc_avpair_add(&(data
.send_pairs
), PW_NAS_PORT
, &client_port
, 0, VENDOR_NONE
) == NULL
)
322 * Fill in Acct-Delay-Time
326 if ((adt_vp
= rc_avpair_add(&(data
.send_pairs
), PW_ACCT_DELAY_TIME
, &dtime
, 0, VENDOR_NONE
)) == NULL
)
329 start_time
= time(NULL
);
331 for(i
=0; (i
<acctserver
->max
) && (result
!= OK_RC
) && (result
!= BADRESP_RC
)
334 if (data
.receive_pairs
!= NULL
) {
335 rc_avpair_free(data
.receive_pairs
);
336 data
.receive_pairs
= NULL
;
338 rc_buildreq(&data
, PW_ACCOUNTING_REQUEST
, acctserver
->name
[i
],
339 acctserver
->port
[i
], timeout
, retries
);
341 dtime
= time(NULL
) - start_time
;
342 rc_avpair_assign(adt_vp
, &dtime
, 0);
344 result
= rc_send_server (&data
, msg
, NULL
);
347 rc_avpair_free(data
.receive_pairs
);
355 * Purpose: Builds an accounting request for port id client_port
356 * with the value_pairs send
358 * Remarks: NAS-Identifier/NAS-IP-Address, NAS-Port and Acct-Delay-Time get
359 * filled in by this function, the rest has to be supplied.
362 int rc_acct(UINT4 client_port
, VALUE_PAIR
*send
)
364 SERVER
*acctserver
= rc_conf_srv("acctserver");
365 if (!acctserver
) return (ERROR_RC
);
367 return rc_acct_using_server(acctserver
, client_port
, send
);
371 * Function: rc_acct_proxy
373 * Purpose: Builds an accounting request with the value_pairs send
377 int rc_acct_proxy(VALUE_PAIR
*send
)
383 SERVER
*acctserver
= rc_conf_srv("authserver");
384 int timeout
= rc_conf_int("radius_timeout");
385 int retries
= rc_conf_int("radius_retries");
387 data
.send_pairs
= send
;
388 data
.receive_pairs
= NULL
;
391 for(i
=0; (i
<acctserver
->max
) && (result
!= OK_RC
) && (result
!= BADRESP_RC
)
394 if (data
.receive_pairs
!= NULL
) {
395 rc_avpair_free(data
.receive_pairs
);
396 data
.receive_pairs
= NULL
;
398 rc_buildreq(&data
, PW_ACCOUNTING_REQUEST
, acctserver
->name
[i
],
399 acctserver
->port
[i
], timeout
, retries
);
401 result
= rc_send_server (&data
, msg
, NULL
);
404 rc_avpair_free(data
.receive_pairs
);
412 * Purpose: ask the server hostname on the specified port for a
417 int rc_check(char *host
, unsigned short port
, char *msg
)
422 int timeout
= rc_conf_int("radius_timeout");
423 int retries
= rc_conf_int("radius_retries");
425 data
.send_pairs
= data
.receive_pairs
= NULL
;
428 * Fill in NAS-IP-Address or NAS-Identifier,
429 * although it isn't neccessary
432 if (rc_get_nas_id(&(data
.send_pairs
)) == ERROR_RC
)
436 * Fill in Service-Type
439 service_type
= PW_ADMINISTRATIVE
;
440 rc_avpair_add(&(data
.send_pairs
), PW_SERVICE_TYPE
, &service_type
, 0, VENDOR_NONE
);
442 rc_buildreq(&data
, PW_STATUS_SERVER
, host
, port
, timeout
, retries
);
443 result
= rc_send_server (&data
, msg
, NULL
);
445 rc_avpair_free(data
.receive_pairs
);