SOLVED: Windows Identity Foundation – “The system cannot find the file specified”

I’ve been working on a proof of concept for using claims-based authorisation with Windows Identity Foundation (WIF) against an Active Directory Federation Services (ADFS) 2.0 security token service (STS).

I seemed to have everything in place but came up against the following error in a yellow screen of death:

System.Security.Cryptography.CryptographicException: The system cannot find the file specified.

image

Looking at the stack trace it seems that Data Protection API (DPAPI which in .NET is exposed as System.Security.Cryptography.ProtectedData) is being used to encrypt data. A common use of DPAPI is to do encryption without you having to worry about key management: you leave it to Windows to worry about where the keys are stored. Those keys are typically buried in your user profile/registry somewhere – so it seemed odd DPAPI was being used here at all – the DPAPI keys would need to be part of the App Pool user account profile/registry.

Anyway, to cut a long story short I wasn’t Reading The Fine error Message fully. The interesting/useful bit was scrolled horizontally off-screen:

[CryptographicException: The system cannot find the file specified.]
System.Security.Cryptography.ProtectedData.Protect(Byte[] userData, Byte[] optionalEntropy, DataProtectionScope scope) +681

Microsoft.IdentityModel.Web.ProtectedDataCookieTransform.Encode(Byte[] value) +121
[InvalidOperationException: ID1074: A CryptographicException occurred when attempting to encrypt the cookie using the ProtectedData API (see inner exception for details). If you are using IIS 7.5, this could be due to the loadUserProfile setting on the Application Pool being set to false. ]
Microsoft.IdentityModel.Web.ProtectedDataCookieTransform.Encode(Byte[] value) +1280740
Microsoft.IdentityModel.Tokens.SessionSecurityTokenHandler.ApplyTransforms(Byte[] cookie, Boolean outbound) +74

Sure enough WIF was using DPAPI to encrypt a token, but DPAPI was complaining it couldn’t get to the keys because there was no user profile for the App Pool identity, which in this case Environment.UserDomainName/UserName told me was “IIS APPPOOL\DefaultAppPool” – and there was no such user profile directory under C:\Users.

So sure enough in IIS, in the advanced settings for the App Pool, Load User Profile was false, and setting it to true creates and loads user profile (a “DefaultAppPool” profile directory appeared in C:\Users), and the application worked:

image

Typically WIF tutorials use the ASP.NET Web Sites, which use Cassini for testing, which runs under the current user identity and therefore a user profile with its DPAPI keys will be loaded – which is why if you use the standard run throughs/demos you don’t come up against this issue. But if you run as a Web Application under “real” IIS, this is when you may hit this problem.

It’s also debatable whether the use of DPAPI here is at all sensible. In a web farm environment the DPAPI keys for the App Pool identities across servers will be different, so if you don’t have sticky sessions enabled on your load balancer you run the risk of such federated logins not working 100% of the time. This issue is mentioned by Matias Woloski in the Geneva forums.

Another case of bad defaults all round.

Fixing WebSVN “Unable to call svn command” error

WebSVN is a great PHP web-based interface to Subversion that we run on our IIS build server. But, after updating to a more recent build we started getting errors like the following when viewing diffs:

Unable to call svn command "svn --non-interactive --config-dir /tmp"

The source of the error is in the getFileContents function in svnlook.php, where it’s piping the output of svn cat to GNU Enscript (for syntax highlighting) and then parsing the output of that using sed. I guessed that maybe the regex that sed is using isn’t being escaped properly for the Windows command line and therefore failing.

But I noticed that all of this code was in an if($config->useEnscript) block. Just before that is an if($config->useGeshi) block that looks a lot simpler. Simpler because GeSHi is PHP-based syntax highlighter, rather than an external command whose output requires special parsing. So I went to our include/config.php and added the $config->useGeshi(); call (as detailed in the distconfig.php template config file), and it all started working happily again!

Unzipping/extracting MSI files

If, like me, you are constantly wanting to just extract the files from a Windows Installer MSI file quickly, then this is for you.

My ZIP utility of choice 7-Zip appears to support extracting MSI files but in fact extracts all the various weird and wonderful binary streams in the MSI rather than simply just the actual files. Thankfully I stumbled across a Windows Installer switch today after typing msiexec /? that does the job perfectly: the /a “administrative install” switch, e.g.:

msiexec /a foo.msi /qb TARGETDIR="C:\TEMP\Foo"

So, what I’ve done is packaged this up as a little registry tweak that conveniently lets you do this by simply right clicking a file like so:

image

Copy and paste the following into a *.reg file and double-click it:

