carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1//go:build linux
2
3package instancectl
4
5import (
6 "fmt"
7 "net"
8 "os"
9 "strconv"
10 "strings"
11)
12
13type AuthenticatedPeer struct {
14 UID uint32
15 PID int
16 ProcessStart, BootID, ControllerID string
17}
18
19func procStart(pid int) (string, error) {
20 b, err := os.ReadFile(fmt.Sprintf("/proc/%d/stat", pid))
21 if err != nil {
22 return "", err
23 }
24 i := strings.LastIndexByte(string(b), ')')
25 if i < 0 {
26 return "", fmt.Errorf("malformed proc stat")
27 }
28 f := strings.Fields(string(b[i+1:]))
29 if len(f) <= 19 {
30 return "", fmt.Errorf("malformed proc stat")
31 }
32 if _, err := strconv.ParseUint(f[19], 10, 64); err != nil {
33 return "", err
34 }
35 return f[19], nil
36}
37
38// AuthenticatePeerTuple binds the accepted Unix peer to kernel identity and
39// rereads starttime to reject PID reuse during collection.
40func AuthenticatePeerTuple(conn net.Conn, expectedUID uint32, expectedPID int, controllerID string) (AuthenticatedPeer, error) {
41 if conn == nil || expectedPID <= 0 || controllerID == "" {
42 return AuthenticatedPeer{}, fmt.Errorf("invalid peer expectation")
43 }
44 u, err := peerCred(conn)
45 if err != nil {
46 return AuthenticatedPeer{}, err
47 }
48 if u.Uid != expectedUID || int(u.Pid) != expectedPID {
49 return AuthenticatedPeer{}, fmt.Errorf("peer identity mismatch")
50 }
51 start, err := procStart(expectedPID)
52 if err != nil {
53 return AuthenticatedPeer{}, err
54 }
55 boot, err := os.ReadFile("/proc/sys/kernel/random/boot_id")
56 if err != nil {
57 return AuthenticatedPeer{}, err
58 }
59 start2, err := procStart(expectedPID)
60 if err != nil || start2 != start {
61 return AuthenticatedPeer{}, fmt.Errorf("peer process changed during authentication")
62 }
63 return AuthenticatedPeer{UID: u.Uid, PID: int(u.Pid), ProcessStart: start, BootID: strings.TrimSpace(string(boot)), ControllerID: controllerID}, nil
64}
65