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