Implemented the dhcpd lease entry decoder and the address decoder for the vmware builder.

This commit is contained in:
Ali Rizvi-Santiago 2020-05-27 21:35:24 -05:00
parent efb775accb
commit e2a7c317eb
2 changed files with 168 additions and 0 deletions

View File

@ -1,15 +1,19 @@
package common package common
import ( import (
"bytes"
"encoding/hex"
"fmt" "fmt"
"log" "log"
"math" "math"
"net" "net"
"os" "os"
"reflect" "reflect"
"regexp"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"time"
) )
/** low-level parsing */ /** low-level parsing */
@ -2233,3 +2237,119 @@ func consumeOpenClosePair(openByte, closeByte byte, in chan byte) ([]byte, chan
// the openByte and closeByte pair. // the openByte and closeByte pair.
return result, out return result, out
} }
// Basic decoding of a dhcpd lease address
func decodeDhcpdLeaseBytes(input string) ([]byte, error) {
processed := &bytes.Buffer{}
// Split the string into pieces as we'll need to validate it.
for _, item := range strings.Split(input, ":") {
if len(item) != 2 {
return []byte{}, fmt.Errorf("bytes are not well-formed (%v)", input)
}
processed.WriteString(item)
}
length := hex.DecodedLen(processed.Len())
// Decode the processed data into the result...
result := make([]byte, length)
if n, err := hex.Decode(result, processed.Bytes()); err != nil {
return []byte{}, err
// Check that our decode length corresponds to what was intended
} else if n != length {
return []byte{}, fmt.Errorf("expected to decode %d bytes, got %d instead", length, n)
}
// ...and then return it.
return result, nil
}
/*** Dhcp Leases */
type dhcpLeaseEntry struct {
address string
starts, ends time.Time
ether, uid []byte
extra []string
}
func readDhcpdLeaseEntry(in chan byte) (entry *dhcpLeaseEntry) {
// Build the regexes we'll use to legitimately parse each item
ipLineRe := regexp.MustCompile(`^lease (.+?) {$`)
startTimeLineRe := regexp.MustCompile(`^\s*starts \d (.+?);$`)
endTimeLineRe := regexp.MustCompile(`^\s*ends \d (.+?);$`)
macLineRe := regexp.MustCompile(`^\s*hardware ethernet (.+?);$`)
uidLineRe := regexp.MustCompile(`^\s*uid (.+?);$`)
/// Read up to the lease item and validate that it actually matches
lease, ch := consumeOpenClosePair('{', '}', in)
matches := ipLineRe.FindStringSubmatch(string(lease))
if matches == nil {
return nil
}
// If we found a lease match and we're definitely beginning a lease
// entry, then create our storage.
if by, ok := <-ch; ok && by == '{' {
entry = &dhcpLeaseEntry{address: matches[1]}
// Otherwise we bail.
} else {
return nil
}
/// Now we can parse the inside of the block.
for insideBraces := true; insideBraces; {
item, ok := consumeUntilSentinel(';', in)
item_s := string(item)
if !ok {
insideBraces = false
}
// Parse out the start time
matches = startTimeLineRe.FindStringSubmatch(item_s)
if matches != nil {
entry.starts, _ = time.Parse("2006/01/02 15:04:05", matches[1])
continue
}
// Parse out the end time
matches = endTimeLineRe.FindStringSubmatch(item_s)
if matches != nil {
entry.ends, _ = time.Parse("2006/01/02 15:04:05", matches[1])
continue
}
// Parse out the hardware ethernet
matches = macLineRe.FindStringSubmatch(item_s)
if matches != nil {
entry.ether, _ = decodeDhcpdLeaseBytes(item_s)
continue
}
// Parse out the uid
matches = uidLineRe.FindStringSubmatch(item_s)
if matches != nil {
entry.uid, _ = decodeDhcpdLeaseBytes(item_s)
continue
}
// Just stash it for now because we have no idea what it is.
entry.extra = append(entry.extra, strings.TrimSpace(item_s))
}
return entry
}
func ReadDhcpdLeases(fd *os.File) ([]dhcpLeaseEntry, error) {
fch := consumeFile(fd)
uncommentedch := uncomment(fch)
wch := filterOutCharacters([]byte{'\n', '\r', '\v'}, uncommentedch)
close(wch)
return []dhcpLeaseEntry{}, fmt.Errorf("Not implemented yet!")
}

View File

@ -634,3 +634,51 @@ func TestParserCombinators(t *testing.T) {
} }
} }
} }
func TestParserDhcpdLeaseBytesDecoder(t *testing.T) {
test_1 := "00:0d:0e:0a:0d:00"
expected_1 := []byte{0, 13, 14, 10, 13, 0}
result, err := decodeDhcpdLeaseBytes(test_1)
if err != nil {
t.Errorf("unable to decode address: %s", err)
}
if bytes.Compare(result, expected_1) != 0 {
t.Errorf("expected %v, got %v", expected_1, result)
}
test_2 := "11"
expected_2 := []byte{17}
result, err = decodeDhcpdLeaseBytes(test_2)
if err != nil {
t.Errorf("unable to decode address: %s", err)
}
if bytes.Compare(result, expected_2) != 0 {
t.Errorf("expected %v, got %v", expected_2, result)
}
failtest_1 := ""
result, err = decodeDhcpdLeaseBytes(failtest_1)
if err == nil {
t.Errorf("expected decoding error: %s", err)
}
failtest_2 := "000000"
result, err = decodeDhcpdLeaseBytes(failtest_2)
if err == nil {
t.Errorf("expected decoding error: %s", err)
}
failtest_3 := "000:00"
result, err = decodeDhcpdLeaseBytes(failtest_3)
if err == nil {
t.Errorf("expected decoding error: %s", err)
}
failtest_4 := "00:00:"
result, err = decodeDhcpdLeaseBytes(failtest_4)
if err == nil {
t.Errorf("expected decoding error: %s", err)
}
}