From c076bc0153e2d539710f839ae9dca98dcd04f795 Mon Sep 17 00:00:00 2001 From: Russ Magee Date: Sun, 26 Apr 2020 00:50:02 +0000 Subject: [PATCH] FreeBSD 12 support --- goutmp_bsd.go | 135 ++++++++++++++++++++++++++++++++ goutmp.go => goutmp_linux.go | 1 + main/test_bsd.go | 17 ++++ main/{test.go => test_linux.go} | 1 + 4 files changed, 154 insertions(+) create mode 100644 goutmp_bsd.go rename goutmp.go => goutmp_linux.go (99%) create mode 100644 main/test_bsd.go rename main/{test.go => test_linux.go} (94%) diff --git a/goutmp_bsd.go b/goutmp_bsd.go new file mode 100644 index 0000000..9523354 --- /dev/null +++ b/goutmp_bsd.go @@ -0,0 +1,135 @@ +// +build bsd +// Golang bindings for basic login/utmp accounting +package goutmp + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +// +//#include +// +//typedef char char_t; +// +//void pututmpx(struct utmpx* entry, char* uname, char* ptsname, char* host) { +// entry->ut_type = USER_PROCESS; +// entry->ut_pid = getpid(); +// strcpy(entry->ut_line, ptsname + strlen("/dev/")); +// +// strcpy(entry->ut_id, ptsname + strlen("/dev/pts/")); +// +// //entry->ut_time = time(NULL); +// strcpy(entry->ut_user, uname); +// strcpy(entry->ut_host, host); +// //entry->ut_addr = 0; +// setutxent(); +// pututxline(entry); +//} +// +//void unpututmpx(struct utmpx* entry) { +// entry->ut_type = DEAD_PROCESS; +// entry->ut_line[0] = '\0'; +// //entry->ut_time = 0; +// entry->ut_user[0] = '\0'; +// setutxent(); +// pututxline(entry); +// +// endutxent(); +//} +// +//#if 0 +//int putlastlogentry(int64_t t, int uid, char* line, char* host) { +// int retval = 0; +// FILE *f; +// struct lastlog l; +// +// strncpy(l.ll_line, line, UT_LINESIZE); +// l.ll_line[UT_LINESIZE-1] = '\0'; +// strncpy(l.ll_host, host, UT_HOSTSIZE); +// l.ll_host[UT_HOSTSIZE-1] = '\0'; +// +// l.ll_time = (time_t)t; +// //printf("l: ll_line '%s', ll_host '%s', ll_time %d\n", l.ll_line, l.ll_host, l.ll_time); +// +// /* Write lastlog entry at fixed offset (uid * sizeof(struct lastlog) */ +// if( NULL != (f = fopen("/var/log/lastlog", "rw+")) ) { +// if( !fseek(f, (uid * sizeof(struct lastlog)), SEEK_SET) ) { +// int fd = fileno(f); +// if( write(fd, &l, sizeof(l)) == sizeof(l) ) { +// retval = 1; +// //int32_t stat = system("echo ---- lastlog ----; lastlog"); +// } +// } +// fclose(f); +// } +// return retval; +//} +//#else +//int putlastlogentry(int64_t t, int uid, char* line, char* host) { +// return 0; +//} +//#endif +import "C" + +import ( + "fmt" + "net" + "os/user" + "strings" + "time" +) + +// UtmpEntry wraps the C struct utmp +type UtmpEntry struct { + entry C.struct_utmpx +} + +// return remote client hostname or IP if host lookup fails +// addr is expected to be of the format given by net.Addr.String() +// eg., "127.0.0.1:80" or "[::1]:80" +func GetHost(addr string) (h string) { + if !strings.Contains(addr, "[") { + h = strings.Split(addr, ":")[0] + } else { + h = strings.Split(strings.Split(addr, "[")[1], "]")[0] + } + hList, e := net.LookupAddr(h) + //fmt.Printf("lookupAddr:%v\n", hList) + if e == nil { + h = hList[0] + } + return +} + +// Put a username and the originating host/IP to utmp +func Put_utmp(user, ptsName, host string) UtmpEntry { + var entry UtmpEntry + + //log.Println("Put_utmp:host ", host, " user ", user) + C.pututmpx(&entry.entry, C.CString(user), C.CString(ptsName), C.CString(host)) + return entry +} + +// Remove a username/host entry from utmp +func Unput_utmp(entry UtmpEntry) { + C.unpututmpx(&entry.entry) +} + +// Put the login app, username and originating host/IP to lastlog +func Put_lastlog_entry(app, usr, ptsname, host string) { + u, e := user.Lookup(usr) + if e != nil { + return + } + var uid uint32 + fmt.Sscanf(u.Uid, "%d", &uid) + + t := time.Now().Unix() + _ = C.putlastlogentry(C.int64_t(t), C.int(uid), C.CString(app), C.CString(host)) + //stat := C.putlastlogentry(C.int64_t(t), C.int(uid), C.CString(app), C.CString(host)) + //fmt.Println("stat was:",stat) +} diff --git a/goutmp.go b/goutmp_linux.go similarity index 99% rename from goutmp.go rename to goutmp_linux.go index 2d7721b..7282f3f 100644 --- a/goutmp.go +++ b/goutmp_linux.go @@ -1,3 +1,4 @@ +// +build linux // Golang bindings for basic login/utmp accounting package goutmp diff --git a/main/test_bsd.go b/main/test_bsd.go new file mode 100644 index 0000000..bc41eb9 --- /dev/null +++ b/main/test_bsd.go @@ -0,0 +1,17 @@ +// +build bsd +package main + +import ( + "time" + + "blitter.com/go/goutmp" +) + +func main() { + user := "bin" + host := "test.example.com" + utmp := goutmp.Put_utmp(user, "/dev/pts0", host) + goutmp.Put_lastlog_entry("hkexsh", user, "/dev/pts0", host) + time.Sleep(10 * time.Second) + goutmp.Unput_utmp(utmp) +} diff --git a/main/test.go b/main/test_linux.go similarity index 94% rename from main/test.go rename to main/test_linux.go index 6b67001..c53b928 100644 --- a/main/test.go +++ b/main/test_linux.go @@ -1,3 +1,4 @@ +// +build linux package main import (