#
|
# (C) Copyright 2014-18 Enthought, Inc., Austin, TX
|
# All right reserved.
|
#
|
# This file is open source software distributed according to the terms in
|
# LICENSE.txt
|
#
|
from __future__ import absolute_import
|
|
import ctypes
|
from ctypes import POINTER, Structure, c_void_p, c_wchar_p, c_char_p, cast
|
from ctypes.wintypes import (
|
BOOL, DWORD, FILETIME, LPCWSTR)
|
|
from win32ctypes.core.compat import is_text
|
from ._common import LPBYTE, _PyBytes_FromStringAndSize
|
from ._util import function_factory, check_zero_factory, dlls
|
from ._nl_support import _GetACP
|
|
|
SUPPORTED_CREDKEYS = set((
|
u'Type', u'TargetName', u'Persist',
|
u'UserName', u'Comment', u'CredentialBlob'))
|
|
|
class CREDENTIAL(Structure):
|
_fields_ = [
|
("Flags", DWORD),
|
("Type", DWORD),
|
("TargetName", c_wchar_p),
|
("Comment", c_wchar_p),
|
("LastWritten", FILETIME),
|
("CredentialBlobSize", DWORD),
|
("CredentialBlob", LPBYTE),
|
("Persist", DWORD),
|
("_DO_NOT_USE_AttributeCount", DWORD),
|
("__DO_NOT_USE_Attribute", c_void_p),
|
("TargetAlias", c_wchar_p),
|
("UserName", c_wchar_p)]
|
|
@classmethod
|
def fromdict(cls, credential, flags=0):
|
unsupported = set(credential.keys()) - SUPPORTED_CREDKEYS
|
if len(unsupported):
|
raise ValueError("Unsupported keys: {0}".format(unsupported))
|
if flags != 0:
|
raise ValueError("flag != 0 not yet supported")
|
|
c_creds = cls()
|
c_pcreds = PCREDENTIAL(c_creds)
|
|
# zero-out memory
|
ctypes.memset(c_pcreds, 0, ctypes.sizeof(c_creds))
|
|
for key in SUPPORTED_CREDKEYS:
|
if key in credential:
|
if key != 'CredentialBlob':
|
setattr(c_creds, key, credential[key])
|
else:
|
blob = make_unicode(credential['CredentialBlob'])
|
blob_data = ctypes.create_unicode_buffer(blob)
|
# Create_unicode_buffer adds a NULL at the end of the
|
# string we do not want that.
|
c_creds.CredentialBlobSize = \
|
ctypes.sizeof(blob_data) - \
|
ctypes.sizeof(ctypes.c_wchar)
|
c_creds.CredentialBlob = ctypes.cast(blob_data, LPBYTE)
|
return c_creds
|
|
|
PCREDENTIAL = POINTER(CREDENTIAL)
|
|
|
def make_unicode(password):
|
""" Convert the input string to unicode.
|
|
"""
|
if is_text(password):
|
return password
|
else:
|
code_page = _GetACP()
|
return password.decode(encoding=str(code_page), errors='strict')
|
|
|
def credential2dict(creds):
|
credential = {}
|
for key in SUPPORTED_CREDKEYS:
|
if key != u'CredentialBlob':
|
credential[key] = getattr(creds, key)
|
else:
|
blob = _PyBytes_FromStringAndSize(
|
cast(creds.CredentialBlob, c_char_p),
|
creds.CredentialBlobSize)
|
credential[u'CredentialBlob'] = blob
|
return credential
|
|
|
_CredWrite = function_factory(
|
dlls.advapi32.CredWriteW,
|
[PCREDENTIAL, DWORD],
|
BOOL,
|
check_zero_factory("CredWrite"))
|
|
_CredRead = function_factory(
|
dlls.advapi32.CredReadW,
|
[LPCWSTR, DWORD, DWORD, POINTER(PCREDENTIAL)],
|
BOOL,
|
check_zero_factory("CredRead"))
|
|
_CredDelete = function_factory(
|
dlls.advapi32.CredDeleteW,
|
[LPCWSTR, DWORD, DWORD],
|
BOOL,
|
check_zero_factory("CredDelete"))
|
|
_CredFree = function_factory(dlls.advapi32.CredFree, [PCREDENTIAL])
|