|
|
The audit read device provides the usual character device driver open(S), read(S), and close(S) routines. Writing to this device is not permitted. Read requests are satisfied by the subsystem and optimize the efficiency of the daemon and the performance of the system. Read requests are satisfied when sufficient data has accumulated to meet an administrator-specified threshold. Until the data is available, the read request will block. In this manner, the daemon will receive sufficiently large blocks of data on each read to allow sufficient compaction. Also, the frequency of context switching is greatly reduced since the reads will not be satisfied on small blocks or when no data is available.
The audit write device provides an interface to the audit subsystem for applications that have the writeaudit authorization. The device supports the open, close, write, and ioctl entry points. Once opened, an application may compose an audit record and write it to the device for inclusion in the collection file. The entire audit record must be presented to the subsystem with a single write. It is incumbent on the application to gather the record into a single buffer before writing it to the device.
The format of an audit record depends upon the type of event being audited. All audit records begin with a common audit record header defined by the audit_header structure in the <sys/audit.h> header file.
struct audit_header { ushort rec_length; /* total record length */ time_t tstamp; /* date/time of record */ ulong event_id; /* event sequence id */ ushort event_type; /* event classification */ ushort record_type; /* record format */ ushort obj_type; /* object type */ ushort pid; /* process_id */ };The
event_type
, record_type
, and pid
fields must be filled by the application;
all other fields are filled by the audit subsystem.
The event types are defined
in the header file and provide a method of categorizing audit records into
groups such as login events or system administrator events. The record type
informs the subsystem of the record template type. This information is
also retained with the record when it is written to the collection file by
the subsystem, since it is required at data reduction time.
Some of the record types have variable-length string areas that follow the fixed portion of the audit record. Each text string that is part of the record has its size recorded in a count field. Each string is null-terminated and the count must include the null character. When the record is written to the device, the amount of data written includes the fixed portion plus all text strings. The supported record types for application programs are:
Each record type indicates a unique record structure definition. The RT_LOGIN record uses the login_audit structure. It contains the following fields, defined in <sys/audit.h>:
struct login_audit { struct audit_header aud_hdr; char username[8]; /* login name */ ushort code; /* function code */ ushort luid; /* login userid */ ushort rgid; /* real gid */ dev_t ttyd; /* controlling terminal */ ptr_t cdir; /* current directory */ ptr_t terminal; /* stdin terminal name */ #ifdef B1 ptr_t sec_level; /* login sensitivity level */ #endif };
username
is the login or logout user account name. The luid
and
rgid
fields are those associated with the specified user account.
The audit header, which precedes the login-specific
portion of the record, must have the
record_type
field set to RT_LOGIN. The
event_type
used for login/logout is the ET_LOGIN event.
The code
field is used to distinguish between specific actions that may fall
into a common category. For instance, the ET_LOGIN event category includes
both successful and unsuccessful logins, and also logoffs. The code values,
defined in the header file, indicate which of these occurred.
The login audit record also contains two
variable-length text strings. These
are the login terminal and the process current
directory. The string area begins immediately following the fixed portion of
the record. The size of each text string field is indicated by the
ptr_t typedef
field which contains the length of the string including the null character. The
null character is considered part of the string.
Once the strings have been calculated and the record completed,
the length field in the audit record header is set to the size of structure
plus the total lengths of the strings. This is the amount of data to
write to the audit device.
Modifications to user passwords are audited by the password management subsystem. Each attempt, whether successful or not, results in an audit record of type RT_PASSWORD being generated. The structure is defined in the <sys/audit.h> header file:
struct passwd_audit { struct audit_header aud_hdr; char username[8]; /* login user name */ ushort code; /* function code */ };The
code
value distinguishes between successful and
unsuccessful attempts
to change the password on the indicated user account.
The system maintains a number of protected database files to support the system security policy. Attempts to modify the databases are audited with the RT_DATABASE type records. These records have the following format, as defined in <sys/audit.h>:
struct database_activity { struct audit_header aud_hdr; ptr_t command; /* command name */ ushort code; /* Type of database audit */ ushort object; /* object type */ long expected_val; /* Expected value of parameter */ long present_val; /* Present value of parameter */ ptr_t action; /* security action that failed */ ptr_t result; /* result of failure */ };The
dbase
and code
values identify the database and the specific action, whether successful or
not. A variable-length text string area is provided to identify precisely
the database field along with the old and new
database field values. The audit header
length
field includes the size of the string area and the fixed portion of the
record.
Protected subsystems use the RT_SUBSYSTEM record type
to record security related events that occur in subsystem components.
code
is used to identify the subsystem generating the record. Both the
command and resulting action as well as the resulting failure are recorded
in command
, action
, and result
,
respectively.
struct subsystem_activity { struct audit_header aud_hdr; ptr_t command; /* command name */ ushort code; /* Subsystem type */ ptr_t action; /* action that failed */ ptr_t result; /* result of failure */ };The RT_LOCK record type is used to audit user account and terminal locking events. The
username
identifies the user account which was locked or unlocked.
code
distinguishes between the several events
that result in the generation of a lock audit record.
#include <sys/audit.h>Programs that interact with and control the audit subsystem are audited with the RT_AUDIT record type. The subsystem is enabled and disabled by an application program. The same is true of subsystem parameter initialization and modification. Events such as the initiation and termination of the audit daemon, the execution of the recovery mechanism, data reduction and report generation, and audit file archival are all audited.struct lock_audit { struct audit_header aud_hdr; char username[12]; /* login username */ ushort code; /* lock function code */ ushort trys; /* failed attempts */ };
The text string portion of the audit record is only applicable for the
audit enable function since the initial subsystem collection file must be
specified for the daemon log file. All other audit records do not use this
field. The code
indicates which of the above events took place.
struct audit_actions { struct audit_header aud_hdr; ushort code; /* audit function code */ ptr_t text1; /* initial collection file */ };The audit device supports a number of ioctl functions to control the audit subsystem. The format of the ioctl calls is:
ioctl (fildes, command, arg) int fildes, command; struct audit_init *arg;or,
struct audit_ioctl *arg;or,
struct audit_stats *arg;The audit_init structure is only used for the AUDIT_ENABLE command to perform subsystem initialization. The structure is defined as follows:
struct audit_init { uint buf_length; /* length of data including header */ mask_t audit_flags[1]; /* audit control flags */ mask_t event_mask[AUDIT_MASK_SIZE]; /* system event mask */ uint read_count; /* daemon read count to satisfy */ uint write_count; /* write count for coll. file flush */ long write_time; /* write flush time in seconds */ long switch_count; /* collection file size maximum */ long caf_maxsize; /* compacted audit file max size */ uint dir_count; /* directory count */ uint uid_count; /* uid selection count */ uint gid_count; /* gid selection count */ ulong dir_offset; /* fseek of directory names */ ulong uid_offset; /* fseek of uids to select */ ulong gid_offset; /* fseek of gids to select */ uint buff_count; /* number of collection file buffers */ ulong session; /* system boot session number */ short audit_uid; /* audit user uid */ short audit_gid; /* audit group gid */ };The subsystem initialization parameters are established through the Audit manager or auditsh(ADM) and are written to a parameter file. This file is read and used to fill out the above structure to initialize the subsystem.
The event_mask
is a bit mask of the selected events to audit during the session. Only events
that are enabled will generate audit records. The
read_count
value is used by the subsystem to satisfy audit daemon reads. Only when the
specified amount of data is available in the collection file will the read be
satisfied.
The flushing of the internal subsystem buffers to the collection file is
controlled by the write_count
and write_time
fields. When the specified amount of data has accumulated, the buffers will
be flushed to disk. A time interval in seconds can also be set which will
cause the flushing of data to disk after a certain period of elapsed time.
The switch_count
controls the size to which subsystem collection files may grow until a file
switch is performed.
The size of the output compaction files written by the audit daemon are
controlled by the caf_maxsize
parameter. When these files reach this specified size, the daemon performs
a switch to a new compaction file and records this fact in the audit session
log file.
session
is the current session value that is used in filename generation. The
buff_count
value determines the number of filesystem blocksize buffers to be allocated by
the subsystem for the purpose of internal buffering. At least 2 buffers
are allocated, while 4-6 buffers are optimal.
dir_count
is the number of collection file and compaction file directories that are
available to both the subsystem and the audit daemon for the creation of
their respective files. If a file write error occurs, both will attempt to use
an alternate directory. Both will terminate only when all directories have
been tried without success. The directory names are located in the
variable-length directory area following the fixed portion of the initialization
record. Each pathname is a null-terminated string. The dir_offset
field points to the start of this variable-length text string area with
respect to the start of the structure.
The audit subsystem is capable of selective audit record generation based
on user and group IDs. These values may be specified to the subsystem at
initialization time using the uid_count
and gid_count
values. The actual list of user and group IDs are located at the end of
the structure in a variable-length table of short integers. The offsets where the ID arrays
may be found are located by the uid_offset
and gid_offset
values.
The audit_uid
and audit_gid
fields are used to communicate certain ID values to the subsystem since these
are used to create files with specific owners and groups for security purposes.
All remaining ioctl commands except AUDIT_STATS use the audit_ioctl structure. The audit_ioctl structure is defined by the following:
struct audit_ioctl { uint read_count; /* daemon read count */ uint write_count; /* write count for file flush */ long write_time; /* write flush time */ mask_t user_control[AUDIT_MASK_SIZE]; /* control mask */ mask_t user_disp[AUDIT_MASK_SIZE]; /* disposition mask */ mask_t system_mask[AUDIT_MASK_SIZE]; /* system event mask */ };The AUDIT_STATS ioctl command uses the following structure for the retrieval and display of statistics.
struct audit_stats { uint session; /* current session number */ uint sequence; /* current sequence number */ ulong total_bytes; /* total bytes written */ ulong total_recs; /* total records written */ ulong syscall_recs; /* system call audit record count */ ulong syscall_norecs; /* system call audit record count */ ulong appl_recs; /* application audit record count */ ulong read_count; /* number of device reads */ ulong write_count; /* number of device writes */ ulong coll_files; /* number of collection files */ ulong buffers_used; /* maximum audit buffer usage */ ulong buffer_sleep; /* number of audit write sleeps */ };The commands supported by the audit device are:
ioctl calls will fail, setting one of the following values in errno, if any of these conditions are true:
``Maintaining system security'' in the System Administration Guide