123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132 |
- package authlogger
- import (
- "encoding/json"
- "errors"
- "log"
- "net/http"
- "strconv"
- "strings"
- "time"
- "imuslab.com/arozos/mod/database"
- )
- /*
- AuthLogger
- Author: tobychui
- This module help log the login request and help the user to trace who is trying
- to break into their system.
- */
- type Logger struct {
- database *database.Database
- }
- type LoginRecord struct {
- Timestamp int64
- TargetUsername string
- LoginSucceed bool
- IpAddr string
- Port int
- }
- //New Logger create a new logger object
- func NewLogger() (*Logger, error) {
- db, err := database.NewDatabase("./system/auth/authlog.db", false)
- if err != nil {
- return nil, errors.New("*ERROR* Failed to create database for login tracking")
- }
- return &Logger{
- database: db,
- }, nil
- }
- //Log the current authentication to record, Require the request object and login status
- func (l *Logger) LogAuth(r *http.Request, loginStatus bool) error {
- username, _ := mv(r, "username", true)
- timestamp := time.Now().Unix()
- //Get the current month as the table name, create table if not exists
- current := time.Now().UTC()
- tableName := current.Format("Jan-2006")
- //Create table if not exists
- l.database.NewTable(tableName)
- //Split the remote address into ipaddr and port
- remoteAddrInfo := strings.Split(r.RemoteAddr, ":")
- port := -1
- if len(remoteAddrInfo) > 1 {
- port, _ = strconv.Atoi(remoteAddrInfo[1])
- }
- //Create the entry log struct
- thisRecord := LoginRecord{
- Timestamp: timestamp,
- TargetUsername: username,
- LoginSucceed: loginStatus,
- IpAddr: remoteAddrInfo[0],
- Port: port,
- }
- //Write the log to it
- entryKey := strconv.Itoa(int(time.Now().UnixNano()))
- err := l.database.Write(tableName, entryKey, thisRecord)
- if err != nil {
- log.Println("*ERROR* Failed to write authentication log. Is the storage fulled?")
- log.Println(err.Error())
- return err
- }
- return nil
- }
- //Close the database when system shutdown
- func (l *Logger) Close() {
- l.database.Close()
- }
- //List the total number of months recorded in the database
- func (l *Logger) ListSummary() []string {
- tableNames := []string{}
- l.database.Tables.Range(func(tableName, _ interface{}) bool {
- tableNames = append(tableNames, tableName.(string))
- return true
- })
- return tableNames
- }
- func (l *Logger) ListRecords(key string) ([]LoginRecord, error) {
- results := []LoginRecord{}
- if l.database.TableExists(key) {
- //Read all record from the database to login records
- entries, err := l.database.ListTable(key)
- if err != nil {
- return results, err
- }
- for _, keypairs := range entries {
- record := LoginRecord{}
- json.Unmarshal(keypairs[1], &record)
- results = append(results, record)
- }
- return results, nil
- } else {
- return results, errors.New("Table not exists")
- }
- }
- //Extract the address information from the request object, the first one is the remote address from the last hop,
- //and the 2nd one is the source address filled in by the client (not accurate)
- func getIpAddressFromRequest(r *http.Request) (string, []string) {
- lastHopAddress := r.RemoteAddr
- possibleSourceAddress := []string{}
- rawHeader := r.Header.Get("X-Forwarded-For")
- possibleSourceAddress = strings.Split(rawHeader, ", ")
- return lastHopAddress, possibleSourceAddress
- }
|