Compare commits

...

30 Commits

Author SHA1 Message Date
yo
10201023f0 v0.6.3: BUGFIX: Append to current.godit so we do not block when file already exist 2023-12-22 09:42:42 +01:00
yo
3e4cdd6f35 Update readme 2023-12-18 14:00:28 +01:00
yo
f4314a8940 go version bump to 1.18 2023-12-18 13:13:51 +01:00
yo
30ea998620 v0.6.2 : Write to output file, SIGUSR1 will reopen output file so we can newsyslog 2023-12-18 11:55:23 +01:00
yo
e028ca7ee2 Write output to *bufio.Writer 2023-12-18 11:53:12 +01:00
yo
a1892cbe37 Bugfix when no input file specified 2023-09-11 16:14:33 +02:00
yo
9b849fad3a v0.6 2023-09-11 16:09:21 +02:00
yo
e9c7c7b744 Revert "v0.6"
This reverts commit 74ad307bd1b6587e8b0e93e0c4919b25ae63bcb3.
2023-09-11 16:08:20 +02:00
yo
74ad307bd1 v0.6 2023-09-11 16:05:39 +02:00
yo
d1aedbb521 Fix version 2023-09-11 16:04:31 +02:00
yo
2a101d89d0 Add godit binary to gitignore 2023-09-11 14:54:07 +02:00
yo
e801a48c7c Add FreeBSD capabilities defines 2023-09-11 14:47:45 +02:00
yo
58ba24444d Readme update 2023-09-11 14:42:47 +02:00
yo
23441feaae Add AUT_RIGHTS (capabilities) 2023-09-11 14:41:10 +02:00
yo
ad4a46104c README update 2023-09-10 16:37:57 +02:00
yo
99bf812571 Add RSYSLOG_SyslogProtocol23Format timestamp format, bugfix zone name was printed in base64 2023-09-10 16:32:05 +02:00
yo
2f1fc7e526 Merge branch 'json' 2023-09-10 15:19:33 +02:00
yo
079361c8cd Add support for zone name 2023-09-10 09:32:45 +02:00
yo
811d2c40d4 temporary work dir 2023-09-10 09:32:29 +02:00
yo
85844065e9 Merge branch 'json' of https://git.nosd.in/yo/libbsm into json 2023-09-06 21:35:04 +02:00
yo
85c1aff8ab Return -1 when input file not available 2023-09-06 21:33:44 +02:00
yo
9eb1d557b6 json support 2023-09-06 21:19:32 +02:00
yo
9716e6ed15 json support 2023-09-06 21:18:42 +02:00
yo
4b06c3064b Manual merge 2023-01-18 17:19:39 +01:00
yo
517bae6dd8 Add error messages 2023-01-17 20:50:44 +01:00
yo
744f087e6c More err check, https://github.com/openbsm/openbsm/pull/75 workaround 2023-01-17 20:50:44 +01:00
yo
65afab1eec WIP: json output option 2023-01-17 11:17:01 +01:00
yo
9218ae6daa Code formatting 2022-07-01 17:20:56 +02:00
yo
dcecaf6c62 Code formatting 2022-07-01 17:15:54 +02:00
yo
8d87cc12c4 BUGFIX: *id were not displayed correctly using -n 2022-07-01 12:12:08 +02:00
7 changed files with 3314 additions and 941 deletions

2
.gitignore vendored
View File

@ -1 +1,3 @@
./20211228134923.20211228151348 ./20211228134923.20211228151348
tmpwrk
godit

View File

@ -4,3 +4,9 @@ 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 "-"
godit can be run as a service with included rc file. It needs audit to be configured to output to /dev/auditpipe.

460
bsmerrno.go Normal file
View File

