edauth.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,199 行 · 第 1/2 页
C
1,199 行
auth->a_authmask |= A_CHANGE_PASSWORD; else if(!strcmp(s, "enter_password")) auth->a_authmask |= A_ENTER_PASSWORD; else { fputs("Error, invalid authmask value \"", stderr); fputs(s, stderr); fputs("\"\n", stderr); return FAIL; } } } else { fputs("Warning, unrecognized keyword \"", stderr); fputs(s, stderr); fputs("\" in temp file\n", stderr); } }/* * Analyze results. Report missing or inconsistant values. */ if(!*auth->a_password) fputs("Warning, no password\n", stderr); if(pwmax_flag && !auth->a_pw_maxexp) fputs("Warning, no password expiration\n", stderr); if(!pwmin_flag) { fputs("Warning, missing passlifemin entry, setting to zero\n", stderr); auth->a_pw_minexp = 0; } if(!pwmod_flag) { fputs("Warning, missing passmod entry, setting to zero\n", stderr); auth->a_pass_mod = 0; } if(!fc_flag) { fputs("Warning, missing fail_count entry, setting to zero\n", stderr); auth->a_fail_count = 0; } if(!uid_flag) { fputs("Error, missing uid entry\n", stderr); return FAIL; } if(!aid_flag) { fputs("Error, missing audit_id entry\n", stderr); return FAIL; } if(!ac_flag) { fputs("Error, missing audit_control entry\n", stderr); return FAIL; } if(!pwmax_flag) { fputs("Error, missing passlifemax entry\n", stderr); return FAIL; } if(!am_flag) { fputs("Error, missing authmask entry\n", stderr); return FAIL; } return SUCCEED;}/* link with /sys/`machine`/BINARY/{syscalls.o,trustedevents.o} *//* get integer value from kernel */static int getkval(var)int var;{ static int vm_fd = -1; static int km_fd; int i = 0; if(vm_fd == -1) { if((vm_fd = open("/vmunix", 0)) == -1) return -1; if((km_fd = open("/dev/kmem", 0)) == -1) return -1; nlist("/vmunix", nlst); if(nlst[0].n_type == 0) return -1; } if(lseek(km_fd, nlst[var].n_value, 0) == -1) return -1; if(read(km_fd, &i, sizeof (int)) != sizeof (int)) return -1; else return i;}/* * Function to output an audit event value. */static void put_audit_value(value, file)int value;FILE *file;{ switch(value) { case 3: break; case 2: fputs(":1", file); break; case 1: fputs(":0:1", file); break; case 0: default: fputs(":0:0", file); break; }}/* * Function to output the audit information of the record. */static void output_aud(file, acntl, amask)FILE *file;char acntl;char *amask;{ extern char *syscallnames[]; extern char *trustedevent[]; int nsyscalls, audit_flag; int i, j, k;/* * Output acntl flag value. */ fputs("audit_control = ", file); if(acntl & AUDIT_OFF) fputs("off\n", file); else if(acntl & AUDIT_AND) fputs("and\n", file); else if(acntl & AUDIT_USR) fputs("user\n", file); else fputs("or\n", file);/* * Get # syscalls. */ nsyscalls = getkval(X_NSYSENT); if ( nsyscalls == -1) { perror ( "nsyscalls failed"); return; }/* * Display syscall mask */ fputs("audit_syscalls = ", file); i = 0; for(j = 0; j < SYSCALL_MASK_LEN; j++) for(k = 0; k < 8; k+=2) { if((j<<2)+(k>>1) >= nsyscalls) break; if(amask[j] &(0x3 <<(6-k%8))) { if(i) putc(',', file); if(!((++i)%6)) fputs("\\\n\t", file); fputs(syscallnames[(j<<2)+(k>>1)], file); audit_flag = 0; audit_flag = amask[j] &(0x2 <<(6-k%8)) ? 2 : 0; audit_flag |= amask[j] &(0x1 <<(6-k%8)) ? 1 : 0; put_audit_value(audit_flag, file); } }/* * Kludge for shmsys operations */ j =(N_SYSCALLS*2)/8 - 1; for(k = 0; k < 8; k+=2) if(amask[j] &(0x3 <<(6-k%8))) { if(i) putc(',', file); if(!((++i)%6)) fputs("\\\n\t", file); fputs(special_event[k>>1], file); audit_flag = 0; audit_flag = amask[j] &(0x2 <<(6-k%8)) ? 2 : 0; audit_flag |= amask[j] &(0x1 <<(6-k%8)) ? 1 : 0; put_audit_value(audit_flag, file); } putc('\n', file);/* * Display trusted event mask */ fputs("audit_tevents = ", file); i = 0; for(j = SYSCALL_MASK_LEN; j < SYSCALL_MASK_LEN+TRUSTED_MASK_LEN; j++) for(k = 0; k < 8; k+=2) { if(amask[j] &(0x3 <<(6-k%8))) { if(i) putc(',', file); if(!((++i)%8)) fputs("\\\n\t", file); fputs(trustedevent[((j-SYSCALL_MASK_LEN)<<2)+(k>>1)], file); audit_flag = 0; audit_flag = amask[j] &(0x2 <<(6-k%8)) ? 2 : 0; audit_flag |= amask[j] &(0x1 <<(6-k%8)) ? 1 : 0; put_audit_value(audit_flag, file); } } putc('\n', file);}/* * Function to display an integer value followed by a unit label. */static void put_unit(i, s, file)int i;char *s;FILE *file;{ fprintf(file, " %d %s", i, s); if(i > 1) putc('s', file);}/* * Function to output a time duration value broken down into units. */static void put_time(i, file)int i;FILE *file;{ int j;/* * If less than a minute output unlabelled value (seconds). */ if(i < 60) { fprintf(file, " %d\n", i); return; }/* * If greater than a day output integral days. */ if(j=i/(60*60*24)) { put_unit(j, "day", file); i %= (60*60*24); }/* * If remainder is greater than an hour, output integral hours. */ if(j=i/(60*60)) { put_unit(j, "hour", file); i %= (60*60); }/* * If remainder is greater than a minute, output integral minutes. */ if(j=i/60) { put_unit(j, "minute", file); i %= 60; }/* * Output remaining seconds, if any. */ if(i) { put_unit(i, "second", file); } putc('\n', file);}/* * Function to convert a binary auth record into a human readable but still * machine parsable ASCII representation. */unparse(file, auth)FILE *file;AUTHORIZATION *auth;{ struct tm *tm; int i, j; fprintf(file, "uid = %d\n", auth->a_uid); fputs("password = ", file); fputs(auth->a_password, file); putc('\n', file); fputs("passlifemin =", file); put_time(auth->a_pw_minexp, file); fputs("passlifemax =", file); put_time(auth->a_pw_maxexp, file); if(auth->a_pass_mod > 0) { tm = localtime(&auth->a_pass_mod); fprintf(file, "passmod = %02d/%02d/%02d - %02d:%02d:%02d\n", tm->tm_mon+1, tm->tm_mday, tm->tm_year%100, tm->tm_hour, tm->tm_min, tm->tm_sec); } else fputs("passmod = epoch\n", file); fputs("authmask = ", file); j = 0; for(i=0; i < (sizeof auth->a_authmask)*8; i++) { if(auth->a_authmask & (1<<i)) { if(j++) fputc(',',file); switch(i) { case 0: fputs("login", file); break; case 1: fputs("change_password", file); break; case 2: fputs("enter_password", file); break; default: ; } } } putc('\n', file); fprintf(file, "fail_count = %d\n", auth->a_fail_count); fprintf(file, "audit_id = %d\n", auth->a_audit_id); output_aud(file, auth->a_audit_control, auth->a_audit_mask);#ifdef PRIV fputs("privileges = ?\n", file);#endif PRIV}/* * Function to unparse a binary auth record and put it into a new temporary * file. The file name is returned as the value of the function. If the * function fails it returns the NULL pointer. */static char *putinfile(auth)AUTHORIZATION *auth;{ static char *filename; extern char *mktemp(); FILE *file; filename = mktemp("/tmp/edauth.XXXXXX"); if(!(file=fopen(filename, "w"))) return (char *) NULL; unparse(file, auth); if(fclose(file) == EOF) return (char *) NULL; else return filename;}/* * Function to read the named file and parse the data into a binary auth * record. If the function is successful it returns a pointer to a static * area containing the auth record. Otherwise it returns the NULL pointer. */static AUTHORIZATION *getfromfile(filename)char *filename;{ char line[1024]; FILE *file; static AUTHORIZATION auth; if(!(file=fopen(filename, "r"))) { fputs("Unable to reopen tmp file.\n", stderr); exit(1); } if(parse(file, &auth)) { fclose(file); return &auth; } else { fclose(file); return (AUTHORIZATION *) NULL; }}/* * Function to edit an auth record. */AUTHORIZATION *editit(auth)AUTHORIZATION *auth;{ static char def_editor[] = "/bin/ed"; union wait status; int pid; char *editor, *filename, *getenv(); char line[BUFSIZ];/* * Put ASCII representation of record into a new temporary file. */ filename = putinfile(auth);/* * Edit the file with the editor of choice until successful. */ while(1) { fflush(stdout); fflush(stderr); signal(SIGINT, SIG_IGN); pid = fork(); if(pid < 0) { perror(progname); exit(1); } if(pid) { wait(&status); } else { signal(SIGINT, SIG_DFL); if(!(editor=getenv("EDITOR"))) editor = def_editor; execlp(editor, editor, filename, 0); exit(1); } signal(SIGINT, SIG_DFL);/* * Get the record from the file and convert to binary. */ auth = getfromfile(filename);/* * If problems give the user another shot at fixing it up. */ if(!auth) { fputs("Error in file, do you wish to resume editing?> ", stdout); if(fgetline(line, sizeof line, stdin)) if(*line == 'y' || *line == 'Y') continue; break; } else break; }/* * Dispose of temporary file. */ unlink(filename); if(!auth || (status.w_status&0xffff)) return (AUTHORIZATION *) NULL; else return auth;}/* * Print an error message. */static void audevent(statustr, status)char *statustr;int status;{ char tmask[AUD_NPARAM]; struct { char *a; int b; } aud_arg; int i;/* * Build token mask. */ tmask[0] = T_CHARP; if(status == 0) tmask[1] = T_RESULT; else tmask[1] = T_ERROR; tmask[2] = '\0'; aud_arg.a = statustr; aud_arg.b = status;/* * Generate audit record. */ if(audgen(AUTH_EVENT, tmask, &aud_arg) == -1 ) perror("audgen" );}/* * Error termination function. */static void getout(statustr, status)int status;char *statustr;{ if(statustr) { audevent(statustr, status); fputs(statustr, stderr); putc('\n', stderr); } exit(status);}static char usage[] = "usage: edauth [-p protouser] username";main(argc, argv)/* * The main event. */int argc;char *argv[];{ AUTHORIZATION authorization, *auth; int uid, protouid, pflag=0, c; char user[17], protouser[17], buf[AUD_BUF_LEN]; extern int optind; extern char *optarg;/* turn off auditing of all events except for LOGIN and failed setgroups */ if ( audcntl (SET_PROC_ACNTL, (char *)0, 0, AUDIT_AND, 0) == -1) perror ( "audcntl" ); A_PROCMASK_SET ( buf, AUTH_EVENT, 1, 1 ); if (audcntl(SET_PROC_AMASK, buf, AUD_BUF_LEN, 0, 0) == -1 ) perror ( "audcntl" ); if(argc > 0) progname = argv[0]; while((c=getopt(argc, argv, "p:")) != EOF) switch(c) { case 'p': pflag = 1; strncpy(protouser, optarg, sizeof protouser); break; default: getout(usage, 1); } if(optind == (argc-1)) strncpy(user, argv[optind], sizeof user); else { getout(usage, 1); } umask(077); if(pflag) if((protouid=getuser(protouser)) == -1) getout("Protouser not found in passwd data base.", 1); if((uid=getuser(user)) == -1) { getout("User not found in passwd data base.", 1); } if(open_auth(AUTHORIZATION_DB, O_RDWR)) { getout("Unable to open auth data base.", 1); }/* * Get auth record. */ if(pflag) { if(get_auth(protouid, &authorization) < 0) getout("Protouser not found in auth data base.", 1); } else if(get_auth(uid, &authorization) < 0) getout("User not found in auth data base.", 1);/* * Save the record from the static area used in getauthent(). */ auth = &authorization; bcopy(auth, &authsave, sizeof (AUTHORIZATION));/* * If creating from protouser, set the new UID and clear the audit ID. */ if(pflag) { authorization.a_uid = uid; authorization.a_audit_id = 0; authorization.a_fail_count = 0; }/* * Don't leave the auth files open when giving the user their editor. */ close_auth(); if(!(auth=editit(auth))) { getout("Edit failed.", 1); }/* * If the record didn't change at all don't do anything. */ if(!bcmp(auth, &authsave, sizeof (AUTHORIZATION))) { getout("Record unchanged.", 0); } if(open_auth(AUTHORIZATION_DB, O_RDWR)) { getout("Unable to reopen auth data base.", 1); }/* * If the UID field of the record changed we have to take special action. * This is because the UID is the key into the data base. If we just * stored out the new record the old one would also still be around. So we * must delete the record stored undewr the old UID first. */ if(auth->a_uid != authsave.a_uid) { char buf[100]; sprintf(buf, "Warning, changing UID from %d to %d", authsave.a_uid, auth->a_uid); fputs(buf, stderr); putc('\n', stderr); if(delete_auth(authsave.a_uid) < 0) { getout("Unable to remove old entry.", 1); } audevent(buf, 0); }/* * Store out new record. */ bcopy(auth, &authsave, sizeof (AUTHORIZATION)); auth = &authsave; if(storeauthent(auth) < 0) { close_auth(); getout("Failed to store new entry.", 1); } else { char buf[100]; close_auth(); sprintf(buf, "Updated auth entry for uid %d.", auth->a_uid); getout(buf, 0); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?