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 }