WebDAV is a … pain

[Titled edited ;P]

As a concept – WebDAV is great. File shares over HTTP – no fussy protocols to deal with, security and encryption built right in.

Problems. You want to use Apache as a WebDAV server with mod_dav. Theroetically, this is fine. In my circumstances, I wanted to use it for a few specific people to reach their /home/username folders, so I thought using Apache I could just export those directories as DAV shares, using LDAP authentication. I hit several problems with this.

First, permissions. Apache obviously runs as ‘nobody’ or ‘apache’ or ‘httpd’ depending on your system. This user doesn’t have permission to access your home directory, much less, write to it. And you don’t REALLY want your front-facing web server having that permission. I solved this by installing mod_proxy and mod_proxy_http, then running a tiny little lighttpd instance as the user(s) who wanted access to their home directories, with it’s own mod_webdav inserted. I had Apache pass connections to the webdav-server.domain/username vhost/folder alias through the proxy to the lighttpd server for that user, which was exporting that user’s home directory as a single share. I also used lighttpd’s own mod_auth to do the LDAP authentication for each user instead of Apache, because I didn’t want to chance someone getting around the front-facing proxy and connecting directly to one of the DAV servers, obviously. It is worth noting that you will want to set the document-root to either /home or /home/username for the lighty instance, as COPY and MOVE will not work if you don’t. Since authentication is required for the site anyway, it’s not a huge concern to set it to the user’s home directory. This setup seems to work pretty well.

Which brings us to the second problem. Windows XP SP2, Windows Vista and Windows 7 refuse to authenticate to a WebDAV server using BASIC as it’s authentication method (instead of DIGEST). If I were using password files, this would be no problem to change to DIGEST authentication using lighty’s mod_auth, but because I’m using LDAP as a backend, it’s not feasible. You can’t use DIGEST with LDAP because, with DIGEST, the password is never actually sent – just a hash to be compared, but the comparison hash will simply never match what’s in the LDAP database, so there’s no way to do the auth. Instead, the solution seems to be dealing with Windows. After lots and lots of Googling, I found a few registry hacks:

HKLM\SYSTEM\CurrentControlSet\services\WebClient\Parameters\UseBasicAuth
HKLM\SYSTEM\CurrentControlSet\services\WebClient\Parameters\BasicAuthLevel

If you set UseBasicAuth (a DWORD value) to 0×00000001 and BasicAuthLevel (also a DWORD value) to 0×00000002, you will be able to authenticate to the DAV server with BASIC authentication. The first parameter enabled BASIC authentication altogether. The latter has three possible values: 0, which disabled BASIC authentication, 1, which enabled it for SSL-secured sites and 2, the value I’m using above, to enable it for all sites. When you’re done, restart the webclient service. (In Vista/7, you can only do this from services.msc or by using an ELEVATED privileges command prompt – not a normal one.)

Now, I wanted to use this with Active Directory to set a user’s N-drive to their home directory. I know it would be easier to use Samba, but if a user is behind a vaguely-filtered internet connection, say Comcast, Virgin Media or Verizon Fios, you can’t actually hit a Samba share over the internet. And VPNs can be even more of a … pain than WebDAV. In theory, you can address a WebDAV share with a UNC path and it works (\\webdav-server.fqdn\sharename). It doesn’t, however, seem to work when you set that UNC path to a drive letter in someone’s AD account. Which sucks.

So I thought, ooh – I know! Map it with a logon script! DERP. Logon scripts have to run from a Samba share. Which we can’t get to. Hence using WebDAV. The solution, if I say so myself, is pretty creative, if not a little over-the-top. I created a folder, say, C:\logon. In there, there is ‘wget.exe’, a Windows binary-only version of the ‘wget’ tool for Linux, which is a simple command-line based HTTP/FTP downloader. Then there’s a file called loader. bat. This file fetches a logon.bat from a web server, and runs it. Then, in their Active Directory profile, I set their logon script to \\localhost\c$\logon\loader.bat – causing them, each time they logon, to download the latest logon.bat and run it. In logon.bat, I use wget again to download a little .exe file written in AutoIT that checks if the registry has already been updated to connect to WebDAV shares using BASIC authentication as above, and if not, requests administrative privileges to update the registry and then restart the webclient service for you. After all this happens, it finally uses ‘net use’ to map the WebDAV shares (the lighty one from earlier as well as an additional SharePoint share) to their relevant drive letters. Scripts below.

The wget.exe I’m using comes from: http://pages.interlog.com/~tcharron/wgetwin.html

loader.bat

@echo off
cd C:\logon
del c:\logon\logon.bat
C:\logon\wget http://some-http-server.fqdn/logon/logon.bat
C:\logon\logon.bat

logon.bat

@echo off
cd C:\logon
del C:\logon\dav-setup.exe
C:\logon\wget http://some-http-server.fqdn/logon/dav-setup.exe
C:\logon\dav-setup.exe

net use N: "http://apache-proxy-to-lighty.fqdn/sharename" /user:username /persistent:yes /savecred
net use T: "http://sharepoint.fqdn/sharename" /user:domain\username /persistent:yes /savecred

dav-setup.au3

#RequireAdmin

$useBasicAuth = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\WebClient\Parameters", "UseBasicAuth")
$basicAuthLevel = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\WebClient\Parameters", "BasicAuthLevel")

$restartService = 0

if $useBasicAuth <> 1 Then
    RegWrite("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\WebClient\Parameters", "UseBasicAuth", "REG_DWORD", "0x00000001")
    $restartService = 1
EndIf

if $basicAuthLevel <> 2 Then
    RegWrite("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\WebClient\Parameters", "BasicAuthLevel", "REG_DWORD", "0x00000002")
    $restartService = 1
EndIf

if $restartService = 1 Then
    RunWait(@WindowsDir & "\System32\net stop webclient")
    RunWait(@WindowsDir & "\System32\net start webclient")
EndIf

Post Revisions:

Leave a comment

You must be logged in to post a comment.