/// <summary> /// Saves this instance. /// </summary> /// <returns><c>true</c> if credential is saved properly, <c>false</c> otherwise.</returns> /// <exception cref="System.ArgumentOutOfRangeException">password;The password has exceeded 512 bytes.</exception> public bool Save() { CheckNotDisposed(); UnmanagedCodePermission.Demand(); var passwordBytes = Encoding.Unicode.GetBytes(Password); if (Password.Length > (512)) { throw new ArgumentOutOfRangeException("password", "The password has exceeded 512 bytes."); } var credential = new NativeCode.CREDENTIAL { TargetName = Target, UserName = Username, CredentialBlob = Marshal.StringToCoTaskMemUni(Password), CredentialBlobSize = passwordBytes.Length, Comment = Description, Type = (int)Type, Persist = (int)PersistenceType }; var result = NativeCode.CredWrite(ref credential, 0); if (!result) { return(false); } LastWriteTimeUtc = DateTime.UtcNow; return(true); }
/// <summary> /// Loads all credentials with filter /// </summary> /// <param name="filter">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> /// <returns>Credentials collection</returns> public static IEnumerable <Credential> LoadAll(string filter) { UnmanagedCodePermission.Demand(); return(NativeCode.CredEnumerate(filter) .Select(c => new Credential(c.UserName, null, c.TargetName)) .Where(c => c.Load())); }
/// <summary> /// Deletes this instance. /// </summary> /// <returns><c>true</c> if credential was deleted properly, <c>false</c> otherwise.</returns> /// <exception cref="System.InvalidOperationException">Target must be specified to delete a credential.</exception> public bool Delete() { CheckNotDisposed(); UnmanagedCodePermission.Demand(); if (string.IsNullOrEmpty(Target)) { throw new InvalidOperationException("Target must be specified to delete a credential."); } return(NativeCode.CredDelete(Target, Type, 0)); }
/// <summary> /// Extract the stored credential from Windows Credential store /// </summary> /// <param name="Target">Name of the application/Url where the credential is used for</param> /// <returns>null if target not found, else stored credentials</returns> public static NetworkCredential GetCredentials(string Target, CredentialType type = CredentialType.Generic) { Credential cred = new Credential(String.Empty, String.Empty, Target, type); bool ret = cred.Load(); int lastError = Marshal.GetLastWin32Error(); if (!ret) { //throw new Win32Exception(lastError, "CredRead throw an error"); return(null); } var username = cred.Username; var passwd = cred.Password; var domain = String.Empty; // Make the API call using the P/Invoke signature try { if (!String.IsNullOrEmpty(cred.Username)) { var user = cred.Username; StringBuilder userBuilder = new StringBuilder(cred.Username.Length + 2); StringBuilder domainBuilder = new StringBuilder(cred.Username.Length + 2); var ret1 = NativeCode.CredUIParseUserName(user, userBuilder, userBuilder.Capacity, domainBuilder, domainBuilder.Capacity); lastError = Marshal.GetLastWin32Error(); if (ret1 == NativeCode.CredentialUIReturnCodes.InvalidAccountName) { userBuilder.Append(user); } else if ((uint)ret1 > 0) { throw new Win32Exception(lastError, "CredUIParseUserName throw an error"); } username = userBuilder.ToString(); domain = domainBuilder.ToString(); } return(new NetworkCredential(username, passwd, domain)); } catch (Exception e) { return(null); } }
private static bool ParseUserName(string usernameBuf, int maxUserName, int maxDomain, out string user, out string domain) { StringBuilder userBuilder = new StringBuilder(); StringBuilder domainBuilder = new StringBuilder(); user = String.Empty; domain = String.Empty; var returnCode = NativeCode.CredUIParseUserName(usernameBuf, userBuilder, maxUserName, domainBuilder, maxDomain); Debug.WriteLine(returnCode); switch (returnCode) { case NativeCode.CredentialUIReturnCodes.Success: // The username is valid. user = userBuilder.ToString(); domain = domainBuilder.ToString(); return(true); } return(false); }
/// <summary> /// Remove stored credentials from windows credential store /// </summary> /// <param name="Target">Name of the application/Url where the credential is used for</param> /// <returns>True: Success, False: Failure</returns> public static bool RemoveCredentials(string Target, CredentialType type = CredentialType.Generic) { IntPtr credPointer; var result = NativeCode.CredRead(Target, type, 0, out credPointer); if (!result) { return(false); } // Make the API call using the P/Invoke signature var ret = NativeCode.CredDelete(Target, type, 0); int lastError = Marshal.GetLastWin32Error(); if (!ret) { throw new Win32Exception(lastError, "CredDelete throw an error"); } return(ret); }
/// <summary> /// Accepts credentials in a console window /// </summary> /// <param name="Target">A descriptive text for where teh credentials being asked are used for</param> /// <returns>NetworkCredential object containing the user name, </returns> public static NetworkCredential PromptForCredentialsConsole(string target) { var user = String.Empty; var password = String.Empty; var domain = String.Empty; // Setup the flags and variables StringBuilder userPassword = new StringBuilder(), userID = new StringBuilder(); bool save = true; NativeCode.CredentialUIFlags flags = NativeCode.CredentialUIFlags.CompleteUsername | NativeCode.CredentialUIFlags.ExcludeCertificates | NativeCode.CredentialUIFlags.GenericCredentials; // Prompt the user NativeCode.CredentialUIReturnCodes returnCode = NativeCode.CredUICmdLinePromptForCredentials(target, IntPtr.Zero, 0, userID, 100, userPassword, 100, ref save, flags); password = userPassword.ToString(); StringBuilder userBuilder = new StringBuilder(); StringBuilder domainBuilder = new StringBuilder(); returnCode = NativeCode.CredUIParseUserName(userID.ToString(), userBuilder, int.MaxValue, domainBuilder, int.MaxValue); switch (returnCode) { case NativeCode.CredentialUIReturnCodes.Success: // The username is valid. user = userBuilder.ToString(); domain = domainBuilder.ToString(); break; case NativeCode.CredentialUIReturnCodes.InvalidAccountName: // The username is not valid. user = userID.ToString(); domain = null; break; case NativeCode.CredentialUIReturnCodes.InsufficientBuffer: // One of the buffers is too small. throw new OutOfMemoryException(); case NativeCode.CredentialUIReturnCodes.InvalidParameter: // ulUserMaxChars or ulDomainMaxChars is zero OR userName, user, or domain is NULL. throw new ArgumentNullException("userName"); } return(new NetworkCredential(user, password, domain)); }
/// <summary> /// Loads this instance. /// </summary> /// <returns><c>true</c> if credential is load properly, <c>false</c> otherwise.</returns> public bool Load() { CheckNotDisposed(); UnmanagedCodePermission.Demand(); IntPtr credPointer; var result = NativeCode.CredRead(Target, Type, 0, out credPointer); if (!result) { return(false); } using (var credentialHandle = new NativeCode.CriticalCredentialHandle(credPointer)) { LoadInternal(credentialHandle.GetCredential()); } return(true); }
private static bool PromptForCredentials(string target, NativeCode.CredentialUIInfo credUI, ref bool save, out string user, out string password, out string domain) { user = String.Empty; password = String.Empty; domain = String.Empty; // Setup the flags and variables credUI.cbSize = Marshal.SizeOf(credUI); int errorcode = 0; uint authPackage = 0; IntPtr outCredBuffer = new IntPtr(); uint outCredSize; var flags = NativeCode.PromptForWindowsCredentialsFlags.GenericCredentials | NativeCode.PromptForWindowsCredentialsFlags.EnumerateCurrentUser; flags = save ? flags | NativeCode.PromptForWindowsCredentialsFlags.ShowCheckbox : flags; // Setup the flags and variables int result = NativeCode.CredUIPromptForWindowsCredentials(ref credUI, errorcode, ref authPackage, IntPtr.Zero, 0, out outCredBuffer, out outCredSize, ref save, flags); var usernameBuf = new StringBuilder(100); var passwordBuf = new StringBuilder(100); var domainBuf = new StringBuilder(100); int maxUserName = 100; int maxDomain = 100; int maxPassword = 100; if (result == 0) { if (NativeCode.CredUnPackAuthenticationBuffer(0, outCredBuffer, outCredSize, usernameBuf, ref maxUserName, domainBuf, ref maxDomain, passwordBuf, ref maxPassword)) { user = usernameBuf.ToString(); password = passwordBuf.ToString(); domain = domainBuf.ToString(); if (String.IsNullOrWhiteSpace(domain)) { Debug.WriteLine("Domain null"); if (!ParseUserName(usernameBuf.ToString(), usernameBuf.Capacity, domainBuf.Capacity, out user, out domain)) { user = usernameBuf.ToString(); } } } //mimic SecureZeroMem function to make sure buffer is zeroed out. SecureZeroMem is not an exported function, neither is RtlSecureZeroMemory var zeroBytes = new byte[outCredSize]; Marshal.Copy(zeroBytes, 0, outCredBuffer, (int)outCredSize); //clear the memory allocated by CredUIPromptForWindowsCredentials NativeCode.CoTaskMemFree(outCredBuffer); return(true); } user = null; domain = null; return(false); }