diff --git a/osxkeychain/osxkeychain_darwin.c b/osxkeychain/osxkeychain_darwin.c index 371222e..5b420d0 100644 --- a/osxkeychain/osxkeychain_darwin.c +++ b/osxkeychain/osxkeychain_darwin.c @@ -14,7 +14,9 @@ char *get_error(OSStatus status) { return buf; } -char *keychain_add(struct Server *server, char *username, char *secret) { +char *keychain_add(struct Server *server, char *label, char *username, char *secret) { + SecKeychainItemRef item; + OSStatus status = SecKeychainAddInternetPassword( NULL, strlen(server->host), server->host, @@ -25,11 +27,27 @@ char *keychain_add(struct Server *server, char *username, char *secret) { server->proto, kSecAuthenticationTypeDefault, strlen(secret), secret, - NULL + &item ); + if (status) { return get_error(status); } + + SecKeychainAttribute attribute; + SecKeychainAttributeList attrs; + attribute.tag = kSecLabelItemAttr; + attribute.data = label; + attribute.length = strlen(label); + attrs.count = 1; + attrs.attr = &attribute; + + status = SecKeychainItemModifyContent(item, &attrs, 0, NULL); + + if (status) { + return get_error(status); + } + return NULL; } @@ -116,11 +134,12 @@ char * CFStringToCharArr(CFStringRef aString) { return NULL; } -char *keychain_list(char *** paths, char *** accts, unsigned int *list_l) { +char *keychain_list(char *credsLabel, char *** paths, char *** accts, unsigned int *list_l) { CFMutableDictionaryRef query = CFDictionaryCreateMutable (NULL, 1, NULL, NULL); CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword); CFDictionaryAddValue(query, kSecReturnAttributes, kCFBooleanTrue); CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitAll); + CFDictionaryAddValue(query, kSecAttrLabel, CFSTR(credsLabel)); //Use this query dictionary CFTypeRef result= NULL; OSStatus status = SecItemCopyMatching( diff --git a/osxkeychain/osxkeychain_darwin.go b/osxkeychain/osxkeychain_darwin.go index 21761aa..137b894 100644 --- a/osxkeychain/osxkeychain_darwin.go +++ b/osxkeychain/osxkeychain_darwin.go @@ -35,12 +35,14 @@ func (h Osxkeychain) Add(creds *credentials.Credentials) error { } defer freeServer(s) + label := C.CString(creds.Label) + defer C.free(unsafe.Pointer(label)) username := C.CString(creds.Username) defer C.free(unsafe.Pointer(username)) secret := C.CString(creds.Secret) defer C.free(unsafe.Pointer(secret)) - errMsg := C.keychain_add(s, username, secret) + errMsg := C.keychain_add(s, label, username, secret) if errMsg != nil { defer C.free(unsafe.Pointer(errMsg)) return errors.New(C.GoString(errMsg)) @@ -98,13 +100,16 @@ func (h Osxkeychain) Get(serverURL string) (string, string, error) { } // List returns the stored URLs and corresponding usernames. -func (h Osxkeychain) List() (map[string]string, error) { +func (h Osxkeychain) List(credsLabel string) (map[string]string, error) { + credsLabelC := C.CString(credsLabel) + defer C.free(unsafe.Pointer(credsLabelC)) + var pathsC **C.char defer C.free(unsafe.Pointer(pathsC)) var acctsC **C.char defer C.free(unsafe.Pointer(acctsC)) var listLenC C.uint - errMsg := C.keychain_list(&pathsC, &acctsC, &listLenC) + errMsg := C.keychain_list(credsLabelC, &pathsC, &acctsC, &listLenC) if errMsg != nil { defer C.free(unsafe.Pointer(errMsg)) goMsg := C.GoString(errMsg) diff --git a/osxkeychain/osxkeychain_darwin.h b/osxkeychain/osxkeychain_darwin.h index 6b01e97..a368046 100644 --- a/osxkeychain/osxkeychain_darwin.h +++ b/osxkeychain/osxkeychain_darwin.h @@ -7,7 +7,7 @@ struct Server { unsigned int port; }; -char *keychain_add(struct Server *server, char *username, char *secret); +char *keychain_add(struct Server *server, char *label, char *username, char *secret); char *keychain_get(struct Server *server, unsigned int *username_l, char **username, unsigned int *secret_l, char **secret); char *keychain_delete(struct Server *server); char *keychain_list(char *** data, char *** accts, unsigned int *list_l); diff --git a/osxkeychain/osxkeychain_darwin_test.go b/osxkeychain/osxkeychain_darwin_test.go index 406fe9b..700f153 100644 --- a/osxkeychain/osxkeychain_darwin_test.go +++ b/osxkeychain/osxkeychain_darwin_test.go @@ -34,14 +34,14 @@ func TestOSXKeychainHelper(t *testing.T) { t.Fatalf("expected %s, got %s\n", "foobarbaz", secret) } - auths, err := helper.List() + auths, err := helper.List(credentials.CredsLabel) if err != nil || len(auths) == 0 { t.Fatal(err) } helper.Add(creds1) defer helper.Delete(creds1.ServerURL) - newauths, err := helper.List() + newauths, err := helper.List(credentials.CredsLabel) if len(newauths)-len(auths) != 1 { if err == nil { t.Fatalf("Error: len(newauths): %d, len(auths): %d", len(newauths), len(auths))