summaryrefslogtreecommitdiff
path: root/usr/src/lib/libbsm/common
diff options
context:
space:
mode:
authorgww <gww@eng.sun.com>2010-04-12 16:53:16 -0700
committergww <gww@eng.sun.com>2010-04-12 16:53:16 -0700
commit91b2cbb33f0dcb9fb5a72db1795003e07afeded9 (patch)
tree527dac9a1fd2fb993c7123f4f869453c0e1003b5 /usr/src/lib/libbsm/common
parentb5875ddd9f650174db2616fc7cc262d30eb77bf0 (diff)
downloadillumos-gate-91b2cbb33f0dcb9fb5a72db1795003e07afeded9.tar.gz
6935410 setting audit context when audit is not enabled should be more tolerant of getaddrinfo failure
Diffstat (limited to 'usr/src/lib/libbsm/common')
-rw-r--r--usr/src/lib/libbsm/common/adt.c272
-rw-r--r--usr/src/lib/libbsm/common/adt_xlate.h9
2 files changed, 176 insertions, 105 deletions
diff --git a/usr/src/lib/libbsm/common/adt.c b/usr/src/lib/libbsm/common/adt.c
index 06042324e9..76b3d23357 100644
--- a/usr/src/lib/libbsm/common/adt.c
+++ b/usr/src/lib/libbsm/common/adt.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <bsm/adt.h>
@@ -68,6 +67,29 @@ static int adt_get_local_address(int, struct ifaddrlist *);
#define DFLUSH
#endif
+/*
+ * Local audit states are a bit mask
+ *
+ * The global audit states are
+ *
+ * AUC_UNSET 0 - on/off hasn't been decided
+ * AUC_ENABLED 1 - loaded and enabled
+ *
+ * The local Zone states are
+ *
+ * AUC_AUDITING 0x1 - audit daemon is active
+ * AUC_NOAUDIT 0x2 - audit daemon is not active
+ * AUC_INIT_AUDIT 0x4 - audit is ready but auditd has not run
+ * AUC_NOSPACE 0x8 - audit enabled, no space for audit records
+ *
+ * The only values returned by auditon(A_GETCOND) are:
+ * AUC_INIT_AUDIT, AUC_AUDITING, AUC_NOAUDIT, AUC_NOSPACE
+ *
+ * The pseudo audit state used when the c2audit module is excluded is
+ *
+ * AUC_DISABLED 0x100 - c2audit module is excluded
+ */
+
static int auditstate = AUC_DISABLED; /* default state */
/*
@@ -104,22 +126,12 @@ adt_write_syslog(const char *message, int err)
}
/*
- * return true if audit is enabled. "Enabled" is any state
- * other than AUC_DISABLED.
- *
- * states are
- * AUC_INIT_AUDIT -- c2audit queuing enabled.
- * AUC_AUDITING -- up and running
- * AUC_DISABLED -- no audit subsystem loaded
- * AUC_UNSET -- early boot state
- * AUC_NOAUDIT -- subsystem loaded, turned off via
- * auditon(A_SETCOND...)
- * AUC_NOSPACE -- up and running, but log partitions are full
- *
- * For purpose of this API, anything but AUC_DISABLED or
- * AUC_UNSET is enabled; however one never actually sees
- * AUC_DISABLED since auditon returns EINVAL in that case. Any
- * auditon error is considered the same as EINVAL for our
+ * return true if c2audit is not excluded.
+ *
+ * For purpose of this API, anything but AUC_DISABLED
+ * is enabled; however one never actually sees
+ * AUC_DISABLED since auditon returns ENOTSUP in that case. Any
+ * auditon error is considered the same as ENOTSUP for our
* purpose. auditstate is not changed by auditon if an error
* is returned.
*/
@@ -131,6 +143,8 @@ adt_write_syslog(const char *message, int err)
* users are zoneadmd and init.
* All but dtlogin are in ON, so we can do this without cross gate
* synchronization.
+ *
+ * No longer used in adt.c.
*/
boolean_t
@@ -155,7 +169,7 @@ adt_audit_state(int state)
(void) auditon(A_GETCOND, (caddr_t)&auditstate, sizeof (auditstate));
- return (auditstate == state);
+ return (auditstate & state);
}
/*
@@ -176,7 +190,8 @@ adt_get_mask_from_user(uid_t uid, au_mask_t *mask)
char pwd_buff[NSS_BUFSIZ];
char naflag_buf[NAFLAG_LEN];
- if (auditstate == AUC_DISABLED) {
+ if (auditstate & AUC_DISABLED) {
+ /* c2audit excluded */
mask->am_success = 0;
mask->am_failure = 0;
} else if (uid <= MAXUID) {
@@ -335,22 +350,25 @@ adt_start_session(adt_session_data_t **new_session,
adt_internal_state_t *state;
adt_session_flags_t flgmask = ADT_FLAGS_ALL;
- *new_session = NULL; /* assume failure */
-
- /* ensure that auditstate is set */
- (void) adt_audit_enabled();
+ /* test and set auditstate */
+ if (adt_audit_state(AUC_DISABLED)) {
+ /* c2audit excluded */
+ *new_session = NULL;
+ return (0);
+ }
if ((flags & ~flgmask) != 0) {
errno = EINVAL;
goto return_err;
}
- state = calloc(1, sizeof (adt_internal_state_t));
- if (state == NULL)
+ if ((state = calloc(1, sizeof (adt_internal_state_t))) == NULL) {
goto return_err;
+ }
- if (adt_init(state, flags & ADT_USE_PROC_DATA) != 0)
+ if (adt_init(state, flags & ADT_USE_PROC_DATA) != 0) {
goto return_err_free; /* errno from adt_init() */
+ }
/*
* The imported state overwrites the initial state if the
@@ -368,16 +386,13 @@ adt_start_session(adt_session_data_t **new_session,
DPRINTF(("(%lld) Starting session id = %08X\n",
(long long) getpid(), state->as_info.ai_asid));
- if (state->as_audit_enabled) {
- *new_session = (adt_session_data_t *)state;
- } else {
- free(state);
- }
-
+ *new_session = (adt_session_data_t *)state;
return (0);
+
return_err_free:
free(state);
return_err:
+ *new_session = NULL;
adt_write_syslog("audit session create failed", errno);
return (-1);
}
@@ -614,24 +629,25 @@ adt_load_termid(int fd, adt_termid_t **termid)
int peerlen = sizeof (peer);
int socklen = sizeof (sock);
- *termid = NULL;
-
/* get peer name if its a socket, else assume local terminal */
if (getpeername(fd, (struct sockaddr *)&peer, (socklen_t *)&peerlen)
< 0) {
- if (errno == ENOTSOCK)
+ if (errno == ENOTSOCK) {
return (adt_load_hostname(NULL, termid));
+ }
goto return_err;
}
- if ((p_term = calloc(1, sizeof (au_tid_addr_t))) == NULL)
+ if ((p_term = calloc(1, sizeof (au_tid_addr_t))) == NULL) {
goto return_err;
+ }
/* get sock name */
if (getsockname(fd, (struct sockaddr *)&sock,
- (socklen_t *)&socklen) < 0)
+ (socklen_t *)&socklen) < 0) {
goto return_err_free;
+ }
if (peer.sin6_family == AF_INET6) {
adt_do_ipv6_address(&peer, &sock, p_term);
@@ -646,6 +662,7 @@ adt_load_termid(int fd, adt_termid_t **termid)
return_err_free:
free(p_term);
return_err:
+ *termid = NULL;
return (-1);
}
@@ -672,6 +689,14 @@ adt_have_termid(au_tid_addr_t *dest)
return (B_TRUE);
}
+/*
+ * adt_get_hostIP - construct a terminal id from a hostname
+ *
+ * Returns 0 = success
+ * -1 = failure and errno = ENETDOWN with the address
+ * defaulted to IPv4 loopback.
+ */
+
static int
adt_get_hostIP(const char *hostname, au_tid_addr_t *p_term)
{
@@ -716,7 +741,25 @@ adt_get_hostIP(const char *hostname, au_tid_addr_t *p_term)
}
freeaddrinfo(ai);
return (0);
- } else {
+ } else if (auditstate & (AUC_AUDITING | AUC_NOSPACE)) {
+ auditinfo_addr_t audit_info;
+
+ /*
+ * auditd is running so there should be a
+ * kernel audit context
+ */
+ if (auditon(A_GETKAUDIT, (caddr_t)&audit_info,
+ sizeof (audit_info)) < 0) {
+ adt_write_syslog("unable to get kernel audit context",
+ errno);
+ goto try_interface;
+ }
+ adt_write_syslog("setting Audit IP address to kernel", 0);
+ *p_term = audit_info.ai_termid;
+ return (0);
+ }
+try_interface:
+ {
struct ifaddrlist al;
int family;
char ntop[INET6_ADDRSTRLEN];
@@ -724,7 +767,8 @@ adt_get_hostIP(const char *hostname, au_tid_addr_t *p_term)
/*
* getaddrinfo has failed to map the hostname
* to an IP address, try to get an IP address
- * from a local interface.
+ * from a local interface. If none up, default
+ * to loopback.
*/
family = AF_INET6;
if (adt_get_local_address(family, &al) != 0) {
@@ -732,8 +776,14 @@ adt_get_hostIP(const char *hostname, au_tid_addr_t *p_term)
if (adt_get_local_address(family, &al) != 0) {
adt_write_syslog("adt_get_local_address "
- "failed, no Audit IP address available",
+ "failed, no Audit IP address available, "
+ "faking loopback and error",
errno);
+ IN_SET_LOOPBACK_ADDR(
+ (struct sockaddr_in *)&(al.addr.addr));
+ (void) memcpy(p_term->at_addr, &al.addr.addr,
+ AU_IPv4);
+ p_term->at_type = AU_IPv4;
return (-1);
}
}
@@ -760,10 +810,14 @@ adt_get_hostIP(const char *hostname, au_tid_addr_t *p_term)
* the terminal id has already been set; instead it returns the
* existing terminal id.
*
- * If audit is off and the hostname lookup fails, no error is
- * returned, since an error may be interpreted by the caller
- * as grounds for denying a login. Otherwise the caller would
- * need to be aware of the audit state.
+ * If c2audit is excluded, success is returned.
+ * If the hostname lookup fails, the loopback address is assumed,
+ * errno is set to ENETDOWN, this allows the caller to interpret
+ * whether failure is fatal, and if not to have a address for the
+ * hostname.
+ * Otherwise the caller would need to be aware of the audit state.
+ *
+ * Other errors are ignored if not auditing.
*/
int
@@ -772,13 +826,15 @@ adt_load_hostname(const char *hostname, adt_termid_t **termid)
char localhost[MAXHOSTNAMELEN + 1];
au_tid_addr_t *p_term;
- *termid = NULL;
-
- if (!adt_audit_enabled())
+ if (adt_audit_state(AUC_DISABLED)) {
+ /* c2audit excluded */
+ *termid = NULL;
return (0);
+ }
- if ((p_term = calloc(1, sizeof (au_tid_addr_t))) == NULL)
+ if ((p_term = calloc(1, sizeof (au_tid_addr_t))) == NULL) {
goto return_err;
+ }
if (adt_have_termid(p_term)) {
*termid = (adt_termid_t *)p_term;
@@ -790,19 +846,19 @@ adt_load_hostname(const char *hostname, adt_termid_t **termid)
(void) sysinfo(SI_HOSTNAME, localhost, MAXHOSTNAMELEN);
hostname = localhost;
}
- if (adt_get_hostIP(hostname, p_term))
- goto return_err_free;
-
- *termid = (adt_termid_t *)p_term;
- return (0);
-
-return_err_free:
- free(p_term);
+ if (adt_get_hostIP(hostname, p_term) == 0) {
+ *termid = (adt_termid_t *)p_term;
+ return (0);
+ } else {
+ *termid = (adt_termid_t *)p_term;
+ return (-1);
+ }
return_err:
- if ((auditstate == AUC_DISABLED) ||
- (auditstate == AUC_NOAUDIT))
+ *termid = NULL;
+ if (auditstate & AUC_NOAUDIT) {
return (0);
+ }
return (-1);
}
@@ -814,10 +870,15 @@ return_err:
* the terminal id has already been set; instead it returns the
* existing terminal id.
*
- * If audit is off and the ttyname lookup fails, no error is
- * returned, since an error may be interpreted by the caller
- * as grounds for denying a login. Otherwise the caller would
- * need to be aware of the audit state.
+ * If c2audit is excluded, success is returned.
+ * The local hostname is used for the local IP address.
+ * If that hostname lookup fails, the loopback address is assumed,
+ * errno is set to ENETDOWN, this allows the caller to interpret
+ * whether failure is fatal, and if not to have a address for the
+ * hostname.
+ * Otherwise the caller would need to be aware of the audit state.
+ *
+ * Other errors are ignored if not auditing.
*/
int
@@ -827,13 +888,15 @@ adt_load_ttyname(const char *ttyname, adt_termid_t **termid)
au_tid_addr_t *p_term;
struct stat stat_buf;
- *termid = NULL;
-
- if (!adt_audit_enabled())
+ if (adt_audit_state(AUC_DISABLED)) {
+ /* c2audit excluded */
+ *termid = NULL;
return (0);
+ }
- if ((p_term = calloc(1, sizeof (au_tid_addr_t))) == NULL)
+ if ((p_term = calloc(1, sizeof (au_tid_addr_t))) == NULL) {
goto return_err;
+ }
if (adt_have_termid(p_term)) {
*termid = (adt_termid_t *)p_term;
@@ -842,29 +905,34 @@ adt_load_ttyname(const char *ttyname, adt_termid_t **termid)
p_term->at_port = 0;
- if (sysinfo(SI_HOSTNAME, localhost, MAXHOSTNAMELEN) < 0)
+ if (sysinfo(SI_HOSTNAME, localhost, MAXHOSTNAMELEN) < 0) {
goto return_err_free; /* errno from sysinfo */
+ }
if (ttyname != NULL && *ttyname != '\0') {
- if (stat(ttyname, &stat_buf) < 0)
+ if (stat(ttyname, &stat_buf) < 0) {
goto return_err_free;
+ }
p_term->at_port = stat_buf.st_rdev;
}
- if (adt_get_hostIP(localhost, p_term))
- goto return_err_free;
-
- *termid = (adt_termid_t *)p_term;
- return (0);
+ if (adt_get_hostIP(localhost, p_term) == 0) {
+ *termid = (adt_termid_t *)p_term;
+ return (0);
+ } else {
+ *termid = (adt_termid_t *)p_term;
+ return (-1);
+ }
return_err_free:
free(p_term);
return_err:
- if ((auditstate == AUC_DISABLED) ||
- (auditstate == AUC_NOAUDIT))
+ *termid = NULL;
+ if (auditstate & AUC_NOAUDIT) {
return (0);
+ }
return (-1);
}
@@ -1051,7 +1119,7 @@ adt_from_export_format(adt_internal_state_t *internal,
adrm_int32(&context,
(int *)&(internal->as_info.ai_termid.at_addr[0]), 4);
adrm_int32(&context, (int *)&(internal->as_info.ai_asid), 1);
- adrm_int32(&context, (int *)&(internal->as_audit_enabled), 1);
+ adrm_int32(&context, (int *)&(internal->as_audit_state), 1);
internal->as_pid = (pid_t)-1;
internal->as_label = NULL;
} else if (version == PROTOCOL_VERSION_2) {
@@ -1069,7 +1137,7 @@ adt_from_export_format(adt_internal_state_t *internal,
adrm_int32(&context,
(int *)&(internal->as_info.ai_termid.at_addr[0]), 4);
adrm_int32(&context, (int *)&(internal->as_info.ai_asid), 1);
- adrm_int32(&context, (int *)&(internal->as_audit_enabled), 1);
+ adrm_int32(&context, (int *)&(internal->as_audit_state), 1);
adrm_int32(&context, (int *)&(internal->as_pid), 1);
adrm_int32(&context, (int *)&label_len, 1);
if (label_len > 0) {
@@ -1143,7 +1211,7 @@ adt_to_export_format(adt_export_data_t *external,
adrm_putint32(&context,
(int *)&(internal->as_info.ai_termid.at_addr[0]), 4);
adrm_putint32(&context, (int *)&(internal->as_info.ai_asid), 1);
- adrm_putint32(&context, (int *)&(internal->as_audit_enabled), 1);
+ adrm_putint32(&context, (int *)&(internal->as_audit_state), 1);
adrm_putint32(&context, (int *)&(internal->as_pid), 1);
adrm_putint32(&context, (int *)&label_len, 1);
if (internal->as_label != NULL) {
@@ -1173,7 +1241,7 @@ adt_to_export_format(adt_export_data_t *external,
adrm_putint32(&context,
(int *)&(internal->as_info.ai_termid.at_addr[0]), 4);
adrm_putint32(&context, (int *)&(internal->as_info.ai_asid), 1);
- adrm_putint32(&context, (int *)&(internal->as_audit_enabled), 1);
+ adrm_putint32(&context, (int *)&(internal->as_audit_state), 1);
/* ignored in v1 */
adrm_putint32(&context, (int *)&label_len, 1);
@@ -1212,8 +1280,8 @@ adt_import(adt_internal_state_t *internal, const adt_export_data_t *external)
{
au_mask_t mask;
- /* save local audit enabled state */
- int local_audit_enabled = internal->as_audit_enabled;
+ /* save local audit state */
+ int local_audit_state = internal->as_audit_state;
if (adt_from_export_format(internal, external) < 1)
return (-1); /* errno from adt_from_export_format */
@@ -1229,7 +1297,7 @@ adt_import(adt_internal_state_t *internal, const adt_export_data_t *external)
* recoverable.
*/
- if (!internal->as_audit_enabled) {
+ if (!(internal->as_audit_state & AUC_DISABLED)) {
if (adt_get_mask_from_user(internal->as_info.ai_auid,
&(internal->as_info.ai_mask)))
return (-1);
@@ -1243,7 +1311,7 @@ adt_import(adt_internal_state_t *internal, const adt_export_data_t *external)
mask.am_failure;
}
}
- internal->as_audit_enabled = local_audit_enabled;
+ internal->as_audit_state = local_audit_state;
DPRINTF(("(%lld)imported asid = %X %u\n", (long long) getpid(),
internal->as_info.ai_asid,
@@ -1308,14 +1376,14 @@ return_length_free:
static void
adt_setto_unaudited(adt_internal_state_t *state)
{
- state->as_ruid = AU_NOAUDITID;
- state->as_euid = AU_NOAUDITID;
- state->as_rgid = AU_NOAUDITID;
- state->as_egid = AU_NOAUDITID;
- state->as_pid = (pid_t)-1;
- state->as_label = NULL;
-
- if (state->as_audit_enabled) {
+ if (state->as_audit_state & AUC_DISABLED) {
+ state->as_ruid = AU_NOAUDITID;
+ state->as_euid = AU_NOAUDITID;
+ state->as_rgid = AU_NOAUDITID;
+ state->as_egid = AU_NOAUDITID;
+ state->as_pid = (pid_t)-1;
+ state->as_label = NULL;
+ } else {
state->as_info.ai_asid = 0;
state->as_info.ai_auid = AU_NOAUDITID;
@@ -1340,8 +1408,10 @@ adt_setto_unaudited(adt_internal_state_t *state)
static int
adt_init(adt_internal_state_t *state, int use_proc_data)
{
+ /* ensure auditstate is set */
- state->as_audit_enabled = (auditstate == AUC_DISABLED) ? 0 : 1;
+ (void) adt_audit_state(0);
+ state->as_audit_state = auditstate;
if (use_proc_data) {
state->as_ruid = getuid();
@@ -1350,7 +1420,7 @@ adt_init(adt_internal_state_t *state, int use_proc_data)
state->as_egid = getegid();
state->as_pid = getpid();
- if (state->as_audit_enabled) {
+ if (!(state->as_audit_state & AUC_DISABLED)) {
const au_tid64_addr_t *tid;
const au_mask_t *mask;
ucred_t *ucred = ucred_get(P_MYID);
@@ -1396,7 +1466,7 @@ adt_init(adt_internal_state_t *state, int use_proc_data)
}
state->as_session_model = ADT_SESSION_MODEL; /* default */
- if (state->as_audit_enabled &&
+ if ((state->as_audit_state & (AUC_AUDITING | AUC_NOSPACE)) &&
auditon(A_GETPOLICY, (caddr_t)&(state->as_kernel_audit_policy),
sizeof (state->as_kernel_audit_policy))) {
return (-1); /* errno set by auditon */
@@ -1425,8 +1495,9 @@ adt_set_proc(const adt_session_data_t *session_data)
{
adt_internal_state_t *state;
- if (auditstate == AUC_DISABLED || (session_data == NULL))
+ if (session_data == NULL) {
return (0);
+ }
state = (adt_internal_state_t *)session_data;
@@ -1916,9 +1987,10 @@ adt_put_event(const adt_event_data_t *event, int status, int return_val)
}
event_state = (struct adt_event_state *)event;
- /* if audit off or this is a broken session, exit */
- if (auditstate == AUC_DISABLED ||
- (event_state->ae_session == NULL)) {
+ /* if this is a broken session or not auditing, exit */
+ if ((event_state->ae_session == NULL) ||
+ !(event_state->ae_session->as_audit_state &
+ (AUC_AUDITING | AUC_NOSPACE))) {
return (0);
}
@@ -2028,7 +2100,7 @@ adt_selected(struct adt_event_state *event, au_event_t actual_id, int status)
* to act as the hosts IP address for auditing.
*/
-int
+static int
adt_get_local_address(int family, struct ifaddrlist *al)
{
struct ifaddrlist *ifal;
diff --git a/usr/src/lib/libbsm/common/adt_xlate.h b/usr/src/lib/libbsm/common/adt_xlate.h
index 4e417bf287..068bed8c71 100644
--- a/usr/src/lib/libbsm/common/adt_xlate.h
+++ b/usr/src/lib/libbsm/common/adt_xlate.h
@@ -21,8 +21,7 @@
/*
* adt_xlate.h
*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
*
*/
@@ -196,7 +195,7 @@ struct adt_internal_state {
* .ai_termid.at_addr[3]
* ai_asid session id
*/
- int as_audit_enabled; /* audit enable/disable state */
+ int as_audit_state; /* audit state */
/*
* data above this line is exported / imported
* To maintain upward compatibility, the above structures
@@ -242,7 +241,7 @@ struct adt_export_v2 {
uint32_t ax_type;
uint32_t ax_addr[4];
uint32_t ax_asid;
- int ax_audit_enabled;
+ int ax_audit_state;
pid_t ax_pid;
size32_t ax_label_len; /* 0, unlabeled */
/* char ax_label[ax_label_len]; if, is_system_labeled */
@@ -259,7 +258,7 @@ struct adt_export_v1 {
uint32_t ax_type;
uint32_t ax_addr[4];
uint32_t ax_asid;
- int ax_audit_enabled;
+ int ax_audit_state;
uint32_t ax_size_of_tsol_data; /* zero for non-TSOL systems */
};
struct export_link {