edauth.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,199 行 · 第 1/2 页

C
1,199
字号
#ifndef lintstatic  char    *sccsid = "@(#)edauth.c	4.3  (ULTRIX)        11/13/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1989, 1990 by			* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * Modification History * * 04-Sep-1990	dlong *	Added "-p protouser" option, support for AUDIT_USER, and use the *	library routine getopt(). * * 12-Nov-1990	scott *	Added AUDIT_USR to output_aud */#include <sys/wait.h>#include <sys/file.h>#include <sys/audit.h>#include <sys/time.h>#include <signal.h>#include <time.h>#include <nlist.h>#include <limits.h>#include <stdio.h>#include <pwd.h>#include <auth.h>#define AUD_BUF_LEN (SYSCALL_MASK_LEN+TRUSTED_MASK_LEN)#define	SUCCEED		1#define	FAIL		0/* * Code to convert a date back into time(2) format. */#define	dysize(A) (((A)%4)? 365: 366)static	int	dmsize[12] =    { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };/* * Add up the seconds since the epoch */long julian_second(year, month, day, hour, minute, second)int year, month, day, hour, minute, second;{	long jtime=0;	int i;	if(year < 100)		year += 1900;	for (i = 1970; i < year; i++)		jtime += dysize(i);	/* 	 * Leap year 	 */	if (dysize(year) == 366 && month >= 3)		jtime++;	/*	 * Do the current year	 */	while (--month)		jtime += dmsize[month-1];	jtime += day-1;	jtime = 24*jtime + hour;	jtime = 60*jtime + minute;	jtime = 60*jtime + second;	return jtime;}/* * Module-wide definitions and declarations. */typedef struct passwd PWD;extern char *strchr();static char *progname = "???";static AUTHORIZATION authsave;struct nlist nlst[] = {    { "_nsysent" },#define X_NSYSENT      0    { 0 },};char *special_event[] = {    "shmget",    "shmdt",    "shmctl",    "shmat"};/* * Function to check a string and return success if all digits. */static int alldigits(s)register char *s;{	register c;	c = *s++;	do {		if (!isdigit(c))			return (0);	} while (c = *s++);	return (1);}/* * Function to convert a username or uid into a uid. */static int getuser(user)char *user;{	PWD *pwd;	int uid;/* * Look it up first to see if it's in the passwd file. */	setpwent();	pwd = getpwnam(user);	if(!pwd) {/* * If not in the passwd file see if it's an integer uid. */		if(alldigits(user))			uid = atoi(user);		else			uid = -1;	} else/* * Otherwise return the uid field from the passwd file entry. */		uid = pwd->pw_uid;	return uid;}/* * Function to remove leading and trailing white space from a string. * Returns a pointer to the first non-white character in the string. */static char *trim(s)char *s;{	char *start, *end, *strpbrk();	int i;/* * Skip over leading white space. */	start = s + strspn(s, " \t");	i = strlen(start);/* * Step from back to front while still encountering white-space characters. */	for(end=start+i-1; i; i--) {		if(!strchr(" \t", *end))			break;		*end-- = '\0';	}/* * Return pointer to first non-white character in string. */	return start;}extern char *strtok();/* * Function to read a number using the string initialized in strtok(). * If successful returns non-zero and stores the number in the integer * pointed to by the argument.  Otherwise returns zero and strores zero in * the location pointed to by the argument. */static int getnum(i)int *i;{	char *s;	if(s=strtok(NULL, " \t\n")) {		s = trim(s);		if(*s && alldigits(s)) {			*i = atoi(s);			return SUCCEED;		}	}	*i = 0;	return FAIL;}/* * Internal function to safely get a line from the named stream.  If * the line is too long to fit into the buffer it is thrown away and a * new line is fetched until successful or end-of-file. */static char *fgetline(string, len, file)char *string;int len;FILE *file;{	register char *s;	int c, i=0, j;/* * Keep trying until successful or end-of-file. */	while(s=fgets(&string[i], len, file)) {		j = strlen(s);		len -= j;		i += j;/* * If not a complete line throw it away and go to the next line. */		if(!strchr(s, '\n')) {			while((c=getc(file)) != EOF && c != '\n') ;			break;		}/* * If line ends in backslash-newline, get next line and concatenate. */		if(i >= 2 && s[j-2] == '\\') {			i -= 2;			len += 2;		} else			break;	}	if(s)		return s;	else		return NULL;}/* Parsing functions *//* set auth auditmask */#define REQ_LEN 32extern char *syscallnames[];extern char *trustedevent[];/* * Function to convert a value subfield from an audit event token into * the appropriate value. */static int event_value(string)char *string;{	switch(*string) {	case '0':		return FAIL;	case '1':		return SUCCEED;	default:		return -1;	}}/* * Function to add an audit event into the appropriate audit mask. */static int change_audit(amask, event)char *amask;char *event;{	char flags, *value;	int nsyscalls;	int i;/* * Process event and get value fields if present. */	if(value=strchr(event, ':')) {		*value++ = '\0';		if((i=event_value(value)) >= 0) {			flags = i << 1;			if(value=strchr(value, ':')) {				value++;				if((i=event_value(value)) >= 0)					flags |= i;				else {					fputs("Error, bad value for event fail flag, must be 0 or 1\n", stderr);					return FAIL;				}			}		} else {			fputs("Error, bad value for event success flag, must be 0 or 1\n", stderr);			return FAIL;		}	} else/* * No value fields present, default to both success and fail. */		flags = 0x3;/* * get # syscalls by reading kernel. */	nsyscalls = getkval (X_NSYSENT);	if (nsyscalls == -1) {		perror ("failed");		exit(1);	}/* * set syscall event. */	for (i = 0; i < nsyscalls; i++)		if (strcmp (event, syscallnames[i]) == 0) {			A_PROCMASK_SET (amask, i, (flags&0x2)>>1, flags&0x1);			return SUCCEED;		}/* * kludge for shmsys operations. */	for (i = 0; i < 4; i++)		if (strcmp (event, special_event[i]) == 0) {			A_PROCMASK_SET (amask, (N_SYSCALLS-4+i), (flags&0x2)>>1, flags&0x1);			return SUCCEED;		}/* * set trusted event. */	for (i = 0; i < N_TRUSTED_EVENTS; i++)		if (strcmp (event, trustedevent[i]) == 0) {			A_PROCMASK_SET (amask, i+MIN_TRUSTED_EVENT, (flags&0x2)>>1, flags&0x1);			return SUCCEED;		}/* * invalid event. */	if (i == N_TRUSTED_EVENTS) {		fputs("Error, can't find audit event \"", stderr);		fputs(event, stderr);		fputs("\"\n", stderr);	}	return FAIL;}/* * Function to read and parse an ASCII duration value.  Duration may be * specified as time in seconds, minutes, hours, days, or a combination * of all of the preceeding.  The default for unlabelled time values is * seconds.  If the function returns non-zero if successful, zero otherwise. * The result is the time duration in seconds and is stored into the integer * variable pointed to by the argument. */static int get_time(i)int *i;{	char *s;	int total=0, j;	if(!getnum(&j))		return FAIL;	do {		if(s=strtok(NULL, " \t\n")) {			s = trim(s);			switch(*s) {/* * Days. */			case 'd':			case 'D':				total += j * (60*60*24);				break;/* * Hours. */			case 'h':			case 'H':				total += j * (60*60);				break;/* * Minutes. */			case 'm':			case 'M':				total += j * 60;				break;/* * Seconds. */			case 's':			case 'S':				total += j;				break;/* * Unrecognized value label. */			default:				return FAIL;			}		} else {/* * Default to seconds. */			total += j;			break;		}	} while(getnum(&j));	*i = total;	return SUCCEED;}/* * Read in an ASCII representation of the auth record for a user, parsing it * into a binary representation.  The open file is the first argument, and the * binary output record is pointed to by the second argument. */parse(file, auth)FILE *file;AUTHORIZATION *auth;{	char line[4097];	char *s, pw_flag, pwmin_flag, pwmax_flag, pwmod_flag, am_flag;	char aid_flag, ac_flag, uid_flag, fc_flag;	int i;/* * Initialize flags used to catch missing mandatory fields. */	pw_flag = pwmin_flag = pwmax_flag = pwmod_flag = am_flag = 0;	aid_flag = ac_flag = uid_flag = fc_flag = 0;/* * Parse the file. */	while(fgetline(line, sizeof line, file)) {/* * Reject comment lines */	s = line + strspn(line, " \t\n");	if(!*s || *s == '#')		continue;/* * Get first token */	if(!(s=strtok(line, "="))) {		fputs("Error, bad line in file\n", stderr);		return FAIL;	}#ifdef	DEBUGfputs("first token = ", stderr);fputs(s, stderr);putc('\n', stderr);fflush(stderr);#endif	DEBUG/* * Process token value(s) */	s = trim(s);	if(!strcmp(s, "fail_count")) {		fc_flag = 1;		if(!getnum(&i)) {			i = authsave.a_fail_count;			fprintf(stderr, "Warning bad or missing fail_count value, setting to %d\n", i);		}		auth->a_fail_count = i;	} else	if(!strcmp(s, "audit_id")) {		aid_flag = 1;		if(getnum(&i) && i > 0)			auth->a_audit_id = i;		else {			fputs("Error, bad or missing audit_id value\n", stderr);			return FAIL;		}	} else	if(!strcmp(s, "audit_syscalls") || !strcmp(s, "audit_tevents")) {		while(s=strtok(NULL, ",\n")) {			s = trim(s);			if(*s)				if(!change_audit(auth->a_audit_mask, s)) {					fputs("Error in audit event \"", stderr);					fputs(s, stderr);					fputs("\"\n", stderr);					return FAIL;				}		}	} else	if(!strcmp(s, "uid")) {		uid_flag = 1;		if(getnum(&i) && i <= UID_MAX && i >= -UID_MAX)			auth->a_uid = i;		else {			fputs("Error, bad or missing uid value\n", stderr);			return FAIL;		}	} else	if(!strcmp(s, "password")) {		pw_flag = 1;		if(s=strtok(NULL, " \t\n"))			s = trim(s);		else			s = "";		bzero(auth->a_password, sizeof auth->a_password);		strncpy(auth->a_password, s, sizeof auth->a_password);	} else	if(!strcmp(s, "passmod")) {		int month, day, year, hour, minute, second;		long jtime;		hour = minute = second = 0;		pwmod_flag = 1;		if(s=strtok(NULL, "\n"))			s = trim(s);		if(s && !strcmp(s, "epoch"))			jtime = 0;		else if(s && sscanf(s, "%d/%d/%d - %d:%d:%d",		    &month, &day, &year, &hour, &minute, &second) >= 3) {			extern long julian_second();			extern struct tm *localtime();			struct timeval tv;			struct timezone tz;			jtime = julian_second(year, month, day, hour, minute, second);			gettimeofday(&tv, &tz);			jtime += tz.tz_minuteswest*60;			if(localtime(&jtime)->tm_isdst)				jtime -= 60*60;		} else {			jtime = authsave.a_pass_mod;			fputs("Warning, bad or missing passmod value, setting to ", stderr);			if(jtime)				fputs(ctime(&jtime), stderr);			else				fputs("epoch\n", stderr);		}		auth->a_pass_mod = jtime;	} else	if(!strcmp(s, "passlifemin")) {		pwmin_flag = 1;		if(!get_time(&i)) {			i = authsave.a_pw_minexp;			fprintf(stderr, "Warning, bad or missing passlifemin value, setting to %d\n", i);		}		auth->a_pw_minexp = i;	} else	if(!strcmp(s, "passlifemax")) {		pwmax_flag = 1;		if(!get_time(&i)) {			i = authsave.a_pw_maxexp;			fprintf(stderr, "Warning, bad or missing passlifemax value, setting to %d\n", i);		}		auth->a_pw_maxexp = i;	} else	if(!strcmp(s, "audit_control")) {		ac_flag = 1;		s = strtok(NULL, " \t\n");		s = trim(s);		if(!strcmp(s, "or"))			auth->a_audit_control = AUDIT_OR;		else if(!strcmp(s, "and"))			auth->a_audit_control = AUDIT_AND;		else if(!strcmp(s, "off"))			auth->a_audit_control = AUDIT_OFF;		else if(!strcmp(s, "user"))			auth->a_audit_control = AUDIT_USR;		else {			fputs("Error, invalid audit_control value\n", stderr);			return FAIL;		}	} else	if(!strcmp(s, "authmask")) {		am_flag = 1;		while(s=strtok(NULL, ",\n")) {			s = trim(s);			if(*s)				if(!strcmp(s, "login"))					auth->a_authmask |= A_LOGIN;				else if(!strcmp(s, "change_password"))

⌨️ 快捷键说明

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