Skip to content

Commit 8ec1efc

Browse files
committed
Fix compiler warnings and move obj-c code into a separate file.
1 parent d56f231 commit 8ec1efc

File tree

4 files changed

+157
-148
lines changed

4 files changed

+157
-148
lines changed

certificates/certificates.go

-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import (
3737
)
3838

3939
var (
40-
host = "localhost"
4140
validFrom = ""
4241
validFor = 365 * 24 * time.Hour * 2 // 2 years
4342
rsaBits = 2048

certificates/certificates.h

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const char *getDefaultBrowserName();
2+
3+
const char *installCert(const char *path);
4+
const char *uninstallCert();
5+
const char *certInKeychain();
6+
7+
const char *getExpirationDate(long *expirationDate);

certificates/certificates.m

+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
#import <Foundation/Foundation.h>
2+
#import <AppKit/AppKit.h>
3+
#include "certificates.h"
4+
5+
// Used to return error strings (as NSString) as a C-string to the Go code.
6+
const char *toErrorString(NSString *errString) {
7+
NSLog(@"%@", errString);
8+
return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];
9+
}
10+
11+
const char *getDefaultBrowserName() {
12+
NSURL *defaultBrowserURL = [[NSWorkspace sharedWorkspace] URLForApplicationToOpenURL:[NSURL URLWithString:@"http://"]];
13+
if (defaultBrowserURL) {
14+
NSBundle *defaultBrowserBundle = [NSBundle bundleWithURL:defaultBrowserURL];
15+
NSString *defaultBrowser = [defaultBrowserBundle objectForInfoDictionaryKey:@"CFBundleDisplayName"];
16+
17+
return [defaultBrowser cStringUsingEncoding:[NSString defaultCStringEncoding]];
18+
}
19+
20+
return "";
21+
}
22+
23+
// inspired by https://stackoverflow.com/questions/12798950/ios-install-ssl-certificate-programmatically
24+
const char *installCert(const char *path) {
25+
NSURL *url = [NSURL fileURLWithPath:@(path) isDirectory:NO];
26+
NSData *rootCertData = [NSData dataWithContentsOfURL:url];
27+
28+
OSStatus err = noErr;
29+
SecCertificateRef rootCert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef) rootCertData);
30+
31+
CFTypeRef result;
32+
33+
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
34+
(id)kSecClassCertificate, kSecClass,
35+
rootCert, kSecValueRef,
36+
nil];
37+
38+
err = SecItemAdd((CFDictionaryRef)dict, &result);
39+
40+
if (err == noErr) {
41+
NSLog(@"Install root certificate success");
42+
} else if (err == errSecDuplicateItem) {
43+
NSString *errString = [@"duplicate root certificate entry. Error: " stringByAppendingFormat:@"%d", err];
44+
NSLog(@"%@", errString);
45+
return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];
46+
} else {
47+
NSString *errString = [@"install root certificate failure. Error: " stringByAppendingFormat:@"%d", err];
48+
NSLog(@"%@", errString);
49+
return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];
50+
}
51+
52+
NSDictionary *newTrustSettings = @{(id)kSecTrustSettingsResult: [NSNumber numberWithInt:kSecTrustSettingsResultTrustRoot]};
53+
err = SecTrustSettingsSetTrustSettings(rootCert, kSecTrustSettingsDomainUser, (__bridge CFTypeRef)(newTrustSettings));
54+
if (err != errSecSuccess) {
55+
NSString *errString = [@"Could not change the trust setting for a certificate. Error: " stringByAppendingFormat:@"%d", err];
56+
NSLog(@"%@", errString);
57+
return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];
58+
}
59+
60+
return "";
61+
}
62+
63+
const char *uninstallCert() {
64+
// Each line is a key-value of the dictionary. Note: the the inverted order, value first then key.
65+
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
66+
(id)kSecClassCertificate, kSecClass,
67+
CFSTR("Arduino"), kSecAttrLabel,
68+
kSecMatchLimitOne, kSecMatchLimit,
69+
kCFBooleanTrue, kSecReturnAttributes,
70+
nil];
71+
72+
OSStatus err = noErr;
73+
// Use this function to check for errors
74+
err = SecItemCopyMatching((CFDictionaryRef)dict, nil);
75+
if (err == noErr) {
76+
err = SecItemDelete((CFDictionaryRef)dict);
77+
if (err != noErr) {
78+
NSString *errString = [@"Could not delete the certificates. Error: " stringByAppendingFormat:@"%d", err];
79+
NSLog(@"%@", errString);
80+
return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];
81+
}
82+
} else if (err != errSecItemNotFound){
83+
NSString *errString = [@"Error: " stringByAppendingFormat:@"%d", err];
84+
NSLog(@"%@", errString);
85+
return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];
86+
}
87+
return "";
88+
}
89+
90+
const char *certInKeychain() {
91+
// Each line is a key-value of the dictionary. Note: the the inverted order, value first then key.
92+
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
93+
(id)kSecClassCertificate, kSecClass,
94+
CFSTR("Arduino"), kSecAttrLabel,
95+
kSecMatchLimitOne, kSecMatchLimit,
96+
kCFBooleanTrue, kSecReturnAttributes,
97+
nil];
98+
99+
OSStatus err = noErr;
100+
// Use this function to check for errors
101+
err = SecItemCopyMatching((CFDictionaryRef)dict, nil);
102+
NSString *exists = @"false";
103+
if (err == noErr) {
104+
exists = @"true";
105+
}
106+
return [exists cStringUsingEncoding:[NSString defaultCStringEncoding]];
107+
}
108+
109+
// Returns the expiration date "kSecOIDX509V1ValidityNotAfter" of the Arduino certificate.
110+
// The value is returned as a CFAbsoluteTime: a long number of seconds from the date of 1 Jan 2001 00:00:00 GMT.
111+
const char *getExpirationDate(long *expirationDate) {
112+
// Create a key-value dictionary used to query the Keychain and look for the "Arduino" root certificate.
113+
NSDictionary *getquery = @{
114+
(id)kSecClass: (id)kSecClassCertificate,
115+
(id)kSecAttrLabel: @"Arduino",
116+
(id)kSecReturnRef: @YES,
117+
};
118+
119+
SecCertificateRef cert = NULL;
120+
121+
// Search the keychain for certificates matching the query above.
122+
OSStatus err = SecItemCopyMatching((CFDictionaryRef)getquery, (CFTypeRef *)&cert);
123+
if (err != noErr) return toErrorString([@"Error getting the certificate: " stringByAppendingFormat:@"%d", err]);
124+
125+
// Get data from the certificate, as a dictionary of properties. We just need the "invalidity not after" property.
126+
CFDictionaryRef certDict = SecCertificateCopyValues(cert,
127+
(__bridge CFArrayRef)@[(__bridge id)kSecOIDX509V1ValidityNotAfter], NULL);
128+
if (certDict == NULL) return toErrorString(@"SecCertificateCopyValues failed");
129+
130+
131+
// Get the "validity not after" property as a dictionary, and get the "value" key (that is a number).
132+
CFDictionaryRef validityNotAfterDict = CFDictionaryGetValue(certDict, kSecOIDX509V1ValidityNotAfter);
133+
if (validityNotAfterDict == NULL) return toErrorString(@"CFDictionaryGetValue (validity) failed");
134+
135+
CFNumberRef number = (CFNumberRef)CFDictionaryGetValue(validityNotAfterDict, kSecPropertyKeyValue);
136+
if (number == NULL) return toErrorString(@"CFDictionaryGetValue (keyValue) failed");
137+
138+
CFNumberGetValue(number, kCFNumberSInt64Type, expirationDate);
139+
// NSLog(@"Certificate validity not after: %ld", *expirationDate);
140+
141+
CFRelease(certDict);
142+
return ""; // No error.
143+
}

certificates/install_darwin.go

+7-147
Original file line numberDiff line numberDiff line change
@@ -15,154 +15,16 @@
1515

1616
package certificates
1717

18-
//inspired by https://stackoverflow.com/questions/12798950/ios-install-ssl-certificate-programmatically
19-
2018
/*
2119
// Explicitly tell the GCC compiler that the language is Objective-C.
2220
#cgo CFLAGS: -x objective-c
23-
// Pass the list of macOS frameworks needed by this piece of Objective-C code.
24-
#cgo LDFLAGS: -framework Cocoa
25-
#import <Cocoa/Cocoa.h>
26-
27-
28-
// Used to return error strings (as NSString) as a C-string to the Go code.
29-
const char *toErrorString(NSString *errString) {
30-
NSLog(@"%@", errString);
31-
return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];
32-
}
33-
34-
const char *installCert(const char *path) {
35-
NSURL *url = [NSURL fileURLWithPath:@(path) isDirectory:NO];
36-
NSData *rootCertData = [NSData dataWithContentsOfURL:url];
37-
38-
OSStatus err = noErr;
39-
SecCertificateRef rootCert = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef) rootCertData);
40-
41-
CFTypeRef result;
42-
43-
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
44-
(id)kSecClassCertificate, kSecClass,
45-
rootCert, kSecValueRef,
46-
nil];
47-
48-
err = SecItemAdd((CFDictionaryRef)dict, &result);
49-
50-
if (err == noErr) {
51-
NSLog(@"Install root certificate success");
52-
} else if (err == errSecDuplicateItem) {
53-
NSString *errString = [@"duplicate root certificate entry. Error: " stringByAppendingFormat:@"%d", err];
54-
NSLog(@"%@", errString);
55-
return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];;
56-
} else {
57-
NSString *errString = [@"install root certificate failure. Error: " stringByAppendingFormat:@"%d", err];
58-
NSLog(@"%@", errString);
59-
return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];
60-
}
61-
62-
NSDictionary *newTrustSettings = @{(id)kSecTrustSettingsResult: [NSNumber numberWithInt:kSecTrustSettingsResultTrustRoot]};
63-
err = SecTrustSettingsSetTrustSettings(rootCert, kSecTrustSettingsDomainUser, (__bridge CFTypeRef)(newTrustSettings));
64-
if (err != errSecSuccess) {
65-
NSString *errString = [@"Could not change the trust setting for a certificate. Error: " stringByAppendingFormat:@"%d", err];
66-
NSLog(@"%@", errString);
67-
return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];
68-
}
69-
70-
return "";
71-
}
72-
73-
const char *uninstallCert() {
74-
// Each line is a key-value of the dictionary. Note: the the inverted order, value first then key.
75-
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
76-
(id)kSecClassCertificate, kSecClass,
77-
CFSTR("Arduino"), kSecAttrLabel,
78-
kSecMatchLimitOne, kSecMatchLimit,
79-
kCFBooleanTrue, kSecReturnAttributes,
80-
nil];
81-
82-
OSStatus err = noErr;
83-
// Use this function to check for errors
84-
err = SecItemCopyMatching((CFDictionaryRef)dict, nil);
85-
if (err == noErr) {
86-
err = SecItemDelete((CFDictionaryRef)dict);
87-
if (err != noErr) {
88-
NSString *errString = [@"Could not delete the certificates. Error: " stringByAppendingFormat:@"%d", err];
89-
NSLog(@"%@", errString);
90-
return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];;
91-
}
92-
} else if (err != errSecItemNotFound){
93-
NSString *errString = [@"Error: " stringByAppendingFormat:@"%d", err];
94-
NSLog(@"%@", errString);
95-
return [errString cStringUsingEncoding:[NSString defaultCStringEncoding]];;
96-
}
97-
return "";
98-
}
99-
100-
// Returns the expiration date "kSecOIDX509V1ValidityNotAfter" of the Arduino certificate.
101-
// The value is returned as a CFAbsoluteTime: a long number of seconds from the date of 1 Jan 2001 00:00:00 GMT.
102-
const char *getExpirationDate(long *expirationDate) {
103-
// Create a key-value dictionary used to query the Keychain and look for the "Arduino" root certificate.
104-
NSDictionary *getquery = @{
105-
(id)kSecClass: (id)kSecClassCertificate,
106-
(id)kSecAttrLabel: @"Arduino",
107-
(id)kSecReturnRef: @YES,
108-
};
10921
110-
SecCertificateRef cert = NULL;
111-
112-
// Search the keychain for certificates matching the query above.
113-
OSStatus err = SecItemCopyMatching((CFDictionaryRef)getquery, (CFTypeRef *)&cert);
114-
if (err != noErr) return toErrorString([@"Error getting the certificate: " stringByAppendingFormat:@"%d", err]);
115-
116-
// Get data from the certificate, as a dictionary of properties. We just need the "invalidity not after" property.
117-
CFDictionaryRef certDict = SecCertificateCopyValues(cert,
118-
(__bridge CFArrayRef)@[(__bridge id)kSecOIDX509V1ValidityNotAfter], NULL);
119-
if (certDict == NULL) return toErrorString(@"SecCertificateCopyValues failed");
120-
121-
122-
// Get the "validity not after" property as a dictionary, and get the "value" key (that is a number).
123-
CFDictionaryRef validityNotAfterDict = CFDictionaryGetValue(certDict, kSecOIDX509V1ValidityNotAfter);
124-
if (validityNotAfterDict == NULL) return toErrorString(@"CFDictionaryGetValue (validity) failed");
125-
126-
CFNumberRef number = (CFNumberRef)CFDictionaryGetValue(validityNotAfterDict, kSecPropertyKeyValue);
127-
if (number == NULL) return toErrorString(@"CFDictionaryGetValue (keyValue) failed");
128-
129-
CFNumberGetValue(number, kCFNumberSInt64Type, expirationDate);
130-
// NSLog(@"Certificate validity not after: %ld", *expirationDate);
131-
132-
CFRelease(certDict);
133-
return ""; // No error.
134-
}
135-
136-
const char *getDefaultBrowserName() {
137-
NSURL *defaultBrowserURL = [[NSWorkspace sharedWorkspace] URLForApplicationToOpenURL:[NSURL URLWithString:@"http://"]];
138-
if (defaultBrowserURL) {
139-
NSBundle *defaultBrowserBundle = [NSBundle bundleWithURL:defaultBrowserURL];
140-
NSString *defaultBrowser = [defaultBrowserBundle objectForInfoDictionaryKey:@"CFBundleDisplayName"];
141-
142-
return [defaultBrowser cStringUsingEncoding:[NSString defaultCStringEncoding]];
143-
}
144-
145-
return "";
146-
}
147-
148-
const char *certInKeychain() {
149-
// Each line is a key-value of the dictionary. Note: the the inverted order, value first then key.
150-
NSDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys:
151-
(id)kSecClassCertificate, kSecClass,
152-
CFSTR("Arduino"), kSecAttrLabel,
153-
kSecMatchLimitOne, kSecMatchLimit,
154-
kCFBooleanTrue, kSecReturnAttributes,
155-
nil];
22+
// Pass the list of macOS frameworks needed by this piece of Objective-C code.
23+
// The "-ld_classic" is needed to avoid a wrong warning about duplicate libraries when building with XCode 15.
24+
#cgo LDFLAGS: -framework Foundation -framework Security -framework AppKit -ld_classic
15625
157-
OSStatus err = noErr;
158-
// Use this function to check for errors
159-
err = SecItemCopyMatching((CFDictionaryRef)dict, nil);
160-
NSString *exists = @"false";
161-
if (err == noErr) {
162-
exists = @"true";
163-
}
164-
return [exists cStringUsingEncoding:[NSString defaultCStringEncoding]];;
165-
}
26+
#import <Foundation/Foundation.h>
27+
#include "certificates.h"
16628
*/
16729
import "C"
16830
import (
@@ -236,8 +98,6 @@ func CertInKeychain() bool {
23698
log.Infof("Checking if the Arduino certificate is in the keychain")
23799
p := C.certInKeychain()
238100
s := C.GoString(p)
239-
if s == "true" {
240-
return true
241-
}
242-
return false
101+
102+
return s == "true"
243103
}

0 commit comments

Comments
 (0)