arblant
firefox-vpn-client / core / internal / tunapi / programs.go
programs.go49 lines · 1.4 KB
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
package tunapi

import (
	"os"
	"path"
	"runtime"
	"strings"
)

// MatchProgram reports whether an executable's file name is the program a
// Program's Name stands for: the same name, without case, or a pattern
// with * (any text) and ? (one character), such as steam*.
func MatchProgram(pattern, name string) bool {
	pattern, name = strings.ToLower(pattern), strings.ToLower(name)
	if !strings.ContainsAny(pattern, "*?") {
		return pattern == name
	}
	ok, err := path.Match(pattern, name)
	return err == nil && ok
}

// SystemProgram reports whether path is one of the system's own programs:
// on Windows one in its folder (its services' svchost, for one), on Linux
// and macOS a system daemon (systemd's, the clock's, mDNSResponder). Its
// UDP is no call, and no one picks it to bypass the VPN.
func SystemProgram(path string) bool {
	switch runtime.GOOS {
	case "windows":
		root := os.Getenv("SystemRoot")
		if root == "" {
			root = `C:\Windows`
		}
		prefix := strings.TrimRight(root, `\`) + `\`
		return len(path) > len(prefix) && strings.EqualFold(path[:len(prefix)], prefix)
	case "linux":
		for _, dir := range []string{"/usr/sbin/", "/sbin/", "/usr/lib/systemd/", "/lib/systemd/", "/usr/libexec/"} {
			if strings.HasPrefix(path, dir) {
				return true
			}
		}
	case "darwin":
		for _, dir := range []string{"/System/", "/usr/sbin/", "/sbin/", "/usr/libexec/"} {
			if strings.HasPrefix(path, dir) {
				return true
			}
		}
	}
	return false
}