diff --git a/certificates/install_darwin.go b/certificates/install_darwin.go index 134a4bc0c..2c84d7dcb 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 ( @@ -82,7 +110,22 @@ 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() + _ = UninstallCertificates() + return errors.New(s) + } + 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 \"Arduino Agent: Error uninstalling certificates\"") _ = oscmd.Run() return errors.New(s) } 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") +} 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: