1
- using Microsoft . Win32 . SafeHandles ;
2
- using System ;
3
- using System . Collections . Generic ;
1
+ using System ;
4
2
using System . ComponentModel ;
5
- using System . Linq ;
3
+ using System . Diagnostics ;
6
4
using System . Net ;
7
5
using System . Runtime . InteropServices ;
8
6
using System . Text ;
9
- using System . Threading . Tasks ;
10
7
11
8
namespace AdysTech . CredentialManager
12
9
{
@@ -20,14 +17,15 @@ public static class CredentialManager
20
17
/// Opens OS Version specific Window prompting for credentials
21
18
/// </summary>
22
19
/// <param name="Target">A descriptive text for where teh credentials being asked are used for</param>
20
+ /// <param name="save">Whether or not to offer the checkbox to save the credentials</param>
23
21
/// <returns>NetworkCredential object containing the user name, </returns>
24
- public static NetworkCredential PromptForCredentials ( string Target )
22
+ public static NetworkCredential PromptForCredentials ( string Target , ref bool save )
25
23
{
26
24
var username = String . Empty ;
27
25
var passwd = String . Empty ;
28
26
var domain = String . Empty ;
29
27
30
- if ( ! PromptForCredentials ( Target , out username , out passwd , out domain ) )
28
+ if ( ! PromptForCredentials ( Target , ref save , out username , out passwd , out domain ) )
31
29
return null ;
32
30
return new NetworkCredential ( username , passwd , domain ) ;
33
31
}
@@ -36,73 +34,165 @@ public static NetworkCredential PromptForCredentials(string Target)
36
34
/// Opens OS Version specific Window prompting for credentials
37
35
/// </summary>
38
36
/// <param name="Target">A descriptive text for where teh credentials being asked are used for</param>
37
+ /// <param name="save">Whether or not to offer the checkbox to save the credentials</param>
39
38
/// <param name="Message">A brief message to display in the dialog box</param>
40
39
/// <param name="Caption">Title for the dialog box</param>
41
40
/// <returns>NetworkCredential object containing the user name, </returns>
42
- public static NetworkCredential PromptForCredentials ( string Target , string Message , string Caption )
41
+ public static NetworkCredential PromptForCredentials ( string Target , ref bool save , string Message , string Caption )
43
42
{
44
43
var username = String . Empty ;
45
44
var passwd = String . Empty ;
46
45
var domain = String . Empty ;
47
46
48
- if ( ! PromptForCredentials ( Target , Message , Caption , out username , out passwd , out domain ) )
47
+ if ( ! PromptForCredentials ( Target , ref save , Message , Caption , out username , out passwd , out domain ) )
49
48
return null ;
50
49
return new NetworkCredential ( username , passwd , domain ) ;
51
50
}
52
51
53
- internal static bool PromptForCredentials ( string target , out string user , out string password , out string domain )
52
+ internal static bool PromptForCredentials ( string target , ref bool save , out string user , out string password , out string domain )
54
53
{
55
- return PromptForCredentials ( target , new NativeStructs . CredentialUIInfo ( ) , out user , out password , out domain ) ;
54
+ return PromptForCredentials ( target , new NativeCode . CredentialUIInfo ( ) , ref save , out user , out password , out domain ) ;
56
55
}
57
56
58
- internal static bool PromptForCredentials ( string target , string Message , string Caption , out string user , out string password , out string domain )
57
+ internal static bool PromptForCredentials ( string target , ref bool save , string Message , string Caption , out string user , out string password , out string domain )
59
58
{
60
- NativeStructs . CredentialUIInfo credUI = new NativeStructs . CredentialUIInfo ( ) ;
59
+ NativeCode . CredentialUIInfo credUI = new NativeCode . CredentialUIInfo ( ) ;
61
60
credUI . pszMessageText = Message ;
62
61
credUI . pszCaptionText = Caption ;
63
- return PromptForCredentials ( target , credUI , out user , out password , out domain ) ;
62
+ return PromptForCredentials ( target , credUI , ref save , out user , out password , out domain ) ;
64
63
}
65
64
66
- private static bool PromptForCredentials ( string target , NativeStructs . CredentialUIInfo credUI , out string user , out string password , out string domain )
65
+ private static bool PromptForCredentials ( string target , NativeCode . CredentialUIInfo credUI , ref bool save , out string user , out string password , out string domain )
67
66
{
67
+ user = String . Empty ;
68
+ password = String . Empty ;
69
+ domain = String . Empty ;
70
+
71
+
72
+
68
73
// Setup the flags and variables
69
- StringBuilder userPassword = new StringBuilder ( ) , userID = new StringBuilder ( ) ;
70
74
credUI . cbSize = Marshal . SizeOf ( credUI ) ;
75
+ int errorcode = 0 ;
76
+ uint dialogReturn ;
77
+ uint authPackage = 0 ;
78
+
79
+ IntPtr outCredBuffer = new IntPtr ( ) ;
80
+ uint outCredSize ;
81
+ var flags = NativeCode . PromptForWindowsCredentialsFlags . GenericCredentials | NativeCode . PromptForWindowsCredentialsFlags . EnumerateCurrentUser ;
82
+ flags = save ? flags | NativeCode . PromptForWindowsCredentialsFlags . ShowCheckbox : flags ;
83
+
84
+ // Setup the flags and variables
85
+ int result = NativeCode . CredUIPromptForWindowsCredentials ( ref credUI ,
86
+ errorcode ,
87
+ ref authPackage ,
88
+ IntPtr . Zero ,
89
+ 0 ,
90
+ out outCredBuffer ,
91
+ out outCredSize ,
92
+ ref save ,
93
+ flags ) ;
94
+
95
+ var usernameBuf = new StringBuilder ( 100 ) ;
96
+ var passwordBuf = new StringBuilder ( 100 ) ;
97
+ var domainBuf = new StringBuilder ( 100 ) ;
98
+
99
+ int maxUserName = 100 ;
100
+ int maxDomain = 100 ;
101
+ int maxPassword = 100 ;
102
+ if ( result == 0 )
103
+ {
104
+ if ( NativeCode . CredUnPackAuthenticationBuffer ( 0 , outCredBuffer , outCredSize , usernameBuf , ref maxUserName ,
105
+ domainBuf , ref maxDomain , passwordBuf , ref maxPassword ) )
106
+ {
107
+ user = usernameBuf . ToString ( ) ;
108
+ password = passwordBuf . ToString ( ) ;
109
+ domain = domainBuf . ToString ( ) ;
110
+ if ( String . IsNullOrWhiteSpace ( domain ) )
111
+ {
112
+ Debug . WriteLine ( "Domain null" ) ;
113
+ if ( ! ParseUserName ( usernameBuf . ToString ( ) , maxUserName , maxDomain , out user , out password ) )
114
+ user = usernameBuf . ToString ( ) ;
115
+ }
116
+ }
117
+
118
+ //mimic SecureZeroMem function to make sure buffer is zeroed out. SecureZeroMem is not an exported function, neither is RtlSecureZeroMemory
119
+ var zeroBytes = new byte [ outCredSize ] ;
120
+ Marshal . Copy ( zeroBytes , 0 , outCredBuffer , ( int ) outCredSize ) ;
121
+
122
+ //clear the memory allocated by CredUIPromptForWindowsCredentials
123
+ NativeCode . CoTaskMemFree ( outCredBuffer ) ;
124
+ return true ;
125
+ }
126
+
127
+ user = null ;
128
+ domain = null ;
129
+ return false ;
130
+ }
131
+
132
+ private static bool ParseUserName ( string usernameBuf , int maxUserName , int maxDomain , out string user , out string domain )
133
+ {
134
+ StringBuilder userBuilder = new StringBuilder ( ) ;
135
+ StringBuilder domainBuilder = new StringBuilder ( ) ;
136
+ user = String . Empty ;
137
+ domain = String . Empty ;
138
+
139
+ var returnCode = NativeCode . CredUIParseUserName ( usernameBuf , userBuilder , maxUserName , domainBuilder , maxDomain ) ;
140
+ Debug . WriteLine ( returnCode ) ;
141
+ switch ( returnCode )
142
+ {
143
+ case NativeCode . CredentialUIReturnCodes . Success : // The username is valid.
144
+ user = userBuilder . ToString ( ) ;
145
+ domain = domainBuilder . ToString ( ) ;
146
+ return true ;
147
+ }
148
+ return false ;
149
+ }
150
+
151
+ /// <summary>
152
+ /// Accepts credentials in a console window
153
+ /// </summary>
154
+ /// <param name="Target">A descriptive text for where teh credentials being asked are used for</param>
155
+ /// <returns>NetworkCredential object containing the user name, </returns>
156
+ public static NetworkCredential PromptForCredentialsConsole ( string target )
157
+ {
158
+ var user = String . Empty ;
159
+ var password = String . Empty ;
160
+ var domain = String . Empty ;
161
+
162
+ // Setup the flags and variables
163
+ StringBuilder userPassword = new StringBuilder ( ) , userID = new StringBuilder ( ) ;
71
164
bool save = true ;
72
- NativeStructs . CredentialUIFlags flags = NativeStructs . CredentialUIFlags . COMPLETE_USERNAME | NativeStructs . CredentialUIFlags . PERSIST | NativeStructs . CredentialUIFlags . EXCLUDE_CERTIFICATES ;
165
+ NativeCode . CredentialUIFlags flags = NativeCode . CredentialUIFlags . CompleteUsername | NativeCode . CredentialUIFlags . ExcludeCertificates ;
73
166
74
167
// Prompt the user
75
- NativeStructs . CredentialUIReturnCodes returnCode = NativeStructs . CredUIPromptForCredentials ( ref credUI , target , IntPtr . Zero , 0 , userID , 100 , userPassword , 100 , ref save , flags ) ;
168
+ NativeCode . CredentialUIReturnCodes returnCode = NativeCode . CredUICmdLinePromptForCredentials ( target , IntPtr . Zero , 0 , userID , 100 , userPassword , 100 , ref save , flags ) ;
76
169
77
170
password = userPassword . ToString ( ) ;
78
171
79
172
StringBuilder userBuilder = new StringBuilder ( ) ;
80
173
StringBuilder domainBuilder = new StringBuilder ( ) ;
81
174
82
- returnCode = NativeStructs . CredUIParseUserName ( userID . ToString ( ) , userBuilder , int . MaxValue , domainBuilder , int . MaxValue ) ;
175
+ returnCode = NativeCode . CredUIParseUserName ( userID . ToString ( ) , userBuilder , int . MaxValue , domainBuilder , int . MaxValue ) ;
83
176
switch ( returnCode )
84
177
{
85
- case NativeStructs . CredentialUIReturnCodes . NO_ERROR : // The username is valid.
178
+ case NativeCode . CredentialUIReturnCodes . Success : // The username is valid.
86
179
user = userBuilder . ToString ( ) ;
87
180
domain = domainBuilder . ToString ( ) ;
88
- return true ;
181
+ break ;
89
182
90
- case NativeStructs . CredentialUIReturnCodes . ERROR_INVALID_ACCOUNT_NAME : // The username is not valid.
183
+ case NativeCode . CredentialUIReturnCodes . InvalidAccountName : // The username is not valid.
91
184
user = userID . ToString ( ) ;
92
185
domain = null ;
93
- return false ;
186
+ break ;
94
187
95
- case NativeStructs . CredentialUIReturnCodes . ERROR_INSUFFICIENT_BUFFER : // One of the buffers is too small.
188
+ case NativeCode . CredentialUIReturnCodes . InsufficientBuffer : // One of the buffers is too small.
96
189
throw new OutOfMemoryException ( ) ;
97
190
98
- case NativeStructs . CredentialUIReturnCodes . ERROR_INVALID_PARAMETER : // ulUserMaxChars or ulDomainMaxChars is zero OR userName, user, or domain is NULL.
191
+ case NativeCode . CredentialUIReturnCodes . InvalidParameter : // ulUserMaxChars or ulDomainMaxChars is zero OR userName, user, or domain is NULL.
99
192
throw new ArgumentNullException ( "userName" ) ;
100
193
101
- default :
102
- user = null ;
103
- domain = null ;
104
- return false ;
105
194
}
195
+ return new NetworkCredential ( user , password , domain ) ;
106
196
}
107
197
108
198
@@ -118,10 +208,10 @@ public static bool SaveCredentials(string Target, NetworkCredential credential)
118
208
// Go ahead with what we have are stuff it into the CredMan structures.
119
209
Credential cred = new Credential ( credential ) ;
120
210
cred . TargetName = Target ;
121
- cred . Persist = NativeStructs . Persistance . ENTERPRISE ;
122
- NativeStructs . NativeCredential ncred = cred . GetNativeCredential ( ) ;
211
+ cred . Persist = NativeCode . Persistance . Entrprise ;
212
+ NativeCode . NativeCredential ncred = cred . GetNativeCredential ( ) ;
123
213
// Write the info into the CredMan storage.
124
- bool written = NativeStructs . CredWrite ( ref ncred , 0 ) ;
214
+ bool written = NativeCode . CredWrite ( ref ncred , 0 ) ;
125
215
int lastError = Marshal . GetLastWin32Error ( ) ;
126
216
if ( written )
127
217
{
@@ -148,7 +238,7 @@ public static NetworkCredential GetCredentials(string Target)
148
238
var domain = String . Empty ;
149
239
150
240
// Make the API call using the P/Invoke signature
151
- bool ret = NativeStructs . CredRead ( Target , NativeStructs . CredentialType . GENERIC , 0 , out nCredPtr ) ;
241
+ bool ret = NativeCode . CredRead ( Target , NativeCode . CredentialType . Generic , 0 , out nCredPtr ) ;
152
242
int lastError = Marshal . GetLastWin32Error ( ) ;
153
243
if ( ! ret )
154
244
throw new Win32Exception ( lastError , "CredDelete throw an error" ) ;
@@ -163,12 +253,12 @@ public static NetworkCredential GetCredentials(string Target)
163
253
var user = cred . UserName ;
164
254
StringBuilder userBuilder = new StringBuilder ( ) ;
165
255
StringBuilder domainBuilder = new StringBuilder ( ) ;
166
- var ret1 = NativeStructs . CredUIParseUserName ( user , userBuilder , int . MaxValue , domainBuilder , int . MaxValue ) ;
256
+ var ret1 = NativeCode . CredUIParseUserName ( user , userBuilder , int . MaxValue , domainBuilder , int . MaxValue ) ;
167
257
lastError = Marshal . GetLastWin32Error ( ) ;
168
258
169
259
//assuming invalid account name to be not meeting condition for CredUIParseUserName
170
260
//"The name must be in UPN or down-level format, or a certificate"
171
- if ( ret1 == NativeStructs . CredentialUIReturnCodes . ERROR_INVALID_ACCOUNT_NAME )
261
+ if ( ret1 == NativeCode . CredentialUIReturnCodes . InvalidAccountName )
172
262
userBuilder . Append ( user ) ;
173
263
else if ( ( uint ) ret1 > 0 )
174
264
throw new Win32Exception ( lastError , "CredUIParseUserName throw an error" ) ;
@@ -190,7 +280,7 @@ public static NetworkCredential GetCredentials(string Target)
190
280
public static bool RemoveCredentials ( string Target )
191
281
{
192
282
// Make the API call using the P/Invoke signature
193
- var ret = NativeStructs . CredDelete ( Target , NativeStructs . CredentialType . GENERIC , 0 ) ;
283
+ var ret = NativeCode . CredDelete ( Target , NativeCode . CredentialType . Generic , 0 ) ;
194
284
int lastError = Marshal . GetLastWin32Error ( ) ;
195
285
if ( ! ret )
196
286
throw new Win32Exception ( lastError , "CredDelete throw an error" ) ;
0 commit comments