Windows Registry Editor Version 5.00
[HKEY_CURRENT_USER\Software\Classes\Msi.Package\shell\Extract MSI\command]
@="msiexec.exe /a \"%1\" /qb TARGETDIR=\"%1 Extracted\""

Hope that helps!

Disabling direct PDF viewing/opening from the web

This worries me (more information). It would appear that you could craft PDFs that could hijack someone’s machine simply by their opening the PDF. This is especially pernicious because Adobe Reader is so intent on integrating PDF into Internet Explorer using various Browser Helper Objects and ActiveX Controls that a “drive-by” hijack would be simple to set up once you’ve crafted the malicious PDF file.

A quick fix (that Works On My Machine™) that prevents the automatic opening/viewing of PDF files from the web is to change the HKEY_CLASSES_ROOT\.pdf\Content Type registry key from application/pdf to something like application/octet-stream. This means that you have to save the files first before opening them.

Some possible scriptable ways of automating this:

Method 1: A .REG file

Save the following into a file with a “.reg” file extension and running using regedit.exe /s filename.reg.

REGEDIT4
[HKEY_CLASSES_ROOT\.pdf]
"Content Type"="application/octet-stream"

Method 2: The REG command

Alternatively the following, using the reg.exe command will achieve the same result:

reg add HKCR\.pdf /v "Content Type" /d "application/octet-stream" /f

You obviously still need to be careful about PDFs, you just have the ability now to actively decide whether you want to open them.

Cisco home page FAIL

UPDATE: it’s over 2 hours later now and they’ve finally fixed it :)

Cisco’s home page this morning: looks like they ran out of their allocation of lowercase letter ‘t’ (thanks to Chris Venus for pointing it out):

image

Or was it “Speak Like an Irishman” day and nobody told me?

Lowercase ‘t’s were being stripped from the source which explains why there were no styles, etc:

image

Chris reckons it’s a possibly a whitespace-trimming RegEx gone wrong, WDYT?

Moving on from SVN_ASP_DOT_NET_HACK

I noticed that I was running TortoiseSVN in SVN_ASP_DOT_NET_HACK mode (where Subversion clients use ‘_svn’ instead of ‘.svn’ directories) unnecessarily as I don’t have silly old Visual Studio 2003 installed anymore which caused this mess in the first place.

The _svn directories work just as well as .svn, but nevertheless (due to mild OCD?), I created a batch script that ripped through my project directory renaming all ‘_svn’ directories to ‘.svn’, so I could remove the SVN_ASP_DOT_NET_HACK mode. It uses the wonderfully flexible FOR command drive the whole process. We don’t need no stinkin’ Powershell round these parts…

Save this script as something like “SvnRenameDirs.cmd” in the root of your projects folder:

:: Make script directory current
pushd "%~dp0"

:: Unhide, rename and re-hide svn dirs
for /r /d %%D in (*) do @if exist "%%D\_svn" (
   attrib -H "%%D\_svn"
   ren "%%D\_svn" ".svn"
   attrib +H "%%D\.svn"
)
popd

rundll32.exe shell32.dll,Control_RunDLL sysdm.cpl,0,3

At the end click the Environment Variables button in the System Properties dialog and remove the SVN_ASP_DOT_NET_HACK environment variable and then log out and back in again (or restart explorer.exe and TSVNCache.exe).

CTRL+TAB switching between document windows in Visual Studio

Visual Studio 2008 introduced a document switcher window that pops up when you do a CTRL+TAB. Nice idea, inspired by ALT+TAB application switching  but I find that the little previews it shows you are pretty useless. One code window looks like pretty much any other at that resolution. I prefer the previous behaviour of just immediately switching windows.

Sara Ford’s excellent series of Visual Studio tips prompted me to restore CTRL+TAB’s previous behaviour. You can do this by using the Keyboard binding page in Tools Options. In Tools > Options > Keyboard locate Window.NextDocumentWindowNav and remove the CTRL+TAB binding, then go to Window.NextDocumentWindow and assign CTRL+TAB there instead. Same drill for CTRL+SHIFT+TAB for Window.PreviousDocumentWindowNav and Window.PreviousDocumentWindow.

Sharing Google Picasa Libraries between users on the same computer

After a few years of using Adobe Photoshop Elements, last year we switched over to using Google’s free Picasa for organising our photo collection. Consecutive versions of Photoshop Elements were just getting slower and slower mainly it seemed due to waiting for the ‘kewl’ interface to redraw itself. Picasa is really slick and fast on our 2.8GHz Pentium 4 home PC. It can also upload our photos for printing to PhotoBox, and share them online using Google’s own Picasa Web Albums.

