# # (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])