internal static SafeToken LogonUser(string username, string password, int logonType, int logonProvider) { string domain; string user; int index = username.IndexOf('\\'); if (0 <= index) { domain = username.Substring(0, index); user = username.Substring(index + 1); } else { // // No slash '\' in user account string. Assume local account or // a internet style account user@dns_domain_name // domain = null; user = username; } SafeToken token; if (!CredentialNativeMethods.LogonUser(user, domain, password, logonType, logonProvider, out token)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return(token); }
internal static bool ExistsLocalAccount(string username) { IntPtr infoPtr = IntPtr.Zero; try { int errCode = CredentialNativeMethods.NetUserGetInfo(null, username, 1, out infoPtr); if (errCode == CredentialNativeMethods.NERR_Success) { return(true); } else if (errCode == CredentialNativeMethods.NERR_UserNotFound) { return(false); } throw new Exception("Error when checking whether the local account " + username + " exists. Error code: " + errCode); } finally { if (infoPtr != IntPtr.Zero) { try { Marshal.FreeHGlobal(infoPtr); } catch { } } } }
/// <summary> /// Set password for a specified local account regardless of old password /// In this function, we assume the caller has already checked that the user exists. /// Check it using ExistsLocalAccount method. /// </summary> /// <param name="username">local account name</param> /// <param name="password">new password for the specified local account</param> internal static void SetLocalAccountPassword(string username, SecureString password) { CredentialNativeMethods.USER_INFO_1003 info = new CredentialNativeMethods.USER_INFO_1003(); if (password == null) { info.sPassword = Marshal.StringToCoTaskMemUni(String.Empty); } else { info.sPassword = Marshal.SecureStringToCoTaskMemUnicode(password); } IntPtr infoPtr = IntPtr.Zero; try { infoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(info)); Marshal.StructureToPtr(info, infoPtr, false); uint errParam; int errCode = CredentialNativeMethods.NetUserSetInfo(null, username, /*information level of infoPtr =*/ 1003, infoPtr, out errParam); if (errCode != CredentialNativeMethods.NERR_Success) { switch (errCode) { case CredentialNativeMethods.NERR_UserNotFound: throw new ArgumentException("The local user " + username + " is not found."); default: throw new Exception("Error when setting password for local account " + username + ". Error code: " + errCode); } } } finally { if (info.sPassword != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(info.sPassword); } if (infoPtr != IntPtr.Zero) { try { Marshal.FreeHGlobal(infoPtr); } catch { } } } }
static void AddUserGroup(string username, string groupname) { CredentialNativeMethods.LOCALGROUP_MEMBERS_INFO_3 grpinfo; grpinfo.Domain = username; int errCode = 0; // add the user to the administrators group errCode = CredentialNativeMethods.NetLocalGroupAddMembers(null, groupname, 3, ref grpinfo, 1); if (errCode != 0 && errCode != CredentialNativeMethods.ERROR_MEMBER_IN_ALIAS) { throw new Exception("Error when trying to add local account " + username + " to group " + groupname + ". Error code:" + errCode); } }
/// <summary> /// In this function, we assume the caller has already checked that the user exists. /// Check it using ExistsLocalAccount method. /// </summary> /// <param name="username"></param> internal static void DeleteLocalAccount(string username) { int errCode = CredentialNativeMethods.NetUserDel(null, username); if (errCode != CredentialNativeMethods.NERR_Success) { switch (errCode) { case CredentialNativeMethods.NERR_UserNotFound: throw new ArgumentException("The local user " + username + " is not found."); default: throw new Exception("Error when trying to delete local account " + username + " exists. Error code: " + errCode); } } }
protected override bool ReleaseHandle() { CredentialNativeMethods.CloseHandle(this.handle); return(true); }
/// <summary> /// In this function, we assume the caller has already checked that the user does not exist. /// Check it using ExistsLocalAccount method /// </summary> /// <param name="username"></param> /// <param name="password"></param> /// <param name="isAdmin"></param> /// <param name="schedulerOnAzure"></param> internal static void AddLocalAccount(string username, SecureString password, bool isAdmin, bool schedulerOnAzure) { CredentialNativeMethods.USER_INFO_1 info = new CredentialNativeMethods.USER_INFO_1(); info.sUsername = username; if (password == null) { info.sPassword = Marshal.StringToCoTaskMemUni(String.Empty); } else { info.sPassword = Marshal.SecureStringToCoTaskMemUnicode(password); } info.uiPriv = CredentialNativeMethods.USER_PRIV_USER; info.sHome_Dir = null; info.sComment = null; info.sScript_Path = null; info.uiFlags = CredentialNativeMethods.UF_SCRIPT; // Check the string length to prevent memory overflow if (info.sUsername.Length > 128) { throw new ArgumentException("The user name is too long."); } if (password != null && password.Length > 512) { throw new ArgumentException("The password is too long."); } try { uint errParam = 0; int errCode = CredentialNativeMethods.NetUserAdd(null, 1, ref info, out errParam); if (errCode != CredentialNativeMethods.NERR_Success) { switch (errCode) { case CredentialNativeMethods.NERR_UserExists: throw new ArgumentException("The local user " + username + " already exists."); case CredentialNativeMethods.NERR_PasswordTooShort: throw new ArgumentException("The password given is too short."); default: throw new Exception("Error when trying to create local account " + username + " exists. Error code: " + errCode + ", sub-error: " + errParam); } } } finally { if (info.sPassword != IntPtr.Zero) { try { Marshal.ZeroFreeCoTaskMemUnicode(info.sPassword); } catch { } } } AddUserGroups(username, isAdmin, schedulerOnAzure); }
/// <summary> /// In this function, we assume the caller has already checked that the user exists. /// Check it using ExistsLocalAccount method. /// </summary> /// <param name="username"></param> /// <param name="newPassword"></param> /// <param name="oldPassword"></param> internal static void SetLocalAccountPassword(string username, SecureString newPassword, SecureString oldPassword) { IntPtr newPlainPassword = IntPtr.Zero; IntPtr oldPlainPassword = IntPtr.Zero; try { if (newPassword == null) { newPlainPassword = Marshal.StringToCoTaskMemUni(String.Empty); } else { newPlainPassword = Marshal.SecureStringToCoTaskMemUnicode(newPassword); } if (oldPassword == null) { oldPlainPassword = Marshal.StringToCoTaskMemUni(String.Empty); } else { oldPlainPassword = Marshal.SecureStringToCoTaskMemUnicode(oldPassword); } // Note: the first parameter of NetUserChangePassword is domain name. If it // is NULL, the logon domain of the caller, instead of local computer, is used. // This is unlike NetUserAdd, NetUserGetInfo or NetUserSetInfo. uint errCode = CredentialNativeMethods.NetUserChangePassword( Environment.MachineName, username, oldPlainPassword, newPlainPassword); if (errCode != CredentialNativeMethods.NERR_Success) { switch (errCode) { case CredentialNativeMethods.NERR_UserNotFound: throw new ArgumentException("The local user " + username + " is not found."); case CredentialNativeMethods.NERR_PasswordTooShort: // If password is long enough but still you receive error // "NERR_PasswordTooShort" in a DOMAIN environment, then it is probably // an indication that the time span since the previous password change // operation is shorter than the allowed policy. It is a policy in AD to // have a minimum password age, for example, of 1 day. throw new ArgumentException("The password given is too short."); case CredentialNativeMethods.ERROR_INVALID_PASSWORD: throw new ArgumentException("The given old password is not valid."); default: throw new Exception("Error when trying to reset password for local account " + username + " exists. Error code: " + errCode); } } } finally { if (newPlainPassword != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(newPlainPassword); } if (oldPlainPassword != IntPtr.Zero) { Marshal.ZeroFreeCoTaskMemUnicode(oldPlainPassword); } } }
/// <summary> /// Prompt for credentials /// </summary> /// <param name="target">Target to the credentials</param> /// <param name="username">receives user name</param> /// <param name="password">receives password associated</param> /// <param name="fSave">receives if credentials are saved.</param> /// <param name="fConsole">Is this a console application</param> /// <param name="hwndParent">Parent window handle</param> /// <param name="flags">options for the window.</param> /// <param name="message">Message to end user included in the window.</param> internal static void PromptForCredentials(string target, ref string username, ref SecureString password, ref bool fSave, bool fConsole, IntPtr hwndParent, CredentialNativeMethods.CREDUI_FLAGS flags, string message) { CredentialNativeMethods.CREDUI_INFO info = new CredentialNativeMethods.CREDUI_INFO(); int result; int saveCredentials; StringBuilder user = new StringBuilder(username, CRED_MAX_USERNAME_LENGTH); StringBuilder pwd = new StringBuilder(CRED_MAX_PASSWORD_LENGTH); saveCredentials = 0; info.cbSize = Marshal.SizeOf(info); info.hwndParent = hwndParent; if (!string.IsNullOrEmpty(message)) { // Use default message text, when message is not specified. info.pszMessageText = message; } if (fConsole) { result = CredentialNativeMethods.CredUICmdLinePromptForCredentials(target, IntPtr.Zero, 0, user, CRED_MAX_USERNAME_LENGTH, pwd, CRED_MAX_PASSWORD_LENGTH, ref saveCredentials, flags); } else { if (hwndParent == new IntPtr(-1)) { throw new System.Security.Authentication.InvalidCredentialException(); } result = CredentialNativeMethods.CredUIPromptForCredentials(ref info, target, IntPtr.Zero, 0, user, CRED_MAX_USERNAME_LENGTH, pwd, CRED_MAX_PASSWORD_LENGTH, ref saveCredentials, flags); } if (result != 0) { throw new System.ComponentModel.Win32Exception(result); } fSave = (saveCredentials != 0); username = user.ToString(); password = new SecureString(); for (int i = 0; i < pwd.Length; i++) { password.AppendChar(pwd[i]); pwd[i] = ' '; // overwrite the cleartext password } password.MakeReadOnly(); }
/// <summary> /// Prompt for credentials /// </summary> /// <param name="target">Target to the credentials</param> /// <param name="username">receives user name</param> /// <param name="password">receives password associated</param> /// <param name="fSave">receives if credentials are saved.</param> /// <param name="fConsole">Is this a console application</param> /// <param name="hwndParent">Parent window handle</param> /// <param name="flags">options for the window.</param> /// <param name="message">Message to end user included in the window.</param> internal static void PromptForCredentials(string target, ref string username, ref SecureString password, ref bool fSave, bool fConsole, IntPtr hwndParent, CredentialNativeMethods.CREDUI_FLAGS flags, string message) { CredentialNativeMethods.CREDUI_INFO info = new CredentialNativeMethods.CREDUI_INFO(); int result; int saveCredentials; StringBuilder user = new StringBuilder(username, CRED_MAX_USERNAME_LENGTH); StringBuilder pwd = new StringBuilder(CRED_MAX_PASSWORD_LENGTH); saveCredentials = 0; info.cbSize = Marshal.SizeOf(info); info.hwndParent = hwndParent; if (!string.IsNullOrEmpty(message)) { // Use default message text, when message is not specified. info.pszMessageText = message; } if (fConsole) { result = CredentialNativeMethods.CredUICmdLinePromptForCredentials(target, IntPtr.Zero, 0, user, CRED_MAX_USERNAME_LENGTH, pwd, CRED_MAX_PASSWORD_LENGTH, ref saveCredentials, flags); } else { if (hwndParent == new IntPtr(-1)) { throw new System.Security.Authentication.InvalidCredentialException(); } result = CredentialNativeMethods.CredUIPromptForCredentials(ref info, target, IntPtr.Zero, 0, user, CRED_MAX_USERNAME_LENGTH, pwd, CRED_MAX_PASSWORD_LENGTH, ref saveCredentials, flags); } if (result != 0) { throw new System.ComponentModel.Win32Exception(result); } fSave = (saveCredentials != 0); username = user.ToString(); password = new SecureString(); for (int i = 0; i < pwd.Length; i++) { password.AppendChar(pwd[i]); pwd[i] = ' '; // overwrite the cleartext password } password.MakeReadOnly(); }