Photoshop Elements keeps all of your photo tags and collections in a ‘*.psa’ database file (which is actually Microsoft Access database). The useful thing we found about this was that we could share all our photo collection settings and tags between users. Picasa, on the other hand, stores its settings in hidden Picasa.ini files in your photo directories as well as in your local app settings user profile folder (buried in ‘Documents and Settings’ on Windows XP or the ‘Users’ folder on Vista). The problem with this is that you can’t share your Picasa library between users on the same machine as Picasa is hard-coded to look in the currently logged on user’s profile directory, and can’t be coaxed to look elsewhere, such as a shared location.

So to workaround this, you can take advantage of a feature of NTFS called junctions, which allow you to wire up one folder to another (or symbolic links, I’m not sure what the difference is, but the end result is the same). Windows Vista has a command-line tool called MKLINK which will create these. On Windows XP you will need to use the Sysinternals Junction command-line tool. Here’s what I did:

  1. Copy %LocalAppData%\Google\Picasa2 and Picasa2Albums to a shared location to which all users will have Modify access. (I chose C:\Users\Public\AppData\Local\Google on Vista, it’d be something like C:\Documents and Settings\Public on XP)
  2. Rename %LocalAppData%\Google\Picasa2 and Picasa2Albums e.g. “Picasa2.old” and “Picasa2Albums.old”
  3. Use MKLINK (Vista) or Junction (XP) to create a junction from
    %LocalAppData%\Google\Picasa2 to
    <SharedLocation>\Google\Picasa2
    and:
    %LocalAppData%\Google\Picasa2Albums to <SharedLocation>\Google\Picasa2Albums
  4. Repeat steps 2-3 for each user for whom you want to share the Picasa library

Of course this may break with a future version of Picasa, so proceed with caution and don’t blame me if it all goes horribly wrong.

Microsoft Search Server and FAST

Microsoft have a new server product: Search Server 2008. Well I say “new” but it seems to be based the same technology they’ve been pushing since the days of Site Server, on which I spent most of the late 1990′s travelling the world doing training and consulting. The same technology is used in Index Server, SQL Server Full Text Search, SharePoint, and even Windows Desktop Search.

It’s a workmanlike search technology, but I think people are so used to Google being so effective on the Internet that when they come to search their intranet using these technologies they come up short. You have to do a bit more wading through useless hits before you find what you’re looking for. In fact it’s a bit like going back the bad old days of AltaVista, et al before Google revolutionised search with PageRank.

This begs the question how good any intranet search solution could be (including Google’s own Search Appliance) on a intranet that consists of file shares and SharePoint document libraries containing mostly Word documents, Excel spreadsheets, etc, with nary a hyperlink in sight. How would you get something like PageRank, which relies on incoming links to help rank content, working with a “corpus” (in search parlance) such as this?

So, Microsoft have now pretty much admitted that their search technology needs some work, because they’ve just shelled out $1.2 billion for FAST,a Norwegian search technology company. Or should that be “bailed out” as FAST seem to have had some financial difficulties recently? It’ll be interesting to see if FAST’s technology, when they integrate it, is more effective than Microsoft’s current offerings.

Changing the font in Google Reader

I love Google Reader for reading blogs, but one thing that bugs me is the rather dull choice of font: sans-serif (Arial if you’re on Windows). If you have Vista or Office 2007 installed then you have a much better choice of fonts, one of my favourites being Calibri. If you don’t have Calibri, Microsoft ‘s trusty Verdana font is more readable online. Unfortunately, there’s currently no way to change the font in Reader’s settings pages. But, if you’re using Mozilla Firefox you can take advantage of user CSS and style any website however you choose, as long as you understand CSS.

Firefox’s user CSS lives in a file called userContent.css in the chrome directory within your Firefox profile which on Windows is somewhere like: %APPDATA%\Mozilla\Firefox\Profiles\<some alphanumeric id>.default\chrome\userContent.css.

Create the userContent.css file if it isn’t there already (there will just be a couple of example files there initially) and add the following:

@-moz-document url-prefix(http://www.google.com/reader/)
{
    body
    {
        font-family:Calibri !important;
        font-size:105% !important;
    }
}

Tweak the font and size to taste.

Internet Explorer also allows user stylesheets, but there’s no ability to target certain styles for specific sites. It’s made possible in Firefox by the “@-moz-document” and “url-prefix” psuedo-selectors.

It turns out there’s quite a community with the same idea: that they can tweak sites to their own tastes. So check out http://userstyles.org/ and the Stylish extension, which makes it even easier to apply user CSS, and a huge repository of ready-prepared CSS for popular sites, which you can use if you’re not CSS-literate. Daniel Cazzulino has a great example of a pimped-out GMail courtesy of Stylish.

Follow

Get every new post delivered to your Inbox.