Skip to content

Commit b6433d2

Browse files
committed
made the digest with proxy work
1 parent cf5bc36 commit b6433d2

File tree

4 files changed

+135
-6
lines changed

4 files changed

+135
-6
lines changed

api/src/main/java/com/ning/http/client/ProxyServer.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,17 @@ public String toString() {
5353
private int port;
5454
private String ntlmDomain = System.getProperty("http.auth.ntlm.domain", "");
5555

56-
public ProxyServer(final Protocol protocol, final String host, final int port, String principal, String password) {
56+
private boolean isBasic = true;
57+
58+
public boolean isBasic() {
59+
return isBasic;
60+
}
61+
62+
public void setBasic(boolean isBasic) {
63+
this.isBasic = isBasic;
64+
}
65+
66+
public ProxyServer(final Protocol protocol, final String host, final int port, String principal, String password) {
5767
this.protocol = protocol;
5868
this.host = host;
5969
this.port = port;

api/src/main/java/com/ning/http/client/Realm.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,19 @@ public RealmBuilder parseWWWAuthenticateHeader(String headerLine) {
439439
return this;
440440
}
441441

442+
public RealmBuilder parseProxyAuthenticateHeader(String headerLine) {
443+
setRealmName(match(headerLine, "realm"));
444+
setNonce(match(headerLine, "nonce"));
445+
setOpaque(match(headerLine, "opaque"));
446+
setQop(match(headerLine, "qop"));
447+
if (getNonce() != null && !getNonce().equalsIgnoreCase("")) {
448+
setScheme(AuthScheme.DIGEST);
449+
} else {
450+
setScheme(AuthScheme.BASIC);
451+
}
452+
return this;
453+
}
454+
442455
public RealmBuilder setNtlmMessageType2Received(boolean messageType2Received) {
443456
this.messageType2Received = messageType2Received;
444457
return this;

api/src/main/java/com/ning/http/util/AuthenticatorUtils.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,18 @@ public static String computeDigestAuthentication(Realm realm) throws NoSuchAlgor
4949
return new String(builder.toString().getBytes("ISO_8859_1"));
5050
}
5151

52+
public static String computeDigestAuthentication(ProxyServer proxy) {
53+
try{
54+
StringBuilder builder = new StringBuilder().append("Digest ");
55+
construct(builder, "username", proxy.getPrincipal(),true);
56+
return new String(builder.toString().getBytes("ISO_8859_1"));
57+
}
58+
catch (Exception e){
59+
e.printStackTrace();
60+
}
61+
return null;
62+
}
63+
5264
private static StringBuilder construct(StringBuilder builder, String name, String value) {
5365
return construct(builder, name, value, false);
5466
}

providers/grizzly/src/main/java/com/ning/http/client/providers/grizzly/GrizzlyAsyncHttpProvider.java

Lines changed: 99 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -915,9 +915,9 @@ private boolean sendAsGrizzlyRequest(final Request request,
915915
}
916916

917917
if (proxy.getPrincipal() != null) {
918-
requestPacket.setHeader(Header.ProxyAuthorization,
919-
AuthenticatorUtils.computeBasicAuthentication(proxy));
918+
requestPacket.setHeader(Header.ProxyAuthorization, AuthenticatorUtils.computeBasicAuthentication(proxy));
920919
}
920+
921921
}
922922
}
923923
final AsyncHandler h = httpCtx.handler;
@@ -1091,6 +1091,8 @@ private static final class AsyncHttpClientEventFilter extends HttpClientFilter {
10911091
this.provider = provider;
10921092
HANDLER_MAP.put(HttpStatus.UNAUTHORIZED_401.getStatusCode(),
10931093
AuthorizationHandler.INSTANCE);
1094+
HANDLER_MAP.put(HttpStatus.PROXY_AUTHENTICATION_REQUIRED_407.getStatusCode(),
1095+
ProxyAuthorizationHandler.INSTANCE);
10941096
HANDLER_MAP.put(HttpStatus.MOVED_PERMANENTLY_301.getStatusCode(),
10951097
RedirectHandler.INSTANCE);
10961098
HANDLER_MAP.put(HttpStatus.FOUND_302.getStatusCode(),
@@ -1265,9 +1267,9 @@ protected void onHttpHeadersParsed(HttpHeader httpHeader,
12651267
ConnectionManager.markConnectionAsDoNotCache(ctx.getConnection());
12661268
}
12671269
}
1268-
final HttpTransactionContext context =
1269-
provider.getHttpTransactionContext(ctx.getConnection());
1270-
if (httpHeader.isSkipRemainder() || context.establishingTunnel) {
1270+
final HttpTransactionContext context = provider.getHttpTransactionContext(ctx.getConnection());
1271+
1272+
if (httpHeader.isSkipRemainder() || (context.establishingTunnel && context.statusHandler==null)) {
12711273
return;
12721274
}
12731275

@@ -1327,6 +1329,14 @@ protected void onHttpHeadersParsed(HttpHeader httpHeader,
13271329
}
13281330
if (context.isWSRequest) {
13291331
try {
1332+
//in case of DIGEST auth protocol handler is null and just returning here is working
1333+
if(context.protocolHandler == null)
1334+
{
1335+
return;
1336+
//context.protocolHandler = Version.DRAFT17.createHandler(true);
1337+
//context.currentState = AsyncHandler.STATE.UPGRADE;
1338+
}
1339+
13301340
context.protocolHandler.setConnection(ctx.getConnection());
13311341
DefaultWebSocket ws = new DefaultWebSocket(context.protocolHandler);
13321342
context.webSocket = new GrizzlyWebSocketAdapter(ws);
@@ -1569,6 +1579,90 @@ public boolean handleStatus(final HttpResponsePacket responsePacket,
15691579

15701580
} // END AuthorizationHandler
15711581

1582+
private static final class ProxyAuthorizationHandler implements StatusHandler {
1583+
1584+
private static final ProxyAuthorizationHandler INSTANCE =
1585+
new ProxyAuthorizationHandler();
1586+
1587+
// -------------------------------------- Methods from StatusHandler
1588+
1589+
1590+
public boolean handlesStatus(int statusCode) {
1591+
return (HttpStatus.PROXY_AUTHENTICATION_REQUIRED_407.statusMatches(statusCode));
1592+
}
1593+
1594+
@SuppressWarnings({"unchecked"})
1595+
public boolean handleStatus(final HttpResponsePacket responsePacket,
1596+
final HttpTransactionContext httpTransactionContext,
1597+
final FilterChainContext ctx) {
1598+
1599+
final String proxy_auth = responsePacket.getHeader(Header.ProxyAuthenticate);
1600+
if (proxy_auth == null) {
1601+
throw new IllegalStateException("407 response received, but no Proxy Authenticate header was present");
1602+
}
1603+
1604+
final Request req = httpTransactionContext.request;
1605+
ProxyServer proxyServer = httpTransactionContext.provider.clientConfig.getProxyServer();
1606+
String principal = proxyServer.getPrincipal();
1607+
String password = proxyServer.getPassword();
1608+
Realm realm = new Realm.RealmBuilder().setPrincipal(principal)
1609+
.setPassword(password)
1610+
.setUri("/")
1611+
.setMethodName("CONNECT")
1612+
.setUsePreemptiveAuth(true)
1613+
.parseProxyAuthenticateHeader(proxy_auth)
1614+
.build();
1615+
if (proxy_auth.toLowerCase().startsWith("basic")) {
1616+
req.getHeaders().remove(Header.ProxyAuthenticate.toString());
1617+
req.getHeaders().remove(Header.ProxyAuthorization.toString());
1618+
try {
1619+
req.getHeaders().add(Header.ProxyAuthorization.toString(),
1620+
AuthenticatorUtils.computeBasicAuthentication(realm));
1621+
} catch (UnsupportedEncodingException ignored) {
1622+
}
1623+
} else if (proxy_auth.toLowerCase().startsWith("digest")) {
1624+
req.getHeaders().remove(Header.ProxyAuthenticate.toString());
1625+
req.getHeaders().remove(Header.ProxyAuthorization.toString());
1626+
try {
1627+
req.getHeaders().add(Header.ProxyAuthorization.toString(),
1628+
AuthenticatorUtils.computeDigestAuthentication(realm));
1629+
} catch (NoSuchAlgorithmException e) {
1630+
throw new IllegalStateException("Digest authentication not supported", e);
1631+
} catch (UnsupportedEncodingException e) {
1632+
throw new IllegalStateException("Unsupported encoding.", e);
1633+
}
1634+
} else {
1635+
throw new IllegalStateException("Unsupported authorization method: " + proxy_auth);
1636+
}
1637+
1638+
final ConnectionManager m = httpTransactionContext.provider.connectionManager;
1639+
try {
1640+
final Connection c = m.obtainConnection(req,
1641+
httpTransactionContext.future);
1642+
final HttpTransactionContext newContext =
1643+
httpTransactionContext.copy();
1644+
httpTransactionContext.future = null;
1645+
httpTransactionContext.provider.setHttpTransactionContext(c, newContext);
1646+
newContext.invocationStatus = InvocationStatus.STOP;
1647+
try {
1648+
httpTransactionContext.provider.execute(c,
1649+
req,
1650+
httpTransactionContext.handler,
1651+
httpTransactionContext.future);
1652+
return false;
1653+
} catch (IOException ioe) {
1654+
newContext.abort(ioe);
1655+
return false;
1656+
}
1657+
} catch (Exception e) {
1658+
httpTransactionContext.abort(e);
1659+
}
1660+
httpTransactionContext.invocationStatus = InvocationStatus.STOP;
1661+
return false;
1662+
}
1663+
1664+
} // END AuthorizationHandler
1665+
15721666

15731667
private static final class RedirectHandler implements StatusHandler {
15741668

0 commit comments

Comments
 (0)