mirror of
https://github.com/docker/docker-credential-helpers.git
synced 2026-06-13 16:01:28 +05:30
a994ca1d54
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 <daniel@joosweb.de>
138 lines
3.7 KiB
Go
138 lines
3.7 KiB
Go
package wincred
|
|
|
|
import (
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
var (
|
|
modadvapi32 = syscall.NewLazyDLL("advapi32.dll")
|
|
|
|
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
|
|
Type uint32
|
|
TargetName *uint16
|
|
Comment *uint16
|
|
LastWritten syscall.Filetime
|
|
CredentialBlobSize uint32
|
|
CredentialBlob uintptr
|
|
Persist uint32
|
|
AttributeCount uint32
|
|
Attributes uintptr
|
|
TargetAlias *uint16
|
|
UserName *uint16
|
|
}
|
|
|
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa374790(v=vs.85).aspx
|
|
type nativeCREDENTIAL_ATTRIBUTE struct {
|
|
Keyword *uint16
|
|
Flags uint32
|
|
ValueSize uint32
|
|
Value uintptr
|
|
}
|
|
|
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa374788(v=vs.85).aspx
|
|
type nativeCRED_TYPE uint32
|
|
|
|
const (
|
|
naCRED_TYPE_GENERIC nativeCRED_TYPE = 0x1
|
|
naCRED_TYPE_DOMAIN_PASSWORD nativeCRED_TYPE = 0x2
|
|
naCRED_TYPE_DOMAIN_CERTIFICATE nativeCRED_TYPE = 0x3
|
|
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
|
|
func nativeCredRead(targetName string, typ nativeCRED_TYPE) (*Credential, error) {
|
|
var pcred uintptr
|
|
targetNamePtr, _ := syscall.UTF16PtrFromString(targetName)
|
|
ret, _, err := procCredRead.Call(
|
|
uintptr(unsafe.Pointer(targetNamePtr)),
|
|
uintptr(typ),
|
|
0,
|
|
uintptr(unsafe.Pointer(&pcred)),
|
|
)
|
|
if ret == 0 {
|
|
return nil, err
|
|
}
|
|
defer procCredFree.Call(pcred)
|
|
|
|
return nativeToCredential((*nativeCREDENTIAL)(unsafe.Pointer(pcred))), nil
|
|
}
|
|
|
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa375187(v=vs.85).aspx
|
|
func nativeCredWrite(cred *Credential, typ nativeCRED_TYPE) error {
|
|
ncred := nativeFromCredential(cred)
|
|
ncred.Type = uint32(typ)
|
|
ret, _, err := procCredWrite.Call(
|
|
uintptr(unsafe.Pointer(ncred)),
|
|
0,
|
|
)
|
|
if ret == 0 {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa374787(v=vs.85).aspx
|
|
func nativeCredDelete(cred *Credential, typ nativeCRED_TYPE) error {
|
|
targetNamePtr, _ := syscall.UTF16PtrFromString(cred.TargetName)
|
|
ret, _, err := procCredDelete.Call(
|
|
uintptr(unsafe.Pointer(targetNamePtr)),
|
|
uintptr(typ),
|
|
0,
|
|
)
|
|
if ret == 0 {
|
|
return err
|
|
}
|
|
|
|
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
|
|
}
|