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

📄 radiusd.c

📁 This program is a RADIUS RFC-compliant daemon, which is derived from original Livingston Enterprise
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* fork our child */  cleanup_pid = -1;  rad_spawned_child_pid = fork();  if(rad_spawned_child_pid < 0) {  	log_err("system error: fork failed with error %d for request from %s\n",  		errno,req2strp(authreq));  	reqfree(authreq,"rad_spawn_child");  	return;  }  if(rad_spawned_child_pid == 0) {  	/* This is the child, it should go ahead and respond */  	child_authenticate(authreq, activefd);  	exit(0);  }  /* Register the Child */  authreq->child_pid = rad_spawned_child_pid;  /*   * If cleanup_pid is not -1, then we received a SIGCHLD between   * the time we forked and the time we got here, so clean up after it   */  if(cleanup_pid != -1) {  	clean_child(cleanup_pid);  	cleanup_pid = -1;  }}void clean_child(int pid){  AUTH_REQ	*curreq;  curreq = first_request;  while(curreq != (AUTH_REQ *)NULL) {  	if(curreq->child_pid == pid) {  		curreq->child_pid = -1;  		curreq->timestamp = (UINT4)time((time_t *)NULL);  		return;  	}  	curreq = curreq->next;  }  cleanup_pid = (int)pid;  return;}void sig_cleanup(int sig){  int		status;         pid_t		pid;           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);  	}  	clean_child(pid);         }}/*************************************************************************  *  *	Function: child_authenticate  *  *	Purpose: Process and reply to an authentication request  *  *************************************************************************/void child_authenticate(AUTH_REQ *authreq,int activefd){#ifdef SMARTCARD  key_t			msg_key;  int			msg_id;  int			length;  struct	sockaddr_in	*sin;  msg_key = RADIUS_MSG_KEY(getpid());#endif /* SMARTCARD */  for (;;) {  	if (rad_authenticate(authreq, activefd) == 0) {  		break;  	}#ifdef SMARTCARD  	if ((msg_id = msgget(msg_key, IPC_CREAT | 0600)) == -1) {  		log_err("child_authenticate: msgget for key %x for id %d returned error: %s\n", msg_key, msg_id, strerror(errno));  		break;  	}  	if ((length = msgrcv(msg_id, recv_buffer,   			sizeof recv_buffer - sizeof(long),  			0, 0)) == -1) {  		log_err("child_authenticate: msgrcv for msgid %d returned error: %s\n", msg_id, strerror(errno));  		break;  	}  	if (msgctl(msg_id, IPC_RMID, 0) == -1) {  		log_err("child_authenticate: msgctl for msgid %d returned error: %s\n", msg_id, strerror(errno));  	}  	sin = (struct sockaddr_in *) &rad_saremote;  	authreq = radrecv(  		ntohl(sin->sin_addr.s_addr),  		ntohs(sin->sin_port),  		authreq->secret, recv_buffer, length);#else /* not SMARTCARD */  	break;#endif /* not SMARTCARD */  }}/*************************************************************************  *  *	Function: rad_authenticate  *  *	Purpose: Process and reply to an authentication request  *  *************************************************************************/int rad_authenticate(AUTH_REQ *authreq,int activefd){  USER_FILE	user_desc;  VALUE_PAIR	*attr;  VALUE_PAIR	*auth_item;  VALUE_PAIR	*callpair;  VALUE_PAIR	*challenge;  VALUE_PAIR	*check_item;  VALUE_PAIR	*password_item;  VALUE_PAIR	*user_check;  VALUE_PAIR	*user_reply;  char		auth_name[AUTH_STRING_LEN + 2];  char		callfrom[ID_LENGTH];  char		pw_digest[16];  char		string[AUTH_STRING_LEN + 20 + 2];  char		umsg[AUTH_STRING_LEN + 2];  char		*encpw;  char		*ptr;  char		*user_msg;  char		*pass;  int		authtype;  int		chlen;  int		result;  int		retval;  int		speed;  /* The username was placed in authreq->name by handle_proxy */  if(strlen(authreq->name) <= (size_t)0) {  	log_err("auth: access-request from %s ignored; no user name\n",  		req2strp(authreq));  	reqfree(authreq,"rad_authenticate");  	return(0);  }#ifdef VPORTS         if (vports_flag == 1) {                 switch(vp_check_req(authreq)) {  	case VP_RET_REJECT:  		send_reject(authreq, (char *)NULL, activefd);  		reqfree(authreq,"rad_authenticate");  		return(0);  		break;  	case VP_RET_ACCEPT:  		send_accept(authreq, (VALUE_PAIR *)NULL, (char *)NULL, activefd);  		reqfree(authreq,"rad_authenticate");  		return(0);  		break;  	case VP_RET_IGNORE:  	default:  		break;  }}#endif /* VPORTS */  /* calculate the MD5 Password Digest */  calc_digest((u_char*)pw_digest, authreq, (u_char*)authreq->secret);  /*   * If the request is processing a menu, service it here.   */  if((attr = get_attribute(authreq->request, PW_STATE)) !=  	(VALUE_PAIR *)NULL && strncmp(attr->strvalue, "MENU=", 5) == 0){  	process_menu(authreq, activefd, pw_digest);  	return(0);  }  callpair = get_attribute(authreq->request, PW_CALLING);  if (callpair == (VALUE_PAIR *)NULL || callpair->lvalue > 20) {  	callfrom[0] = '\0';  } else {  	snprintf(callfrom,(size_t)ID_LENGTH," at %s",callpair->strvalue);  }  /*   * Open the user table   */  user_desc = user_open();  if(user_desc.gdbm == NULL && user_desc.flat == NULL) {  	reqfree(authreq,"rad_authenticate");  	return(0);  }  for (;;) {  	/* Get the user from the database */  	if ((result = user_find(authreq->name,  				auth_name,  				&user_check,  				&user_reply,  				user_desc)) != 0) {  		log_err("auth: access-request from %s denied for unknown user \"%s\"%s\n",  			req2strp(authreq), authreq->name, callfrom);  		send_reject(authreq, (char *)NULL, activefd);  		reqfree(authreq,"rad_authenticate");  		user_close(user_desc);  		return(0);  	}  	/* Validate the user */  	/* Look for matching check items */  	password_item = (VALUE_PAIR *)NULL;  	authtype = PW_AUTHTYPE_NONE;  	user_msg = (char *)NULL;  	check_item = user_check;	result = allow_user(authreq->name);	if (result != 0) {	  result = deny_user(authreq->name);	  if (result != 0) {		log_err("auth: denied connection for '%s' (listed in '%s/%s')",			authreq->name,radius_dir,			(result==-2)?"denyusers":"stopusers");	  }	}  	while(result == 0 && check_item != (VALUE_PAIR *)NULL) {  		auth_item = get_attribute(authreq->request,  						check_item->attribute);    		switch(check_item->attribute) {  		case PW_PREFIX:  		case PW_SUFFIX:  			break;  		case PW_EXPIRATION:  			/*  			 * Check expiration date if we are  			 * doing password aging.  			 */#if defined(SHADOW_EXPIRATION) 			if (!strncasecmp(check_item->strvalue,"SHADOW", 6))                        	retval = shadow_expired(authreq->name);                     	else#endif  				retval = pw_expired(check_item->lvalue);  			if(retval < 0) {  				result = -2;  				snprintf(umsg,sizeof(umsg),"Password Has Expired\r\n");  				user_msg = umsg;                       		log_err("auth: Password expired for '%s'\n",authreq->name);  			} else {  				if(retval > 0) {  					snprintf(umsg,(size_t)(AUTH_STRING_LEN)+2,"Password Will Expire in %d Days\r\n",  					  retval);  					user_msg = umsg;                            		log_err("auth: Password for '%s' will expire in %d days\n", retval);  				}  			}  			break;    		case PW_PASSWORD:  			if(strcmp(check_item->strvalue, "UNIX") == 0) {  				authtype = PW_AUTHTYPE_UNIX;  			}  			else {  				authtype = PW_AUTHTYPE_LOCAL;  				password_item = check_item;  			}  			break;  		case PW_AUTHTYPE:  			authtype = check_item->lvalue;  			break;    		case PW_GROUP:  			if(!unix_group(auth_name, check_item->strvalue)) {  				result = -1;  			}  			break;  		case PW_CRYPT_PASSWORD:  			authtype = PW_AUTHTYPE_CRYPT;  			password_item = check_item;  			break;  /** FIXME 	This is a problem for Yard.	Connect-Info or Connect-Info-Old are often not used by	non-Livingston boxes, so this check item is unuseful.	Ascend and USR boxes uses their VSAs to register connection	speed. Cisco too. Not RFC compliant at this moment.**/		case PW_CONNECT_RATE:                      	auth_item = get_attribute(authreq->request,  					      PW_CONNECT_INFO);         	        if (auth_item != (VALUE_PAIR *)NULL) {                 	       	if ( sscanf(auth_item->strvalue,"%d/%*d%*s",&speed)==1|| (speed=atoi(auth_item->strvalue)) ) 				  if ( speed>check_item->lvalue ) result=-1;                     	} else {                        	auth_item = get_attribute(authreq->request,                                                   PW_CONNECT_INFO_OLD);                         	if (auth_item != (VALUE_PAIR *)NULL) {                            		speed = atoi(auth_item->strvalue);                            		if (speed > check_item->lvalue) result=-1;                         	}                     	   }                     	   break;#if defined(PAM) && defined(HAVE_LIBPAM)                case PW_PAM_AUTH:                	pam_auth = check_item->strvalue;                     	break;#endif        	case PW_LOGINS:                	retval = check_logins(auth_name, check_item->lvalue);                     	if (retval != 0) {                       		result = -2;                       		snprintf(umsg,(size_t)(AUTH_STRING_LEN+2),"Too many logins - max %d\r\n",(unsigned int)check_item->lvalue);                       		user_msg = umsg;                       		log_err("Too many logins for '%s' (max %d)\n",authreq->name,(unsigned int)check_item->lvalue);                       	}                       	break;                case PW_MAXDTIME:                     retval = check_maxtime(auth_name,check_item->lvalue,DAY_LIMIT);                     if (retval != 0) {                         result = -2;                         snprintf(umsg,sizeof(umsg),"Total on-line daily time expired (%d hours)\r\n",(unsigned int)check_item->lvalue);                         user_msg = umsg;                         log_err("Total on-line daily time expired (%d hours) for '%s'\n", (unsigned int)check_item->lvalue, authreq->name);                     }                     break;                 case PW_MAXMTIME:                     retval = check_maxtime(auth_name,check_item->lvalue,MONTH_LIMIT);                     if (retval != 0) {                         result = -2;                         snprintf(umsg,sizeof(umsg),"Total on-line time expired (%d hours)\r\n", (unsigned int)check_item->lvalue);                         user_msg = umsg;                         log_err("Total on-line time expired (%d hours) for '%s'\n", (unsigned int)check_item->lvalue, authreq->name);                     }                     break;                 case PW_MAXYTIME:                     retval = check_maxtime(auth_name,check_item->lvalue,YEAR_LIMIT);                     if (retval != 0) {                         result = -2;                         snprintf(umsg,sizeof(umsg),"Total on-line yearly time expired (%d hours)\r\n", (unsigned int)check_item->lvalue);                         user_msg = umsg;                         log_err("Total on-line yearly time expired (%d hours) for '%s'\n", (unsigned int)check_item->lvalue, authreq->name);                     }                     break;                 case PW_TIME:                     retval = allowed_time(check_item->strvalue);                     if (retval != 0) {                         result = -2;                         snprintf(umsg,sizeof(umsg),"Not allowed to login at this time\r\n");                         user_msg = umsg;                         log_err( "Not allowed to login at this time for '%s'\n",authreq->name );                     }                     break;                 case PW_MAXDTRAFFIC:                     retval = check_maxtraffic(auth_name,check_item->lvalue,DAY_LIMIT);                     if (retval != 0) {                         result = -2;                         snprintf(umsg,sizeof(umsg),"Maximum allowed daily traffic size reached (%d KB)\r\n",(unsigned int)check_item->lvalue);                         user_msg=umsg;                         log_err("Maximum allowed daily traffic size reached (%dKB) for '%s'\r\n", (unsigned int)check_item->lvalue, authreq->name);                     }                     break;                 case PW_MAXMTRAFFIC:                     retval = check_maxtraffic(auth_name,check_item->lvalue,MONTH_LIMIT);                     if (retval != 0) {                         result = -2;                         snprintf(umsg,sizeof(umsg),"Maximum allowed monthly traffic size reached (%d KB)\r\n", (unsigned int)check_item->lvalue);                         user_msg=umsg;                         log_err("Maximum allowed monthly traffic size reached (%d KB) for '%s'\r\n", (unsigned int)check_item->lvalue, authreq->name);                     }                     break;                 case PW_MAXYTRAFFIC:                     retval = check_maxtraffic(auth_name,check_item->lvalue,YEAR_LIMIT);                     if (retval != 0) {                         result = -2;                         snprintf(umsg,sizeof(umsg),"Maximum allowed yearly traffic size reached (%d KB)\r\n", (unsigned int)check_item->lvalue);                         user_msg=umsg;                         log_err("Maximum allowed yearly traffic size reached (%d KB) for '%s'\r\n", (unsigned int)check_item->lvalue, authreq->name);                     }                     break;  		default:  			if(auth_item == (VALUE_PAIR *)NULL) {  				result = -1;  				break;  			}  			switch(check_item->type) {  			case PW_TYPE_STRING:  				if(strcmp(check_item->strvalue,  					  auth_item->strvalue) != 0) {  					result = -1;  				}  				break;  			case PW_TYPE_INTEGER:  			case PW_TYPE_IPADDR:  				if(check_item->lvalue  						!= auth_item->lvalue) {  					result = -1;  				}  				break;  			default:  				result = -1;  				break;  			}  			break;  		}  		check_item = check_item->next;  	}  	if (result != -1) {  		break;  	}  	pairfree(user_check,"rad_authenticate");  	pairfree(user_reply,"rad_authenticate");  }  user_close(user_desc);  /*   * At this point we have validated all normal comparisons   * for the user.  All that is left is the actual authentication.   * Authentication will be done based on the authentication type   * previously specified.   */  if(result == 0) {  	/*  	 * Decrypt the password in the request.  	 */  	pass = decrypt_password(authreq,authreq->secret);  	if (pass != (char *)NULL) {  		strncpy(string,pass,AUTH_STRING_LEN);  		string[AUTH_STRING_LEN] = '\0'; /* always null-term */  	}  	else {  		string[0] = '\0';  	}  	switch(authtype) {  	case PW_AUTHTYPE_LOCAL:  		/*  		 * The local authentication type supports normal  		 * password comparison and the Three-Way CHAP.  		 */  		if (password_item == (VALUE_PAIR *)NULL) {  			log_err("Warning: entry for user \"%s\" is missing Password check item\n",authreq->name);  			result = -1;  		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -