Blog

Like many, Armedia has customers who are upgrading their desktop computing environments from Windows XP to Windows 7 (Did anyone use Vista?). We recently ran into an interesting situation with one such customer who was using a customized WebDAV solution to allow users to quickly retrieve and edit documents from a back-end content management system. Their WebDAV solution had worked flawlessly for years with Windows XP, but with Windows 7, two really annoying problems cropped up. The first was that the user was prompted to authenticate with the WebDAV server three times. The second problem was that even after authentication (3x), documents were always retrieved in read-only mode and could not be saved back to the repository. Thus started the adventure to make WebDAV work with Windows 7.

After searching Google and other sources, two things became apparent:

  • lots of people were having issues with WebDAV and Windows 7
  • no one was using WebDAV quite the way we were.

Let me start with some background. Our customer accessed content (mostly Microsoft Office documents) by clicking on a link on a custom web page. The link opened the document in its native editor. When the user was done editing, simply closing the editor automatically saved the updated document back to the repository. Architecturally, the setup looks like this: IIS fronts the system such that Windows authentication passes through to WebDAV. IIS is running the Jakarta Slide WebDAV ISAPI filter (yes, this Apache project is retired). The Jakarta WebDAV servlet is running in Tomcat. The stock Jakarta WebDAV servlet was extended to include modifications to interface with the back-end content management system (in this case Documentum). Fortunately, none of the problems we experienced were due to this customized code.

Our conclusion is that Windows 7 adheres to the WebDAV specification (RFC 4918) much more strictly than Windows XP did. In summary, here are the modifications we made to get WebDAV to work with Windows 7 and Microsoft Office 2007.

  1. Configure the IIS server to support Digest Authentication. Previously, IIS was configured to work with Basic Authentication (Windows credentials passed in clear text). Windows 7 does not support Basic Authentication. To enable Digest Authentication in IIS:
    • right-click on the Default Website in IIS Manager and pull up the site’s properties page.
    • click the “Directory Security” tab, and then the Edit button in the “Authentication and access control” panel.
    • turn “Enable anonymous access” OFF (unchecked)
    • turn “Integrated Windows authentication” ON (checked)
    • turn “Digest authentication for Windows domain servers” ON (checked)
    • turn “Basic authentication (password is sent in clear text)” OFF (unchecked)

 

  1. Update each workstation’s Registry to pass Digest Authentication credentials to fully qualified domain (FQDN) hosts who request them. The Registry requires an additional key to be added to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WebClient\Parameters. The Microsoft KB 943280 article describes this process. Restart the client workstation.

 

  1. Make sure you are using the latest Jakarta WebDAV servlet code. At the time of this writing, version 1359670 is the latest, and can be found here: https://svn.apache.org/repos/asf/tomcat/tc7.0.x/trunk/ java/org/apache/catalina/servlets/WebdavServlet.java. This link, https://issues.apache.org/bugzilla/show_bug.cgi?id=49428, explains the revisions that were made to the servlet to address some of the Windows 7 problems. One key change that we discovered that was not addressed by Apache, resides in the PROPPATCH method. After days of tracing the conversation between clients and the WebDAV servlet, we discovered that PROPPATCH should be returning a multistatus response instead of the default “501 – Not Implemented”. We added a multistatus response to the PROPPATCH method and this seems to have solved the problem.  Our doProppatch() method (which implements the WebDAV PROPPATCHmethod) now looks like this:
[sourcecode language="ccs"]
 protected void doProppatch(HttpServletRequest req,HttpServletResponse resp) throws ServletException, IOException {
if (readOnly) {
 resp.sendError(WebdavStatus.SC_FORBIDDEN);
 return;
 }
if (isLocked(req)) {
 resp.sendError(WebdavStatus.SC_LOCKED);
 return;
 }
/**
 * do not return default response
 */
 //resp.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED);
/**
 * ========== ALL NEW CODE ==========
 * create multi-status response for three basic windows properties:
 * Win32CreationTime, Win32LastAccessTime, Win32LastModifiedTime
 */
XMLWriter generatedXML = new XMLWriter();
 generatedXML.writeXMLHeader();
generatedXML.writeElement("D", DEFAULT_NAMESPACE,"multistatus", XMLWriter.OPENING);
 generatedXML.writeElement("D", "response",XMLWriter.OPENING);
 generatedXML.writeElement("D", "href",XMLWriter.OPENING);
 generatedXML.writeText(req.getRequestURI());
 generatedXML.writeElement("D", "href",XMLWriter.CLOSING);
 generatedXML.writeElement("D", "propstat",XMLWriter.OPENING);
 generatedXML.writeElement("D", "status",XMLWriter.OPENING);
 generatedXML.writeText("HTTP/1.1 " + WebdavStatus.SC_FAILED_DEPENDENCY + " " +
 WebdavStatus.getStatusText(WebdavStatus.SC_FAILED_DEPENDENCY));
 generatedXML.writeElement("D", "status",XMLWriter.CLOSING);
 generatedXML.writeElement("D", "prop",XMLWriter.OPENING);
 generatedXML.writeText ("><n3:Win32CreationTime/><n3:Win32LastAccessTime/><n3:Win32LastModifiedTime/>");
 generatedXML.writeElement("D", "prop",XMLWriter.CLOSING);
 generatedXML.writeElement("D", "propstat",XMLWriter.CLOSING);
 generatedXML.writeElement("D", "response",XMLWriter.CLOSING);
 generatedXML.writeElement("D", "multistatus",XMLWriter.CLOSING);
Writer writer = resp.getWriter();
 writer.write(generatedXML.toString());
 writer.close();
 }
 [/sourcecode]

One caveat about this code: It works for us; your mileage may vary. It is not yet clear to me whether the content of the multistatus response is ever evaluated, or if its content is predicated on the content of another method. It seems that it just has to exist!

  1. In the ../webdav/WEB_INF/web.xml, make sure the listings parameter is set to true.

    <init-param>
    <param-name>listings</param-name>
    <param-value>true</param-value>
    </init-param>

As I stated earlier: this solution works for us; applicability to your situation may vary. Hopefully, even if this solution isn’t an exact fit for your situation, it gives you some ideas and places to begin searching for a solution.

Useful links:

Categories

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *