github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbnm/installer/installer.go (about) 1 package installer 2 3 import ( 4 "os" 5 "path/filepath" 6 "strings" 7 8 "github.com/keybase/client/go/kbnm/hostmanifest" 9 ) 10 11 const kbnmAppName = "io.keybase.kbnm" 12 13 // CurrentUser returns a hostmanifest.User while allowing for overrides using 14 // environment variables: 15 // * KBNM_INSTALL_ROOT != "" will force the user paths to be root 16 // * KBNM_INSTALL_OVERLAY will prefix the paths 17 func CurrentUser() (hostmanifest.User, error) { 18 u, err := hostmanifest.CurrentUser() 19 if err != nil { 20 return nil, err 21 } 22 if os.Getenv("KBNM_INSTALL_ROOT") != "" { 23 u.Admin = true 24 u.Path = "" 25 } 26 overlay := os.Getenv("KBNM_INSTALL_OVERLAY") 27 if overlay != "" { 28 u.Path = filepath.Join(overlay, u.Path) 29 } 30 return u, err 31 } 32 33 // UninstallKBNM removes NativeMessaging whitelisting for KBNM. 34 func UninstallKBNM() error { 35 u, err := CurrentUser() 36 if err != nil { 37 return err 38 } 39 40 app := hostmanifest.App{ 41 Name: kbnmAppName, 42 } 43 44 for _, whitelist := range hostmanifest.KnownInstallers() { 45 if err := whitelist.Uninstall(u, app); err != nil { 46 return err 47 } 48 } 49 50 return nil 51 } 52 53 // InstallKBNM writes NativeMessaging whitelisting for KBNM. 54 func InstallKBNM(path string) error { 55 u, err := CurrentUser() 56 if err != nil { 57 return err 58 } 59 60 // If we're installing in an overlay, we need to strip it as a prefix from 61 // the path we detect. 62 overlay := os.Getenv("KBNM_INSTALL_OVERLAY") 63 if overlay != "" { 64 // This is a bit arcane because filepath.HasPrefix deprecated due to 65 // being broken, but what it does is it attempts to map path as 66 // relative to overlay. If it succeeds and they're both absolute paths 67 // (which means the relative path won't start with "../"), then make 68 // path an absolute path with the overlay removed 69 // filepath.Rel takes care of normalizing paths which is an advantage 70 // over direct string comparisons which would be simpler. 71 rel, err := filepath.Rel(overlay, path) 72 if err == nil && !strings.HasPrefix(rel, ".") { 73 path = "/" + rel 74 } 75 } 76 77 app := hostmanifest.App{ 78 Name: kbnmAppName, 79 Description: "Keybase Native Messaging API", 80 Path: path, 81 Type: "stdio", 82 } 83 84 var manifest hostmanifest.AppManifest 85 for browser, whitelist := range hostmanifest.KnownInstallers() { 86 switch browser { 87 case "chrome", "chromium": 88 manifest = hostmanifest.ChromeApp{ 89 App: app, 90 AllowedOrigins: []string{ 91 // Production public version in the store 92 "chrome-extension://ognfafcpbkogffpmmdglhbjboeojlefj/", 93 // Hard-coded key from the repo version 94 "chrome-extension://kockbbfoibcdfibclaojljblnhpnjndg/", 95 // Keybase-internal version 96 "chrome-extension://gnjkbjlgkpiaehpibpdefaieklbfljjm/", 97 }, 98 } 99 case "firefox": 100 manifest = hostmanifest.FirefoxApp{ 101 App: app, 102 AllowedExtensions: []string{ 103 "keybase@keybase.io", 104 }, 105 } 106 } 107 108 if err := whitelist.Install(u, manifest); err != nil { 109 return err 110 } 111 } 112 return nil 113 }