Beispiel #1
0
        /// <summary>
        /// Returns a list of groups of which the user is a member.  It does so in a fashion that
        /// may seem strange since one can call UserPrincipal.GetGroups, but seems to be much faster
        /// in my tests.
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        private static List <GroupPrincipal> GetGroups(UserPrincipal user)
        {
            List <GroupPrincipal> result = new List <GroupPrincipal>();

            // Get all groups using a PrincipalSearcher and
            GroupPrincipal filter = new GroupPrincipal(m_machinePrincipal);

            using (PrincipalSearcher searcher = new PrincipalSearcher(filter))
            {
                PrincipalSearchResult <Principal> sResult = searcher.FindAll();
                foreach (Principal p in sResult)
                {
                    if (p is GroupPrincipal)
                    {
                        GroupPrincipal gp = (GroupPrincipal)p;
                        if (LocalAccount.IsUserInGroup(user, gp))
                        {
                            result.Add(gp);
                        }
                        else
                        {
                            gp.Dispose();
                        }
                    }
                    else
                    {
                        p.Dispose();
                    }
                }
            }
            return(result);
        }
Beispiel #2
0
        private UserPrincipal CreateOrGetUserPrincipal(UserInformation userInfo)
        {
            UserPrincipal user = null;

            if (!LocalAccount.UserExists(userInfo.Username))
            {
                // See note about MS bug in CreateOrGetGroupPrincipal to understand the mix of DE/Principal here:
                using (user = new UserPrincipal(m_machinePrincipal))
                {
                    user.Name = userInfo.Username;
                    user.SetPassword(userInfo.Password);
                    user.Description     = "pGina created";
                    userInfo.Description = user.Description;
                    if (userInfo.PasswordEXP)
                    {
                        user.ExpirePasswordNow();
                    }
                    user.Save();

                    // Sync via DE
                    SyncUserPrincipalInfo(userInfo);

                    // We have to re-fetch to get changes made via underlying DE
                    return(GetUserPrincipal(user.Name));
                }
            }

            user = GetUserPrincipal(userInfo.Username);
            if (user == null)
            {
                m_logger.ErrorFormat("Unable to get user principal for account that apparently exists: {0}", userInfo.Username);
            }

            return(user);
        }
Beispiel #3
0
        private UserPrincipal CreateOrGetUserPrincipal(UserInformation userInfo)
        {
            UserPrincipal user = null;

            if (!LocalAccount.UserExists(userInfo.Username))
            {
                // See note about MS bug in CreateOrGetGroupPrincipal to understand the mix of DE/Principal here:
                using (user = new UserPrincipal(m_machinePrincipal))
                {
                    user.Name = userInfo.Username;
                    user.SetPassword(userInfo.Password);
                    user.Save();

                    // Sync via DE
                    SyncUserPrincipalInfo(user, userInfo);

                    // We have to re-fetch to get changes made via underlying DE
                    return(GetUserPrincipal(user.Name));
                }
            }

            user = GetUserPrincipal(userInfo.Username);
            if (user != null)
            {
                return(user);
            }
            else
            {
                throw new Exception(
                          String.Format("Unable to get user principal for account that apparently exists: {0}", userInfo.Username));
            }
        }
Beispiel #4
0
        public BooleanResult ChangePassword(ChangePasswordInfo cpInfo, ChangePasswordPluginActivityInfo pluginInfo)
        {
            m_logger.Debug("ChangePassword()");

            // Verify the old password
            if (Abstractions.WindowsApi.pInvokes.ValidateCredentials(cpInfo.Username, cpInfo.OldPassword))
            {
                m_logger.DebugFormat("Authenticated via old password: {0}", cpInfo.Username);
            }
            else
            {
                return(new BooleanResult {
                    Success = false, Message = "Current password or username is not valid."
                });
            }

            using (UserPrincipal user = LocalAccount.GetUserPrincipal(cpInfo.Username))
            {
                if (user != null)
                {
                    m_logger.DebugFormat("Found principal, changing password for {0}", cpInfo.Username);
                    user.SetPassword(cpInfo.NewPassword);
                }
                else
                {
                    return(new BooleanResult {
                        Success = false, Message = "Local machine plugin internal error: directory entry not found."
                    });
                }
            }

            return(new BooleanResult {
                Success = true, Message = "Local password successfully changed."
            });
        }
