loadUserProfile and IIS7 - understanding temporary directory failures

I've noticed quite a few people running into temporary directory permission issues.  The PHP blog post I made last month is one example of this issue, there are also several forum posts related to ASP & Access database failures, where the reported failure is:

Microsoft JET Database Engine error '80004005'
Unspecified error

Not a very helpful error, to be sure.  It turns out all of these cases have a similar underlying cause:  the effective user of the web application (including the anonymous user for unauthenticated requests) can not effectively write to the temporary directory.  What changed in IIS7 and why did this always work before?

With IIS6, all worker processes, regardless of which the process identity was configured, used to C:\windows\temp as the temporary directory.  More specifically, none of the worker processes loaded their 'user profile' by default, causing all of them to use c:\windows\temp as a temporary directory.  Windows allows all users read/write/creator privledges on this directory, which allowed things to 'just work'.  The negative side effect of this is that all AppPools are effectively sharing the same temporary directory by default, which could lead to cross-appPool information disclosure. 

With IIS7, we've chosen a more secure default and now load user profile by default for all application pools.  Unfortunately, the temporary directory underneath the user directory (for example - %windir%\serviceprofiles\networkservice\AppData\Local\Temp for the default NetworkService identity we use for DefaultAppPool) is not writable by anyone other than NetworkService by default.

There are two ways to workaround this.  First, I recommend that ACL the NetworkService temporary directory to allow whichever users read/write/creator privs that you want to allow access so that you still have the benefits of loading a user profile and separating temp directories per appPool.  This can easily be done on the command line like this:

 

icacls %windir%\serviceprofiles\networkservice\AppData\Local\Temp /grant Users:(CI)(S,WD,AD,X)

icacls %windir%\serviceprofiles\networkservice\AppData\Local\Temp /grant "CREATOR OWNER":(OI)(CI)(IO)(F)

This allows every user to create files and directories (WD = Write to Directory, AD = Add Directory, X = Execute, S = Synchronize). The user who creates them will be the “CREATOR OWNER” of the file/directory.

The “CREATOR OWNER” ACE allows this user to do whatever he wants with the file. Other users can’t access these files/directories because they are not “CREATOR OWNER” of them.

 

The other less favorable workaround is to disable the loadUserProfile setting on a per-appPool basis.  loadUserProfile is a boolean property on an AppPool section, and can easily be set on the command line (for defaultAppPool) like this:

 

%windir%\system32\inetsrv\appcmd set config -section:applicationPools /[name='DefaultAppPool'].processModel.loadUserProfile:false

 

hope this helps -

 

bill

6 Comments

  • You could also configure your app to not write to %temp%.

    filemon from sysinternals.com allows you to quickly identify file system access issues.

  • very true, Rick. For PHP this is relatively simple. Use the session.save_path in the php.ini file. I'm not sure how or if this is possible with Access, for example. ADO is opening the file in the temporary directory behind the scenes, and I'm not sure if there is a way to change the directory it uses.

  • With Vista RTM I get the following error;

    C:\>c:\windows\system32\inetsrv\appcmd set config -section:applicationPools /[nme='DefaultAppPool'].processModel.loadUserProfile:false
    ERROR ( message:Configuration error Filename: \\?\C:\Windows\system32\inetsrv\config\applicationHost.config
    Line Number: 0
    Description: Cannot read configuration file
    . )

  • Alex: make sure you run this command line in an 'elevated' cmd window. Right click on "Command Prompt" in start menu and choose "Run as Administrator"

  • I have tried the above several times with the exception of re-setting the location of the temp folder and I still can' get the sessions (i think that is the problem) to work. I have Vista, PHP 5? MySQL (latest) and coppermine running. I ran the install so I know the SQL works, and as far as I can tell everything is working. I can login to copermine, however, when it reloads it doe snot appea to be setting the session values to know I am logged in.

    Ideas?

  • The first solution didn't work for me and I had to use the second option of disabling the user profile for the app pool. This allowed my asp pages to read an Access db but does not allow them to write to the db. I get the old 'operation must use an updatable query' error.

    I've checked file and folder permissions and they all allow IUSR correctly.

    Also tried Process Monitor to isolate the problem but can't see anything obvious, although there are various 'name not found' errors when IE looks at register keys.

    What else needs to be set??

Comments have been disabled for this content.