Skip to content

Commit

Permalink
Initial refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
nbrownus committed Mar 24, 2016
1 parent 8f82a30 commit 2bdb83b
Show file tree
Hide file tree
Showing 7 changed files with 389 additions and 375 deletions.
67 changes: 11 additions & 56 deletions audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,54 +10,10 @@ import (
"os/exec"
"runtime/pprof"
"strings"
"syscall"
"time"

"github.com/spf13/viper"
)

var count int

func ping(count *int, interval int) bool {
*count++
return (*count % interval) == 0
}

func connect() (conn *NetlinkConnection) {
conn, err := newNetlinkConnection()
if err != nil {
log.Fatal(err)
}
return

}

func startFlow(conn *NetlinkConnection) {
//this mask starts the flow
var ret []byte
a, err := newAuditStatusPayload()
a.Mask = 4
a.Enabled = 1
a.Pid = uint32(syscall.Getpid())

n := newNetlinkPacket(1001)

ret, _ = AuditRequestSerialize(n, a)
//PrettyPacketSplit(ret, []int{32, 48, 64, 96, 128, 160, 192, 224, 256, 288})

err = conn.Send(&ret)
if err != nil {
fmt.Println("something broke")
}
}

func keepFlow(conn *NetlinkConnection) {
for {
startFlow(conn)
time.Sleep(time.Second * 5)
}
}

//Helper for profiling. Don't forget to "pprof.StopCPUProfile()" at some point or the file isn't written.
func profile() {
f, err := os.Create("/tmp/profile")
Expand Down Expand Up @@ -100,24 +56,23 @@ func loadConfig() {
}

func main() {

loadConfig()

//This buffer holds partial events because they come as associated but separate lines from the kernel
eventBuffer := make(map[int]map[string]string)
//TODO: auditLogger should be configurable
auditLogger := log.New(os.Stdout, "", 0)
nlClient := NewNetlinkClient()
marshaller := NewAuditMarshaller(auditLogger)

conn := connect()
//startFlow(conn)
go keepFlow(conn)
auditLogger.Print("Starting up")

//Main loop. Get data from netlink and send it to the json lib for processing
for {
data, _ := conn.Receive()
header := readNetlinkPacketHeader(data[:16])
dstring := fmt.Sprintf("%s", data[16:])
jstring := makeJsonString(eventBuffer, header.Type, dstring)
if jstring != "" {
logLine(jstring)
msg, err := nlClient.Receive()
if err != nil {
fmt.Println("Error during message receive:", err)
continue
}

marshaller.Consume(msg)
}
}
139 changes: 139 additions & 0 deletions client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package main

import (
"syscall"
"log"
"sync/atomic"
"bytes"
"encoding/binary"
"fmt"
"time"
"errors"
)

var Endianness = binary.LittleEndian

const (
//TODO: http://lxr.free-electrons.com/source/include/uapi/linux/audit.h#L402
MAX_AUDIT_MESSAGE_LENGTH = 8970
)

//TODO: this should live in a marshaller
type AuditStatusPayload struct {
Mask uint32
Enabled uint32
Failure uint32
Pid uint32
RateLimit uint32
BacklogLimit uint32
Lost uint32
Backlog uint32
Version uint32
BacklogWaitTime uint32
}

//An alias to give the header a similar name here
type NetlinkPacket syscall.NlMsghdr

type NetlinkClient struct {
fd int
address syscall.SockaddrNetlink
seq uint32
}

func NewNetlinkClient() (*NetlinkClient) {
fd, err := syscall.Socket(syscall.AF_NETLINK, syscall.SOCK_RAW, syscall.NETLINK_AUDIT)
if err != nil {
log.Fatal("Could not create a socket:", err)
}

n := &NetlinkClient{
fd: fd,
address: syscall.SockaddrNetlink{Family: syscall.AF_NETLINK, Groups: 0, Pid: 0},
}

if err = syscall.Bind(fd, &n.address); err != nil {
syscall.Close(fd)
log.Fatal("Could not bind to netlink socket:", err)
}

go n.KeepConnection()

return n
}

func (n *NetlinkClient) Send(packet *[]byte) error {
if err := syscall.Sendto(n.fd, *packet, 0, &n.address); err != nil {
return err
}
return nil
}

func (n *NetlinkClient) Receive() (*syscall.NetlinkMessage, error) {
var raw = make([]byte, MAX_AUDIT_MESSAGE_LENGTH)
nlen, _, err := syscall.Recvfrom(n.fd, raw, 0)
if err != nil {
return nil, err
}

if nlen < 1 {
return nil, errors.New("Got a 0 length packet")
}

buf := bytes.NewReader(raw[:nlen])

msg := syscall.NetlinkMessage{
Data: raw[syscall.SizeofNlMsghdr:nlen],
}

//TODO: handle internal messages, maybe use a channel as well
binary.Read(buf, Endianness, &msg.Header)
return &msg, nil
}

func (n *NetlinkClient) KeepConnection() {
for {
var ret []byte

payload := &AuditStatusPayload{
Mask: 4,
Enabled: 1,
Pid: uint32(syscall.Getpid()),
//TODO: Failure: http://lxr.free-electrons.com/source/include/uapi/linux/audit.h#L338
}

packet := &NetlinkPacket{
Type: uint16(1001),
Flags: syscall.NLM_F_REQUEST | syscall.NLM_F_ACK,
Seq: atomic.AddUint32(&n.seq, 1),
Pid: uint32(syscall.Getpid()),
}

ret, _ = AuditRequestSerialize(packet, payload)

err := n.Send(&ret)
if err != nil {
fmt.Println("Error occurred while trying to keep the connection:", err)
}

time.Sleep(time.Second * 5)
}
}

func AuditRequestSerialize(n *NetlinkPacket, a *AuditStatusPayload) (data []byte, err error) {
//We need to get the length first. This is a bit wasteful, but requests are rare so yolo..
buf := new(bytes.Buffer)
var length int
for {
buf.Reset()
binary.Write(buf, Endianness, n)
binary.Write(buf, Endianness, a)
if n.Len == 0 {
length = len(buf.Bytes())
n.Len = uint32(length)
} else {
break
}
}
return buf.Bytes(), err
}
155 changes: 0 additions & 155 deletions json_parser.go

This file was deleted.

Loading

0 comments on commit 2bdb83b

Please sign in to comment.