📄 radiusd.c
字号:
case PW_AUTHENTICATION_REQUEST:
if(spawn_flag) {
rad_spawn_child(authreq, activefd);
} else {
rad_authenticate(authreq, activefd);
}
break;
case PW_ACCOUNTING_REQUEST:
acct_check_dup(authreq, activefd);
/* rad_accounting(authreq, activefd);*/
break;
#ifdef PASSCHANGE
case PW_PASSWORD_REQUEST:
rad_passchange(authreq, activefd);
break;
#endif
default:
break;
}
return(0);
}
/*************************************************************************
*
* Function: rad_spawn_child
*
* Purpose: Spawns child processes to perform password authentication
* and respond to RADIUS clients. This functions also
* cleans up complete child requests, and verifies that there
* is only one process responding to each request (duplicate
* requests are filtered out.
*
*************************************************************************/
rad_spawn_child(authreq, activefd)
AUTH_REQ *authreq;
int activefd;
{
AUTH_REQ *curreq;
AUTH_REQ *prevreq;
UINT4 curtime;
int request_count;
char msg[512];
char *ip_hostname();
int child_pid;
curtime = (UINT4)time(0);
request_count = 0;
curreq = first_request;
prevreq = (AUTH_REQ *)NULL;
while(curreq != (AUTH_REQ *)NULL) {
if(curreq->child_pid == -1 &&
curreq->timestamp + CLEANUP_DELAY <= curtime) {
/* Request completed, delete it */
if(prevreq == (AUTH_REQ *)NULL) {
first_request = curreq->next;
pairfree(curreq->request);
free(curreq);
curreq = first_request;
}
else {
prevreq->next = curreq->next;
pairfree(curreq->request);
free(curreq);
curreq = prevreq->next;
}
}
/************** authreq->id不能作为判断重复的依据 ******************/
/*
else if(curreq->ipaddr == authreq->ipaddr && curreq->id == authreq->id) {
sprintf(msg,
"Dropping duplicate: from %s - ID: %d\n",
ip_hostname(authreq->ipaddr), authreq->id);
msg[127] = '\0';
log_err(msg);
pairfree(authreq->request);
free(authreq);
return(0);
}
*/
else {
if(curreq->timestamp + MAX_REQUEST_TIME <= curtime &&
curreq->child_pid != -1) {
/* This request seems to have hung - kill it */
child_pid = curreq->child_pid;
sprintf(msg,
"Killing unresponsive child pid %d\n",
child_pid);
log_err(msg);
curreq->child_pid = -1;
kill(child_pid, SIGHUP);
}
prevreq = curreq;
curreq = curreq->next;
request_count++;
}
}
/* This is a new request */
if(request_count > MAX_REQUESTS) {
sprintf(msg, "AUTH dropping request (too many): from %s - ID: %d\n",
ip_hostname(authreq->ipaddr), authreq->id);
msg[127] = '\0';
log_err(msg);
pairfree(authreq->request);
free(authreq);
return(0);
}
/* Add this request to the list */
authreq->next = (AUTH_REQ *)NULL;
authreq->child_pid = -1;
authreq->timestamp = curtime;
if(prevreq == (AUTH_REQ *)NULL) {
first_request = authreq;
}
else {
prevreq->next = authreq;
}
/* fork our child */
child_pid = fork();
if(child_pid < 0) {
sprintf(msg, "Fork failed for request from %s - ID: %d\n",
ip_hostname(authreq->ipaddr), authreq->id);
msg[127] = '\0';
log_err(msg);
}
if(child_pid == 0) {
/* This is the child, it should go ahead and respond */
rad_authenticate(authreq, activefd);
exit(0);
}
/* Register the Child */
authreq->child_pid = child_pid;
return(0);
}
void sig_cleanup()
{
int status;
pid_t pid;
AUTH_REQ *curreq;
for (;;) {
pid = waitpid((pid_t)-1,&status,WNOHANG);
signal(SIGCHLD, sig_cleanup);
if (pid <= 0)
return;
#if defined (aix)
kill(pid, SIGKILL);
#endif
if(pid == acct_pid) {
sig_fatal(100);
}
curreq = first_request;
while(curreq != (AUTH_REQ *)NULL) {
if(curreq->child_pid == pid) {
curreq->child_pid = -1;
curreq->timestamp = (UINT4)time(0);
break;
}
curreq = curreq->next;
}
}
}
/******************************************************
** **
** function acct_check_dup(authreq, activefd) **
** **
******************************************************/
acct_check_dup(authreq, activefd)
AUTH_REQ *authreq;
int activefd;
{
AUTH_REQ *curreq;
AUTH_REQ *prevreq;
UINT4 curtime;
int request_count;
char msg[512];
char *ip_hostname();
VALUE_PAIR *vtp;
long s_time_authreq;
long s_time_curreq;
UINT4 status_type;
time_t logtime;
char thetime[30];
curtime = (UINT4)time(0);
request_count = 0;
curreq = first_request_acct;
prevreq = (AUTH_REQ *)NULL;
vtp = authreq->request;
while(vtp != (VALUE_PAIR *)NULL)
{
if(vtp->attribute == PW_ACCT_SESSION_TIME)
{
s_time_authreq = vtp->lvalue;
}
vtp = vtp->next;
}
status_type = check_acct_status(authreq->request);
if(status_type==PW_ACCT_START)
{
rad_accounting(authreq, activefd);
}
else if(status_type==PW_ACCT_STOP)
{
while(curreq != (AUTH_REQ *)NULL)
{
vtp = curreq->request;
while(vtp != (VALUE_PAIR *)NULL)
{
if(vtp->attribute == PW_ACCT_SESSION_TIME)
{
s_time_curreq = vtp->lvalue;
}
vtp = vtp->next;
}
if(curreq->timestamp + 15 <= curtime)
{
/* 已保留在ACCT请求队列中足够长时间,可清除*/
if(prevreq == (AUTH_REQ *)NULL)
{
first_request_acct = curreq->next;
pairfree(curreq->request);
free(curreq);
curreq = first_request_acct;
}
else
{
prevreq->next = curreq->next;
pairfree(curreq->request);
free(curreq);
curreq = prevreq->next;
}
printf("\n清除ACCT队列");
}
else
{
if(curreq->ipaddr == authreq->ipaddr && s_time_authreq==s_time_curreq)
{
/* This is a duplicate request - just drop it */
sprintf(msg,"Acct Dropping duplicate: from %s - ID: %d\n",ip_hostname(authreq->ipaddr), authreq->id);
msg[127] = '\0';
log_err(msg);
printf("\n发现重复的ACCT请求包!");
pairfree(authreq->request);
free(authreq);
return(0);
}
prevreq = curreq;
curreq = curreq->next;
request_count++;
}
}
/* This is a new request */
if(request_count > 120)
{
sprintf(msg, "Acct dropping request (too many): from %s - ID: %d\n",
ip_hostname(authreq->ipaddr), authreq->id);
msg[127] = '\0';
log_err(msg);
pairfree(authreq->request);
free(authreq);
printf("\nACCT队列溢出,新的请求被忽略!!");
return(0);
}
/* Add this request to the list */
authreq->next = (AUTH_REQ *)NULL;
authreq->timestamp = curtime;
if(prevreq == (AUTH_REQ *)NULL) {
first_request_acct = authreq;
}
else {
prevreq->next = authreq;
}
rad_accounting(authreq, activefd);
}
else
{
printf("\n非法请求包类型!!");
time(&logtime);
strcpy(thetime,ctime(&logtime));
thetime[24]=0;
sprintf(msg, "\nAcct 非法请求包类型 from %s - ID: %d %s",ip_hostname(authreq->ipaddr), authreq->id,thetime);
msg[127] = '\0';
log_err_inf(msg);
}
return(0);
}
/*************************************************************************
*
* Function: rad_passchange
*
* Purpose: Change a users password
*
*************************************************************************/
void
rad_passchange(authreq, activefd)
AUTH_REQ *authreq;
int activefd;
{
VALUE_PAIR *namepair;
VALUE_PAIR *check_item;
VALUE_PAIR *newpasspair;
VALUE_PAIR *oldpasspair;
VALUE_PAIR *curpass;
VALUE_PAIR *user_check;
VALUE_PAIR *user_reply;
char pw_digest[16];
char string[64];
char passbuf[AUTH_PASS_LEN];
int i;
int secretlen;
char msg[512];
char *ip_hostname();
/* Get the username */
namepair = authreq->request;
while(namepair != (VALUE_PAIR *)NULL) {
if(namepair->attribute == PW_USER_NAME) {
break;
}
namepair = namepair->next;
}
if(namepair == (VALUE_PAIR *)NULL) {
sprintf(msg, "Passchange: from %s - No User name supplied\n",
ip_hostname(authreq->ipaddr));
msg[127] = '\0';
log_err(msg);
pairfree(authreq->request);
memset(authreq, 0, sizeof(AUTH_REQ));
free(authreq);
return;
}
/*
* Look the user up in the database
*/
if(user_find(namepair->strvalue, &user_check, &user_reply) != 0) {
sprintf(msg, "Passchange: from %s - Invalid User: %s\n",
ip_hostname(authreq->ipaddr), namepair->strvalue);
msg[127] = '\0';
log_err(msg);
#ifndef IGNORE_BOGUS_PASSCHANGE
send_reject(authreq, (char *)NULL, activefd);
#endif
pairfree(authreq->request);
memset(authreq, 0, sizeof(AUTH_REQ));
free(authreq);
return;
}
/*
* Validate the user -
*
* We have to unwrap this in a special way to decrypt the
* old and new passwords. The MD5 calculation is based
* on the old password. The vector is different. The old
* password is encrypted using the encrypted new password
* as its vector. The new password is encrypted using the
* random encryption vector in the request header.
*/
/* Extract the attr-value pairs for the old and new passwords */
check_item = authreq->request;
while(check_item != (VALUE_PAIR *)NULL) {
if(check_item->attribute == PW_PASSWORD) {
newpasspair = check_item;
}
else if(check_item->attribute == PW_OLD_PASSWORD) {
oldpasspair = check_item;
}
check_item = check_item->next;
}
/* Verify that both encrypted passwords were supplied */
if(newpasspair == (VALUE_PAIR *)NULL ||
oldpasspair == (VALUE_PAIR *)NULL) {
/* Missing one of the passwords */
sprintf(msg, "Passchange: from %s - Missing Password: %s\n",
ip_hostname(authreq->ipaddr), namepair->strvalue);
msg[127] = '\0';
log_err(msg);
#ifndef IGNORE_BOGUS_PASSCHANGE
send_reject(authreq, (char *)NULL, activefd);
#endif
pairfree(authreq->request);
pairfree(user_check);
pairfree(user_reply);
memset(authreq, 0, sizeof(AUTH_REQ));
free(authreq);
return;
}
/* Get the current password from the database */
curpass = user_check;
while(curpass != (VALUE_PAIR *)NULL) {
if(curpass->attribute == PW_PASSWORD) {
break;
}
curpass = curpass->next;
}
if((curpass == (VALUE_PAIR *)NULL) || curpass->strvalue == (char *)NULL) {
/* Missing our local copy of the password */
sprintf(msg,
"Passchange: from %s - Missing Local Password: %s\n",
ip_hostname(authreq->ipaddr), namepair->strvalue);
msg[127] = '\0';
log_err(msg);
#ifndef IGNORE_BOGUS_PASSCHANGE
send_reject(authreq, (char *)NULL, activefd);
#endif
pairfree(authreq->request);
pairfree(user_check);
pairfree(user_reply);
memset(authreq, 0, sizeof(AUTH_REQ));
free(authreq);
return;
}
if(strcmp(curpass->strvalue,"UNIX") == 0) {
/* Can't change passwords that aren't in users file */
sprintf(msg,
"Passchange: from %s - system password change not allowed: %s\n",
ip_hostname(authreq->ipaddr), namepair->strvalue);
msg[127] = '\0';
log_err(msg);
#ifndef IGNORE_BOGUS_PASSCHANGE
send_reject(authreq, (char *)NULL, activefd);
#endif
pairfree(authreq->request);
pairfree(user_check);
pairfree(user_reply);
memset(authreq, 0, sizeof(AUTH_REQ));
free(authreq);
return;
}
/* Decrypt the old password */
secretlen = strlen(curpass->strvalue);
memcpy(string, curpass->strvalue, secretlen);
memcpy(string + secretlen, newpasspair->strvalue, AUTH_VECTOR_LEN);
md5_calc(pw_digest, string, AUTH_VECTOR_LEN + secretlen);
memcpy(passbuf, oldpasspair->strvalue, AUTH_PASS_LEN);
for(i = 0;i < AUTH_PASS_LEN;i++) {
passbuf[i] ^= pw_digest[i];
}
/* Did they supply the correct password ??? */
if(strncmp(passbuf, curpass->strvalue, AUTH_PASS_LEN) != 0) {
sprintf(msg,
"Passchange: from %s - Incorrect Password: %s\n",
ip_hostname(authreq->ipaddr), namepair->strvalue);
msg[127] = '\0';
log_err(msg);
send_reject(authreq, (char *)NULL, activefd);
pairfree(authreq->request);
pairfree(user_check);
pairfree(user_reply);
memset(authreq, 0, sizeof(AUTH_REQ));
free(authreq);
return;
}
/* Decrypt the new password */
memcpy(string, curpass->strvalue, secretlen);
memcpy(string + secretlen, authreq->vector, AUTH_VECTOR_LEN);
md5_calc(pw_digest, string, AUTH_VECTOR_LEN + secretlen);
memcpy(passbuf, newpasspair->strvalue, AUTH_PASS_LEN);
for(i = 0;i < AUTH_PASS_LEN;i++) {
passbuf[i] ^= pw_digest[i];
}
/* Update the users password */
strncpy(curpass->strvalue, passbuf, AUTH_PASS_LEN);
/* Add a new expiration date if we are aging passwords */
if(expiration_seconds != (UINT4)0) {
set_expiration(user_check, expiration_seconds);
}
/* Update the database */
if(user_update(namepair->strvalue, user_check, user_reply) != 0) {
send_reject(authreq, (char *)NULL, activefd);
sprintf(msg, "Passchange: unable to update password for %s\n",
namepair->strvalue);
msg[127] = '\0';
log_err(msg);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -