WebDAV revisited

In my previous endeavour with WebDAV, I ended up using a complicated lighttpd/apache proxy system to get the permissions right. This did work well enough, but it had a few limitations. In involved modifying the registry on the client systems and it required a new lighty instance running for each share with different permissions to the last (which wasn’t terribly efficient). Additionally, lighty’s mod_webdav lacked support for a few vital operations which made working with the shares a bit difficult, not to mention there were some MIME-type conflicts between lighty/apache/the webDAV client that made working with certain types of files near impossible.

I have since revised some of the methods I’ve used to implement the WebDAV server. For a start, I managed to resolve the XP SP2/Vista/7 basic vs DIGEST authentication method hacks to not need registry editing – it turns out, by default, if the share is SSL encrypted, basic authentication should be fine. I also decided on a new approach. Using Apache, PHP5, suPHP and eZ Component’s WebDAV module, I was able to implement a sturdier WebDAV solutions that still solved the problems.

First things first, Apache, PHP5, mod_php, mod_suphp all needed to be installed and configured. Once that was done, ez Component’s WebDAV module needed to be installed – on Fedora, this is php-ezc-Webdav in the Yum repositories. Then I needed to make a couple of scripts to handle authentication and module loading. These are modified right from the ezc-Webdav documentation. These scripts need to go in Apache’s DocumentRoot.

autoload.php

<?php
require_once "/usr/share/pear/ezc/Base/base.php";

/**
 * Autoload ezc classes
 *
 * @param string $className
 */
function __autoload( $className )
{
    ezcBase::autoload( $className );
}
?>

You may need to alter the path to base.php above.

authenticator.php

<?php
class ldapAuthenticator extends ezcWebdavDigestAuthenticatorBase
                   implements ezcWebdavAuthorizer
{

    public function authenticateAnonymous( ezcWebdavAnonymousAuth $data )
    {
        return false;
    }

    public function authenticateBasic( ezcWebdavBasicAuth $data )
    {
        $username = $data->username;
        $password = $data->password;

	if(strstr($username, '\\')){
		$username = strstr($username, '\\');
		$username = preg_replace("^.", '', $username);
	}

	$ldap = ldap_connect("ldap.company.tld", 389);
	$bind = @ldap_bind($ldap);
	$search = ldap_search($ldap, "dc=company,dc=tld", "(&(objectClass=shadowAccount)(uid=".$username."))", array("dn"));
	$data = ldap_get_entries($ldap, $search);
	$dn = $data[0]['dn'];

	if(!$dn){ return false; }

	$bind = @ldap_bind($ldap, $dn, $password);
	$search = ldap_search($ldap, "dc=company,dc=tld", "(&(objectClass=shadowAccount)(uid=".$username."))", array("dn"));
	$data = ldap_get_entries($ldap, $search);

	if(!$bind){ return false; }

	return true;
    }

    public function authenticateDigest( ezcWebdavDigestAuth $data )
    {
        $username = $data->username;

	error_log("User attempted unsupported DIGEST authentication: ".$username);

	return false;
   } 

    public function authorize( $user, $path, $access = ezcWebdavAuthorizer::ACCESS_READ )
    {
        return true;
    }
}
?>

You will need to modify the authenticateBasic function. The one above is to authenticate with an LDAP backend.

sharename.php

<?php
require_once 'autoload.php';
require_once 'authenticator.php';

$server = ezcWebdavServer::getInstance();

$server->options->realm = "CCPG Solutions Ltd WebDAV";

$server->auth = new ldapAuthenticator();

$backend = new ezcWebdavFileBackend(
   '/path/to/share'
);

$server->handle( $backend );
?>

In this one, you will need to modify the share path (in $backend) and the realm.

Then you need to change the owning uid/gid (chown user:group sharename.php) of the sharename.php file to the user/group you want to use for read/write permissions of the files. You can make as many sharename.php files for each share (or combination of share/permissions) you need.

With all that done, you should be able to go ahead and map the share using the URL https://dav.company.tld/sharename.php

The eZ Component’s WebDAV module seems pretty in-depth – the above is really just a very basic usage of it’s capabilities, but it does work pretty well. The only other thing you may have to do, depending how pedantic your Windows boxes are going to be, is disable the DIGEST authentication headers altogether. To do this, edit /usr/share/pear/ezc/Webdav/servers.php (or wherever your Webdav/server.php is located) and comment the following lines in the createUnauthenticatedResponse function:

$wwwAuthHeader['digest'] = 'Digest realm="' .$this->options->realm . '"'
 . ', nonce="' . $this->getNonce() . '"'
 . ', algorithm="MD5"';

Save the file and exit. That’s all it takes. With all that done, your users should be able to map the share in Windows, authenticate via LDAP and read/write files with the permissions of the PHP script owner.

Post Revisions:

Leave a comment

You must be logged in to post a comment.