Commit ddef40ac authored by Ricki Hirner's avatar Ricki Hirner

Fix WWW-Authenticate parsing; add DAV:principal resource type

* WWW-Authenticate parsing: fix bug with quoted spaces in first parameter after auth scheme name
* DAV: add PRINCIPAL resource type
* Digest auth: don't require opaque parameter
parent adb19e52
......@@ -209,9 +209,6 @@ public class BasicDigestAuthenticatorTest extends TestCase {
assertNull(authenticator.authorizationRequest(original, authScheme));
authScheme.params.put("nonce", "56212407212c8");
assertNull(authenticator.authorizationRequest(original, authScheme));
authScheme.params.put("opaque", "df58bdff8cf60599c939187d0b5c54de");
assertNotNull(authenticator.authorizationRequest(original, authScheme));
}
......
......@@ -125,6 +125,16 @@ public class HttpUtilsTest extends TestCase {
assertEquals(1, scheme.params.size());
assertEquals("Newcastle", scheme.params.get("realm"));
assertEquals(0, scheme.unnamedParams.size());
// Contacts and Calendar Server example; space in second token!
schemes = HttpUtils.parseWwwAuthenticate(new String[]{ "digest nonce=\"785592012006934833760823299624355448128925071071026584347\", realm=\"Test Realm\", algorithm=\"md5\"" });
assertEquals(1, schemes.size());
scheme = schemes.get(0);
assertEquals("digest", scheme.name);
assertEquals(3, scheme.params.size());
assertEquals("785592012006934833760823299624355448128925071071026584347", scheme.params.get("nonce"));
assertEquals("Test Realm", scheme.params.get("realm"));
assertEquals("md5", scheme.params.get("algorithm"));
}
}
......@@ -81,6 +81,8 @@ public class BasicDigestAuthenticator implements Authenticator {
if (triedBefore && !"true".equalsIgnoreCase(digestAuth.params.get("stale")))
// credentials didn't work last time, and they won't work now -> stop here
return null;
Constants.log.debug("Adding Digest authorization request for {}", request.httpUrl());
return authorizationRequest(request, digestAuth);
} else if (basicAuth != null) {
......@@ -88,10 +90,12 @@ public class BasicDigestAuthenticator implements Authenticator {
if (triedBefore) // credentials didn't work last time, and they won't work now -> stop here
return null;
Constants.log.debug("Adding Basic authorization header for {}", request.httpUrl());
return request.newBuilder()
.header(HEADER_AUTHORIZATION, Credentials.basic(username, password))
.build();
}
} else
Constants.log.error("No supported authentication scheme");
// no supported auth scheme
return null;
......@@ -126,8 +130,6 @@ public class BasicDigestAuthenticator implements Authenticator {
return null;
if (opaque != null)
params.add("opaque=" + quotedString(opaque));
else
return null;
if (algorithm != null)
params.add("algorithm=" + quotedString(algorithm.name));
......@@ -149,7 +151,7 @@ public class BasicDigestAuthenticator implements Authenticator {
a1 = username + ":" + realm + ":" + password;
else if (algorithm == Algorithm.MD5_SESSION)
a1 = h(username + ":" + realm + ":" + password) + ":" + nonce + ":" + clientNonce;
//Constants.log.trace("A1=" + a1);
Constants.log.trace("A1=" + a1);
String a2 = null;
if (qop == Protection.Auth)
......@@ -161,13 +163,13 @@ public class BasicDigestAuthenticator implements Authenticator {
} catch(IOException e) {
Constants.log.warn("Couldn't get entity-body for hash calculation");
}
//Constants.log.trace("A2=" + a2);
Constants.log.trace("A2=" + a2);
if (a1 != null && a2 != null)
response = kd(h(a1), nonce + ":" + ncValue + ":" + clientNonce + ":" + qop.name + ":" + h(a2));
} else {
//Constants.log.debug("Using legacy Digest auth");
Constants.log.trace("Using legacy Digest auth");
// legacy (backwards compatibility with RFC 2069)
if (algorithm == Algorithm.MD5) {
......
......@@ -19,7 +19,7 @@ import lombok.RequiredArgsConstructor;
public class HttpUtils {
private static final Pattern authSchemeWithParam = Pattern.compile("^([^ ]+) +(.*)$");
private static final Pattern authSchemeWithParam = Pattern.compile("^([^ \"]+) +(.*)$");
public static List<AuthScheme> parseWwwAuthenticate(String[] wwwAuths) {
......@@ -100,9 +100,9 @@ public class HttpUtils {
}
}
/*Constants.log.trace("Server authentication schemes: ");
Constants.log.trace("Server authentication schemes: ");
for (AuthScheme scheme : schemes)
Constants.log.trace(" - " + scheme);*/
Constants.log.trace(" - " + scheme);
return schemes;
}
......
......@@ -20,9 +20,10 @@ public class ResourceType implements Property {
public static final Name NAME = new Name(XmlUtils.NS_WEBDAV, "resourcetype");
public static final Name
COLLECTION = new Name(XmlUtils.NS_WEBDAV, "collection"),
ADDRESSBOOK = new Name(XmlUtils.NS_CARDDAV, "addressbook"),
CALENDAR = new Name(XmlUtils.NS_CALDAV, "calendar");
COLLECTION = new Name(XmlUtils.NS_WEBDAV, "collection"), // WebDAV
PRINCIPAL = new Name(XmlUtils.NS_WEBDAV, "principal"), // WebDAV ACL
ADDRESSBOOK = new Name(XmlUtils.NS_CARDDAV, "addressbook"), // CardDAV
CALENDAR = new Name(XmlUtils.NS_CALDAV, "calendar"); // CalDAV
public final Set<Property.Name> types = new HashSet<>();
......@@ -49,6 +50,8 @@ public class ResourceType implements Property {
Name typeName = new Name(parser.getNamespace(), parser.getName());
if (COLLECTION.equals(typeName))
typeName = COLLECTION;
else if (PRINCIPAL.equals(typeName))
typeName = PRINCIPAL;
else if (ADDRESSBOOK.equals(typeName))
typeName = ADDRESSBOOK;
else if (CALENDAR.equals(typeName))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment