// This is an implementation of libbsm // Copyright johan@nosd.in 2021 // //go:build freebsd // +build freebsd // // update 23/01/2023 // // // Use libc to get pw name from uid package main /* #cgo CFLAGS: -I /usr/lib #cgo LDFLAGS: -L. -lc #include #include #include #include #include */ import "C" import ( "io" "os" "fmt" "time" "bufio" "bytes" "strconv" "strings" "encoding/binary" "encoding/json" ) const ( // bsm/libbsm.h AUDIT_MAX_ARGS = 128 AUDIT_EVENT_FILE = "/etc/security/audit_event" // sys/bsm/audit.h MAXAUDITDATA = (0x8000 - 1) MAX_AUDIT_RECORD_SIZE = MAXAUDITDATA // Max length for a Path (AUT_PATH) or an arg (AUT_EXEC_ARGS) MAX_AUDIT_ARG_LENGTH = 1024 ISIPV4 = 4 ISIPV6 = 16 /* * Token type identifiers. From https://github.com/freebsd/freebsd-src/blob/main/contrib/openbsm/sys/bsm/audit_record.h */ AUT_INVALID = 0x00 AUT_OTHER_FILE32 = 0x11 AUT_OHEADER = 0x12 AUT_TRAILER = 0x13 AUT_HEADER32 = 0x14 AUT_HEADER32_EX = 0x15 AUT_DATA = 0x21 AUT_IPC = 0x22 AUT_PATH = 0x23 AUT_SUBJECT32 = 0x24 AUT_XATPATH = 0x25 AUT_PROCESS32 = 0x26 AUT_RETURN32 = 0x27 AUT_TEXT = 0x28 AUT_OPAQUE = 0x29 AUT_IN_ADDR = 0x2a AUT_IP = 0x2b AUT_IPORT = 0x2c AUT_ARG32 = 0x2d AUT_SOCKET = 0x2e AUT_SEQ = 0x2f AUT_ACL = 0x30 AUT_ATTR = 0x31 AUT_IPC_PERM = 0x32 AUT_LABEL = 0x33 AUT_GROUPS = 0x34 AUT_ACE = 0x35 AUT_PRIV = 0x38 AUT_UPRIV = 0x39 AUT_LIAISON = 0x3a AUT_NEWGROUPS = 0x3b AUT_EXEC_ARGS = 0x3c AUT_EXEC_ENV = 0x3d AUT_ATTR32 = 0x3e AUT_UNAUTH = 0x3f AUT_XATOM = 0x40 AUT_XOBJ = 0x41 AUT_XPROTO = 0x42 AUT_XSELECT = 0x43 AUT_XCOLORMAP = 0x44 AUT_XCURSOR = 0x45 AUT_XFONT = 0x46 AUT_XGC = 0x47 AUT_XPIXMAP = 0x48 AUT_XPROPERTY = 0x49 AUT_XWINDOW = 0x4a AUT_XCLIENT = 0x4b AUT_CMD = 0x51 AUT_EXIT = 0x52 AUT_ZONENAME = 0x60 AUT_HOST = 0x70 AUT_ARG64 = 0x71 AUT_RETURN64 = 0x72 AUT_ATTR64 = 0x73 AUT_HEADER64 = 0x74 AUT_SUBJECT64 = 0x75 AUT_PROCESS64 = 0x77 AUT_OTHER_FILE64 = 0x78 AUT_HEADER64_EX = 0x79 AUT_SUBJECT32_EX = 0x7a AUT_PROCESS32_EX = 0x7b AUT_SUBJECT64_EX = 0x7c AUT_PROCESS64_EX = 0x7d AUT_IN_ADDR_EX = 0x7e AUT_SOCKET_EX = 0x7f // From sys/bsm/audit_record.h AUT_SOCKINET32 = 0x80 AUT_SOCKINET128 = 0x81 AUT_SOCKUNIX = 0x82 AUT_RIGHTS = 0x83 // Display control PRT_ONELINE = 1 PRT_NORESOLVE_USER = 2 PRT_TIMESYSLOG23 = 4 PRT_JSON = 8 ) var ( // A global user/uid cache gUsers []user // A global group/gid cache gGroups []group // Cache of audit_event file gEventDB []event ) type event struct { Type int Name string Desc string Class string } // Fields types, from https://github.com/freebsd/freebsd-src/blob/main/contrib/openbsm/bsm/libbsm.h // Abstraction of a record type Record interface { GetType() uint8 // Length() LoadFromBinary(rdr *bufio.Reader) error Print(*bufio.Writer, string, int) } type Header32 struct { Size uint32 `json:"size"` // Record byte count Version uint8 `json:"version"` // version # (uchar) E_type uint16 `json:"event_type"` // Event type E_mod uint16 `json:"event_modifier"` // Event modifier S uint32 `json:"timestamp"` // Seconds of time Msec uint32 `json:"msec"` // Milliseconds of time } type Header32Ex struct { Size uint32 `json:"size"` // Record byte count Version uint8 `json:"version"` // version # (uchar) E_type uint16 `json:"event_type"` // Event type E_mod uint16 `json:"event_modifier"` // Event modifier Ad_type uint32 `json:"address_type"` // Address type/Length Addr [4]uint32 `json:"address"` // Ipv4 or IPv6 S uint32 `json:"timestamp"` // Seconds of time Msec uint32 `json:"msec"` // Milliseconds of time } type Trailer struct { Magic uint16 `json:"magic"` Count uint32 `json:"size"` } type Arg32 struct { No byte `json:"count"` // Argument # Val uint32 `json:"value"` // Argument value Length uint16 `json:"length"` // Text length Text []byte `json:"text"` // Text } type Arg64 struct { No byte `json:"count"` // Argument # Val uint64 `json:"value"` // Argument value Length uint16 `json:"length"` // Text length Text []byte `json:"text"` // Text } type Attribute32 struct { Mode uint32 `json:"mode"` // file access mode Uid uint32 `json:"user_id"` // Owner user ID Gid uint32 `json:"group_id"` // Owner group ID Fsid uint32 `json:"filesystem_id"` // File system ID Nid uint64 `json:"node_id"` // Node ID Dev uint32 `json:"device"` // Device } type Attribute64 struct { Mode uint32 `json:"mode"` // file access mode Uid uint32 `json:"user_id"` // Owner user ID Gid uint32 `json:"group_id"` // Owner group ID Fsid uint32 `json:"filesystem_id"` // File system ID Nid uint64 `json:"node_id"` // Node ID Dev uint64 `json:"device"` // Device } /* * count 4 bytes * text count null-terminated string(s) */ type ExecArg struct { Count uint32 `json:"count"` //Text [AUDIT_MAX_ARGS][]byte Text [][]byte `json:"text"` } type Path struct { Length uint16 `json:"length"` // path length Path []byte `json:"path"` } type Return32 struct { Status byte `json:"status"` // Error status Ret uint32 `json:"code"` // Return code } type Return64 struct { Status byte `json:"status"` // Error status Ret uint64 `json:"code"` // Return code } type Subject32 struct { Auid uint32 `json:"audit_id"` // Audit ID Euid uint32 `json:"effective_user_id"` // Effective user ID Egid uint32 `json:"effective_group_id"` // Effective Group ID Ruid uint32 `json:"real_user_id"` // Real User ID Rgid uint32 `json:"real_group_id"` // Real Group ID Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid Tid32 `json:"terminal_id"` } type Process32 Subject32 type Subject32Ex struct { Auid uint32 `json:"audit_id"` // Audit ID Euid uint32 `json:"effective_user_id"` // Effective user ID Egid uint32 `json:"effective_group_id"` // Effective Group ID Ruid uint32 `json:"real_user_id"` // Real User ID Rgid uint32 `json:"real_group_id"` // Real Group ID Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid Tid32Ex `json:"terminal_id_ex"` } type Process32Ex Subject32Ex type Tid32 struct { Port uint32 `json:"port"` Addr uint32 `json:"ip4"` } type Tid32Ex struct { Port uint32 `json:"port"` IpVers uint32 `json:"ip_version"` // 0x10 = IPv6, 0x04 = IPv4 Addr4 uint32 `json:"ip4,omitempty"` // 4 bytes long if IpVers == 0x04 Addr6 [4]uint32 `json:"ip6,omitempty"` // 4x4 bytes long if IpVers == 0x10 } type Subject64 struct { Auid uint32 `json:"audit_id"` // Audit ID Euid uint32 `json:"effective_user_id"` // Effective user ID Egid uint32 `json:"effective_group_id"` // Effective Group ID Ruid uint32 `json:"real_user_id"` // Real User ID Rgid uint32 `json:"real_group_id"` // Real Group ID Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid Tid64 `json:"terminal_id"` } type Process64 Subject64 type Subject64Ex struct { Auid uint32 `json:"audit_id"` // Audit ID Euid uint32 `json:"effective_user_id"` // Effective user ID Egid uint32 `json:"effective_group_id"` // Effective Group ID Ruid uint32 `json:"real_user_id"` // Real User ID Rgid uint32 `json:"real_group_id"` // Real Group ID Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid Tid64Ex `json:"terminal_id_ex"` } type Process64Ex Subject64Ex type Tid64 struct { Port uint64 `json:"port"` Addr uint32 `json:"ip4"` } type Tid64Ex struct { Port uint64 `json:"port"` IpVers uint32 `json:"ip_version"` // 0x10 = IPv6, 0x04 = IPv4 Addr4 uint32 `json:"ip4,omitempty"` Addr6 [4]uint32 `json:"ip6,omitempty"` } /* * socket domain 2 bytes * socket type 2 bytes * address type 2 bytes * local port 2 bytes * local Internet address 4/16 bytes * remote port 2 bytes * remote Internet address 4/16 bytes */ type SocketEx struct { Domain uint16 `json:"domain"` SockType uint16 `json:"type"` AddrType uint16 `json:"ip_version"` LocalPort uint16 `json:"local_port"` LocalAddr4 uint32 `json:"local_ip4",omitempty` LocalAddr6 [4]uint32 `json:"local_ip6",omitempty` RemotePort uint16 `json:"remote_port"` RemoteAddr4 uint32 `json:"remote_ip4",omitempty` RemoteAddr6 [4]uint32 `json:"remote_ip6",omitempty` } type SockInet32 struct { Family uint16 `json:"family"` Port uint16 `json:"port"` Addr4 uint32 `json:"ip4"` } type SockInet128 struct { Family uint16 `json:"family"` Port uint16 `json:"port"` Addr6 [4]uint32 `json:"ip6"` } /* * token ID 1 byte * socket family 2 bytes * path (up to) 104 bytes + NULL (NULL terminated string) */ type SockUnix struct { Family uint16 Path []byte } type Exit struct { Status uint32 `json:"status"` Ret uint32 `json:"code"` } type Text struct { Length uint16 `json:"length"` Text []byte `json:"text"` } type ZoneName struct { Length uint16 `json:"length"` // zone name length 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 */ // users ID for resolution type user struct { uid uint32 name string } // groups ID for resolution type group struct { gid uint32 name string } /* Utilities */ // Return uid if user not found func getUserName(uid uint32) (string, error) { for _, u := range gUsers { if u.uid == uid { return u.name, nil } } // Not found in cache, get it from system query u, err := getUserNameByUid(uid) if err != nil { // If not found, return user object with name = uid if err.Error() == "User ID not found" { u.uid = uid u.name = strconv.FormatUint(uint64(uid), 10) gUsers = append(gUsers, u) return u.name, err } else { return "", err } } gUsers = append(gUsers, u) return u.name, nil } func getUserNameByUid(uid uint32) (user, error) { var pw *C.struct_passwd var usr user pw = C.getpwuid((C.uint32_t)(uid)) if pw == nil { return usr, fmt.Errorf("User ID not found") } usr.uid = uid usr.name = C.GoString(pw.pw_name) return usr, nil } func getGroupName(gid uint32) (string, error) { for _, g := range gGroups { if g.gid == gid { return g.name, nil } } // Not found in cache, get it from system query g, err := getGroupNameByGid(gid) if err != nil { // If not found, return group object with name = gid if err.Error() == "Group ID not found" { g.gid = gid g.name = strconv.FormatUint(uint64(gid), 10) gGroups = append(gGroups, g) return g.name, err } else { return "", err } } gGroups = append(gGroups, g) return g.name, nil } func getGroupNameByGid(gid uint32) (group, error) { var gr *C.struct_group var grp group gr = C.getgrgid((C.uint32_t)(gid)) if gr == nil { return grp, fmt.Errorf("Group ID not found") } grp.gid = gid grp.name = C.GoString(gr.gr_name) return grp, nil } func getEventName(event uint16) (string, error) { if len(gEventDB) == 0 { err := loadEventDB() if err != nil { fmt.Printf("%v\n", err) } } for _, ev := range gEventDB { if ev.Type == int(event) { return ev.Desc, nil } } return "", fmt.Errorf("Event ID not found: %d\n", event) } // We load the entire file in memory func loadEventDB() error { file, err := os.Open(AUDIT_EVENT_FILE) if err != nil { return err } defer file.Close() fileScan := bufio.NewScanner(file) fileScan.Split(bufio.ScanLines) for fileScan.Scan() { line := fileScan.Text() if strings.HasPrefix(line, "#") { continue } eventStr := strings.Split(line, ":") // Wait for https://github.com/openbsm/openbsm/pull/75 //if len(eventStr) != 4 { if (len(eventStr) != 4 && eventStr[0] != "43082") || (len(eventStr) == 5 && eventStr[0] != "43082") { continue } t, err := strconv.Atoi(eventStr[0]) if err != nil { return fmt.Errorf("Unable to convert to int: %v\n", eventStr[0]) } // Wait for https://github.com/openbsm/openbsm/pull/75 if t == 43082 && (len(eventStr) == 5) { gEventDB = append(gEventDB, event{Type: t, Name: eventStr[1], Desc: eventStr[3], Class: eventStr[4]}) } else { gEventDB = append(gEventDB, event{Type: t, Name: eventStr[1], Desc: eventStr[2], Class: eventStr[3]}) } } return nil } func PrintIpv4FromInt(ipv4int uint32) string { return fmt.Sprintf("%d.%d.%d.%d", ipv4int&0xFF000000>>24, ipv4int&0x00FF0000>>16, ipv4int&0x0000FF00>>8, ipv4int&0x000000FF) } func PrintIpv6FromInt(ipv6int [4]uint32) string { //return fmt.Sprintf("%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", return fmt.Sprintf("%x:%x:%x:%x:%x:%x:%x:%x", ipv6int[0]&0xFFFF0000>>16, ipv6int[0]&0x0000FFFF, ipv6int[1]&0xFFFF0000>>16, ipv6int[1]&0x0000FFFF, ipv6int[2]&0xFFFF0000>>16, ipv6int[2]&0x0000FFFF, ipv6int[3]&0xFFFF0000>>16, ipv6int[3]&0x0000FFFF) } /* Records structs implementation */ func NewHeader32(h Header32) *Header32 { return &Header32{ Size: h.Size, Version: h.Version, E_type: h.E_type, E_mod: h.E_mod, S: h.S, Msec: h.Msec, } } func (h *Header32) GetType() uint8 { return AUT_HEADER32 } // TODO : Take *io.Reader as arg? func (h *Header32) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &h.Size) if err != nil { return fmt.Errorf("Unable to read Header32.Size: %v", err) } /* Check for recsize sanity: We already read 32 bits + 8 bits */ if h.Size < (4 + 1) { return fmt.Errorf("Record size is corrupted: %d", h.Size) } err = binary.Read(rdr, binary.BigEndian, &h.Version) if err != nil { return fmt.Errorf("Unable to read Header32.Version: %v", err) } err = binary.Read(rdr, binary.BigEndian, &h.E_type) if err != nil { return fmt.Errorf("Unable to read Header32.E_type: %v", err) } err = binary.Read(rdr, binary.BigEndian, &h.E_mod) if err != nil { return fmt.Errorf("Unable to read Header32.E_mod: %v", err) } err = binary.Read(rdr, binary.BigEndian, &h.S) if err != nil { return fmt.Errorf("Unable to read Header32.S: %v", err) } err = binary.Read(rdr, binary.BigEndian, &h.Msec) if err != nil { return fmt.Errorf("Unable to read Header32.Msec: %v", err) } return nil } /* Implementation of static void print_header32_tok(FILE *fp, tokenstr_t *tok, char *del, int oflags) */ func (h *Header32) Print(file *bufio.Writer, delimiter string, flags int) { var timeval string if PRT_TIMESYSLOG23 == flags&PRT_TIMESYSLOG23 { timeval = time.Unix((int64)(h.S), 0).Add(time.Millisecond * (time.Duration)(h.Msec)).Format("2006-01-02T15:04:05.000Z07:00") } else { t := time.Unix((int64)(h.S), 0) timeval = t.Format(time.UnixDate) } evdesc, err := getEventName(h.E_type) if err != nil { fmt.Printf("%v\n", err) return } if flags&PRT_JSON == PRT_JSON { var printable interface{} if PRT_TIMESYSLOG23 == flags&PRT_TIMESYSLOG23 { 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 RSYSLOG_SyslogProtocol23Format }{ Size: h.Size, Version: h.Version, E_type: evdesc, E_mod: h.E_mod, 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) if err != nil { // TODO return } // Header start the json object fmt.Fprintf(file, "{\"header32\":") fmt.Fprintf(file, "%s", j) // and header is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "header%s%d%s%d%s%s%s%v%s%s%s%d", delimiter, h.Size, delimiter, h.Version, delimiter, //h.E_type, delimiter, h.E_mod, delimiter, t.Format(time.UnixDate), delimiter, h.Msec) evdesc, delimiter, h.E_mod, delimiter, timeval, delimiter, h.Msec) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewExecArg(e ExecArg) *ExecArg { return &ExecArg{ Count: e.Count, Text: e.Text, } } func (e *ExecArg) GetType() uint8 { return AUT_EXEC_ARGS } func (e *ExecArg) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &e.Count) if err != nil { return fmt.Errorf("Unable to read ExecArg.Count: %v", err) } for i := uint32(0); i < e.Count; i++ { // Get this arg length arg, err := rdr.ReadBytes((byte)(0x00)) if err != nil { return fmt.Errorf("Error searching for null terminated exec arg: Loop exec n%d, error : %v", i, err) } e.Text = append(e.Text, arg[:len(arg)-1]) } return nil } func (e *ExecArg) Print(file *bufio.Writer, delimiter string, flags int) { if flags&PRT_JSON == PRT_JSON { // We don't need no count, bc we reconstiture command line printable := struct { Text string `json:"text"` }{} for i, b := range e.Text { /*printable.Text = append(printable.Text, b...) printable.Text = append(printable.Text, []byte(" ")...)*/ printable.Text = fmt.Sprintf("%s%s", printable.Text, b) if i < (len(e.Text) - 1) { printable.Text += " " } } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"execarg\":") fmt.Fprintf(file, "%s", j) fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "exec arg%s", delimiter) for i := uint32(0); i < e.Count; i++ { if i < e.Count-1 { fmt.Fprintf(file, "%s%s", string(e.Text[i]), delimiter) } else { fmt.Fprintf(file, "%s", string(e.Text[i])) } } if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewPath(p Path) *Path { return &Path{ Length: p.Length, Path: p.Path, } } func (p *Path) GetType() uint8 { return AUT_PATH } func (p *Path) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &p.Length) if err != nil { return fmt.Errorf("Unable to read Path.Length: %v", err) } arg, err := rdr.ReadBytes((byte)(0x00)) if err != nil { return fmt.Errorf("Error searching for null terminated path: error : %v", err) } p.Path = arg[:len(arg)-1] return nil } func (p *Path) Print(file *bufio.Writer, delimiter string, flags int) { if flags&PRT_JSON == PRT_JSON { // We don't need no length printable := struct { Path string `json:"path"` }{ Path: fmt.Sprintf("%s", p.Path), } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"path\":") fmt.Fprintf(file, "%s", j) // path is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "path%s%s", delimiter, string(p.Path)) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewAttribute32(a Attribute32) *Attribute32 { return &Attribute32{ Mode: a.Mode, Uid: a.Uid, Gid: a.Gid, Fsid: a.Fsid, Nid: a.Nid, Dev: a.Dev, } } func (a *Attribute32) GetType() uint8 { return AUT_ATTR32 } func (a *Attribute32) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &a.Mode) if err != nil { return fmt.Errorf("Unable to read Attribute32.Mode: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Uid) if err != nil { return fmt.Errorf("Unable to read Attribute32.Uid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Gid) if err != nil { return fmt.Errorf("Unable to read Attribute32.Gid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Fsid) if err != nil { return fmt.Errorf("Unable to read Attribute32.Fsid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Nid) if err != nil { return fmt.Errorf("Unable to read Attribute32.Nid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Dev) if err != nil { return fmt.Errorf("Unable to read Attribute32.Dev: %v", err) } return nil } func (a *Attribute32) Print(file *bufio.Writer, delimiter string, flags int) { var user string var group string if PRT_NORESOLVE_USER == flags&PRT_NORESOLVE_USER { user = strconv.Itoa(int(a.Uid)) group = strconv.Itoa(int(a.Gid)) } else { user, _ = getUserName(a.Uid) group, _ = getGroupName(a.Gid) } if flags&PRT_JSON == PRT_JSON { printable := struct { Mode uint32 `json:"mode"` // file access mode Uid uint32 `json:"user_id",omitempty` // Owner user ID User string `json:"username",omitempty` // Owner username Gid uint32 `json:"group_id",omitempty` // Owner group ID Group string `json:"group",omitempty` // Owner group name Fsid uint32 `json:"filesystem_id"` // File system ID Nid uint64 `json:"node_id"` // Node ID Dev uint32 `json:"device"` // Device }{ Mode: a.Mode, Uid: a.Uid, Gid: a.Gid, Fsid: a.Fsid, Nid: a.Nid, Dev: a.Dev, } if PRT_NORESOLVE_USER != flags&PRT_NORESOLVE_USER { printable.User = fmt.Sprintf("%s", user) printable.Group = fmt.Sprintf("%s", group) } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"attribute32\":") fmt.Fprintf(file, "%s", j) // attribute32 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "attribute%s%o%s%s%s%s%s%v%s%v%s%v", delimiter, a.Mode, delimiter, user, delimiter, group, delimiter, a.Fsid, delimiter, a.Nid, delimiter, a.Dev) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewAttribute64(a Attribute64) *Attribute64 { return &Attribute64{ Mode: a.Mode, Uid: a.Uid, Gid: a.Gid, Fsid: a.Fsid, Nid: a.Nid, Dev: a.Dev, } } func (a *Attribute64) GetType() uint8 { return AUT_ATTR64 } func (a *Attribute64) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &a.Mode) if err != nil { return fmt.Errorf("Unable to read Attribute64.Mode: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Uid) if err != nil { return fmt.Errorf("Unable to read Attribute64.Uid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Gid) if err != nil { return fmt.Errorf("Unable to read Attribute64.Gid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Fsid) if err != nil { return fmt.Errorf("Unable to read Attribute64.Fsid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Nid) if err != nil { return fmt.Errorf("Unable to read Attribute64.Nid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Dev) if err != nil { return fmt.Errorf("Unable to read Attribute64.Dev: %v", err) } return nil } func (a *Attribute64) Print(file *bufio.Writer, delimiter string, flags int) { var user string var group string // TODO : resolve Uid and Gid (also support domain accounts) if PRT_NORESOLVE_USER == flags&PRT_NORESOLVE_USER { user = strconv.Itoa(int(a.Uid)) group = strconv.Itoa(int(a.Gid)) } else { user, _ = getUserName(a.Uid) group, _ = getGroupName(a.Gid) } if flags&PRT_JSON == PRT_JSON { printable := struct { Mode uint32 `json:"mode"` // file access mode Uid uint32 `json:"user_id",omitempty` // Owner user ID User string `json:"username",omitempty` // Owner username Gid uint32 `json:"group_id",omitempty` // Owner group ID Group string `json:"group",omitempty` // Owner group name Fsid uint32 `json:"filesystem_id"` // File system ID Nid uint64 `json:"node_id"` // Node ID Dev uint64 `json:"device"` // Device }{ Mode: a.Mode, Uid: a.Uid, Gid: a.Gid, Fsid: a.Fsid, Nid: a.Nid, Dev: a.Dev, } if PRT_NORESOLVE_USER != flags&PRT_NORESOLVE_USER { printable.User = fmt.Sprintf("%s", user) printable.Group = fmt.Sprintf("%s", group) } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"attribute64\":") fmt.Fprintf(file, "%s", j) // attribute64 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "attribute%s%o%s%v%s%v%s%v%s%v%s%v", delimiter, a.Mode, delimiter, user, delimiter, group, delimiter, a.Fsid, delimiter, a.Nid, delimiter, a.Dev) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewSubject32(s Subject32) *Subject32 { return &Subject32{ Auid: s.Auid, Euid: s.Euid, Egid: s.Egid, Ruid: s.Ruid, Rgid: s.Rgid, Pid: s.Pid, Sid: s.Sid, Tid: s.Tid, } } func (s *Subject32) GetType() uint8 { return AUT_SUBJECT32 } func (s *Subject32) LoadFromBinary(rdr *bufio.Reader) error { /* type Subject32 struct { Auid uint32 `json:"audit_id"` // Audit ID Euid uint32 `json:"effective_user_id"` // Effective user ID Egid uint32 `json:"effective_group_id"` // Effective Group ID Ruid uint32 `json:"real_user_id"` // Real User ID Rgid uint32 `json:"real_group_id"` // Real Group ID Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid Tid32 `json:"terminal_id"` } */ err := binary.Read(rdr, binary.BigEndian, &s.Auid) if err != nil { return fmt.Errorf("Unable to read Sibject32.Auid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Euid) if err != nil { return fmt.Errorf("Unable to read Subject32.Euid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Egid) if err != nil { return fmt.Errorf("Unable to read Subject32.Egid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Ruid) if err != nil { return fmt.Errorf("Unable to read Subject32.Ruid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Rgid) if err != nil { return fmt.Errorf("Unable to read Subject32.Rgid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Pid) if err != nil { return fmt.Errorf("Unable to read Subject32.Pid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Sid) if err != nil { return fmt.Errorf("Unable to read Subject32.Sid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Tid) if err != nil { return fmt.Errorf("Unable to read Subject32.Tid.Port: %v", err) } return nil } func (s *Subject32) Print(file *bufio.Writer, delimiter string, flags int) { var auser string var euser string var egroup string var ruser string var rgroup string if PRT_NORESOLVE_USER == flags&PRT_NORESOLVE_USER { auser = strconv.Itoa(int(s.Auid)) euser = strconv.Itoa(int(s.Euid)) egroup = strconv.Itoa(int(s.Egid)) ruser = strconv.Itoa(int(s.Ruid)) rgroup = strconv.Itoa(int(s.Rgid)) } else { auser, _ = getUserName(s.Auid) euser, _ = getUserName(s.Euid) egroup, _ = getGroupName(s.Egid) ruser, _ = getUserName(s.Ruid) rgroup, _ = getGroupName(s.Rgid) } if flags&PRT_JSON == PRT_JSON { type ttid struct { Port uint32 `json:"port"` Addr string `json:"ip4"` } tid := ttid{ Port: s.Tid.Port, Addr: PrintIpv4FromInt(s.Tid.Addr), } printable := struct { Auid uint32 `json:"audit_id"` // Audit ID Auser string `json:"audit_username",omitempty` Euid uint32 `json:"effective_user_id"` // Effective user ID Euser string `json:"effective_username",omitempty` Egid uint32 `json:"effective_group_id"` // Effective Group ID Egroup string `json:"effective_group",omitempty` Ruid uint32 `json:"real_user_id"` // Real User ID Ruser string `json:"real_username",omitempty` Rgid uint32 `json:"real_group_id"` // Real Group ID Rgroup string `json:"real_group",omitempty` Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid ttid `json:"terminal"` }{ Auid: s.Auid, Euid: s.Euid, Egid: s.Egid, Ruid: s.Ruid, Rgid: s.Rgid, Pid: s.Pid, Sid: s.Sid, Tid: tid, } if PRT_NORESOLVE_USER != flags&PRT_NORESOLVE_USER { printable.Auser = auser printable.Euser = euser printable.Egroup = egroup printable.Ruser = ruser printable.Rgroup = rgroup } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"subject32\":") fmt.Fprintf(file, "%s", j) // subject32 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "subject%s%s%s%s%s%s%s%s%s%s%s%v%s%v%s%v%s%s", delimiter, auser, delimiter, euser, delimiter, egroup, delimiter, ruser, delimiter, rgroup, delimiter, s.Pid, delimiter, s.Sid, delimiter, s.Tid.Port, delimiter, PrintIpv4FromInt(s.Tid.Addr)) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewProcess32(s Process32) *Process32 { return &Process32{ Auid: s.Auid, Euid: s.Euid, Egid: s.Egid, Ruid: s.Ruid, Rgid: s.Rgid, Pid: s.Pid, Sid: s.Sid, Tid: s.Tid, } } func (p *Process32) GetType() uint8 { return AUT_PROCESS32 } func (p *Process32) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &p.Auid) if err != nil { return fmt.Errorf("Unable to read Process32.Auid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Euid) if err != nil { return fmt.Errorf("Unable to read Process32.Euid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Egid) if err != nil { return fmt.Errorf("Unable to read Process32.Egid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Ruid) if err != nil { return fmt.Errorf("Unable to read Process32.Ruid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Rgid) if err != nil { return fmt.Errorf("Unable to read Process32.Rgid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Pid) if err != nil { return fmt.Errorf("Unable to read Process32.Pid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Sid) if err != nil { return fmt.Errorf("Unable to read Process32.Sid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Tid) if err != nil { return fmt.Errorf("Unable to read Process32.Tid: %v", err) } return nil } func (p *Process32) Print(file *bufio.Writer, delimiter string, flags int) { var auser string var euser string var egroup string var ruser string var rgroup string if PRT_NORESOLVE_USER == flags&PRT_NORESOLVE_USER { auser = strconv.Itoa(int(p.Auid)) euser = strconv.Itoa(int(p.Euid)) egroup = strconv.Itoa(int(p.Egid)) ruser = strconv.Itoa(int(p.Ruid)) rgroup = strconv.Itoa(int(p.Rgid)) } else { auser, _ = getUserName(p.Auid) euser, _ = getUserName(p.Euid) egroup, _ = getGroupName(p.Egid) ruser, _ = getUserName(p.Ruid) rgroup, _ = getGroupName(p.Rgid) } if flags&PRT_JSON == PRT_JSON { type ttid struct { Port uint32 `json:"port"` Addr string `json:"ip"` } tid := ttid{ Port: p.Tid.Port, Addr: PrintIpv4FromInt(p.Tid.Addr), } printable := struct { Auid uint32 `json:"audit_id"` // Audit ID Auser string `json:"audit_username",omitempty` Euid uint32 `json:"effective_user_id"` // Effective user ID Euser string `json:"effective_username",omitempty` Egid uint32 `json:"effective_group_id"` // Effective Group ID Egroup string `json:"effective_group",omitempty` Ruid uint32 `json:"real_user_id"` // Real User ID Ruser string `json:"real_username",omitempty` Rgid uint32 `json:"real_group_id"` // Real Group ID Rgroup string `json:"real_group",omitempty` Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid ttid `json:"terminal"` }{ Auid: p.Auid, Euid: p.Euid, Egid: p.Egid, Ruid: p.Ruid, Rgid: p.Rgid, Pid: p.Pid, Sid: p.Sid, Tid: tid, } if PRT_NORESOLVE_USER != flags&PRT_NORESOLVE_USER { printable.Auser = auser printable.Euser = euser printable.Egroup = egroup printable.Ruser = ruser printable.Rgroup = rgroup } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"process32\":") fmt.Fprintf(file, "%s", j) // process32 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "process%s%s%s%s%s%s%s%s%s%s%s%v%s%v%s%v%s%s", delimiter, auser, delimiter, euser, delimiter, egroup, delimiter, ruser, delimiter, rgroup, delimiter, p.Pid, delimiter, p.Sid, delimiter, p.Tid.Port, delimiter, PrintIpv4FromInt(p.Tid.Addr)) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewSubject32Ex(s Subject32Ex) *Subject32Ex { return &Subject32Ex{ Auid: s.Auid, Euid: s.Euid, Egid: s.Egid, Ruid: s.Ruid, Rgid: s.Rgid, Pid: s.Pid, Sid: s.Sid, Tid: s.Tid, } } func (s *Subject32Ex) GetType() uint8 { return AUT_SUBJECT32_EX } func (s *Subject32Ex) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &s.Auid) if err != nil { return fmt.Errorf("Unable to read Sibject32Ex.Auid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Euid) if err != nil { return fmt.Errorf("Unable to read Subject32Ex.Euid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Egid) if err != nil { return fmt.Errorf("Unable to read Subject32Ex.Egid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Ruid) if err != nil { return fmt.Errorf("Unable to read Subject32Ex.Ruid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Rgid) if err != nil { return fmt.Errorf("Unable to read Subject32Ex.Rgid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Pid) if err != nil { return fmt.Errorf("Unable to read Subject32Ex.Pid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Sid) if err != nil { return fmt.Errorf("Unable to read Subject32Ex.Sid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Tid.Port) if err != nil { return fmt.Errorf("Unable to read Subject32Ex.Tid.Port: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Tid.IpVers) if err != nil { return fmt.Errorf("Unable to read Subject32Ex.Tid.IpVers: %v", err) } if s.Tid.IpVers == 0x10 { err = binary.Read(rdr, binary.BigEndian, &s.Tid.Addr6) if err != nil { return fmt.Errorf("Unable to read Subject32Ex.Tid.Addr6: %v", err) } } else if s.Tid.IpVers == 0x04 { err = binary.Read(rdr, binary.BigEndian, &s.Tid.Addr4) if err != nil { return fmt.Errorf("Unable to read Subject32Ex.Tid.Addr4: %v", err) } } return nil } func (s *Subject32Ex) Print(file *bufio.Writer, delimiter string, flags int) { var auser string var euser string var egroup string var ruser string var rgroup string var ip string if PRT_NORESOLVE_USER == flags&PRT_NORESOLVE_USER { auser = strconv.Itoa(int(s.Auid)) euser = strconv.Itoa(int(s.Euid)) egroup = strconv.Itoa(int(s.Egid)) ruser = strconv.Itoa(int(s.Ruid)) rgroup = strconv.Itoa(int(s.Rgid)) } else { auser, _ = getUserName(s.Auid) euser, _ = getUserName(s.Euid) egroup, _ = getGroupName(s.Egid) ruser, _ = getUserName(s.Ruid) rgroup, _ = getGroupName(s.Rgid) } if s.Tid.IpVers == 0x04 { ip = PrintIpv4FromInt(s.Tid.Addr4) } else { ip = PrintIpv6FromInt(s.Tid.Addr6) } if flags&PRT_JSON == PRT_JSON { type ttid struct { Port uint32 `json:"port"` Addr4 string `json:"ip4,omitempty"` Addr6 string `json:"ip6,omitempty"` } tid := ttid{ Port: s.Tid.Port, } if s.Tid.IpVers == 0x04 { tid.Addr4 = ip } else { tid.Addr6 = ip } printable := struct { Auid uint32 `json:"audit_id"` // Audit ID Auser string `json:"audit_username",omitempty` Euid uint32 `json:"effective_user_id"` // Effective user ID Euser string `json:"effective_username",omitempty` Egid uint32 `json:"effective_group_id"` // Effective Group ID Egroup string `json:"effective_group",omitempty` Ruid uint32 `json:"real_user_id"` // Real User ID Ruser string `json:"real_username",omitempty` Rgid uint32 `json:"real_group_id"` // Real Group ID Rgroup string `json:"real_group",omitempty` Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid ttid `json:"terminal"` }{ Auid: s.Auid, Euid: s.Euid, Egid: s.Egid, Ruid: s.Ruid, Rgid: s.Rgid, Pid: s.Pid, Sid: s.Sid, Tid: tid, } if PRT_NORESOLVE_USER != flags&PRT_NORESOLVE_USER { printable.Auser = auser printable.Euser = euser printable.Egroup = egroup printable.Ruser = ruser printable.Rgroup = rgroup } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"subject32ex\":") fmt.Fprintf(file, "%s", j) // subject32ex is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "subject_ex%s%s%s%s%s%s%s%s%s%s%s%v%s%v%s%v%s%s", delimiter, auser, delimiter, euser, delimiter, egroup, delimiter, ruser, delimiter, rgroup, delimiter, s.Pid, delimiter, s.Sid, delimiter, s.Tid.Port, delimiter, ip) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewProcess32Ex(p Process32Ex) *Process32Ex { return &Process32Ex{ Auid: p.Auid, Euid: p.Euid, Egid: p.Egid, Ruid: p.Ruid, Rgid: p.Rgid, Pid: p.Pid, Sid: p.Sid, Tid: p.Tid, } } func (s *Process32Ex) GetType() uint8 { return AUT_PROCESS32_EX } func (p *Process32Ex) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &p.Auid) if err != nil { return fmt.Errorf("Unable to read Process32Ex.Auid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Euid) if err != nil { return fmt.Errorf("Unable to read Process32Ex.Euid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Egid) if err != nil { return fmt.Errorf("Unable to read Process32Ex.Egid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Ruid) if err != nil { return fmt.Errorf("Unable to read Process32Ex.Ruid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Rgid) if err != nil { return fmt.Errorf("Unable to read Process32Ex.Rgid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Pid) if err != nil { return fmt.Errorf("Unable to read Process32Ex.Pid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Sid) if err != nil { return fmt.Errorf("Unable to read Process32Ex.Sid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Tid.Port) if err != nil { return fmt.Errorf("Unable to read Process32Ex.Tid.Port: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Tid.IpVers) if err != nil { return fmt.Errorf("Unable to read Process32Ex.Tid.IpVers: %v", err) } if p.Tid.IpVers == 0x10 { err = binary.Read(rdr, binary.BigEndian, &p.Tid.Addr6) if err != nil { return fmt.Errorf("Unable to read Process32Ex.Tid.Addr6: %v", err) } } else if p.Tid.IpVers == 0x04 { err = binary.Read(rdr, binary.BigEndian, &p.Tid.Addr4) if err != nil { return fmt.Errorf("Unable to read Process32Ex.Tid.Addr4: %v", err) } } return nil } func (p *Process32Ex) Print(file *bufio.Writer, delimiter string, flags int) { var auser string var euser string var egroup string var ruser string var rgroup string var ip string if PRT_NORESOLVE_USER == flags&PRT_NORESOLVE_USER { auser = strconv.Itoa(int(p.Auid)) euser = strconv.Itoa(int(p.Euid)) egroup = strconv.Itoa(int(p.Egid)) ruser = strconv.Itoa(int(p.Ruid)) rgroup = strconv.Itoa(int(p.Rgid)) } else { auser, _ = getUserName(p.Auid) euser, _ = getUserName(p.Euid) egroup, _ = getGroupName(p.Egid) ruser, _ = getUserName(p.Ruid) rgroup, _ = getGroupName(p.Rgid) } if p.Tid.IpVers == 0x04 { ip = PrintIpv4FromInt(p.Tid.Addr4) } else { ip = PrintIpv6FromInt(p.Tid.Addr6) } if flags&PRT_JSON == PRT_JSON { type ttid struct { Port uint32 `json:"port"` Addr4 string `json:"ip4,omitempty"` Addr6 string `json:"ip6,omitempty"` } tid := ttid{ Port: p.Tid.Port, } if p.Tid.IpVers == 0x04 { tid.Addr4 = ip } else { tid.Addr6 = ip } printable := struct { Auid uint32 `json:"audit_id"` // Audit ID Auser string `json:"audit_username",omitempty` Euid uint32 `json:"effective_user_id"` // Effective user ID Euser string `json:"effective_username",omitempty` Egid uint32 `json:"effective_group_id"` // Effective Group ID Egroup string `json:"effective_group",omitempty` Ruid uint32 `json:"real_user_id"` // Real User ID Ruser string `json:"real_username",omitempty` Rgid uint32 `json:"real_group_id"` // Real Group ID Rgroup string `json:"real_group",omitempty` Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid ttid `json:"terminal"` }{ Auid: p.Auid, Euid: p.Euid, Egid: p.Egid, Ruid: p.Ruid, Rgid: p.Rgid, Pid: p.Pid, Sid: p.Sid, Tid: tid, } if PRT_NORESOLVE_USER != flags&PRT_NORESOLVE_USER { printable.Auser = auser printable.Euser = euser printable.Egroup = egroup printable.Ruser = ruser printable.Rgroup = rgroup } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"process32ex\":") fmt.Fprintf(file, "%s", j) // process32ex is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "process_ex%s%s%s%s%s%s%s%s%s%s%s%v%s%v%s%v%s%s", delimiter, auser, delimiter, euser, delimiter, egroup, delimiter, ruser, delimiter, rgroup, delimiter, p.Pid, delimiter, p.Sid, delimiter, p.Tid.Port, delimiter, ip) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewSubject64(s Subject64) *Subject64 { return &Subject64{ Auid: s.Auid, Euid: s.Euid, Egid: s.Egid, Ruid: s.Ruid, Rgid: s.Rgid, Pid: s.Pid, Sid: s.Sid, Tid: s.Tid, } } func (s *Subject64) GetType() uint8 { return AUT_SUBJECT64 } func (s *Subject64) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &s.Auid) if err != nil { return fmt.Errorf("Unable to read Sibject64.Auid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Euid) if err != nil { return fmt.Errorf("Unable to read Subject64.Euid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Egid) if err != nil { return fmt.Errorf("Unable to read Subject64.Egid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Ruid) if err != nil { return fmt.Errorf("Unable to read Subject64.Ruid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Rgid) if err != nil { return fmt.Errorf("Unable to read Subject64.Rgid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Pid) if err != nil { return fmt.Errorf("Unable to read Subject64.Pid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Sid) if err != nil { return fmt.Errorf("Unable to read Subject64.Sid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Tid) if err != nil { return fmt.Errorf("Unable to read Subject64.Tid: %v", err) } return nil } func (s *Subject64) Print(file *bufio.Writer, delimiter string, flags int) { var auser string var euser string var egroup string var ruser string var rgroup string if PRT_NORESOLVE_USER == flags&PRT_NORESOLVE_USER { auser = strconv.Itoa(int(s.Auid)) euser = strconv.Itoa(int(s.Euid)) egroup = strconv.Itoa(int(s.Egid)) ruser = strconv.Itoa(int(s.Ruid)) rgroup = strconv.Itoa(int(s.Rgid)) } else { auser, _ = getUserName(s.Auid) euser, _ = getUserName(s.Euid) egroup, _ = getGroupName(s.Egid) ruser, _ = getUserName(s.Ruid) rgroup, _ = getGroupName(s.Rgid) } if flags&PRT_JSON == PRT_JSON { type ttid struct { Port uint64 `json:"port"` Addr string `json:"ip4"` } tid := ttid{ Port: s.Tid.Port, Addr: PrintIpv4FromInt(s.Tid.Addr), } printable := struct { Auid uint32 `json:"audit_id"` // Audit ID Auser string `json:"audit_username",omitempty` Euid uint32 `json:"effective_user_id"` // Effective user ID Euser string `json:"effective_username",omitempty` Egid uint32 `json:"effective_group_id"` // Effective Group ID Egroup string `json:"effective_group",omitempty` Ruid uint32 `json:"real_user_id"` // Real User ID Ruser string `json:"real_username",omitempty` Rgid uint32 `json:"real_group_id"` // Real Group ID Rgroup string `json:"real_group",omitempty` Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid ttid `json:"terminal"` }{ Auid: s.Auid, Euid: s.Euid, Egid: s.Egid, Ruid: s.Ruid, Rgid: s.Rgid, Pid: s.Pid, Sid: s.Sid, Tid: tid, } if PRT_NORESOLVE_USER != flags&PRT_NORESOLVE_USER { printable.Auser = auser printable.Euser = euser printable.Egroup = egroup printable.Ruser = ruser printable.Rgroup = rgroup } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"subject64\":") fmt.Fprintf(file, "%s", j) // subject64 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "subject%s%s%s%s%s%s%s%s%s%s%s%v%s%v%s%v%s%s", delimiter, auser, delimiter, euser, delimiter, egroup, delimiter, ruser, delimiter, rgroup, delimiter, s.Pid, delimiter, s.Sid, delimiter, s.Tid.Port, delimiter, PrintIpv4FromInt(s.Tid.Addr)) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewProcess64(p Process64) *Process64 { return &Process64{ Auid: p.Auid, Euid: p.Euid, Egid: p.Egid, Ruid: p.Ruid, Rgid: p.Rgid, Pid: p.Pid, Sid: p.Sid, Tid: p.Tid, } } func (s *Process64) GetType() uint8 { return AUT_PROCESS64 } func (p *Process64) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &p.Auid) if err != nil { return fmt.Errorf("Unable to read Process64.Auid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Euid) if err != nil { return fmt.Errorf("Unable to read Process64.Euid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Egid) if err != nil { return fmt.Errorf("Unable to read Process64.Egid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Ruid) if err != nil { return fmt.Errorf("Unable to read Process64.Ruid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Rgid) if err != nil { return fmt.Errorf("Unable to read Process64.Rgid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Pid) if err != nil { return fmt.Errorf("Unable to read Process64.Pid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Sid) if err != nil { return fmt.Errorf("Unable to read Process64.Sid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Tid) if err != nil { return fmt.Errorf("Unable to read Process64.Tid: %v", err) } return nil } func (p *Process64) Print(file *bufio.Writer, delimiter string, flags int) { var auser string var euser string var egroup string var ruser string var rgroup string if PRT_NORESOLVE_USER == flags&PRT_NORESOLVE_USER { auser = strconv.Itoa(int(p.Auid)) euser = strconv.Itoa(int(p.Euid)) egroup = strconv.Itoa(int(p.Egid)) ruser = strconv.Itoa(int(p.Ruid)) rgroup = strconv.Itoa(int(p.Rgid)) } else { auser, _ = getUserName(p.Auid) euser, _ = getUserName(p.Euid) egroup, _ = getGroupName(p.Egid) ruser, _ = getUserName(p.Ruid) rgroup, _ = getGroupName(p.Rgid) } if flags&PRT_JSON == PRT_JSON { type ttid struct { Port uint64 `json:"port"` Addr string `json:"ip4"` } tid := ttid{ Port: p.Tid.Port, Addr: PrintIpv4FromInt(p.Tid.Addr), } printable := struct { Auid uint32 `json:"audit_id"` // Audit ID Auser string `json:"audit_username",omitempty` Euid uint32 `json:"effective_user_id"` // Effective user ID Euser string `json:"effective_username",omitempty` Egid uint32 `json:"effective_group_id"` // Effective Group ID Egroup string `json:"effective_group",omitempty` Ruid uint32 `json:"real_user_id"` // Real User ID Ruser string `json:"real_username",omitempty` Rgid uint32 `json:"real_group_id"` // Real Group ID Rgroup string `json:"real_group",omitempty` Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid ttid `json:"terminal"` }{ Auid: p.Auid, Euid: p.Euid, Egid: p.Egid, Ruid: p.Ruid, Rgid: p.Rgid, Pid: p.Pid, Sid: p.Sid, Tid: tid, } if PRT_NORESOLVE_USER != flags&PRT_NORESOLVE_USER { printable.Auser = auser printable.Euser = euser printable.Egroup = egroup printable.Ruser = ruser printable.Rgroup = rgroup } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"process64\":") fmt.Fprintf(file, "%s", j) // process64 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "process%s%s%s%s%s%s%s%s%s%s%s%v%s%v%s%v%s%s", delimiter, auser, delimiter, euser, delimiter, egroup, delimiter, ruser, delimiter, rgroup, delimiter, p.Pid, delimiter, p.Sid, delimiter, p.Tid.Port, delimiter, PrintIpv4FromInt(p.Tid.Addr)) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewSubject64Ex(s Subject64Ex) *Subject64Ex { return &Subject64Ex{ Auid: s.Auid, Euid: s.Euid, Egid: s.Egid, Ruid: s.Ruid, Rgid: s.Rgid, Pid: s.Pid, Sid: s.Sid, Tid: s.Tid, } } func (s *Subject64Ex) GetType() uint8 { return AUT_SUBJECT64_EX } func (s *Subject64Ex) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &s.Auid) if err != nil { return fmt.Errorf("Unable to read Subject64Ex.Auid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Euid) if err != nil { return fmt.Errorf("Unable to read Subject64Ex.Euid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Egid) if err != nil { return fmt.Errorf("Unable to read Subject64Ex.Egid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Ruid) if err != nil { return fmt.Errorf("Unable to read Subject64Ex.Ruid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Rgid) if err != nil { return fmt.Errorf("Unable to read Subject64Ex.Rgid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Pid) if err != nil { return fmt.Errorf("Unable to read Subject64Ex.Pid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Sid) if err != nil { return fmt.Errorf("Unable to read Subject64Ex.Sid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Tid.Port) if err != nil { return fmt.Errorf("Unable to read Subject64Ex.Tid.Port: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Tid.IpVers) if err != nil { return fmt.Errorf("Unable to read Subject64Ex.Tid.IpVers: %v", err) } if s.Tid.IpVers == ISIPV6 { err = binary.Read(rdr, binary.BigEndian, &s.Tid.Addr6) if err != nil { return fmt.Errorf("Unable to read Subject64Ex.Tid.Addr6: %v", err) } } else if s.Tid.IpVers == ISIPV4 { err = binary.Read(rdr, binary.BigEndian, &s.Tid.Addr4) if err != nil { return fmt.Errorf("Unable to read Subject64Ex.Tid.Addr4: %v", err) } } return nil } func (s *Subject64Ex) Print(file *bufio.Writer, delimiter string, flags int) { var auser string var euser string var egroup string var ruser string var rgroup string var ip string if PRT_NORESOLVE_USER == flags&PRT_NORESOLVE_USER { auser = strconv.Itoa(int(s.Auid)) euser = strconv.Itoa(int(s.Euid)) egroup = strconv.Itoa(int(s.Egid)) ruser = strconv.Itoa(int(s.Ruid)) rgroup = strconv.Itoa(int(s.Rgid)) } else { auser, _ = getUserName(s.Auid) euser, _ = getUserName(s.Euid) egroup, _ = getGroupName(s.Egid) ruser, _ = getUserName(s.Ruid) rgroup, _ = getGroupName(s.Rgid) } if s.Tid.IpVers == ISIPV4 { ip = PrintIpv4FromInt(s.Tid.Addr4) } else { ip = PrintIpv6FromInt(s.Tid.Addr6) } if flags&PRT_JSON == PRT_JSON { type ttid struct { Port uint64 `json:"port"` Addr4 string `json:"ip4,omitempty"` Addr6 string `json:"ip6,omitempty"` } tid := ttid{ Port: s.Tid.Port, } if s.Tid.IpVers == ISIPV4 { tid.Addr4 = ip } else { tid.Addr6 = ip } printable := struct { Auid uint32 `json:"audit_id"` // Audit ID Auser string `json:"audit_username",omitempty` Euid uint32 `json:"effective_user_id"` // Effective user ID Euser string `json:"effective_username",omitempty` Egid uint32 `json:"effective_group_id"` // Effective Group ID Egroup string `json:"effective_group",omitempty` Ruid uint32 `json:"real_user_id"` // Real User ID Ruser string `json:"real_username",omitempty` Rgid uint32 `json:"real_group_id"` // Real Group ID Rgroup string `json:"real_group",omitempty` Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid ttid `json:"terminal"` }{ Auid: s.Auid, Euid: s.Euid, Egid: s.Egid, Ruid: s.Ruid, Rgid: s.Rgid, Pid: s.Pid, Sid: s.Sid, Tid: tid, } if PRT_NORESOLVE_USER != flags&PRT_NORESOLVE_USER { printable.Auser = auser printable.Euser = euser printable.Egroup = egroup printable.Ruser = ruser printable.Rgroup = rgroup } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"subject64\":") fmt.Fprintf(file, "%s", j) // subject64 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "subject_ex%s%s%s%s%s%s%s%s%s%s%s%v%s%v%s%v%s%s", delimiter, auser, delimiter, euser, delimiter, egroup, delimiter, ruser, delimiter, rgroup, delimiter, s.Pid, delimiter, s.Sid, delimiter, s.Tid.Port, delimiter, ip) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewProcess64Ex(p Process64Ex) *Process64Ex { return &Process64Ex{ Auid: p.Auid, Euid: p.Euid, Egid: p.Egid, Ruid: p.Ruid, Rgid: p.Rgid, Pid: p.Pid, Sid: p.Sid, Tid: p.Tid, } } func (p *Process64Ex) GetType() uint8 { return AUT_PROCESS64_EX } func (p *Process64Ex) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &p.Auid) if err != nil { return fmt.Errorf("Unable to read Process64Ex.Auid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Euid) if err != nil { return fmt.Errorf("Unable to read Process64Ex.Euid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Egid) if err != nil { return fmt.Errorf("Unable to read Process64Ex.Egid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Ruid) if err != nil { return fmt.Errorf("Unable to read Process64Ex.Ruid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Rgid) if err != nil { return fmt.Errorf("Unable to read Process64Ex.Rgid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Pid) if err != nil { return fmt.Errorf("Unable to read Process64Ex.Pid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Sid) if err != nil { return fmt.Errorf("Unable to read Process64Ex.Sid: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Tid.Port) if err != nil { return fmt.Errorf("Unable to read Process64Ex.Tid.Port: %v", err) } err = binary.Read(rdr, binary.BigEndian, &p.Tid.IpVers) if err != nil { return fmt.Errorf("Unable to read Process64Ex.Tid.IpVers: %v", err) } if p.Tid.IpVers == 0x10 { err = binary.Read(rdr, binary.BigEndian, &p.Tid.Addr6) if err != nil { return fmt.Errorf("Unable to read Process64Ex.Tid.Addr6: %v", err) } } else if p.Tid.IpVers == 0x04 { err = binary.Read(rdr, binary.BigEndian, &p.Tid.Addr4) if err != nil { return fmt.Errorf("Unable to read Process64Ex.Tid.Addr4: %v", err) } } return nil } func (p *Process64Ex) Print(file *bufio.Writer, delimiter string, flags int) { var auser string var euser string var egroup string var ruser string var rgroup string var ip string if PRT_NORESOLVE_USER == flags&PRT_NORESOLVE_USER { auser = strconv.Itoa(int(p.Auid)) euser = strconv.Itoa(int(p.Euid)) egroup = strconv.Itoa(int(p.Egid)) ruser = strconv.Itoa(int(p.Ruid)) rgroup = strconv.Itoa(int(p.Rgid)) } else { auser, _ = getUserName(p.Auid) euser, _ = getUserName(p.Euid) egroup, _ = getGroupName(p.Egid) ruser, _ = getUserName(p.Ruid) rgroup, _ = getGroupName(p.Rgid) } if p.Tid.IpVers == 0x04 { ip = PrintIpv4FromInt(p.Tid.Addr4) } else { ip = PrintIpv6FromInt(p.Tid.Addr6) } if flags&PRT_JSON == PRT_JSON { type ttid struct { Port uint64 `json:"port"` Addr4 string `json:"ip4,omitempty"` Addr6 string `json:"ip6,omitempty"` } tid := ttid{ Port: p.Tid.Port, } if p.Tid.IpVers == 0x04 { tid.Addr4 = ip } else { tid.Addr6 = ip } printable := struct { Auid uint32 `json:"audit_id"` // Audit ID Auser string `json:"audit_username",omitempty` Euid uint32 `json:"effective_user_id"` // Effective user ID Euser string `json:"effective_username",omitempty` Egid uint32 `json:"effective_group_id"` // Effective Group ID Egroup string `json:"effective_group",omitempty` Ruid uint32 `json:"real_user_id"` // Real User ID Ruser string `json:"real_username",omitempty` Rgid uint32 `json:"real_group_id"` // Real Group ID Rgroup string `json:"real_group",omitempty` Pid uint32 `json:"process_id"` // Process ID Sid uint32 `json:"session_id"` // Session ID Tid ttid `json:"terminal"` }{ Auid: p.Auid, Euid: p.Euid, Egid: p.Egid, Ruid: p.Ruid, Rgid: p.Rgid, Pid: p.Pid, Sid: p.Sid, Tid: tid, } if PRT_NORESOLVE_USER != flags&PRT_NORESOLVE_USER { printable.Auser = auser printable.Euser = euser printable.Egroup = egroup printable.Ruser = ruser printable.Rgroup = rgroup } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"process64\":") fmt.Fprintf(file, "%s", j) // process64 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "process_ex%s%s%s%s%s%s%s%s%s%s%s%v%s%v%s%v%s%s", delimiter, auser, delimiter, euser, delimiter, egroup, delimiter, ruser, delimiter, rgroup, delimiter, p.Pid, delimiter, p.Sid, delimiter, p.Tid.Port, delimiter, ip) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewReturn32(r Return32) *Return32 { return &Return32{ Status: r.Status, Ret: r.Ret, } } func (r *Return32) GetType() uint8 { return AUT_RETURN32 } func (r *Return32) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &r.Status) if err != nil { return fmt.Errorf("Unable to read Return32.Status: %v", err) } err = binary.Read(rdr, binary.BigEndian, &r.Ret) if err != nil { return fmt.Errorf("Unable to read Return32.Ret: %v", err) } return nil } func (r *Return32) Print(file *bufio.Writer, delimiter string, flags int) { var errMsg string errNo, err := lookupErrno(r.Status) if err == nil { errMsg = fmt.Sprintf("%s (%d)", errNo.StrError, r.Status) } else { errMsg = fmt.Sprintf("Godit error searching (%d)", r.Status) } if flags&PRT_JSON == PRT_JSON { printable := struct { Msg string `json:"error"` Code uint32 `json:"retval"` // Effective user ID }{ Msg: errMsg, Code: r.Ret, } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"return32\":") fmt.Fprintf(file, "%s", j) // return32 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "return%s%s%s%v", delimiter, errMsg, delimiter, r.Ret) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewReturn64(r Return64) *Return64 { return &Return64{ Status: r.Status, Ret: r.Ret, } } func (r *Return64) GetType() uint8 { return AUT_RETURN64 } func (r *Return64) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &r.Status) if err != nil { return fmt.Errorf("Unable to read Return64.Status: %v", err) } err = binary.Read(rdr, binary.BigEndian, &r.Ret) if err != nil { return fmt.Errorf("Unable to read Return64.Ret: %v", err) } return nil } func (r *Return64) Print(file *bufio.Writer, delimiter string, flags int) { var errMsg string errNo, err := lookupErrno(r.Status) if err == nil { errMsg = fmt.Sprintf("%s (%d)", errNo.StrError, r.Status) } else { errMsg = fmt.Sprintf("Godit error searching (%d)", r.Status) } if flags&PRT_JSON == PRT_JSON { printable := struct { Msg string `json:"message"` Code uint64 `json:"code"` // Effective user ID }{ Msg: errMsg, Code: r.Ret, } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"return64\":") fmt.Fprintf(file, "%s", j) // return64 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "return%s%v%s%v", delimiter, errMsg, delimiter, r.Ret) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewTrailer(t Trailer) *Trailer { return &Trailer{ Magic: t.Magic, Count: t.Count, } } func (t *Trailer) GetType() uint8 { return AUT_TRAILER } func (t *Trailer) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &t.Magic) if err != nil { return fmt.Errorf("Unable to read Trailer.Magic: %v", err) } err = binary.Read(rdr, binary.BigEndian, &t.Count) if err != nil { return fmt.Errorf("Unable to read Trailer.Count: %v", err) } return nil } func (t *Trailer) Print(file *bufio.Writer, delimiter string, flags int) { if flags&PRT_JSON == PRT_JSON { printable := struct { Count uint32 `json:"length"` // Effective user ID }{ Count: t.Count, } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"trailer\":") fmt.Fprintf(file, "%s", j) // trailer close the json object fmt.Fprintf(file, "}\n") } else { fmt.Fprintf(file, "trailer%s%v", delimiter, t.Count) // The trailer close the record print, whatever the oneLine flag value fmt.Fprintf(file, "\n") } } func NewArg32(a Arg32) *Arg32 { return &Arg32{ No: a.No, Val: a.Val, Length: a.Length, Text: a.Text, } } func (a *Arg32) GetType() uint8 { return AUT_ARG32 } func (a *Arg32) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &a.No) if err != nil { return fmt.Errorf("Unable to read Arg32.No: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Val) if err != nil { return fmt.Errorf("Unable to read Arg32.Val: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Length) if err != nil { return fmt.Errorf("Unable to read Arg32.Length: %v", err) } // Search for null terminating byte arg, err := rdr.ReadBytes((byte)(0x00)) if err != nil { return fmt.Errorf("Error searching for null terminated path: %v", err) } a.Text = arg[:len(arg)-1] return nil } func (a *Arg32) Print(file *bufio.Writer, delimiter string, flags int) { if flags&PRT_JSON == PRT_JSON { printable := struct { Count uint32 `json:"count"` // Effective user ID Val uint32 `json:"value"` Text string `json:"text"` }{ Count: uint32(a.No), Val: a.Val, Text: string(a.Text), } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"arg32\":") fmt.Fprintf(file, "%s", j) // Arg32 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "argument%s%v%s%v%s%s", delimiter, a.No, delimiter, a.Val, delimiter, string(a.Text)) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewArg64(a Arg64) *Arg64 { return &Arg64{ No: a.No, Val: a.Val, Length: a.Length, Text: a.Text, } } func (a *Arg64) GetType() uint8 { return AUT_ARG64 } func (a *Arg64) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &a.No) if err != nil { return fmt.Errorf("Unable to read Arg64.No: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Val) if err != nil { return fmt.Errorf("Unable to read Arg64.Val: %v", err) } err = binary.Read(rdr, binary.BigEndian, &a.Length) if err != nil { return fmt.Errorf("Unable to read Arg64.Length: %v", err) } // Search for null terminating byte arg, err := rdr.ReadBytes((byte)(0x00)) if err != nil { return fmt.Errorf("Error searching for null terminated path: %v", err) } a.Text = arg[:len(arg)-1] return nil } func (a *Arg64) Print(file *bufio.Writer, delimiter string, flags int) { if flags&PRT_JSON == PRT_JSON { printable := struct { Count uint32 `json:"count"` // Effective user ID Val uint64 `json:"value"` Text string `json:"text"` }{ Count: uint32(a.No), Val: a.Val, Text: string(a.Text), } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"arg64\":") fmt.Fprintf(file, "%s", j) // Arg64 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "argument%s%v%s%v%s%s", delimiter, a.No, delimiter, a.Val, delimiter, string(a.Text)) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewSocketEx(s SocketEx) *SocketEx { return &SocketEx{ Domain: s.Domain, SockType: s.SockType, AddrType: s.AddrType, LocalPort: s.LocalPort, LocalAddr4: s.LocalAddr4, LocalAddr6: s.LocalAddr6, RemotePort: s.RemotePort, RemoteAddr4: s.RemoteAddr4, RemoteAddr6: s.RemoteAddr6, } } func (s *SocketEx) GetType() uint8 { return AUT_SOCKET_EX } func (s *SocketEx) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &s.Domain) if err != nil { return fmt.Errorf("Unable to read SocketEx.Domain: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.SockType) if err != nil { return fmt.Errorf("Unable to read SocketEx.SockType: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.AddrType) if err != nil { return fmt.Errorf("Unable to read SocketEx.AddrType: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.LocalPort) if err != nil { return fmt.Errorf("Unable to read SocketEx.LocalPort: %v", err) } if s.AddrType == ISIPV4 { err = binary.Read(rdr, binary.BigEndian, &s.LocalAddr4) if err != nil { return fmt.Errorf("Unable to read SocketEx.LocalAddr4: %v", err) } } else if s.AddrType == ISIPV6 { err = binary.Read(rdr, binary.BigEndian, &s.LocalAddr6) if err != nil { return fmt.Errorf("Unable to read SocketEx.LocalAddr6: %v", err) } } err = binary.Read(rdr, binary.BigEndian, &s.RemotePort) if err != nil { return fmt.Errorf("Unable to read SocketEx.RemotePort: %v", err) } if s.AddrType == ISIPV4 { err = binary.Read(rdr, binary.BigEndian, &s.RemoteAddr4) if err != nil { return fmt.Errorf("Unable to read SocketEx.RemoteAddr4: %v", err) } } else if s.AddrType == ISIPV6 { err = binary.Read(rdr, binary.BigEndian, &s.RemoteAddr6) if err != nil { return fmt.Errorf("Unable to read SocketEx.RemoteAddr6: %v", err) } } else { // TODO: Invalid packet } return nil } func (s *SocketEx) Print(file *bufio.Writer, delimiter string, flags int) { var lip string var rip string if s.AddrType == ISIPV4 { lip = PrintIpv4FromInt(s.LocalAddr4) rip = PrintIpv4FromInt(s.RemoteAddr4) } else if s.AddrType == ISIPV6 { lip = PrintIpv6FromInt(s.LocalAddr6) rip = PrintIpv6FromInt(s.RemoteAddr6) } else { // TODO : Handle error } if flags&PRT_JSON == PRT_JSON { j, err := json.Marshal(s) if err != nil { // TODO return } fmt.Fprintf(file, "\"socket_ex\":") fmt.Fprintf(file, "%s", j) // SocketEx is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "socket%s%v%s%v%s%v%s%s%s%v%s%s", delimiter, s.Domain, delimiter, s.SockType, delimiter, s.LocalPort, delimiter, lip, delimiter, s.RemotePort, delimiter, rip) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewSockInet32(s SockInet32) *SockInet32 { return &SockInet32{ Family: s.Family, Port: s.Port, Addr4: s.Addr4, } } func (s *SockInet32) GetType() uint8 { return AUT_SOCKINET32 } func (s *SockInet32) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &s.Family) if err != nil { return fmt.Errorf("Unable to read SockInet32.Family: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Port) if err != nil { return fmt.Errorf("Unable to read SockInet32.Port: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Addr4) if err != nil { return fmt.Errorf("Unable to read SockInet32.Addr4: %v", err) } return nil } func (s *SockInet32) Print(file *bufio.Writer, delimiter string, flags int) { if flags&PRT_JSON == PRT_JSON { printable := struct { Family uint16 `json:"family"` Port uint16 `json:"port"` Addr4 string `json:"ip4"` }{ Family: s.Family, Port: s.Port, Addr4: PrintIpv4FromInt(s.Addr4), } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"sockinet32\":") fmt.Fprintf(file, "%s", j) // SockInet32 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "socket-inet%s%v%s%v%s%s", delimiter, s.Family, delimiter, s.Port, delimiter, PrintIpv4FromInt(s.Addr4)) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewSockInet128(s SockInet128) *SockInet128 { return &SockInet128{ Family: s.Family, Port: s.Port, Addr6: s.Addr6, } } func (s *SockInet128) GetType() uint8 { return AUT_SOCKINET128 } func (s *SockInet128) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &s.Family) if err != nil { return fmt.Errorf("Unable to read SockInet128.Family: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Port) if err != nil { return fmt.Errorf("Unable to read SockInet128.Port: %v", err) } err = binary.Read(rdr, binary.BigEndian, &s.Addr6) if err != nil { return fmt.Errorf("Unable to read SockInet128.Addr6: %v", err) } return nil } func (s *SockInet128) Print(file *bufio.Writer, delimiter string, flags int) { if flags&PRT_JSON == PRT_JSON { printable := struct { Family uint16 `json:"family"` Port uint16 `json:"port"` Addr6 string `json:"ip6"` }{ Family: s.Family, Port: s.Port, Addr6: PrintIpv6FromInt(s.Addr6), } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"sockinet128\":") fmt.Fprintf(file, "%s", j) // SockInet128 is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "socket-inet6%s%v%s%v%s%s", delimiter, s.Family, delimiter, s.Port, delimiter, PrintIpv6FromInt(s.Addr6)) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewSockUnix(s SockUnix) *SockUnix { return &SockUnix{ Family: s.Family, Path: s.Path, } } func (s *SockUnix) GetType() uint8 { return AUT_SOCKUNIX } func (s *SockUnix) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &s.Family) if err != nil { return fmt.Errorf("Unable to read SockUnix.Family: %v", err) } // Search for null terminating byte arg, err := rdr.ReadBytes((byte)(0x00)) if err != nil { return fmt.Errorf("Error searching for null terminated SockUnix.Path: %v", err) } s.Path = arg[:len(arg)-1] return nil } func (s *SockUnix) Print(file *bufio.Writer, delimiter string, flags int) { if flags&PRT_JSON == PRT_JSON { printable := struct { Family uint16 `json:"family"` Path string `json:"path"` }{ Family: s.Family, Path: string(s.Path), } j, err := json.Marshal(printable) if err != nil { // TODO return } fmt.Fprintf(file, "\"sockunix\":") fmt.Fprintf(file, "%s", j) // SockUnix is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "socket-unix%s%v%s%s", delimiter, s.Family, delimiter, string(s.Path)) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewExit(e Exit) *Exit { return &Exit{ Status: e.Status, Ret: e.Ret, } } func (e *Exit) GetType() uint8 { return AUT_EXIT } func (e *Exit) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &e.Status) if err != nil { return fmt.Errorf("Unable to read Exit.Status: %v", err) } err = binary.Read(rdr, binary.BigEndian, &e.Ret) if err != nil { return fmt.Errorf("Unable to read Exit.Ret: %v", err) } return nil } func (e *Exit) Print(file *bufio.Writer, delimiter string, flags int) { if flags&PRT_JSON == PRT_JSON { j, err := json.Marshal(e) if err != nil { // TODO return } fmt.Fprintf(file, "\"exit\":") fmt.Fprintf(file, "%s", j) // Exit is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "exit%s%v%s%v", delimiter, e.Status, delimiter, e.Ret) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewText(t Text) *Text { return &Text{ Length: t.Length, Text: t.Text, } } func (t *Text) GetType() uint8 { return AUT_TEXT } func (t *Text) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &t.Length) if err != nil { return fmt.Errorf("Unable to read Text.Length: %v", err) } text := make([]byte, t.Length) err = binary.Read(rdr, binary.BigEndian, &text) if err != nil { return fmt.Errorf("Unable to read Text.Text: %v", err) } t.Text = text[:len(text)-1] return nil } func (t *Text) Print(file *bufio.Writer, delimiter string, flags int) { if flags&PRT_JSON == PRT_JSON { j, err := json.Marshal(t) if err != nil { // TODO return } fmt.Fprintf(file, "\"text\":") fmt.Fprintf(file, "%s", j) // Text is always followed by something fmt.Fprintf(file, ",") } else { fmt.Fprintf(file, "text%s%s", delimiter, t.Text) if 0 == (flags & PRT_ONELINE) { fmt.Fprintf(file, "\n") } else { fmt.Fprintf(file, "%s", delimiter) } } } func NewZoneName(z ZoneName) *ZoneName { return &ZoneName{ Length: z.Length, Zone: z.Zone, } } func (z *ZoneName) GetType() uint8 { return AUT_ZONENAME } func (z *ZoneName) LoadFromBinary(rdr *bufio.Reader) error { err := binary.Read(rdr, binary.BigEndian, &z.Length) if err != nil { return fmt.Errorf("Unable to read ZoneName.Length: %v", err) } zone := make([]byte, z.Length) err = binary.Read(rdr, binary.BigEndian, &zone) if err != nil { return fmt.Errorf("Unable to read ZoneName.Zone: %v", err) } z.Zone = zone[:len(zone)-1] return nil } func (z *ZoneName) Print(file *bufio.Writer, delimiter string, flags int) { if flags&PRT_JSON == PRT_JSON { printable := struct { 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 { 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 *bufio.Writer, 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 func readRecordToStruct(reader *bufio.Reader) (Record, error) { var rec Record hdr := make([]byte, 1) n, err := reader.Read(hdr) if err != nil || n < 1 { if err != io.EOF { return rec, fmt.Errorf("Unable to read header ID: %v", err) } return rec, err } switch (uint8)(hdr[0]) { case AUT_HEADER32: var h Header32 err := h.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewHeader32(h), nil case AUT_EXEC_ARGS: var e ExecArg err := e.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewExecArg(e), nil case AUT_PATH: var p Path err := p.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewPath(p), nil case AUT_ATTR32: var a Attribute32 err := a.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewAttribute32(a), nil case AUT_ATTR64: var a Attribute64 err := a.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewAttribute64(a), nil case AUT_SUBJECT32: var s Subject32 err := s.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewSubject32(s), nil case AUT_SUBJECT32_EX: var s Subject32Ex err := s.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewSubject32Ex(s), nil case AUT_RETURN32: var r Return32 err := r.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewReturn32(r), nil case AUT_TRAILER: var t Trailer err := t.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewTrailer(t), nil case AUT_ARG32: var a Arg32 err := a.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewArg32(a), nil case AUT_ARG64: var a Arg64 err := a.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewArg64(a), nil case AUT_EXIT: var e Exit err := e.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewExit(e), nil case AUT_PROCESS32: var p Process32 err := p.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewProcess32(p), nil case AUT_PROCESS32_EX: var p Process32Ex err := p.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewProcess32Ex(p), nil case AUT_PROCESS64: var p Process64 err := p.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewProcess64(p), nil case AUT_PROCESS64_EX: var p Process64Ex err := p.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewProcess64Ex(p), nil case AUT_TEXT: var t Text err := t.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewText(t), nil case AUT_SOCKET_EX: var s SocketEx err := s.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewSocketEx(s), nil case AUT_SOCKINET32: var s SockInet32 err := s.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewSockInet32(s), nil case AUT_SOCKINET128: var s SockInet128 err := s.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewSockInet128(s), nil case AUT_SOCKUNIX: var s SockUnix err := s.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } return NewSockUnix(s), nil case AUT_ZONENAME: var z ZoneName err := z.LoadFromBinary(reader) if err != nil { return rec, fmt.Errorf("Unable to read: %v", err) } 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]) } /* Implementation of int au_read_rec(FILE *fp, u_char **buf) source: https://github.com/freebsd/freebsd-src/blob/main/contrib/openbsm/libbsm/bsm_io.c */ func readRecord(file *os.File) ([]byte, error) { var buf *bytes.Buffer var recSize int32 hdr := make([]byte, 1) n, err := file.Read(hdr) if err != nil || n < 1 { return hdr, fmt.Errorf("Unable to read file") } //switch hdr.(int8) { switch (int8)(hdr[0]) { case AUT_HEADER32, AUT_HEADER32_EX, AUT_HEADER64, AUT_HEADER64_EX: err := binary.Read(file, binary.BigEndian, &recSize) if err != nil { return hdr, fmt.Errorf("Unable to read file") } /* Check for recsize sanity: We already read 32 bits + 8 bits */ if recSize < (4 + 1) { return hdr, fmt.Errorf("Record size is corrupted: %d", recSize) } /* store the token contents already read, back to the buffer*/ data := make([]byte, 0) buf = bytes.NewBuffer(data) err = binary.Write(buf, binary.BigEndian, (int8)(hdr[0])) if err != nil { return hdr, fmt.Errorf("Unable to concatenate header to data") } err = binary.Write(buf, binary.BigEndian, recSize) if err != nil { return hdr, fmt.Errorf("Unable to concatenate recordsize to existing data") } /* now read remaining record bytes */ remainSize := recSize - (4 + 1) remain := make([]byte, remainSize) n, err = file.Read(remain) if err != nil || (int32)(n) < remainSize { return hdr, fmt.Errorf("Unable to read data from file") } n, err = buf.Write(remain) if err != nil { return hdr, fmt.Errorf("Unable to write data to buffer") } case AUT_OTHER_FILE32: var sec int32 var msec int32 var filenamelen int16 err := binary.Read(file, binary.BigEndian, &sec) if err != nil { return hdr, fmt.Errorf("Unable to read file") } err = binary.Read(file, binary.BigEndian, &msec) if err != nil { return hdr, fmt.Errorf("Unable to read file") } err = binary.Read(file, binary.BigEndian, &filenamelen) if err != nil { return hdr, fmt.Errorf("Unable to read file") } recSize = 1 + 4 + 4 + 2 + int32(filenamelen) data := make([]byte, 0) buf = bytes.NewBuffer(data) /* store the token contents already read, back to the buffer*/ err = binary.Write(buf, binary.BigEndian, (int8)(hdr[0])) if err != nil { return hdr, fmt.Errorf("Unable to concatenate header to data") } err = binary.Write(buf, binary.BigEndian, sec) if err != nil { return hdr, fmt.Errorf("Unable to concatenate sec to data") } err = binary.Write(buf, binary.BigEndian, msec) if err != nil { return hdr, fmt.Errorf("Unable to concatenate msec to data") } err = binary.Write(buf, binary.BigEndian, filenamelen) if err != nil { return hdr, fmt.Errorf("Unable to concatenate filenamelen to data") } filename := make([]byte, filenamelen) n, err = file.Read(filename) if err != nil || n < int(filenamelen) { return hdr, fmt.Errorf("Unable to read filename from file") } n, err = buf.Write(filename) if err != nil { return hdr, fmt.Errorf("Unable to concatenate filename to buffer") } default: return hdr, fmt.Errorf("Record type not implemented: %v", hdr) } return buf.Bytes(), nil }