Exemple #1
0
        public void ActivateScreen()
        {
            var lockState = WorkstationHelper.GetCurrentSessionLockState();

            if (lockState == WorkstationHelper.LockState.Locked ||
                lockState == WorkstationHelper.LockState.Unknown)
            {
                try
                {
                    // Should trigger activation of the screen in credential provider with zero impact on user
                    //inputSimulator.Keyboard.KeyPress(WindowsInput.Native.VirtualKeyCode.F12);
                    inputSimulator.Mouse.RightButtonClick(); // Windows 10 lockui ignores right mouse button for controls interaction
                }
                catch (Exception ex)
                {
                    // The exception generated by library uses generic Exception class
                    if (ex.Message.StartsWith("Some simulated input commands were not sent successfully"))
                    {
                        // This exception is thrown when the library could not successfully send simulated input
                        // To the target window, usually due to User Interface Privacy Isolation (UIPI)
                        _log.WriteLine("UIPI prevented simulated input", LogErrorSeverity.Warning);
                    }
                    else
                    {
                        throw;
                    }
                }
            }
        }
Exemple #2
0
            public async Task Run()
            {
#if !DEBUG
                if (WorkstationHelper.GetActiveSessionLockState() == WorkstationHelper.LockState.Unlocked)
                {
                    try
                    {
                        SessionSwitchMonitor.SessionSwitch += SessionSwitchMonitor_SessionSwitch;

                        _wcfLocker.LockWorkstation();

                        await Task.WhenAny(_tcs.Task, Task.Delay(_lockTimeout));
                    }
                    finally
                    {
                        SessionSwitchMonitor.SessionSwitch -= SessionSwitchMonitor_SessionSwitch;
                    }

                    if (!_tcs.Task.IsCompleted &&
                        WorkstationHelper.GetActiveSessionLockState() == WorkstationHelper.LockState.Unlocked)
                    {
                        _wtsapiLocker.LockWorkstation();
                    }
                }
#endif
            }
        public SessionTimestampLogger(string timestampFilePath, SessionInfoProvider sessionInfoProvider, EventSaver eventSaver, ILog log)
            : base(nameof(SessionTimestampLogger), log)
        {
            _timestampFilePath   = timestampFilePath;
            _sessionInfoProvider = sessionInfoProvider;
            _eventSaver          = eventSaver;

            _timestampSaveTimer.Elapsed += TimestampSaveTimer_Elapsed;

            var savedTimestamp = GetSavedTimestamp();

            if (savedTimestamp != null)
            {
                GenerateSessionEndEvent(savedTimestamp);
                ClearSavedTimestamp();
            }

            SessionSwitchMonitor.SessionSwitch += SessionSwitchMonitor_SessionSwitch;

            var state = WorkstationHelper.GetSessionLockState(WorkstationHelper.GetSessionId());

            if (state == WorkstationHelper.LockState.Unlocked)
            {
                SaveOrUpdateTimestamp(CreateNewTimestamp());
                _timestampSaveTimer.Start();
            }
        }
