private LoginResponseMessage HandleLoginRequest(LoginRequestMessage msg) { try { PluginDriver sessionDriver = new PluginDriver(); sessionDriver.UserInformation.Username = msg.Username.Trim(); sessionDriver.UserInformation.Password = msg.Password; m_logger.DebugFormat("Processing LoginRequest for: {0} in session: {1} reason: {2}", sessionDriver.UserInformation.Username, msg.Session, msg.Reason); BooleanResult result = sessionDriver.PerformLoginProcess(); if (msg.Reason == LoginRequestMessage.LoginReason.Login) { lock (m_sessionPropertyCache) { m_sessionPropertyCache.Add(msg.Session, sessionDriver.SessionProperties); } } return new LoginResponseMessage() { Result = result.Success, Message = result.Message, Username = sessionDriver.UserInformation.Username, Domain = sessionDriver.UserInformation.Domain, Password = sessionDriver.UserInformation.Password }; } catch (Exception e) { m_logger.ErrorFormat("Internal error, unexpected exception while handling login request: {0}", e); return new LoginResponseMessage() { Result = false, Message = "Internal error" }; } }
private LoginResponseMessage HandleLoginRequest(LoginRequestMessage msg) { try { PluginDriver sessionDriver = new PluginDriver(); bool LastUsernameEnable = Settings.Get.LastUsernameEnable; msg = SplitDomainfromUsername(msg); sessionDriver.UserInformation.Username = msg.Username; sessionDriver.UserInformation.Password = (String.IsNullOrEmpty(msg.Password)) ? "" : msg.Password; sessionDriver.UserInformation.Domain = msg.Domain; sessionDriver.UserInformation.SessionID = msg.Session; if (msg.Reason == LoginRequestMessage.LoginReason.CredUI) { sessionDriver.SessionProperties.CREDUI = true; } if (String.IsNullOrEmpty(sessionDriver.UserInformation.Username)) { return new LoginResponseMessage() { Result = false, Message = String.Format("No Username supplied\n\n'{0}' was entered and parsed to '{1}'", msg.Username, sessionDriver.UserInformation.Username) }; } // check if a plugin still does some logoff work for this user Boolean thisUserLogoff = false; foreach (IPluginLogoffRequestAddTime plugin in PluginLoader.GetOrderedPluginsOfType<IPluginLogoffRequestAddTime>()) { if (plugin.LoginUserRequest(sessionDriver.UserInformation.Username)) thisUserLogoff = true; } if (thisUserLogoff) { return new LoginResponseMessage() { Result = false, Message = String.Format("Still logoff work to do for user {0}\nWait a view seconds and retry", sessionDriver.UserInformation.Username) }; } // do the domain logon string domainmember = Abstractions.WindowsApi.pInvokes.GetMachineDomainMembershipEX(); m_logger.InfoFormat("domain check:[{0}] [{1}] [{2}]", Regex.IsMatch(msg.Username, "\\|@"), !String.IsNullOrEmpty(domainmember), !sessionDriver.UserInformation.Domain.Equals(Environment.MachineName, StringComparison.CurrentCultureIgnoreCase)); if ((Regex.IsMatch(msg.Username, "\\|@") || !String.IsNullOrEmpty(domainmember)) && !sessionDriver.UserInformation.Domain.Equals(Environment.MachineName, StringComparison.CurrentCultureIgnoreCase)) { m_logger.DebugFormat("domain logon: Username:{0} domainmember:{1} domain:{2}", msg.Username, domainmember, sessionDriver.UserInformation.Domain); // if domain was provided by username and it got messed up ... if (String.IsNullOrEmpty(sessionDriver.UserInformation.Domain) && Regex.IsMatch(msg.Username, "\\|@")) { return new LoginResponseMessage() { Result = false, Message = String.Format("No Domainname supplied\n\n'{0}' was entered and parsed to '{1}'", msg.Username, sessionDriver.UserInformation.Domain) }; } if (Abstractions.WindowsApi.pInvokes.DomainMember(sessionDriver.UserInformation.Domain)) { m_logger.InfoFormat("DomainMember"); // pc is member of this domain provided by the username field if (Abstractions.WindowsApi.pInvokes.ValidateUser(sessionDriver.UserInformation.Username, sessionDriver.UserInformation.Domain, sessionDriver.UserInformation.Password)) { if (LastUsernameEnable && msg.Reason == LoginRequestMessage.LoginReason.Login) { Settings.s_settings.SetSetting("LastUsername", String.Format("{0}\\{1}", sessionDriver.UserInformation.Domain, sessionDriver.UserInformation.Username)); } m_logger.InfoFormat("Sucess"); return new LoginResponseMessage() { Result = true, Message = "", Username = sessionDriver.UserInformation.Username, Domain = sessionDriver.UserInformation.Domain, Password = sessionDriver.UserInformation.Password }; } else { string message = String.Format("The provided account:{0} name does not exist on:{1} or the password is wrong", sessionDriver.UserInformation.Username, sessionDriver.UserInformation.Domain); m_logger.InfoFormat(message); return new LoginResponseMessage() { Result = false, Message = message, Username = sessionDriver.UserInformation.Username, Domain = sessionDriver.UserInformation.Domain, Password = sessionDriver.UserInformation.Password }; } } else if (!String.IsNullOrEmpty(domainmember)) { m_logger.InfoFormat("GetMachineDomainMembership"); // pc is member of a domain sessionDriver.UserInformation.Domain = domainmember; if (Abstractions.WindowsApi.pInvokes.ValidateUser(sessionDriver.UserInformation.Username, sessionDriver.UserInformation.Domain, sessionDriver.UserInformation.Password)) { if (LastUsernameEnable && msg.Reason == LoginRequestMessage.LoginReason.Login) { Settings.s_settings.SetSetting("LastUsername", String.Format("{0}\\{1}", sessionDriver.UserInformation.Domain, sessionDriver.UserInformation.Username)); } m_logger.InfoFormat("Sucess"); return new LoginResponseMessage() { Result = true, Message = "", Username = sessionDriver.UserInformation.Username, Domain = sessionDriver.UserInformation.Domain, Password = sessionDriver.UserInformation.Password }; } else { m_logger.InfoFormat("Failed, query Remote({0}) SAM", domainmember); sessionDriver.UserInformation.Domain = Environment.MachineName; } } } BooleanResult result = new BooleanResult() { Success = true, Message = "" }; if (new[] { LoginRequestMessage.LoginReason.Login, LoginRequestMessage.LoginReason.CredUI }.Contains(msg.Reason)) { m_logger.DebugFormat("Processing LoginRequest for: {0} in session: {1} reason: {2}", sessionDriver.UserInformation.Username, msg.Session, msg.Reason); Boolean isLoggedIN = false; Boolean isUACLoggedIN = false; // is this user a local user and was not created by pGina Abstractions.WindowsApi.pInvokes.structenums.USER_INFO_4 userinfo4 = new Abstractions.WindowsApi.pInvokes.structenums.USER_INFO_4(); if (Abstractions.WindowsApi.pInvokes.UserGet(sessionDriver.UserInformation.Username, ref userinfo4)) { if (!userinfo4.comment.Contains("pGina created")) { result.Success = Abstractions.WindowsApi.pInvokes.ValidateUser(sessionDriver.UserInformation.Username, sessionDriver.UserInformation.Domain, sessionDriver.UserInformation.Password); if (result.Success) { if (LastUsernameEnable && msg.Reason == LoginRequestMessage.LoginReason.Login) { Settings.s_settings.SetSetting("LastUsername", String.Format("{0}", sessionDriver.UserInformation.Username)); } } return new LoginResponseMessage() { Result = result.Success, Message = (result.Success) ? "Local non pGina user" : "Unknown username or bad password", Username = sessionDriver.UserInformation.Username, Domain = sessionDriver.UserInformation.Domain, Password = sessionDriver.UserInformation.Password }; } } Dictionary<int, List<string>> contextALL = Abstractions.WindowsApi.pInvokes.GetSessionContext(); List<string> Users = Abstractions.WindowsApi.pInvokes.GetSessionContextParser(-1, contextALL); List<string> iUsers = Abstractions.WindowsApi.pInvokes.GetInteractiveUserList(); foreach (string user in Users) { m_logger.DebugFormat("Program running as user:{0}", user); if (user.Equals(sessionDriver.UserInformation.Username, StringComparison.CurrentCultureIgnoreCase)) { //the user is still logged in isLoggedIN = true; if (iUsers.Any(s => s.EndsWith("\\" + sessionDriver.UserInformation.Username, StringComparison.CurrentCultureIgnoreCase))) { int Locked_sessionID = Convert.ToInt32(iUsers.Find(s => s.EndsWith("\\" + sessionDriver.UserInformation.Username, StringComparison.CurrentCultureIgnoreCase)).Split('\\').First()); m_logger.DebugFormat("User:{0} is Locked in Session:{1}", sessionDriver.UserInformation.Username, Locked_sessionID); // verify that this unlock is present somewhere in m_sessionPropertyCache // if not, this login is not backed by m_sessionPropertyCache if (m_sessionPropertyCache.GetAll().Any(i => i == Locked_sessionID)) { UserInformation uInfo = m_sessionPropertyCache.Get(Locked_sessionID).First().GetTrackedSingle<UserInformation>(); if (!uInfo.Username.Equals(sessionDriver.UserInformation.Username, StringComparison.CurrentCultureIgnoreCase)) { // that should never ever happen m_logger.ErrorFormat("User {0} is Locked in Session {1} but the username doesn't match the session information pGina contains. '{0}' vs. '{2}'", sessionDriver.UserInformation.Username, Locked_sessionID, uInfo.Username); return new LoginResponseMessage() { Result = false, Message = String.Format("User {0} is Locked in Session {1} but the username doesn't match the session information pGina contains\n\n'{0}' vs '{2}'", sessionDriver.UserInformation.Username, Locked_sessionID, uInfo.Username) }; } } else { m_logger.ErrorFormat("User {0} is Locked in Session {1} but was not authenticated by pGina. Unable to find SessionProperty in m_sessionPropertyCache.Get({1})", sessionDriver.UserInformation.Username, Locked_sessionID); return new LoginResponseMessage() { Result = false, Message = String.Format("User {0} is Locked in Session {1} but was not authenticated by pGina\n\nIt is possible that another Credential Provider was used\nor the pGina service has crashed.\n", sessionDriver.UserInformation.Username, Locked_sessionID) }; } } else { // verify that this UACed login is present somewhere in m_sessionPropertyCache // if not, this login is not backed by m_sessionPropertyCache foreach (int session in m_sessionPropertyCache.GetAll()) { if (m_sessionPropertyCache.Get(session).Any(s => s.GetTrackedSingle<UserInformation>().Username.Equals(sessionDriver.UserInformation.Username, StringComparison.CurrentCultureIgnoreCase))) { m_logger.DebugFormat("User:{0} is pGina UACed in Session:{1}", sessionDriver.UserInformation.Username, session); isUACLoggedIN = true; break; } } // is this user a local user and was not created by pGina /*Abstractions.WindowsApi.pInvokes.structenums.USER_INFO_4 userinfo4 = new Abstractions.WindowsApi.pInvokes.structenums.USER_INFO_4(); if (Abstractions.WindowsApi.pInvokes.UserGet(sessionDriver.UserInformation.Username, ref userinfo4)) { if (!userinfo4.comment.Contains("pGina created")) { m_logger.DebugFormat("User:{0} is local non pGina", sessionDriver.UserInformation.Username); isUACLoggedIN = true; } }*/ if (!isUACLoggedIN) { List<string> runas_in_session = new List<string>(); foreach (KeyValuePair<int, List<string>> pair in contextALL) { if (pair.Value.Any(s => s.Equals(sessionDriver.UserInformation.Username, StringComparison.CurrentCultureIgnoreCase))) { runas_in_session.Add(iUsers.DefaultIfEmpty("").FirstOrDefault(s => s.StartsWith(pair.Key.ToString()))); } } m_logger.DebugFormat("There is a program running as {0} but it was'nt started with pGina. I can't log you in because this would conflict with the current running process. Session in which a process is running:{1}", sessionDriver.UserInformation.Username, String.Join(",", runas_in_session)); return new LoginResponseMessage() { Result = false, Message = String.Format("There is a program running as {0} but it was'nt started with pGina.\nI can't log you in because this would conflict with the current running process.\n\nSession in which a process is running:\n{1}", sessionDriver.UserInformation.Username, String.Join("\n", runas_in_session)) }; } } } } if (!isLoggedIN) { result = sessionDriver.PerformLoginProcess(); } else { // testing. ValidateCredentials would be correct here if (!Abstractions.WindowsApi.pInvokes.ValidateUser(sessionDriver.UserInformation.Username, sessionDriver.UserInformation.Domain, sessionDriver.UserInformation.Password)) { m_logger.ErrorFormat("Query local SAM: Bad password"); return new LoginResponseMessage() { Result = false, Message = "Bad password", Username = sessionDriver.UserInformation.Username, Domain = sessionDriver.UserInformation.Domain, Password = sessionDriver.UserInformation.Password }; } } if (result.Success && (!isLoggedIN || msg.Reason == LoginRequestMessage.LoginReason.CredUI || isUACLoggedIN)) { lock (m_sessionPropertyCache) { List<SessionProperties> ses = new List<SessionProperties>(); if (m_sessionPropertyCache.Exists(msg.Session)) { ses = m_sessionPropertyCache.Get(msg.Session); } bool partof = false; foreach (SessionProperties sess in ses) { UserInformation ui = sess.GetTrackedSingle<UserInformation>(); m_logger.InfoFormat("compare stored-user:{0} this-user:{1}", ui.Username, sessionDriver.UserInformation.Username); if (sessionDriver.UserInformation.Username.Equals(ui.Username, StringComparison.CurrentCultureIgnoreCase)) { partof = true; m_logger.InfoFormat("contain user {0} in sessioninfo:{1} GUID:{2}", ui.Username, msg.Session, sess.Id); break; } } if (!partof) { if (isLoggedIN) { UserInformation ui = FindUserInfoInPropertyCache(sessionDriver.UserInformation.Username); if (ui != null) { ui.SessionID = msg.Session; sessionDriver.SessionProperties.AddTrackedSingle<UserInformation>(ui); } } else { // add local profile path // its not sure that the profile realy ends up there // a win profile loading error can redirect the path to a temp path too UserInformation ui = sessionDriver.SessionProperties.GetTrackedSingle<UserInformation>(); if (ui != null) { // worst case empty string ui.LocalProfilePath = Abstractions.Windows.User.GetProfileDir(ui.Username, ui.Password, ui.SID); sessionDriver.SessionProperties.AddTrackedSingle<UserInformation>(ui); m_logger.InfoFormat("ses add LocalProfilePath:[{0}]", ui.LocalProfilePath); } } ses.Add(sessionDriver.SessionProperties); m_logger.InfoFormat("add user {0} to sessioninfo:{1} GUID:{2} CREDUI:{3}", sessionDriver.UserInformation.Username, msg.Session, sessionDriver.SessionProperties.Id, (msg.Reason == LoginRequestMessage.LoginReason.CredUI) ? "true" : "false"); m_logger.InfoFormat("ses username:{0} description:{1} credui:{2} isLoggedIN:{3}", ses.Last().GetTrackedSingle<UserInformation>().Username, ses.Last().GetTrackedSingle<UserInformation>().Description, ses.Last().CREDUI, isLoggedIN); m_sessionPropertyCache.Add(msg.Session, ses); } } } } else { // check if username is equal originalusername // if not return originalusername and password bool originalUsernameUnlock = Settings.Get.UseOriginalUsernameInUnlockScenario; if (originalUsernameUnlock && LoginRequestMessage.LoginReason.Unlock == msg.Reason) { m_logger.InfoFormat("Unlock with original Username:{0} for Session:{1}", sessionDriver.UserInformation.Username, msg.Session); lock (m_sessionPropertyCache) { List<SessionProperties> ses = new List<SessionProperties>(); if (m_sessionPropertyCache.Exists(msg.Session)) { ses = m_sessionPropertyCache.Get(msg.Session); } // the first entry is always the interactive user SessionProperties sess = ses.DefaultIfEmpty(new SessionProperties(Guid.Empty, true)).FirstOrDefault(); UserInformation ui = sess.GetTrackedSingle<UserInformation>(); if (ui.Username != ui.OriginalUsername) { if (ui.OriginalPassword == sessionDriver.UserInformation.Password) { sessionDriver.UserInformation.Username = ui.Username; sessionDriver.UserInformation.Domain = Environment.MachineName; sessionDriver.UserInformation.Password = ui.Password; result.Success = true; m_logger.InfoFormat("Unlock as:{0} for Session:{1}", sessionDriver.UserInformation.Username, msg.Session); } else { result.Success = false; result.Message = "Password incorrect!"; } } } } else { m_logger.DebugFormat("Parse Request for: {0} in session: {1} reason: {2}", sessionDriver.UserInformation.Username, msg.Session, msg.Reason); } } if (LastUsernameEnable && msg.Reason == LoginRequestMessage.LoginReason.Login && result.Success) { Settings.s_settings.SetSetting("LastUsername", String.Format("{0}", sessionDriver.UserInformation.Username)); } return new LoginResponseMessage() { Result = result.Success, Message = result.Message, Username = sessionDriver.UserInformation.Username, Domain = sessionDriver.UserInformation.Domain, Password = sessionDriver.UserInformation.Password }; } catch (Exception e) { m_logger.ErrorFormat("Internal error, unexpected exception while handling login request: {0}", e); return new LoginResponseMessage() { Result = false, Message = "Internal error" }; } }