Skip to content

Explicit-credential impersonation and process launch

SAIFCredentials holds a username, domain, and SecureString password so that a caller can later act as that identity — either by impersonating it on the current thread, or by launching an entirely separate child process under it. The two use cases share the same stored credential set but reach the target identity through different mechanisms: in-thread impersonation via clsElevateImpersonate, or process-level credential delegation via ProcessStartInfo.

Field Value
Operation ID OP-010
Trigger Caller invokes Impersonate() or RunAs()
Inputs Stored username, domain, secure password, optional ProcessStartInfo
Outputs Boolean impersonation result, started process, or cleared impersonation state
Primary components SAIFCredentials.Impersonate, SAIFCredentials.RunAs, SAIFCredentials.UndoImpersonate, clsElevateImpersonate.ImpersonateUser
Entry point SAIF.Framework.Security\SAIFCredentials.vb

Steps

  1. Impersonate() first undoes any impersonation already in effect, then creates a new clsElevateImpersonate, converts the stored SecureString password back to clear text just long enough to authenticate, and calls ImpersonateUser(userName, domain, password).
  2. If ImpersonateUser fails: the method returns False and leaves the thread running under its prior identity.
  3. clsElevateImpersonate.ImpersonateUser invokes Win32 LogonUser and DuplicateToken, builds a WindowsIdentity from the duplicated token, impersonates it, and stores the resulting WindowsImpersonationContext so it can be undone later.
  4. If the Win32 logon call or token duplication fails: the helper returns False rather than raising a library-specific exception, so callers must check the boolean result.
  5. RunAs() takes a different path for one-off process launches: it temporarily calls UndoImpersonate() if credentials are currently impersonated, copies the stored username/domain/password directly onto a ProcessStartInfo, disables shell execution (required when supplying alternate credentials), and starts the child process.
  6. Once the child process has launched, RunAs() restores impersonation if it had been active before step 3 began, so the calling thread's security context is left exactly as it was found.
  7. UndoImpersonate() and Clear() provide the explicit teardown path: they unwind the active impersonation context, reset internal flags, and — in Clear()'s case — dispose the secure password object and null out the stored credential references.

Process flow

The following diagram visualizes this operation's control flow.

flowchart TD
    Start([Impersonate or RunAs called]) --> Mode{RunAs?}
    Mode -->|No| Imp[Acquire token and impersonate]
    Mode -->|Yes| Undo[Undo active impersonation if needed]
    Undo --> Launch[Populate ProcessStartInfo and launch]
    Launch --> Restore[Restore impersonation if needed]
    Imp --> Result{Impersonation succeeded?}
    Result -->|Yes| EndOk([Return success])
    Result -->|No| EndErr([Return failure])
    Restore --> EndProc([Return started process])

Failure and edge-case behavior

  • Any existing impersonation is torn down before a new impersonation attempt begins, so the two states never overlap.
  • RunAs() disables shell execution because Windows requires it when a process is launched with alternate credentials supplied directly on ProcessStartInfo.
  • Clear() disposes the secure password object and nulls the stored credential fields, leaving the SAIFCredentials instance unusable for further impersonation until new credentials are supplied.

Sources

  • SAIF.Framework.Security\SAIFCredentials.vb
  • SAIF.Framework.Security\clsElevateImpersonate.vb