/// <summary> /// Handles the Elapsed event for the rights removal timer. /// </summary> /// <param name="sender"> /// The timer whose Elapsed event is firing. /// </param> /// <param name="e"> /// Data related to the event. /// </param> private void RemovalTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) { EncryptedSettings encryptedSettings = new EncryptedSettings(EncryptedSettings.SettingsFilePath); User[] expiredUsers = encryptedSettings.GetExpiredUsers(); if (expiredUsers != null) { foreach (User prin in expiredUsers) { LocalAdministratorGroup.RemoveUser(prin.Sid, RemovalReason.Timeout); if ((Settings.EndRemoteSessionsUponExpiration) && (!string.IsNullOrEmpty(prin.RemoteAddress))) { string userName = prin.Name; while (userName.LastIndexOf("\\") >= 0) { userName = userName.Substring(userName.LastIndexOf("\\") + 1); } int returnCode = 0; if (!string.IsNullOrEmpty(userName)) { returnCode = LocalAdministratorGroup.EndNetworkSession(string.Format(@"\\{0}", prin.RemoteAddress), userName); } } } } LocalAdministratorGroup.ValidateAllAddedUsers(); }
/// <summary> /// Adds a user to the local Administrators group. /// </summary> /// <param name="userIdentity"> /// The identity of the user to be added to the Administrators group. /// </param> /// <param name="expirationTime"> /// The date and time at which the user's administrator rights should expire. /// </param> /// <param name="remoteAddress"> /// The address of the remote host from which a request for administrator rights came, if applicable. /// </param> public static void AddUser(WindowsIdentity userIdentity, DateTime?expirationTime, string remoteAddress) { // TODO: Only do this if the user is not a member of the group? AdminGroupManipulator adminGroupManipulator = new AdminGroupManipulator(); bool userIsAuthorized = adminGroupManipulator.UserIsAuthorized(Settings.LocalAllowedEntities, Settings.LocalDeniedEntities); if (!string.IsNullOrEmpty(remoteAddress)) { // Request is from a remote computer. Check the remote authorization list. userIsAuthorized &= adminGroupManipulator.UserIsAuthorized(Settings.RemoteAllowedEntities, Settings.RemoteDeniedEntities); } if ( (LocalAdminGroup != null) && (userIdentity.User != null) && (userIdentity.Groups != null) && (userIsAuthorized) ) { // Save the user's information to the list of users. EncryptedSettings encryptedSettings = new EncryptedSettings(EncryptedSettings.SettingsFilePath); encryptedSettings.AddUser(userIdentity, expirationTime, remoteAddress); AddUserToAdministrators(userIdentity.User); } }
public static ActionResult RemoveUserList(Session session) { session.Log(string.Format("Removing saved user list \"{0}\".", EncryptedSettings.SettingsFilePath)); int tries = 5; TimeSpan sleepTime = new TimeSpan(0, 0, 5); while ((tries > 0) && (System.IO.File.Exists(EncryptedSettings.SettingsFilePath))) { try { EncryptedSettings.RemoveAllSettings(); } catch (Exception e) { session.Log("Error while trying to remove saved user list."); session.Log(e.Message); } tries--; if (tries > 0) { session.Log(string.Format("{0:N0} tries remaining.", tries)); System.Threading.Thread.Sleep(sleepTime); } } session.Log("Finished removing saved user list."); return(ActionResult.Success); }
/// <summary> /// Handles the stopping of the service. /// </summary> /// <remarks> /// Executes when a stop command is sent to the service by the Service Control Manager (SCM). /// </remarks> protected override void OnStop() { if ((this.namedPipeServiceHost != null) && (this.namedPipeServiceHost.State == CommunicationState.Opened)) { this.namedPipeServiceHost.Close(); } if ((this.tcpServiceHost != null) && (this.tcpServiceHost.State == CommunicationState.Opened)) { this.tcpServiceHost.Close(); } this.removalTimer.Stop(); EncryptedSettings encryptedSettings = new EncryptedSettings(EncryptedSettings.SettingsFilePath); SecurityIdentifier[] sids = encryptedSettings.AddedUserSIDs; for (int i = 0; i < sids.Length; i++) { LocalAdministratorGroup.RemoveUser(sids[i], RemovalReason.ServiceStopped); } if (processWatchSession != null) { processWatchSession.Dispose(); } base.OnStop(); }
/// <summary> /// Gets an object representing the local Administrators group. /// </summary> /*private static GroupPrincipal LocalAdminGroup * { * get * { * if (LocalMachineContext == null) * { * ApplicationLog.WriteEvent(Properties.Resources.LocalMachineContextIsNull, EventID.DebugMessage, System.Diagnostics.EventLogEntryType.Error); * } * else * { * if (LocalAdminsGroupSid == null) * { * ApplicationLog.WriteEvent(Properties.Resources.LocalAdminsGroupSIDIsNull, EventID.DebugMessage, System.Diagnostics.EventLogEntryType.Error); * } * else * { * if (localAdminGroup == null) * { * try * { * localAdminGroup = GroupPrincipal.FindByIdentity(LocalMachineContext, IdentityType.Sid, LocalAdminsGroupSid.Value); * } * catch (Exception exception) * { * ApplicationLog.WriteEvent(string.Format("{0}: {1}", Properties.Resources.Exception, exception.Message), EventID.DebugMessage, System.Diagnostics.EventLogEntryType.Error); * throw; * } * } * } * } * return localAdminGroup; * } * }*/ /// <summary> /// Adds a user to the local Administrators group. /// </summary> /// <param name="userIdentity"> /// The identity of the user to be added to the Administrators group. /// </param> /// <param name="expirationTime"> /// The date and time at which the user's administrator rights should expire. /// </param> /// <param name="remoteAddress"> /// The address of the remote host from which a request for administrator rights came, if applicable. /// </param> public static void AddUser(WindowsIdentity userIdentity, DateTime?expirationTime, string remoteAddress) { // TODO: Only do this if the user is not a member of the group? #if DEBUG ApplicationLog.WriteEvent(string.Format("Calling UserIsAuthorized(3) from AddUser() beginning of function."), EventID.DebugMessage, System.Diagnostics.EventLogEntryType.Information); #endif //AdminGroupManipulator adminGroupManipulator = new AdminGroupManipulator(); bool userIsAuthorized = AdminGroupManipulator.UserIsAuthorized(userIdentity, Settings.LocalAllowedEntities, Settings.LocalDeniedEntities); if (!string.IsNullOrEmpty(remoteAddress)) { // Request is from a remote computer. Check the remote authorization list. #if DEBUG ApplicationLog.WriteEvent(string.Format("Calling UserIsAuthorized(3) from AddUser() where remote address is not null or empty."), EventID.DebugMessage, System.Diagnostics.EventLogEntryType.Information); #endif userIsAuthorized &= AdminGroupManipulator.UserIsAuthorized(userIdentity, Settings.RemoteAllowedEntities, Settings.RemoteDeniedEntities); } if ( (LocalAdminGroupName != null) && (userIdentity.User != null) && (userIdentity.Groups != null) && (userIsAuthorized) ) { // Save the user's information to the list of users. EncryptedSettings encryptedSettings = new EncryptedSettings(EncryptedSettings.SettingsFilePath); encryptedSettings.AddUser(userIdentity, expirationTime, remoteAddress); AddUserToAdministrators(userIdentity.User); } }
/// <summary> /// Loads application settings from the specified file. /// </summary> /// <param name="filePath"> /// The path of the file from which settings should be loaded. /// </param> private void Load(string filePath) { if (System.IO.File.Exists(filePath)) { // The specified file exists. byte[] buffer = new byte[128]; int bytesRead = int.MinValue; // Read the encrpyted bytes from the file. System.IO.MemoryStream ciphertextMemoryStream = new System.IO.MemoryStream(); System.IO.FileStream ciphertextFileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Open, System.IO.FileAccess.Read); while ((bytesRead = ciphertextFileStream.Read(buffer, 0, buffer.Length)) > 0) { ciphertextMemoryStream.Write(buffer, 0, bytesRead); } ciphertextFileStream.Close(); // Convert the encrypted bytes to an array. byte[] ciphertextBytes = ciphertextMemoryStream.ToArray(); // Decrypt the byte array. byte[] plaintextBytes = System.Security.Cryptography.ProtectedData.Unprotect(ciphertextBytes, null, DataProtectionScope.LocalMachine); ciphertextMemoryStream.Close(); // Deserialize the plaintext byte array. EncryptedSettings deserializedSettings = null; System.IO.MemoryStream plaintextStream = new System.IO.MemoryStream(plaintextBytes); System.Xml.XmlTextReader reader = new XmlTextReader(plaintextStream); XmlSerializer serializer = EncryptedSettings.Serializer; lock (serializer) { deserializedSettings = (EncryptedSettings)serializer.Deserialize(reader); } reader.Close(); plaintextStream.Close(); /* * // This is the unencrypted version. * EncryptedSettings deserializedSettings = null; * System.Xml.XmlTextReader reader = new XmlTextReader(filePath); * XmlSerializer serializer = EncryptedSettings.Serializer; * lock (serializer) * { * deserializedSettings = (EncryptedSettings)serializer.Deserialize(reader); * } * reader.Close(); */ this.AddedUsers = deserializedSettings.AddedUsers; } else { // The specified file does not exist. Save a new one. this.AddedUsers = new UserList(); this.Save(filePath); } }
public bool UserSessionIsInList(int sessionID) { SecurityIdentifier sid = LsaLogonSessions.LogonSessions.GetSidForSessionId(sessionID); if (sid != null) { EncryptedSettings encryptedSettings = new EncryptedSettings(EncryptedSettings.SettingsFilePath); return(encryptedSettings.ContainsSID(sid)); } else { return(false); } }
/// <summary> /// Removes the given security identifier (SID) from the local Administrators group. /// </summary> /// <param name="userSid"> /// The security identifier (SID) to be removed from the local Administrators group. /// </param> /// <param name="reason"> /// The reason for the removal. /// </param> public static void RemoveUser(SecurityIdentifier userSid, RemovalReason reason) { // TODO: Only do this if the user is a member of the group? if ((LocalAdminGroup != null) && (userSid != null)) { SecurityIdentifier[] localAdminSids = GetLocalGroupMembers(LocalAdminGroup.SamAccountName); foreach (SecurityIdentifier sid in localAdminSids) { if (sid == userSid) { string accountName = GetAccountNameFromSID(userSid); int result = RemoveLocalGroupMembers(LocalAdminGroup.SamAccountName, userSid); if (result == 0) { EncryptedSettings encryptedSettings = new EncryptedSettings(EncryptedSettings.SettingsFilePath); encryptedSettings.RemoveUser(userSid); string reasonString = Properties.Resources.RemovalReasonUnknown; switch (reason) { case RemovalReason.ServiceStopped: reasonString = Properties.Resources.RemovalReasonServiceStopped; break; case RemovalReason.Timeout: reasonString = Properties.Resources.RemovalReasonTimeout; break; case RemovalReason.UserLogoff: reasonString = Properties.Resources.RemovalReasonUserLogoff; break; case RemovalReason.UserRequest: reasonString = Properties.Resources.RemovalReasonUserRequest; break; } string message = string.Format(Properties.Resources.UserRemoved, userSid, accountName, reasonString); ApplicationLog.WriteEvent(message, EventID.UserRemovedFromAdminsSuccess, System.Diagnostics.EventLogEntryType.Information); } else { ApplicationLog.WriteEvent(string.Format(Properties.Resources.RemovingUserReturnedError, userSid, accountName, result), EventID.UserRemovedFromAdminsFailure, System.Diagnostics.EventLogEntryType.Warning); } } } } }
/// <summary> /// Handles the Elapsed event for the rights removal timer. /// </summary> /// <param name="sender"> /// The timer whose Elapsed event is firing. /// </param> /// <param name="e"> /// Data related to the event. /// </param> private void RemovalTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) { EncryptedSettings encryptedSettings = new EncryptedSettings(EncryptedSettings.SettingsFilePath); User[] expiredUsers = encryptedSettings.GetExpiredUsers(); if (expiredUsers != null) { foreach (User prin in expiredUsers) { LocalAdministratorGroup.RemoveUser(prin.Sid, RemovalReason.Timeout); if ((Settings.EndRemoteSessionsUponExpiration) && (!string.IsNullOrEmpty(prin.RemoteAddress))) { string userName = prin.Name; while (userName.LastIndexOf("\\") >= 0) { userName = userName.Substring(userName.LastIndexOf("\\") + 1); } // TODO: Log this return code if it's not a success? int returnCode = 0; if (!string.IsNullOrEmpty(userName)) { returnCode = LocalAdministratorGroup.EndNetworkSession(string.Format(@"\\{0}", prin.RemoteAddress), userName); } } } } LocalAdministratorGroup.ValidateAllAddedUsers(); if (Settings.LogElevatedProcesses != ElevatedProcessLogging.Never) { if (this.processWatchSession == null) { StartTracing(); } if (this.processWatchSession != null) { LogProcesses(); } } }
/// <summary> /// Returns a value indicating whether a user is in the /// list of added users. /// </summary> /// <returns> /// Returns true if the given user is already in the list of added /// users. Otherwise, false is returned. /// </returns> public bool UserIsInList() { WindowsIdentity userIdentity = null; if (ServiceSecurityContext.Current != null) { userIdentity = ServiceSecurityContext.Current.WindowsIdentity; } if (userIdentity != null) { EncryptedSettings encryptedSettings = new EncryptedSettings(EncryptedSettings.SettingsFilePath); return(encryptedSettings.ContainsSID(userIdentity.User)); } else { return(false); } }
/// <summary> /// Validates that all of the users stored in the on-disk user list /// are in the local Adminstrators group if they're supposed to be, and vice-vera. /// </summary> public static void ValidateAllAddedUsers() { // Get a list of the users stored in the on-disk list. EncryptedSettings encryptedSettings = new EncryptedSettings(EncryptedSettings.SettingsFilePath); SecurityIdentifier[] addedUserList = encryptedSettings.AddedUserSIDs; // Get a list of the current members of the Administrators group. SecurityIdentifier[] localAdminSids = null; if ((addedUserList.Length > 0) && (LocalAdminGroup != null)) { localAdminSids = GetLocalGroupMembers(LocalAdminGroup.SamAccountName); } for (int i = 0; i < addedUserList.Length; i++) { bool sidFoundInAdminsGroup = false; if ((addedUserList[i] != null) && (localAdminSids != null)) { foreach (SecurityIdentifier sid in localAdminSids) { if (sid == addedUserList[i]) { sidFoundInAdminsGroup = true; break; } } AdminGroupManipulator adminGroup = new AdminGroupManipulator(); if (sidFoundInAdminsGroup) { // User's SID was found in the local administrators group. DateTime?expirationTime = encryptedSettings.GetExpirationTime(addedUserList[i]); if (expirationTime.HasValue) { // The user's rights expire at some point. if (expirationTime.Value > DateTime.Now) { // The user's administrator rights expire in the future. // Nothing to do here, since the user is already in the administrators group. } else { // The user's administrator rights have expired. LocalAdministratorGroup.RemoveUser(addedUserList[i], RemovalReason.Timeout); } } else { // The user's rights never expire. // Get a WindowsIdentity object for the user matching the added user SID. WindowsIdentity sessionIdentity = null; WindowsIdentity userIdentity = null; int[] loggedOnSessionIDs = LsaLogonSessions.LogonSessions.GetLoggedOnUserSessionIds(); foreach (int sessionId in loggedOnSessionIDs) { sessionIdentity = LsaLogonSessions.LogonSessions.GetWindowsIdentityForSessionId(sessionId); if ((sessionIdentity != null) && (sessionIdentity.User == addedUserList[i])) { userIdentity = sessionIdentity; break; } } if ( (Settings.AutomaticAddAllowed != null) && (Settings.AutomaticAddAllowed.Length > 0) && (adminGroup.UserIsAuthorized(Settings.AutomaticAddAllowed, Settings.AutomaticAddDenied)) ) { // The user is an automatically-added user. // Nothing to do here. The user is an automatically-added one, and their rights don't expire. } else { // The user is not an automatically-added user. // Users who are not automatically added should not have non-expiring rights. Remove this user. LocalAdministratorGroup.RemoveUser(addedUserList[i], RemovalReason.Timeout); } } } else { // User's SID was not found in the local administrators group. DateTime?expirationTime = encryptedSettings.GetExpirationTime(addedUserList[i]); if (expirationTime.HasValue) { // The user's rights expire at some point. if (expirationTime.Value > DateTime.Now) { // The user's administrator rights expire in the future. string accountName = GetAccountNameFromSID(addedUserList[i]); if (Settings.OverrideRemovalByOutsideProcess) { ApplicationLog.WriteEvent(string.Format(Properties.Resources.UserRemovedByOutsideProcess + " " + Properties.Resources.AddingUserBackToAdministrators, addedUserList[i], string.IsNullOrEmpty(accountName) ? Properties.Resources.UnknownAccount : accountName), EventID.UserRemovedByExternalProcess, System.Diagnostics.EventLogEntryType.Information); AddUserToAdministrators(addedUserList[i]); } else { ApplicationLog.WriteEvent(string.Format(Properties.Resources.UserRemovedByOutsideProcess + " " + Properties.Resources.RemovingUserFromList, addedUserList[i], string.IsNullOrEmpty(accountName) ? Properties.Resources.UnknownAccount : accountName), EventID.UserRemovedByExternalProcess, System.Diagnostics.EventLogEntryType.Information); encryptedSettings.RemoveUser(addedUserList[i]); } } else { // The user's administrator rights have expired. // No need to remove from the administrators group, as we already know the SID // is not present in the group. encryptedSettings.RemoveUser(addedUserList[i]); } } else { // The user's rights never expire. // Get a WindowsIdentity object for the user matching the added user SID. WindowsIdentity sessionIdentity = null; WindowsIdentity userIdentity = null; int[] loggedOnSessionIDs = LsaLogonSessions.LogonSessions.GetLoggedOnUserSessionIds(); foreach (int sessionId in loggedOnSessionIDs) { sessionIdentity = LsaLogonSessions.LogonSessions.GetWindowsIdentityForSessionId(sessionId); if ((sessionIdentity != null) && (sessionIdentity.User == addedUserList[i])) { userIdentity = sessionIdentity; break; } } if ( (Settings.AutomaticAddAllowed != null) && (Settings.AutomaticAddAllowed.Length > 0) && (adminGroup.UserIsAuthorized(Settings.AutomaticAddAllowed, Settings.AutomaticAddDenied)) ) { // The user is an automatically-added user. // The users rights do not expire, but they are an automatically-added user and are missing // from the Administrators group. Add the user back in. AddUserToAdministrators(addedUserList[i]); } else { // The user is not an automatically-added user. // The user is not in the Administrators group now, but they are // listed as having non-expiring rights, even though they are not // automatically added. This should never really happen, but // just in case, we'll remove them from the on-disk user list. encryptedSettings.RemoveUser(addedUserList[i]); } } } } } }
/// <summary> /// Executes when a change event is received from a Terminal Server session. /// </summary> /// <param name="changeDescription"> /// Identifies the type of session change and the session to which it applies. /// </param> protected override void OnSessionChange(SessionChangeDescription changeDescription) { switch (changeDescription.Reason) { // The user has logged off from a session, either locally or remotely. case SessionChangeReason.SessionLogoff: EncryptedSettings encryptedSettings = new EncryptedSettings(EncryptedSettings.SettingsFilePath); System.Collections.Generic.List <SecurityIdentifier> sidsToRemove = new System.Collections.Generic.List <SecurityIdentifier>(encryptedSettings.AddedUserSIDs); int[] sessionIds = LsaLogonSessions.LogonSessions.GetLoggedOnUserSessionIds(); // For any user that is still logged on, remove their SID from the list of // SIDs to be removed from Administrators. That is, let the users who are still // logged on stay in the Administrators group. foreach (int id in sessionIds) { SecurityIdentifier sid = LsaLogonSessions.LogonSessions.GetSidForSessionId(id); if (sid != null) { if (sidsToRemove.Contains(sid)) { sidsToRemove.Remove(sid); } } } // Process the list of SIDs to be removed from Administrators. for (int i = 0; i < sidsToRemove.Count; i++) { if ( // If the user is not remote. (!(encryptedSettings.ContainsSID(sidsToRemove[i]) && encryptedSettings.IsRemote(sidsToRemove[i]))) && // If admin rights are to be removed on logoff, or the user's rights do not expire. (Settings.RemoveAdminRightsOnLogout || !encryptedSettings.GetExpirationTime(sidsToRemove[i]).HasValue) ) { LocalAdministratorGroup.RemoveUser(sidsToRemove[i], RemovalReason.UserLogoff); } } /* * In theory, this code should remove the user associated with the logoff, but it doesn't work. * SecurityIdentifier sid = LsaLogonSessions.LogonSessions.GetSidForSessionId(changeDescription.SessionId); * if (!(UserList.ContainsSID(sid) && UserList.IsRemote(sid))) * { * LocalAdministratorGroup.RemoveUser(sid, RemovalReason.UserLogoff); * } */ break; // The user has logged on to a session, either locally or remotely. case SessionChangeReason.SessionLogon: WindowsIdentity userIdentity = LsaLogonSessions.LogonSessions.GetWindowsIdentityForSessionId(changeDescription.SessionId); if (userIdentity != null) { NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport); ChannelFactory <IAdminGroup> namedPipeFactory = new ChannelFactory <IAdminGroup>(binding, Settings.NamedPipeServiceBaseAddress); IAdminGroup channel = namedPipeFactory.CreateChannel(); bool userIsAuthorizedForAutoAdd = channel.UserIsAuthorized(Settings.AutomaticAddAllowed, Settings.AutomaticAddDenied); namedPipeFactory.Close(); // If the user is in the automatic add list, then add them to the Administrators group. if ( (Settings.AutomaticAddAllowed != null) && (Settings.AutomaticAddAllowed.Length > 0) && (userIsAuthorizedForAutoAdd /*UserIsAuthorized(userIdentity, Settings.AutomaticAddAllowed, Settings.AutomaticAddDenied)*/) ) { LocalAdministratorGroup.AddUser(userIdentity, null, null); } } else { ApplicationLog.WriteEvent(Properties.Resources.UserIdentifyIsNull, EventID.DebugMessage, System.Diagnostics.EventLogEntryType.Warning); } break; /* * // The user has reconnected or logged on to a remote session. * case SessionChangeReason.RemoteConnect: * ApplicationLog.WriteInformationEvent(string.Format("Remote connect. Session ID: {0}", changeDescription.SessionId), EventID.SessionChangeEvent); * break; */ /* * // The user has disconnected or logged off from a remote session. * case SessionChangeReason.RemoteDisconnect: * ApplicationLog.WriteInformationEvent(string.Format("Remote disconnect. Session ID: {0}", changeDescription.SessionId), EventID.SessionChangeEvent); * break; */ /* * // The user has locked their session. * case SessionChangeReason.SessionLock: * ApplicationLog.WriteInformationEvent(string.Format("Session lock. Session ID: {0}", changeDescription.SessionId), EventID.SessionChangeEvent); * break; */ /* * // The user has unlocked their session. * case SessionChangeReason.SessionUnlock: * ApplicationLog.WriteInformationEvent(string.Format("Session unlock. Session ID: {0}", changeDescription.SessionId), EventID.SessionChangeEvent); * break; */ } base.OnSessionChange(changeDescription); }