Beispiel #5
0
        public void SyncToLocalUser()
        {
            m_logger.Debug("SyncToLocalUser()");
            using (UserPrincipal user = CreateOrGetUserPrincipal(UserInfo))
            {
                // Force password and fullname match (redundant if we just created, but oh well)
                SyncUserPrincipalInfo(user, UserInfo);

                try
                {
                    List <SecurityIdentifier> ignoredSids = new List <SecurityIdentifier>(new SecurityIdentifier[] {
                        new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null),    // "Authenticated Users"
                        new SecurityIdentifier("S-1-1-0"),                                      // "Everyone"
                    });

                    // First remove from any local groups they aren't supposed to be in
                    m_logger.Debug("Checking for groups to remove.");
                    List <GroupPrincipal> localGroups = LocalAccount.GetGroups(user);
                    foreach (GroupPrincipal group in localGroups)
                    {
                        m_logger.DebugFormat("Remove {0}?", group.Name);
                        // Skip ignored sids
                        if (!ignoredSids.Contains(group.Sid))
                        {
                            GroupInformation gi = new GroupInformation()
                            {
                                Name = group.Name, SID = group.Sid, Description = group.Description
                            };
                            if (!UserInfo.InGroup(gi))
                            {
                                m_logger.DebugFormat("Removing user {0} from group {1}", user.Name, group.Name);
                                RemoveUserFromGroup(user, group);
                            }
                        }
                        group.Dispose();
                    }

                    // Now add to any they aren't already in that they should be
                    m_logger.Debug("Checking for groups to add");
                    foreach (GroupInformation groupInfo in UserInfo.Groups)
                    {
                        m_logger.DebugFormat("Add {0}?", groupInfo.Name);
                        if (!IsUserInGroup(user, groupInfo))
                        {
                            using (GroupPrincipal group = CreateOrGetGroupPrincipal(groupInfo))
                            {
                                m_logger.DebugFormat("Adding user {0} to group {1}", user.Name, group.Name);
                                AddUserToGroup(user, group);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new GroupSyncException(e);
                }
            }
            m_logger.Debug("End SyncToLocalUser()");
        }
Beispiel #6
0
        public BooleanResult AuthenticateUser(SessionProperties properties)
        {
            try
            {
                bool alwaysAuth = Settings.Store.AlwaysAuthenticate;

                m_logger.DebugFormat("AuthenticateUser({0})", properties.Id.ToString());

                // Get user info
                UserInformation userInfo = properties.GetTrackedSingle <UserInformation>();
                m_logger.DebugFormat("Found username: {0}", userInfo.Username);

                // Should we authenticate? Only if user has not yet authenticated, or we are not in fallback mode
                if (alwaysAuth || !HasUserAuthenticatedYet(properties))
                {
                    if (LocalAccount.UserExists(userInfo.Username))
                    {
                        // We use a pInvoke here instead of using PrincipalContext.ValidateCredentials
                        // due to the fact that the latter will throw an exception when the network is disconnected.
                        if (Abstractions.WindowsApi.pInvokes.ValidateCredentials(userInfo.Username, userInfo.Password))
                        {
                            m_logger.InfoFormat("Authenticated user: {0}", userInfo.Username);
                            userInfo.Domain = Environment.MachineName;

                            m_logger.Debug("AuthenticateUser: Mirroring group membership from SAM");
                            LocalAccount.SyncLocalGroupsToUserInfo(userInfo);

                            // Return success
                            return(new BooleanResult()
                            {
                                Success = true
                            });
                        }
                    }
                    else
                    {
                        m_logger.InfoFormat("User {0} does not exist on this machine.", userInfo.Username);
                    }
                }

                m_logger.ErrorFormat("Failed to authenticate user: {0}", userInfo.Username);
                // Note that we don't include a message.  We are a last chance auth, and want previous/failed plugins
                //  to have the honor of explaining why.
                return(new BooleanResult()
                {
                    Success = false, Message = null
                });
            }
            catch (Exception e)
            {
                m_logger.ErrorFormat("AuthenticateUser exception: {0}", e);
                throw;  // Allow pGina service to catch and handle exception
            }
        }
Beispiel #7
0
 /// <summary>
 /// This is a faster technique for determining whether or not a user exists on the local
 /// machine.  UserPrincipal.FindByIdentity tends to be quite slow in general, so if
 /// you only need to know whether or not the account exists, this method is much
 /// faster.
 /// </summary>
 /// <param name="strUserName">The user name</param>
 /// <returns>Whether or not the account with the given user name exists on the system</returns>
 public static bool UserExists(string strUserName)
 {
     try
     {
         using (DirectoryEntry userEntry = LocalAccount.GetUserDirectoryEntry(strUserName))
         {
             return(userEntry != null);
         }
     }
     catch (Exception)
     {
         return(false);
     }
 }
Beispiel #8
0
        // Load userInfo.Username's group list and populate userInfo.Groups accordingly
        public static void SyncLocalGroupsToUserInfo(UserInformation userInfo)
        {
            ILog logger = LogManager.GetLogger("LocalAccount.SyncLocalGroupsToUserInfo");

            try
            {
                SecurityIdentifier EveryoneSid           = new SecurityIdentifier("S-1-1-0");
                SecurityIdentifier AuthenticatedUsersSid = new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null);

                if (LocalAccount.UserExists(userInfo.Username))
                {
                    using (UserPrincipal user = LocalAccount.GetUserPrincipal(userInfo.Username))
                    {
                        foreach (GroupPrincipal group in LocalAccount.GetGroups(user))
                        {
                            // Skip "Authenticated Users" and "Everyone" as these are generated
                            if (group.Sid == EveryoneSid || group.Sid == AuthenticatedUsersSid)
                            {
                                continue;
                            }

                            userInfo.AddGroup(new GroupInformation()
                            {
                                Name        = group.Name,
                                Description = group.Description,
                                SID         = group.Sid
                            });
                        }
                    }
                }
            }
            catch (Exception e)
            {
                logger.ErrorFormat("Unexpected error while syncing local groups, skipping rest: {0}", e);
            }
        }
Beispiel #9
0
        private void cleanup(UserInformation userInfo, int sessionID, SessionProperties properties)
        {
            bool scramble = Settings.Store.ScramblePasswords;
            bool remove   = Settings.Store.RemoveProfiles;

            while (true)
            {
                // logoff detection is quite a problem under NT6
                // a disconnectEvent is only triggered during a logoff
                // but not during a shutdown/reboot
                // and the SessionLogoffEvent is only saying that the user is logging of
                // So, there is no event that is fired during a user-logoff/reboot/shutdown
                // that indicates that the user has logged of
                if (Abstractions.WindowsApi.pInvokes.IsSessionLoggedOFF(sessionID) || IsShuttingDown)
                {
                    break;
                }
                else
                {
                    Thread.Sleep(1000);
                }
            }
            while (true)
            {
                // if no other notification plugin is working on this user
                // if the first entry from GetNotificationPlugins is equal to this plugin UID
                IEnumerable <Guid> guids = properties.GetTrackedSingle <PluginActivityInformation>().GetNotificationPlugins();

                /*foreach(Guid gui in guids)
                 * {
                 *  m_logger.DebugFormat("{1} PluginActivityInformation guid:{0}", gui, userInfo.Username);
                 * }*/
                if (guids.DefaultIfEmpty(Guid.Empty).FirstOrDefault().Equals(PluginUuid) || guids.ToList().Count == 0)
                {
                    break;
                }

                Thread.Sleep(1000);
            }

            m_logger.DebugFormat("{0} start cleanup with Description \"{1}\"", userInfo.Username, userInfo.Description);

            if (LocalAccount.UserExists(userInfo.Username))
            {
                lock (logoff_locker)
                {
                    LocalAccount lo = new LocalAccount(userInfo);
                    if (remove)
                    {
                        m_logger.DebugFormat("{0} remove profile", userInfo.Username);
                        lo.RemoveUserAndProfile(userInfo.Username, sessionID);
                    }
                    else
                    {
                        m_logger.DebugFormat("{0} not removing profile", userInfo.Username);
                    }
                    if (scramble && !remove)
                    {
                        m_logger.DebugFormat("{0} scramble password", userInfo.Username);
                        lo.ScrambleUsersPassword(userInfo.Username);
                    }
                    else
                    {
                        m_logger.DebugFormat("{0} not scramble password", userInfo.Username);
                    }
                    m_logger.DebugFormat("{0} cleanup done", userInfo.Username);
                }
            }
            else
            {
                m_logger.DebugFormat("{0} doesnt exist", userInfo.Username);
            }

            try
            {
                Locker.TryEnterWriteLock(-1);
                RunningTasks.Remove(userInfo.Username.ToLower());

                PluginActivityInformation notification = properties.GetTrackedSingle <PluginActivityInformation>();
                notification.DelNotificationResult(PluginUuid);
                m_logger.InfoFormat("{1} PluginActivityInformation del Guid:{0}", PluginUuid, userInfo.Username);
                properties.AddTrackedSingle <PluginActivityInformation>(notification);
                foreach (Guid guid in properties.GetTrackedSingle <PluginActivityInformation>().GetNotificationPlugins())
                {
                    m_logger.InfoFormat("{1} PluginActivityInformation Guid:{0}", guid, userInfo.Username);
                }
            }
            finally
            {
                Locker.ExitWriteLock();
            }
        }
Beispiel #10
0
        public BooleanResult AuthorizeUser(SessionProperties properties)
        {
            // Some things we always do,
            bool mirrorGroups = Settings.Store.MirrorGroupsForAuthdUsers;   // Should we load users groups from SAM? We always do if we auth'd only

            if (mirrorGroups && !DidWeAuthThisUser(properties, false))
            {
                UserInformation userInfo = properties.GetTrackedSingle <UserInformation>();
                if (LocalAccount.UserExists(userInfo.Username))
                {
                    m_logger.DebugFormat("AuthorizeUser: Mirroring users group membership from SAM");
                    LocalAccount.SyncLocalGroupsToUserInfo(userInfo);
                }
            }

            // Do we need to do authorization?
            if (DoesAuthzApply(properties))
            {
                bool     limitToLocalAdmins          = Settings.Store.AuthzLocalAdminsOnly;
                bool     limitToLocalGroups          = Settings.Store.AuthzLocalGroupsOnly;
                string[] limitToGroupList            = Settings.Store.AuthzLocalGroups;
                bool     restrictionsApply           = limitToLocalAdmins || limitToLocalGroups;
                PluginActivityInformation pluginInfo = properties.GetTrackedSingle <PluginActivityInformation>();

                if (!restrictionsApply)
                {
                    return(new BooleanResult()
                    {
                        Success = true
                    });
                }
                else if (!pluginInfo.LoadedAuthenticationGatewayPlugins.Contains(this))
                {
                    return(new BooleanResult()
                    {
                        Success = false,
                        Message = string.Format("Plugin configured to authorize users based on group membership, but not in the gateway list to ensure membership is enforced, denying access")
                    });
                }

                // The user must have the local administrator group in his group list, and
                //  we must be in the Gateway list of plugins (as we'll be the ones ensuring
                //  this group membership is enforced).
                if (limitToLocalAdmins)
                {
                    SecurityIdentifier adminSid  = Abstractions.Windows.Security.GetWellknownSID(WellKnownSidType.BuiltinAdministratorsSid);
                    string             adminName = Abstractions.Windows.Security.GetNameFromSID(adminSid);

                    if (!ListedInGroup(adminName, adminSid, properties))
                    {
                        return(new BooleanResult()
                        {
                            Success = false,
                            Message = string.Format("Users group list does not include the admin group ({0}), denying access", adminName)
                        });
                    }
                }

                // The user must have one of the groups listed (by name) in their group list
                // and we must be in the Gateway list of plugins (as we'll be the ones ensuring
                //  this group membership is enforced).
                if (limitToLocalGroups)
                {
                    if (limitToGroupList.Length > 0)
                    {
                        foreach (string group in limitToGroupList)
                        {
                            SecurityIdentifier sid = null;
                            try { sid = new SecurityIdentifier(group); }
                            catch { }
                            if (ListedInGroup(group, sid, properties))
                            {
                                return(new BooleanResult()
                                {
                                    Success = true
                                });
                            }
                        }
                    }
                    return(new BooleanResult()
                    {
                        Success = false,
                        Message = "User is not a member of one of the required groups, denying access"
                    });
                }

                return(new BooleanResult()
                {
                    Success = true
                });
            }
            else
            {
                // We elect to not do any authorization, let the user pass for us
                return(new BooleanResult()
                {
                    Success = true
                });
            }
        }
Beispiel #11
0
        public BooleanResult AuthenticatedUserGateway(SessionProperties properties)
        {
            // Our job, if we've been elected to do gateway, is to ensure that an
            //  authenticated user:
            //
            //  1. Has a local account
            //  2. That account's password is set to the one they used to authenticate
            //  3. That account is a member of all groups listed, and not a member of any others

            // Is failure at #3 a total fail?
            bool failIfGroupSyncFails = Settings.Store.GroupCreateFailIsFail;

            // Groups everyone is added to
            string[] MandatoryGroups = Settings.Store.MandatoryGroups;

            // user info
            UserInformation userInfo = properties.GetTrackedSingle <UserInformation>();

            // is this a pgina user?
            Abstractions.WindowsApi.pInvokes.structenums.USER_INFO_4 userinfo4 = new Abstractions.WindowsApi.pInvokes.structenums.USER_INFO_4();
            if (Abstractions.WindowsApi.pInvokes.UserGet(userInfo.Username, ref userinfo4)) //true if user exists
            {
                if (!userinfo4.comment.Contains("pGina created"))
                {
                    m_logger.InfoFormat("User {0} is'nt a pGina created user. I'm not executing Gateway stage", userInfo.Username);
                    return(new BooleanResult()
                    {
                        Success = true
                    });
                }
            }

            // Add user to all mandatory groups
            if (MandatoryGroups.Length > 0)
            {
                foreach (string group in MandatoryGroups)
                {
                    string group_string = group;

                    m_logger.DebugFormat("Is there a Group with SID/Name:{0}", group);
                    using (GroupPrincipal groupconf = LocalAccount.GetGroupPrincipal(group))
                    {
                        if (groupconf != null)
                        {
                            m_logger.DebugFormat("Groupname: \"{0}\"", groupconf.Name);
                            group_string = groupconf.Name;
                        }
                        else
                        {
                            m_logger.ErrorFormat("Group: \"{0}\" not found", group);
                            m_logger.Error("Failsave add user to group Users");
                            using (GroupPrincipal groupfail = LocalAccount.GetGroupPrincipal(new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null).ToString()))
                            {
                                if (groupfail != null)
                                {
                                    group_string = groupfail.Name;
                                }
                                else
                                {
                                    m_logger.Debug("no BuiltinUsers. I'm out of options");
                                    group_string = null;
                                }
                            }
                        }
                    }

                    if (group_string != null)
                    {
                        userInfo.AddGroup(new GroupInformation()
                        {
                            Name = group_string
                        });
                    }
                }
            }

            try
            {
                m_logger.DebugFormat("AuthenticatedUserGateway({0}) for user: {1}", properties.Id.ToString(), userInfo.Username);
                LocalAccount.SyncUserInfoToLocalUser(userInfo);
                using (UserPrincipal user = LocalAccount.GetUserPrincipal(userInfo.Username))
                {
                    userInfo.SID         = user.Sid;
                    userInfo.Description = user.Description;
                }
                properties.AddTrackedSingle <UserInformation>(userInfo);
            }
            catch (LocalAccount.GroupSyncException e)
            {
                if (failIfGroupSyncFails)
                {
                    return new BooleanResult()
                           {
                               Success = false, Message = string.Format("Unable to sync users local group membership: {0}", e.RootException)
                           }
                }
                ;
            }
            catch (Exception e)
            {
                if (e.Message.ToLower().Contains("0x800708c5"))
                {
                    return(new BooleanResult()
                    {
                        Success = false, Message = string.Format("This Worstation is denying the password of {0}.\nMost likely the password does not meet complexity requirements\n\n{1}", userInfo.Username, e)
                    });
                }

                return(new BooleanResult()
                {
                    Success = false, Message = string.Format("Unexpected error while syncing user's info: {0}", e)
                });
            }

            return(new BooleanResult()
            {
                Success = true
            });
        }
