Skip to content

Commit cefee44

Browse files
committed
add cert install on macos
leverage objective C APIs to install our CA certificate in the user's trusted keystore
1 parent cc95027 commit cefee44

File tree

3 files changed

+100
-1
lines changed

3 files changed

+100
-1
lines changed

certificates/install_darwin.go

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2023 Arduino SA
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU Affero General Public License as published
5+
// by the Free Software Foundation, either version 3 of the License, or
6+
// (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU Affero General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU Affero General Public License
14+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
15+
16+
package certificates
17+
18+
//inspired by https://stackoverflow.com/questions/12798950/ios-install-ssl-certificate-programmatically
19+
20+
/*
21+
#cgo CFLAGS: -x objective-c
22+
#cgo LDFLAGS: -framework Cocoa
23+
#import <Cocoa/Cocoa.h>
24+
25+
void installCert(const char *path) {
26+
NSURL *url = [NSURL fileURLWithPath:@(path) isDirectory:NO];
27+
NSData *rootCertData = [NSData dataWithContentsOfURL:url];
28+
29+
OSStatus err = noErr;
30+
SecCertificateRef rootCert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef) rootCertData);
31+
32+
CFTypeRef result;
33+
34+
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
35+
(id)kSecClassCertificate, kSecClass,
36+
rootCert, kSecValueRef,
37+
nil];
38+
39+
err = SecItemAdd((CFDictionaryRef)dict, &result);
40+
41+
if( err == noErr) {
42+
NSLog(@"Install root certificate success");
43+
} else if( err == errSecDuplicateItem ) {
44+
NSLog(@"duplicate root certificate entry");
45+
} else {
46+
NSLog(@"install root certificate failure");
47+
}
48+
49+
NSDictionary *newTrustSettings = @{(id)kSecTrustSettingsResult: [NSNumber numberWithInt:kSecTrustSettingsResultTrustRoot]};
50+
err = SecTrustSettingsSetTrustSettings(rootCert, kSecTrustSettingsDomainUser, (__bridge CFTypeRef)(newTrustSettings));
51+
if (err != errSecSuccess) {
52+
NSLog(@"Could not change the trust setting for a certificate. Error: %d", err);
53+
exit(0);
54+
}
55+
}
56+
57+
*/
58+
import "C"
59+
import (
60+
log "github.com/sirupsen/logrus"
61+
62+
"github.com/arduino/go-paths-helper"
63+
)
64+
65+
// InstallCertificate will install the certificates in the system keychain on macos
66+
func InstallCertificate(cert *paths.Path) {
67+
log.Infof("Installing certificate: %s", cert)
68+
C.installCert(C.CString(cert.String()))
69+
}

certificates/install_default.go

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2023 Arduino SA
2+
//
3+
// This program is free software: you can redistribute it and/or modify
4+
// it under the terms of the GNU Affero General Public License as published
5+
// by the Free Software Foundation, either version 3 of the License, or
6+
// (at your option) any later version.
7+
//
8+
// This program is distributed in the hope that it will be useful,
9+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11+
// GNU Affero General Public License for more details.
12+
//
13+
// You should have received a copy of the GNU Affero General Public License
14+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
15+
16+
//go:build !darwin
17+
18+
package certificates
19+
20+
import (
21+
log "github.com/sirupsen/logrus"
22+
23+
"github.com/arduino/go-paths-helper"
24+
)
25+
26+
// InstallCertificate won't do anything on unsupported Operative Systems
27+
func InstallCertificate(cert *paths.Path) {
28+
log.Warn("platform not supported for the certificate install")
29+
}

systray/systray_real.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func (s *Systray) start() {
6464
mRmCrashes := systray.AddMenuItem("Remove crash reports", "")
6565
s.updateMenuItem(mRmCrashes, config.LogsIsEmpty())
6666

67-
mGenCerts := systray.AddMenuItem("Generate HTTPS certificates", "HTTPS Certs")
67+
mGenCerts := systray.AddMenuItem("Generate and Install HTTPS certificates", "HTTPS Certs")
6868
s.updateMenuItem(mGenCerts, config.CertsExist())
6969

7070
// Add pause/quit
@@ -90,6 +90,7 @@ func (s *Systray) start() {
9090
s.updateMenuItem(mRmCrashes, config.LogsIsEmpty())
9191
case <-mGenCerts.ClickedCh:
9292
cert.GenerateCertificates(config.GetCertificatesDir())
93+
cert.InstallCertificate(config.GetCertificatesDir().Join("ca.cert.cer"))
9394
s.Restart()
9495
case <-mPause.ClickedCh:
9596
s.Pause()

0 commit comments

Comments
 (0)