-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathNativeMethods.cs
More file actions
199 lines (185 loc) · 11 KB
/
NativeMethods.cs
File metadata and controls
199 lines (185 loc) · 11 KB
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace PSWindowsUpdate
{
public class NativeMethods
{
/// <summary>
/// The CredRead function reads a credential from the user's credential set.
/// The credential set used is the one associated with the logon session of the current token.
/// The token must not have the user's SID disabled.
/// </summary>
/// <remarks>
/// If the value of the Type member of the CREDENTIAL structure specified by the Credential parameter is
/// CRED_TYPE_DOMAIN_EXTENDED, a namespace must be specified in the target name. This function can return only one
/// credential of the specified type.
/// </remarks>
/// <param name="target">Pointer to a null-terminated string that contains the name of the credential to read.</param>
/// <param name="type">Type of the credential to read. Type must be one of the CRED_TYPE_* defined types.</param>
/// <param name="reservedFlag">Currently reserved and must be zero.</param>
/// <param name="credentialPtr">
/// Pointer to a single allocated block buffer to return the credential.
/// Any pointers contained within the buffer are pointers to locations within this single allocated block.
/// The single returned buffer must be freed by calling CredFree.
/// </param>
/// <returns>The function returns TRUE on success and FALSE on failure.</returns>
[DllImport("Advapi32.dll", EntryPoint = "CredReadW", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool CredRead(
string target,
CredentialType type,
int reservedFlag,
out IntPtr credentialPtr);
/// <summary>
/// The CredWrite function creates a new credential or modifies an existing credential in the user's credential set.
/// The new credential is associated with the logon session of the current token.
/// The token must not have the user's security identifier (SID) disabled.
/// </summary>
/// <remarks>
/// This function creates a credential if a credential with the specified TargetName and Type does not exist. If a
/// credential with the specified TargetName and Type exists, the new specified credential replaces the existing one.
/// When this function writes a CRED_TYPE_CERTIFICATE credential, the Credential->CredentialBlob member specifies the
/// PIN protecting the private key of the certificate specified by the Credential->UserName member. The credential
/// manager does not maintain the PIN. Rather, the PIN is passed to the cryptographic service provider (CSP) indicated
/// on the certificate for later use by the CSP and the authentication packages. The CSP defines the lifetime of the
/// PIN. Most CSPs flush the PIN when the smart card removal from the smart card reader.
/// If the value of the Type member of the CREDENTIAL structure specified by the Credential parameter is
/// CRED_TYPE_DOMAIN_EXTENDED, a namespace must be specified in the target name. This function does not support writing
/// to target names that contain wildcards.
/// </remarks>
/// <param name="userCredential">A pointer to the CREDENTIAL structure to be written.</param>
/// <param name="flags">Flags that control the function's operation. The following flag is defined.</param>
/// <returns>If the function succeeds, the function returns TRUE, if the function fails, it returns FALSE. </returns>
[DllImport("Advapi32.dll", EntryPoint = "CredWriteW", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool CredWrite([In] ref CREDENTIAL userCredential, [In] uint flags);
/// <summary>
/// The CredFree function frees a buffer returned by any of the credentials management functions.
/// </summary>
/// <param name="cred">Pointer to the buffer to be freed.</param>
[DllImport("Advapi32.dll", SetLastError = true)]
internal static extern void CredFree([In] IntPtr cred);
/// <summary>
/// The CredDelete function deletes a credential from the user's credential set.
/// The credential set used is the one associated with the logon session of the current token.
/// The token must not have the user's SID disabled.
/// </summary>
/// <param name="target">Pointer to a null-terminated string that contains the name of the credential to delete.</param>
/// <param name="type">
/// Type of the credential to delete. Must be one of the CRED_TYPE_* defined types.
/// For a list of the defined types, see the Type member of the CREDENTIAL structure.
/// If the value of this parameter is CRED_TYPE_DOMAIN_EXTENDED,
/// this function can delete a credential that specifies a user name when there are multiple credentials for the same
/// target. The value of the TargetName parameter must specify the user name as Target|UserName.
/// </param>
/// <param name="flags">Reserved and must be zero.</param>
/// <returns>The function returns TRUE on success and FALSE on failure.</returns>
[DllImport("Advapi32.dll", EntryPoint = "CredDeleteW", CharSet = CharSet.Unicode)]
internal static extern bool CredDelete(StringBuilder target, CredentialType type, int flags);
/// <summary>
/// Enumerate credentials in the credential store
/// signature: BOOL CredEnumerate (
/// _In_ LPCTSTR Filter,
/// _In_ DWORD Flags,
/// _Out_ DWORD *Count,
/// _Out_ PCREDENTIAL **Credentials
/// );
/// <param name="filter">[in]
/// Pointer to a null-terminated string that contains the filter for the returned credentials.Only credentials with a TargetName matching the filter will be returned.The filter specifies a name prefix followed by an asterisk.For instance, the filter "FRED*" will return all credentials with a TargetName beginning with the string "FRED".
/// If NULL is specified, all credentials will be returned.</param>
/// <param name="flag">[in]
/// The value of this parameter can be zero or more of the following values combined with a bitwise-OR operation.
/// Value Meaning
/// CRED_ENUMERATE_ALL_CREDENTIALS 0x1
/// This function enumerates all of the credentials in the user's credential set. The target name of each credential is returned in the "namespace:attribute=target" format. If this flag is set and the Filter parameter is not NULL, the function fails and returns ERROR_INVALID_FLAGS.
/// Windows Server 2003 and Windows XP: This flag is not supported.
/// </param>
/// <param name="count">[out] Count of the credentials returned in the Credentials array.</param>
/// <param name="pCredentials"> [out]
/// Pointer to an array of pointers to credentials.The returned credential is a single allocated block. Any pointers contained within the buffer are pointers to locations within this single allocated block.The single returned buffer must be freed by calling CredFree.
/// Return value
/// </param>
/// <returns>
/// The function returns TRUE on success and FALSE on failure. The GetLastError function can be called to get a more specific status code.The following status codes can be returned.
/// Return code/value Description
/// ERROR_NOT_FOUND
/// 1168 (0x490)
/// No credential exists matching the specified Filter.
/// ERROR_NO_SUCH_LOGON_SESSION
/// 1312 (0x520)
/// The logon session does not exist or there is no credential set associated with this logon session. Network logon sessions do not have an associated credential set.
/// ERROR_INVALID_FLAGS
/// 1004 (0x3EC)
/// A flag that is not valid was specified for the Flags parameter, or CRED_ENUMERATE_ALL_CREDENTIALS is specified for the Flags parameter and the Filter parameter is not NULL.
/// </returns>
/// </summary>
[DllImport("Advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool CredEnumerate(
string filter,
int flag,
out int count,
out IntPtr pCredentials);
internal static IEnumerable<CREDENTIAL> CredEnumerate()
{
int count;
IntPtr pCredentials;
if (!CredEnumerate(null, 0, out count, out pCredentials))
{
throw new Exception("Failed to enumerate credentials");
}
var source = new IntPtr[count];
for (var index = 0; index < count; ++index)
{
source[index] = Marshal.ReadIntPtr(pCredentials, index * Marshal.SizeOf(typeof(IntPtr)));
}
return source.Select(ptr => (CREDENTIAL)Marshal.PtrToStructure(ptr, typeof(CREDENTIAL)));
}
/// <summary>
/// The CREDENTIAL structure contains an individual credential.
///
/// See CREDENTIAL structure <see href="/?originalUrl=https%3A%2F%2Fgithub.com%2F%26quot%3Bhttp%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2Fwindows%2Fdesktop%2Faa374788(v%3Dvs.85).aspx%26quot%3B%26gt%3Bdocumentation.%26lt%3B%2Fsee%26gt%3B%253C%2Fdiv">
/// </summary>
internal struct CREDENTIAL
{
public int Flags;
public int Type;
[MarshalAs(UnmanagedType.LPWStr)] public string TargetName;
[MarshalAs(UnmanagedType.LPWStr)] public string Comment;
public long LastWritten;
public int CredentialBlobSize;
public IntPtr CredentialBlob;
public int Persist;
public int AttributeCount;
public IntPtr Attributes;
[MarshalAs(UnmanagedType.LPWStr)] public string TargetAlias;
[MarshalAs(UnmanagedType.LPWStr)] public string UserName;
}
internal sealed class CriticalCredentialHandle : CriticalHandleZeroOrMinusOneIsInvalid
{
internal CriticalCredentialHandle(IntPtr preexistingHandle)
{
SetHandle(preexistingHandle);
}
internal CREDENTIAL GetCredential()
{
if (!IsInvalid)
{
return (CREDENTIAL)Marshal.PtrToStructure(handle, typeof(CREDENTIAL));
}
throw new InvalidOperationException("Invalid CriticalHandle!");
}
protected override bool ReleaseHandle()
{
if (IsInvalid)
{
return false;
}
CredFree(handle);
SetHandleAsInvalid();
return true;
}
}
}
}