goutmp

package module
v0.5.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 29, 2024 License: MIT Imports: 6 Imported by: 1

README

goutmp

This is a golang client module which support utmpx API: which includes utmpx and wtmp. The new API is inspired by libutempter. Currenly, The implementation is a golang wrapper for utmpx C library. On alpine linux (musl based) it will call utmps through utmpx API. On other linux (glibc based) it will call glibc utmpx API.

To use goutmp module in your golang development, you need to provide additional build tags.

go build -tags utmps . # for alpine linux
go build -tags utmp .  # for glibc based linux

API

// called when user login, adds a login utmp/wtmp record to database with the specified
// pseudo-terminal device name, user name, host name and process PID.
// this fuction will update both utmp and wtmp within one call
func AddRecord(ptsName string, user string, host string, pid int) bool {

// called when user logout, marks a login session as being closed with the specified
// pseudo-terminal device name, process PID.
// this fuction will update both utmp and wtmp within one call
func RemoveRecord(ptsName string, pid int) bool {

// read the next utmpx record from utmp database
func GetRecord() *Utmpx

// Add a record to last log, with the specified login line, username and
// originating host/IP.
func AddLastLog(line, userName, host string) bool {

prepare the utmps environment

Refer to alpine container with openrc support to build the docker image, run the following command to start container.

% docker run --env TZ=Asia/Shanghai --tty --privileged --volume /sys/fs/cgroup:/sys/fs/cgroup:ro \
  -h openrc-ssh --name openrc-ssh -d -p 5022:22 openrc-ssh:0.1.0

Install go SDK and utmps-dev package to prepare build dependencies. Note, the following command require root privilege.

# apk add go utmps-dev

Run setup-utmp script to setup utmps services for the container. Note, this command require root privilege.

# setup-utmp

Restart the container. Run the following command to make sure everything works. pstree command shows that 3 utmps related service is ready for us. who and last command shows the correct result from utmps service.

openrc-ssh:~# pstree -p
init(1)-+-s6-ipcserverd(154)
        |-s6-ipcserverd(217)
        |-s6-ipcserverd(245)
        `-sshd(190)---sshd(286)---ash(288)---pstree(292)
openrc-ssh:~# who
root            pts/1           00:00   May 29 22:48:09  172.17.0.1
openrc-ssh:~# last
USER       TTY            HOST               LOGIN        TIME
root       pts/1          172.17.0.1         May 29 22:48

build and run goutmp application.

Now, it's time to build your application and run it according to the following section.

Add user ide into utmp group. This is required by utmps. Note, this command require root privilege.

openrc-ssh:~# adduser ide utmp

Set GID for the application. Note, local mounted file system in docker (such as the ~/develop directory) doesn't support set GID appplication. That is why we move it to the /tmp directory.

openrc-ssh:~/develop/goutmp$ cd goutmp
openrc-ssh:~/develop/goutmp$ go build -tags utmps main/test_linux.go
openrc-ssh:~/develop/goutmp$ ls -al
total 2116
drwxr-xr-x   11 ide      develop        352 May 29 22:50 .
drwxr-xr-x   24 ide      develop        768 May 24 07:00 ..
drwxr-xr-x   16 ide      develop        512 May 29 21:59 .git
-rw-r--r--    1 ide      develop        515 May 28 19:16 .gitignore
-rw-r--r--    1 ide      develop       1063 May 21 14:31 LICENSE
-rw-r--r--    1 ide      develop       4651 May 29 22:49 README.md
-rw-r--r--    1 ide      develop         41 May 21 14:34 go.mod
-rw-r--r--    1 ide      develop       4120 May 28 19:13 goutmp_linux.go
drwxr-xr-x    3 ide      develop         96 May 28 20:11 main
-rwxr-xr-x    1 ide      develop    2137992 May 29 22:50 test_linux
drwxr-xr-x    6 ide      develop        192 May 28 19:13 xutmp
openrc-ssh:~/develop/goutmp$ cp test_linux  /tmp/
openrc-ssh:~/develop/goutmp$ cd /tmp
openrc-ssh:/tmp$ chgrp utmp test_linux
openrc-ssh:/tmp$ chmod g+s test_linux
openrc-ssh:/tmp$ ls -al
total 2096
drwxrwxrwt    1 root     root          4096 May 29 22:50 .
drwxr-xr-x    1 root     root          4096 May 29 22:41 ..
-rwxr-sr-x    1 ide      utmp       2137992 May 29 22:50 test_linux
openrc-ssh:/tmp$ ./test_linux

how to set effective GID for your service

You has a service and want that service has the privileges to access utmps service. Then you need to set the effective GID for your service to be utmp. The utmps service require effective GID of utmp. Refer to The utmps-utmpd program for detail.

Let's say your service program is prog2. You need set GID for prog2. Let's assume that user ide belongs to two groups: develop and utmp. You can use $ adduser ide utmp command to achive it.

  • first, change the group of prog2 to utmp.
  • second, set-GID for prog2.
  • finally, if you run the prog2 program, it's effective GID will be utmp.
openrc-ssh:/tmp$ ls -al
total 2096
drwxrwxrwt    1 root     root          4096 May 27 20:38 .
drwxr-xr-x    1 root     root          4096 May 27 18:12 ..
-rwxr-xr-x    1 ide      develop    2137512 May 27 20:38 prog2
openrc-ssh:/tmp$ chgrp utmp prog2
openrc-ssh:/tmp$ ls -al
total 2096
drwxrwxrwt    1 root     root          4096 May 27 20:38 .
drwxr-xr-x    1 root     root          4096 May 27 18:12 ..
-rwxr-xr-x    1 ide      utmp       2137512 May 27 20:38 prog2
openrc-ssh:/tmp$ chmod g+s prog2
openrc-ssh:/tmp$ ls -al
total 2096
drwxrwxrwt    1 root     root          4096 May 27 20:38 .
drwxr-xr-x    1 root     root          4096 May 27 18:12 ..
-rwxr-sr-x    1 ide      utmp       2137512 May 27 20:38 prog2

Please refer to s6-setuidgid to accomplish the above work in a single command. Note: in docker environment, mounted local file system does not support set UID/GID operation.

difference with original goutmp

After search the internet, I found RLabs/goutmp and decide to use it to access utmp and wutmp database. As I learn more about utmp/utmpx API and RLabs/goutmp. I found it's time to create an alternative go module.

There are several differences between ericwq/goutmp and RLabs/goutmp. ericwq/goutmp refer to libutempter and the example from The linux programming interface (P829).

  • ericwq/goutmp support utmpx API, while RLabs/goutmp support utmp API.
  • ericwq/goutmp update wtmp when update utmp record. This behavior is more reasonable.
  • ericwq/goutmp support tty and pts device, while RLabs/goutmp only support pts device.

inline C or stand alone C module

We use the following cgo derective and inline C functions to implement the wrapper. Inline C functions is more easy to build than stand alone C module.

// #cgo pkg-config: utmps skalibs

Please use the following commands to build the stand alone C module, either staticly or dynamicly.

$ cd ./xutmp/
$ gcc -I/usr/include/utmps -lutmps -lskarnet -c -o xutmp.o xutmp.c
$ ar rcs libxutmp.a xutmp.o
$ gcc -shared -I/usr/include/utmps -lutmps -lskarnet -o libxutmp.so xutmp.c

The following cgo derective is for stand alone C module.

/*
#cgo CFLAGS: -I./xutmp
#cgo LDFLAGS: -L${SRCDIR}/xutmp -lxutmp

#include "xutmp.h"
*/

license

It's MIT license, please see the LICENSE file.

Documentation

Index

Constants

View Source
const (
	EMPTY         = 0x0
	BOOT_TIME     = 0x2
	OLD_TIME      = 0x4
	NEW_TIME      = 0x3
	USER_PROCESS  = 0x7
	INIT_PROCESS  = 0x5
	LOGIN_PROCESS = 0x6
	DEAD_PROCESS  = 0x8

	UTMPS_UT_LINESIZE = 0x20
	UTMPS_UT_NAMESIZE = 0x20
	UTMPS_UT_HOSTSIZE = 0x100
	UTMPS_UT_IDSIZE   = 0x4
)

Variables

This section is empty.

Functions

func DeviceExists added in v0.4.2

func DeviceExists(line string) bool

check whether device exist, the line parameter should be form of "pts/0" or "ttys001"

func HasUtmpSupport added in v0.4.1

func HasUtmpSupport() bool

return true if we can read from the utmp data file

Types

type ExitStatus added in v0.2.0

type ExitStatus struct {
	Termination int16
	Exit        int16
}

type TimeVal added in v0.2.0

type TimeVal struct {
	Sec  int64
	Usec int64
}

type Utmpx added in v0.2.0

type Utmpx struct {
	Type      int16
	Pid       int32
	Line      [32]int8
	Id        [4]int8
	User      [32]int8
	Host      [256]int8
	Exit      ExitStatus
	Session   int32
	Tv        TimeVal
	Addr_v6   [4]uint32
	X_dummy   [20]int8
	Pad_cgo_0 [4]byte
}

func (*Utmpx) GetHost added in v0.2.0

func (u *Utmpx) GetHost() string

func (*Utmpx) GetId added in v0.2.0

func (u *Utmpx) GetId() int

func (*Utmpx) GetLine added in v0.2.0

func (u *Utmpx) GetLine() string

func (*Utmpx) GetPid added in v0.2.0

func (u *Utmpx) GetPid() int

func (*Utmpx) GetTime added in v0.2.0

func (u *Utmpx) GetTime() time.Time

func (*Utmpx) GetType added in v0.2.0

func (u *Utmpx) GetType() int

func (*Utmpx) GetUser added in v0.2.0

func (u *Utmpx) GetUser() string

func (*Utmpx) SetHost added in v0.4.5

func (u *Utmpx) SetHost(s string)

func (*Utmpx) SetId added in v0.4.5

func (u *Utmpx) SetId(id int)

func (*Utmpx) SetLine added in v0.4.5

func (u *Utmpx) SetLine(s string)

func (*Utmpx) SetPid added in v0.4.5

func (u *Utmpx) SetPid(pid int)

func (*Utmpx) SetTime added in v0.5.0

func (u *Utmpx) SetTime(t time.Time)

func (*Utmpx) SetType added in v0.4.5

func (u *Utmpx) SetType(t int)

func (*Utmpx) SetUser added in v0.4.5

func (u *Utmpx) SetUser(s string)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL