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

📄 radiud.mp.c

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