Beispiel #12
0
        public BooleanResult AuthenticatedUserGateway(SessionProperties properties)
        {
            // Our job, if we've been elected to do gateway, is to ensure that an
            //  authenticated user:
            //
            //  1. Has a local account
            //  2. That account's password is set to the one they used to authenticate
            //  3. That account is a member of all groups listed, and not a member of any others

            // Is failure at #3 a total fail?
            bool failIfGroupSyncFails = Settings.Store.GroupCreateFailIsFail;

            // Groups everyone is added to
            string[] MandatoryGroups = Settings.Store.MandatoryGroups;

            // user info
            UserInformation userInfo = properties.GetTrackedSingle <UserInformation>();

            // Add user to all mandatory groups
            if (MandatoryGroups.Length > 0)
            {
                foreach (string group in MandatoryGroups)
                {
                    userInfo.AddGroup(new GroupInformation()
                    {
                        Name = group
                    });
                }
            }

            try
            {
                bool scramble = Settings.Store.ScramblePasswords;
                bool remove   = Settings.Store.RemoveProfiles;

                if (remove)
                {
                    // If this user doesn't already exist, and we are supposed to clean up after ourselves,
                    //  make note of the username!
                    if (!LocalAccount.UserExists(userInfo.Username))
                    {
                        m_logger.DebugFormat("Marking for deletion: {0}", userInfo.Username);
                        CleanupTasks.AddTask(new CleanupTask(userInfo.Username, CleanupAction.DELETE_PROFILE));
                    }
                }

                // If we are configured to scramble passwords
                if (scramble)
                {
                    // Scramble the password only if the user is not in the list
                    // of exceptions.
                    string[] exceptions = Settings.Store.ScramblePasswordsExceptions;
                    if (!exceptions.Contains(userInfo.Username, StringComparer.CurrentCultureIgnoreCase))
                    {
                        // If configured to do so, we check to see if this plugin failed
                        // to auth this user, and only scramble in that case
                        bool scrambleWhenLMFail = Settings.Store.ScramblePasswordsWhenLMAuthFails;
                        if (scrambleWhenLMFail)
                        {
                            // Scramble the password only if we did not authenticate this user
                            if (!DidWeAuthThisUser(properties, false))
                            {
                                m_logger.DebugFormat("LM did not authenticate this user, marking user for scramble: {0}", userInfo.Username);
                                CleanupTasks.AddTask(new CleanupTask(userInfo.Username, CleanupAction.SCRAMBLE_PASSWORD));
                            }
                        }
                        else
                        {
                            m_logger.DebugFormat("Marking user for scramble: {0}", userInfo.Username);
                            CleanupTasks.AddTask(new CleanupTask(userInfo.Username, CleanupAction.SCRAMBLE_PASSWORD));
                        }
                    }
                }

                m_logger.DebugFormat("AuthenticatedUserGateway({0}) for user: {1}", properties.Id.ToString(), userInfo.Username);
                LocalAccount.SyncUserInfoToLocalUser(userInfo);
            }
            catch (LocalAccount.GroupSyncException e)
            {
                if (failIfGroupSyncFails)
                {
                    return new BooleanResult()
                           {
                               Success = false, Message = string.Format("Unable to sync users local group membership: {0}", e.RootException)
                           }
                }
                ;
            }
            catch (Exception e)
            {
                return(new BooleanResult()
                {
                    Success = false, Message = string.Format("Unexpected error while syncing user's info: {0}", e)
                });
            }

            return(new BooleanResult()
            {
                Success = true
            });
        }
