Skip to content

Commit 60b85cb

Browse files
committed
making the proxy work with kerberos (grizzly provider)
1 parent ba1a0a4 commit 60b85cb

File tree

3 files changed

+113
-34
lines changed

3 files changed

+113
-34
lines changed

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

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

56-
private boolean isBasic = true;
56+
/*private boolean isBasic = true;
5757
5858
public boolean isBasic() {
5959
return isBasic;
6060
}
6161
6262
public void setBasic(boolean isBasic) {
6363
this.isBasic = isBasic;
64-
}
64+
}*/
6565

6666
public ProxyServer(final Protocol protocol, final String host, final int port, String principal, String password) {
6767
this.protocol = protocol;
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.ning.http.client.providers.grizzly;
2+
3+
import org.ietf.jgss.GSSContext;
4+
import org.ietf.jgss.GSSException;
5+
import org.ietf.jgss.GSSManager;
6+
import org.ietf.jgss.GSSName;
7+
import org.ietf.jgss.Oid;
8+
9+
import com.ning.http.util.Base64;
10+
11+
public class GSSSPNEGOWrapper {
12+
13+
private static final String KERBEROS_OID = "1.2.840.113554.1.2.2";
14+
15+
static GSSManager getManager() {
16+
return GSSManager.getInstance();
17+
}
18+
19+
static byte[] generateGSSToken(
20+
final byte[] input, final Oid oid, final String authServer) throws GSSException {
21+
byte[] token = input;
22+
if (token == null) {
23+
token = new byte[0];
24+
}
25+
GSSManager manager = getManager();
26+
GSSName serverName = manager.createName("HTTP@" + authServer, GSSName.NT_HOSTBASED_SERVICE);
27+
GSSContext gssContext = manager.createContext(
28+
serverName.canonicalize(oid), oid, null, GSSContext.DEFAULT_LIFETIME);
29+
gssContext.requestMutualAuth(true);
30+
gssContext.requestCredDeleg(true);
31+
return gssContext.initSecContext(token, 0, token.length);
32+
}
33+
34+
public static String generateToken(String authServer)
35+
{
36+
String returnVal = "";
37+
Oid oid;
38+
try {
39+
oid = new Oid(KERBEROS_OID);
40+
byte[] token = GSSSPNEGOWrapper.generateGSSToken(null, oid, authServer);
41+
returnVal = new String(Base64.encode(token));
42+
} catch (GSSException e) {
43+
// TODO Auto-generated catch block
44+
e.printStackTrace();
45+
}
46+
47+
return returnVal;
48+
}
49+
}

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

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ public class GrizzlyAsyncHttpProvider implements AsyncHttpProvider {
168168

169169
private final static NTLMEngine ntlmEngine = new NTLMEngine();
170170

171-
172171
// ------------------------------------------------------------ Constructors
173172

174173

@@ -916,12 +915,16 @@ private boolean sendAsGrizzlyRequest(final Request request,
916915
requestPacket.setHeader(Header.ProxyConnection, "keep-alive");
917916
}
918917

919-
if(proxy.getNtlmDomain() != null && proxy.getNtlmDomain().length() > 0)
918+
if(null == requestPacket.getHeader(Header.ProxyAuthorization) )
919+
{
920+
requestPacket.setHeader(Header.ProxyAuthorization, AuthenticatorUtils.computeBasicAuthentication(proxy));
921+
}
922+
/*if(proxy.getNtlmDomain() != null && proxy.getNtlmDomain().length() > 0)
920923
{
921924
LOGGER.debug("probably ntlm.. not adding header..");
922925
}else if (proxy.getPrincipal() != null && proxy.isBasic()) {
923926
requestPacket.setHeader(Header.ProxyAuthorization, AuthenticatorUtils.computeBasicAuthentication(proxy));
924-
}
927+
}*/
925928

926929
}
927930
}
@@ -1393,7 +1396,7 @@ protected boolean onHttpPacketParsed(HttpHeader httpHeader, FilterChainContext c
13931396
final String proxy_auth = httpHeader.getHeader(Header.ProxyAuthenticate);
13941397

13951398
if (httpHeader.isSkipRemainder() ) {
1396-
if(!ProxyAuthorizationHandler.isSecondHandShake(proxy_auth))
1399+
if(!ProxyAuthorizationHandler.isNTLMSecondHandShake(proxy_auth))
13971400
{
13981401
clearResponse(ctx.getConnection());
13991402
cleanup(ctx, provider);
@@ -1653,7 +1656,7 @@ public boolean handleStatus(final HttpResponsePacket responsePacket,
16531656
String msg = null;
16541657
try {
16551658

1656-
if(isFirstHandShake(proxy_auth))
1659+
if(isNTLMFirstHandShake(proxy_auth))
16571660
{
16581661
msg = ntlmEngine.generateType1Msg(proxyServer.getNtlmDomain(), "");
16591662
}else {
@@ -1665,21 +1668,46 @@ public boolean handleStatus(final HttpResponsePacket responsePacket,
16651668
} catch (Exception e1) {
16661669
e1.printStackTrace();
16671670
}
1668-
} else {
1671+
} else if (proxy_auth.toLowerCase().startsWith("negotiate")){
1672+
//this is for kerberos
1673+
req.getHeaders().remove(Header.ProxyAuthenticate.toString());
1674+
req.getHeaders().remove(Header.ProxyAuthorization.toString());
1675+
1676+
}else {
16691677
throw new IllegalStateException("Unsupported authorization method: " + proxy_auth);
16701678
}
16711679

16721680
final ConnectionManager m = httpTransactionContext.provider.connectionManager;
16731681
InvocationStatus tempInvocationStatus = InvocationStatus.STOP;
16741682

16751683
try {
1676-
if(isFirstHandShake(proxy_auth))
1684+
1685+
if(isNTLMFirstHandShake(proxy_auth))
16771686
{
16781687
tempInvocationStatus = InvocationStatus.CONTINUE;
16791688

16801689
}
16811690

1682-
if(isSecondHandShake(proxy_auth))
1691+
if(proxy_auth.toLowerCase().startsWith("negotiate"))
1692+
{
1693+
final Connection c = m.obtainConnection(req, httpTransactionContext.future);
1694+
final HttpTransactionContext newContext = httpTransactionContext.copy();
1695+
httpTransactionContext.future = null;
1696+
httpTransactionContext.provider.setHttpTransactionContext(c, newContext);
1697+
1698+
newContext.invocationStatus = tempInvocationStatus;
1699+
1700+
String challengeHeader = null;
1701+
String server = proxyServer.getHost();
1702+
1703+
challengeHeader = GSSSPNEGOWrapper.generateToken(server);
1704+
1705+
req.getHeaders().add(Header.ProxyAuthorization.toString(), "Negotiate " + challengeHeader);
1706+
1707+
1708+
return exceuteRequest(httpTransactionContext, req, c,
1709+
newContext);
1710+
}else if(isNTLMSecondHandShake(proxy_auth))
16831711
{
16841712
final Connection c = ctx.getConnection();
16851713
final HttpTransactionContext newContext = httpTransactionContext.copy(); //httpTransactionContext.copy();
@@ -1690,17 +1718,8 @@ public boolean handleStatus(final HttpResponsePacket responsePacket,
16901718
newContext.invocationStatus = tempInvocationStatus;
16911719
httpTransactionContext.establishingTunnel = true;
16921720

1693-
try {
1694-
httpTransactionContext.provider.execute(c,
1695-
req,
1696-
httpTransactionContext.handler,
1697-
httpTransactionContext.future);
1698-
return false;
1699-
} catch (IOException ioe) {
1700-
ioe.printStackTrace();
1701-
newContext.abort(ioe);
1702-
return false;
1703-
}
1721+
return exceuteRequest(httpTransactionContext, req, c,
1722+
newContext);
17041723

17051724
}
17061725
else{
@@ -1711,28 +1730,39 @@ public boolean handleStatus(final HttpResponsePacket responsePacket,
17111730

17121731
newContext.invocationStatus = tempInvocationStatus;
17131732

1714-
try {
1715-
httpTransactionContext.provider.execute(c,
1716-
req,
1717-
httpTransactionContext.handler,
1718-
httpTransactionContext.future);
1719-
return false;
1720-
} catch (IOException ioe) {
1721-
newContext.abort(ioe);
1722-
return false;
1723-
}
1733+
return exceuteRequest(httpTransactionContext, req, c,
1734+
newContext);
17241735
}
17251736
} catch (Exception e) {
17261737
httpTransactionContext.abort(e);
1727-
}
1738+
} catch (Throwable e) {
1739+
e.printStackTrace();
1740+
httpTransactionContext.abort(e);
1741+
}
17281742
httpTransactionContext.invocationStatus = tempInvocationStatus;
17291743
return false;
17301744
}
17311745

1732-
public static boolean isSecondHandShake(final String proxy_auth) {
1746+
private boolean exceuteRequest(
1747+
final HttpTransactionContext httpTransactionContext,
1748+
final Request req, final Connection c,
1749+
final HttpTransactionContext newContext) {
1750+
try {
1751+
httpTransactionContext.provider.execute(c,
1752+
req,
1753+
httpTransactionContext.handler,
1754+
httpTransactionContext.future);
1755+
return false;
1756+
} catch (IOException ioe) {
1757+
newContext.abort(ioe);
1758+
return false;
1759+
}
1760+
}
1761+
1762+
public static boolean isNTLMSecondHandShake(final String proxy_auth) {
17331763
return (proxy_auth.toLowerCase().startsWith("ntlm") && !proxy_auth.equalsIgnoreCase("ntlm"));
17341764
}
1735-
public static boolean isFirstHandShake(final String proxy_auth) {
1765+
public static boolean isNTLMFirstHandShake(final String proxy_auth) {
17361766
return (proxy_auth.equalsIgnoreCase("ntlm"));
17371767
}
17381768

0 commit comments

Comments
 (0)