//******************************************************************************************************// WindowsUserInfo.cs - Gbtc//// Copyright © 2014, Grid Protection Alliance. All Rights Reserved.//// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See// the NOTICE file distributed with this work for additional information regarding copyright ownership.// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may// not use this file except in compliance with the License. You may obtain a copy of the License at://// http://www.opensource.org/licenses/MIT//// Unless agreed to in writing, the subject software distributed under the License is distributed on an// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the// License for the specific language governing permissions and limitations.//// Code Modification History:// ----------------------------------------------------------------------------------------------------// 08/27/2014 - J. Ritchie Carroll// Generated original version of source code.////****************************************************************************************************** using System;using System.Collections;using System.Collections.Generic;using System.DirectoryServices;using System.IO;using System.Linq;using System.Management;using System.Reflection;using System.Runtime.InteropServices;using System.Security;using System.Security.Principal;using System.Text.RegularExpressions;using System.Threading;using GSF.Interop;using GSF.IO;using Microsoft.Win32; namespace GSF.Identity{ // Windows implementation of key UserInfo class elements internal sealed class WindowsUserInfo : IUserInfo { #region [ Members ] // Constants private const string LogonDomainRegistryKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"; private const string LogonDomainRegistryValue = "DefaultDomainName"; // Fields private readonly UserInfo m_parent; private DirectoryEntry m_userEntry; private bool m_domainRespondsForUser; private bool m_isLocalAccount; private bool m_enabled; private bool m_disposed; private bool m_initialized; #endregion #region [ Constructors ] public WindowsUserInfo(UserInfo parent) { m_parent = parent; // Attempt to attach to power mode changed system event try { SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; } catch { // This event will not be raised when running from a Windows service since // a service does not establish a message loop. } } ~WindowsUserInfo() { Dispose(false); } #endregion #region [ Properties ] public bool DomainRespondsForUser { get { if (!m_initialized) { // Attempt to initialize try { Initialize(); } catch (InitializationException) { // Initialization failures are due to domain not responding, // member flag is set in Initialize() method. } } return m_domainRespondsForUser; } } public bool Exists { get { bool exists = false; if (!m_initialized) { // Attempt to initialize try { Initialize(); } catch (InitializationException) { // User could not be found - this could simply mean that ActiveDirectory is unavailable (e.g., laptop disconnected from the domain). // In this case, if user logged in with cached credentials they are at least authenticated so we can assume that the user exists... WindowsPrincipal windowsPrincipal = Thread.CurrentPrincipal as WindowsPrincipal; exists = (object)windowsPrincipal != null && !string.IsNullOrEmpty(m_parent.LoginID) && windowsPrincipal.Identity.Name.Equals(m_parent.LoginID, StringComparison.OrdinalIgnoreCase) && windowsPrincipal.Identity.IsAuthenticated; } } if (!exists) { if (m_isLocalAccount) { try { exists = DirectoryEntry.Exists("WinNT://" + m_parent.Domain + "/" + m_parent.UserName); } catch { exists = false; } } else { exists = ((object)m_userEntry != null); } } return exists; } } public bool Enabled { get { return m_enabled; } set { m_enabled = value; } } public DateTime LastLogon { get { if (m_enabled) { try { if (m_isLocalAccount) return DateTime.Parse(GetUserPropertyValue("lastLogin")); return DateTime.FromFileTime(ConvertToLong(GetUserPropertyValueCollection("lastLogon").Value)); } catch { return DateTime.MinValue; } } return DateTime.MinValue; } } public DateTime AccountCreationDate { get { if (m_enabled) { try { if (m_isLocalAccount) { string profilePath = GetUserPropertyValue("profile"); if (string.IsNullOrEmpty(profilePath) || !Directory.Exists(profilePath)) { // Remove any trailing directory separator character from the file path. string rootFolder = FilePath.AddPathSuffix(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)); string userFolder = FilePath.GetLastDirectoryName(rootFolder); int folderLocation = rootFolder.LastIndexOf(userFolder, StringComparison.OrdinalIgnoreCase); // Remove user profile name for current user (this class may be for user other than owner of current thread) rootFolder = FilePath.AddPathSuffix(rootFolder.Substring(0, folderLocation)); // Create profile path for user referenced in this UserInfo class profilePath = FilePath.AddPathSuffix(rootFolder + m_parent.UserName); } return Directory.GetCreationTime(profilePath); } return Convert.ToDateTime(GetUserPropertyValue("whenCreated")); } catch { return DateTime.MinValue; } } return DateTime.MinValue; } } public DateTime NextPasswordChangeDate { get { DateTime passwordChangeDate = DateTime.MaxValue; if (m_enabled && !m_parent.PasswordCannotChange && !m_parent.PasswordDoesNotExpire) { try { if (m_isLocalAccount) { Ticks maxPasswordTicksAge = MaximumPasswordAge; if (maxPasswordTicksAge >= 0) { // WinNT properties are in seconds, not ticks long passwordAge = long.Parse(GetUserPropertyValue("passwordAge")); long maxPasswordAge = (long)maxPasswordTicksAge.ToSeconds(); if (passwordAge > maxPasswordAge || GetUserPropertyValue("passwordExpired").ParseBoolean()) { // User must change password on next logon. passwordChangeDate = DateTime.UtcNow; } else { // User must change password periodically. passwordChangeDate = DateTime.UtcNow.AddSeconds(maxPasswordAge - passwordAge); } } } else { long passwordSetOn = ConvertToLong(GetUserPropertyValueCollection("pwdLastSet").Value); if (passwordSetOn == 0) { // User must change password on next logon. passwordChangeDate = DateTime.UtcNow; } else { // User must change password periodically. long maxPasswordAge = MaximumPasswordAge; // Ignore extremes if (maxPasswordAge != long.MaxValue && maxPasswordAge > 0) passwordChangeDate = DateTime.FromFileTime(passwordSetOn).AddDays(TimeSpan.FromTicks(maxPasswordAge).Duration().Days); } } } catch { return DateTime.MaxValue; } } return passwordChangeDate; } } public int LocalUserAccountControl { get { int userAccountControl = -1; string userPropertyValue; if (m_enabled && m_isLocalAccount) { userPropertyValue = GetUserPropertyValue("userFlags"); if (string.IsNullOrEmpty(userPropertyValue)) throw new SecurityException(string.Format(UserInfo.SecurityExceptionFormat, "Local", UserInfo.CurrentUserID, "local machine accounts")); if (!int.TryParse(userPropertyValue, out userAccountControl)) throw new InvalidOperationException(string.Format(UserInfo.UnknownErrorFormat, m_parent.LoginID, userPropertyValue)); } return userAccountControl; } } public Ticks MaximumPasswordAge { get { if (m_enabled) { string maxAgePropertyValue = string.Empty; if (m_isLocalAccount) { maxAgePropertyValue = GetUserPropertyValue("maxPasswordAge"); } else { WindowsImpersonationContext currentContext = null; try { currentContext = m_parent.ImpersonatePrivilegedAccount(); using (DirectorySearcher searcher = CreateDirectorySearcher()) { SearchResult searchResult = searcher.FindOne(); if ((object)searchResult != null && searchResult.Properties.Contains("maxPwdAge")) maxAgePropertyValue = searchResult.Properties["maxPwdAge"][0].ToString(); } } finally { UserInfo.EndImpersonation(currentContext); } } if (string.IsNullOrEmpty(maxAgePropertyValue)) return -1; long maxPasswordAge = long.Parse(maxAgePropertyValue); if (m_isLocalAccount) return Ticks.FromSeconds(maxPasswordAge); return maxPasswordAge; } return -1; } } public string[] Groups { get { HashSet<string> groups = new HashSet<string>(StringComparer.OrdinalIgnoreCase); string groupName; if (m_enabled) { if (m_isLocalAccount) { // Get fixed list of BUILTIN local groups string[] builtInGroups = UserInfo.GetBuiltInLocalGroups(); // Get local groups that local user is a member of object localGroups = m_userEntry.Invoke("Groups"); foreach (object localGroup in (IEnumerable)localGroups) { using (DirectoryEntry groupEntry = new DirectoryEntry(localGroup)) { groupName = groupEntry.Name; if (Array.BinarySearch(builtInGroups, groupName, StringComparer.OrdinalIgnoreCase) < 0) groups.Add(Environment.MachineName + "\\" + groupName); else groups.Add("BUILTIN\\" + groupName); } } // Union this with a manual scan of local groups since "Groups" call will not derive // "NT AUTHORITY\Authenticated Users" which will miss "BUILTIN\Users" for authenticated // users. This will also catch other groups that may have been missed by "Groups" call. groups.UnionWith(LocalGroups); } else { // Get active directory groups that active directory user is a member of m_userEntry.RefreshCache(new[] { "TokenGroups" }); foreach (byte[] sid in m_userEntry.Properties["TokenGroups"]) { try { groupName = new SecurityIdentifier(sid, 0).Translate(typeof(NTAccount)).ToString(); groups.Add(groupName); } catch (IdentityNotMappedException) { // This might happen when AD server is not accessible. } catch (SystemException) { // Ignoring group SID's that fail to translate to an active AD group, for whatever reason } } // Union this with local groups that active directory user is a member of. The // "TokenGroups" call doesn't get all of these :-p, generally this call only // returns some of the common "BUILTIN\*" groups. groups.UnionWith(LocalGroups); } } return groups.ToArray(); } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")] public string[] LocalGroups { get { List<string> groups = new List<string>(); const string authenticatedUsersGroupPath = "WinNT://NT AUTHORITY/Authenticated Users"; // Get local groups that user is a member of DirectoryEntry root = new DirectoryEntry("WinNT://.,computer", null, null, AuthenticationTypes.Secure); string userPath = string.Format("WinNT://{0}/{1}", m_parent.Domain, m_parent.UserName); string groupName; bool userIsAuthenticated = false; string[] builtInGroups = UserInfo.GetBuiltInLocalGroups(); // See if identity for current thread matches user information login ID - when this is true we can check // if the current user is authenticated. When a user is authenticated we will also need to validate if // the local groups that contain the local "NT AUTHORITY\Authenticated Users" group. if (Thread.CurrentPrincipal.Identity.Name.Equals(m_parent.LoginID, StringComparison.OrdinalIgnoreCase)) userIsAuthenticated = Thread.CurrentPrincipal.Identity.IsAuthenticated; // Only enumerate groups root.Children.SchemaFilter.Add("Group"); // Have to scan each local group for the AD user... foreach (DirectoryEntry groupEntry in root.Children) { if ((bool)groupEntry.Invoke("IsMember", new object[] { userPath }) || (userIsAuthenticated && (bool)groupEntry.Invoke("IsMember", new object[] { authenticatedUsersGroupPath }))) { groupName = groupEntry.Name; if (Array.BinarySearch(builtInGroups, groupName, StringComparer.OrdinalIgnoreCase) < 0) groups.Add(Environment.MachineName + "\\" + groupName); else groups.Add("BUILTIN\\" + groupName); } } return groups.ToArray(); } } public string FullLocalUserName { get { string name = GetUserPropertyValue("fullName"); if (string.IsNullOrEmpty(name)) name = GetUserPropertyValue("Name"); return name; } } public bool IsLocalAccount { get { return m_isLocalAccount; } } Lines 1–500 of 1513. Load more
//****************************************************************************************************** // WindowsUserInfo.cs - Gbtc // // Copyright © 2014, Grid Protection Alliance. All Rights Reserved. // // Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See // the NOTICE file distributed with this work for additional information regarding copyright ownership. // The GPA licenses this file to you under the MIT License (MIT), the "License"; you may // not use this file except in compliance with the License. You may obtain a copy of the License at: // // http://www.opensource.org/licenses/MIT // // Unless agreed to in writing, the subject software distributed under the License is distributed on an // "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the // License for the specific language governing permissions and limitations. // // Code Modification History: // ---------------------------------------------------------------------------------------------------- // 08/27/2014 - J. Ritchie Carroll // Generated original version of source code. // //****************************************************************************************************** using System; using System.Collections; using System.Collections.Generic; using System.DirectoryServices; using System.IO; using System.Linq; using System.Management; using System.Reflection; using System.Runtime.InteropServices; using System.Security; using System.Security.Principal; using System.Text.RegularExpressions; using System.Threading; using GSF.Interop; using GSF.IO; using Microsoft.Win32; namespace GSF.Identity { // Windows implementation of key UserInfo class elements internal sealed class WindowsUserInfo : IUserInfo { #region [ Members ] // Constants private const string LogonDomainRegistryKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"; private const string LogonDomainRegistryValue = "DefaultDomainName"; // Fields private readonly UserInfo m_parent; private DirectoryEntry m_userEntry; private bool m_domainRespondsForUser; private bool m_isLocalAccount; private bool m_enabled; private bool m_disposed; private bool m_initialized; #endregion #region [ Constructors ] public WindowsUserInfo(UserInfo parent) { m_parent = parent; // Attempt to attach to power mode changed system event try { SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged; } catch { // This event will not be raised when running from a Windows service since // a service does not establish a message loop. } } ~WindowsUserInfo() { Dispose(false); } #endregion #region [ Properties ] public bool DomainRespondsForUser { get { if (!m_initialized) { // Attempt to initialize try { Initialize(); } catch (InitializationException) { // Initialization failures are due to domain not responding, // member flag is set in Initialize() method. } } return m_domainRespondsForUser; } } public bool Exists { get { bool exists = false; if (!m_initialized) { // Attempt to initialize try { Initialize(); } catch (InitializationException) { // User could not be found - this could simply mean that ActiveDirectory is unavailable (e.g., laptop disconnected from the domain). // In this case, if user logged in with cached credentials they are at least authenticated so we can assume that the user exists... WindowsPrincipal windowsPrincipal = Thread.CurrentPrincipal as WindowsPrincipal; exists = (object)windowsPrincipal != null && !string.IsNullOrEmpty(m_parent.LoginID) && windowsPrincipal.Identity.Name.Equals(m_parent.LoginID, StringComparison.OrdinalIgnoreCase) && windowsPrincipal.Identity.IsAuthenticated; } } if (!exists) { if (m_isLocalAccount) { try { exists = DirectoryEntry.Exists("WinNT://" + m_parent.Domain + "/" + m_parent.UserName); } catch { exists = false; } } else { exists = ((object)m_userEntry != null); } } return exists; } } public bool Enabled { get { return m_enabled; } set { m_enabled = value; } } public DateTime LastLogon { get { if (m_enabled) { try { if (m_isLocalAccount) return DateTime.Parse(GetUserPropertyValue("lastLogin")); return DateTime.FromFileTime(ConvertToLong(GetUserPropertyValueCollection("lastLogon").Value)); } catch { return DateTime.MinValue; } } return DateTime.MinValue; } } public DateTime AccountCreationDate { get { if (m_enabled) { try { if (m_isLocalAccount) { string profilePath = GetUserPropertyValue("profile"); if (string.IsNullOrEmpty(profilePath) || !Directory.Exists(profilePath)) { // Remove any trailing directory separator character from the file path. string rootFolder = FilePath.AddPathSuffix(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)); string userFolder = FilePath.GetLastDirectoryName(rootFolder); int folderLocation = rootFolder.LastIndexOf(userFolder, StringComparison.OrdinalIgnoreCase); // Remove user profile name for current user (this class may be for user other than owner of current thread) rootFolder = FilePath.AddPathSuffix(rootFolder.Substring(0, folderLocation)); // Create profile path for user referenced in this UserInfo class profilePath = FilePath.AddPathSuffix(rootFolder + m_parent.UserName); } return Directory.GetCreationTime(profilePath); } return Convert.ToDateTime(GetUserPropertyValue("whenCreated")); } catch { return DateTime.MinValue; } } return DateTime.MinValue; } } public DateTime NextPasswordChangeDate { get { DateTime passwordChangeDate = DateTime.MaxValue; if (m_enabled && !m_parent.PasswordCannotChange && !m_parent.PasswordDoesNotExpire) { try { if (m_isLocalAccount) { Ticks maxPasswordTicksAge = MaximumPasswordAge; if (maxPasswordTicksAge >= 0) { // WinNT properties are in seconds, not ticks long passwordAge = long.Parse(GetUserPropertyValue("passwordAge")); long maxPasswordAge = (long)maxPasswordTicksAge.ToSeconds(); if (passwordAge > maxPasswordAge || GetUserPropertyValue("passwordExpired").ParseBoolean()) { // User must change password on next logon. passwordChangeDate = DateTime.UtcNow; } else { // User must change password periodically. passwordChangeDate = DateTime.UtcNow.AddSeconds(maxPasswordAge - passwordAge); } } } else { long passwordSetOn = ConvertToLong(GetUserPropertyValueCollection("pwdLastSet").Value); if (passwordSetOn == 0) { // User must change password on next logon. passwordChangeDate = DateTime.UtcNow; } else { // User must change password periodically. long maxPasswordAge = MaximumPasswordAge; // Ignore extremes if (maxPasswordAge != long.MaxValue && maxPasswordAge > 0) passwordChangeDate = DateTime.FromFileTime(passwordSetOn).AddDays(TimeSpan.FromTicks(maxPasswordAge).Duration().Days); } } } catch { return DateTime.MaxValue; } } return passwordChangeDate; } } public int LocalUserAccountControl { get { int userAccountControl = -1; string userPropertyValue; if (m_enabled && m_isLocalAccount) { userPropertyValue = GetUserPropertyValue("userFlags"); if (string.IsNullOrEmpty(userPropertyValue)) throw new SecurityException(string.Format(UserInfo.SecurityExceptionFormat, "Local", UserInfo.CurrentUserID, "local machine accounts")); if (!int.TryParse(userPropertyValue, out userAccountControl)) throw new InvalidOperationException(string.Format(UserInfo.UnknownErrorFormat, m_parent.LoginID, userPropertyValue)); } return userAccountControl; } } public Ticks MaximumPasswordAge { get { if (m_enabled) { string maxAgePropertyValue = string.Empty; if (m_isLocalAccount) { maxAgePropertyValue = GetUserPropertyValue("maxPasswordAge"); } else { WindowsImpersonationContext currentContext = null; try { currentContext = m_parent.ImpersonatePrivilegedAccount(); using (DirectorySearcher searcher = CreateDirectorySearcher()) { SearchResult searchResult = searcher.FindOne(); if ((object)searchResult != null && searchResult.Properties.Contains("maxPwdAge")) maxAgePropertyValue = searchResult.Properties["maxPwdAge"][0].ToString(); } } finally { UserInfo.EndImpersonation(currentContext); } } if (string.IsNullOrEmpty(maxAgePropertyValue)) return -1; long maxPasswordAge = long.Parse(maxAgePropertyValue); if (m_isLocalAccount) return Ticks.FromSeconds(maxPasswordAge); return maxPasswordAge; } return -1; } } public string[] Groups { get { HashSet<string> groups = new HashSet<string>(StringComparer.OrdinalIgnoreCase); string groupName; if (m_enabled) { if (m_isLocalAccount) { // Get fixed list of BUILTIN local groups string[] builtInGroups = UserInfo.GetBuiltInLocalGroups(); // Get local groups that local user is a member of object localGroups = m_userEntry.Invoke("Groups"); foreach (object localGroup in (IEnumerable)localGroups) { using (DirectoryEntry groupEntry = new DirectoryEntry(localGroup)) { groupName = groupEntry.Name; if (Array.BinarySearch(builtInGroups, groupName, StringComparer.OrdinalIgnoreCase) < 0) groups.Add(Environment.MachineName + "\\" + groupName); else groups.Add("BUILTIN\\" + groupName); } } // Union this with a manual scan of local groups since "Groups" call will not derive // "NT AUTHORITY\Authenticated Users" which will miss "BUILTIN\Users" for authenticated // users. This will also catch other groups that may have been missed by "Groups" call. groups.UnionWith(LocalGroups); } else { // Get active directory groups that active directory user is a member of m_userEntry.RefreshCache(new[] { "TokenGroups" }); foreach (byte[] sid in m_userEntry.Properties["TokenGroups"]) { try { groupName = new SecurityIdentifier(sid, 0).Translate(typeof(NTAccount)).ToString(); groups.Add(groupName); } catch (IdentityNotMappedException) { // This might happen when AD server is not accessible. } catch (SystemException) { // Ignoring group SID's that fail to translate to an active AD group, for whatever reason } } // Union this with local groups that active directory user is a member of. The // "TokenGroups" call doesn't get all of these :-p, generally this call only // returns some of the common "BUILTIN\*" groups. groups.UnionWith(LocalGroups); } } return groups.ToArray(); } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope")] public string[] LocalGroups { get { List<string> groups = new List<string>(); const string authenticatedUsersGroupPath = "WinNT://NT AUTHORITY/Authenticated Users"; // Get local groups that user is a member of DirectoryEntry root = new DirectoryEntry("WinNT://.,computer", null, null, AuthenticationTypes.Secure); string userPath = string.Format("WinNT://{0}/{1}", m_parent.Domain, m_parent.UserName); string groupName; bool userIsAuthenticated = false; string[] builtInGroups = UserInfo.GetBuiltInLocalGroups(); // See if identity for current thread matches user information login ID - when this is true we can check // if the current user is authenticated. When a user is authenticated we will also need to validate if // the local groups that contain the local "NT AUTHORITY\Authenticated Users" group. if (Thread.CurrentPrincipal.Identity.Name.Equals(m_parent.LoginID, StringComparison.OrdinalIgnoreCase)) userIsAuthenticated = Thread.CurrentPrincipal.Identity.IsAuthenticated; // Only enumerate groups root.Children.SchemaFilter.Add("Group"); // Have to scan each local group for the AD user... foreach (DirectoryEntry groupEntry in root.Children) { if ((bool)groupEntry.Invoke("IsMember", new object[] { userPath }) || (userIsAuthenticated && (bool)groupEntry.Invoke("IsMember", new object[] { authenticatedUsersGroupPath }))) { groupName = groupEntry.Name; if (Array.BinarySearch(builtInGroups, groupName, StringComparer.OrdinalIgnoreCase) < 0) groups.Add(Environment.MachineName + "\\" + groupName); else groups.Add("BUILTIN\\" + groupName); } } return groups.ToArray(); } } public string FullLocalUserName { get { string name = GetUserPropertyValue("fullName"); if (string.IsNullOrEmpty(name)) name = GetUserPropertyValue("Name"); return name; } } public bool IsLocalAccount { get { return m_isLocalAccount; } }