From 8fc4e4ac9d1bc465f543859d4efee0d82ea77db3 Mon Sep 17 00:00:00 2001 From: MatteoPologruto Date: Thu, 4 Apr 2024 10:56:07 +0200 Subject: [PATCH 1/4] Add function to uninstall certificate from the system keychain --- certificates/install_darwin.go | 42 +++++++++++++++++++++++++++++++++ certificates/install_default.go | 6 +++++ 2 files changed, 48 insertions(+) diff --git a/certificates/install_darwin.go b/certificates/install_darwin.go index 134a4bc0c..d2e82cc5c 100644 --- a/certificates/install_darwin.go +++ b/certificates/install_darwin.go @@ -18,7 +18,9 @@ package certificates //inspired by https://stackoverflow.com/questions/12798950/ios-install-ssl-certificate-programmatically /* +// Explicitly tell the GCC compiler that the language is Objective-C. #cgo CFLAGS: -x objective-c +// Pass the list of macOS frameworks needed by this piece of Objective-C code. #cgo LDFLAGS: -framework Cocoa #import @@ -61,6 +63,32 @@ const char *installCert(const char *path) { return ""; } +const char *uninstallCert() { + // Each line is a key-value of the dictionary. Note: the the inverted order, value first then key. + NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: + (id)kSecClassCertificate, kSecClass, + CFSTR("Arduino"), kSecAttrLabel, + kSecMatchLimitOne, kSecMatchLimit, + kCFBooleanTrue, kSecReturnAttributes, + nil]; + + OSStatus err = noErr; + // Use this function to check for errors + err = SecItemCopyMatching((CFDictionaryRef)dict, nil); + if (err == noErr) { + err = SecItemDelete((CFDictionaryRef)dict); + if (err != noErr) { + NSString *errString = [@"Could not delete the certificates. Error: " stringByAppendingFormat:@"%d", err]; + NSLog(@"%@", errString); + return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];; + } + } else if (err != errSecItemNotFound){ + NSString *errString = [@"Error: " stringByAppendingFormat:@"%d", err]; + NSLog(@"%@", errString); + return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];; + } + return ""; +} */ import "C" import ( @@ -88,3 +116,17 @@ func InstallCertificate(cert *paths.Path) error { } return nil } + +// UninstallCertificates will uninstall the certificates from the system keychain on macos, +// if something goes wrong will show a dialog with the error and return an error +func UninstallCertificates() error { + log.Infof("Uninstalling certificates") + p := C.uninstallCert() + s := C.GoString(p) + if len(s) != 0 { + oscmd := exec.Command("osascript", "-e", "display dialog \""+s+"\" buttons \"OK\" with title \"Error uninstalling certificates\"") + _ = oscmd.Run() + return errors.New(s) + } + return nil +} diff --git a/certificates/install_default.go b/certificates/install_default.go index 2a1cf794f..1b7f24bb9 100644 --- a/certificates/install_default.go +++ b/certificates/install_default.go @@ -30,3 +30,9 @@ func InstallCertificate(cert *paths.Path) error { log.Warn("platform not supported for the certificate install") return errors.New("platform not supported for the certificate install") } + +// UninstallCertificates won't do anything on unsupported Operative Systems +func UninstallCertificates() error { + log.Warn("platform not supported for the certificates uninstall") + return errors.New("platform not supported for the certificates uninstall") +} From 6d48a90eb928520135759f1bd1d825352b41baef Mon Sep 17 00:00:00 2001 From: MatteoPologruto Date: Thu, 4 Apr 2024 11:35:15 +0200 Subject: [PATCH 2/4] Remove certificates from the keychain using the systray icon --- systray/systray_real.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/systray/systray_real.go b/systray/systray_real.go index 9e4e5aac1..62e52e21d 100644 --- a/systray/systray_real.go +++ b/systray/systray_real.go @@ -64,12 +64,15 @@ func (s *Systray) start() { s.updateMenuItem(mRmCrashes, config.LogsIsEmpty()) mGenCerts := systray.AddMenuItem("Generate and Install HTTPS certificates", "HTTPS Certs") + mRemoveCerts := systray.AddMenuItem("Remove HTTPS certificates", "") // On linux/windows chrome/firefox/edge(chromium) the agent works without problems on plain HTTP, // so we disable the menuItem to generate/install the certificates if runtime.GOOS != "darwin" { s.updateMenuItem(mGenCerts, true) + s.updateMenuItem(mRemoveCerts, true) } else { s.updateMenuItem(mGenCerts, config.CertsExist()) + s.updateMenuItem(mRemoveCerts, !config.CertsExist()) } // Add pause/quit @@ -103,6 +106,15 @@ func (s *Systray) start() { cert.DeleteCertificates(certDir) } s.Restart() + case <-mRemoveCerts.ClickedCh: + err := cert.UninstallCertificates() + if err != nil { + log.Errorf("cannot uninstall certificates something went wrong: %s", err) + } else { + certDir := config.GetCertificatesDir() + cert.DeleteCertificates(certDir) + } + s.Restart() case <-mPause.ClickedCh: s.Pause() case <-mQuit.ClickedCh: From 0a97918e92ba14eeb0d9c920dfbc642d889f34ef Mon Sep 17 00:00:00 2001 From: MatteoPologruto Date: Wed, 10 Apr 2024 17:26:42 +0200 Subject: [PATCH 3/4] Improve error messages when installing and uninstalling certificates --- certificates/install_darwin.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/certificates/install_darwin.go b/certificates/install_darwin.go index d2e82cc5c..fc973d33c 100644 --- a/certificates/install_darwin.go +++ b/certificates/install_darwin.go @@ -110,7 +110,7 @@ func InstallCertificate(cert *paths.Path) error { p := C.installCert(ccert) s := C.GoString(p) if len(s) != 0 { - oscmd := exec.Command("osascript", "-e", "display dialog \""+s+"\" buttons \"OK\" with title \"Error installing certificates\"") + oscmd := exec.Command("osascript", "-e", "display dialog \""+s+"\" buttons \"OK\" with title \"Arduino Agent: Error installing certificates\"") _ = oscmd.Run() return errors.New(s) } @@ -124,7 +124,7 @@ func UninstallCertificates() error { p := C.uninstallCert() s := C.GoString(p) if len(s) != 0 { - oscmd := exec.Command("osascript", "-e", "display dialog \""+s+"\" buttons \"OK\" with title \"Error uninstalling certificates\"") + oscmd := exec.Command("osascript", "-e", "display dialog \""+s+"\" buttons \"OK\" with title \"Arduino Agent: Error uninstalling certificates\"") _ = oscmd.Run() return errors.New(s) } From 8daa25f6c9309933d4785f5485904996c9c86f0c Mon Sep 17 00:00:00 2001 From: MatteoPologruto Date: Wed, 10 Apr 2024 17:35:29 +0200 Subject: [PATCH 4/4] Remove certificate from the keychain if an error occurs during install --- certificates/install_darwin.go | 1 + 1 file changed, 1 insertion(+) diff --git a/certificates/install_darwin.go b/certificates/install_darwin.go index fc973d33c..2c84d7dcb 100644 --- a/certificates/install_darwin.go +++ b/certificates/install_darwin.go @@ -112,6 +112,7 @@ func InstallCertificate(cert *paths.Path) error { if len(s) != 0 { oscmd := exec.Command("osascript", "-e", "display dialog \""+s+"\" buttons \"OK\" with title \"Arduino Agent: Error installing certificates\"") _ = oscmd.Run() + _ = UninstallCertificates() return errors.New(s) } return nil