2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. 2N/A * Local audit states are a bit mask 2N/A * The global audit states are 2N/A * AUC_UNSET 0 - on/off hasn't been decided 2N/A * AUC_ENABLED 1 - loaded and enabled 2N/A * The local Zone states are 2N/A * AUC_AUDITING 0x1 - audit daemon is active 2N/A * AUC_NOAUDIT 0x2 - audit daemon is not active 2N/A * AUC_INIT_AUDIT 0x4 - audit is ready but auditd has not run 2N/A * The only values returned by auditon(A_GETCOND) are: 2N/A * AUC_INIT_AUDIT, AUC_AUDITING, AUC_NOAUDIT 2N/A * The pseudo audit state used when the c2audit module is excluded is 2N/A * AUC_DISABLED 0x100 - c2audit module is excluded 2N/A * errors that are not the user's fault (bugs or whatever in 2N/A * the underlying audit code are noted in syslog.) 2N/A * Avoid calling adt_write_syslog for things that can happen 2N/A * syslog's open (openlog) and close (closelog) are interesting; 2N/A * openlog *may* create a file descriptor and is optional. closelog 2N/A * *will* close any open file descriptors and is also optional. 2N/A * Since syslog may also be used by the calling application, the 2N/A * choice is to avoid openlog, which sets some otherwise useful 2N/A * parameters, and to embed "Solaris_audit" in the log message. 2N/A * returns true if the kernel audit state matches with at least one 2N/A * of audit states set in the argument. 2N/A /* c2audit excluded */ 2N/A * adt_get_unique_id -- generate a hopefully unique 32 bit value 2N/A * there will be a follow up to replace this with the use of /dev/random 2N/A * An MD5 hash is taken on a buffer of 2N/A * hostname . audit id . unix time . pid . count 2N/A * "count = noise++;" is subject to a race condition but I don't 2N/A * see a need to put a lock around it. 2N/A while (
retval == 0) {
/* 0 is the only invalid result */ 2N/A * the following "port" function deals with the following issues: 2N/A * 1 the kernel and ucred deal with a dev_t as a 64 bit value made 2N/A * up from a 32 bit major and 32 bit minor. 2N/A * 2 User space deals with a dev_t as either the above 64 bit value 2N/A * or a 32 bit value made from a 14 bit major and an 18 bit minor. 2N/A * 3 The various audit interfaces (except ucred) pass the 32 or 2N/A * 64 bit version depending the architecture of the userspace 2N/A * application. If you get a port value from ucred and pass it 2N/A * to the kernel via auditon(), it must be squeezed into a 32 2N/A * bit value because the kernel knows the userspace app's bit 2N/A * The internal state structure for adt (adt_internal_state_t) uses 2N/A * from 64 or 32 bit applications, so they always send 64 bits and 2N/A * the 32 bit end(s) are responsible to convert 32 -> 64 -> 32 as 2N/A * adt_cpy_tid() -- if lib is 64 bit, just copy it (dev_t and port are 2N/A * both 64 bits). If lib is 32 bits, squeeze the two-int port into 2N/A * a 32 bit dev_t. A port fits in the "minor" part of au_port_t, 2N/A * so it isn't broken up into pieces. (When it goes to the kernel 2N/A * adt_start_session -- create interface handle, create context 2N/A * The imported_state input is normally NULL, if not, it represents 2N/A * a continued session; its values obviate the need for a subsequent 2N/A * call to adt_set_user(). 2N/A * The flag is used to decide how to set the initial state of the session. 2N/A * If 0, the session is "no audit" until a call to adt_set_user; if 2N/A * ADT_USE_PROC_DATA, the session is built from the process audit 2N/A * characteristics obtained from the kernel. If imported_state is 2N/A * not NULL, the resulting audit mask is an OR of the current process 2N/A * audit mask and that passed in. 2N/A * The basic model is that the caller can use the pointer returned 2N/A * by adt_start_session whether or not auditing is enabled or an 2N/A * error was returned. The functions that take the session handle 2N/A * as input generally return without doing anything if auditing is 2N/A /* test and set auditstate */ 2N/A /* c2audit excluded */ 2N/A * The imported state overwrites the initial state if the 2N/A * imported state represents a valid audit trail 2N/A * loads the event translation table into the audit session. 2N/A * adt_get_asid() and adt_set_asid() 2N/A * if you use this interface, you are responsible to insure that the 2N/A * rest of the session data is populated correctly before calling 2N/A * adt_proccess_attr() 2N/A * neither of these are intended for general use and will likely 2N/A * remain private interfaces for a long time. Forever is a long 2N/A * time. In the case of adt_set_asid(), you should have a very, 2N/A * very good reason for setting your own session id. The process 2N/A * audit characteristics are not changed by put, use adt_set_proc(). 2N/A * These are "volatile" (more changable than "evolving") and will 2N/A * probably change in the S10 period. 2N/A * adt_get_auid() and adt_set_auid() 2N/A * neither of these are intended for general use and will likely 2N/A * remain private interfaces for a long time. Forever is a long 2N/A * time. In the case of adt_set_auid(), you should have a very, 2N/A * very good reason for setting your own audit id. The process 2N/A * audit characteristics are not changed by put, use adt_set_proc(). 2N/A * adt_get_termid(), adt_set_termid() 2N/A * if you use this interface, you are responsible to insure that the 2N/A * rest of the session data is populated correctly before calling 2N/A * adt_proccess_attr() 2N/A * The process audit characteristics are not changed by put, use 2N/A * adt_get_mask(), adt_set_mask() 2N/A * if you use this interface, you are responsible to insure that the 2N/A * rest of the session data is populated correctly before calling 2N/A * adt_proccess_attr() 2N/A * The process audit characteristics are not changed by put, use 2N/A * helpers for adt_load_termid 2N/A * adt_load_termid: convenience function; inputs file handle and 2N/A * outputs an au_tid_addr struct. 2N/A * in that it does not write the terminal id to the process. 2N/A /* get peer name if its a socket, else assume local terminal */ 2N/A * adt_get_hostIP - construct a terminal id from a hostname 2N/A * Returns 0 = success 2N/A * -1 = failure and errno = ENETDOWN with the address 2N/A * defaulted to IPv4 loopback. 2N/A * If local request try to use the current system instance 2N/A * getaddrinfo returns its own set of errors. 2N/A * Log them here, so any subsequent syslogs will 2N/A * have a context. adt_get_hostIP callers can only 2N/A * return errno, so subsequent syslogs may be lacking 2N/A * that getaddrinfo failed. 2N/A /* see if resolution becomes available */ 2N/A * auditd is running see if there's an 2N/A * kernel audit context. It could be that 2N/A * auditd is being refreshed from a loopback 2N/A * situation. See __do_sethost(). 2N/A * getaddrinfo has failed to map the hostname 2N/A * to an IP address, try to get an IP address 2N/A * from a local interface. If none up, default 2N/A "no Audit IP address available, " 2N/A "faking loopback for %s and " 2N/A * adt_load_hostname() is called when the caller does not have a file 2N/A * handle that gives access to the socket info or any other way to 2N/A * pass in both port and ip address. The hostname input is ignored if 2N/A * the terminal id has already been set; instead it returns the 2N/A * existing terminal id. 2N/A * If c2audit is excluded, success is returned. 2N/A * If the hostname lookup fails, the loopback address is assumed, 2N/A * errno is set to ENETDOWN, this allows the caller to interpret 2N/A * whether failure is fatal, and if not to have a address for the 2N/A * Otherwise the caller would need to be aware of the audit state. 2N/A * Other errors are ignored if not auditing. 2N/A /* c2audit excluded */ 2N/A * adt_load_ttyname() is called when the caller does not have a file 2N/A * handle that gives access to the local terminal or any other way 2N/A * of determining the device id. The ttyname input is ignored if 2N/A * the terminal id has already been set; instead it returns the 2N/A * existing terminal id. 2N/A * If c2audit is excluded, success is returned. 2N/A * The local hostname is used for the local IP address. 2N/A * If that hostname lookup fails, the loopback address is assumed, 2N/A * errno is set to ENETDOWN, this allows the caller to interpret 2N/A * whether failure is fatal, and if not to have a address for the 2N/A * Otherwise the caller would need to be aware of the audit state. 2N/A * Other errors are ignored if not auditing. 2N/A /* c2audit excluded */ 2N/A * adt_get_session_id returns a stringified representation of 2N/A * the audit session id. See also adt_get_asid() for how to 2N/A * get the unexpurgated version. No guarantees as to how long 2N/A * the returned string will be or its general form; hex for now. 2N/A * An empty string is returned if auditing is off; length = 1 2N/A * and the pointer is valid. 2N/A * returns strlen + 1 if buffer is valid; else 0 and errno. 2N/A * output is 0x followed by 2N/A * two characters per byte 2N/A * except leading 0's are suppressed, so a few bytes may 2N/A /* length < 1 is a bug: the session data type may have changed */ 2N/A * adt_end_session -- close handle, clear context 2N/A * if as_check is invalid, no harm, no foul, EXCEPT that this could 2N/A * be an attempt to free data already free'd, so output to syslog 2N/A * to help explain why the process cored dumped. 2N/A /* no errors yet defined */ 2N/A * adt_dup_session -- copy the session data 2N/A * from_export_format() 2N/A * read from a network order buffer into struct adt_session_data 2N/A * Skip newer versions. 2N/A return (0);
/* failed to match version */ 2N/A * Adjust buffer pointer to the first data item (euid). 2N/A * if down rev version, neither pid nor label are included 2N/A * in v1 ax_size_of_tsol_data intentionally ignored 2N/A /* read in and deal with different sized labels. */ 2N/A * adt_to_export_format 2N/A * read from struct adt_session_data into a network order buffer. 2N/A * (network order 'cause this data may be shared with a remote host.) 2N/A /* version 2 first */ 2N/A /* serialize the label */ 2N/A /* finally terminator */ 2N/A * adt_ucred_label() -- if label is available, duplicate it. 2N/A * adt_import() -- convert from network order to machine-specific order 2N/A /* save local audit state */ 2N/A return (-
1);
/* errno from adt_from_export_format */ 2N/A * If audit isn't enabled on the remote, they were unable 2N/A * to generate the audit mask, so generate it based on 2N/A * local configuration. If the user id has changed, the 2N/A * resulting mask may miss some subtleties that occurred 2N/A * on the remote system. 2N/A * If the remote failed to generate a terminal id, it is not 2N/A * adt_export_session_data() 2N/A * copies a adt_session_data struct into a network order buffer 2N/A * In a misconfigured network, the local host may have auditing 2N/A * off while the destination may have auditing on, so if there 2N/A * is sufficient memory, a buffer will be returned even in the 2N/A * adt_init -- set session context by copying the audit characteristics 2N/A * from the proc and picking up current uid/tid information. 2N/A * By default, an audit session is based on the process; the default 2N/A * is overriden by adt_set_user() 2N/A /* ensure auditstate is set */ 2N/A * Even if the ucred is NULL, the underlying 2N/A * credential may have a valid terminal id; if the 2N/A * terminal id is set, then that's good enough. An 2N/A * example of where this matters is failed login, 2N/A * calling login; login does not load the credential 2N/A * since auth failed. 2N/A return (-
1);
/* errno set by auditon */ 2N/A * Copy the current session state to the process. If this function 2N/A * is called, the model becomes a process model rather than a 2N/A * In the current implementation, the value state->as_have_user_data 2N/A * must contain all of: ADT_HAVE_{AUID,MASK,TID,ASID}. These are all set 2N/A * by adt_set_user() when the ADT_SETTID or ADT_NEW flag is passed in. 2N/A /* Assume intending to audit as this process */ 2N/A DPRINTF((
"changed mask to %08llX/%08llX for ruid=%d\n",
2N/A * adt_set_user -- see also adt_set_from_ucred() 2N/A * ADT_NO_ATTRIB is a valid uid/gid meaning "not known" or 2N/A * "unattributed." If ruid, change the model to session. 2N/A * ADT_NO_CHANGE is a valid uid/gid meaning "do not change this value" 2N/A * only valid with ADT_UPDATE. 2N/A * ADT_NO_AUDIT is the external equivalent to AU_NOAUDITID -- there 2N/A * isn't a good reason to call adt_set_user() with it unless you don't 2N/A * have a good value yet and intend to replace it later; auid will be 2N/A * adt_set_user should be called even if auditing is not enabled 2N/A * so that adt_export_session_data() will have useful stuff to 2N/A * See the note preceding adt_set_proc() about the use of ADT_HAVE_TID 2N/A /* avoid fooling pam_setcred()... */ 2N/A * adt_set_from_ucred() 2N/A * an alternate to adt_set_user that fills the same role but uses 2N/A * a pointer to a ucred rather than a list of id's. If the ucred 2N/A * pointer is NULL, use the credential from the this process. 2N/A * A key difference is that for ADT_NEW, adt_set_from_ucred() does 2N/A * not overwrite the asid and auid unless auid has not been set. 2N/A * ADT_NEW differs from ADT_UPDATE in that it does not OR together 2N/A * the incoming audit mask with the one that already exists. 2N/A * adt_set_from_ucred should be called even if auditing is not enabled 2N/A * so that adt_export_session_data() will have useful stuff to 2N/A * adt_alloc_event() returns a pointer to allocated memory 2N/A * need to return a valid event pointer even if audit is 2N/A * off, else the caller will end up either (1) keeping its 2N/A * own flags for on/off or (2) writing to a NULL pointer. 2N/A * If auditing is on, the session data must be valid; otherwise 2N/A * preload data so the adt_au_*() functions can detect un-supplied 2N/A * values (0 and NULL are free via calloc()). 2N/A * adt_getXlateTable -- look up translation table address for event id 2N/A * the call to this function is surrounded by a mutex. 2N/A * i walks down the table picking up next_token. j walks again to 2N/A * calculate the offset to the input data. k points to the next 2N/A * token's row. Finally, l, is used to sum the values in the 2N/A * What's going on? The entry array is in the order of the input 2N/A * fields but the processing of array entries is in the order of 2N/A * the output (see next_token). Calculating the offset to the 2N/A * "next" input can't be done in the outer loop (i) since i doesn't 2N/A * point to the current entry and it can't be done with the k index 2N/A * because it doesn't represent the order of input fields. 2N/A * While the resulting algorithm is n**2, it is only done once per 2N/A * adt_calcOffsets is only called once per event type, but it uses 2N/A * the address alignment of memory allocated for that event as if it 2N/A * were the same for all subsequently allocated memory. This is 2N/A * what matters for figuring out the correct alignment is the size 2N/A * of the array element. 2N/A /* adj for first entry */ 2N/A * adt_generate_event 2N/A * generate event record from external struct. The order is based on 2N/A * the output tokens, allowing for the possibility that the input data 2N/A * is in a different order. 2N/A /* can't get an audit record descriptor */ 2N/A * offsets are not pre-calculated; the initial offsets are all 2N/A * 0; valid offsets are >= 0. Offsets for no-input tokens such 2N/A * as subject are set to -1 by adt_calcOffset() 2N/A * adt_put_event -- main event generation function. 2N/A * The input "event" is the address of the struct containing 2N/A * event-specific data. 2N/A * However if auditing is off or the session handle 2N/A * is NULL, no attempt to write a record is made. 2N/A /* if this is a broken session or not auditing, exit */ 2N/A /* look up the event */ 2N/A * adt_free_event -- invalidate and free 2N/A * adt_is_selected -- helper to adt_selected(), below. 2N/A * "sorf" is "success or fail" status; au_preselect compares 2N/A * that with success, fail, or both. 2N/A * selected -- see if this event is preselected. 2N/A * if errors are encountered trying to check a preselection mask 2N/A * or look up a user name, the event is selected. Otherwise, the 2N/A * preselection mask is used for the job. 2N/A return (
1);
/* default is "selected" */ 2N/A /* non-attributable? */ 2N/A /* if forced preselection */ 2N/A * Can't map the host name to an IP address in 2N/A * adt_get_hostIP. Get something off an interface 2N/A * to act as the hosts IP address for auditing. 2N/A * loopback always defined, 2N/A * even if there is no real address 2N/A * Callers of adt_get_hostIP() can only return 2N/A * errno to their callers and eventually the application. 2N/A * Picked one that seemed least worse for saying no 2N/A * usable address for Audit terminal ID.