1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#
# (C) Copyright 2014 Enthought, Inc., Austin, TX
# All right reserved.
#
# This file is open source software distributed according to the terms in
# LICENSE.txt
#
""" Interface to credentials management functions. """
from win32ctypes.core import _authentication, _common, _backend
from win32ctypes.pywin32.pywintypes import pywin32error as _pywin32error
 
CRED_TYPE_GENERIC = 0x1
CRED_PERSIST_SESSION = 0x1
CRED_PERSIST_LOCAL_MACHINE = 0x2
CRED_PERSIST_ENTERPRISE = 0x3
CRED_PRESERVE_CREDENTIAL_BLOB = 0
CRED_ENUMERATE_ALL_CREDENTIALS = 0x1
 
 
def CredWrite(Credential, Flags=CRED_PRESERVE_CREDENTIAL_BLOB):
    """ Creates or updates a stored credential.
 
    Parameters
    ----------
    Credential : dict
        A dictionary corresponding to the PyWin32 ``PyCREDENTIAL``
        structure.
    Flags : int
        Always pass ``CRED_PRESERVE_CREDENTIAL_BLOB`` (i.e. 0).
 
    """
    c_creds = _authentication.CREDENTIAL.fromdict(Credential, Flags)
    c_pcreds = _authentication.PCREDENTIAL(c_creds)
    with _pywin32error():
        _authentication._CredWrite(c_pcreds, 0)
 
 
def CredRead(TargetName, Type, Flags=0):
    """ Retrieves a stored credential.
 
    Parameters
    ----------
    TargetName : unicode
        The target name to fetch from the keyring.
    Type : int
        One of the CRED_TYPE_* constants.
    Flags : int
        Reserved, always use 0.
 
    Returns
    -------
    credentials : dict
        ``None`` if the target name was not found or A dictionary
        corresponding to the PyWin32 ``PyCREDENTIAL`` structure.
 
    """
    if Type != CRED_TYPE_GENERIC:
        raise ValueError("Type != CRED_TYPE_GENERIC not yet supported")
 
    flag = 0
    with _pywin32error():
        if _backend == 'cffi':
            ppcreds = _authentication.PPCREDENTIAL()
            _authentication._CredRead(TargetName, Type, flag, ppcreds)
            pcreds = _common.dereference(ppcreds)
        else:
            pcreds = _authentication.PCREDENTIAL()
            _authentication._CredRead(
                TargetName, Type, flag, _common.byreference(pcreds))
    try:
        return _authentication.credential2dict(_common.dereference(pcreds))
    finally:
        _authentication._CredFree(pcreds)
 
 
def CredDelete(TargetName, Type, Flags=0):
    """ Remove the given target name from the stored credentials.
 
    Parameters
    ----------
    TargetName : unicode
        The target name to fetch from the keyring.
    Type : int
        One of the CRED_TYPE_* constants.
    Flags : int
        Reserved, always use 0.
 
    """
    if not Type == CRED_TYPE_GENERIC:
        raise ValueError("Type != CRED_TYPE_GENERIC not yet supported.")
    with _pywin32error():
        _authentication._CredDelete(TargetName, Type, 0)
 
 
def CredEnumerate(Filter=None, Flags=0):
    """ Remove the given target name from the stored credentials.
 
    Parameters
    ----------
    Filter : unicode
        Matches credentials' target names by prefix, can be None.
    Flags : int
        When set to CRED_ENUMERATE_ALL_CREDENTIALS enumerates all of
        the credentials in the user's credential set but in that
        case the Filter parameter should be NULL, an error is
        raised otherwise
 
    Returns
    -------
    credentials : list
        Returns a sequence of CREDENTIAL dictionaries.
 
    """
    with _pywin32error():
        if _backend == 'cffi':
            pcount = _common.PDWORD()
            pppcredential = _authentication.PPPCREDENTIAL()
            _authentication._CredEnumerate(
                Filter, Flags, pcount, pppcredential)
            count = pcount[0]
            data = _common.dereference(
                _common.ffi.cast(f"PCREDENTIAL*[{count}]", pppcredential))
            memory = _common.dereference(pppcredential)
        else:
            import ctypes
            count = _authentication.DWORD()
            pcredential = _authentication.PCREDENTIAL()
            ppcredential = ctypes.pointer(pcredential)
            pppcredential = ctypes.pointer(ppcredential)
            _authentication._CredEnumerate(
                Filter, Flags, _common.byreference(count), pppcredential)
            count = count.value
            data = _common.dereference(
                _common.cast(
                    ppcredential,
                    _common.POINTER(_authentication.PCREDENTIAL*count)))
            memory = pcredential
    try:
        result = []
        for i in range(count):
            credential = _common.dereference(data[i])
            result.append(_authentication.credential2dict(credential))
        return result
    finally:
        _authentication._CredFree(memory)