Search code examples
winapiiispermissionspinvoke

CreateProcessAsUser() gives "A required privilege is not held by the client" Which one?


Using System.Diagnostic.Process.Start() from IIS Express running in my interactive session, I can execute a program running as a different user with correction functionality. Unfortunately, it seems that this doesn't work from non-interactive sessions.

Process.Start internally calls CreateProcessWithLogonW(CPLW) when credentials are specified. CreateProcessWithLogonW cannot be called from a Windows Service Environment (such as an IIS WCF service). It can only be called from an Interactive Process (an application launched by a user who logged on via CTRL-ALT-DELETE). -- from this SO answer

I need to publish this site to IIS 8 from the app pool account. So I CreateProcessAsUser as suggested by the above-quoted answer. I've set the service account and agent account with Local Security Policies and restarted as suggested in that answer - service account can replace token, modify quotas and agent account can logon as batch (and as service for that test). But I can't get it to work in IIS Express (or a console test app) nor IIS 8. I've tried running as LOGON32_LOGON_BATCH, LOGON32_LOGON_NETWORK_CLEARTEXT, and LOGON32_LOGON_SERVICE, and even LOGON32_LOGON_INTERACTIVE. I've even given my own account "logon as service" and "act as part of the operating system" privilege with no change - all tested after a reboot.

I'm getting "A required privilege is not held by the client" from IIS Express for all configurations. On the server, I get the same running the console app. But publishing the app, it seems to start the process just fine, but then I seem to be getting permissions errors subsequently.

I'd like to know WHICH privilege my accounts are missing when running locally so I can debug them properly (and eventually figure out whatever permissions error I'm getting). Is there any way to determine that? Either way, if you know what the issue is, I'd like that too!

Thanks!


Solution

  • Per the documentation:

    CreateProcessAsUser function

    Typically, the process that calls the CreateProcessAsUser function must have the SE_INCREASE_QUOTA_NAME privilege and may require the SE_ASSIGNPRIMARYTOKEN_NAME privilege if the token is not assignable. If this function fails with ERROR_PRIVILEGE_NOT_HELD (1314), use the CreateProcessWithLogonW function instead. CreateProcessWithLogonW requires no special privileges, but the specified user account must be allowed to log on interactively. Generally, it is best to use CreateProcessWithLogonW to create a process with alternate credentials.
    ...
    If hToken is a restricted version of the caller's primary token, the SE_ASSIGNPRIMARYTOKEN_NAME privilege is not required. If the necessary privileges are not already enabled, CreateProcessAsUser enables them for the duration of the call.

    The calling thread can use OpenThreadToken() and AdjustTokenPrivileges() to enable individual privileges as needed before calling CreateProcessAsUser(). But since it does that internally anyway, that implies the user associated with the calling thread does not have those privileges available to begin with.