📄 radiud.mp.c
字号:
/*************************************************************************
*
* Function: radrespond
*
* Purpose: Respond to supported requests:
*
* PW_AUTHENTICATION_REQUEST - Authentication request from
* a client network access server.
*
* PW_AUTHENTICATION_ACK - Authentication Accept send
* back to network access server.
*
* PW_AUTHENTICATION_REJECT - Authentication Reject send
* back to network access server.
*
* PW_ACCOUNTING_REQUEST - Accounting request from
* a client network access server.
*
* PW_ACCOUNTING_RESPONSE - Accounting response send
* back to network access server.
*
* PW_PASSWORD_REQUEST - User request to change a password.
*
*************************************************************************/
radrespond(authreq, activefd)
AUTH_REQ *authreq;
int activefd;
{
int reply_code;
switch(authreq->code) {
case PW_AUTHENTICATION_REQUEST:
if(spawn_flag) {
rad_spawn_child(authreq, activefd);
} else {
rad_authenticate(authreq, activefd);
}
break;
case PW_ACCOUNTING_REQUEST:
if(spawn_flag) {
rad_spawn_child(authreq, activefd);
} else {
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;
}
}
else if(curreq->ipaddr == authreq->ipaddr &&
curreq->id == authreq->id) {
/* This is a duplicate request - just drop it */
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, "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 */
multi_thre(authreq,activefd);
/* 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: 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);
}
else {
send_pwack(authreq, activefd);
}
pairfree(authreq->request);
pairfree(user_check);
pairfree(user_reply);
memset(authreq, 0, sizeof(AUTH_REQ));
free(authreq);
return;
}
/*************************************************************************
*
* Function: rad_authenticate
*
* Purpose: Process and reply to an authentication request
*
*************************************************************************/
rad_authenticate(authreq, activefd)
AUTH_REQ *authreq;
int activefd;
{
VALUE_PAIR *namepair;
VALUE_PAIR *check_item;
VALUE_PAIR *auth_item;
VALUE_PAIR *user_check;
VALUE_PAIR *user_reply;
VALUE_PAIR *u_reply;
int result;
char pw_digest[16];
char string[128];
int i;
char msg[512];
char umsg[128];
char *user_msg;
char *ip_hostname();
int retval;
char *ptr;
char name_str[32];
char realm_suffix[64];
int realm_status;
char addr_str[32];
VALUE_PAIR *auth_type_pair;
int expire_status;
char *encrypt_pw;
char *enpw;
char *crypt();
USER_ONLINE *online;
long left_time;
long expire_date;
/* Get the username from the request */
namepair = authreq->request;
while(namepair != (VALUE_PAIR *)NULL) {
if(namepair->attribute == PW_USER_NAME) {
break;
}
namepair = namepair->next;
}
if((namepair == (VALUE_PAIR *)NULL) ||
(strlen(namepair->strvalue) <= 0)) {
sprintf(msg, "Authenticate: from %s - No User Name\n",
ip_hostname(authreq->ipaddr));
msg[127] = '\0';
log_err(msg);
pairfree(authreq->request);
memset(authreq, 0, sizeof(AUTH_REQ));
free(authreq);
return;
}
memcpy(authreq->user_name,namepair->strvalue,sizeof(namepair->strvalue));
/* Verify the client and Calculate the MD5 Password Digest */
if(calc_digest(pw_digest, authreq) != 0) {
/* We don't respond when this fails */
sprintf(msg, "Authenticate: from %s - Security Breach: %s\n",
ip_hostname(authreq->ipaddr), namepair->strvalue);
msg[127] = '\0';
log_err(msg);
pairfree(authreq->request);
memset(authreq, 0, sizeof(AUTH_REQ));
free(authreq);
return;
}
memcpy(authreq->digest, pw_digest, AUTH_PASS_LEN);
ipaddr2str(addr_str,authreq->ipaddr);
sprintf(msg,"Auth user: %s - From: %s\n",namepair->strvalue,addr_str);
msg[127]='\0';
log_err(msg);
/* Parse the user_name_string and find the radius server */
if(realm_status=realm_user(namepair->strvalue)){
memset(name_str,'\0',sizeof(name_str));
memset(realm_suffix,'\0',sizeof(realm_suffix));
if(parse_user(namepair->strvalue, name_str,realm_suffix) != 0) {
sprintf(msg, "Authenticate: from %s - Invalid User: %s\n", ip_hostname(authreq->ipaddr), namepair->strvalue);
msg[127] = '\0';
log_err(msg);
send_reject(authreq, (char *)NULL, activefd);
pairfree(authreq->request);
memset(authreq, 0, sizeof(AUTH_REQ));
free(authreq);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -