From 5a8fb214ed22caee8e035cc38ffc66e46d67e0b2 Mon Sep 17 00:00:00 2001 From: avaid96 Date: Mon, 11 Jul 2016 10:50:44 -0700 Subject: [PATCH 01/19] Full implementation for OSX ready Signed-off-by: avaid96 --- credentials/credentials.go | 28 ++++++++++ credentials/credentials_test.go | 18 ++++++ credentials/helper.go | 3 + osxkeychain/osxkeychain_darwin.c | 77 ++++++++++++++++++++++++++ osxkeychain/osxkeychain_darwin.go | 39 ++++++++++++- osxkeychain/osxkeychain_darwin.h | 2 + osxkeychain/osxkeychain_darwin_test.go | 6 +- 7 files changed, 170 insertions(+), 3 deletions(-) diff --git a/credentials/credentials.go b/credentials/credentials.go index b14f495..23fa569 100644 --- a/credentials/credentials.go +++ b/credentials/credentials.go @@ -17,6 +17,11 @@ type Credentials struct { Secret string } +type KeyData struct{ + Path string + Username string +} + // Serve initializes the credentials helper and parses the action argument. // This function is designed to be called from a command line interface. // It uses os.Args[1] as the key for the action. @@ -127,3 +132,26 @@ func Erase(helper Helper, reader io.Reader) error { return helper.Delete(serverURL) } + + //List returns all the serverURLs of keys in + //the OS store as a list of strings +func List(helper Helper, writer io.Writer) error { + x, y, err := helper.List() + if err != nil { + return err + } + keyDataList := []KeyData{} + for index, _ := range(x) { + keyDataObj := KeyData{ + Path:x[index], + Username:y[index], + } + keyDataList = append([]KeyData{keyDataObj}, keyDataList...) + } + buffer := new(bytes.Buffer) + if err := json.NewEncoder(buffer).Encode(keyDataList); err != nil { + return err + } + fmt.Fprint(writer, buffer.String()) + return nil +} \ No newline at end of file diff --git a/credentials/credentials_test.go b/credentials/credentials_test.go index fae219a..0909cb7 100644 --- a/credentials/credentials_test.go +++ b/credentials/credentials_test.go @@ -36,6 +36,11 @@ func (m *memoryStore) Get(serverURL string) (string, string, error) { return c.Username, c.Secret, nil } +func (m *memoryStore) List() ([]string, []string, error) { + //Simply a placeholder to let memoryStore be a valid implementation of Helper interface + return nil, nil, nil +} + func TestStore(t *testing.T) { serverURL := "https://index.docker.io/v1/" creds := &Credentials{ @@ -138,3 +143,16 @@ func TestErase(t *testing.T) { t.Fatal("expected error getting missing creds, got empty") } } + +func TestList(t *testing.T) { + //This tests that there is proper input an output into the byte stream + //Individual stores are very OS specific and have been tested in osxkeychain and secretservice respectively + out := new(bytes.Buffer) + h := newMemoryStore() + if err := List(h, out); err != nil { + t.Fatal(err) + } + if out.Len() == 0 { + t.Fatalf("expected output in the writer, got %d", 0) + } +} diff --git a/credentials/helper.go b/credentials/helper.go index 8a69671..ba1ba34 100644 --- a/credentials/helper.go +++ b/credentials/helper.go @@ -9,4 +9,7 @@ type Helper interface { // Get retrieves credentials from the store. // It returns username and secret as strings. Get(serverURL string) (string, string, error) + // List returns all the serverURLs of keys in + // the OS store as a list of strings + List() ([]string, []string, error) } diff --git a/osxkeychain/osxkeychain_darwin.c b/osxkeychain/osxkeychain_darwin.c index d1289e4..2b4d8d8 100644 --- a/osxkeychain/osxkeychain_darwin.c +++ b/osxkeychain/osxkeychain_darwin.c @@ -1,4 +1,7 @@ #include "osxkeychain_darwin.h" +#include +#include +#include char *get_error(OSStatus status) { char *buf = malloc(128); @@ -96,3 +99,77 @@ char *keychain_delete(struct Server *server) { } return NULL; } + +char * CFStringToCharArr(CFStringRef aString) { + if (aString == NULL) { + return NULL; + } + CFIndex length = CFStringGetLength(aString); + CFIndex maxSize = + CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8) + 1; + char *buffer = (char *)malloc(maxSize); + if (CFStringGetCString(aString, buffer, maxSize, + kCFStringEncodingUTF8)) { + return buffer; + } + return NULL; +} + +char *keychain_list(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); + //Use this query dictionary + CFTypeRef result= NULL; + OSStatus status = SecItemCopyMatching( + query, + &result); + //Ran a search and store the results in result + if (status) { + return get_error(status); + } + int numKeys = CFArrayGetCount(result); + *paths = (char **) malloc((int)sizeof(char *)*numKeys); + *accts = (char **) malloc((int)sizeof(char *)*numKeys); + //result is of type CFArray + for(int i=0; i"); + } + char * path = (char *) malloc(CFStringGetLength(pathTmp)+1); + path = CFStringToCharArr(pathTmp); + path[strlen(path)] = '\0'; + char * acct = (char *) malloc(CFStringGetLength(acctTmp)+1); //<- problem line in 38th iteration + acct = CFStringToCharArr(acctTmp); + acct[strlen(acct)] = '\0'; + //We now have all we need, username and servername. Now export this to .go + (*paths)[i] = (char *) malloc(sizeof(char)*(strlen(path)+1)); + memcpy((*paths)[i], path, sizeof(char)*(strlen(path)+1)); + (*accts)[i] = (char *) malloc(sizeof(char)*(strlen(acct)+1)); + memcpy((*accts)[i], acct, sizeof(char)*(strlen(acct)+1)); + } + else { + char * path = "0"; + char * acct = "0"; + (*paths)[i] = (char *) malloc(sizeof(char)*(strlen(path))); + memcpy((*paths)[i], path, sizeof(char)*(strlen(path))); + (*accts)[i] = (char *) malloc(sizeof(char)*(strlen(acct))); + memcpy((*accts)[i], acct, sizeof(char)*(strlen(acct))); + } + } + *list_l = numKeys; + return NULL; +} + +void freeListData(char *** data, unsigned int length) { + for(int i=0; i> + C.freeListData(&pathsC, listLenC) + return paths, accts, nil +} + func splitServer(serverURL string) (*C.struct_Server, error) { u, err := url.Parse(serverURL) if err != nil { @@ -130,3 +164,4 @@ func freeServer(s *C.struct_Server) { C.free(unsafe.Pointer(s.host)) C.free(unsafe.Pointer(s.path)) } + diff --git a/osxkeychain/osxkeychain_darwin.h b/osxkeychain/osxkeychain_darwin.h index cb463c4..6b01e97 100644 --- a/osxkeychain/osxkeychain_darwin.h +++ b/osxkeychain/osxkeychain_darwin.h @@ -10,3 +10,5 @@ struct Server { char *keychain_add(struct Server *server, 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); +void freeListData(char *** data, unsigned int length); \ No newline at end of file diff --git a/osxkeychain/osxkeychain_darwin_test.go b/osxkeychain/osxkeychain_darwin_test.go index 175da26..94c47aa 100644 --- a/osxkeychain/osxkeychain_darwin_test.go +++ b/osxkeychain/osxkeychain_darwin_test.go @@ -2,7 +2,6 @@ package osxkeychain import ( "testing" - "github.com/docker/docker-credential-helpers/credentials" ) @@ -34,6 +33,11 @@ func TestOSXKeychainHelper(t *testing.T) { if err := helper.Delete(creds.ServerURL); err != nil { t.Fatal(err) } + + _, _, err = helper.List(); + if err != nil { + t.Fatal(err) + } } func TestMissingCredentials(t *testing.T) { From 72661b31038ed4e34ebf5d65ac0b18cad96e5a8b Mon Sep 17 00:00:00 2001 From: Avi Vaid Date: Mon, 11 Jul 2016 19:33:35 -0400 Subject: [PATCH 02/19] Implemented list functionality for secretservice- linux Signed-off-by: Avi Vaid --- osxkeychain/osxkeychain_darwin.c | 4 +-- secretservice/secretservice_linux.c | 41 +++++++++++++++++++++++ secretservice/secretservice_linux.go | 23 +++++++++++++ secretservice/secretservice_linux.h | 1 + secretservice/secretservice_linux_test.go | 3 ++ 5 files changed, 70 insertions(+), 2 deletions(-) diff --git a/osxkeychain/osxkeychain_darwin.c b/osxkeychain/osxkeychain_darwin.c index 2b4d8d8..6c0240a 100644 --- a/osxkeychain/osxkeychain_darwin.c +++ b/osxkeychain/osxkeychain_darwin.c @@ -140,7 +140,7 @@ char *keychain_list(char *** paths, char *** accts, unsigned int *list_l) { CFStringRef pathTmp = CFDictionaryGetValue(currKey, CFSTR("path")); CFStringRef acctTmp = CFDictionaryGetValue(currKey, CFSTR("acct")); if (acctTmp == NULL) { - acctTmp = CFSTR(""); + acctTmp = CFSTR("account not defined"); } char * path = (char *) malloc(CFStringGetLength(pathTmp)+1); path = CFStringToCharArr(pathTmp); @@ -172,4 +172,4 @@ void freeListData(char *** data, unsigned int length) { free((*data)[i]); } free(*data); -} \ No newline at end of file +} diff --git a/secretservice/secretservice_linux.c b/secretservice/secretservice_linux.c index 13950d3..d713814 100644 --- a/secretservice/secretservice_linux.c +++ b/secretservice/secretservice_linux.c @@ -96,3 +96,44 @@ GError *get(char *server, char **username, char **secret) { } return NULL; } + +GError *list(char *** paths, char *** accts, unsigned int *list_l) { + GList *items; + GError *err = NULL; + SecretService *service; + SecretSearchFlags flags = SECRET_SEARCH_LOAD_SECRETS | SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK; + GHashTable *attributes; + g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + attributes = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); + service = secret_service_get_sync(SECRET_SERVICE_NONE, NULL, &err); + items = secret_service_search_sync(service, NULL, attributes, flags, NULL, &err); + int numKeys = g_list_length(items); + if (err != NULL) { + return err; + } + *paths = (char **) malloc((int)sizeof(char *)*numKeys); + *accts = (char **) malloc((int)sizeof(char *)*numKeys); + // items now contains our keys from the gnome keyring + // we will now put it in our two lists to return it to go + GList *current; + int listNumber = 0; + for(current = items; current!=NULL; current = current->next) { + char *pathTmp = secret_item_get_label(current->data); + // you cannot have a key without a label in the gnome keyring + char *acctTmp = get_username(current->data); + if (acctTmp==NULL) { + acctTmp = "account not defined"; + } + char *path = (char *) malloc(strlen(pathTmp)); + char *acct = (char *) malloc(strlen(acctTmp)); + path = pathTmp; + acct = acctTmp; + (*paths)[listNumber] = (char *) malloc(sizeof(char)*(strlen(path))); + memcpy((*paths)[listNumber], path, sizeof(char)*(strlen(path))); + (*accts)[listNumber] = (char *) malloc(sizeof(char)*(strlen(acct))); + memcpy((*accts)[listNumber], acct, sizeof(char)*(strlen(acct))); + listNumber = listNumber + 1; + } + *list_l = numKeys; + return NULL; +} diff --git a/secretservice/secretservice_linux.go b/secretservice/secretservice_linux.go index dcd682e..45ab1f5 100644 --- a/secretservice/secretservice_linux.go +++ b/secretservice/secretservice_linux.go @@ -78,3 +78,26 @@ func (h Secretservice) Get(serverURL string) (string, string, error) { } return user, pass, nil } + +func (h Secretservice) List() ([]string, []string, error) { + var pathsC **C.char + defer C.free(unsafe.Pointer(pathsC)) + var acctsC **C.char + defer C.free(unsafe.Pointer(acctsC)) + var listLenC C.uint + err := C.list(&pathsC, &acctsC, &listLenC) + if err != nil { + defer C.free(unsafe.Pointer(err)) + return nil, nil, errors.New("Error from list function in secretservice_linux.c likely due to error in secretservice library") + } + listLen := int(listLenC) + pathTmp := (*[1 << 30]*C.char)(unsafe.Pointer(pathsC))[:listLen:listLen] + acctTmp := (*[1 << 30]*C.char)(unsafe.Pointer(acctsC))[:listLen:listLen] + paths := make([]string, listLen) + accts := make([]string, listLen) + for i := 0; i < listLen; i++ { + paths[i] = C.GoString(pathTmp[i]) + accts[i] = C.GoString(acctTmp[i]) + } + return paths, accts, nil +} diff --git a/secretservice/secretservice_linux.h b/secretservice/secretservice_linux.h index 5e09bed..3635246 100644 --- a/secretservice/secretservice_linux.h +++ b/secretservice/secretservice_linux.h @@ -9,3 +9,4 @@ const SecretSchema *docker_get_schema(void) G_GNUC_CONST; GError *add(char *server, char *username, char *secret); GError *delete(char *server); GError *get(char *server, char **username, char **secret); +GError *list(char *** paths, char *** accts, unsigned int *list_l); diff --git a/secretservice/secretservice_linux_test.go b/secretservice/secretservice_linux_test.go index e6a1664..98c2669 100644 --- a/secretservice/secretservice_linux_test.go +++ b/secretservice/secretservice_linux_test.go @@ -36,6 +36,9 @@ func TestSecretServiceHelper(t *testing.T) { if err := helper.Delete(creds.ServerURL); err != nil { t.Fatal(err) } + if _, _, err := helper.List(); err != nil { + t.Fatal(err) + } } func TestMissingCredentials(t *testing.T) { From 7566a1e399dfcf22603c5ed4276d8e749dd1085d Mon Sep 17 00:00:00 2001 From: Avi Vaid Date: Mon, 11 Jul 2016 19:45:37 -0400 Subject: [PATCH 03/19] implemented freeing memory in secretservice and made minor edits to osxkeychain Signed-off-by: Avi Vaid --- osxkeychain/osxkeychain_darwin.go | 20 +++++++++----------- secretservice/secretservice_linux.c | 8 ++++++++ secretservice/secretservice_linux.go | 2 ++ secretservice/secretservice_linux.h | 1 + 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/osxkeychain/osxkeychain_darwin.go b/osxkeychain/osxkeychain_darwin.go index 151f1a9..28c316d 100644 --- a/osxkeychain/osxkeychain_darwin.go +++ b/osxkeychain/osxkeychain_darwin.go @@ -10,11 +10,11 @@ package osxkeychain import "C" import ( "errors" + "github.com/docker/docker-credential-helpers/credentials" "net/url" "strconv" "strings" "unsafe" - "github.com/docker/docker-credential-helpers/credentials" ) // errCredentialsNotFound is the specific error message returned by OS X @@ -94,19 +94,19 @@ func (h Osxkeychain) Get(serverURL string) (string, string, error) { return user, pass, nil } -func (h Osxkeychain) List() ([]string, []string, error){ - var pathsC** C.char +func (h Osxkeychain) List() ([]string, []string, error) { + var pathsC **C.char defer C.free(unsafe.Pointer(pathsC)) - var acctsC** C.char + var acctsC **C.char defer C.free(unsafe.Pointer(acctsC)) var listLenC C.uint errMsg := C.keychain_list(&pathsC, &acctsC, &listLenC) - if errMsg!=nil { + if errMsg != nil { defer C.free(unsafe.Pointer(errMsg)) goMsg := C.GoString(errMsg) return nil, nil, errors.New(goMsg) } - var listLen int; + var listLen int listLen = int(listLenC) pathTmp := (*[1 << 30]*C.char)(unsafe.Pointer(pathsC))[:listLen:listLen] acctTmp := (*[1 << 30]*C.char)(unsafe.Pointer(acctsC))[:listLen:listLen] @@ -114,8 +114,8 @@ func (h Osxkeychain) List() ([]string, []string, error){ paths := make([]string, listLen) accts := make([]string, listLen) at := 0 - for i := 0; i < listLen ; i++ { - if C.GoString(pathTmp[i])=="0" { + for i := 0; i < listLen; i++ { + if C.GoString(pathTmp[i]) == "0" { continue } paths[at] = C.GoString(pathTmp[i]) @@ -124,9 +124,8 @@ func (h Osxkeychain) List() ([]string, []string, error){ } paths = paths[:at] accts = accts[:at] - //still need to free all the memory we allocated in the c file - //do it here >> C.freeListData(&pathsC, listLenC) + C.freeListData(&acctsC, listLenC) return paths, accts, nil } @@ -164,4 +163,3 @@ func freeServer(s *C.struct_Server) { C.free(unsafe.Pointer(s.host)) C.free(unsafe.Pointer(s.path)) } - diff --git a/secretservice/secretservice_linux.c b/secretservice/secretservice_linux.c index d713814..331faf9 100644 --- a/secretservice/secretservice_linux.c +++ b/secretservice/secretservice_linux.c @@ -1,4 +1,5 @@ #include +#include #include "secretservice_linux.h" const SecretSchema *docker_get_schema(void) @@ -137,3 +138,10 @@ GError *list(char *** paths, char *** accts, unsigned int *list_l) { *list_l = numKeys; return NULL; } + +void freeListData(char *** data, unsigned int length) { + for(int i=0; i Date: Mon, 11 Jul 2016 23:34:20 -0700 Subject: [PATCH 04/19] cleaned up some of the osx code, added a better test for list Signed-off-by: avaid96 --- credentials/credentials.go | 20 ++++++++++---------- credentials/credentials_test.go | 1 + credentials/helper.go | 5 +++-- osxkeychain/osxkeychain_darwin.c | 2 +- osxkeychain/osxkeychain_darwin_test.go | 12 +++++++++--- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/credentials/credentials.go b/credentials/credentials.go index 23fa569..8fc69c7 100644 --- a/credentials/credentials.go +++ b/credentials/credentials.go @@ -17,9 +17,9 @@ type Credentials struct { Secret string } -type KeyData struct{ - Path string - Username string +type KeyData struct { + Path string + Username string } // Serve initializes the credentials helper and parses the action argument. @@ -133,18 +133,18 @@ func Erase(helper Helper, reader io.Reader) error { return helper.Delete(serverURL) } - //List returns all the serverURLs of keys in - //the OS store as a list of strings +//List returns all the serverURLs of keys in +//the OS store as a list of strings func List(helper Helper, writer io.Writer) error { - x, y, err := helper.List() + paths, accts, err := helper.List() if err != nil { return err } keyDataList := []KeyData{} - for index, _ := range(x) { + for index := 0; index < len(paths); index++ { keyDataObj := KeyData{ - Path:x[index], - Username:y[index], + Path: paths[index], + Username: accts[index], } keyDataList = append([]KeyData{keyDataObj}, keyDataList...) } @@ -154,4 +154,4 @@ func List(helper Helper, writer io.Writer) error { } fmt.Fprint(writer, buffer.String()) return nil -} \ No newline at end of file +} diff --git a/credentials/credentials_test.go b/credentials/credentials_test.go index 0909cb7..6476012 100644 --- a/credentials/credentials_test.go +++ b/credentials/credentials_test.go @@ -152,6 +152,7 @@ func TestList(t *testing.T) { if err := List(h, out); err != nil { t.Fatal(err) } + //testing that there is an output if out.Len() == 0 { t.Fatalf("expected output in the writer, got %d", 0) } diff --git a/credentials/helper.go b/credentials/helper.go index ba1ba34..785fcd7 100644 --- a/credentials/helper.go +++ b/credentials/helper.go @@ -9,7 +9,8 @@ type Helper interface { // Get retrieves credentials from the store. // It returns username and secret as strings. Get(serverURL string) (string, string, error) - // List returns all the serverURLs of keys in - // the OS store as a list of strings + // List returns the serverURLs of keys and their + // associated usernames from the OS store as a + // list of strings List() ([]string, []string, error) } diff --git a/osxkeychain/osxkeychain_darwin.c b/osxkeychain/osxkeychain_darwin.c index 6c0240a..d8105fc 100644 --- a/osxkeychain/osxkeychain_darwin.c +++ b/osxkeychain/osxkeychain_darwin.c @@ -145,7 +145,7 @@ char *keychain_list(char *** paths, char *** accts, unsigned int *list_l) { char * path = (char *) malloc(CFStringGetLength(pathTmp)+1); path = CFStringToCharArr(pathTmp); path[strlen(path)] = '\0'; - char * acct = (char *) malloc(CFStringGetLength(acctTmp)+1); //<- problem line in 38th iteration + char * acct = (char *) malloc(CFStringGetLength(acctTmp)+1); acct = CFStringToCharArr(acctTmp); acct[strlen(acct)] = '\0'; //We now have all we need, username and servername. Now export this to .go diff --git a/osxkeychain/osxkeychain_darwin_test.go b/osxkeychain/osxkeychain_darwin_test.go index 94c47aa..f4b32a0 100644 --- a/osxkeychain/osxkeychain_darwin_test.go +++ b/osxkeychain/osxkeychain_darwin_test.go @@ -1,8 +1,8 @@ package osxkeychain import ( - "testing" "github.com/docker/docker-credential-helpers/credentials" + "testing" ) func TestOSXKeychainHelper(t *testing.T) { @@ -34,10 +34,16 @@ func TestOSXKeychainHelper(t *testing.T) { t.Fatal(err) } - _, _, err = helper.List(); - if err != nil { + paths, accts, err := helper.List() + if err != nil || len(paths) == 0 || len(accts) == 0 { t.Fatal(err) } + helper.Add(creds) + newpaths, newaccts, err := helper.List() + if len(newpaths)-len(paths) != 1 || len(newaccts)-len(accts) != 1 { + t.Fatal() + } + helper.Delete(creds.ServerURL) } func TestMissingCredentials(t *testing.T) { From 59b3d54595ea520d4bbe32903b3c1815487ff2ac Mon Sep 17 00:00:00 2001 From: Avi Vaid Date: Tue, 12 Jul 2016 02:52:44 -0400 Subject: [PATCH 05/19] added better test for list in linux Signed-off-by: Avi Vaid --- secretservice/secretservice_linux_test.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/secretservice/secretservice_linux_test.go b/secretservice/secretservice_linux_test.go index 98c2669..89bd196 100644 --- a/secretservice/secretservice_linux_test.go +++ b/secretservice/secretservice_linux_test.go @@ -36,7 +36,12 @@ func TestSecretServiceHelper(t *testing.T) { if err := helper.Delete(creds.ServerURL); err != nil { t.Fatal(err) } - if _, _, err := helper.List(); err != nil { + paths, accts, err := helper.List() + if err != nil || len(paths) == 0 || len(accts) == 0 { + t.Fatal(err) + } + helper.Add(creds) + if newpaths, newaccts, err := helper.List(); (len(newpaths)-len(paths)) != 1 || (len(newaccts)-len(accts)) != 1 { t.Fatal(err) } } From 9557dc3c3fba5572537eba0b964b098e898a14cf Mon Sep 17 00:00:00 2001 From: avaid96 Date: Tue, 12 Jul 2016 00:04:34 -0700 Subject: [PATCH 06/19] fixing a vet issue Signed-off-by: avaid96 --- osxkeychain/osxkeychain_darwin_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osxkeychain/osxkeychain_darwin_test.go b/osxkeychain/osxkeychain_darwin_test.go index f4b32a0..5d21023 100644 --- a/osxkeychain/osxkeychain_darwin_test.go +++ b/osxkeychain/osxkeychain_darwin_test.go @@ -41,7 +41,7 @@ func TestOSXKeychainHelper(t *testing.T) { helper.Add(creds) newpaths, newaccts, err := helper.List() if len(newpaths)-len(paths) != 1 || len(newaccts)-len(accts) != 1 { - t.Fatal() + t.Fatal(err) } helper.Delete(creds.ServerURL) } From d2e6ed779a888da72d8dd3283195823da6002de6 Mon Sep 17 00:00:00 2001 From: Avi Vaid Date: Tue, 12 Jul 2016 12:51:30 -0400 Subject: [PATCH 07/19] moved loop variable declaration to comply with c mode in travis Signed-off-by: Avi Vaid --- secretservice/secretservice_linux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/secretservice/secretservice_linux.c b/secretservice/secretservice_linux.c index 331faf9..ab23a5e 100644 --- a/secretservice/secretservice_linux.c +++ b/secretservice/secretservice_linux.c @@ -140,7 +140,8 @@ GError *list(char *** paths, char *** accts, unsigned int *list_l) { } void freeListData(char *** data, unsigned int length) { - for(int i=0; i Date: Tue, 12 Jul 2016 10:23:05 -0700 Subject: [PATCH 08/19] I think OSX tests were failing because it was a list against an empty keychain, checking whether that is the case by filling it first Signed-off-by: avaid96 --- osxkeychain/osxkeychain_darwin.go | 1 + osxkeychain/osxkeychain_darwin_test.go | 13 +++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/osxkeychain/osxkeychain_darwin.go b/osxkeychain/osxkeychain_darwin.go index 28c316d..267142a 100644 --- a/osxkeychain/osxkeychain_darwin.go +++ b/osxkeychain/osxkeychain_darwin.go @@ -104,6 +104,7 @@ func (h Osxkeychain) List() ([]string, []string, error) { if errMsg != nil { defer C.free(unsafe.Pointer(errMsg)) goMsg := C.GoString(errMsg) + goMsg = "Error is here" return nil, nil, errors.New(goMsg) } var listLen int diff --git a/osxkeychain/osxkeychain_darwin_test.go b/osxkeychain/osxkeychain_darwin_test.go index 5d21023..bfaa69c 100644 --- a/osxkeychain/osxkeychain_darwin_test.go +++ b/osxkeychain/osxkeychain_darwin_test.go @@ -11,7 +11,11 @@ func TestOSXKeychainHelper(t *testing.T) { Username: "foobar", Secret: "foobarbaz", } - + creds1 := &credentials.Credentials{ + ServerURL: "https://foobar.docker.io:2376/v2", + Username: "foobarbaz", + Secret: "foobar", + } helper := Osxkeychain{} if err := helper.Add(creds); err != nil { t.Fatal(err) @@ -33,17 +37,18 @@ func TestOSXKeychainHelper(t *testing.T) { if err := helper.Delete(creds.ServerURL); err != nil { t.Fatal(err) } - + helper.Add(creds); + defer helper.Delete(creds.ServerURL) paths, accts, err := helper.List() if err != nil || len(paths) == 0 || len(accts) == 0 { t.Fatal(err) } - helper.Add(creds) + helper.Add(creds1) newpaths, newaccts, err := helper.List() if len(newpaths)-len(paths) != 1 || len(newaccts)-len(accts) != 1 { t.Fatal(err) } - helper.Delete(creds.ServerURL) + helper.Delete(creds1.ServerURL) } func TestMissingCredentials(t *testing.T) { From 8fa18eb16ccf42051d21abddb27660176f790ae5 Mon Sep 17 00:00:00 2001 From: avaid96 Date: Wed, 13 Jul 2016 10:20:51 -0700 Subject: [PATCH 09/19] implementation on client side as well, complete with tests Signed-off-by: avaid96 --- client/client.go | 15 +++++++++++++-- client/client_test.go | 9 +++++++++ credentials/credentials.go | 4 +++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/client/client.go b/client/client.go index ddd30bb..759ae1d 100644 --- a/client/client.go +++ b/client/client.go @@ -55,11 +55,10 @@ func Get(program ProgramFunc, serverURL string) (*credentials.Credentials, error return resp, nil } -// Erase executes a program to remove the server credentails from the native store. +// Erase executes a program to remove the server credentials from the native store. func Erase(program ProgramFunc, serverURL string) error { cmd := program("erase") cmd.Input(strings.NewReader(serverURL)) - out, err := cmd.Output() if err != nil { t := strings.TrimSpace(string(out)) @@ -68,3 +67,15 @@ func Erase(program ProgramFunc, serverURL string) error { return nil } + +// List executes a program to remove the server credentials from the native store. +func List(program ProgramFunc) error { + cmd := program("list") + cmd.Input(strings.NewReader("garbage")) + out, err := cmd.Output() + if err != nil { + t := strings.TrimSpace(string(out)) + return fmt.Errorf("error listing credentials - err: %v, out: `%s`", err, t) + } + return nil +} \ No newline at end of file diff --git a/client/client_test.go b/client/client_test.go index 1f2ee53..1f8b4bd 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -70,6 +70,9 @@ func (m *mockProgram) Output() ([]byte, error) { default: return []byte("error storing credentials"), errProgramExited } + case "list": + return []byte(`{"Path":"e237574ae22fd53ddb9490dc1f72139946fd5372d42ba54d1eeb3ae5068fd22b","Username":"http://example.com/collections\u003cnotary_key\u003eSnapshot"}`), nil + } return []byte(fmt.Sprintf("unknown argument %q with %q", m.arg, inS)), errProgramExited @@ -190,3 +193,9 @@ func TestErase(t *testing.T) { t.Fatalf("Expected error for server %s, got nil", invalidServerAddress) } } + +func TestList(t *testing.T) { + if err := List(mockProgramFn); err != nil { + t.Fatal(err) + } +} diff --git a/credentials/credentials.go b/credentials/credentials.go index 8fc69c7..6d7259b 100644 --- a/credentials/credentials.go +++ b/credentials/credentials.go @@ -30,7 +30,7 @@ type KeyData struct { func Serve(helper Helper) { var err error if len(os.Args) != 2 { - err = fmt.Errorf("Usage: %s ", os.Args[0]) + err = fmt.Errorf("Usage: %s ", os.Args[0]) } if err == nil { @@ -52,6 +52,8 @@ func HandleCommand(helper Helper, key string, in io.Reader, out io.Writer) error return Get(helper, in, out) case "erase": return Erase(helper, in) + case "list": + return List(helper, out) } return fmt.Errorf("Unknown credential action `%s`", key) } From 029e094488a8154c6bbae9cec5cbd9c69f5b3cbb Mon Sep 17 00:00:00 2001 From: avaid96 Date: Wed, 13 Jul 2016 14:36:14 -0700 Subject: [PATCH 10/19] removed a semicolon and the placeholder for the error which we used to locate it. Seems like SecItemCopyMatching is giving an error for some reason- no error on local machine Signed-off-by: avaid96 --- osxkeychain/osxkeychain_darwin.go | 1 - osxkeychain/osxkeychain_darwin_test.go | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/osxkeychain/osxkeychain_darwin.go b/osxkeychain/osxkeychain_darwin.go index 267142a..28c316d 100644 --- a/osxkeychain/osxkeychain_darwin.go +++ b/osxkeychain/osxkeychain_darwin.go @@ -104,7 +104,6 @@ func (h Osxkeychain) List() ([]string, []string, error) { if errMsg != nil { defer C.free(unsafe.Pointer(errMsg)) goMsg := C.GoString(errMsg) - goMsg = "Error is here" return nil, nil, errors.New(goMsg) } var listLen int diff --git a/osxkeychain/osxkeychain_darwin_test.go b/osxkeychain/osxkeychain_darwin_test.go index bfaa69c..51ae1b4 100644 --- a/osxkeychain/osxkeychain_darwin_test.go +++ b/osxkeychain/osxkeychain_darwin_test.go @@ -37,18 +37,18 @@ func TestOSXKeychainHelper(t *testing.T) { if err := helper.Delete(creds.ServerURL); err != nil { t.Fatal(err) } - helper.Add(creds); + helper.Add(creds) defer helper.Delete(creds.ServerURL) paths, accts, err := helper.List() if err != nil || len(paths) == 0 || len(accts) == 0 { t.Fatal(err) } helper.Add(creds1) + defer helper.Delete(creds1.ServerURL) newpaths, newaccts, err := helper.List() if len(newpaths)-len(paths) != 1 || len(newaccts)-len(accts) != 1 { t.Fatal(err) } - helper.Delete(creds1.ServerURL) } func TestMissingCredentials(t *testing.T) { From b3ebaa455d56dbdcbebb3a6c1f815bd18ef8cbe1 Mon Sep 17 00:00:00 2001 From: avaid96 Date: Fri, 15 Jul 2016 17:32:47 -0700 Subject: [PATCH 11/19] trying to the OSX test to pass on Travis, it passes locally Signed-off-by: avaid96 --- osxkeychain/osxkeychain_darwin_test.go | 10 +++++----- wincred/wincred_windows.go | 8 ++++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/osxkeychain/osxkeychain_darwin_test.go b/osxkeychain/osxkeychain_darwin_test.go index 51ae1b4..3734d93 100644 --- a/osxkeychain/osxkeychain_darwin_test.go +++ b/osxkeychain/osxkeychain_darwin_test.go @@ -34,15 +34,15 @@ func TestOSXKeychainHelper(t *testing.T) { t.Fatalf("expected %s, got %s\n", "foobarbaz", secret) } - if err := helper.Delete(creds.ServerURL); err != nil { - t.Fatal(err) - } - helper.Add(creds) - defer helper.Delete(creds.ServerURL) paths, accts, err := helper.List() if err != nil || len(paths) == 0 || len(accts) == 0 { t.Fatal(err) } + + if err := helper.Delete(creds.ServerURL); err != nil { + t.Fatal(err) + } + helper.Add(creds1) defer helper.Delete(creds1.ServerURL) newpaths, newaccts, err := helper.List() diff --git a/wincred/wincred_windows.go b/wincred/wincred_windows.go index 0587cf0..134883c 100644 --- a/wincred/wincred_windows.go +++ b/wincred/wincred_windows.go @@ -37,3 +37,11 @@ func (h Wincred) Get(serverURL string) (string, string, error) { } return g.UserName, string(g.CredentialBlob), nil } + +func (h Wincred) List() ([]string, []string, error) { + accts, paths, err := winc.List() + if err != nil { + return err + } + return paths, accts, nil +} From 173fe2dbc2aaf203eab0e57aff61f03ec2a3c9c6 Mon Sep 17 00:00:00 2001 From: avaid96 Date: Fri, 15 Jul 2016 17:43:52 -0700 Subject: [PATCH 12/19] fixed a bug in the test for osx Signed-off-by: avaid96 --- osxkeychain/osxkeychain_darwin_test.go | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/osxkeychain/osxkeychain_darwin_test.go b/osxkeychain/osxkeychain_darwin_test.go index 3734d93..80e6f60 100644 --- a/osxkeychain/osxkeychain_darwin_test.go +++ b/osxkeychain/osxkeychain_darwin_test.go @@ -39,14 +39,17 @@ func TestOSXKeychainHelper(t *testing.T) { t.Fatal(err) } - if err := helper.Delete(creds.ServerURL); err != nil { - t.Fatal(err) - } - helper.Add(creds1) defer helper.Delete(creds1.ServerURL) newpaths, newaccts, err := helper.List() if len(newpaths)-len(paths) != 1 || len(newaccts)-len(accts) != 1 { + if(err == nil) { + t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), nil) + } + t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), err.Error()) + } + + if err := helper.Delete(creds.ServerURL); err != nil { t.Fatal(err) } } From b63a32e7a27ee1822ad1700b0d22af64b199e012 Mon Sep 17 00:00:00 2001 From: avaid96 Date: Fri, 15 Jul 2016 17:46:46 -0700 Subject: [PATCH 13/19] fixed another bug in the test for osx Signed-off-by: avaid96 --- osxkeychain/osxkeychain_darwin_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osxkeychain/osxkeychain_darwin_test.go b/osxkeychain/osxkeychain_darwin_test.go index 80e6f60..99efea9 100644 --- a/osxkeychain/osxkeychain_darwin_test.go +++ b/osxkeychain/osxkeychain_darwin_test.go @@ -44,7 +44,7 @@ func TestOSXKeychainHelper(t *testing.T) { newpaths, newaccts, err := helper.List() if len(newpaths)-len(paths) != 1 || len(newaccts)-len(accts) != 1 { if(err == nil) { - t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), nil) + t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), "") } t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), err.Error()) } From 5b764cc13ae8317e1a4594519a7da28b5a8fdad4 Mon Sep 17 00:00:00 2001 From: avaid96 Date: Sat, 16 Jul 2016 11:59:43 -0700 Subject: [PATCH 14/19] changes to wincred, completes list functionality in windows Signed-off-by: avaid96 --- .../danieljoos/wincred/conversion.go | 1 - .../github.com/danieljoos/wincred/native.go | 40 +++++++++++++++++-- .../github.com/danieljoos/wincred/wincred.go | 5 +++ wincred/wincred_windows.go | 8 +++- wincred/wincred_windows_test.go | 15 +++++++ 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/vendor/github.com/danieljoos/wincred/conversion.go b/vendor/github.com/danieljoos/wincred/conversion.go index 36e67b1..dc64718 100644 --- a/vendor/github.com/danieljoos/wincred/conversion.go +++ b/vendor/github.com/danieljoos/wincred/conversion.go @@ -58,7 +58,6 @@ func nativeToCredential(cred *nativeCREDENTIAL) (result *Credential) { resultAttr.Keyword = utf16PtrToString(attr.Keyword) resultAttr.Value = C.GoBytes(unsafe.Pointer(attr.Value), C.int(attr.ValueSize)) } - return result } diff --git a/vendor/github.com/danieljoos/wincred/native.go b/vendor/github.com/danieljoos/wincred/native.go index 16e91ad..5fb8bb4 100644 --- a/vendor/github.com/danieljoos/wincred/native.go +++ b/vendor/github.com/danieljoos/wincred/native.go @@ -1,6 +1,7 @@ package wincred import ( + "C" "syscall" "unsafe" ) @@ -8,10 +9,11 @@ import ( var ( modadvapi32 = syscall.NewLazyDLL("advapi32.dll") - procCredRead = modadvapi32.NewProc("CredReadW") - procCredWrite = modadvapi32.NewProc("CredWriteW") - procCredDelete = modadvapi32.NewProc("CredDeleteW") - procCredFree = modadvapi32.NewProc("CredFree") + procCredRead = modadvapi32.NewProc("CredReadW") + procCredWrite = modadvapi32.NewProc("CredWriteW") + procCredDelete = modadvapi32.NewProc("CredDeleteW") + procCredFree = modadvapi32.NewProc("CredFree") + procCredEnumerate = modadvapi32.NewProc("CredEnumerateW") ) // http://msdn.microsoft.com/en-us/library/windows/desktop/aa374788(v=vs.85).aspx @@ -97,3 +99,33 @@ func nativeCredDelete(cred *Credential, typ nativeCRED_TYPE) error { return nil } + +// https://msdn.microsoft.com/en-us/library/windows/desktop/aa374794(v=vs.85).aspx +func nativeCredEnumerate(filter string, all bool) ([]*Credential, error) { + var count int + var pcreds uintptr + var filterPtr uintptr + if !all { + filterUtf16Ptr, _ := syscall.UTF16PtrFromString(filter) + filterPtr = uintptr(unsafe.Pointer(filterUtf16Ptr)) + } else { + filterPtr = 0 + } + ret, _, err := procCredEnumerate.Call( + filterPtr, + 0, + uintptr(unsafe.Pointer(&count)), + uintptr(unsafe.Pointer(&pcreds)), + ) + if ret == 0 { + return nil, err + } + defer procCredFree.Call(pcreds) + pcredsSlice := (*[1 << 30]uintptr)(unsafe.Pointer(pcreds))[:count:count] + creds := make([]*Credential, count) + for i := range creds { + creds[i] = nativeToCredential((*nativeCREDENTIAL)(unsafe.Pointer(pcredsSlice[i]))) + } + + return creds, nil +} diff --git a/vendor/github.com/danieljoos/wincred/wincred.go b/vendor/github.com/danieljoos/wincred/wincred.go index bdcf609..5044520 100644 --- a/vendor/github.com/danieljoos/wincred/wincred.go +++ b/vendor/github.com/danieljoos/wincred/wincred.go @@ -67,3 +67,8 @@ func (t *DomainPassword) Delete() (err error) { func (t *DomainPassword) SetPassword(pw string) { t.CredentialBlob = utf16ToByte(syscall.StringToUTF16(pw)) } + +// List the contents of the Credentials store +func List() ([]*Credential, error) { + return nativeCredEnumerate("", true) +} diff --git a/wincred/wincred_windows.go b/wincred/wincred_windows.go index 134883c..e79b2e9 100644 --- a/wincred/wincred_windows.go +++ b/wincred/wincred_windows.go @@ -39,9 +39,15 @@ func (h Wincred) Get(serverURL string) (string, string, error) { } func (h Wincred) List() ([]string, []string, error) { - accts, paths, err := winc.List() + creds, err := winc.List() + paths := make([]string, len(creds)) + accts := make([]string, len(creds)) if err != nil { return err } + for i := range(creds) { + paths[i] = creds[i].TargetName + accts[i] = creds[i].UserName + } return paths, accts, nil } diff --git a/wincred/wincred_windows_test.go b/wincred/wincred_windows_test.go index b2ff86f..a37ec04 100644 --- a/wincred/wincred_windows_test.go +++ b/wincred/wincred_windows_test.go @@ -31,6 +31,21 @@ func TestWinCredHelper(t *testing.T) { t.Fatalf("expected %s, got %s\n", "foobarbaz", secret) } + paths, accts, err := helper.List() + if err != nil || len(paths) == 0 || len(accts) == 0 { + t.Fatal(err) + } + + helper.Add(creds1) + defer helper.Delete(creds1.ServerURL) + newpaths, newaccts, err := helper.List() + if len(newpaths)-len(paths) != 1 || len(newaccts)-len(accts) != 1 { + if(err == nil) { + t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), "") + } + t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), err.Error()) + } + if err := helper.Delete(creds.ServerURL); err != nil { t.Fatal(err) } From b0c64357eb222f7c39457cead8177e489ef93ccb Mon Sep 17 00:00:00 2001 From: avaid96 Date: Sat, 16 Jul 2016 12:07:50 -0700 Subject: [PATCH 15/19] fixed issue with the windows test Signed-off-by: avaid96 --- wincred/wincred_windows_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/wincred/wincred_windows_test.go b/wincred/wincred_windows_test.go index a37ec04..8059617 100644 --- a/wincred/wincred_windows_test.go +++ b/wincred/wincred_windows_test.go @@ -12,6 +12,11 @@ func TestWinCredHelper(t *testing.T) { Username: "foobar", Secret: "foobarbaz", } + creds1 := &credentials.Credentials{ + ServerURL: "https://foobar.docker.io:2376/v2", + Username: "foobarbaz", + Secret: "foobar", + } helper := Wincred{} if err := helper.Add(creds); err != nil { From cf9b6df432de71d40882a73433580cb63073397c Mon Sep 17 00:00:00 2001 From: avaid96 Date: Sat, 16 Jul 2016 12:08:55 -0700 Subject: [PATCH 16/19] fixed issue with wincred Signed-off-by: avaid96 --- wincred/wincred_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wincred/wincred_windows.go b/wincred/wincred_windows.go index e79b2e9..8ca8001 100644 --- a/wincred/wincred_windows.go +++ b/wincred/wincred_windows.go @@ -43,7 +43,7 @@ func (h Wincred) List() ([]string, []string, error) { paths := make([]string, len(creds)) accts := make([]string, len(creds)) if err != nil { - return err + nil, nil, return err } for i := range(creds) { paths[i] = creds[i].TargetName From 9e96a4905d2bec32cf08450095aedebcc061c97c Mon Sep 17 00:00:00 2001 From: avaid96 Date: Sat, 16 Jul 2016 12:09:31 -0700 Subject: [PATCH 17/19] fixed issue with wincred Signed-off-by: avaid96 --- wincred/wincred_windows.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wincred/wincred_windows.go b/wincred/wincred_windows.go index 8ca8001..f47e9ac 100644 --- a/wincred/wincred_windows.go +++ b/wincred/wincred_windows.go @@ -43,7 +43,7 @@ func (h Wincred) List() ([]string, []string, error) { paths := make([]string, len(creds)) accts := make([]string, len(creds)) if err != nil { - nil, nil, return err + return nil, nil, err } for i := range(creds) { paths[i] = creds[i].TargetName From c2abee4c0c1d37a8732b4844606b17100a7795df Mon Sep 17 00:00:00 2001 From: Avi Vaid Date: Sat, 16 Jul 2016 12:18:03 -0700 Subject: [PATCH 18/19] go fmt in windows files Signed-off-by: Avi Vaid --- wincred/wincred_windows.go | 2 +- wincred/wincred_windows_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/wincred/wincred_windows.go b/wincred/wincred_windows.go index f47e9ac..8b36814 100644 --- a/wincred/wincred_windows.go +++ b/wincred/wincred_windows.go @@ -45,7 +45,7 @@ func (h Wincred) List() ([]string, []string, error) { if err != nil { return nil, nil, err } - for i := range(creds) { + for i := range creds { paths[i] = creds[i].TargetName accts[i] = creds[i].UserName } diff --git a/wincred/wincred_windows_test.go b/wincred/wincred_windows_test.go index 8059617..1634156 100644 --- a/wincred/wincred_windows_test.go +++ b/wincred/wincred_windows_test.go @@ -45,7 +45,7 @@ func TestWinCredHelper(t *testing.T) { defer helper.Delete(creds1.ServerURL) newpaths, newaccts, err := helper.List() if len(newpaths)-len(paths) != 1 || len(newaccts)-len(accts) != 1 { - if(err == nil) { + if err == nil { t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), "") } t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), err.Error()) From f1498a052407fe96254d20d6272c51e70a93e0ea Mon Sep 17 00:00:00 2001 From: avaid96 Date: Sat, 16 Jul 2016 12:19:47 -0700 Subject: [PATCH 19/19] go fmt is all osx files and general files Signed-off-by: avaid96 --- client/client.go | 2 +- osxkeychain/osxkeychain_darwin_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/client.go b/client/client.go index 759ae1d..469754c 100644 --- a/client/client.go +++ b/client/client.go @@ -78,4 +78,4 @@ func List(program ProgramFunc) error { return fmt.Errorf("error listing credentials - err: %v, out: `%s`", err, t) } return nil -} \ No newline at end of file +} diff --git a/osxkeychain/osxkeychain_darwin_test.go b/osxkeychain/osxkeychain_darwin_test.go index 99efea9..7dcfb06 100644 --- a/osxkeychain/osxkeychain_darwin_test.go +++ b/osxkeychain/osxkeychain_darwin_test.go @@ -43,7 +43,7 @@ func TestOSXKeychainHelper(t *testing.T) { defer helper.Delete(creds1.ServerURL) newpaths, newaccts, err := helper.List() if len(newpaths)-len(paths) != 1 || len(newaccts)-len(accts) != 1 { - if(err == nil) { + if err == nil { t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), "") } t.Fatalf("Error: len(newpaths): %d, len(paths): %d\n len(newaccts): %d, len(accts): %d\n Error= %s", len(newpaths), len(paths), len(newaccts), len(accts), err.Error())