📄 radiusd.c
字号:
int passlen; char *hold_vector; char pw_digest[16]; char *string; char *ptr; calc_digest((u_char*)pw_digest, authreq, (u_char*)secret); /* * Decrypt the password in the request. */ if((auth_item = get_attribute(authreq->request, PW_PASSWORD)) == (VALUE_PAIR *)NULL) { return (char *)NULL; } passlen = auth_item->lvalue; if(passlen > AUTH_MAXPASS_LEN) { log_err("encrypt_password: Password length %d > %d not allowed, truncating\n",passlen, AUTH_MAXPASS_LEN); passlen = AUTH_MAXPASS_LEN; auth_item->lvalue = AUTH_MAXPASS_LEN; auth_item->strvalue[AUTH_MAXPASS_LEN] = '\0'; } string = auth_item->strvalue; ptr = string; for(i = 0;i < passlen;i += AUTH_PASS_LEN) { /* Encrypt using the digest */ hold_vector = ptr; for(j = 0;j < AUTH_PASS_LEN;j++) { *ptr ^= pw_digest[j]; ptr++; } /* Calculate the next digest if necessary */ if(i < passlen) { calc_next_digest((u_char*)pw_digest, (u_char*)secret, (u_char*)hold_vector); } } *ptr = '\0'; /* this depends on the fact that auth_item->strvalue always has an extra byte available */ return string;}/************************************************************************* * * Function: calc_digest * * Purpose: Validates the requesting client NAS. Calculates the * digest to be used for decrypting the users password * based on the clients private key. * *************************************************************************/void calc_digest(u_char *digest,AUTH_REQ *authreq,u_char *secret){ u_char buffer[128]; int secretlen; /* Use the secret to setup the decryption digest */ memset(buffer, 0, sizeof(buffer)); secretlen = strlen((char *)secret); memcpy((char *)buffer, (char *)secret,secretlen); memcpy(buffer + secretlen, authreq->vector, AUTH_VECTOR_LEN); md5_calc(digest, buffer, secretlen + AUTH_VECTOR_LEN); memset(buffer, 0, secretlen+AUTH_VECTOR_LEN); return;}/************************************************************************* * * Function: calc_next_digest * * Purpose: Calculates the digest to be used for decrypting the * users password past the first 16 octets based on the clients * private key. * *************************************************************************/void calc_next_digest(u_char*digest,u_char*secret,u_char*vector){ u_char buffer[128]; int secretlen; /* Use the secret to setup the decryption digest */ memset(buffer, 0, sizeof(buffer)); secretlen = strlen((const char *)secret); strcpy((char *)buffer, (const char *)secret); memcpy(buffer + secretlen, vector, AUTH_VECTOR_LEN); md5_calc(digest, buffer, secretlen + AUTH_VECTOR_LEN); memset(buffer, 0, sizeof(buffer));}/************************************************************************* * * Function: client_hostname * * Purpose: Return the cached client name if we have one. Otherwise * use the regular ip_hostname() function. * *************************************************************************/char* client_hostname(UINT4 ipaddr){ u_char secret[64]; char hostnm[MAX_HOST_SIZE]; /* Look at the last used entry first */ if(ipaddr == cached_ipaddr) { return(cached_hostnm); } if(find_client(ipaddr, secret, sizeof(secret), hostnm, sizeof(hostnm)) != 0) { memset(secret, 0, sizeof(secret)); return(cached_hostnm); /* set by find_client() */ } return(ip_hostname(ipaddr));}/************************************************************************* * * Function: find_client * * Purpose: Retrieve the client name and secret from the temporary * DBM client database. * *************************************************************************/int find_client(UINT4 ipaddr,char*secret,int secretlen,char*hostnm,size_t hostnmlen){ GDBM_FILE db; char buffer[MAX_LINE_SIZE]; char ip_str[32]; datum contentd; datum named; int ret; char fmt[16]; if (snprintf(fmt,sizeof(fmt), "%%%ds%%%ds", secretlen, hostnmlen)>=sizeof(fmt)) { log_err("format too long\n"); return(-1); } /* Find the client in the database */ snprintf((char *)buffer,sizeof(buffer),"%s/%s", radius_dir, RADIUS_CLIENT_CACHE); if ((db = gdbm_open(buffer,0,GDBM_READER,0600,NULL )) == NULL) { log_err("could not read %s to find clients\n", buffer); return(-1); } ipaddr2str(ip_str, sizeof(ip_str), ipaddr); named.dptr = ip_str; named.dsize = strlen(ip_str); contentd = gdbm_fetch(db, named); if(contentd.dsize == 0 || contentd.dptr == NULL) { gdbm_close(db); log_err("client %s not found in client cache\n",ip_str); if (contentd.dptr!=NULL) free(contentd.dptr); return(-1); } if (contentd.dsize >= MAX_LINE_SIZE) { gdbm_close(db); log_err("client %s length %d > %d in client cache\n", ip_str, contentd.dsize, MAX_LINE_SIZE-1); free(contentd.dptr); return(-1); } /* convoluted method of working around Solaris x86 2.5 bug */ memcpy(buffer,contentd.dptr,contentd.dsize-1); buffer[contentd.dsize - 1] = '\n'; buffer[contentd.dsize] = '\0'; if((ret=sscanf((const char *)buffer, fmt, hostnm, secret)) != 2) { gdbm_close(db); log_err("client cache entry for %s could not be parsed (%d)\n", ip_str,ret); free(contentd.dptr); return(-1); } /* Build a cached hostname entry for client_hostname() to use */ strncpy(cached_hostnm, hostnm, MAX_HOST_SIZE); cached_hostnm[MAX_HOST_SIZE-1] = '\0'; cached_ipaddr = ipaddr; gdbm_close(db); free(contentd.dptr); return(0);}/************************************************************************* * * Function: update_clients * * Purpose: Check last modified time on clients file and build a * new temporary DBM client database if the file has been * changed. * *************************************************************************/int update_clients(void){ static time_t last_update_time; struct stat statbuf; struct stat statbuf2; datum named; datum contentd; GDBM_FILE db; FILE *clientfd; u_char buffer[256]; u_char oldcache[256]; u_char newcache[256]; u_char secret[64]; char hostnm[128]; char ip_str[64]; int nclients; int rcode; int s1; int s2; UINT4 ipaddr; nclients = 0; rcode = 0; /* Check last modified time of clients file */ snprintf((char *)buffer,sizeof(buffer),"%s/%s", radius_dir, RADIUS_CLIENTS); if(stat(buffer, &statbuf) != 0) { log_err("Error: clients file %s not found\n", buffer); return(-1); } if(statbuf.st_mtime == last_update_time) { /* nothing to update */ return(0); } cached_ipaddr = 0; /* Open the standard clients file */ if((clientfd = fopen((const char *)buffer, "r")) == (FILE *)NULL) { log_err("Error: could not read clients file %s\n", buffer); return(-1); } /* Open and truncate the clients DBM cache file */ snprintf((char *)oldcache,sizeof(oldcache),"%s/%s", radius_dir, RADIUS_CLIENT_CACHE); snprintf((char *)newcache,sizeof(oldcache),"%s.lock", oldcache); if((db=gdbm_open(newcache,0,GDBM_NEWDB,0600,NULL)) == NULL) { log_err("Error: could not create temporary client cache file %s\n",newcache); return(-1); } while(fgets((char *)buffer, sizeof(buffer), clientfd) != (char *)NULL) { if(*buffer == '#') { continue; } if(sscanf((const char *)buffer, "%s%s", hostnm, secret) != 2) { continue; } if((ipaddr = get_ipaddr(hostnm)) != (UINT4)0) { ipaddr2str(ip_str, sizeof(ip_str), ipaddr); named.dptr = ip_str; named.dsize = strlen(ip_str); contentd.dptr = (char *)buffer; contentd.dsize = strlen(buffer); if(gdbm_store(db, named, contentd, GDBM_INSERT) != 0) { log_err("could not cache client datum for host %s\n", hostnm); rcode = -1; } else { nclients++; } } } gdbm_close(db); fclose(clientfd); if (rename(newcache,oldcache) != 0) { log_err("Error: could not move client cache file %s to %s," "error %d\n",newcache,oldcache,errno); return(-1); } else { debug("updated client cache with %d clients\n",nclients); } if (rcode == 0) last_update_time = statbuf.st_mtime; return(rcode);}/************************************************************************* * * Function: debug_pair * * Purpose: Print the Attribute-value pair to the desired File. * *************************************************************************/void debug_pair(VALUE_PAIR * pair){ if(debug_flag) { fprint_attr_val(stdout, pair); }}/************************************************************************* * * Function: usage * * Purpose: Display the syntax for starting this program. * *************************************************************************/void usage(void){ fprintf(stderr, "Usage: %s\n", progname); fprintf(stderr, " [-a <acct_dir>] set accounting directory\n"); fprintf(stderr, " [-b] use GDBM for users file\n"); fprintf(stderr, " [-c] clear user stats database\n"); fprintf(stderr, " [-d <db_dir>] set radiusd database directory\n"); fprintf(stderr, " [-h] print this usage\n"); fprintf(stderr, " [-f <alt_passwd_file>] set alternate password file\n"); fprintf(stderr, " [-i <ip_address>] set alternate IP\n"); fprintf(stderr, " [-l <log_file>] set radius log file\n"); fprintf(stderr, " [-o] accept all-zero accounting requests authenticator\n"); fprintf(stderr, " [-p <udp_port>] set alternate radius port number\n"); fprintf(stderr, " [-q <max outstanding requests>] set incoming packets queue size\n"); fprintf(stderr, " [-s] do fork\n"); fprintf(stderr, " [-t <max seconds in queue>] set time out for requests queue\n"); fprintf(stderr, " [-v] print version\n"); fprintf(stderr, " [-w <max seconds for proxy>] set time out for proxy requests\n"); fprintf(stderr, " [-x] set debug mode on\n");#if defined(PAM) fprintf(stderr, " [-P] set PAM auth mode on\n"); fprintf(stderr, " [-A] set PAM acct mode on\n");#endif fprintf(stderr, " [-z] as -b -x -d . -a ra\n\n"); exit(-1);}/************************************************************************* * * Function: config_init * * Purpose: intializes configuration values * * expiration_seconds - When updating a user password, * the amount of time to add to the current time * to set the time when the password will expire. * This is stored as the VALUE Password-Expiration * in the dictionary as number of days. * * warning_seconds - When acknowledging a user authentication * time remaining for valid password to notify user * of password expiration. * *************************************************************************/int config_init(void){ DICT_VALUE *dval; DICT_VALUE *dict_valfind(); if((dval = dict_valfind("Password-Expiration")) == (DICT_VALUE *)NULL) { expiration_seconds = (UINT4)0; } else { expiration_seconds = dval->value * (UINT4)SECONDS_PER_DAY; } if((dval = dict_valfind("Password-Warning")) == (DICT_VALUE *)NULL) { warning_seconds = (UINT4)0; } else { warning_seconds = dval->value * (UINT4)SECONDS_PER_DAY; } strcpy(unknown,"unknown"); /* for client caching error return */ return(0);}/************************************************************************* * * Function: set_expiration * * Purpose: Set the new expiration time by updating or adding the Expiration attribute-value pair. * *************************************************************************/int set_expiration(VALUE_PAIR*user_check,UINT4 expiration){ VALUE_PAIR *exppair; VALUE_PAIR *prev; struct timeval tp; struct timezone tzp; if(user_check == (VALUE_PAIR *)NULL) { return(-1); } /* Look for an existing expiration entry */ exppair = user_check; prev = (VALUE_PAIR *)NULL; while(exppair != (VALUE_PAIR *)NULL) { if(exppair->attribute == PW_EXPIRATION) { break; } prev = exppair; exppair = exppair->next; } if(exppair == (VALUE_PAIR *)NULL) { /* Add a new attr-value pair */ exppair = pairalloc("set_expiration"); /* Initialize it */ strcpy(exppair->name, "Expiration"); exppair->attribute = PW_EXPIRATION; exppair->type = PW_TYPE_DATE; /* Attach it to the list. */ prev->next = exppair; } /* calculate a new expiration */ gettimeofday(&tp, &tzp); exppair->lvalue = tp.tv_sec + expiration; return(0);}/************************************************************************* * * Function: pw_expired * * Purpose: Tests to see if the users password has expired. * * Return: Number of days before expiration if a warning is required * otherwise 0 for success and -1 for failure. * *************************************************************************/int pw_expired(UINT4 exptime){ struct timeval tp; struct timezone tzp; UINT4 exp_remain; int exp_remain_int; if(expiration_seconds == (UINT4)0) { /* expiration not enabled */ return(0); } gettimeofday(&tp, &tzp); if(tp.tv_sec > exptime) { return(-1); } if(warning_seconds != (UINT4)0) { if(tp.tv_sec > exptime - warning_seconds) { exp_remain = exptime - tp.tv_sec; exp_remain /= (UINT4)SECONDS_PER_DAY; exp_remain_int = exp_remain; return(exp_remain_int); } } return(0);}/************************************************************************* * * Function: get_attribute * * Purpose: Retrieve a specific value-pair from a list of value-pairs. * *************************************************************************/VALUE_PAIR* get_attribute(VALUE_PAIR*v
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -