forked from keybase/go-keychain
-
Notifications
You must be signed in to change notification settings - Fork 8
/
osx.go
103 lines (85 loc) · 3.21 KB
/
osx.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
// +build darwin,!ios
package keychain
/*
#cgo LDFLAGS: -framework CoreFoundation -framework Security
#include <CoreFoundation/CoreFoundation.h>
#include <Security/Security.h>
*/
import "C"
import "unsafe"
var AccessibleKey = attrKey(C.CFTypeRef(C.kSecAttrAccessible))
var accessibleTypeRef = map[Accessible]C.CFTypeRef{
AccessibleWhenUnlocked: C.CFTypeRef(C.kSecAttrAccessibleWhenUnlocked),
AccessibleAfterFirstUnlock: C.CFTypeRef(C.kSecAttrAccessibleAfterFirstUnlock),
AccessibleAlways: C.CFTypeRef(C.kSecAttrAccessibleAlways),
AccessibleWhenUnlockedThisDeviceOnly: C.CFTypeRef(C.kSecAttrAccessibleWhenUnlockedThisDeviceOnly),
AccessibleAfterFirstUnlockThisDeviceOnly: C.CFTypeRef(C.kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly),
AccessibleAccessibleAlwaysThisDeviceOnly: C.CFTypeRef(C.kSecAttrAccessibleAlwaysThisDeviceOnly),
// Only available in 10.10
//AccessibleWhenPasscodeSetThisDeviceOnly: C.CFTypeRef(C.kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly),
}
var (
AccessKey = attrKey(C.CFTypeRef(C.kSecAttrAccess))
)
// The returned SecAccessRef, if non-nil, must be released via CFRelease.
func createAccess(label string, trustedApplications []string) (C.CFTypeRef, error) {
if len(trustedApplications) == 0 {
return nil, nil
}
// Always prepend with empty string which signifies that we
// include a NULL application, which means ourselves.
trustedApplications = append([]string{""}, trustedApplications...)
var err error
var labelRef C.CFStringRef
if labelRef, err = StringToCFString(label); err != nil {
return nil, err
}
defer C.CFRelease(C.CFTypeRef(labelRef))
var trustedApplicationsRefs []C.CFTypeRef
for _, trustedApplication := range trustedApplications {
trustedApplicationRef, err := createTrustedApplication(trustedApplication)
if err != nil {
return nil, err
}
defer C.CFRelease(C.CFTypeRef(trustedApplicationRef))
trustedApplicationsRefs = append(trustedApplicationsRefs, trustedApplicationRef)
}
var access C.SecAccessRef
trustedApplicationsArray := ArrayToCFArray(trustedApplicationsRefs)
defer C.CFRelease(C.CFTypeRef(trustedApplicationsArray))
errCode := C.SecAccessCreate(labelRef, trustedApplicationsArray, &access)
err = checkError(errCode)
if err != nil {
return nil, err
}
return C.CFTypeRef(access), nil
}
// The returned SecTrustedApplicationRef, if non-nil, must be released via CFRelease.
func createTrustedApplication(trustedApplication string) (C.CFTypeRef, error) {
var trustedApplicationCStr *C.char
if trustedApplication != "" {
trustedApplicationCStr = C.CString(trustedApplication)
defer C.free(unsafe.Pointer(trustedApplicationCStr))
}
var trustedApplicationRef C.SecTrustedApplicationRef
errCode := C.SecTrustedApplicationCreateFromPath(trustedApplicationCStr, &trustedApplicationRef)
err := checkError(errCode)
if err != nil {
return nil, err
}
return C.CFTypeRef(trustedApplicationRef), nil
}
type Access struct {
Label string
TrustedApplications []string
}
func (a Access) Convert() (C.CFTypeRef, error) {
return createAccess(a.Label, a.TrustedApplications)
}
func (k *Item) SetAccess(a *Access) {
if a != nil {
k.attr[AccessKey] = a
} else {
delete(k.attr, AccessKey)
}
}