int rc_find_server (rc_handle *rh, const char *server_name, uint32_t *ip_addr, char *secret) { int i; size_t len; int result = 0; FILE *clientfd; char *h; char *s; char buffer[128]; char hostnm[AUTH_ID_LEN + 1]; char *buffer_save; char *hostnm_save; SERVER *authservers; SERVER *acctservers; /* Lookup the IP address of the radius server */ if ((*ip_addr = rc_get_ipaddr (server_name)) == (uint32_t) 0) return -1; /* Check to see if the server secret is defined in the rh config */ if( (authservers = rc_conf_srv(rh, "authserver")) != NULL ) { for( i = 0; i < authservers->max; i++ ) { if( (strncmp(server_name, authservers->name[i], strlen(server_name)) == 0) && (authservers->secret[i] != NULL) ) { memset (secret, '\0', MAX_SECRET_LENGTH); len = strlen (authservers->secret[i]); if (len > MAX_SECRET_LENGTH) { len = MAX_SECRET_LENGTH; } strncpy (secret, authservers->secret[i], (size_t) len); secret[MAX_SECRET_LENGTH] = '\0'; return 0; } } } if( (acctservers = rc_conf_srv(rh, "acctserver")) != NULL ) { for( i = 0; i < acctservers->max; i++ ) { if( (strncmp(server_name, acctservers->name[i], strlen(server_name)) == 0) && (acctservers->secret[i] != NULL) ) { memset (secret, '\0', MAX_SECRET_LENGTH); len = strlen (acctservers->secret[i]); if (len > MAX_SECRET_LENGTH) { len = MAX_SECRET_LENGTH; } strncpy (secret, acctservers->secret[i], (size_t) len); secret[MAX_SECRET_LENGTH] = '\0'; return 0; } } } /* We didn't find it in the rh_config or the servername is too long so look for a * servers file to define the secret(s) */ if ((clientfd = fopen (rc_conf_str(rh, "servers"), "r")) == NULL) { rc_log(LOG_ERR, "rc_find_server: couldn't open file: %s: %s", strerror(errno), rc_conf_str(rh, "servers")); return -1; } while (fgets (buffer, sizeof (buffer), clientfd) != NULL) { if (*buffer == '#') continue; if ((h = strtok_r(buffer, " \t\n", &buffer_save)) == NULL) /* first hostname */ continue; memset (hostnm, '\0', AUTH_ID_LEN); len = strlen (h); if (len > AUTH_ID_LEN) { len = AUTH_ID_LEN; } strncpy (hostnm, h, (size_t) len); hostnm[AUTH_ID_LEN] = '\0'; if ((s = strtok_r (NULL, " \t\n", &buffer_save)) == NULL) /* and secret field */ continue; memset (secret, '\0', MAX_SECRET_LENGTH); len = strlen (s); if (len > MAX_SECRET_LENGTH) { len = MAX_SECRET_LENGTH; } strncpy (secret, s, (size_t) len); secret[MAX_SECRET_LENGTH] = '\0'; if (!strchr (hostnm, '/')) /* If single name form */ { if (find_match (ip_addr, hostnm) == 0) { result++; break; } } else /* <name1>/<name2> "paired" form */ { strtok_r(hostnm, "/", &hostnm_save); if (rc_is_myname(hostnm) == 0) { /* If we're the 1st name, target is 2nd */ if (find_match (ip_addr, hostnm_save) == 0) { result++; break; } } else /* If we were 2nd name, target is 1st name */ { if (find_match (ip_addr, hostnm) == 0) { result++; break; } } } } fclose (clientfd); if (result == 0) { memset (buffer, '\0', sizeof (buffer)); memset (secret, '\0', sizeof (secret)); rc_log(LOG_ERR, "rc_find_server: couldn't find RADIUS server %s in %s", server_name, rc_conf_str(rh, "servers")); return -1; } return 0; }
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; }
static int test_config(char *filename) { #if 0 struct stat st; char *file; #endif if (!(rc_conf_srv("authserver")->max)) { error("%s: no authserver specified", filename); return (-1); } if (!(rc_conf_srv("acctserver")->max)) { error("%s: no acctserver specified", filename); return (-1); } if (!rc_conf_str("servers")) { error("%s: no servers file specified", filename); return (-1); } if (!rc_conf_str("dictionary")) { error("%s: no dictionary specified", filename); return (-1); } if (rc_conf_int("radius_timeout") <= 0) { error("%s: radius_timeout <= 0 is illegal", filename); return (-1); } if (rc_conf_int("radius_retries") <= 0) { error("%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)) { error("%s: not a regular file: %s", filename, file); return (-1); } } else { error("%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)) { error("%s: not a regular file: %s", filename, file); return (-1); } } else { error("%s: file not found: %s", filename, file); return (-1); } #endif if (rc_conf_int("login_tries") <= 0) { error("%s: login_tries <= 0 is illegal", filename); return (-1); } if (rc_conf_str("seqfile") == NULL) { error("%s: seqfile not specified", filename); return (-1); } if (rc_conf_int("login_timeout") <= 0) { error("%s: login_timeout <= 0 is illegal", filename); return (-1); } if (rc_conf_str("mapfile") == NULL) { error("%s: mapfile not specified", filename); return (-1); } if (rc_conf_str("nologin") == NULL) { error("%s: nologin not specified", filename); return (-1); } return 0; }
int main (int argc, char **argv) { int result = ERROR_RC; int c,i; char *p, msg[4096]; SERVER *srv; char *path_radiusclient_conf = RC_CONFIG_FILE; rc_handle *rh; extern int optind; pname = (pname = strrchr(argv[0],'/'))?pname+1:argv[0]; rc_openlog(pname); while ((c = getopt(argc,argv,"hVf:")) > 0) { switch(c) { case 'f': path_radiusclient_conf = optarg; break; case 'V': version(); break; case 'h': usage(); break; default: exit(ERROR_RC); break; } } argc -= optind; argv += optind; if ((rh = rc_read_config(path_radiusclient_conf)) == NULL) exit(ERROR_RC); if (rc_read_dictionary(rh, rc_conf_str(rh, "dictionary")) != 0) exit (ERROR_RC); if (argc > 0) { for (i = 0; i < argc; i++) { if ((p = strchr(argv[i], ':')) == NULL) { result = rc_check(rh, argv[i],rc_getport(AUTH), msg); } else if (!strcmp(p+1, "auth")) { *p = '\0'; result = rc_check(rh, argv[i],rc_getport(AUTH), msg); } else if (!strcmp(p+1, "acct")) { *p = '\0'; result = rc_check(rh, argv[i],rc_getport(ACCT), msg); } else { *p = '\0'; result = rc_check(rh, argv[i], atoi(p+1), msg); } if (result == OK_RC) fputs(msg, stdout); else printf(SC_STATUS_FAILED); } } else { srv = rc_conf_srv(rh, "authserver"); for(i=0; i<srv->max ; i++) { result = rc_check(rh, srv->name[i], srv->port[i], msg); fputs(msg, stdout); } srv = rc_conf_srv(rh, "acctserver"); for(i=0; i<srv->max ; i++) { result = rc_check(rh, srv->name[i], srv->port[i], msg); fputs(msg, stdout); } } }
/** 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_getmtime(); 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_getmtime()) { 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_getmtime() - 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; }
/** Locate a server in the rh config or if not found, check for a servers file * * @param rh a handle to parsed configuration. * @param server_name the name of the server. * @param info: will hold a pointer to addrinfo * @param secret will hold the server's secret (of %MAX_SECRET_LENGTH). * @param flags %AUTH or %ACCT * @return 0 on success, -1 on failure. */ int rc_find_server_addr (rc_handle const *rh, char const *server_name, struct addrinfo** info, char *secret, unsigned flags) { int i; int result = 0; FILE *clientfd; char *h; char *s; char buffer[128]; char hostnm[AUTH_ID_LEN + 1]; char *buffer_save; char *hostnm_save; SERVER *authservers; SERVER *acctservers; struct addrinfo *tmpinfo = NULL; /* Lookup the IP address of the radius server */ if ((*info = rc_getaddrinfo (server_name, flags==AUTH?PW_AI_AUTH:PW_AI_ACCT)) == NULL) return -1; if (flags == AUTH) { /* Check to see if the server secret is defined in the rh config */ if( (authservers = rc_conf_srv(rh, "authserver")) != NULL ) { for( i = 0; i < authservers->max; i++ ) { if( (strncmp(server_name, authservers->name[i], strlen(server_name)) == 0) && (authservers->secret[i] != NULL) ) { memset (secret, '\0', MAX_SECRET_LENGTH); strlcpy (secret, authservers->secret[i], MAX_SECRET_LENGTH); return 0; } } } } else if (flags == ACCT) { if( (acctservers = rc_conf_srv(rh, "acctserver")) != NULL ) { for( i = 0; i < acctservers->max; i++ ) { if( (strncmp(server_name, acctservers->name[i], strlen(server_name)) == 0) && (acctservers->secret[i] != NULL) ) { memset (secret, '\0', MAX_SECRET_LENGTH); strlcpy (secret, acctservers->secret[i], MAX_SECRET_LENGTH); return 0; } } } } /* We didn't find it in the rh_config or the servername is too long so look for a * servers file to define the secret(s) */ if ((clientfd = fopen (rc_conf_str(rh, "servers"), "r")) == NULL) { rc_log(LOG_ERR, "rc_find_server: couldn't open file: %s: %s", strerror(errno), rc_conf_str(rh, "servers")); goto fail; } while (fgets (buffer, sizeof (buffer), clientfd) != NULL) { if (*buffer == '#') continue; if ((h = strtok_r(buffer, " \t\n", &buffer_save)) == NULL) /* first hostname */ continue; strlcpy (hostnm, h, AUTH_ID_LEN); if ((s = strtok_r (NULL, " \t\n", &buffer_save)) == NULL) /* and secret field */ continue; strlcpy (secret, s, MAX_SECRET_LENGTH); if (!strchr (hostnm, '/')) /* If single name form */ { tmpinfo = rc_getaddrinfo(hostnm, 0); if (tmpinfo) { result = find_match (*info, tmpinfo); if (result == 0) { result++; break; } freeaddrinfo(tmpinfo); tmpinfo = NULL; } } else /* <name1>/<name2> "paired" form */ { strtok_r(hostnm, "/", &hostnm_save); tmpinfo = rc_getaddrinfo(hostnm, 0); if (tmpinfo) { if (rc_is_myname(tmpinfo) == 0) { /* If we're the 1st name, target is 2nd */ if (find_match (*info, tmpinfo) == 0) { result++; break; } } else /* If we were 2nd name, target is 1st name */ { if (find_match (*info, tmpinfo) == 0) { result++; break; } } freeaddrinfo(tmpinfo); tmpinfo = NULL; } } } fclose (clientfd); if (result == 0) { memset (buffer, '\0', sizeof (buffer)); memset (secret, '\0', MAX_SECRET_LENGTH); rc_log(LOG_ERR, "rc_find_server: couldn't find RADIUS server %s in %s", server_name, rc_conf_str(rh, "servers")); goto fail; } result = 0; goto cleanup; fail: freeaddrinfo(*info); result = -1; cleanup: if (tmpinfo) freeaddrinfo(tmpinfo); return result; }