Beispiel #13
0
        private void IterateCleanupUsers()
        {
            lock (this)
            {
                List <CleanupTask> tasks         = CleanupTasks.GetEligibleTasks();
                List <string>      loggedOnUsers = null;
                try
                {
                    loggedOnUsers = LoggedOnLocalUsers();
                }
                catch (System.ComponentModel.Win32Exception e)
                {
                    m_logger.ErrorFormat("Error (ignored) LoggedOnLocalUsers {0}", e);
                    return;
                }

                m_logger.DebugFormat("IterateCleanupUsers Eligible users: {0}", string.Join(",", tasks));
                m_logger.DebugFormat("IterateCleanupUsers loggedOnUsers: {0}", string.Join(",", loggedOnUsers));

                foreach (CleanupTask task in tasks)
                {
                    try
                    {
                        using (UserPrincipal userPrincipal = LocalAccount.GetUserPrincipal(task.UserName))
                        {
                            // Make sure the user exists
                            if (userPrincipal == null)
                            {
                                // This dude doesn't exist!
                                m_logger.DebugFormat("User {0} doesn't exist, not cleaning up.", task.UserName);
                                CleanupTasks.RemoveTaskForUser(task.UserName);
                                continue;
                            }

                            // Is she logged in still?
                            if (loggedOnUsers.Contains(task.UserName, StringComparer.CurrentCultureIgnoreCase))
                            {
                                continue;
                            }

                            m_logger.InfoFormat("Cleaning up: {0} -> {1}", task.UserName, task.Action);

                            try
                            {
                                switch (task.Action)
                                {
                                case CleanupAction.SCRAMBLE_PASSWORD:
                                    LocalAccount.ScrambleUsersPassword(task.UserName);
                                    break;

                                case CleanupAction.DELETE_PROFILE:
                                    LocalAccount.RemoveUserAndProfile(task.UserName);
                                    break;

                                default:
                                    m_logger.ErrorFormat("Unrecognized action: {0}, skipping user {1}", task.Action, task.UserName);
                                    throw new Exception();
                                }
                            }
                            catch (Exception e)
                            {
                                m_logger.WarnFormat("Cleanup for {0} failed, will retry next time around. Error: {1}", task.UserName, e);
                                continue;
                            }

                            // All done! No more cleanup for this user needed
                            CleanupTasks.RemoveTaskForUser(task.UserName);
                        }
                    }
                    catch (Exception e)
                    {
                        // If something goes wrong, we log the exception and ignore.
                        m_logger.ErrorFormat("Caught (ignoring) Exception {0}", e);
                    }
                }
            }
        }