Exemple #4
0
        public void LockWorkstation()
        {
            var lockState = WorkstationHelper.GetActiveSessionLockState();

            if (lockState == WorkstationHelper.LockState.Unlocked)
            {
                IntPtr ppSessionInfo  = IntPtr.Zero;
                IntPtr userPtr        = IntPtr.Zero;
                IntPtr domainPtr      = IntPtr.Zero;
                Int32  count          = 0;
                Int32  retval         = WTSEnumerateSessions(IntPtr.Zero, 0, 1, ref ppSessionInfo, ref count);
                Int32  dataSize       = Marshal.SizeOf(typeof(WTS_SESSION_INFO));
                var    currentSession = ppSessionInfo;
                uint   bytes          = 0;

                if (retval == 0)
                {
                    return;
                }

                WriteLine("Query sessions");
                for (int i = 0; i < count; i++)
                {
                    WTS_SESSION_INFO si = (WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)currentSession, typeof(WTS_SESSION_INFO));
                    currentSession += dataSize;

                    WTSQuerySessionInformation(IntPtr.Zero, si.SessionID, WTS_INFO_CLASS.WTSUserName, out userPtr, out bytes);
                    WTSQuerySessionInformation(IntPtr.Zero, si.SessionID, WTS_INFO_CLASS.WTSDomainName, out domainPtr, out bytes);

                    var domain          = Marshal.PtrToStringAnsi(domainPtr);
                    var userName        = Marshal.PtrToStringAnsi(userPtr);
                    var sessionFullName = domain + "\\" + userName;

                    WTSFreeMemory(userPtr);
                    WTSFreeMemory(domainPtr);

                    // Note: it might be a good idea to limit session disconnects only to those activated by triggered device
                    //if (sessionFullName == sessionTolock)
                    if (!string.IsNullOrWhiteSpace(domain) && !string.IsNullOrWhiteSpace(userName))
                    {
                        if (si.State == WTS_CONNECTSTATE_CLASS.WTSActive)
                        {
                            WriteLine($"Disconnecting session: {sessionFullName}");
                            bool disconnected = WTSDisconnectSession(IntPtr.Zero, si.SessionID, true);
                            WriteLine($"Session disconnected: {disconnected}");
                        }
                        else
                        {
                            WriteLine($"Session inactive: {sessionFullName}");
                        }
                    }
                    else
                    {
                        WriteLine($"Session skipped: {sessionFullName}");
                    }
                }
                WTSFreeMemory(ppSessionInfo);
            }
        }
Exemple #5
0
        void GenerateNewSessionId()
        {
            PreviousSession = CurrentSession;
            var virtualSessionId = Guid.NewGuid().ToString();
            var sessionName      = WorkstationHelper.GetSessionName(WorkstationHelper.GetSessionId());

            CurrentSession = new SessionInfo(virtualSessionId, sessionName);
            WriteLine($"Generated new session id: (current: {CurrentSession?.SessionId}), (prev: {PreviousSession?.SessionId})");
        }
Exemple #6
0
        void GenerateNewIdIfUnlocked()
        {
            var sid   = WorkstationHelper.GetSessionId();
            var state = WorkstationHelper.GetSessionLockState(sid);
            var name  = WorkstationHelper.GetSessionName(sid);

            WriteLine($"Startup sid:{sid}, state:{state}, name:{name}");

            if (state == WorkstationHelper.LockState.Unlocked && name != "SYSTEM")
            {
                GenerateNewSessionId();
            }
        }
Exemple #7
0
 void ProximityMonitorManager_DeviceConnectionLost(object sender, IDevice device)
 {
     if (IsEnabled)
     {
         // Reconnect is performed only if manager is enabled and we are in unlocked windows session
         // Certain operations explicitly deny device reconnect and so CanReconnect will be FALSE during them
         if (!WorkstationHelper.IsActiveSessionLocked() && CanReconnect(device.SerialNo))
         {
             Task.Run(() => Reconnect(device));
         }
         else
         {
             SafeInvoke(DeviceDisconnected, device);
         }
     }
 }
Exemple #8
0
 void LockWorkstationAsync()
 {
     Task.Run(async() =>
     {
         var lockState = WorkstationHelper.GetActiveSessionLockState();
         if (lockState == WorkstationHelper.LockState.Unlocked)
         {
             try
             {
                 await _messenger.Publish(new LockWorkstationMessage());
             }
             catch (Exception ex)
             {
                 WriteLine(ex);
             }
         }
     });
 }
        public void Start()
        {
            lock (_isRunningLock)
            {
                if (!_isRunning)
                {
                    if (!WorkstationHelper.IsActiveSessionLocked())
                    {
                        GenerateAndSaveUnlockToken();
                    }

                    // Ensure that during the first launch on locked workstation unlock token is still generated
                    if (_unlockTokenProvider.GetUnlockToken() == string.Empty)
                    {
                        GenerateAndSaveUnlockToken();
                    }

                    _isRunning = true;
                    WriteLine("Started");
                }
            }
        }
