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; (i<acctserver->max) && (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, NULL); } rc_avpair_free(data.receive_pairs); return result; }
int rc_check(char *host, unsigned short port, char *msg) { SEND_DATA data; int result; UINT4 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 or NAS-Identifier, * although it isn't neccessary */ if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC) return (ERROR_RC); /* * 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, NULL); rc_avpair_free(data.receive_pairs); return result; }
/** Asks the server hostname on the specified port for a status message * * @param rh a handle to parsed configuration. * @param host the name of the server. * @param secret the secret used by the server. * @param port the server's port number. * @param msg must be an array of PW_MAX_MSG_SIZE or NULL; will contain the concatenation of any * PW_REPLY_MESSAGE received. * @return OK_RC (0) on success, negative on failure as return value. */ int rc_check(rc_handle *rh, char *host, char *secret, unsigned short port, char *msg) { SEND_DATA data; int result; uint32_t service_type; int timeout = rc_conf_int(rh, "radius_timeout"); int retries = rc_conf_int(rh, "radius_retries"); rc_type type; data.send_pairs = data.receive_pairs = NULL; if (rh->so_type == RC_SOCKET_TLS || rh->so_type == RC_SOCKET_DTLS) type = AUTH; else type = ACCT; /* * Fill in Service-Type */ service_type = PW_ADMINISTRATIVE; rc_avpair_add(rh, &(data.send_pairs), PW_SERVICE_TYPE, &service_type, 0, 0); rc_buildreq(rh, &data, PW_STATUS_SERVER, host, port, secret, timeout, retries); result = rc_send_server (rh, &data, msg, type); rc_avpair_free(data.receive_pairs); return result; }
int rc_acct_using_server(SERVER *acctserver, UINT4 client_port, VALUE_PAIR *send) { SEND_DATA data; VALUE_PAIR *adt_vp; int result; time_t start_time, dtime; char msg[4096]; int i; 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 or NAS-Identifier */ if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC) 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; (i<acctserver->max) && (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, NULL); } rc_avpair_free(data.receive_pairs); return result; }
static RETSIGTYPE alarm_handler(int sn) { fprintf(stderr, SC_TIMEOUT, rc_conf_int("login_timeout")); sleep(1); exit(ERROR_RC); }
int rc_auth_using_server(SERVER *authserver, UINT4 client_port, VALUE_PAIR *send, VALUE_PAIR **received, char *msg, REQUEST_INFO *info) { SEND_DATA data; int result; int i; 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 or NAS-Identifier */ if (rc_get_nas_id(&(data.send_pairs)) == ERROR_RC) 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; (i<authserver->max) && (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, info); } *received = data.receive_pairs; return result; }
/** Tests the configuration the user supplied * * @param rh a handle to parsed configuration. * @param filename a name of a configuration file. * @return 0 on success, -1 when failure. */ int rc_test_config(rc_handle *rh, char const *filename) { SERVER *srv; srv = rc_conf_srv(rh, "authserver"); if (!srv || !srv->max) { rc_log(LOG_ERR,"%s: no authserver specified", filename); return -1; } srv = rc_conf_srv(rh, "acctserver"); if (!srv || !srv->max) { /* it is allowed not to have acct servers */ if (rh->so_type != RC_SOCKET_TLS && rh->so_type != RC_SOCKET_DTLS) rc_log(LOG_DEBUG,"%s: no acctserver specified", filename); } if (!rc_conf_str(rh, "dictionary")) { rc_log(LOG_ERR,"%s: no dictionary specified", filename); return -1; } if (rc_conf_int(rh, "radius_timeout") <= 0) { rc_log(LOG_ERR,"%s: radius_timeout <= 0 is illegal", filename); return -1; } if (rc_conf_int(rh, "radius_retries") <= 0) { rc_log(LOG_ERR,"%s: radius_retries <= 0 is illegal", filename); return -1; } if (apply_config(rh) == -1) { return -1; } return 0; }
int main (int argc, char **argv) { char username[128]; char passwd[AUTH_PASS_LEN + 1]; int tries, remaining, c; UINT4 client_port; void (*login_func)(char *); FILE *fp; char buf[4096]; char tty[1024], *p; int noissue = 0; int maxtries = 0; char *ttyn = NULL; char *path_radiusclient_conf = RC_CONFIG_FILE; extern char *optarg; extern int optind; pname = (pname = strrchr(argv[0],'/'))?pname+1:argv[0]; rc_openlog(pname); while ((c = getopt(argc,argv,"f:m:i:nhV")) > 0) { switch(c) { case 'f': path_radiusclient_conf = optarg; break; case 'i': ttyn = optarg; break; case 'n': noissue = 1; break; case 'm': maxtries = atoi(optarg); break; case 'V': version(); break; case 'h': usage(); break; default: exit(ERROR_RC); break; } } if (rc_read_config(path_radiusclient_conf) != 0) exit(ERROR_RC); if (rc_read_dictionary(rc_conf_str("dictionary")) != 0) exit (ERROR_RC); if (rc_read_mapfile(rc_conf_str("mapfile")) != 0) exit (ERROR_RC); if (ttyn != NULL) { client_port = rc_map2id(ttyn); if ((p = strrchr(ttyn, '/')) == NULL) strncpy(tty, ttyn, sizeof(tty)); else strncpy(tty, p+1, sizeof(tty)); } else { ttyn = ttyname(0); if (ttyn) { if ((p = strrchr(ttyn, '/')) == NULL) strncpy(tty, ttyn, sizeof(tty)); else strncpy(tty, p+1, sizeof(tty)); client_port = rc_map2id(ttyn); } else { *tty = '\0'; client_port = 0; } } #ifdef SETVBUF_REVERSED setvbuf(stdout, _IONBF, NULL, 0); #else setvbuf(stdout, NULL, _IONBF, 0); #endif if ((argc - optind) == 1) { strncpy(username,argv[optind], sizeof(username)); } else { *username = '******'; if (!noissue) { if (rc_conf_str("issue") && ((fp = fopen(rc_conf_str("issue"), "r")) != NULL)) { while (fgets(buf, sizeof(buf), fp) != NULL) fputs(subst_placeholders(buf, tty), stdout); fflush(stdout); fclose(fp); } else { fputs(subst_placeholders(SC_DEFAULT_ISSUE, tty), stdout); fflush(stdout); } } } if ((env = rc_new_env(ENV_SIZE)) == NULL) { rc_log(LOG_CRIT, "rc_new_env: FATAL: out of memory"); abort(); } #ifdef SECURITY_DISABLED if (rc_import_env(env,environ) < 0) { rc_log(LOG_CRIT, "rc_import_env: FATAL: not enough space for environment (increase ENV_SIZE)"); abort(); } #else rc_add_env(env, "IFS", " "); rc_add_env(env, "PATH", RC_SECURE_PATH); #endif signal(SIGALRM, alarm_handler); remaining = rc_conf_int("login_timeout"); if (!maxtries) maxtries = rc_conf_int("login_tries"); tries = 1; while (tries <= maxtries) { alarm(remaining); while (!*username) { p = rc_getstr (SC_LOGIN, 1); if (p) strncpy(username, p, sizeof(username)); else exit (ERROR_RC); } p = rc_getstr(SC_PASSWORD,0); if (p) strncpy (passwd, p, sizeof (passwd)); else exit (ERROR_RC); remaining = alarm(0); login_func = NULL; if (rc_conf_int("auth_order") & AUTH_LOCAL_FST) { login_func = auth_local(username, passwd); if (!login_func) if (rc_conf_int("auth_order") & AUTH_RADIUS_SND) login_func = auth_radius(client_port, username, passwd); } else { login_func = auth_radius(client_port, username, passwd); if (!login_func) if (rc_conf_int("auth_order") & AUTH_LOCAL_SND) login_func = auth_local(username, passwd); } memset(passwd, '\0', sizeof(passwd)); if (login_func != NULL) if (login_allowed(tty)) { (*login_func)(username); } else { sleep(1); exit (ERROR_RC); } *username = '******'; if ((++tries) <= maxtries) { alarm(remaining); sleep(tries * 2); remaining = alarm(0); } } fprintf(stderr, SC_EXCEEDED); sleep(1); exit (ERROR_RC); }
static int test_config(char *filename) { #if 0 struct stat st; char *file; #endif if (!(rc_conf_srv("authserver")->max)) { errorlog("%s: no authserver specified", filename); return (-1); } if (!(rc_conf_srv("acctserver")->max)) { errorlog("%s: no acctserver specified", filename); return (-1); } if (!rc_conf_str("servers")) { errorlog("%s: no servers file specified", filename); return (-1); } if (!rc_conf_str("dictionary")) { errorlog("%s: no dictionary specified", filename); return (-1); } if (rc_conf_int("radius_timeout") <= 0) { errorlog("%s: radius_timeout <= 0 is illegal", filename); return (-1); } if (rc_conf_int("radius_retries") <= 0) { errorlog("%s: radius_retries <= 0 is illegal", filename); return (-1); } #if 0 file = rc_conf_str("login_local"); if (stat(file, &st) == 0) { if (!S_ISREG(st.st_mode)) { errorlog("%s: not a regular file: %s", filename, file); return (-1); } } else { errorlog("%s: file not found: %s", filename, file); return (-1); } file = rc_conf_str("login_radius"); if (stat(file, &st) == 0) { if (!S_ISREG(st.st_mode)) { errorlog("%s: not a regular file: %s", filename, file); return (-1); } } else { errorlog("%s: file not found: %s", filename, file); return (-1); } #endif if (rc_conf_int("login_tries") <= 0) { errorlog("%s: login_tries <= 0 is illegal", filename); return (-1); } if (rc_conf_str("seqfile") == NULL) { errorlog("%s: seqfile not specified", filename); return (-1); } if (rc_conf_int("login_timeout") <= 0) { errorlog("%s: login_timeout <= 0 is illegal", filename); return (-1); } if (rc_conf_str("mapfile") == NULL) { errorlog("%s: mapfile not specified", filename); return (-1); } if (rc_conf_str("nologin") == NULL) { errorlog("%s: nologin not specified", filename); return (-1); } return 0; }
/** Builds an authentication/accounting request for port id client_port with the value_pairs send and submits it to a server * * @param rh a handle to parsed configuration. * @param client_port the client port number to use (may be zero to use any available). * @param send a #VALUE_PAIR array of values (e.g., %PW_USER_NAME). * @param received an allocated array of received values. * @param msg must be an array of %PW_MAX_MSG_SIZE or %NULL; will contain the concatenation of any * %PW_REPLY_MESSAGE received. * @param add_nas_port if non-zero it will include %PW_NAS_PORT in sent pairs. * @param request_type one of standard RADIUS codes (e.g., %PW_ACCESS_REQUEST). * @return received value_pairs in received, messages from the server in msg and %OK_RC (0) on success, negative * on failure as return value. */ int rc_aaa(rc_handle *rh, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received, char *msg, int add_nas_port, int request_type) { SEND_DATA data; VALUE_PAIR *adt_vp = NULL; int result; int i, skip_count; SERVER *aaaserver; int timeout = rc_conf_int(rh, "radius_timeout"); int retries = rc_conf_int(rh, "radius_retries"); int radius_deadtime = rc_conf_int(rh, "radius_deadtime"); double start_time = 0; double now = 0; time_t dtime; unsigned type; if (request_type != PW_ACCOUNTING_REQUEST) { aaaserver = rc_conf_srv(rh, "authserver"); type = AUTH; } else { aaaserver = rc_conf_srv(rh, "acctserver"); type = ACCT; } if (aaaserver == NULL) return ERROR_RC; data.send_pairs = send; data.receive_pairs = NULL; if (add_nas_port != 0) { /* * Fill in NAS-Port */ if (rc_avpair_add(rh, &(data.send_pairs), PW_NAS_PORT, &client_port, 0, 0) == NULL) return ERROR_RC; } if (request_type == PW_ACCOUNTING_REQUEST) { /* * Fill in Acct-Delay-Time */ dtime = 0; now = rc_getctime(); adt_vp = rc_avpair_get(data.send_pairs, PW_ACCT_DELAY_TIME, 0); if (adt_vp == NULL) { adt_vp = rc_avpair_add(rh, &(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, 0); if (adt_vp == NULL) return ERROR_RC; start_time = now; } else { start_time = now - adt_vp->lvalue; } } skip_count = 0; result = ERROR_RC; for (i=0; (i < aaaserver->max) && (result != OK_RC) && (result != REJECT_RC) ; i++, now = rc_getctime()) { if (aaaserver->deadtime_ends[i] != -1 && aaaserver->deadtime_ends[i] > start_time) { skip_count++; continue; } if (data.receive_pairs != NULL) { rc_avpair_free(data.receive_pairs); data.receive_pairs = NULL; } rc_buildreq(rh, &data, request_type, aaaserver->name[i], aaaserver->port[i], aaaserver->secret[i], timeout, retries); if (request_type == PW_ACCOUNTING_REQUEST) { dtime = now - start_time; rc_avpair_assign(adt_vp, &dtime, 0); } result = rc_send_server (rh, &data, msg, type); if (result == TIMEOUT_RC && radius_deadtime > 0) aaaserver->deadtime_ends[i] = start_time + (double)radius_deadtime; } if (result == OK_RC || result == REJECT_RC || skip_count == 0) goto exit; result = ERROR_RC; for (i=0; (i < aaaserver->max) && (result != OK_RC) && (result != REJECT_RC) ; i++) { if (aaaserver->deadtime_ends[i] == -1 || aaaserver->deadtime_ends[i] <= start_time) { continue; } if (data.receive_pairs != NULL) { rc_avpair_free(data.receive_pairs); data.receive_pairs = NULL; } rc_buildreq(rh, &data, request_type, aaaserver->name[i], aaaserver->port[i], aaaserver->secret[i], timeout, retries); if (request_type == PW_ACCOUNTING_REQUEST) { dtime = rc_getctime() - start_time; rc_avpair_assign(adt_vp, &dtime, 0); } result = rc_send_server (rh, &data, msg, type); if (result != TIMEOUT_RC) aaaserver->deadtime_ends[i] = -1; } exit: if (request_type != PW_ACCOUNTING_REQUEST) { *received = data.receive_pairs; } else { rc_avpair_free(data.receive_pairs); } return result; }
int test_config(rc_handle *rh, const char *filename) { #if 0 struct stat st; char *file; #endif if (!(rc_conf_srv(rh, "authserver")->max)) { rc_log(LOG_ERR,"%s: no authserver specified", filename); return -1; } if (!(rc_conf_srv(rh, "acctserver")->max)) { rc_log(LOG_ERR,"%s: no acctserver specified", filename); return -1; } if (!rc_conf_str(rh, "servers")) { rc_log(LOG_ERR,"%s: no servers file specified", filename); return -1; } if (!rc_conf_str(rh, "dictionary")) { rc_log(LOG_ERR,"%s: no dictionary specified", filename); return -1; } if (rc_conf_int(rh, "radius_timeout") <= 0) { rc_log(LOG_ERR,"%s: radius_timeout <= 0 is illegal", filename); return -1; } if (rc_conf_int(rh, "radius_retries") <= 0) { rc_log(LOG_ERR,"%s: radius_retries <= 0 is illegal", filename); return -1; } if (rc_conf_int(rh, "radius_deadtime") < 0) { rc_log(LOG_ERR,"%s: radius_deadtime is illegal", filename); return -1; } #if 0 file = rc_conf_str(rh, "login_local"); if (stat(file, &st) == 0) { if (!S_ISREG(st.st_mode)) { rc_log(LOG_ERR,"%s: not a regular file: %s", filename, file); return -1; } } else { rc_log(LOG_ERR,"%s: file not found: %s", filename, file); return -1; } file = rc_conf_str(rh, "login_radius"); if (stat(file, &st) == 0) { if (!S_ISREG(st.st_mode)) { rc_log(LOG_ERR,"%s: not a regular file: %s", filename, file); return -1; } } else { rc_log(LOG_ERR,"%s: file not found: %s", filename, file); return -1; } #endif if (rc_conf_int(rh, "login_tries") <= 0) { rc_log(LOG_ERR,"%s: login_tries <= 0 is illegal", filename); return -1; } if (rc_conf_str(rh, "seqfile") == NULL) { rc_log(LOG_ERR,"%s: seqfile not specified", filename); return -1; } if (rc_conf_int(rh, "login_timeout") <= 0) { rc_log(LOG_ERR,"%s: login_timeout <= 0 is illegal", filename); return -1; } if (rc_conf_str(rh, "mapfile") == NULL) { rc_log(LOG_ERR,"%s: mapfile not specified", filename); return -1; } if (rc_conf_str(rh, "nologin") == NULL) { rc_log(LOG_ERR,"%s: nologin not specified", filename); return -1; } return 0; }
//int rc_aaa(rc_handle *rh, char *host, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received, char *msg, int add_nas_port, int request_type) int rc_aaa(rc_handle *rh, const string & host, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received, char *msg, int add_nas_port, int request_type) { fprintf(stdout, "rc_aaa::Start\n"); SEND_DATA data; VALUE_PAIR *adt_vp; int result; int i, skip_count; SERVER aaaserver; int timeout = rc_conf_int(rh, "radius_timeout"); int retries = rc_conf_int(rh, "radius_retries"); int radius_deadtime = rc_conf_int(rh, "radius_deadtime"); double start_time; time_t dtime; if (request_type != PW_ACCOUNTING_REQUEST) { // aaaserver = rc_conf_srv(rh, "authserver"); // fprintf(stdout, "rc_aaa::authserver\n"); // rc_conf_srv(rh, "authserver", &aaaserver); // aaaserver.name = host; } else { // aaaserver = rc_conf_srv(rh, "acctserver"); // fprintf(stdout, "rc_aaa::acctserver\n"); } // char srvName[15] = "192.168.10.102"; // strcpy(srvName ,aaaserver.name); // fprintf(stdout, "srvName: %s\n", srvName); // fprintf(stdout, "aaaserver.name: %s\n", aaaserver.name); /* if (aaaserver == NULL) { return ERROR_RC; } */ if( !host.empty() ) { aaaserver.name = host; } data.send_pairs = send; data.receive_pairs = NULL; if (add_nas_port != 0) { /* * Fill in NAS-Port */ if (rc_avpair_add(rh, &(data.send_pairs), PW_NAS_PORT, &client_port, 0, 0) == NULL) return ERROR_RC; } if (request_type == PW_ACCOUNTING_REQUEST) { /* * Fill in Acct-Delay-Time */ dtime = 0; if ((adt_vp = rc_avpair_add(rh, &(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, 0)) == NULL) return ERROR_RC; } start_time = rc_getctime(); skip_count = 0; result = ERROR_RC; // fprintf(stdout, "rc_aaa::aaaserver.max %d\n", aaaserver.max); aaaserver.max = 1; for (i=0; (i < aaaserver.max) && (result != OK_RC) && (result != BADRESP_RC); i++) { if (aaaserver.deadtime_ends != -1 && aaaserver.deadtime_ends > start_time) { skip_count++; continue; } if (data.receive_pairs != NULL) { rc_avpair_free(data.receive_pairs); data.receive_pairs = NULL; } rc_buildreq(rh, &data, request_type, aaaserver.name.c_str(), aaaserver.port, aaaserver.secret.c_str(), timeout, retries); fprintf(stdout, "rc_buildreq: data.server: %s\n", data.server.c_str()); fprintf(stdout, "rc_buildreq: data.secret: %s\n", data.secret.c_str()); fprintf(stdout, "rc_buildreq: data.svc_port: %i\n", data.svc_port); // fprintf(stdout, "aaaserver.name %s, port: %s, secert %s\n", aaaserver.name[i], aaaserver.port[i], aaaserver.secret[i]); if (request_type == PW_ACCOUNTING_REQUEST) { dtime = rc_getctime() - start_time; rc_avpair_assign(adt_vp, &dtime, 0); } result = rc_send_server (rh, &data, msg); if (result == TIMEOUT_RC && radius_deadtime > 0) aaaserver.deadtime_ends = start_time + (double)radius_deadtime; } if (result == OK_RC || result == BADRESP_RC || skip_count == 0) goto exit; result = ERROR_RC; for (i=0; (i < aaaserver.max) && (result != OK_RC) && (result != BADRESP_RC) ; i++) { if (aaaserver.deadtime_ends == -1 || aaaserver.deadtime_ends <= start_time) { continue; } if (data.receive_pairs != NULL) { rc_avpair_free(data.receive_pairs); data.receive_pairs = NULL; } rc_buildreq(rh, &data, request_type, aaaserver.name.c_str(), aaaserver.port, aaaserver.secret.c_str(), timeout, retries); if (request_type == PW_ACCOUNTING_REQUEST) { dtime = rc_getctime() - start_time; rc_avpair_assign(adt_vp, &dtime, 0); } fprintf(stdout, "rc_aaa::rc_send_server Start\n"); result = rc_send_server (rh, &data, msg); fprintf(stdout, "rc_aaa::rc_send_server End\n"); if (result != TIMEOUT_RC) aaaserver.deadtime_ends = -1; } exit: if (request_type != PW_ACCOUNTING_REQUEST) { *received = data.receive_pairs; } else { rc_avpair_free(data.receive_pairs); } printf("rc_aaa return: %d\n", result); return result; }
/** Builds an authentication/accounting request for port id client_port with the value_pairs send and submits it to a specified server. * This function keeps its state in ctx after a successful operation. It can be deallocated using * rc_aaa_ctx_free(). * * @param rh a handle to parsed configuration. * @param ctx if non-NULL it will contain the context of the request; Its initial value should be NULL and it must be released using rc_aaa_ctx_free(). * @param aaaserver a non-NULL SERVER to send the message to. * @param client_port the client port number to use (may be zero to use any available). * @param send a VALUE_PAIR array of values (e.g., PW_USER_NAME). * @param received an allocated array of received values. * @param msg must be an array of PW_MAX_MSG_SIZE or NULL; will contain the concatenation of any * PW_REPLY_MESSAGE received. * @param add_nas_port if non-zero it will include PW_NAS_PORT in sent pairs. * @param request_type one of standard RADIUS codes (e.g., PW_ACCESS_REQUEST). * @return received value_pairs in received, messages from the server in msg and OK_RC (0) on success, negative * on failure as return value. */ int rc_aaa_ctx_server(rc_handle *rh, RC_AAA_CTX **ctx, SERVER *aaaserver, rc_type type, uint32_t client_port, VALUE_PAIR *send, VALUE_PAIR **received, char *msg, int add_nas_port, rc_standard_codes request_type) { SEND_DATA data; VALUE_PAIR *adt_vp = NULL; int result; int timeout = rc_conf_int(rh, "radius_timeout"); int retries = rc_conf_int(rh, "radius_retries"); double start_time = 0; double now = 0; time_t dtime; int servernum; data.send_pairs = send; data.receive_pairs = NULL; /* * if there is more than zero servers, then divide waiting time * among all the servers. */ if(aaaserver->max > 0) { if(timeout > 0) { timeout = (timeout+1) / aaaserver->max; } if(retries > 0) { retries = (retries+1) / aaaserver->max; } } if (add_nas_port != 0 && rc_avpair_get(data.send_pairs, PW_NAS_PORT, 0) == NULL) { /* * Fill in NAS-Port */ if (rc_avpair_add(rh, &(data.send_pairs), PW_NAS_PORT, &client_port, 0, 0) == NULL) return ERROR_RC; } if (request_type == PW_ACCOUNTING_REQUEST) { /* * Fill in Acct-Delay-Time */ dtime = 0; now = rc_getctime(); adt_vp = rc_avpair_get(data.send_pairs, PW_ACCT_DELAY_TIME, 0); if (adt_vp == NULL) { adt_vp = rc_avpair_add(rh, &(data.send_pairs), PW_ACCT_DELAY_TIME, &dtime, 0, 0); if (adt_vp == NULL) return ERROR_RC; start_time = now; } else { start_time = now - adt_vp->lvalue; } } if (data.receive_pairs != NULL) { rc_avpair_free(data.receive_pairs); data.receive_pairs = NULL; } servernum=0; do { rc_buildreq(rh, &data, request_type, aaaserver->name[servernum], aaaserver->port[servernum], aaaserver->secret[servernum], timeout, retries); if (request_type == PW_ACCOUNTING_REQUEST) { dtime = rc_getctime() - start_time; rc_avpair_assign(adt_vp, &dtime, 0); } result = rc_send_server_ctx (rh, ctx, &data, msg, type); if (request_type != PW_ACCOUNTING_REQUEST) { *received = data.receive_pairs; } else { rc_avpair_free(data.receive_pairs); } if(result == OK_RC) { DEBUG(LOG_INFO, "servernum %u returned success", servernum); return result; } //rc_log(LOG_ERR, // "servernum %u returned error: %d", servernum, result); servernum++; } while(servernum < aaaserver->max && result == TIMEOUT_RC); return result; }