Beispiel #14
0
 public static void SyncUserInfoToLocalUser(UserInformation userInfo)
 {
     LocalAccount la = new LocalAccount(userInfo);
     la.SyncToLocalUser();
 }
Beispiel #15
0
        public void SyncToLocalUser()
        {
            m_logger.Debug("SyncToLocalUser()");

            using (UserPrincipal user = CreateOrGetUserPrincipal(UserInfo))
            {
                // Force password and fullname match (redundant if we just created, but oh well)
                SyncUserPrincipalInfo(UserInfo);

                try
                {
                    List <SecurityIdentifier> ignoredSids = new List <SecurityIdentifier>(new SecurityIdentifier[] {
                        new SecurityIdentifier(WellKnownSidType.AuthenticatedUserSid, null),    // "Authenticated Users"
                        new SecurityIdentifier("S-1-1-0"),                                      // "Everyone"
                    });

                    // First remove from any local groups they aren't supposed to be in
                    m_logger.Debug("Checking for groups to remove.");
                    List <GroupPrincipal> localGroups = LocalAccount.GetGroups(user);
                    foreach (GroupPrincipal group in localGroups)
                    {
                        m_logger.DebugFormat("Remove {0}?", group.Name);
                        // Skip ignored sids
                        if (!ignoredSids.Contains(group.Sid))
                        {
                            GroupInformation gi = new GroupInformation()
                            {
                                Name = group.Name, SID = group.Sid, Description = group.Description
                            };
                            if (!UserInfo.InGroup(gi))
                            {
                                m_logger.DebugFormat("Removing user {0} from group {1}", user.Name, group.Name);
                                RemoveUserFromGroup(user, group);
                            }
                        }
                        group.Dispose();
                    }

                    // Now add to any they aren't already in that they should be
                    m_logger.Debug("Checking for groups to add");
                    foreach (GroupInformation groupInfo in UserInfo.Groups)
                    {
                        m_logger.DebugFormat("Add {0}?", groupInfo.Name);
                        if (!IsUserInGroup(user, groupInfo))
                        {
                            using (GroupPrincipal group = CreateOrGetGroupPrincipal(groupInfo))
                            {
                                m_logger.DebugFormat("Adding user {0} to group {1}", user.Name, group.Name);
                                AddUserToGroup(user, group);
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new GroupSyncException(e);
                }
            }

            //set ntuser.dat permissions
            if (!String.IsNullOrEmpty(UserInfo.usri4_profile) && !UserInfo.Description.Contains("pgSMB"))
            {
                Abstractions.WindowsApi.pInvokes.structenums.OSVERSIONINFOW verinfo = Abstractions.WindowsApi.pInvokes.VersionsInfo();
                if (verinfo.dwMajorVersion == 0)
                {
                    m_logger.WarnFormat("SyncToLocalUser: VersionsInfo() failed. I'm unable to detect OS beyond Windows 8.0");
                    verinfo.dwBuildNumber  = Environment.OSVersion.Version.Build;
                    verinfo.dwMajorVersion = Environment.OSVersion.Version.Major;
                    verinfo.dwMinorVersion = Environment.OSVersion.Version.Minor;
                    verinfo.dwPlatformId   = Environment.OSVersion.Version.Build;
                }
                string ProfileExtension = (Environment.OSVersion.Version.Major == 6) ? (verinfo.dwMinorVersion > 3) /*greater than 8.1*/ ? ".V5" : ".V2" : "";

                if (Connect2share(UserInfo.usri4_profile + ProfileExtension, UserInfo.Username, UserInfo.Password, 3, false))
                {
                    if (File.Exists(UserInfo.usri4_profile + ProfileExtension + "\\NTUSER.DAT"))
                    {
                        SetACL(UserInfo, ProfileExtension);
                        Connect2share(UserInfo.usri4_profile + ProfileExtension, null, null, 0, true);
                    }
                    else
                    {
                        Connect2share(UserInfo.usri4_profile + ProfileExtension, null, null, 0, true);
                    }
                }
            }

            m_logger.Debug("End SyncToLocalUser()");
        }
Beispiel #16
0
        public static void SyncUserInfoToLocalUser(UserInformation userInfo)
        {
            LocalAccount la = new LocalAccount(userInfo);

            la.SyncToLocalUser();
        }
Beispiel #17
0
        private void cleanup(UserInformation userInfo, int sessionID, SessionProperties properties)
        {
            bool scramble = Settings.Store.ScramblePasswords;
            bool remove = Settings.Store.RemoveProfiles;

            while (true)
            {
                // logoff detection is quite a problem under NT6
                // a disconnectEvent is only triggered during a logoff
                // but not during a shutdown/reboot
                // and the SessionLogoffEvent is only saying that the user is logging of
                // So, there is no event that is fired during a user-logoff/reboot/shutdown
                // that indicates that the user has logged of
                if (Abstractions.WindowsApi.pInvokes.IsSessionLoggedOFF(sessionID) || IsShuttingDown)
                {
                    break;
                }
                else
                {
                    Thread.Sleep(1000);
                }
            }
            while (true)
            {
                // if no other notification plugin is working on this user
                // if the first entry from GetNotificationPlugins is equal to this plugin UID
                IEnumerable<Guid> guids = properties.GetTrackedSingle<PluginActivityInformation>().GetNotificationPlugins();
                /*foreach(Guid gui in guids)
                {
                    m_logger.DebugFormat("{1} PluginActivityInformation guid:{0}", gui, userInfo.Username);
                }*/
                if (guids.DefaultIfEmpty(Guid.Empty).FirstOrDefault().Equals(PluginUuid) || guids.ToList().Count == 0)
                {
                    break;
                }

                Thread.Sleep(1000);
            }

            m_logger.DebugFormat("{0} start cleanup with Description \"{1}\"", userInfo.Username, userInfo.Description);

            if (LocalAccount.UserExists(userInfo.Username))
            {
                lock (logoff_locker)
                {
                    LocalAccount lo = new LocalAccount(userInfo);
                    if (remove)
                    {
                        m_logger.DebugFormat("{0} remove profile", userInfo.Username);
                        lo.RemoveUserAndProfile(userInfo.Username, sessionID);
                    }
                    else
                    {
                        m_logger.DebugFormat("{0} not removing profile", userInfo.Username);
                    }
                    if (scramble && !remove)
                    {
                        m_logger.DebugFormat("{0} scramble password", userInfo.Username);
                        lo.ScrambleUsersPassword(userInfo.Username);
                    }
                    else
                    {
                        m_logger.DebugFormat("{0} not scramble password", userInfo.Username);
                    }
                    m_logger.DebugFormat("{0} cleanup done", userInfo.Username);
                }
            }
            else
            {
                m_logger.DebugFormat("{0} doesnt exist", userInfo.Username);
            }

            try
            {
                Locker.TryEnterWriteLock(-1);
                RunningTasks.Remove(userInfo.Username.ToLower());

                PluginActivityInformation notification = properties.GetTrackedSingle<PluginActivityInformation>();
                notification.DelNotificationResult(PluginUuid);
                m_logger.InfoFormat("{1} PluginActivityInformation del Guid:{0}", PluginUuid, userInfo.Username);
                properties.AddTrackedSingle<PluginActivityInformation>(notification);
                foreach (Guid guid in properties.GetTrackedSingle<PluginActivityInformation>().GetNotificationPlugins())
                {
                    m_logger.InfoFormat("{1} PluginActivityInformation Guid:{0}", guid, userInfo.Username);
                }
            }
            finally
            {
                Locker.ExitWriteLock();
            }
        }