Exemple #10
0
        /// <summary>
        /// Create and authorize remote device, then load credentials storage from this device
        /// </summary>
        /// <param name="authorizeDevice">If false, skip remote device authorization step. Default is true.</param>
        public async Task InitRemoteAndLoadStorageAsync(bool authorizeDevice = true)
        {
            if (Interlocked.CompareExchange(ref _interlockedRemote, 1, 0) == 0)
            {
                try
                {
                    if (!IsCreatingRemoteDevice &&
                        !IsAuthorizingRemoteDevice &&
                        !IsLoadingStorage &&
                        WorkstationHelper.GetCurrentSessionLockState() == WorkstationHelper.LockState.Unlocked)
                    {
                        try
                        {
                            authCancellationTokenSource = new CancellationTokenSource();
                            var ct = authCancellationTokenSource.Token;

                            remoteCancellationTokenSource = new CancellationTokenSource();

                            _infNid = Guid.NewGuid().ToString();
                            _errNid = Guid.NewGuid().ToString();

                            await CreateRemoteDeviceAsync(remoteCancellationTokenSource.Token);

                            if (remoteCancellationTokenSource.IsCancellationRequested)
                            {
                                _log.WriteLine($"({SerialNo}) Remote vault creation cancelled");
                                return;
                            }

                            if (_remoteDevice != null)
                            {
                                _log.WriteLine($"({_remoteDevice.SerialNo}) Remote vault created");
                                await _remoteDevice.RefreshDeviceInfo();

                                if (_remoteDevice.AccessLevel != null)
                                {
                                    _log.WriteLine($"({_remoteDevice.SerialNo}) access profile (allOk:{_remoteDevice.AccessLevel.IsAllOk}; " +
                                                   $"pin:{_remoteDevice.AccessLevel.IsPinRequired}; " +
                                                   $"newPin:{_remoteDevice.AccessLevel.IsNewPinRequired}; " +
                                                   $"button:{_remoteDevice.AccessLevel.IsButtonRequired}; " +
                                                   $"link:{_remoteDevice.AccessLevel.IsLinkRequired}; " +
                                                   $"master:{_remoteDevice.AccessLevel.IsMasterKeyRequired}; " +
                                                   $"locked:{_remoteDevice.AccessLevel.IsLocked})");
                                }
                                else
                                {
                                    _log.WriteLine($"({_remoteDevice.SerialNo}) access level is null");
                                }
                            }

                            if (_remoteDevice.IsLockedByCode)
                            {
                                throw new HideezException(HideezErrorCode.DeviceIsLocked);
                            }
                            else if (authorizeDevice && !IsAuthorized && _remoteDevice?.AccessLevel != null && !_remoteDevice.AccessLevel.IsAllOk)
                            {
                                await AuthorizeRemoteDevice(ct);
                            }
                            else if (!authorizeDevice && !IsAuthorized && _remoteDevice?.AccessLevel != null && _remoteDevice.AccessLevel.IsAllOk)
                            {
                                await AuthorizeRemoteDevice(ct);
                            }
                            else if (_remoteDevice?.AccessLevel != null && _remoteDevice.AccessLevel.IsLocked)
                            {
                                throw new HideezException(HideezErrorCode.DeviceIsLocked);
                            }

                            if (!ct.IsCancellationRequested && !IsStorageLoaded)
                            {
                                await LoadStorage();
                            }
                        }
                        catch (HideezException ex) when(ex.ErrorCode == HideezErrorCode.DeviceDisconnected)
                        {
                            _log.WriteLine("Remote vault creation aborted, vault disconnected", LogErrorSeverity.Warning);
                        }
                        catch (HideezException ex) when(ex.ErrorCode == HideezErrorCode.DeviceIsLocked)
                        {
                            if (_remoteDevice.IsLockedByCode)
                            {
                                await _metaMessenger.Publish(new ShowLockNotificationMessage(TranslationSource.Instance["Notification.DeviceLockedByCode.Message"],
                                                                                             TranslationSource.Instance["Notification.DeviceLockedByCode.Caption"],
                                                                                             new NotificationOptions()
                                {
                                    CloseTimeout = NotificationOptions.LongTimeout
                                },
                                                                                             Mac));
                            }
                            else if (_remoteDevice.IsLockedByPin)
                            {
                                await _metaMessenger.Publish(new ShowLockNotificationMessage(TranslationSource.Instance["Notification.DeviceLockedByPin.Message"],
                                                                                             TranslationSource.Instance["Notification.DeviceLockedByPin.Caption"],
                                                                                             new NotificationOptions()
                                {
                                    CloseTimeout = NotificationOptions.LongTimeout
                                },
                                                                                             Mac));
                            }
                            else
                            {
                                _log.WriteLine(ex);
                            }
                        }
                        catch (HideezException ex) when(ex.ErrorCode == HideezErrorCode.DeviceIsLockedByPin)
                        {
                        }
                        catch (HideezException ex) when(ex.ErrorCode == HideezErrorCode.DeviceIsLockedByCode)
                        {
                        }
                        catch (Exception ex)
                        {
                            ShowError(ex.Message, _errNid);
                        }
                        finally
                        {
                            var tmp = authCancellationTokenSource;
                            authCancellationTokenSource = null;
                            tmp.Dispose();

                            tmp = remoteCancellationTokenSource;
                            remoteCancellationTokenSource = null;
                            tmp.Dispose();
                        }
                    }
                }
                finally
                {
                    Interlocked.Exchange(ref _interlockedRemote, 0);
                }
            }
        }
        async Task MainWorkflow(string mac, bool rebondOnConnectionFail, bool tryUnlock, Action <WorkstationUnlockResult> onUnlockAttempt, CancellationToken ct)
        {
            // Ignore MainFlow requests for devices that are already connected
            // IsConnected-true indicates that device already finished main flow or is in progress
            var existingDevice = _deviceManager.Find(mac, (int)DefaultDeviceChannel.Main);

            if (existingDevice != null && existingDevice.IsConnected && !WorkstationHelper.IsActiveSessionLocked())
            {
                return;
            }

            WriteLine($"Started main workflow ({mac})");

            var flowId = Guid.NewGuid().ToString();

            Started?.Invoke(this, flowId);

            bool    workflowFinishedSuccessfully = false;
            bool    deleteVaultBond = false;
            string  errorMessage    = null;
            IDevice device          = null;

            try
            {
                await _ui.SendNotification(string.Empty, mac);

                _subp.PermissionsCheckProcessor.CheckPermissions();

                // Start periodic screen activator to raise the "curtain"
                if (WorkstationHelper.IsActiveSessionLocked())
                {
                    _screenActivator?.ActivateScreen();
                    _screenActivator?.StartPeriodicScreenActivation(0);

                    await new WaitWorkstationUnlockerConnectProc(_workstationUnlocker)
                    .Run(SdkConfig.WorkstationUnlockerConnectTimeout, ct);
                }

                device = await _subp.VaultConnectionProcessor.ConnectVault(mac, rebondOnConnectionFail, ct);

                device.Disconnected       += OnVaultDisconnectedDuringFlow;
                device.OperationCancelled += OnCancelledByVaultButton;

                await _subp.VaultConnectionProcessor.WaitVaultInitialization(mac, device, ct);

                if (device.IsBoot)
                {
                    throw new WorkflowException(TranslationSource.Instance["ConnectionFlow.Error.VaultInBootloaderMode"]);
                }

                device.SetUserProperty(CustomProperties.HW_CONNECTION_STATE_PROP, HwVaultConnectionState.Initializing);

                HwVaultInfoFromHesDto vaultInfo = new HwVaultInfoFromHesDto(); // Initializes with default values for when HES is not connected
                if (_hesConnection.State == HesConnectionState.Connected)
                {
                    vaultInfo = await _hesConnection.UpdateHwVaultProperties(new HwVaultInfoFromClientDto(device), true);
                }

                _subp.CacheVaultInfoProcessor.CacheAndUpdateVaultOwner(ref device, vaultInfo, ct);

                await _subp.LicensingProcessor.CheckLicense(device, vaultInfo, ct);

                vaultInfo = await _subp.StateUpdateProcessor.UpdateVaultStatus(device, vaultInfo, ct);

                vaultInfo = await _subp.ActivationProcessor.ActivateVault(device, vaultInfo, ct);

                await _subp.MasterkeyProcessor.AuthVault(device, ct);

                var osAccUpdateTask = _subp.AccountsUpdateProcessor.UpdateAccounts(device, vaultInfo, true);
                if (_workstationUnlocker.IsConnected && WorkstationHelper.IsActiveSessionLocked() && tryUnlock)
                {
                    await Task.WhenAll(_subp.UserAuthorizationProcessor.AuthorizeUser(device, ct), osAccUpdateTask);

                    _screenActivator?.StopPeriodicScreenActivation();
                    await _subp.UnlockProcessor.UnlockWorkstation(device, flowId, onUnlockAttempt, ct);
                }
                else
                {
                    await osAccUpdateTask;
                }

                device.SetUserProperty(CustomProperties.HW_CONNECTION_STATE_PROP, HwVaultConnectionState.Finalizing);
                WriteLine($"Finalizing main workflow: ({device.Id})");
                DeviceFinilizingMainFlow?.Invoke(this, device);

                await _subp.AccountsUpdateProcessor.UpdateAccounts(device, vaultInfo, false);

                device.SetUserProperty(CustomProperties.HW_CONNECTION_STATE_PROP, HwVaultConnectionState.Online);

                if (_hesConnection.State == HesConnectionState.Connected)
                {
                    await _hesConnection.UpdateHwVaultProperties(new HwVaultInfoFromClientDto(device), false);
                }

                workflowFinishedSuccessfully = true;
            }
            catch (HideezException ex)
            {
                switch (ex.ErrorCode)
                {
                case HideezErrorCode.DeviceIsLocked:
                case HideezErrorCode.DeviceNotAssignedToUser:
                case HideezErrorCode.HesDeviceNotFound:
                case HideezErrorCode.HesDeviceCompromised:
                case HideezErrorCode.DeviceHasBeenWiped:
                    // There errors require bond removal
                    deleteVaultBond = true;
                    errorMessage    = HideezExceptionLocalization.GetErrorAsString(ex);
                    break;

                case HideezErrorCode.ButtonConfirmationTimeout:
                case HideezErrorCode.GetPinTimeout:
                case HideezErrorCode.GetActivationCodeTimeout:
                    // Silent handling
                    WriteLine(ex);
                    break;

                case HideezErrorCode.HesNotConnected:
                    // We need to display an error message which is different from one that is usually shown for that error code.
                    errorMessage = TranslationSource.Instance["ConnectionFlow.Error.UnexpectedlyLostNetworkConnection"];
                    break;

                default:
                    errorMessage = HideezExceptionLocalization.GetErrorAsString(ex);
                    break;
                }
            }
            catch (VaultFailedToAuthorizeException ex)
            {
                // User should never receive this error unless there is a bug in algorithm
                errorMessage = HideezExceptionLocalization.GetErrorAsString(ex);
            }
            catch (WorkstationUnlockFailedException ex)
            {
                // Silent handling of failed workstation unlock
                // The actual message will be displayed by credential provider
                WriteLine(ex);
            }
            catch (OperationCanceledException ex)
            {
                // Silent cancelation handling
                WriteLine(ex);
            }
            catch (TimeoutException ex)
            {
                // Silent timeout handling
                WriteLine(ex);
            }
            catch (WebSocketException ex)
            {
                // Retrieve the most inner WebSocketException to retrieve the error code
                if (ex.WebSocketErrorCode != 0)
                {
                    errorMessage = string.Format(TranslationSource.Instance["ConnectionFlow.Error.UnexpectedNetworkError"], ex.WebSocketErrorCode);
                }
                else if (ex.ErrorCode != 0)
                {
                    errorMessage = string.Format(TranslationSource.Instance["ConnectionFlow.Error.UnexpectedNetworkError"], ex.ErrorCode);
                }
                else if (ex.InnerException is Win32Exception)
                {
                    errorMessage = string.Format(TranslationSource.Instance["ConnectionFlow.Error.UnexpectedNetworkError"], "native " + (ex.InnerException as Win32Exception).NativeErrorCode);
                }
            }
            catch (Exception ex)
            {
                errorMessage = HideezExceptionLocalization.GetErrorAsString(ex);
            }
            finally
            {
                if (device != null)
                {
                    device.Disconnected       -= OnVaultDisconnectedDuringFlow;
                    device.OperationCancelled -= OnCancelledByVaultButton;
                }
                _screenActivator?.StopPeriodicScreenActivation();
            }

            await WorkflowCleanup(errorMessage, mac, device, workflowFinishedSuccessfully, deleteVaultBond);

            Finished?.Invoke(this, flowId);

            WriteLine($"Main workflow end {mac}");
        }