authpixious/main.go

130 lines
2.5 KiB
Go
Raw Normal View History

2015-08-11 19:03:37 -07:00
package main
import (
"bufio"
"flag"
"fmt"
"os"
"regexp"
"sort"
"strconv"
)
var max = flag.Int64("max", 5, "limit output, if negative print all")
func main() {
flag.Parse()
// Failed password for root from 43.229.53.57 port 62954 ssh2
// message repeated 2 times: [ Failed password for root from 43.229.53.57 port 32871 ssh2]
p, err := regexp.Compile(`(message repeated (\d+) times: \[)? Failed password for (invalid user )?(.*?) from (.*) port`)
if err != nil {
fail("failed to compile regex", err)
}
unames := counter{}
ips := counter{}
s := bufio.NewScanner(os.Stdin)
for s.Scan() {
if m := p.FindSubmatch(s.Bytes()); m == nil {
continue
} else {
if len(m) != 6 {
fail("failure to capture correct number of tokens", nil)
}
multstr := string(m[2])
uname, ip := m[4], m[5]
multiplier := 1
if multstr != "" {
i, err := strconv.Atoi(multstr)
if err != nil {
fail("problem parsing int", err)
}
multiplier = i
}
unames[string(uname)] += multiplier
ips[string(ip)] += multiplier
}
}
if err := s.Err(); err != nil {
fail("failure reading from stdin", err)
}
display(unames, ips)
}
// fail constructs an error message, sends to stderr, and exists 1
func fail(msg string, err error) {
fmt.Fprintf(os.Stderr, "%s; %v\n", msg, err)
os.Exit(1)
}
type counter map[string]int
// top sorts the map by value and returns max pairs, unless max is negative in
// which case it returns all pairs
func top(m counter, max int64) pairList {
p := make(pairList, len(m))
i := 0
for k, v := range m {
p[i] = pair{k, v}
i++
}
sort.Sort(p)
if max < 0 {
return p
}
if int64(len(p)) > max {
p = p[:max]
}
return p
}
// How I sort a counter by value
type pair struct {
key string
value int
}
type pairList []pair
func (p pairList) Swap(i, j int) {
p[i], p[j] = p[j], p[i]
}
func (p pairList) Len() int {
return len(p)
}
// Less sorts in descending order
func (p pairList) Less(i, j int) bool {
return p[i].value > p[j].value
}
func display(unames, ips map[string]int) {
var title string
title = fmt.Sprintf("%-20s %s", "unames", "count")
fmt.Printf("%s\n", title)
for _ = range title {
fmt.Print("-")
}
fmt.Println()
for _, v := range top(unames, *max) {
fmt.Printf("%-20s %d\n", v.key, v.value)
}
title = fmt.Sprintf("%-20s %s", "ips", "count")
fmt.Printf("\n%s\n", title)
for _ = range title {
fmt.Print("-")
}
fmt.Println()
for _, v := range top(ips, *max) {
fmt.Printf("%-20s %d\n", v.key, v.value)
}
}