X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fplugins%2Fradius%2Fradiusclient%2Flib%2Fbuildreq.c;fp=pppd%2Fplugins%2Fradius%2Fradiusclient%2Flib%2Fbuildreq.c;h=507a25c63fce0d869dcfa54ad6e07bea3744af38;hp=0000000000000000000000000000000000000000;hb=d95598c16f6a3feb4846db669601856bad15bb74;hpb=14768a012e45353cde5b60896ccc6b7528d90c69;ds=sidebyside diff --git a/pppd/plugins/radius/radiusclient/lib/buildreq.c b/pppd/plugins/radius/radiusclient/lib/buildreq.c new file mode 100644 index 0000000..507a25c --- /dev/null +++ b/pppd/plugins/radius/radiusclient/lib/buildreq.c @@ -0,0 +1,370 @@ +/* + * $Id: buildreq.c,v 1.1 2002/01/22 16:03:02 dfs Exp $ + * + * Copyright (C) 1995,1997 Lars Fenneberg + * + * See the file COPYRIGHT for the respective terms and conditions. + * If the file is missing contact me at lf@elemental.net + * and I'll send you a copy. + * + */ + +#include +#include +#include + +unsigned char rc_get_seqnbr(void); + +/* + * Function: rc_buildreq + * + * Purpose: builds a skeleton RADIUS request using information from the + * config file. + * + */ + +void rc_buildreq(SEND_DATA *data, int code, char *server, unsigned short port, + int timeout, int retries) +{ + data->server = server; + data->svc_port = port; + data->seq_nbr = rc_get_seqnbr(); + data->timeout = timeout; + data->retries = retries; + data->code = code; +} + +/* + * Function: rc_guess_seqnbr + * + * Purpose: return a random sequence number + * + */ + +static unsigned char rc_guess_seqnbr(void) +{ + srandom((unsigned int)(time(NULL)+getpid())); + return (unsigned char)(random() & UCHAR_MAX); +} + +/* + * Function: rc_get_seqnbr + * + * Purpose: generate a sequence number + * + */ + +unsigned char rc_get_seqnbr(void) +{ + FILE *sf; + int tries = 1; + int seq_nbr; + char *seqfile = rc_conf_str("seqfile"); + + if ((sf = fopen(seqfile, "a+")) == NULL) + { + rc_log(LOG_ERR,"rc_get_seqnbr: couldn't open sequence file %s: %s", seqfile, strerror(errno)); + /* well, so guess a sequence number */ + return rc_guess_seqnbr(); + } + + while (do_lock_exclusive(fileno(sf))!= 0) + { + if (errno != EWOULDBLOCK) { + rc_log(LOG_ERR, "rc_get_seqnbr: flock failure: %s: %s", seqfile, strerror(errno)); + fclose(sf); + return rc_guess_seqnbr(); + } + tries++; + if (tries <= 10) + rc_mdelay(500); + else + break; + } + + if (tries > 10) { + rc_log(LOG_ERR,"rc_get_seqnbr: couldn't get lock after %d tries: %s", tries-1, seqfile); + fclose(sf); + return rc_guess_seqnbr(); + } + + rewind(sf); + if (fscanf(sf, "%d", &seq_nbr) != 1) { + rc_log(LOG_ERR,"rc_get_seqnbr: fscanf failure: %s", seqfile); + seq_nbr = rc_guess_seqnbr(); + } + + rewind(sf); + ftruncate(fileno(sf),0); + fprintf(sf,"%d\n", (seq_nbr+1) & UCHAR_MAX); + + fflush(sf); /* fflush because a process may read it between the do_unlock and fclose */ + + if (do_unlock(fileno(sf)) != 0) + rc_log(LOG_ERR, "rc_get_seqnbr: couldn't release lock on %s: %s", seqfile, strerror(errno)); + + fclose(sf); + + return (unsigned char)seq_nbr; +} + +/* + * Function: rc_auth + * + * Purpose: Builds an authentication request for port id client_port + * with the value_pairs send and submits it to a server + * + * Returns: received value_pairs in received, messages from the server in msg + * and 0 on success, negative on failure as return value + * + */ + +int rc_auth(UINT4 client_port, VALUE_PAIR *send, VALUE_PAIR **received, + char *msg) +{ + SEND_DATA data; + UINT4 client_id; + int result; + int i; + SERVER *authserver = rc_conf_srv("authserver"); + int timeout = rc_conf_int("radius_timeout"); + int retries = rc_conf_int("radius_retries"); + + data.send_pairs = send; + data.receive_pairs = NULL; + + /* + * Fill in NAS-IP-Address + */ + + if ((client_id = rc_own_ipaddress()) == 0) + return (ERROR_RC); + + if (rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0, VENDOR_NONE) == NULL) + return (ERROR_RC); + + /* + * Fill in NAS-Port + */ + + if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL) + return (ERROR_RC); + + result = ERROR_RC; + for(i=0; (imax) && (result != OK_RC) && (result != BADRESP_RC) + ; i++) + { + if (data.receive_pairs != NULL) { + rc_avpair_free(data.receive_pairs); + data.receive_pairs = NULL; + } + rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i], + authserver->port[i], timeout, retries); + + result = rc_send_server (&data, msg); + } + + *received = data.receive_pairs; + + return result; +} + +/* + * Function: rc_auth_proxy + * + * Purpose: Builds an authentication request + * with the value_pairs send and submits it to a server. + * Works for a proxy; does not add IP address, and does + * does not rely on config file. + * + * Returns: received value_pairs in received, messages from the server in msg + * and 0 on success, negative on failure as return value + * + */ + +int rc_auth_proxy(VALUE_PAIR *send, VALUE_PAIR **received, char *msg) +{ + SEND_DATA data; + int result; + int i; + SERVER *authserver = rc_conf_srv("authserver"); + int timeout = rc_conf_int("radius_timeout"); + int retries = rc_conf_int("radius_retries"); + + data.send_pairs = send; + data.receive_pairs = NULL; + + result = ERROR_RC; + for(i=0; (imax) && (result != OK_RC) && (result != BADRESP_RC) + ; i++) + { + if (data.receive_pairs != NULL) { + rc_avpair_free(data.receive_pairs); + data.receive_pairs = NULL; + } + rc_buildreq(&data, PW_ACCESS_REQUEST, authserver->name[i], + authserver->port[i], timeout, retries); + + result = rc_send_server (&data, msg); + } + + *received = data.receive_pairs; + + return result; +} + + +/* + * Function: rc_acct + * + * Purpose: Builds an accounting request for port id client_port + * with the value_pairs send + * + * Remarks: NAS-IP-Address, NAS-Port and Acct-Delay-Time get filled + * in by this function, the rest has to be supplied. + */ + +int rc_acct(UINT4 client_port, VALUE_PAIR *send) +{ + SEND_DATA data; + VALUE_PAIR *adt_vp; + UINT4 client_id; + int result; + time_t start_time, dtime; + char msg[4096]; + int i; + SERVER *acctserver = rc_conf_srv("acctserver"); + int timeout = rc_conf_int("radius_timeout"); + int retries = rc_conf_int("radius_retries"); + + data.send_pairs = send; + data.receive_pairs = NULL; + + /* + * Fill in NAS-IP-Address + */ + + if ((client_id = rc_own_ipaddress()) == 0) + return (ERROR_RC); + + if (rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0, VENDOR_NONE) == NULL) + return (ERROR_RC); + + /* + * Fill in NAS-Port + */ + + if (rc_avpair_add(&(data.send_pairs), PW_NAS_PORT, &client_port, 0, VENDOR_NONE) == NULL) + return (ERROR_RC); + + /* + * Fill in Acct-Delay-Time + */ + + dtime = 0; + if ((adt_vp = rc_avpair_add(&(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, VENDOR_NONE)) == NULL) + return (ERROR_RC); + + start_time = time(NULL); + result = ERROR_RC; + for(i=0; (imax) && (result != OK_RC) && (result != BADRESP_RC) + ; i++) + { + if (data.receive_pairs != NULL) { + rc_avpair_free(data.receive_pairs); + data.receive_pairs = NULL; + } + rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i], + acctserver->port[i], timeout, retries); + + dtime = time(NULL) - start_time; + rc_avpair_assign(adt_vp, &dtime, 0); + + result = rc_send_server (&data, msg); + } + + rc_avpair_free(data.receive_pairs); + + return result; +} + +/* + * Function: rc_acct_proxy + * + * Purpose: Builds an accounting request with the value_pairs send + * + */ + +int rc_acct_proxy(VALUE_PAIR *send) +{ + SEND_DATA data; + int result; + char msg[4096]; + int i; + SERVER *acctserver = rc_conf_srv("authserver"); + int timeout = rc_conf_int("radius_timeout"); + int retries = rc_conf_int("radius_retries"); + + data.send_pairs = send; + data.receive_pairs = NULL; + + result = ERROR_RC; + for(i=0; (imax) && (result != OK_RC) && (result != BADRESP_RC) + ; i++) + { + if (data.receive_pairs != NULL) { + rc_avpair_free(data.receive_pairs); + data.receive_pairs = NULL; + } + rc_buildreq(&data, PW_ACCOUNTING_REQUEST, acctserver->name[i], + acctserver->port[i], timeout, retries); + + result = rc_send_server (&data, msg); + } + + rc_avpair_free(data.receive_pairs); + + return result; +} + +/* + * Function: rc_check + * + * Purpose: ask the server hostname on the specified port for a + * status message + * + */ + +int rc_check(char *host, unsigned short port, char *msg) +{ + SEND_DATA data; + int result; + UINT4 client_id, service_type; + int timeout = rc_conf_int("radius_timeout"); + int retries = rc_conf_int("radius_retries"); + + data.send_pairs = data.receive_pairs = NULL; + + /* + * Fill in NAS-IP-Address, although it isn't neccessary + */ + + if ((client_id = rc_own_ipaddress()) == 0) + return (ERROR_RC); + + rc_avpair_add(&(data.send_pairs), PW_NAS_IP_ADDRESS, &client_id, 0, VENDOR_NONE); + + /* + * Fill in Service-Type + */ + + service_type = PW_ADMINISTRATIVE; + rc_avpair_add(&(data.send_pairs), PW_SERVICE_TYPE, &service_type, 0, VENDOR_NONE); + + rc_buildreq(&data, PW_STATUS_SERVER, host, port, timeout, retries); + result = rc_send_server (&data, msg); + + rc_avpair_free(data.receive_pairs); + + return result; +}