From a994ca1d54472fc9986ad57efbb344109b192b5c Mon Sep 17 00:00:00 2001 From: Daniel Joos Date: Wed, 7 Sep 2016 09:07:00 +0200 Subject: [PATCH 1/2] Updated `vendor` pkg: `github.com/danieljoos/wincred` This includes the following changes: - Removed need for `C` - Added some null checks to avoid possible panics - `List` returns an empty list instead of an error, in case no credentials are installed on the system Signed-off-by: Daniel Joos --- .../danieljoos/wincred/conversion.go | 24 ++++++++++++++++--- .../github.com/danieljoos/wincred/native.go | 18 +++++++++----- .../github.com/danieljoos/wincred/wincred.go | 8 ++++++- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/vendor/github.com/danieljoos/wincred/conversion.go b/vendor/github.com/danieljoos/wincred/conversion.go index dc64718..e36f876 100644 --- a/vendor/github.com/danieljoos/wincred/conversion.go +++ b/vendor/github.com/danieljoos/wincred/conversion.go @@ -1,7 +1,6 @@ package wincred import ( - "C" "encoding/binary" "reflect" "syscall" @@ -10,6 +9,8 @@ import ( "unsafe" ) +var nullPointer = unsafe.Pointer(uintptr(0)) + // Create a Go string using a pointer to a zero-terminated UTF 16 encoded string. // See github.com/AllenDang/w32 func utf16PtrToString(wstr *uint16) string { @@ -36,8 +37,22 @@ func utf16ToByte(wstr []uint16) (result []byte) { return } +// Copies the given C byte array to a Go byte array (see `C.GoBytes`) +func goBytes(src unsafe.Pointer, len uint32) []byte { + if src == nullPointer { + return []byte{} + } + slice := (*[1 << 30]byte)(src)[0:len] + rv := make([]byte, len) + copy(rv, slice) + return rv[:] +} + // Convert the given CREDENTIAL struct to a more usable structure func nativeToCredential(cred *nativeCREDENTIAL) (result *Credential) { + if unsafe.Pointer(cred) == nullPointer { + return nil + } result = new(Credential) result.Comment = utf16PtrToString(cred.Comment) result.TargetName = utf16PtrToString(cred.TargetName) @@ -45,7 +60,7 @@ func nativeToCredential(cred *nativeCREDENTIAL) (result *Credential) { result.UserName = utf16PtrToString(cred.UserName) result.LastWritten = time.Unix(0, cred.LastWritten.Nanoseconds()) result.Persist = CredentialPersistence(cred.Persist) - result.CredentialBlob = C.GoBytes(unsafe.Pointer(cred.CredentialBlob), C.int(cred.CredentialBlobSize)) + result.CredentialBlob = goBytes(unsafe.Pointer(cred.CredentialBlob), cred.CredentialBlobSize) result.Attributes = make([]CredentialAttribute, cred.AttributeCount) attrSliceHeader := reflect.SliceHeader{ Data: cred.Attributes, @@ -56,7 +71,7 @@ func nativeToCredential(cred *nativeCREDENTIAL) (result *Credential) { for i, attr := range attrSlice { resultAttr := &result.Attributes[i] resultAttr.Keyword = utf16PtrToString(attr.Keyword) - resultAttr.Value = C.GoBytes(unsafe.Pointer(attr.Value), C.int(attr.ValueSize)) + resultAttr.Value = goBytes(unsafe.Pointer(attr.Value), attr.ValueSize) } return result } @@ -64,6 +79,9 @@ func nativeToCredential(cred *nativeCREDENTIAL) (result *Credential) { // Convert the given Credential object back to a CREDENTIAL struct, which can be used for calling the // Windows APIs func nativeFromCredential(cred *Credential) (result *nativeCREDENTIAL) { + if cred == nil { + return nil + } result = new(nativeCREDENTIAL) result.Flags = 0 result.Type = 0 diff --git a/vendor/github.com/danieljoos/wincred/native.go b/vendor/github.com/danieljoos/wincred/native.go index 5fb8bb4..55926c8 100644 --- a/vendor/github.com/danieljoos/wincred/native.go +++ b/vendor/github.com/danieljoos/wincred/native.go @@ -1,7 +1,6 @@ package wincred import ( - "C" "syscall" "unsafe" ) @@ -9,13 +8,18 @@ import ( var ( modadvapi32 = syscall.NewLazyDLL("advapi32.dll") - procCredRead = modadvapi32.NewProc("CredReadW") - procCredWrite = modadvapi32.NewProc("CredWriteW") - procCredDelete = modadvapi32.NewProc("CredDeleteW") - procCredFree = modadvapi32.NewProc("CredFree") - procCredEnumerate = modadvapi32.NewProc("CredEnumerateW") + procCredRead proc = modadvapi32.NewProc("CredReadW") + procCredWrite proc = modadvapi32.NewProc("CredWriteW") + procCredDelete proc = modadvapi32.NewProc("CredDeleteW") + procCredFree proc = modadvapi32.NewProc("CredFree") + procCredEnumerate proc = modadvapi32.NewProc("CredEnumerateW") ) +// Interface for syscall.Proc: helps testing +type proc interface { + Call(a ...uintptr) (r1, r2 uintptr, lastErr error) +} + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa374788(v=vs.85).aspx type nativeCREDENTIAL struct { Flags uint32 @@ -50,6 +54,8 @@ const ( naCRED_TYPE_DOMAIN_VISIBLE_PASSWORD nativeCRED_TYPE = 0x4 naCRED_TYPE_GENERIC_CERTIFICATE nativeCRED_TYPE = 0x5 naCRED_TYPE_DOMAIN_EXTENDED nativeCRED_TYPE = 0x6 + + naERROR_NOT_FOUND = "Element not found." ) // http://msdn.microsoft.com/en-us/library/windows/desktop/aa374804(v=vs.85).aspx diff --git a/vendor/github.com/danieljoos/wincred/wincred.go b/vendor/github.com/danieljoos/wincred/wincred.go index 5044520..ac5d4a7 100644 --- a/vendor/github.com/danieljoos/wincred/wincred.go +++ b/vendor/github.com/danieljoos/wincred/wincred.go @@ -70,5 +70,11 @@ func (t *DomainPassword) SetPassword(pw string) { // List the contents of the Credentials store func List() ([]*Credential, error) { - return nativeCredEnumerate("", true) + creds, err := nativeCredEnumerate("", true) + if err != nil && err.Error() == naERROR_NOT_FOUND { + // Ignore ERROR_NOT_FOUND and return an empty list instead + creds = []*Credential{} + err = nil + } + return creds, err } From cfbce1c8455cbf29978fab2c2b9ccb65550662cd Mon Sep 17 00:00:00 2001 From: Daniel Joos Date: Wed, 7 Sep 2016 09:28:21 +0200 Subject: [PATCH 2/2] Removed unnecessary lines in `wincred_windows.go` Those lines seem to be left from the last merge. They cause build errors on Windows. Signed-off-by: Daniel Joos --- wincred/wincred_windows.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/wincred/wincred_windows.go b/wincred/wincred_windows.go index fc8da99..294c939 100644 --- a/wincred/wincred_windows.go +++ b/wincred/wincred_windows.go @@ -41,8 +41,6 @@ func (h Wincred) Get(serverURL string) (string, string, error) { // List returns the stored URLs and corresponding usernames. func (h Wincred) List() (map[string]string, error) { creds, err := winc.List() - paths := make([]string, len(creds)) - accts := make([]string, len(creds)) if err != nil { return nil, err }