⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radiusd.c

📁 国际标准协议的
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 + -