def pre_spawn_start(self, user, spawner): """Load profile for user if so configured""" token = None profilepath = None if not self.open_sessions: return try: loop = asyncio.new_event_loop() auth_state = loop.run_until_complete(user.get_auth_state()) token = pywintypes.HANDLE(auth_state['auth_token']) if '@' not in user.name: # Check if user has a roaming Profile user_info = win32net.NetUserGetInfo(None, user.name, 4) profilepath = user_info['profile'] # Loading the profile will create the USERPROFILE and APPDATA folders, # if not present. To load the profile, the running process needs to have # the SE_RESTORE_NAME and SE_BACKUP_NAME privileges. self._hreg = win32profile.LoadUserProfile( token, {'UserName': user.name, 'ProfilePath': profilepath} ) except Exception as exc: self.log.warning("Failed to load user profile for %s: %s\n%s", user.name, exc, traceback.format_exc()) finally: if token: # Detach so the underlying winhandle stays alive token.Detach()
def install_client(self): logon = win32security.LogonUser( self.user.name, None, self.user.infos["password"], win32security.LOGON32_LOGON_INTERACTIVE, win32security.LOGON32_PROVIDER_DEFAULT) data = {} data["UserName"] = self.user.name hkey = win32profile.LoadUserProfile(logon, data) self.windowsProfileDir = win32profile.GetUserProfileDirectory(logon) self.windowsProgramsDir = shell.SHGetFolderPath( 0, shellcon.CSIDL_PROGRAMS, logon, 0) Logger.debug("startmenu: %s" % (self.windowsProgramsDir)) # remove default startmenu if os.path.exists(self.windowsProgramsDir): Platform.System.DeleteDirectory(self.windowsProgramsDir) os.makedirs(self.windowsProgramsDir) self.windowsDesktopDir = shell.SHGetFolderPath( 0, shellcon.CSIDL_DESKTOPDIRECTORY, logon, 0) self.appDataDir = shell.SHGetFolderPath(0, shellcon.CSIDL_APPDATA, logon, 0) self.localAppDataDir = shell.SHGetFolderPath( 0, shellcon.CSIDL_LOCAL_APPDATA, logon, 0) Logger.debug("localAppdata: '%s'" % (self.localAppDataDir)) Logger.debug("appdata: '%s'" % (self.appDataDir)) win32profile.UnloadUserProfile(logon, hkey) win32api.CloseHandle(logon) self.set_user_profile_directories(self.windowsProfileDir, self.appDataDir) self.init_user_session_dir( os.path.join(self.appDataDir, "ulteo", "ovd")) if self.profile is not None and self.profile.hasProfile(): if not self.profile.mount(): return False self.profile.copySessionStart() if self.profile is not None and self.profile.mountPoint is not None: d = os.path.join(self.profile.mountPoint, self.profile.DesktopDir) self.cleanupShortcut(d) self.install_desktop_shortcuts() self.overwriteDefaultRegistry(self.windowsProfileDir) if self.profile is not None and self.profile.hasProfile(): self.profile.umount() self.succefully_initialized = True return True
## Marshal saved credential and use it to log on mc = win32cred.CredMarshalCredential(win32cred.UsernameTargetCredential, target) th = win32security.LogonUser(mc, None, '', win32con.LOGON32_LOGON_INTERACTIVE, win32con.LOGON32_PROVIDER_DEFAULT) win32security.ImpersonateLoggedOnUser(th) print 'GetUserName:'******'s profile. (first check if user has a roaming profile) username, domain = win32cred.CredUIParseUserName(target) user_info_4 = win32net.NetUserGetInfo(None, username, 4) profilepath = user_info_4['profile'] ## LoadUserProfile apparently doesn't like an empty string if not profilepath: profilepath = None ## leave Flags in since 2.3 still chokes on some types of optional keyword args hk = win32profile.LoadUserProfile(th, { 'UserName': username, 'Flags': 0, 'ProfilePath': profilepath }) ## Get user's environment variables in a form that can be passed to win32process.CreateProcessAsUser env = win32profile.CreateEnvironmentBlock(th, False) ## Cleanup should probably be in a finally block win32profile.UnloadUserProfile(th, hk) th.Close()
## Marshal saved credential and use it to log on mc = win32cred.CredMarshalCredential(win32cred.UsernameTargetCredential, target) th = win32security.LogonUser(mc, None, "", win32con.LOGON32_LOGON_INTERACTIVE, win32con.LOGON32_PROVIDER_DEFAULT) win32security.ImpersonateLoggedOnUser(th) print("GetUserName:"******"profile"] ## LoadUserProfile apparently doesn't like an empty string if not profilepath: profilepath = None ## leave Flags in since 2.3 still chokes on some types of optional keyword args hk = win32profile.LoadUserProfile(th, { "UserName": username, "Flags": 0, "ProfilePath": profilepath }) ## Get user's environment variables in a form that can be passed to win32process.CreateProcessAsUser env = win32profile.CreateEnvironmentBlock(th, False) ## Cleanup should probably be in a finally block win32profile.UnloadUserProfile(th, hk) th.Close()
def runas_system(cmd, username, password): # This only works as system, when salt is running as a service for example # Check for a domain domain = '.' if '@' in username: username, domain = username.split('@') if '\\' in username: domain, username = username.split('\\') # Load User and Get Token token = win32security.LogonUser(username, domain, password, win32con.LOGON32_LOGON_INTERACTIVE, win32con.LOGON32_PROVIDER_DEFAULT) # Load the User Profile handle_reg = win32profile.LoadUserProfile(token, {'UserName': username}) try: # Get Unrestricted Token (UAC) if this is an Admin Account elevated_token = win32security.GetTokenInformation( token, win32security.TokenLinkedToken) # Get list of privileges this token contains privileges = win32security.GetTokenInformation( elevated_token, win32security.TokenPrivileges) # Create a set of all privileges to be enabled enable_privs = set() for luid, flags in privileges: enable_privs.add((luid, win32con.SE_PRIVILEGE_ENABLED)) # Enable the privileges win32security.AdjustTokenPrivileges(elevated_token, 0, enable_privs) except win32security.error as exc: # User doesn't have admin, use existing token if exc[0] == winerror.ERROR_NO_SUCH_LOGON_SESSION \ or exc[0] == winerror.ERROR_PRIVILEGE_NOT_HELD: elevated_token = token else: raise # Get Security Attributes security_attributes = win32security.SECURITY_ATTRIBUTES() security_attributes.bInheritHandle = 1 # Create a pipe to set as stdout in the child. The write handle needs to be # inheritable. stdin_read, stdin_write = win32pipe.CreatePipe(security_attributes, 0) stdin_read = make_inheritable(stdin_read) stdout_read, stdout_write = win32pipe.CreatePipe(security_attributes, 0) stdout_write = make_inheritable(stdout_write) stderr_read, stderr_write = win32pipe.CreatePipe(security_attributes, 0) stderr_write = make_inheritable(stderr_write) # Get startup info structure startup_info = win32process.STARTUPINFO() startup_info.dwFlags = win32con.STARTF_USESTDHANDLES startup_info.hStdInput = stdin_read startup_info.hStdOutput = stdout_write startup_info.hStdError = stderr_write # Get User Environment user_environment = win32profile.CreateEnvironmentBlock(token, False) # Build command cmd = 'cmd /c {0}'.format(cmd) # Run command and return process info structure procArgs = (None, cmd, security_attributes, security_attributes, 1, 0, user_environment, None, startup_info) hProcess, hThread, PId, TId = \ win32process.CreateProcessAsUser(elevated_token, *procArgs) if stdin_read is not None: stdin_read.Close() if stdout_write is not None: stdout_write.Close() if stderr_write is not None: stderr_write.Close() hThread.Close() # Initialize ret and set first element ret = {'pid': PId} # Get Standard Out fd_out = msvcrt.open_osfhandle(stdout_read, os.O_RDONLY | os.O_TEXT) with os.fdopen(fd_out, 'r') as f_out: ret['stdout'] = f_out.read() # Get Standard Error fd_err = msvcrt.open_osfhandle(stderr_read, os.O_RDONLY | os.O_TEXT) with os.fdopen(fd_err, 'r') as f_err: ret['stderr'] = f_err.read() # Get Return Code if win32event.WaitForSingleObject( hProcess, win32event.INFINITE) == win32con.WAIT_OBJECT_0: exitcode = win32process.GetExitCodeProcess(hProcess) ret['retcode'] = exitcode # Close handle to process win32api.CloseHandle(hProcess) # Unload the User Profile win32profile.UnloadUserProfile(token, handle_reg) return ret
def __init__(self, userHandle, userSID, userName, domain, forceSidAdd=False): """ Constructs a Windows-specific user perspective used to access the event manager. @pre userHandle is a valid PyHANDLE object. @param userHandle Handle to the user's authentication. @param userSID The SID for the user represented by this avatar. @param userName The name of the user represented by this avatar. @param domain The domain for the user. @param forceSidAdd Causes the given ID to be added to the window station and desktop ACLs even if it is already present. Use with caution! """ assert (userHandle is not None) UserPerspective.__init__(self) self.mUserHandle = userHandle self.mUserSID = userSID self.mWinsta = None self.mDesktop = None self.mAddedHandles = [] self.mLogger = logging.getLogger('daemon.WindowsAvatar') # Save the current window station for later. cur_winsta = win32service.GetProcessWindowStation() # Open window station winsta0 and make it the window station for this # process. winsta_flags = win32con.READ_CONTROL | win32con.WRITE_DAC new_winsta = win32service.OpenWindowStation("winsta0", False, winsta_flags) new_winsta.SetProcessWindowStation() # Get a handle to the default desktop so that we can change its access # control list. desktop_flags = win32con.READ_CONTROL | \ win32con.WRITE_DAC | \ win32con.DESKTOP_WRITEOBJECTS | \ win32con.DESKTOP_READOBJECTS desktop = win32service.OpenDesktop("default", 0, False, desktop_flags) # If user_sid is not already among the SIDs who have access to # new_winsta, then add it now. It will be removed in logout(). if forceSidAdd or not windesktop.handleHasSID(new_winsta, self.mUserSID): windesktop.addUserToWindowStation(new_winsta, self.mUserSID) self.mAddedHandles.append(new_winsta) self.mLogger.debug("Added SID to new_winsta") # If user_sid is not already among the SIDs who have access to desktop, # then add it now. It will be removed in logout(). if forceSidAdd or not windesktop.handleHasSID(desktop, self.mUserSID): windesktop.addUserToDesktop(desktop, self.mUserSID) self.mAddedHandles.append(desktop) self.mLogger.debug("Added SID to desktop") cur_winsta.SetProcessWindowStation() self.mWinsta = new_winsta self.mDesktop = desktop # (username, domain, acct_type) = \ # win32security.LookupAccountSid(dc_name, self.mUserSID) # self.mUserName = username # self.mDomain = domain self.mUserName = userName self.mDomain = domain # Get name of domain controller. try: dc_name = win32net.NetGetDCName() except: dc_name = None user_info_4 = win32net.NetUserGetInfo(dc_name, self.mUserName, 4) profilepath = user_info_4['profile'] # LoadUserProfile apparently doesn't like an empty string if not profilepath: profilepath = None try: # Leave Flags in since 2.3 still chokes on some types of optional # keyword args self.mUserProfile = win32profile.LoadUserProfile( self.mUserHandle, { 'UserName': self.mUserName, 'Flags': 0, 'ProfilePath': profilepath }) self.mLogger.debug("self.mUserProfile = %s" % str(self.mUserProfile)) self.mLogger.info("Loaded profile %s" % profilepath) except pywintypes.error, error: self.mLogger.error("Error loading profile: %s" % error)
def runas(cmdLine, username, password=None, cwd=None): ''' Run a command as another user. It the proccess is running as an admin or system account this method does not require a password. Other non priviledged accounts need to provide a password for the user to runas. Commands are run in with the highest level priviledges possible for the account provided. ''' # Elevate the token from the current process access = (win32security.TOKEN_QUERY | win32security.TOKEN_ADJUST_PRIVILEGES) th = win32security.OpenProcessToken(win32api.GetCurrentProcess(), access) salt.platform.win.elevate_token(th) # Try to impersonate the SYSTEM user. This process needs to be runnung as a # user who as been granted the SeImpersonatePrivilege, Administrator # accounts have this permission by default. try: impersonation_token = salt.platform.win.impersonate_sid( salt.platform.win.SYSTEM_SID, session_id=0, privs=['SeTcbPrivilege'], ) except WindowsError: # pylint: disable=undefined-variable log.debug("Unable to impersonate SYSTEM user") impersonation_token = None # Impersonation of the SYSTEM user failed. Fallback to an un-priviledged # runas. if not impersonation_token: log.debug("No impersonation token, using unprivileged runas") return runas_unpriv(cmdLine, username, password, cwd) username, domain = split_username(username) # Validate the domain and sid exist for the username sid, domain, sidType = win32security.LookupAccountName(domain, username) if domain == 'NT AUTHORITY': # Logon as a system level account, SYSTEM, LOCAL SERVICE, or NETWORK # SERVICE. logonType = win32con.LOGON32_LOGON_SERVICE user_token = win32security.LogonUser( username, domain, '', win32con.LOGON32_LOGON_SERVICE, win32con.LOGON32_PROVIDER_DEFAULT, ) elif password: # Login with a password. user_token = win32security.LogonUser( username, domain, password, win32con.LOGON32_LOGON_INTERACTIVE, win32con.LOGON32_PROVIDER_DEFAULT, ) else: # Login without a password. This always returns an elevated token. user_token = salt.platform.win.logon_msv1_s4u(username).Token # Get a linked user token to elevate if needed elevation_type = win32security.GetTokenInformation( user_token, win32security.TokenElevationType) if elevation_type > 1: user_token = win32security.GetTokenInformation( user_token, win32security.TokenLinkedToken) # Elevate the user token salt.platform.win.elevate_token(user_token) # Make sure the user's profile is loaded. handle_reg = win32profile.LoadUserProfile(user_token, {'UserName': username}) # Make sure the user's token has access to a windows station and desktop salt.platform.win.grant_winsta_and_desktop(user_token) # Create pipes for standard in, out and error streams security_attributes = win32security.SECURITY_ATTRIBUTES() security_attributes.bInheritHandle = 1 stdin_read, stdin_write = win32pipe.CreatePipe(security_attributes, 0) stdin_read = salt.platform.win.make_inheritable(stdin_read) stdout_read, stdout_write = win32pipe.CreatePipe(security_attributes, 0) stdout_write = salt.platform.win.make_inheritable(stdout_write) stderr_read, stderr_write = win32pipe.CreatePipe(security_attributes, 0) stderr_write = salt.platform.win.make_inheritable(stderr_write) # Run the process without showing a window. creationflags = (win32process.CREATE_NO_WINDOW | win32process.CREATE_NEW_CONSOLE | win32process.CREATE_SUSPENDED) startup_info = salt.platform.win.STARTUPINFO( dwFlags=win32con.STARTF_USESTDHANDLES, hStdInput=stdin_read.handle, hStdOutput=stdout_write.handle, hStdError=stderr_write.handle, ) # Create the environment for the user env = win32profile.CreateEnvironmentBlock(user_token, False) # Start the process in a suspended state. process_info = salt.platform.win.CreateProcessWithTokenW( int(user_token), logonflags=1, applicationname=None, commandline=cmdLine, currentdirectory=cwd, creationflags=creationflags, startupinfo=startup_info, environment=env, ) hProcess = process_info.hProcess hThread = process_info.hThread dwProcessId = process_info.dwProcessId dwThreadId = process_info.dwThreadId salt.platform.win.kernel32.CloseHandle(stdin_write.handle) salt.platform.win.kernel32.CloseHandle(stdout_write.handle) salt.platform.win.kernel32.CloseHandle(stderr_write.handle) ret = {'pid': dwProcessId} # Resume the process psutil.Process(dwProcessId).resume() # Wait for the process to exit and get it's return code. if win32event.WaitForSingleObject( hProcess, win32event.INFINITE) == win32con.WAIT_OBJECT_0: exitcode = win32process.GetExitCodeProcess(hProcess) ret['retcode'] = exitcode # Read standard out fd_out = msvcrt.open_osfhandle(stdout_read.handle, os.O_RDONLY | os.O_TEXT) with os.fdopen(fd_out, 'r') as f_out: stdout = f_out.read() ret['stdout'] = stdout # Read standard error fd_err = msvcrt.open_osfhandle(stderr_read.handle, os.O_RDONLY | os.O_TEXT) with os.fdopen(fd_err, 'r') as f_err: stderr = f_err.read() ret['stderr'] = stderr win32profile.UnloadUserProfile(user_token, handle_reg) salt.platform.win.kernel32.CloseHandle(hProcess) win32api.CloseHandle(user_token) if impersonation_token: win32security.RevertToSelf() win32api.CloseHandle(impersonation_token) return ret