freebsd-dev/sys/security/audit/audit_bsm_token.c
Christian S.J. Peron f0cbfcc468 Fix the handling of IPv6 addresses for subject and process BSM audit
tokens. Currently, we do not support the set{get}audit_addr(2) system
calls which allows processes like sshd to set extended or ip6
information for subject tokens.

The approach that was taken was to change the process audit state
slightly to use an extended terminal ID in the kernel. This allows
us to store both IPv4 IPv6 addresses. In the case that an IPv4 address
is in use, we convert the terminal ID from an struct auditinfo_addr to
a struct auditinfo.

If getaudit(2) is called when the subject is bound to an ip6 address,
we return E2BIG.

- Change the internal audit record to store an extended terminal ID
- Introduce ARG_TERMID_ADDR
- Change the kaudit <-> BSM conversion process so that we are using
  the appropriate subject token. If the address associated with the
  subject is IPv4, we use the standard subject32 token. If the subject
  has an IPv6 address associated with them, we use an extended subject32
  token.
- Fix a couple of endian issues where we do a couple of byte swaps when
  we shouldn't be. IP addresses are already in the correct byte order,
  so reading the ip6 address 4 bytes at a time and swapping them results
  in in-correct address data. It should be noted that the same issue was
  found in the openbsm library and it has been changed there too on the
  vendor branch
- Change A_GETPINFO to use the appropriate structures
- Implement A_GETPINFO_ADDR which basically does what A_GETPINFO does,
  but can also handle ip6 addresses
- Adjust get{set}audit(2) syscalls to convert the data
  auditinfo <-> auditinfo_addr
- Fully implement set{get}audit_addr(2)

NOTE: This adds the ability for processes to correctly set extended subject
information. The appropriate userspace utilities still need to be updated.

MFC after:	1 month
Reviewed by:	rwatson
Obtained from:	TrustedBSD
2007-04-13 14:55:19 +00:00

1199 lines
26 KiB
C

/*
* Copyright (c) 2004 Apple Computer, Inc.
* Copyright (c) 2005 SPARTA, Inc.
* All rights reserved.
*
* This code was developed in part by Robert N. M. Watson, Senior Principal
* Scientist, SPARTA, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* $P4: //depot/projects/trustedbsd/audit3/sys/security/audit/audit_bsm_token.c#23 $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/endian.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/ipc.h>
#include <sys/libkern.h>
#include <sys/malloc.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <sys/socketvar.h>
#include <bsm/audit.h>
#include <bsm/audit_internal.h>
#include <bsm/audit_record.h>
#include <security/audit/audit.h>
#include <security/audit/audit_private.h>
#define GET_TOKEN_AREA(t, dptr, length) do { \
t = malloc(sizeof(token_t), M_AUDITBSM, M_WAITOK); \
t->t_data = malloc(length, M_AUDITBSM, M_WAITOK | M_ZERO); \
t->len = length; \
dptr = t->t_data; \
} while (0)
/*
* token ID 1 byte
* argument # 1 byte
* argument value 4 bytes/8 bytes (32-bit/64-bit value)
* text length 2 bytes
* text N bytes + 1 terminating NULL byte
*/
token_t *
au_to_arg32(char n, char *text, u_int32_t v)
{
token_t *t;
u_char *dptr = NULL;
u_int16_t textlen;
textlen = strlen(text);
textlen += 1;
GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t) +
sizeof(u_int16_t) + textlen);
ADD_U_CHAR(dptr, AUT_ARG32);
ADD_U_CHAR(dptr, n);
ADD_U_INT32(dptr, v);
ADD_U_INT16(dptr, textlen);
ADD_STRING(dptr, text, textlen);
return (t);
}
token_t *
au_to_arg64(char n, char *text, u_int64_t v)
{
token_t *t;
u_char *dptr = NULL;
u_int16_t textlen;
textlen = strlen(text);
textlen += 1;
GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t) +
sizeof(u_int16_t) + textlen);
ADD_U_CHAR(dptr, AUT_ARG64);
ADD_U_CHAR(dptr, n);
ADD_U_INT64(dptr, v);
ADD_U_INT16(dptr, textlen);
ADD_STRING(dptr, text, textlen);
return (t);
}
token_t *
au_to_arg(char n, char *text, u_int32_t v)
{
return (au_to_arg32(n, text, v));
}
#if defined(_KERNEL) || defined(KERNEL)
/*
* token ID 1 byte
* file access mode 4 bytes
* owner user ID 4 bytes
* owner group ID 4 bytes
* file system ID 4 bytes
* node ID 8 bytes
* device 4 bytes/8 bytes (32-bit/64-bit)
*/
token_t *
au_to_attr32(struct vnode_au_info *vni)
{
token_t *t;
u_char *dptr = NULL;
u_int16_t pad0_16 = 0;
u_int16_t pad0_32 = 0;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int16_t) +
3 * sizeof(u_int32_t) + sizeof(u_int64_t) + sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_ATTR32);
/*
* Darwin defines the size for the file mode
* as 2 bytes; BSM defines 4 so pad with 0
*/
ADD_U_INT16(dptr, pad0_16);
ADD_U_INT16(dptr, vni->vn_mode);
ADD_U_INT32(dptr, vni->vn_uid);
ADD_U_INT32(dptr, vni->vn_gid);
ADD_U_INT32(dptr, vni->vn_fsid);
/*
* Some systems use 32-bit file ID's, other's use 64-bit file IDs.
* Attempt to handle both, and let the compiler sort it out. If we
* could pick this out at compile-time, it would be better, so as to
* avoid the else case below.
*/
if (sizeof(vni->vn_fileid) == sizeof(uint32_t)) {
ADD_U_INT32(dptr, pad0_32);
ADD_U_INT32(dptr, vni->vn_fileid);
} else if (sizeof(vni->vn_fileid) == sizeof(uint64_t))
ADD_U_INT64(dptr, vni->vn_fileid);
else
ADD_U_INT64(dptr, 0LL);
ADD_U_INT32(dptr, vni->vn_dev);
return (t);
}
token_t *
au_to_attr64(struct vnode_au_info *vni)
{
return (NULL);
}
token_t *
au_to_attr(struct vnode_au_info *vni)
{
return (au_to_attr32(vni));
}
#endif /* !(defined(_KERNEL) || defined(KERNEL) */
/*
* token ID 1 byte
* how to print 1 byte
* basic unit 1 byte
* unit count 1 byte
* data items (depends on basic unit)
*/
token_t *
au_to_data(char unit_print, char unit_type, char unit_count, char *p)
{
token_t *t;
u_char *dptr = NULL;
size_t datasize, totdata;
/* Determine the size of the basic unit. */
switch (unit_type) {
case AUR_BYTE:
/* case AUR_CHAR: */
datasize = AUR_BYTE_SIZE;
break;
case AUR_SHORT:
datasize = AUR_SHORT_SIZE;
break;
case AUR_INT32:
/* case AUR_INT: */
datasize = AUR_INT32_SIZE;
break;
case AUR_INT64:
datasize = AUR_INT64_SIZE;
break;
default:
return (NULL);
}
totdata = datasize * unit_count;
GET_TOKEN_AREA(t, dptr, 4 * sizeof(u_char) + totdata);
ADD_U_CHAR(dptr, AUT_DATA);
ADD_U_CHAR(dptr, unit_print);
ADD_U_CHAR(dptr, unit_type);
ADD_U_CHAR(dptr, unit_count);
ADD_MEM(dptr, p, totdata);
return (t);
}
/*
* token ID 1 byte
* status 4 bytes
* return value 4 bytes
*/
token_t *
au_to_exit(int retval, int err)
{
token_t *t;
u_char *dptr = NULL;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_EXIT);
ADD_U_INT32(dptr, err);
ADD_U_INT32(dptr, retval);
return (t);
}
/*
*/
token_t *
au_to_groups(int *groups)
{
return (au_to_newgroups(AUDIT_MAX_GROUPS, groups));
}
/*
* token ID 1 byte
* number groups 2 bytes
* group list count * 4 bytes
*/
token_t *
au_to_newgroups(u_int16_t n, gid_t *groups)
{
token_t *t;
u_char *dptr = NULL;
int i;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
n * sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_NEWGROUPS);
ADD_U_INT16(dptr, n);
for (i = 0; i < n; i++)
ADD_U_INT32(dptr, groups[i]);
return (t);
}
/*
* token ID 1 byte
* internet address 4 bytes
*/
token_t *
au_to_in_addr(struct in_addr *internet_addr)
{
token_t *t;
u_char *dptr = NULL;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(uint32_t));
ADD_U_CHAR(dptr, AUT_IN_ADDR);
ADD_MEM(dptr, &internet_addr->s_addr, sizeof(uint32_t));
return (t);
}
/*
* token ID 1 byte
* address type/length 4 bytes
* Address 16 bytes
*/
token_t *
au_to_in_addr_ex(struct in6_addr *internet_addr)
{
token_t *t;
u_char *dptr = NULL;
u_int32_t type = AF_INET6;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 5 * sizeof(uint32_t));
ADD_U_CHAR(dptr, AUT_IN_ADDR_EX);
ADD_U_INT32(dptr, type);
ADD_MEM(dptr, internet_addr, 5 * sizeof(uint32_t));
return (t);
}
/*
* token ID 1 byte
* ip header 20 bytes
*
* The IP header should be submitted in network byte order.
*/
token_t *
au_to_ip(struct ip *ip)
{
token_t *t;
u_char *dptr = NULL;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(struct ip));
ADD_U_CHAR(dptr, AUT_IP);
ADD_MEM(dptr, ip, sizeof(struct ip));
return (t);
}
/*
* token ID 1 byte
* object ID type 1 byte
* object ID 4 bytes
*/
token_t *
au_to_ipc(char type, int id)
{
token_t *t;
u_char *dptr = NULL;
GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_IPC);
ADD_U_CHAR(dptr, type);
ADD_U_INT32(dptr, id);
return (t);
}
/*
* token ID 1 byte
* owner user ID 4 bytes
* owner group ID 4 bytes
* creator user ID 4 bytes
* creator group ID 4 bytes
* access mode 4 bytes
* slot sequence # 4 bytes
* key 4 bytes
*/
token_t *
au_to_ipc_perm(struct ipc_perm *perm)
{
token_t *t;
u_char *dptr = NULL;
u_int16_t pad0 = 0;
GET_TOKEN_AREA(t, dptr, 12 * sizeof(u_int16_t) + sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_IPC_PERM);
/*
* Darwin defines the sizes for ipc_perm members
* as 2 bytes; BSM defines 4 so pad with 0
*/
ADD_U_INT16(dptr, pad0);
ADD_U_INT16(dptr, perm->uid);
ADD_U_INT16(dptr, pad0);
ADD_U_INT16(dptr, perm->gid);
ADD_U_INT16(dptr, pad0);
ADD_U_INT16(dptr, perm->cuid);
ADD_U_INT16(dptr, pad0);
ADD_U_INT16(dptr, perm->cgid);
ADD_U_INT16(dptr, pad0);
ADD_U_INT16(dptr, perm->mode);
ADD_U_INT16(dptr, pad0);
ADD_U_INT16(dptr, perm->seq);
ADD_U_INT32(dptr, perm->key);
return (t);
}
/*
* token ID 1 byte
* port IP address 2 bytes
*/
token_t *
au_to_iport(u_int16_t iport)
{
token_t *t;
u_char *dptr = NULL;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t));
ADD_U_CHAR(dptr, AUT_IPORT);
ADD_U_INT16(dptr, iport);
return (t);
}
/*
* token ID 1 byte
* size 2 bytes
* data size bytes
*/
token_t *
au_to_opaque(char *data, u_int16_t bytes)
{
token_t *t;
u_char *dptr = NULL;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + bytes);
ADD_U_CHAR(dptr, AUT_OPAQUE);
ADD_U_INT16(dptr, bytes);
ADD_MEM(dptr, data, bytes);
return (t);
}
/*
* token ID 1 byte
* seconds of time 4 bytes
* milliseconds of time 4 bytes
* file name len 2 bytes
* file pathname N bytes + 1 terminating NULL byte
*/
token_t *
au_to_file(char *file, struct timeval tm)
{
token_t *t;
u_char *dptr = NULL;
u_int16_t filelen;
u_int32_t timems;
filelen = strlen(file);
filelen += 1;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int32_t) +
sizeof(u_int16_t) + filelen);
timems = tm.tv_usec/1000;
ADD_U_CHAR(dptr, AUT_OTHER_FILE32);
ADD_U_INT32(dptr, tm.tv_sec);
ADD_U_INT32(dptr, timems); /* We need time in ms. */
ADD_U_INT16(dptr, filelen);
ADD_STRING(dptr, file, filelen);
return (t);
}
/*
* token ID 1 byte
* text length 2 bytes
* text N bytes + 1 terminating NULL byte
*/
token_t *
au_to_text(char *text)
{
token_t *t;
u_char *dptr = NULL;
u_int16_t textlen;
textlen = strlen(text);
textlen += 1;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
ADD_U_CHAR(dptr, AUT_TEXT);
ADD_U_INT16(dptr, textlen);
ADD_STRING(dptr, text, textlen);
return (t);
}
/*
* token ID 1 byte
* path length 2 bytes
* path N bytes + 1 terminating NULL byte
*/
token_t *
au_to_path(char *text)
{
token_t *t;
u_char *dptr = NULL;
u_int16_t textlen;
textlen = strlen(text);
textlen += 1;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) + textlen);
ADD_U_CHAR(dptr, AUT_PATH);
ADD_U_INT16(dptr, textlen);
ADD_STRING(dptr, text, textlen);
return (t);
}
/*
* token ID 1 byte
* audit ID 4 bytes
* effective user ID 4 bytes
* effective group ID 4 bytes
* real user ID 4 bytes
* real group ID 4 bytes
* process ID 4 bytes
* session ID 4 bytes
* terminal ID
* port ID 4 bytes/8 bytes (32-bit/64-bit value)
* machine address 4 bytes
*/
token_t *
au_to_process32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
pid_t pid, au_asid_t sid, au_tid_t *tid)
{
token_t *t;
u_char *dptr = NULL;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_PROCESS32);
ADD_U_INT32(dptr, auid);
ADD_U_INT32(dptr, euid);
ADD_U_INT32(dptr, egid);
ADD_U_INT32(dptr, ruid);
ADD_U_INT32(dptr, rgid);
ADD_U_INT32(dptr, pid);
ADD_U_INT32(dptr, sid);
ADD_U_INT32(dptr, tid->port);
ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
return (t);
}
token_t *
au_to_process64(__unused au_id_t auid, __unused uid_t euid,
__unused gid_t egid, __unused uid_t ruid, __unused gid_t rgid,
__unused pid_t pid, __unused au_asid_t sid, __unused au_tid_t *tid)
{
return (NULL);
}
token_t *
au_to_process(__unused au_id_t auid, __unused uid_t euid,
__unused gid_t egid, __unused uid_t ruid, __unused gid_t rgid,
__unused pid_t pid, __unused au_asid_t sid, __unused au_tid_t *tid)
{
return (au_to_process32(auid, euid, egid, ruid, rgid, pid, sid,
tid));
}
/*
* token ID 1 byte
* audit ID 4 bytes
* effective user ID 4 bytes
* effective group ID 4 bytes
* real user ID 4 bytes
* real group ID 4 bytes
* process ID 4 bytes
* session ID 4 bytes
* terminal ID
* port ID 4 bytes/8 bytes (32-bit/64-bit value)
* address type-len 4 bytes
* machine address 4/16 bytes
*/
token_t *
au_to_process32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
{
token_t *t;
u_char *dptr = NULL;
KASSERT((tid->at_type == AU_IPv4) || (tid->at_type == AU_IPv6),
("au_to_process32_ex: type %u", (unsigned int)tid->at_type));
if (tid->at_type == AU_IPv6)
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 13 *
sizeof(u_int32_t));
else
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 10 *
sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_PROCESS32_EX);
ADD_U_INT32(dptr, auid);
ADD_U_INT32(dptr, euid);
ADD_U_INT32(dptr, egid);
ADD_U_INT32(dptr, ruid);
ADD_U_INT32(dptr, rgid);
ADD_U_INT32(dptr, pid);
ADD_U_INT32(dptr, sid);
ADD_U_INT32(dptr, tid->at_port);
ADD_U_INT32(dptr, tid->at_type);
if (tid->at_type == AU_IPv6)
ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t));
else
ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
return (t);
}
token_t *
au_to_process64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
{
return (NULL);
}
token_t *
au_to_process_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
{
return (au_to_process32_ex(auid, euid, egid, ruid, rgid, pid, sid,
tid));
}
/*
* token ID 1 byte
* error status 1 byte
* return value 4 bytes/8 bytes (32-bit/64-bit value)
*/
token_t *
au_to_return32(char status, u_int32_t ret)
{
token_t *t;
u_char *dptr = NULL;
GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_RETURN32);
ADD_U_CHAR(dptr, status);
ADD_U_INT32(dptr, ret);
return (t);
}
token_t *
au_to_return64(char status, u_int64_t ret)
{
token_t *t;
u_char *dptr = NULL;
GET_TOKEN_AREA(t, dptr, 2 * sizeof(u_char) + sizeof(u_int64_t));
ADD_U_CHAR(dptr, AUT_RETURN64);
ADD_U_CHAR(dptr, status);
ADD_U_INT64(dptr, ret);
return (t);
}
token_t *
au_to_return(char status, u_int32_t ret)
{
return (au_to_return32(status, ret));
}
/*
* token ID 1 byte
* sequence number 4 bytes
*/
token_t *
au_to_seq(long audit_count)
{
token_t *t;
u_char *dptr = NULL;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_SEQ);
ADD_U_INT32(dptr, audit_count);
return (t);
}
/*
* token ID 1 byte
* socket type 2 bytes
* local port 2 bytes
* local Internet address 4 bytes
* remote port 2 bytes
* remote Internet address 4 bytes
*/
token_t *
au_to_socket(struct socket *so)
{
/* XXXRW ... */
return (NULL);
}
/*
* Kernel-specific version of the above function.
*/
#ifdef _KERNEL
token_t *
kau_to_socket(struct socket_au_info *soi)
{
token_t *t;
u_char *dptr;
u_int16_t so_type;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(u_int16_t) +
sizeof(u_int32_t) + sizeof(u_int16_t) + sizeof(u_int32_t));
ADD_U_CHAR(dptr, AU_SOCK_TOKEN);
/* Coerce the socket type into a short value */
so_type = soi->so_type;
ADD_U_INT16(dptr, so_type);
ADD_U_INT16(dptr, soi->so_lport);
ADD_U_INT32(dptr, soi->so_laddr);
ADD_U_INT16(dptr, soi->so_rport);
ADD_U_INT32(dptr, soi->so_raddr);
return (t);
}
#endif
/*
* token ID 1 byte
* socket type 2 bytes
* local port 2 bytes
* address type/length 4 bytes
* local Internet address 4 bytes/16 bytes (IPv4/IPv6 address)
* remote port 4 bytes
* address type/length 4 bytes
* remote Internet address 4 bytes/16 bytes (IPv4/IPv6 address)
*/
token_t *
au_to_socket_ex_32(u_int16_t lp, u_int16_t rp, struct sockaddr *la,
struct sockaddr *ra)
{
return (NULL);
}
token_t *
au_to_socket_ex_128(u_int16_t lp, u_int16_t rp, struct sockaddr *la,
struct sockaddr *ra)
{
return (NULL);
}
/*
* token ID 1 byte
* socket family 2 bytes
* path 104 bytes
*/
token_t *
au_to_sock_unix(struct sockaddr_un *so)
{
token_t *t;
u_char *dptr;
GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + strlen(so->sun_path) + 1);
ADD_U_CHAR(dptr, AU_SOCK_UNIX_TOKEN);
/* BSM token has two bytes for family */
ADD_U_CHAR(dptr, 0);
ADD_U_CHAR(dptr, so->sun_family);
ADD_STRING(dptr, so->sun_path, strlen(so->sun_path) + 1);
return (t);
}
/*
* token ID 1 byte
* socket family 2 bytes
* local port 2 bytes
* socket address 4 bytes
*/
token_t *
au_to_sock_inet32(struct sockaddr_in *so)
{
token_t *t;
u_char *dptr = NULL;
uint16_t family;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 2 * sizeof(uint16_t) +
sizeof(uint32_t));
ADD_U_CHAR(dptr, AUT_SOCKINET32);
/*
* BSM defines the family field as 16 bits, but many operating
* systems have an 8-bit sin_family field. Extend to 16 bits before
* writing into the token. Assume that both the port and the address
* in the sockaddr_in are already in network byte order, but family
* is in local byte order.
*
* XXXRW: Should a name space conversion be taking place on the value
* of sin_family?
*/
family = so->sin_family;
ADD_U_INT16(dptr, family);
ADD_MEM(dptr, &so->sin_port, sizeof(uint16_t));
ADD_MEM(dptr, &so->sin_addr.s_addr, sizeof(uint32_t));
return (t);
}
token_t *
au_to_sock_inet128(struct sockaddr_in6 *so)
{
token_t *t;
u_char *dptr = NULL;
GET_TOKEN_AREA(t, dptr, 3 * sizeof(u_char) + sizeof(u_int16_t) +
4 * sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_SOCKINET128);
/*
* In Darwin, sin6_family is one octet, but BSM defines the token
* to store two. So we copy in a 0 first.
*/
ADD_U_CHAR(dptr, 0);
ADD_U_CHAR(dptr, so->sin6_family);
ADD_U_INT16(dptr, so->sin6_port);
ADD_MEM(dptr, &so->sin6_addr, 4 * sizeof(uint32_t));
return (t);
}
token_t *
au_to_sock_inet(struct sockaddr_in *so)
{
return (au_to_sock_inet32(so));
}
/*
* token ID 1 byte
* audit ID 4 bytes
* effective user ID 4 bytes
* effective group ID 4 bytes
* real user ID 4 bytes
* real group ID 4 bytes
* process ID 4 bytes
* session ID 4 bytes
* terminal ID
* port ID 4 bytes/8 bytes (32-bit/64-bit value)
* machine address 4 bytes
*/
token_t *
au_to_subject32(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
pid_t pid, au_asid_t sid, au_tid_t *tid)
{
token_t *t;
u_char *dptr = NULL;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 9 * sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_SUBJECT32);
ADD_U_INT32(dptr, auid);
ADD_U_INT32(dptr, euid);
ADD_U_INT32(dptr, egid);
ADD_U_INT32(dptr, ruid);
ADD_U_INT32(dptr, rgid);
ADD_U_INT32(dptr, pid);
ADD_U_INT32(dptr, sid);
ADD_U_INT32(dptr, tid->port);
ADD_MEM(dptr, &tid->machine, sizeof(u_int32_t));
return (t);
}
token_t *
au_to_subject64(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
pid_t pid, au_asid_t sid, au_tid_t *tid)
{
return (NULL);
}
token_t *
au_to_subject(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid, gid_t rgid,
pid_t pid, au_asid_t sid, au_tid_t *tid)
{
return (au_to_subject32(auid, euid, egid, ruid, rgid, pid, sid,
tid));
}
/*
* token ID 1 byte
* audit ID 4 bytes
* effective user ID 4 bytes
* effective group ID 4 bytes
* real user ID 4 bytes
* real group ID 4 bytes
* process ID 4 bytes
* session ID 4 bytes
* terminal ID
* port ID 4 bytes/8 bytes (32-bit/64-bit value)
* address type/length 4 bytes
* machine address 4/16 bytes
*/
token_t *
au_to_subject32_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
{
token_t *t;
u_char *dptr = NULL;
KASSERT((tid->at_type == AU_IPv4) || (tid->at_type == AU_IPv6),
("au_to_subject32_ex: type %u", (unsigned int)tid->at_type));
if (tid->at_type == AU_IPv6)
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 13 *
sizeof(u_int32_t));
else
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + 10 *
sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_SUBJECT32_EX);
ADD_U_INT32(dptr, auid);
ADD_U_INT32(dptr, euid);
ADD_U_INT32(dptr, egid);
ADD_U_INT32(dptr, ruid);
ADD_U_INT32(dptr, rgid);
ADD_U_INT32(dptr, pid);
ADD_U_INT32(dptr, sid);
ADD_U_INT32(dptr, tid->at_port);
ADD_U_INT32(dptr, tid->at_type);
if (tid->at_type == AU_IPv6)
ADD_MEM(dptr, &tid->at_addr[0], 4 * sizeof(u_int32_t));
else
ADD_MEM(dptr, &tid->at_addr[0], sizeof(u_int32_t));
return (t);
}
token_t *
au_to_subject64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
{
return (NULL);
}
token_t *
au_to_subject_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid)
{
return (au_to_subject32_ex(auid, euid, egid, ruid, rgid, pid, sid,
tid));
}
#if !defined(_KERNEL) && !defined(KERNEL) && defined(HAVE_AUDIT_SYSCALLS)
/*
* Collects audit information for the current process
* and creates a subject token from it
*/
token_t *
au_to_me(void)
{
auditinfo_t auinfo;
if (getaudit(&auinfo) != 0)
return (NULL);
return (au_to_subject32(auinfo.ai_auid, geteuid(), getegid(),
getuid(), getgid(), getpid(), auinfo.ai_asid, &auinfo.ai_termid));
}
#endif
#if defined(_KERNEL) || defined(KERNEL)
static token_t *
au_to_exec_strings(char *strs, int count, u_char type)
{
token_t *t;
u_char *dptr = NULL;
u_int32_t totlen;
int ctr;
char *p;
totlen = 0;
ctr = count;
p = strs;
while (ctr-- > 0) {
totlen += strlen(p) + 1;
p = strs + totlen;
}
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
ADD_U_CHAR(dptr, type);
ADD_U_INT32(dptr, count);
ADD_STRING(dptr, strs, totlen);
return (t);
}
/*
* token ID 1 byte
* count 4 bytes
* text count null-terminated strings
*/
token_t *
au_to_exec_args(char *args, int argc)
{
return (au_to_exec_strings(args, argc, AUT_EXEC_ARGS));
}
/*
* token ID 1 byte
* count 4 bytes
* text count null-terminated strings
*/
token_t *
au_to_exec_env(char *envs, int envc)
{
return (au_to_exec_strings(envs, envc, AUT_EXEC_ENV));
}
#else
/*
* token ID 1 byte
* count 4 bytes
* text count null-terminated strings
*/
token_t *
au_to_exec_args(char **argv)
{
token_t *t;
u_char *dptr = NULL;
const char *nextarg;
int i, count = 0;
size_t totlen = 0;
nextarg = *argv;
while (nextarg != NULL) {
int nextlen;
nextlen = strlen(nextarg);
totlen += nextlen + 1;
count++;
nextarg = *(argv + count);
}
totlen += count * sizeof(char); /* nul terminations. */
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
ADD_U_CHAR(dptr, AUT_EXEC_ARGS);
ADD_U_INT32(dptr, count);
for (i = 0; i < count; i++) {
nextarg = *(argv + i);
ADD_MEM(dptr, nextarg, strlen(nextarg) + 1);
}
return (t);
}
/*
* token ID 1 byte
* count 4 bytes
* text count null-terminated strings
*/
token_t *
au_to_exec_env(char **envp)
{
token_t *t;
u_char *dptr = NULL;
int i, count = 0;
size_t totlen = 0;
const char *nextenv;
nextenv = *envp;
while (nextenv != NULL) {
int nextlen;
nextlen = strlen(nextenv);
totlen += nextlen + 1;
count++;
nextenv = *(envp + count);
}
totlen += sizeof(char) * count;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) + totlen);
ADD_U_CHAR(dptr, AUT_EXEC_ENV);
ADD_U_INT32(dptr, count);
for (i = 0; i < count; i++) {
nextenv = *(envp + i);
ADD_MEM(dptr, nextenv, strlen(nextenv) + 1);
}
return (t);
}
#endif
/*
* token ID 1 byte
* record byte count 4 bytes
* version # 1 byte [2]
* event type 2 bytes
* event modifier 2 bytes
* seconds of time 4 bytes/8 bytes (32-bit/64-bit value)
* milliseconds of time 4 bytes/8 bytes (32-bit/64-bit value)
*/
token_t *
au_to_header32_tm(int rec_size, au_event_t e_type, au_emod_t e_mod,
struct timeval tm)
{
token_t *t;
u_char *dptr = NULL;
u_int32_t timems;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int32_t) +
sizeof(u_char) + 2 * sizeof(u_int16_t) + 2 * sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_HEADER32);
ADD_U_INT32(dptr, rec_size);
ADD_U_CHAR(dptr, AUDIT_HEADER_VERSION_OPENBSM);
ADD_U_INT16(dptr, e_type);
ADD_U_INT16(dptr, e_mod);
timems = tm.tv_usec/1000;
/* Add the timestamp */
ADD_U_INT32(dptr, tm.tv_sec);
ADD_U_INT32(dptr, timems); /* We need time in ms. */
return (t);
}
/*
* token ID 1 byte
* trailer magic number 2 bytes
* record byte count 4 bytes
*/
token_t *
au_to_trailer(int rec_size)
{
token_t *t;
u_char *dptr = NULL;
u_int16_t magic = TRAILER_PAD_MAGIC;
GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(u_int16_t) +
sizeof(u_int32_t));
ADD_U_CHAR(dptr, AUT_TRAILER);
ADD_U_INT16(dptr, magic);
ADD_U_INT32(dptr, rec_size);
return (t);
}