@ -0,0 +1,460 @@
// This is an implementation of libbsm
// Copyright johan@nosd.in 2023
//
//go:build freebsd
// +build freebsd
//
package main
import (
"fmt"
)
type BsmErrno struct {
Errno uint8
LocalErrno uint16
StrError string
}
const (
// From https://github.com/freebsd/freebsd-src/blob/main/sys/sys/errno.h
EPERM = 1 /* Operation not permitted */
ENOENT = 2 /* No such file or directory */
ESRCH = 3 /* No such process */
EINTR = 4 /* Interrupted system call */
EIO = 5 /* Input/output error */
ENXIO = 6 /* Device not configured */
E2BIG = 7 /* Argument list too long */
ENOEXEC = 8 /* Exec format error */
EBADF = 9 /* Bad file descriptor */
ECHILD = 10 /* No child processes */
EDEADLK = 11 /* Resource deadlock avoided */
ENOMEM = 12 /* Cannot allocate memory */
EACCES = 13 /* Permission denied */
EFAULT = 14 /* Bad address */
ENOTBLK = 15 /* Block device required */
EBUSY = 16 /* Device busy */
EEXIST = 17 /* File exists */
EXDEV = 18 /* Cross-device link */
ENODEV = 19 /* Operation not supported by device */
ENOTDIR = 20 /* Not a directory */
EISDIR = 21 /* Is a directory */
EINVAL = 22 /* Invalid argument */
ENFILE = 23 /* Too many open files in system */
EMFILE = 24 /* Too many open files */
ENOTTY = 25 /* Inappropriate ioctl for device */
ETXTBSY = 26 /* Text file busy */
EFBIG = 27 /* File too large */
ENOSPC = 28 /* No space left on device */
ESPIPE = 29 /* Illegal seek */
EROFS = 30 /* Read-only filesystem */
EMLINK = 31 /* Too many links */
EPIPE = 32 /* Broken pipe */
EDOM = 33 /* Numerical argument out of domain */
ERANGE = 34 /* Result too large */
EAGAIN = 35 /* Resource temporarily unavailable */
EWOULDBLOCK = EAGAIN /* Operation would block */
EINPROGRESS = 36 /* Operation now in progress */
EALREADY = 37 /* Operation already in progress */
ENOTSOCK = 38 /* Socket operation on non-socket */
EDESTADDRREQ = 39 /* Destination address required */
EMSGSIZE = 40 /* Message too long */
EPROTOTYPE = 41 /* Protocol wrong type for socket */
ENOPROTOOPT = 42 /* Protocol not available */
EPROTONOSUPPORT = 43 /* Protocol not supported */
ESOCKTNOSUPPORT = 44 /* Socket type not supported */
EOPNOTSUPP = 45 /* Operation not supported */
ENOTSUP = EOPNOTSUPP /* Operation not supported */
EPFNOSUPPORT = 46 /* Protocol family not supported */
EAFNOSUPPORT = 47 /* Address family not supported by protocol family */
EADDRINUSE = 48 /* Address already in use */
EADDRNOTAVAIL = 49 /* Can't assign requested address */
ENETDOWN = 50 /* Network is down */
ENETUNREACH = 51 /* Network is unreachable */
ENETRESET = 52 /* Network dropped connection on reset */
ECONNABORTED = 53 /* Software caused connection abort */
ECONNRESET = 54 /* Connection reset by peer */
ENOBUFS = 55 /* No buffer space available */
EISCONN = 56 /* Socket is already connected */
ENOTCONN = 57 /* Socket is not connected */
ESHUTDOWN = 58 /* Can't send after socket shutdown */
ETOOMANYREFS = 59 /* Too many references: can't splice */
ETIMEDOUT = 60 /* Operation timed out */
ECONNREFUSED = 61 /* Connection refused */
ELOOP = 62 /* Too many levels of symbolic links */
ENAMETOOLONG = 63 /* File name too long */
EHOSTDOWN = 64 /* Host is down */
EHOSTUNREACH = 65 /* No route to host */
ENOTEMPTY = 66 /* Directory not empty */
EPROCLIM = 67 /* Too many processes */
EUSERS = 68 /* Too many users */
EDQUOT = 69 /* Disc quota exceeded */
ESTALE = 70 /* Stale NFS file handle */
EREMOTE = 71 /* Too many levels of remote in path */
EBADRPC = 72 /* RPC struct is bad */
ERPCMISMATCH = 73 /* RPC version wrong */
EPROGUNAVAIL = 74 /* RPC prog. not avail */
EPROGMISMATCH = 75 /* Program version wrong */
EPROCUNAVAIL = 76 /* Bad procedure for program */
ENOLCK = 77 /* No locks available */
ENOSYS = 78 /* Function not implemented */
EFTYPE = 79 /* Inappropriate file type or format */
EAUTH = 80 /* Authentication error */
ENEEDAUTH = 81 /* Need authenticator */
EIDRM = 82 /* Identifier removed */
ENOMSG = 83 /* No message of desired type */
EOVERFLOW = 84 /* Value too large to be stored in data type */
ECANCELED = 85 /* Operation canceled */
EILSEQ = 86 /* Illegal byte sequence */
ENOATTR = 87 /* Attribute not found */
EDOOFUS = 88 /* Programming error */
EBADMSG = 89 /* Bad message */
EMULTIHOP = 90 /* Multihop attempted */
ENOLINK = 91 /* Link has been severed */
EPROTO = 92 /* Protocol error */
ENOTCAPABLE = 93 /* Capabilities insufficient */
ECAPMODE = 94 /* Not permitted in capability mode */
ENOTRECOVERABLE = 95 /* State not recoverable */
EOWNERDEAD = 96 /* Previous owner died */
EINTEGRITY = 97 /* Integrity check failed */
// From https://github.com/freebsd/freebsd-src/blob/373ffc62c158e52cde86a5b934ab4a51307f9f2e/contrib/openbsm/sys/bsm/audit_errno.h
BSM_ERRNO_ESUCCESS = 0
BSM_ERRNO_EPERM = 1
BSM_ERRNO_ENOENT = 2
BSM_ERRNO_ESRCH = 3
BSM_ERRNO_EINTR = 4
BSM_ERRNO_EIO = 5
BSM_ERRNO_ENXIO = 6
BSM_ERRNO_E2BIG = 7
BSM_ERRNO_ENOEXEC = 8
BSM_ERRNO_EBADF = 9
BSM_ERRNO_ECHILD = 10
BSM_ERRNO_EAGAIN = 11
BSM_ERRNO_ENOMEM = 12
BSM_ERRNO_EACCES = 13
BSM_ERRNO_EFAULT = 14
BSM_ERRNO_ENOTBLK = 15
BSM_ERRNO_EBUSY = 16
BSM_ERRNO_EEXIST = 17
BSM_ERRNO_EXDEV = 18
BSM_ERRNO_ENODEV = 19
BSM_ERRNO_ENOTDIR = 20
BSM_ERRNO_EISDIR = 21
BSM_ERRNO_EINVAL = 22
BSM_ERRNO_ENFILE = 23
BSM_ERRNO_EMFILE = 24
BSM_ERRNO_ENOTTY = 25
BSM_ERRNO_ETXTBSY = 26
BSM_ERRNO_EFBIG = 27
BSM_ERRNO_ENOSPC = 28
BSM_ERRNO_ESPIPE = 29
BSM_ERRNO_EROFS = 30
BSM_ERRNO_EMLINK = 31
BSM_ERRNO_EPIPE = 32
BSM_ERRNO_EDOM = 33
BSM_ERRNO_ERANGE = 34
BSM_ERRNO_ENOMSG = 35
BSM_ERRNO_EIDRM = 36
BSM_ERRNO_ECHRNG = 37 /* Solaris/Linux-specific. */
BSM_ERRNO_EL2NSYNC = 38 /* Solaris/Linux-specific. */
BSM_ERRNO_EL3HLT = 39 /* Solaris/Linux-specific. */
BSM_ERRNO_EL3RST = 40 /* Solaris/Linux-specific. */
BSM_ERRNO_ELNRNG = 41 /* Solaris/Linux-specific. */
BSM_ERRNO_EUNATCH = 42 /* Solaris/Linux-specific. */
BSM_ERRNO_ENOCSI = 43 /* Solaris/Linux-specific. */
BSM_ERRNO_EL2HLT = 44 /* Solaris/Linux-specific. */
BSM_ERRNO_EDEADLK = 45
BSM_ERRNO_ENOLCK = 46
BSM_ERRNO_ECANCELED = 47
BSM_ERRNO_ENOTSUP = 48
BSM_ERRNO_EDQUOT = 49
BSM_ERRNO_EBADE = 50 /* Solaris/Linux-specific. */
BSM_ERRNO_EBADR = 51 /* Solaris/Linux-specific. */
BSM_ERRNO_EXFULL = 52 /* Solaris/Linux-specific. */
BSM_ERRNO_ENOANO = 53 /* Solaris/Linux-specific. */
BSM_ERRNO_EBADRQC = 54 /* Solaris/Linux-specific. */
BSM_ERRNO_EBADSLT = 55 /* Solaris/Linux-specific. */
BSM_ERRNO_EDEADLOCK = 56 /* Solaris-specific. */
BSM_ERRNO_EBFONT = 57 /* Solaris/Linux-specific. */
BSM_ERRNO_EOWNERDEAD = 58 /* Solaris/Linux-specific. */
BSM_ERRNO_ENOTRECOVERABLE = 59 /* Solaris/Linux-specific. */
BSM_ERRNO_ENOSTR = 60 /* Solaris/Darwin/Linux-specific. */
BSM_ERRNO_ENODATA = 61 /* Solaris/Darwin/Linux-specific. */
BSM_ERRNO_ETIME = 62 /* Solaris/Darwin/Linux-specific. */
BSM_ERRNO_ENOSR = 63 /* Solaris/Darwin/Linux-specific. */
BSM_ERRNO_ENONET = 64 /* Solaris/Linux-specific. */
BSM_ERRNO_ENOPKG = 65 /* Solaris/Linux-specific. */
BSM_ERRNO_EREMOTE = 66
BSM_ERRNO_ENOLINK = 67
BSM_ERRNO_EADV = 68 /* Solaris/Linux-specific. */
BSM_ERRNO_ESRMNT = 69 /* Solaris/Linux-specific. */
BSM_ERRNO_ECOMM = 70 /* Solaris/Linux-specific. */
BSM_ERRNO_EPROTO = 71
BSM_ERRNO_ELOCKUNMAPPED = 72 /* Solaris-specific. */
BSM_ERRNO_ENOTACTIVE = 73 /* Solaris-specific. */
BSM_ERRNO_EMULTIHOP = 74
BSM_ERRNO_EBADMSG = 77
BSM_ERRNO_ENAMETOOLONG = 78
BSM_ERRNO_EOVERFLOW = 79
BSM_ERRNO_ENOTUNIQ = 80 /* Solaris/Linux-specific. */
BSM_ERRNO_EBADFD = 81 /* Solaris/Linux-specific. */
BSM_ERRNO_EREMCHG = 82 /* Solaris/Linux-specific. */
BSM_ERRNO_ELIBACC = 83 /* Solaris/Linux-specific. */
BSM_ERRNO_ELIBBAD = 84 /* Solaris/Linux-specific. */
BSM_ERRNO_ELIBSCN = 85 /* Solaris/Linux-specific. */
BSM_ERRNO_ELIBMAX = 86 /* Solaris/Linux-specific. */
BSM_ERRNO_ELIBEXEC = 87 /* Solaris/Linux-specific. */
BSM_ERRNO_EILSEQ = 88
BSM_ERRNO_ENOSYS = 89
BSM_ERRNO_ELOOP = 90
BSM_ERRNO_ERESTART = 91
BSM_ERRNO_ESTRPIPE = 92 /* Solaris/Linux-specific. */
BSM_ERRNO_ENOTEMPTY = 93
BSM_ERRNO_EUSERS = 94
BSM_ERRNO_ENOTSOCK = 95
BSM_ERRNO_EDESTADDRREQ = 96
BSM_ERRNO_EMSGSIZE = 97
BSM_ERRNO_EPROTOTYPE = 98
BSM_ERRNO_ENOPROTOOPT = 99
BSM_ERRNO_EPROTONOSUPPORT = 120
BSM_ERRNO_ESOCKTNOSUPPORT = 121
BSM_ERRNO_EOPNOTSUPP = 122
BSM_ERRNO_EPFNOSUPPORT = 123
BSM_ERRNO_EAFNOSUPPORT = 124
BSM_ERRNO_EADDRINUSE = 125
BSM_ERRNO_EADDRNOTAVAIL = 126
BSM_ERRNO_ENETDOWN = 127
BSM_ERRNO_ENETUNREACH = 128
BSM_ERRNO_ENETRESET = 129
BSM_ERRNO_ECONNABORTED = 130
BSM_ERRNO_ECONNRESET = 131
BSM_ERRNO_ENOBUFS = 132
BSM_ERRNO_EISCONN = 133
BSM_ERRNO_ENOTCONN = 134
BSM_ERRNO_ESHUTDOWN = 143
BSM_ERRNO_ETOOMANYREFS = 144
BSM_ERRNO_ETIMEDOUT = 145
BSM_ERRNO_ECONNREFUSED = 146
BSM_ERRNO_EHOSTDOWN = 147
BSM_ERRNO_EHOSTUNREACH = 148
BSM_ERRNO_EALREADY = 149
BSM_ERRNO_EINPROGRESS = 150
BSM_ERRNO_ESTALE = 151
BSM_ERRNO_EPROCLIM = 190 /* FreeBSD/Darwin-specific. */
BSM_ERRNO_EBADRPC = 191 /* FreeBSD/Darwin-specific. */
BSM_ERRNO_ERPCMISMATCH = 192 /* FreeBSD/Darwin-specific. */
BSM_ERRNO_EPROGUNAVAIL = 193 /* FreeBSD/Darwin-specific. */
BSM_ERRNO_EPROGMISMATCH = 194 /* FreeBSD/Darwin-specific. */
BSM_ERRNO_EPROCUNAVAIL = 195 /* FreeBSD/Darwin-specific. */
BSM_ERRNO_EFTYPE = 196 /* FreeBSD/Darwin-specific. */
BSM_ERRNO_EAUTH = 197 /* FreeBSD/Darwin-specific. */
BSM_ERRNO_ENEEDAUTH = 198 /* FreeBSD/Darwin-specific. */
BSM_ERRNO_ENOATTR = 199 /* FreeBSD/Darwin-specific. */
BSM_ERRNO_EDOOFUS = 200 /* FreeBSD-specific. */
BSM_ERRNO_EJUSTRETURN = 201 /* FreeBSD-specific. */
BSM_ERRNO_ENOIOCTL = 202 /* FreeBSD-specific. */
BSM_ERRNO_EDIRIOCTL = 203 /* FreeBSD-specific. */
BSM_ERRNO_EPWROFF = 204 /* Darwin-specific. */
BSM_ERRNO_EDEVERR = 205 /* Darwin-specific. */
BSM_ERRNO_EBADEXEC = 206 /* Darwin-specific. */
BSM_ERRNO_EBADARCH = 207 /* Darwin-specific. */
BSM_ERRNO_ESHLIBVERS = 208 /* Darwin-specific. */
BSM_ERRNO_EBADMACHO = 209 /* Darwin-specific. */
BSM_ERRNO_EPOLICY = 210 /* Darwin-specific. */
BSM_ERRNO_EDOTDOT = 211 /* Linux-specific. */
BSM_ERRNO_EUCLEAN = 212 /* Linux-specific. */
BSM_ERRNO_ENOTNAM = 213 /* Linux(Xenix?)-specific. */
BSM_ERRNO_ENAVAIL = 214 /* Linux(Xenix?)-specific. */
BSM_ERRNO_EISNAM = 215 /* Linux(Xenix?)-specific. */
BSM_ERRNO_EREMOTEIO = 216 /* Linux-specific. */
BSM_ERRNO_ENOMEDIUM = 217 /* Linux-specific. */
BSM_ERRNO_EMEDIUMTYPE = 218 /* Linux-specific. */
BSM_ERRNO_ENOKEY = 219 /* Linux-specific. */
BSM_ERRNO_EKEYEXPIRED = 220 /* Linux-specific. */
BSM_ERRNO_EKEYREVOKED = 221 /* Linux-specific. */
BSM_ERRNO_EKEYREJECTED = 222 /* Linux-specific. */
BSM_ERRNO_ENOTCAPABLE = 223 /* FreeBSD-specific. */
BSM_ERRNO_ECAPMODE = 224 /* FreeBSD-specific. */
BSM_ERRNO_EINTEGRITY = 225 /* FreeBSD-specific. */
BSM_ERRNO_UNKNOWN = 250 /* OpenBSM-specific. */
// From https://github.com/freebsd/freebsd-src/blob/373ffc62c158e52cde86a5b934ab4a51307f9f2e/sys/security/audit/bsm_errno.c
// But we dont want to use int16, so use 255
//ERRNO_NO_LOCAL_MAPPING int16 = -600
ERRNO_NO_LOCAL_MAPPING = 255
)
var (
BsmErrnos = []BsmErrno{
{BSM_ERRNO_ESUCCESS, 0, "Success"},
{BSM_ERRNO_EPERM, EPERM, "Operation not permitted"},
{BSM_ERRNO_ENOENT, ENOENT, "No such file or directory"},
{BSM_ERRNO_ESRCH, ESRCH, "No such process"},
{BSM_ERRNO_EINTR, EINTR, "Interrupted system call"},
{BSM_ERRNO_EIO, EIO, "Input/output error"},
{BSM_ERRNO_ENXIO, ENXIO, "Device not configured"},
{BSM_ERRNO_E2BIG, E2BIG, "Argument list too long"},
{BSM_ERRNO_ENOEXEC, ENOEXEC, "Exec format error"},
{BSM_ERRNO_EBADF, EBADF, "Bad file descriptor"},
{BSM_ERRNO_ECHILD, ECHILD, "No child processes"},
{BSM_ERRNO_EAGAIN, EAGAIN, "Resource temporarily unavailable"},
{BSM_ERRNO_ENOMEM, ENOMEM, "Cannot allocate memory"},
{BSM_ERRNO_EACCES, EACCES, "Permission denied"},
{BSM_ERRNO_EFAULT, EFAULT, "Bad address"},
{BSM_ERRNO_ENOTBLK, ENOTBLK, "Block device required"},
{BSM_ERRNO_EBUSY, EBUSY, "Device busy"},
{BSM_ERRNO_EEXIST, EEXIST, "File exists"},
{BSM_ERRNO_EXDEV, EXDEV, "Cross-device link"},
{BSM_ERRNO_ENODEV, ENODEV, "Operation not supported by device"},
{BSM_ERRNO_ENOTDIR, ENOTDIR, "Not a directory"},
{BSM_ERRNO_EISDIR, EISDIR, "Is a directory"},
{BSM_ERRNO_EINVAL, EINVAL, "Invalid argument"},
{BSM_ERRNO_ENFILE, ENFILE, "Too many open files in system"},
{BSM_ERRNO_EMFILE, EMFILE, "Too many open files"},
{BSM_ERRNO_ENOTTY, ENOTTY, "Inappropriate ioctl for device"},
{BSM_ERRNO_ETXTBSY, ETXTBSY, "Text file busy"},
{BSM_ERRNO_EFBIG, EFBIG, "File too large"},
{BSM_ERRNO_ENOSPC, ENOSPC, "No space left on device"},
{BSM_ERRNO_ESPIPE, ESPIPE, "Illegal seek"},
{BSM_ERRNO_EROFS, EROFS, "Read-only file system"},
{BSM_ERRNO_EMLINK, EMLINK, "Too many links"},
{BSM_ERRNO_EPIPE, EPIPE, "Broken pipe"},
{BSM_ERRNO_EDOM, EDOM, "Numerical argument out of domain"},
{BSM_ERRNO_ERANGE, ERANGE, "Result too large"},
{BSM_ERRNO_ENOMSG, ENOMSG, "No message of desired type"},
{BSM_ERRNO_EIDRM, EIDRM, "Identifier removed"},
{BSM_ERRNO_ECHRNG, ERRNO_NO_LOCAL_MAPPING, "Channel number out of range"},
{BSM_ERRNO_EL2NSYNC, ERRNO_NO_LOCAL_MAPPING, "Level 2 not synchronized"},
{BSM_ERRNO_EL3HLT, ERRNO_NO_LOCAL_MAPPING, "Level 3 halted"},
{BSM_ERRNO_EL3RST, ERRNO_NO_LOCAL_MAPPING, "Level 3 reset"},
{BSM_ERRNO_ELNRNG, ERRNO_NO_LOCAL_MAPPING, "Link number out of range"},
{BSM_ERRNO_EUNATCH, ERRNO_NO_LOCAL_MAPPING, "Protocol driver not attached"},
{BSM_ERRNO_ENOCSI, ERRNO_NO_LOCAL_MAPPING, "No CSI structure available"},
{BSM_ERRNO_EL2HLT, ERRNO_NO_LOCAL_MAPPING, "Level 2 halted"},
{BSM_ERRNO_EDEADLK, EDEADLK, "Resource deadlock avoided"},
{BSM_ERRNO_ENOLCK, ENOLCK, "No locks available"},
{BSM_ERRNO_ECANCELED, ECANCELED, "Operation canceled"},
{BSM_ERRNO_ENOTSUP, ENOTSUP, "Operation not supported"},
{BSM_ERRNO_EDQUOT, EDQUOT, "Disc quota exceeded"},
{BSM_ERRNO_EBADE, ERRNO_NO_LOCAL_MAPPING, "Invalid exchange"},
{BSM_ERRNO_EBADR, ERRNO_NO_LOCAL_MAPPING, "Invalid request descriptor"},
{BSM_ERRNO_EXFULL, ERRNO_NO_LOCAL_MAPPING, "Exchange full"},
{BSM_ERRNO_ENOANO, ERRNO_NO_LOCAL_MAPPING, "No anode"},
{BSM_ERRNO_EBADRQC, ERRNO_NO_LOCAL_MAPPING, "Invalid request descriptor"},
{BSM_ERRNO_EBADSLT, ERRNO_NO_LOCAL_MAPPING, "Invalid slot"},
{BSM_ERRNO_EDEADLOCK, ERRNO_NO_LOCAL_MAPPING, "Resource deadlock avoided"},
{BSM_ERRNO_EBFONT, ERRNO_NO_LOCAL_MAPPING, "Bad font file format"},
{BSM_ERRNO_EOWNERDEAD, ERRNO_NO_LOCAL_MAPPING, "Process died with the lock"},
{BSM_ERRNO_EINTEGRITY, ERRNO_NO_LOCAL_MAPPING, "Integrity check failed"},
{BSM_ERRNO_ENOTRECOVERABLE, ERRNO_NO_LOCAL_MAPPING, "Lock is not recoverable"},
{BSM_ERRNO_ENOSTR, ERRNO_NO_LOCAL_MAPPING, "Device not a stream"},
{BSM_ERRNO_ENONET, ERRNO_NO_LOCAL_MAPPING, "Machine is not on the network"},
{BSM_ERRNO_ENOPKG, ERRNO_NO_LOCAL_MAPPING, "Package not installed"},
{BSM_ERRNO_EREMOTE, EREMOTE, "Too many levels of remote in path"},
{BSM_ERRNO_ENOLINK, ERRNO_NO_LOCAL_MAPPING, "Link has been severed"},
{BSM_ERRNO_EADV, ERRNO_NO_LOCAL_MAPPING, "Advertise error"},
{BSM_ERRNO_ESRMNT, ERRNO_NO_LOCAL_MAPPING, "srmount error"},
{BSM_ERRNO_ECOMM, ERRNO_NO_LOCAL_MAPPING, "Communication error on send"},
{BSM_ERRNO_EPROTO, ERRNO_NO_LOCAL_MAPPING, "Protocol error"},
{BSM_ERRNO_ELOCKUNMAPPED, ERRNO_NO_LOCAL_MAPPING, "Locked lock was unmapped"},
{BSM_ERRNO_ENOTACTIVE, ERRNO_NO_LOCAL_MAPPING, "Facility is not active"},
{BSM_ERRNO_EMULTIHOP, ERRNO_NO_LOCAL_MAPPING, "Multihop attempted"},
{BSM_ERRNO_EBADMSG, ERRNO_NO_LOCAL_MAPPING, "Bad message"},
{BSM_ERRNO_ENAMETOOLONG, ENAMETOOLONG, "File name too long"},
{BSM_ERRNO_EOVERFLOW, EOVERFLOW, "Value too large to be stored in data type"},
{BSM_ERRNO_ENOTUNIQ, ERRNO_NO_LOCAL_MAPPING, "Given log name not unique"},
{BSM_ERRNO_EBADFD, ERRNO_NO_LOCAL_MAPPING, "Given f.d. invalid for this operation"},
{BSM_ERRNO_EREMCHG, ERRNO_NO_LOCAL_MAPPING, "Remote address changed"},
{BSM_ERRNO_ELIBACC, ERRNO_NO_LOCAL_MAPPING, "Can't access a needed shared lib"},
{BSM_ERRNO_ELIBBAD, ERRNO_NO_LOCAL_MAPPING, "Accessing a corrupted shared lib"},
{BSM_ERRNO_ELIBSCN, ERRNO_NO_LOCAL_MAPPING, ".lib section in a.out corrupted"},
{BSM_ERRNO_ELIBMAX, ERRNO_NO_LOCAL_MAPPING, "Attempting to link in too many libs"},
{BSM_ERRNO_ELIBEXEC, ERRNO_NO_LOCAL_MAPPING, "Attempting to exec a shared library"},
{BSM_ERRNO_EILSEQ, EILSEQ, "Illegal byte sequence"},
{BSM_ERRNO_ENOSYS, ENOSYS, "Function not implemented"},
{BSM_ERRNO_ELOOP, ELOOP, "Too many levels of symbolic links"},
{BSM_ERRNO_ERESTART, ERRNO_NO_LOCAL_MAPPING, "Restart syscall"},
{BSM_ERRNO_ESTRPIPE, ERRNO_NO_LOCAL_MAPPING, "If pipe/FIFO, don't sleep in stream head"},
{BSM_ERRNO_ENOTEMPTY, ENOTEMPTY, "Directory not empty"},
{BSM_ERRNO_EUSERS, EUSERS, "Too many users"},
{BSM_ERRNO_ENOTSOCK, ENOTSOCK, "Socket operation on non-socket"},
{BSM_ERRNO_EDESTADDRREQ, EDESTADDRREQ, "Destination address required"},
{BSM_ERRNO_EMSGSIZE, EMSGSIZE, "Message too long"},
{BSM_ERRNO_EPROTOTYPE, EPROTOTYPE, "Protocol wrong type for socket"},
{BSM_ERRNO_ENOPROTOOPT, ENOPROTOOPT, "Protocol not available"},
{BSM_ERRNO_EPROTONOSUPPORT, EPROTONOSUPPORT, "Protocol not supported"},
{BSM_ERRNO_ESOCKTNOSUPPORT, ESOCKTNOSUPPORT, "Socket type not supported"},
{BSM_ERRNO_EOPNOTSUPP, EOPNOTSUPP, "Operation not supported"},
{BSM_ERRNO_EPFNOSUPPORT, EPFNOSUPPORT, "Protocol family not supported"},
{BSM_ERRNO_EAFNOSUPPORT, EAFNOSUPPORT, "Address family not supported by protocol family"},
{BSM_ERRNO_EADDRINUSE, EADDRINUSE, "Address already in use"},
{BSM_ERRNO_EADDRNOTAVAIL, EADDRNOTAVAIL, "Can't assign requested address"},
{BSM_ERRNO_ENETDOWN, ENETDOWN, "Network is down"},
{BSM_ERRNO_ENETRESET, ENETRESET, "Network dropped connection on reset"},
{BSM_ERRNO_ECONNABORTED, ECONNABORTED, "Software caused connection abort"},
{BSM_ERRNO_ECONNRESET, ECONNRESET, "Connection reset by peer"},
{BSM_ERRNO_ENOBUFS, ENOBUFS, "No buffer space available"},
{BSM_ERRNO_EISCONN, EISCONN, "Socket is already connected"},
{BSM_ERRNO_ENOTCONN, ENOTCONN, "Socket is not connected"},
{BSM_ERRNO_ESHUTDOWN, ESHUTDOWN, "Can't send after socket shutdown"},
{BSM_ERRNO_ETOOMANYREFS, ETOOMANYREFS, "Too many references: can't splice"},
{BSM_ERRNO_ETIMEDOUT, ETIMEDOUT, "Operation timed out"},
{BSM_ERRNO_ECONNREFUSED, ECONNREFUSED, "Connection refused"},
{BSM_ERRNO_EHOSTDOWN, EHOSTDOWN, "Host is down"},
{BSM_ERRNO_EHOSTUNREACH, EHOSTUNREACH, "No route to host"},
{BSM_ERRNO_EALREADY, EALREADY, "Operation already in progress"},
{BSM_ERRNO_EINPROGRESS, EINPROGRESS, "Operation now in progress"},
{BSM_ERRNO_ESTALE, ESTALE, "Stale NFS file handle"},
{BSM_ERRNO_EPROCLIM, EPROCLIM, "Too many processes"},
{BSM_ERRNO_EBADRPC, EBADRPC, "RPC struct is bad"},
{BSM_ERRNO_ERPCMISMATCH, ERPCMISMATCH, "RPC version wrong"},
{BSM_ERRNO_EPROGUNAVAIL, EPROGUNAVAIL, "RPC prog. not avail"},
{BSM_ERRNO_EPROGMISMATCH, EPROGMISMATCH, "RPC version wrong"},
{BSM_ERRNO_EPROCUNAVAIL, EPROCUNAVAIL, "Bad procedure for program"},
{BSM_ERRNO_EFTYPE, EFTYPE, "Inappropriate file type or format"},
{BSM_ERRNO_EAUTH, EAUTH, "Authenticateion error"},
{BSM_ERRNO_ENEEDAUTH, ENEEDAUTH, "Need authenticator"},
{BSM_ERRNO_ENOATTR, ENOATTR, "Attribute not found"},
{BSM_ERRNO_EDOOFUS, EDOOFUS, "Programming error"},
{BSM_ERRNO_EJUSTRETURN, ERRNO_NO_LOCAL_MAPPING, "Just return"},
{BSM_ERRNO_ENOIOCTL, ERRNO_NO_LOCAL_MAPPING, "ioctl not handled by this layer"},
{BSM_ERRNO_EDIRIOCTL, ERRNO_NO_LOCAL_MAPPING, "do direct ioctl in GEOM"},
{BSM_ERRNO_EPWROFF, ERRNO_NO_LOCAL_MAPPING, "Device power is off"},
{BSM_ERRNO_EDEVERR, ERRNO_NO_LOCAL_MAPPING, "Device error"},
{BSM_ERRNO_EBADEXEC, ERRNO_NO_LOCAL_MAPPING, "Bad executable"},
{BSM_ERRNO_EBADARCH, ERRNO_NO_LOCAL_MAPPING, "Bad CPU type in executable"},
{BSM_ERRNO_ESHLIBVERS, ERRNO_NO_LOCAL_MAPPING, "Shared library version mismatch"},
{BSM_ERRNO_EBADMACHO, ERRNO_NO_LOCAL_MAPPING, "Malformed Macho file"},
{BSM_ERRNO_EPOLICY, ERRNO_NO_LOCAL_MAPPING, "Operation failed by policy"},
{BSM_ERRNO_EDOTDOT, ERRNO_NO_LOCAL_MAPPING, "RFS specific error"},
{BSM_ERRNO_EUCLEAN, ERRNO_NO_LOCAL_MAPPING, "Structure needs cleaning"},
{BSM_ERRNO_ENOTNAM, ERRNO_NO_LOCAL_MAPPING, "Not a XENIX named type file"},
{BSM_ERRNO_ENAVAIL, ERRNO_NO_LOCAL_MAPPING, "No XENIX semaphores available"},
{BSM_ERRNO_EISNAM, ERRNO_NO_LOCAL_MAPPING, "Is a named type file"},
{BSM_ERRNO_EREMOTEIO, ERRNO_NO_LOCAL_MAPPING, "Remote I/O error"},
{BSM_ERRNO_ENOMEDIUM, ERRNO_NO_LOCAL_MAPPING, "No medium found"},
{BSM_ERRNO_EMEDIUMTYPE, ERRNO_NO_LOCAL_MAPPING, "Wrong medium type"},
{BSM_ERRNO_ENOKEY, ERRNO_NO_LOCAL_MAPPING, "Required key not available"},
{BSM_ERRNO_EKEYEXPIRED, ERRNO_NO_LOCAL_MAPPING, "Key has expired"},
{BSM_ERRNO_EKEYREVOKED, ERRNO_NO_LOCAL_MAPPING, "Key has been revoked"},
{BSM_ERRNO_EKEYREJECTED, ERRNO_NO_LOCAL_MAPPING, "Key was rejected by service"},
{BSM_ERRNO_ENOTCAPABLE, ENOTCAPABLE, "Capabilities insufficient"},
{BSM_ERRNO_ECAPMODE, ECAPMODE, "Not permitted in capability mode"},
}
)
func lookupErrno(errno uint8) (BsmErrno, error) {
var res BsmErrno
for _, res = range BsmErrnos {
if res.Errno == errno {
return res, nil
}
}
return res, fmt.Errorf("ErrNo not found")
}

242
capsicum.go Normal file
View 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
)

2
go.mod
View File

@ -1,5 +1,5 @@
module godit module godit
go 1.17 go 1.18
require github.com/spf13/pflag v1.0.5 require github.com/spf13/pflag v1.0.5

2261
libbsm.go

File diff suppressed because it is too large Load Diff

114
main.go
View File

@ -1,5 +1,7 @@
// Copyright 2021, johan@nosd.in // Copyright 2021, johan@nosd.in
//go:build freebsd
// +build freebsd // +build freebsd
// //
// godit is a search tool for BSM audit trails used by FreeBSD auditd // godit is a search tool for BSM audit trails used by FreeBSD auditd
// //
@ -25,13 +27,16 @@ import (
"io" "io"
"os" "os"
"fmt" "fmt"
"sync"
"bufio" "bufio"
"strings" "strings"
"syscall"
"os/signal"
"github.com/spf13/pflag" "github.com/spf13/pflag"
) )
const ( const (
version = "0.5" version = "0.6.3"
) )
var ( var (
@ -40,19 +45,51 @@ var (
// Default delimiter // Default delimiter
delimiter = "," delimiter = ","
Writer *bufio.Writer
) )
func NewWriter(file string) (*bufio.Writer, *os.File, error) {
if len(file) > 0 {
var f *os.File
var err error
f, err = os.OpenFile(file, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0640)
if err != nil {
return nil, nil, err
}
Writer = bufio.NewWriter(f)
return Writer, f, nil
} else {
Writer = bufio.NewWriter(os.Stdout)
return Writer, nil, nil
}
}
func main() { 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 outputFile string
// Output file mutex
var outfMtx sync.Mutex
var outFile *os.File
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(&timestamp, "timestamp", "t", false, "Print unix timestamp instead of formatted date/time.") 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.StringVarP(&outputFile, "out", "o", "", "Output to file, overwrite existing. File will be re-opened receiving SIGUSR1.")
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()
@ -60,29 +97,55 @@ func main() {
fmt.Printf("Godit v%s\n", version) fmt.Printf("Godit v%s\n", version)
return return
} }
if oneLine { if oneLine {
flags = flags + PRT_ONELINE flags = flags + PRT_ONELINE
} }
if noUserResolve { if noUserResolve {
flags = flags + PRT_NORESOLVE_USER flags = flags + PRT_NORESOLVE_USER
} }
if syslog23 {
if timestamp { flags = flags + PRT_TIMESYSLOG23
flags = flags + PRT_TIMESTAMP }
if json {
flags |= PRT_JSON
} }
args := os.Args args := os.Args
if len(os.Args) < 2 {
pflag.Usage()
os.Exit(1)
}
filename := args[len(args)-1] filename := args[len(args)-1]
/* fmt.Printf("Args: %s\n", args) // Get a writer, file or stdout
fmt.Printf("Filename: %s\n", filename) _, outFile, err := NewWriter(outputFile)
*/ if err != nil {
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
if len(outputFile) > 0 {
// Manage output file rotation when receiving SIGUSR1
sig := make(chan os.Signal)
signal.Notify(sig, syscall.SIGUSR1)
go func() {
for {
<-sig
outfMtx.Lock()
fmt.Println("SIGUSR1 received, recreating output file")
outFile.Close()
_, outFile, err = NewWriter(outputFile)
if err != nil {
outfMtx.Unlock()
fmt.Fprintf(os.Stderr, "%v\n", err)
os.Exit(1)
}
outfMtx.Unlock()
}
}()
}
var f *os.File var f *os.File
var r *bufio.Reader var r *bufio.Reader
var err error
if len(filename) > 0 { if len(filename) > 0 {
// If arg is "-", open stdin to read content // If arg is "-", open stdin to read content
if true == strings.EqualFold(filename, "-") { if true == strings.EqualFold(filename, "-") {
@ -90,13 +153,12 @@ func main() {
} else { } else {
f, err = os.Open(filename) f, err = os.Open(filename)
if err != nil { if err != nil {
fmt.Printf("Impossible d'ouvrir le fichier %s\n", filename) fmt.Fprintf(os.Stderr, "Impossible d'ouvrir le fichier %s\n", filename)
return os.Exit(-1)
} }
r = bufio.NewReader(f) r = bufio.NewReader(f)
} }
//for i := 0 ; i < 20 ; i++ {
for { for {
rec, err := readRecordToStruct(r) rec, err := readRecordToStruct(r)
if err != nil { if err != nil {
@ -106,9 +168,21 @@ func main() {
return return
} }
} }
rec.Print(os.Stdout, ",", flags) if len(outputFile) > 0 {
outfMtx.Lock()
rec.Print(Writer, ",", flags)
Writer.Flush() // Performance ?
outfMtx.Unlock()
} else {
// No need for mutex with stdout
rec.Print(Writer, ",", flags)
} }
} }
} }
if len(outputFile) > 0 && outFile != nil {
outfMtx.Lock()
outFile.Close()
outfMtx.Unlock()
}
}