aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/app/dbus.go
blob: 44a7f910dbc977846a537278203a5a03d4afce76 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package app

import (
	"errors"
	"fmt"
	"os"
	"path"
	"strconv"

	"git.ophivana.moe/cat/fortify/dbus"
	"git.ophivana.moe/cat/fortify/internal/acl"
	"git.ophivana.moe/cat/fortify/internal/state"
	"git.ophivana.moe/cat/fortify/internal/system"
	"git.ophivana.moe/cat/fortify/internal/util"
)

const (
	dbusSessionBusAddress = "DBUS_SESSION_BUS_ADDRESS"
	dbusSystemBusAddress  = "DBUS_SYSTEM_BUS_ADDRESS"
)

var (
	dbusAddress [2]string
	dbusSystem  bool
)

func (a *App) ShareDBus(dse, dsg *dbus.Config, verbose bool) {
	a.setEnablement(state.EnableDBus)

	dbusSystem = dsg != nil
	var binPath string
	var sessionBus, systemBus [2]string

	target := path.Join(system.V.Share, strconv.Itoa(os.Getpid()))
	sessionBus[1] = target + ".bus"
	systemBus[1] = target + ".system-bus"
	dbusAddress = [2]string{
		"unix:path=" + sessionBus[1],
		"unix:path=" + systemBus[1],
	}

	if b, ok := util.Which("xdg-dbus-proxy"); !ok {
		state.Fatal("D-Bus: Did not find 'xdg-dbus-proxy' in PATH")
	} else {
		binPath = b
	}

	if addr, ok := os.LookupEnv(dbusSessionBusAddress); !ok {
		if system.V.Verbose {
			fmt.Println("D-Bus: DBUS_SESSION_BUS_ADDRESS not set, assuming default format")
		}
		sessionBus[0] = fmt.Sprintf("unix:path=/run/user/%d/bus", os.Getuid())
	} else {
		sessionBus[0] = addr
	}

	if addr, ok := os.LookupEnv(dbusSystemBusAddress); !ok {
		if system.V.Verbose {
			fmt.Println("D-Bus: DBUS_SYSTEM_BUS_ADDRESS not set, assuming default format")
		}
		systemBus[0] = "unix:path=/run/dbus/system_bus_socket"
	} else {
		systemBus[0] = addr
	}

	p := dbus.New(binPath, sessionBus, systemBus)

	dse.Log = verbose
	if system.V.Verbose {
		fmt.Println("D-Bus: sealing session proxy", dse.Args(sessionBus))
	}
	if dsg != nil {
		dsg.Log = verbose
		if system.V.Verbose {
			fmt.Println("D-Bus: sealing system proxy", dsg.Args(systemBus))
		}
	}
	if err := p.Seal(dse, dsg); err != nil {
		state.Fatal("D-Bus: invalid config when sealing proxy,", err)
	}

	ready := make(chan bool, 1)
	done := make(chan struct{})

	if system.V.Verbose {
		fmt.Printf("Starting session bus proxy '%s' for address '%s'\n", dbusAddress[0], sessionBus[0])
		if dsg != nil {
			fmt.Printf("Starting system bus proxy '%s' for address '%s'\n", dbusAddress[1], systemBus[0])
		}
	}
	if err := p.Start(&ready); err != nil {
		state.Fatal("D-Bus: error starting proxy,", err)
	}
	if system.V.Verbose {
		fmt.Println("D-Bus proxy launch:", p)
	}

	go func() {
		if err := p.Wait(); err != nil {
			fmt.Println("warn: D-Bus proxy returned error,", err)
		} else {
			if system.V.Verbose {
				fmt.Println("D-Bus proxy uneventful wait")
			}
		}
		if err := os.Remove(target); err != nil && !errors.Is(err, os.ErrNotExist) {
			fmt.Println("Error removing dangling D-Bus socket:", err)
		}
		done <- struct{}{}
	}()

	// register early to enable Fatal cleanup
	state.RegisterDBus(p, &done)

	if !<-ready {
		state.Fatal("D-Bus: proxy did not start correctly")
	}

	a.AppendEnv(dbusSessionBusAddress, dbusAddress[0])
	if err := acl.UpdatePerm(sessionBus[1], a.UID(), acl.Read, acl.Write); err != nil {
		state.Fatal(fmt.Sprintf("Error preparing D-Bus session proxy '%s':", dbusAddress[0]), err)
	} else {
		state.RegisterRevertPath(sessionBus[1])
	}
	if dsg != nil {
		a.AppendEnv(dbusSystemBusAddress, dbusAddress[1])
		if err := acl.UpdatePerm(systemBus[1], a.UID(), acl.Read, acl.Write); err != nil {
			state.Fatal(fmt.Sprintf("Error preparing D-Bus system proxy '%s':", dbusAddress[1]), err)
		} else {
			state.RegisterRevertPath(systemBus[1])
		}
	}
	if system.V.Verbose {
		fmt.Printf("Session bus proxy '%s' for address '%s' configured\n", dbusAddress[0], sessionBus[0])
		if dsg != nil {
			fmt.Printf("System bus proxy '%s' for address '%s' configured\n", dbusAddress[1], systemBus[0])
		}
	}
}