Compare commits
10 Commits
2f1fc7e526
...
v0.6
Author | SHA1 | Date | |
---|---|---|---|
9b849fad3a | |||
e9c7c7b744 | |||
74ad307bd1 | |||
d1aedbb521 | |||
2a101d89d0 | |||
e801a48c7c | |||
58ba24444d | |||
23441feaae | |||
ad4a46104c | |||
99bf812571 |
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
./20211228134923.20211228151348
|
./20211228134923.20211228151348
|
||||||
tmpwrk
|
tmpwrk
|
||||||
|
godit
|
||||||
|
@ -4,3 +4,7 @@ Golang implementation of openBSM library
|
|||||||
|
|
||||||
BSM is the audit format used by Darwin/FreeBSD
|
BSM is the audit format used by Darwin/FreeBSD
|
||||||
See http://www.trustedbsd.org/openbsm.html
|
See http://www.trustedbsd.org/openbsm.html
|
||||||
|
|
||||||
|
Include a binary "godit" which print audit logs in text or json format
|
||||||
|
Godit can read log files, /dev/auditpipe, or stdin with "-"
|
||||||
|
|
||||||
|
242
capsicum.go
Normal file
242
capsicum.go
Normal file
@ -0,0 +1,242 @@
|
|||||||
|
// This is an implementation of libbsm
|
||||||
|
// Copyright johan@nosd.in 2023
|
||||||
|
//
|
||||||
|
//go:build freebsd
|
||||||
|
// +build freebsd
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
|
||||||
|
const (
|
||||||
|
// From freeebsd-src/sys/sys/caprights.h :
|
||||||
|
/*
|
||||||
|
* The top two bits in the first element of the cr_rights[] array contain
|
||||||
|
* total number of elements in the array - 2. This means if those two bits are
|
||||||
|
* equal to 0, we have 2 array elements.
|
||||||
|
* The top two bits in all remaining array elements should be 0.
|
||||||
|
* The next five bits contain array index. Only one bit is used and bit position
|
||||||
|
* in this five-bits range defines array index. This means there can be at most
|
||||||
|
* five array elements.
|
||||||
|
*/
|
||||||
|
// So, I lazily chose to include index bit in following values
|
||||||
|
/* INDEX 0 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* General file I/O.
|
||||||
|
*/
|
||||||
|
/* Allows for openat(O_RDONLY), read(2), readv(2). */
|
||||||
|
CAP_READ = 0x0200000000000001
|
||||||
|
/* Allows for openat(O_WRONLY | O_APPEND), write(2), writev(2). */
|
||||||
|
CAP_WRITE = 0x0200000000000002
|
||||||
|
/* Allows for lseek(fd, 0, SEEK_CUR). */
|
||||||
|
CAP_SEEK_TELL = 0x0200000000000004
|
||||||
|
/* Allows for lseek(2). */
|
||||||
|
CAP_SEEK = CAP_SEEK_TELL | 0x0200000000000008
|
||||||
|
/* Allows for aio_read(2), pread(2), preadv(2). */
|
||||||
|
CAP_PREAD = (CAP_SEEK | CAP_READ)
|
||||||
|
/*
|
||||||
|
* Allows for aio_write(2), openat(O_WRONLY) (without O_APPEND), pwrite(2),
|
||||||
|
* pwritev(2).
|
||||||
|
*/
|
||||||
|
CAP_PWRITE = (CAP_SEEK | CAP_WRITE)
|
||||||
|
/* Allows for mmap(PROT_NONE). */
|
||||||
|
CAP_MMAP = 0x0200000000000010
|
||||||
|
/* Allows for mmap(PROT_READ). */
|
||||||
|
CAP_MMAP_R = (CAP_MMAP | CAP_SEEK | CAP_READ)
|
||||||
|
/* Allows for mmap(PROT_WRITE). */
|
||||||
|
CAP_MMAP_W = (CAP_MMAP | CAP_SEEK | CAP_WRITE)
|
||||||
|
/* Allows for mmap(PROT_EXEC). */
|
||||||
|
CAP_MMAP_X = (CAP_MMAP | CAP_SEEK | 0x0200000000000020)
|
||||||
|
/* Allows for mmap(PROT_READ | PROT_WRITE). */
|
||||||
|
CAP_MMAP_RW = (CAP_MMAP_R | CAP_MMAP_W)
|
||||||
|
/* Allows for mmap(PROT_READ | PROT_EXEC). */
|
||||||
|
CAP_MMAP_RX = (CAP_MMAP_R | CAP_MMAP_X)
|
||||||
|
/* Allows for mmap(PROT_WRITE | PROT_EXEC). */
|
||||||
|
CAP_MMAP_WX = (CAP_MMAP_W | CAP_MMAP_X)
|
||||||
|
/* Allows for mmap(PROT_READ | PROT_WRITE | PROT_EXEC). */
|
||||||
|
CAP_MMAP_RWX = (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X)
|
||||||
|
/* Allows for openat(O_CREAT). */
|
||||||
|
CAP_CREATE = 0x0200000000000040
|
||||||
|
/* Allows for openat(O_EXEC) and fexecve(2) in turn. */
|
||||||
|
CAP_FEXECVE = 0x0200000000000080
|
||||||
|
/* Allows for openat(O_SYNC), openat(O_FSYNC), fsync(2), aio_fsync(2). */
|
||||||
|
CAP_FSYNC = 0x0200000000000100
|
||||||
|
/* Allows for openat(O_TRUNC), ftruncate(2). */
|
||||||
|
CAP_FTRUNCATE = 0x0200000000000200
|
||||||
|
|
||||||
|
/* Lookups - used to constrain *at() calls. */
|
||||||
|
CAP_LOOKUP = 0x0200000000000400
|
||||||
|
|
||||||
|
/* VFS methods. */
|
||||||
|
/* Allows for fchdir(2). */
|
||||||
|
CAP_FCHDIR = 0x0200000000000800
|
||||||
|
/* Allows for fchflags(2). */
|
||||||
|
CAP_FCHFLAGS = 0x0200000000001000
|
||||||
|
/* Allows for fchflags(2) and chflagsat(2). */
|
||||||
|
CAP_CHFLAGSAT = (CAP_FCHFLAGS | CAP_LOOKUP)
|
||||||
|
/* Allows for fchmod(2). */
|
||||||
|
CAP_FCHMOD = 0x0200000000002000
|
||||||
|
/* Allows for fchmod(2) and fchmodat(2). */
|
||||||
|
CAP_FCHMODAT = (CAP_FCHMOD | CAP_LOOKUP)
|
||||||
|
/* Allows for fchown(2). */
|
||||||
|
CAP_FCHOWN = 0x0200000000004000
|
||||||
|
/* Allows for fchown(2) and fchownat(2). */
|
||||||
|
CAP_FCHOWNAT = (CAP_FCHOWN | CAP_LOOKUP)
|
||||||
|
/* Allows for fcntl(2). */
|
||||||
|
CAP_FCNTL = 0x0200000000008000
|
||||||
|
/*
|
||||||
|
* Allows for flock(2), openat(O_SHLOCK), openat(O_EXLOCK),
|
||||||
|
* fcntl(F_SETLK_REMOTE), fcntl(F_SETLKW), fcntl(F_SETLK), fcntl(F_GETLK).
|
||||||
|
*/
|
||||||
|
CAP_FLOCK = 0x0200000000010000
|
||||||
|
/* Allows for fpathconf(2). */
|
||||||
|
CAP_FPATHCONF = 0x0200000000020000
|
||||||
|
/* Allows for UFS background-fsck operations. */
|
||||||
|
CAP_FSCK = 0x0200000000040000
|
||||||
|
/* Allows for fstat(2). */
|
||||||
|
CAP_FSTAT = 0x0200000000080000
|
||||||
|
/* Allows for fstat(2), fstatat(2) and faccessat(2). */
|
||||||
|
CAP_FSTATAT = (CAP_FSTAT | CAP_LOOKUP)
|
||||||
|
/* Allows for fstatfs(2). */
|
||||||
|
CAP_FSTATFS = 0x0200000000100000
|
||||||
|
/* Allows for futimens(2) and futimes(2). */
|
||||||
|
CAP_FUTIMES = 0x0200000000200000
|
||||||
|
/* Allows for futimens(2), futimes(2), futimesat(2) and utimensat(2). */
|
||||||
|
CAP_FUTIMESAT = (CAP_FUTIMES | CAP_LOOKUP)
|
||||||
|
/* Allows for linkat(2) (target directory descriptor). */
|
||||||
|
CAP_LINKAT_TARGET = (CAP_LOOKUP | 0x0200000000400000)
|
||||||
|
/* Allows for mkdirat(2). */
|
||||||
|
CAP_MKDIRAT = (CAP_LOOKUP | 0x0200000000800000)
|
||||||
|
/* Allows for mkfifoat(2). */
|
||||||
|
CAP_MKFIFOAT = (CAP_LOOKUP | 0x0200000001000000)
|
||||||
|
/* Allows for mknodat(2). */
|
||||||
|
CAP_MKNODAT = (CAP_LOOKUP | 0x0200000002000000)
|
||||||
|
/* Allows for renameat(2) (source directory descriptor). */
|
||||||
|
CAP_RENAMEAT_SOURCE = (CAP_LOOKUP | 0x0200000004000000)
|
||||||
|
/* Allows for symlinkat(2). */
|
||||||
|
CAP_SYMLINKAT = (CAP_LOOKUP | 0x0200000008000000)
|
||||||
|
/*
|
||||||
|
* Allows for unlinkat(2) and renameat(2) if destination object exists and
|
||||||
|
* will be removed.
|
||||||
|
*/
|
||||||
|
CAP_UNLINKAT = (CAP_LOOKUP | 0x0200000010000000)
|
||||||
|
|
||||||
|
/* Socket operations. */
|
||||||
|
/* Allows for accept(2) and accept4(2). */
|
||||||
|
CAP_ACCEPT = 0x0200000020000000
|
||||||
|
/* Allows for bind(2). */
|
||||||
|
CAP_BIND = 0x0200000040000000
|
||||||
|
/* Allows for connect(2). */
|
||||||
|
CAP_CONNECT = 0x0200000080000000
|
||||||
|
/* Allows for getpeername(2). */
|
||||||
|
CAP_GETPEERNAME = 0x0200000100000000
|
||||||
|
/* Allows for getsockname(2). */
|
||||||
|
CAP_GETSOCKNAME = 0x0200000200000000
|
||||||
|
/* Allows for getsockopt(2). */
|
||||||
|
CAP_GETSOCKOPT = 0x0200000400000000
|
||||||
|
/* Allows for listen(2). */
|
||||||
|
CAP_LISTEN = 0x0200000800000000
|
||||||
|
/* Allows for sctp_peeloff(2). */
|
||||||
|
CAP_PEELOFF = 0x0300001000000000
|
||||||
|
CAP_RECV = CAP_READ
|
||||||
|
CAP_SEND = CAP_WRITE
|
||||||
|
/* Allows for setsockopt(2). */
|
||||||
|
CAP_SETSOCKOPT = 0x0200002000000000
|
||||||
|
/* Allows for shutdown(2). */
|
||||||
|
CAP_SHUTDOWN = 0x0200004000000000
|
||||||
|
|
||||||
|
/* Allows for bindat(2) on a directory descriptor. */
|
||||||
|
CAP_BINDAT = (CAP_LOOKUP | 0x0200008000000000)
|
||||||
|
/* Allows for connectat(2) on a directory descriptor. */
|
||||||
|
CAP_CONNECTAT = (CAP_LOOKUP | 0x0200010000000000)
|
||||||
|
|
||||||
|
/* Allows for linkat(2) (source directory descriptor). */
|
||||||
|
CAP_LINKAT_SOURCE = (CAP_LOOKUP | 0x0200020000000000)
|
||||||
|
/* Allows for renameat(2) (target directory descriptor). */
|
||||||
|
CAP_RENAMEAT_TARGET = (CAP_LOOKUP | 0x0200040000000000)
|
||||||
|
|
||||||
|
CAP_SOCK_CLIENT = (CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT |
|
||||||
|
CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN)
|
||||||
|
CAP_SOCK_SERVER = (CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME |
|
||||||
|
CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND |
|
||||||
|
CAP_SETSOCKOPT | CAP_SHUTDOWN)
|
||||||
|
|
||||||
|
/* All used bits for index 0. */
|
||||||
|
CAP_ALL0 = 0x020007FFFFFFFFFF
|
||||||
|
|
||||||
|
/* Available bits for index 0. */
|
||||||
|
CAP_UNUSED0_44 = 0x0200080000000000
|
||||||
|
/* ... */
|
||||||
|
CAP_UNUSED0_57 = 0x0300000000000000
|
||||||
|
|
||||||
|
/* INDEX 1 */
|
||||||
|
|
||||||
|
/* Mandatory Access Control. */
|
||||||
|
/* Allows for mac_get_fd(3). */
|
||||||
|
CAP_MAC_GET = 0x0400000000000001
|
||||||
|
/* Allows for mac_set_fd(3). */
|
||||||
|
CAP_MAC_SET = 0x0400000000000002
|
||||||
|
|
||||||
|
/* Methods on semaphores. */
|
||||||
|
CAP_SEM_GETVALUE = 0x0400000000000004
|
||||||
|
CAP_SEM_POST = 0x0400000000000008
|
||||||
|
CAP_SEM_WAIT = 0x0400000000000010
|
||||||
|
|
||||||
|
/* Allows select(2) and poll(2) on descriptor. */
|
||||||
|
CAP_EVENT = 0x0400000000000020
|
||||||
|
/* Allows for kevent(2) on kqueue descriptor with eventlist != NULL. */
|
||||||
|
CAP_KQUEUE_EVENT = 0x0400000000000040
|
||||||
|
|
||||||
|
/* Strange and powerful rights that should not be given lightly. */
|
||||||
|
/* Allows for ioctl(2). */
|
||||||
|
CAP_IOCTL = 0x0400000000000080
|
||||||
|
CAP_TTYHOOK = 0x0400000000000100
|
||||||
|
|
||||||
|
/* Process management via process descriptors. */
|
||||||
|
/* Allows for pdgetpid(2). */
|
||||||
|
CAP_PDGETPID = 0x0400000000000200
|
||||||
|
/*
|
||||||
|
* Allows for pdwait4(2).
|
||||||
|
*
|
||||||
|
* XXX: this constant was imported unused, but is targeted to be implemented
|
||||||
|
* in the future (bug 235871).
|
||||||
|
*/
|
||||||
|
CAP_PDWAIT = 0x0400000000000400
|
||||||
|
/* Allows for pdkill(2). */
|
||||||
|
CAP_PDKILL = 0x0400000000000800
|
||||||
|
|
||||||
|
/* Extended attributes. */
|
||||||
|
/* Allows for extattr_delete_fd(2). */
|
||||||
|
CAP_EXTATTR_DELETE = 0x0400000000001000
|
||||||
|
/* Allows for extattr_get_fd(2). */
|
||||||
|
CAP_EXTATTR_GET = 0x0400000000002000
|
||||||
|
/* Allows for extattr_list_fd(2). */
|
||||||
|
CAP_EXTATTR_LIST = 0x0400000000004000
|
||||||
|
/* Allows for extattr_set_fd(2). */
|
||||||
|
CAP_EXTATTR_SET = 0x0400000000008000
|
||||||
|
|
||||||
|
/* Access Control Lists. */
|
||||||
|
/* Allows for acl_valid_fd_np(3). */
|
||||||
|
CAP_ACL_CHECK = 0x0400000000010000
|
||||||
|
/* Allows for acl_delete_fd_np(3). */
|
||||||
|
CAP_ACL_DELETE = 0x0400000000020000
|
||||||
|
/* Allows for acl_get_fd(3) and acl_get_fd_np(3). */
|
||||||
|
CAP_ACL_GET = 0x0400000000040000
|
||||||
|
/* Allows for acl_set_fd(3) and acl_set_fd_np(3). */
|
||||||
|
CAP_ACL_SET = 0x0400000000080000
|
||||||
|
|
||||||
|
/* Allows for kevent(2) on kqueue descriptor with changelist != NULL. */
|
||||||
|
CAP_KQUEUE_CHANGE = 0x0400000000100000
|
||||||
|
|
||||||
|
CAP_KQUEUE = (CAP_KQUEUE_EVENT | CAP_KQUEUE_CHANGE)
|
||||||
|
|
||||||
|
/* All used bits for index 1. */
|
||||||
|
CAP_ALL1 = 0x04000000001FFFFF
|
||||||
|
|
||||||
|
/* Available bits for index 1. */
|
||||||
|
CAP_UNUSED1_22 = 0x0400000000200000
|
||||||
|
/* ... */
|
||||||
|
CAP_UNUSED1_57 = 0x0500000000000000
|
||||||
|
)
|
201
libbsm.go
201
libbsm.go
@ -120,14 +120,16 @@ const (
|
|||||||
AUT_PROCESS64_EX = 0x7d
|
AUT_PROCESS64_EX = 0x7d
|
||||||
AUT_IN_ADDR_EX = 0x7e
|
AUT_IN_ADDR_EX = 0x7e
|
||||||
AUT_SOCKET_EX = 0x7f
|
AUT_SOCKET_EX = 0x7f
|
||||||
|
// From sys/bsm/audit_record.h
|
||||||
AUT_SOCKINET32 = 0x80
|
AUT_SOCKINET32 = 0x80
|
||||||
AUT_SOCKINET128 = 0x81
|
AUT_SOCKINET128 = 0x81
|
||||||
AUT_SOCKUNIX = 0x82
|
AUT_SOCKUNIX = 0x82
|
||||||
|
AUT_RIGHTS = 0x83
|
||||||
|
|
||||||
// Display control
|
// Display control
|
||||||
PRT_ONELINE = 1
|
PRT_ONELINE = 1
|
||||||
PRT_NORESOLVE_USER = 2
|
PRT_NORESOLVE_USER = 2
|
||||||
PRT_TIMESTAMP = 4
|
PRT_TIMESYSLOG23 = 4
|
||||||
PRT_JSON = 8
|
PRT_JSON = 8
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -373,6 +375,17 @@ type ZoneName struct {
|
|||||||
Zone []byte `json:"zone"`
|
Zone []byte `json:"zone"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Capabilities struct {
|
||||||
|
Index uint8 `json:"index"`
|
||||||
|
Value uint64 `json:"value"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Rights struct {
|
||||||
|
Length uint8 `json:"length"` // Should it be nr of indices, or nr of capabilities? (in which case it should be calculated)
|
||||||
|
// Let it be nr of indices for now, we'll see when we will decode rights
|
||||||
|
Rights []Capabilities `json:"rights"`
|
||||||
|
}
|
||||||
|
|
||||||
/* Utilities */
|
/* Utilities */
|
||||||
// users ID for resolution
|
// users ID for resolution
|
||||||
type user struct {
|
type user struct {
|
||||||
@ -594,8 +607,8 @@ print_header32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags)
|
|||||||
*/
|
*/
|
||||||
func (h *Header32) Print(file *os.File, delimiter string, flags int) {
|
func (h *Header32) Print(file *os.File, delimiter string, flags int) {
|
||||||
var timeval string
|
var timeval string
|
||||||
if PRT_TIMESTAMP == flags&PRT_TIMESTAMP {
|
if PRT_TIMESYSLOG23 == flags&PRT_TIMESYSLOG23 {
|
||||||
timeval = strconv.Itoa(int(h.S))
|
timeval = time.Unix((int64)(h.S), 0).Add(time.Millisecond * (time.Duration)(h.Msec)).Format("2006-01-02T15:04:05.000Z07:00")
|
||||||
} else {
|
} else {
|
||||||
t := time.Unix((int64)(h.S), 0)
|
t := time.Unix((int64)(h.S), 0)
|
||||||
timeval = t.Format(time.UnixDate)
|
timeval = t.Format(time.UnixDate)
|
||||||
@ -607,20 +620,37 @@ func (h *Header32) Print(file *os.File, delimiter string, flags int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if flags&PRT_JSON == PRT_JSON {
|
if flags&PRT_JSON == PRT_JSON {
|
||||||
printable := struct {
|
var printable interface{}
|
||||||
Size uint32 `json:"size"` // Record byte count
|
if PRT_TIMESYSLOG23 == flags&PRT_TIMESYSLOG23 {
|
||||||
Version uint8 `json:"version"` // version # (uchar)
|
printable = struct {
|
||||||
E_type string `json:"event_type"` // Event type
|
Size uint32 `json:"size"` // Record byte count
|
||||||
E_mod uint16 `json:"event_modifier"` // Event modifier
|
Version uint8 `json:"version"` // version # (uchar)
|
||||||
Ts string `json:"timestamp"` // Seconds of time converted to data/hour/DST
|
E_type string `json:"event_type"` // Event type
|
||||||
Msec uint32 `json:"msec"` // Milliseconds of time
|
E_mod uint16 `json:"event_modifier"` // Event modifier
|
||||||
}{
|
Ts string `json:"timestamp"` // Seconds of time converted to RSYSLOG_SyslogProtocol23Format
|
||||||
Size: h.Size,
|
}{
|
||||||
Version: h.Version,
|
Size: h.Size,
|
||||||
E_type: evdesc,
|
Version: h.Version,
|
||||||
E_mod: h.E_mod,
|
E_type: evdesc,
|
||||||
Ts: timeval,
|
E_mod: h.E_mod,
|
||||||
Msec: h.Msec,
|
Ts: timeval,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
printable = struct {
|
||||||
|
Size uint32 `json:"size"` // Record byte count
|
||||||
|
Version uint8 `json:"version"` // version # (uchar)
|
||||||
|
E_type string `json:"event_type"` // Event type
|
||||||
|
E_mod uint16 `json:"event_modifier"` // Event modifier
|
||||||
|
Ts string `json:"timestamp"` // Seconds of time converted to data/hour/DST
|
||||||
|
Msec uint32 `json:"msec"` // Milliseconds of time
|
||||||
|
}{
|
||||||
|
Size: h.Size,
|
||||||
|
Version: h.Version,
|
||||||
|
E_type: evdesc,
|
||||||
|
E_mod: h.E_mod,
|
||||||
|
Ts: timeval,
|
||||||
|
Msec: h.Msec,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
j, err := json.Marshal(printable)
|
j, err := json.Marshal(printable)
|
||||||
@ -2972,14 +3002,136 @@ func (z *ZoneName) LoadFromBinary(rdr *bufio.Reader) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (z *ZoneName) Print(file *os.File, delimiter string, flags int) {
|
func (z *ZoneName) Print(file *os.File, delimiter string, flags int) {
|
||||||
fmt.Fprintf(file, "zone%s%s", delimiter, z.Zone)
|
if flags&PRT_JSON == PRT_JSON {
|
||||||
if 0 == (flags & PRT_ONELINE) {
|
printable := struct {
|
||||||
fmt.Fprintf(file, "\n")
|
Name string `json:"name"`
|
||||||
|
}{
|
||||||
|
Name: string(z.Zone),
|
||||||
|
}
|
||||||
|
j, err := json.Marshal(printable)
|
||||||
|
if err != nil {
|
||||||
|
// TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Fprintf(file, "\"zone\":")
|
||||||
|
fmt.Fprintf(file, "%s", j)
|
||||||
|
// ZoneName is always followed by something
|
||||||
|
fmt.Fprintf(file, ",")
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(file, "%s", delimiter)
|
fmt.Fprintf(file, "zone%s%s", delimiter, z.Zone)
|
||||||
|
if 0 == (flags & PRT_ONELINE) {
|
||||||
|
fmt.Fprintf(file, "\n")
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(file, "%s", delimiter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewRights(r Rights) *Rights {
|
||||||
|
return &Rights{
|
||||||
|
Length: r.Length,
|
||||||
|
Rights: r.Rights,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rights) GetType() uint8 {
|
||||||
|
return AUT_RIGHTS
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rights) getIndex(value uint64) uint8 {
|
||||||
|
var index uint8
|
||||||
|
idx := (value >> 57) & 0b11111
|
||||||
|
switch idx {
|
||||||
|
case 1: index = 0
|
||||||
|
case 2: index = 1
|
||||||
|
case 4: index = 2
|
||||||
|
case 8: index = 3
|
||||||
|
case 16: index = 4
|
||||||
|
}
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rights) LoadFromBinary(rdr *bufio.Reader) error {
|
||||||
|
var firstVal uint64
|
||||||
|
var nextVal uint64
|
||||||
|
err := binary.Read(rdr, binary.BigEndian, &firstVal)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to read Rights.Length: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The top two bits in the first element of the cr_rights[] array contain
|
||||||
|
* total number of elements in the array - 2 */
|
||||||
|
r.Length = uint8((firstVal >> 62) + 2)
|
||||||
|
|
||||||
|
rights := make([]Capabilities, r.Length)
|
||||||
|
capab := &Capabilities{
|
||||||
|
Index: r.getIndex(firstVal),
|
||||||
|
Value: firstVal,
|
||||||
|
}
|
||||||
|
rights[0] = *capab
|
||||||
|
|
||||||
|
for i := 1; i < int(r.Length); i++ {
|
||||||
|
err = binary.Read(rdr, binary.BigEndian, &nextVal)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("Unable to read Rights.Rights: %v", err)
|
||||||
|
} else {
|
||||||
|
capab := &Capabilities{
|
||||||
|
Index: r.getIndex(nextVal),
|
||||||
|
Value: nextVal,
|
||||||
|
}
|
||||||
|
rights[i] = *capab
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r.Rights = rights[:r.Length]
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override Capabilities Marshaling so we can print as hex
|
||||||
|
func (c *Capabilities) MarshalJSON() ([]byte, error) {
|
||||||
|
val := fmt.Sprintf("%0.16x", c.Value)
|
||||||
|
|
||||||
|
type CapabilitiesJSON Capabilities
|
||||||
|
cJSON := struct {
|
||||||
|
Capabilities
|
||||||
|
Value string `json:"value"`
|
||||||
|
}{
|
||||||
|
Capabilities: Capabilities(*c),
|
||||||
|
Value: val,
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(cJSON)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Rights) Print(file *os.File, delimiter string, flags int) {
|
||||||
|
if flags&PRT_JSON == PRT_JSON {
|
||||||
|
// Do not print Rights.Length, only capabilities array
|
||||||
|
j, err := json.Marshal(r.Rights)
|
||||||
|
if err != nil {
|
||||||
|
// TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Fprintf(file, "\"rights\":")
|
||||||
|
fmt.Fprintf(file, "%s", j)
|
||||||
|
// Rights is always followed by something
|
||||||
|
fmt.Fprintf(file, ",")
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(file, "rights%s%d", delimiter, r.Length)
|
||||||
|
for i:=0; i < int(r.Length); i++ {
|
||||||
|
if i < int(r.Length) {
|
||||||
|
fmt.Fprintf(file, "%s", delimiter)
|
||||||
|
}
|
||||||
|
fmt.Fprintf(file, "%d%s%0.16x", r.Rights[i].Index, delimiter, r.Rights[i].Value)
|
||||||
|
}
|
||||||
|
if 0 == (flags & PRT_ONELINE) {
|
||||||
|
fmt.Fprintf(file, "\n")
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(file, "%s", delimiter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// From sys/bsm/audit_record.h
|
// From sys/bsm/audit_record.h
|
||||||
func readRecordToStruct(reader *bufio.Reader) (Record, error) {
|
func readRecordToStruct(reader *bufio.Reader) (Record, error) {
|
||||||
@ -3149,6 +3301,13 @@ func readRecordToStruct(reader *bufio.Reader) (Record, error) {
|
|||||||
return rec, fmt.Errorf("Unable to read: %v", err)
|
return rec, fmt.Errorf("Unable to read: %v", err)
|
||||||
}
|
}
|
||||||
return NewZoneName(z), nil
|
return NewZoneName(z), nil
|
||||||
|
case AUT_RIGHTS:
|
||||||
|
var r Rights
|
||||||
|
err := r.LoadFromBinary(reader)
|
||||||
|
if err != nil {
|
||||||
|
return rec, fmt.Errorf("Unable to read: %v", err)
|
||||||
|
}
|
||||||
|
return NewRights(r), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return rec, fmt.Errorf("Event type not supported: 0x%x", hdr[0])
|
return rec, fmt.Errorf("Event type not supported: 0x%x", hdr[0])
|
||||||
|
22
main.go
22
main.go
@ -33,7 +33,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
version = "5.9.9a"
|
version = "0.6"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -48,13 +48,21 @@ func main() {
|
|||||||
var flags int
|
var flags int
|
||||||
var oneLine bool
|
var oneLine bool
|
||||||
var noUserResolve bool
|
var noUserResolve bool
|
||||||
var timestamp bool
|
var syslog23 bool
|
||||||
var json bool
|
var json bool
|
||||||
|
|
||||||
pflag.BoolVarP(&oneLine, "oneline", "l", false, "Prints the entire record on the same line. If this option is not specified, every token is displayed on a different line.")
|
pflag.BoolVarP(&oneLine, "oneline", "l", false, "Prints the entire record on the same line")
|
||||||
pflag.BoolVarP(&noUserResolve, "numeric", "n", false, "Do not convert user and group IDs to their names but leave in their numeric forms.")
|
pflag.BoolVarP(&noUserResolve, "numeric", "n", false, "Do not convert user and group IDs to their names but leave in their numeric forms")
|
||||||
pflag.BoolVarP(&json, "json", "j", false, "Print compact json")
|
pflag.BoolVarP(&json, "json", "j", false, "Print compact json")
|
||||||
pflag.BoolVarP(&showVersion, "version", "V", false, "Show version then exit")
|
pflag.BoolVarP(&syslog23, "syslog23", "s", false, "Print time as \"2006-01-02T15:04:05.000Z07:00\", RFC339 with ms, also used on RSYSLOG_SyslogProtocol23Format. \"msec\" field will not be print in json output")
|
||||||
|
pflag.BoolVarP(&showVersion, "version", "V", false, "Show version and exit")
|
||||||
|
|
||||||
|
var Usage = func() {
|
||||||
|
fmt.Fprintf(os.Stderr, "Usage of \"%s [opts] auditfile\":\n", os.Args[0])
|
||||||
|
pflag.PrintDefaults()
|
||||||
|
fmt.Fprintf(os.Stderr, "Set auditfile to \"-\" to read stdin\n")
|
||||||
|
}
|
||||||
|
pflag.Usage = Usage
|
||||||
|
|
||||||
pflag.Parse()
|
pflag.Parse()
|
||||||
|
|
||||||
@ -68,8 +76,8 @@ func main() {
|
|||||||
if noUserResolve {
|
if noUserResolve {
|
||||||
flags = flags + PRT_NORESOLVE_USER
|
flags = flags + PRT_NORESOLVE_USER
|
||||||
}
|
}
|
||||||
if timestamp {
|
if syslog23 {
|
||||||
flags = flags + PRT_TIMESTAMP
|
flags = flags + PRT_TIMESYSLOG23
|
||||||
}
|
}
|
||||||
if json {
|
if json {
|
||||||
flags |= PRT_JSON
|
flags |= PRT_JSON
|
||||||
|
Reference in New Issue
Block a user