417 lines
9.6 KiB
C
417 lines
9.6 KiB
C
#ifndef lint
|
|
static char *sccsid = "@(#)audit.c 1.1 94/10/31 SMI"; /* Copywr SunMicro */
|
|
#endif
|
|
|
|
#include <stdio.h>
|
|
#include <sys/file.h>
|
|
#include <sys/errno.h>
|
|
#include <sys/signal.h>
|
|
#include <sys/param.h>
|
|
#include <sys/label.h>
|
|
#include <sys/audit.h>
|
|
#include <pwdadj.h>
|
|
#include <pwd.h>
|
|
|
|
|
|
#define USERTEMP 0 /* change kernel audit flags - only temp. */
|
|
#define SIGREAD 1 /* notify audit kernel to read audit_control file */
|
|
#define SIGNEXT 2 /* notify audit kernel to use next audit directory */
|
|
#define USERPERM 3 /* change kernel audit flags based on passwd.adjunct
|
|
and audit_control for inputted user names */
|
|
#define AUDITOFF 4 /* disable auditing */
|
|
#define UARGNUM 4 /* number of -u arguments */
|
|
#define MAXARG 10 /* max. number of users specified on command line */
|
|
|
|
static char AUDITDATAFILE[] = "/etc/security/audit/audit_data";
|
|
|
|
/* GLOBALS */
|
|
int operation = -1;
|
|
int audit_error = 0;
|
|
char *sprintf();
|
|
char *audit_argv[] = { "audit", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
extern int errno;
|
|
extern char *sys_errlist[];
|
|
|
|
/* audit.c - audit control file operations */
|
|
|
|
/*
|
|
* audit() - This program serves as a general administrator's interface to
|
|
* the audit trail.
|
|
*
|
|
* input: audit -d username(s) - change kernel version of event flags
|
|
* for "username{s}" based on passwd
|
|
* adjunct and audit_control file.
|
|
* audit -s - signal audit daemon to read
|
|
* audit_control file.
|
|
* audit -n - signal audit daemon to use next
|
|
* audit_control audit directory.
|
|
* audit -u username auditflags - change kernel version of users
|
|
* audit flags.
|
|
* audit -t - signal audit daemon to disable auditing.
|
|
*
|
|
* output:
|
|
*
|
|
* returns: 0 - entry read ok
|
|
* -1 - error
|
|
* 1 - end of file
|
|
*/
|
|
|
|
main(argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
int i, j, max, retstat = 0, saveargc;
|
|
char **initargv, *names[MAXARG];
|
|
|
|
/*
|
|
* set up audit record
|
|
*/
|
|
saveargc = argc+1;
|
|
max = MAXARG+2;
|
|
initargv = argv;
|
|
for (i=1, j=2; i<argc && j<max; i++, j++)
|
|
audit_argv[j] = argv[i];
|
|
argv = initargv;
|
|
|
|
if (i != argc) {
|
|
retstat = -2;
|
|
saveargc = max;
|
|
}
|
|
/*
|
|
* get input
|
|
*/
|
|
if ((retstat != -2 &&
|
|
(retstat = ac_getinput(&argc, argv, names)) == 0)) {
|
|
switch(operation) {
|
|
case USERTEMP:
|
|
retstat = ac_utemp(names);
|
|
break;
|
|
case SIGREAD:
|
|
retstat = ac_read();
|
|
break;
|
|
case SIGNEXT:
|
|
retstat = ac_next();
|
|
break;
|
|
case USERPERM:
|
|
retstat = ac_uperm(argc, names);
|
|
break;
|
|
case AUDITOFF:
|
|
retstat = ac_auditoff();
|
|
break;
|
|
default:
|
|
retstat = -2;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (retstat == -2) {
|
|
retstat = -1;
|
|
audit_argv[1] = "Invalid input";
|
|
fprintf(stderr,
|
|
"usage: audit [-s] | [-n] | [-t] | [-d username{s}] | [-u username auditflags]\n");
|
|
}
|
|
/*
|
|
* output audit record
|
|
*/
|
|
if (retstat == 0)
|
|
audit_argv[1] = "Successful";
|
|
audit_text(AU_ADMIN, audit_error, retstat, saveargc, audit_argv);
|
|
|
|
exit (retstat);
|
|
/* NOTREACHED */
|
|
}
|
|
|
|
/*
|
|
* getacinput(): Reads command line arguments.
|
|
* input: argc - number of arguments in argv
|
|
* argv - command line flags and data items.
|
|
* output: names - data items.
|
|
*/
|
|
|
|
ac_getinput(argc, argv, names)
|
|
int *argc;
|
|
char **argv;
|
|
char **names;
|
|
{
|
|
int count = 0, retstat = 0;
|
|
|
|
/*
|
|
* check for flags
|
|
*/
|
|
if ((--(*argc) > 0) && ((*++argv)[0] == '-')) {
|
|
switch((*argv)[1]) {
|
|
case 'u':
|
|
/*
|
|
* get username and new kernel audit flags
|
|
*/
|
|
if (*argc == UARGNUM - 1) {
|
|
operation = USERTEMP;
|
|
while (--(*argc) > 0)
|
|
*names++ = *++argv;
|
|
} else retstat = -2;
|
|
break;
|
|
|
|
case 's':
|
|
/*
|
|
* signal audit daemon to read audit_control file
|
|
*/
|
|
operation = SIGREAD;
|
|
break;
|
|
|
|
case 'n':
|
|
/*
|
|
* signal audit daemon to read audit_control file
|
|
*/
|
|
operation = SIGNEXT;
|
|
break;
|
|
|
|
case 't':
|
|
/*
|
|
* signal audit daemon to disable auditing
|
|
*/
|
|
operation = AUDITOFF;
|
|
break;
|
|
|
|
case 'd':
|
|
/*
|
|
* get user name(s)
|
|
*/
|
|
operation = USERPERM;
|
|
while (--(*argc) > 0) {
|
|
*names++ = *++argv;
|
|
count++;
|
|
}
|
|
if (count <= 0)
|
|
retstat = -2;
|
|
else
|
|
*argc = count;
|
|
break;
|
|
|
|
default:
|
|
retstat = -2;
|
|
break;
|
|
}
|
|
} else
|
|
retstat = -2;
|
|
|
|
if (operation == -1) retstat = -2;
|
|
return (retstat);
|
|
}
|
|
|
|
/*
|
|
* ac_utemp():
|
|
* purpose: set kernel audit event flags to user specified values
|
|
* input: *name[0] - user name
|
|
* *name[1] - kernel event flags
|
|
*
|
|
* returns: 0 - successful
|
|
* -1 - error in getting passwd entry or converting flags
|
|
*/
|
|
|
|
ac_utemp(names)
|
|
char **names;
|
|
{
|
|
int retstat = 0;
|
|
audit_state_t astate;
|
|
struct passwd *pw, *getpwnam();
|
|
|
|
astate.as_success = 0;
|
|
astate.as_failure = 0;
|
|
|
|
if ((pw = getpwnam(*names)) == NULL) {
|
|
fprintf(stderr, "audit: user, %s, invalid.\n", names[0]);
|
|
audit_argv[1] = "Invalid user name";
|
|
retstat = -1;
|
|
}
|
|
|
|
if (retstat == 0) {
|
|
if ((retstat = getauditflagsbin(*++names, &astate)) == 0) {
|
|
if ((retstat =
|
|
setuseraudit(pw->pw_uid, &astate)) != 0) {
|
|
fprintf(stderr,
|
|
"audit: Error in setting state of processes ");
|
|
fprintf(stderr, "owned by %d.\n", pw->pw_uid);
|
|
audit_argv[1] = sys_errlist[errno];
|
|
audit_error = errno;
|
|
retstat = -1;
|
|
}
|
|
} else {
|
|
retstat = -1;
|
|
fprintf(stderr, "audit: error in converting audit flags.\n");
|
|
audit_argv[1] =
|
|
"Error in converting audit flags.";
|
|
}
|
|
}
|
|
return (retstat);
|
|
}
|
|
|
|
/*
|
|
* ac_read():
|
|
* purpose: notify audit daemon to read audit control file
|
|
*
|
|
* returns: 0 - successful
|
|
* -1 - error in opening audit_data file
|
|
*/
|
|
|
|
ac_read()
|
|
{
|
|
int pid, retstat = 0;
|
|
FILE *adp;
|
|
|
|
/*
|
|
* open audit_data file
|
|
*/
|
|
if ((adp = fopen(AUDITDATAFILE, "r")) == NULL) {
|
|
fprintf(stderr, "audit: Can't open audit_data file.\n");
|
|
audit_argv[1] = "Error in audit_data open.";
|
|
retstat = -1;
|
|
} else {
|
|
/*
|
|
* get pid of audit daemon and send signal
|
|
*/
|
|
fscanf(adp, "%d", &pid);
|
|
if ((retstat = kill(pid, SIGHUP)) != 0) {
|
|
fprintf(stderr,
|
|
"audit: Can't send signal to audit daemon.\n");
|
|
audit_argv[1] = sys_errlist[errno];
|
|
audit_error = errno;
|
|
retstat = -1;
|
|
}
|
|
fclose(adp);
|
|
}
|
|
return (retstat);
|
|
}
|
|
|
|
/*
|
|
* ac_next():
|
|
* purpose: notify audit daemon to use next audit directory
|
|
*
|
|
* returns: 0 - successful
|
|
* -1 - error in opening audit_data file
|
|
*/
|
|
|
|
ac_next()
|
|
{
|
|
int pid, retstat = 0;
|
|
FILE *adp;
|
|
|
|
/*
|
|
* get audit daemon pid
|
|
*/
|
|
if ((adp = fopen(AUDITDATAFILE, "r")) == NULL) {
|
|
fprintf(stderr, "audit: Can't open audit_data file.\n");
|
|
audit_argv[1] = "Error in audit_data open.";
|
|
retstat = -1;
|
|
} else {
|
|
/*
|
|
* get pid of audit daemon
|
|
*/
|
|
fscanf(adp, "%d", &pid);
|
|
if ((retstat = kill(pid, SIGUSR1)) != 0) {
|
|
fprintf(stderr,
|
|
"audit: Can't send signal to audit daemon.\n");
|
|
audit_argv[1] = sys_errlist[errno];
|
|
audit_error = errno;
|
|
retstat = -1;
|
|
}
|
|
fclose(adp);
|
|
}
|
|
return (retstat);
|
|
}
|
|
|
|
/*
|
|
* ac_uperm():
|
|
* purpose: notify audit daemon to read audit control file
|
|
* input : count - number of users
|
|
* names - array of names of users
|
|
*
|
|
* returns: 0 - successful
|
|
* -1 - error
|
|
*/
|
|
|
|
ac_uperm(count, names)
|
|
int count;
|
|
char **names;
|
|
{
|
|
int i, retstat = 0;
|
|
audit_state_t astate;
|
|
struct passwd *pw;
|
|
struct passwd_adjunct *apw;
|
|
|
|
astate.as_success = 0;
|
|
astate.as_failure = 0;
|
|
|
|
/*
|
|
* for each user
|
|
*/
|
|
for (i=0; i < count; i++, ++names) {
|
|
if ((pw = getpwnam(*names)) == NULL) {
|
|
fprintf(stderr,"audit: user, %s, invalid.\n", names[0]);
|
|
audit_argv[1] = "Invalid user name";
|
|
retstat = -1;
|
|
} else if ((apw = getpwanam(*names)) == NULL) {
|
|
fprintf(stderr, "audit: user, %s, invalid.\n", names[0]);
|
|
audit_argv[1] = "Invalid user name";
|
|
retstat = -1;
|
|
}
|
|
|
|
if (retstat == 0) {
|
|
if ((getfauditflags(&apw->pwa_au_always,
|
|
&apw->pwa_au_never, &astate)) == 0) {
|
|
if ((retstat =
|
|
setuseraudit(pw->pw_uid, &astate)) != 0) {
|
|
fprintf(stderr,
|
|
"audit: Error in setting state of processes ");
|
|
fprintf(stderr, "owned by %d.\n", pw->pw_uid);
|
|
audit_argv[1] = sys_errlist[errno];
|
|
audit_error = errno;
|
|
retstat = -1;
|
|
}
|
|
} else {
|
|
fprintf(stderr,
|
|
"audit: error in getting event state.\n");
|
|
audit_argv[1] =
|
|
"Error in getting event state..";
|
|
}
|
|
}
|
|
}
|
|
return (retstat);
|
|
}
|
|
|
|
/*
|
|
* ac_auditoff():
|
|
* purpose: disable auditing
|
|
*
|
|
* returns: 0 - successful
|
|
* -1 - error in opening audit_data file
|
|
*/
|
|
|
|
ac_auditoff()
|
|
{
|
|
int pid, retstat = 0;
|
|
FILE *adp;
|
|
|
|
/*
|
|
* get audit daemon pid
|
|
*/
|
|
if ((adp = fopen(AUDITDATAFILE, "r")) == NULL) {
|
|
fprintf(stderr, "audit: Can't open audit_data file.\n");
|
|
audit_argv[1] = "Error in audit_data open.";
|
|
retstat = -1;
|
|
} else {
|
|
/*
|
|
* get pid of audit daemon
|
|
*/
|
|
fscanf(adp, "%d", &pid);
|
|
if ((retstat = kill(pid, SIGTERM)) != 0) {
|
|
fprintf(stderr,
|
|
"audit: Can't send signal to audit daemon.\n");
|
|
audit_argv[1] = sys_errlist[errno];
|
|
audit_error = errno;
|
|
retstat = -1;
|
|
}
|
|
fclose(adp);
|
|
}
|
|
return (retstat);
|
|
}
|