Browse Source

Adds support for SPNEGO

Adds support for Negotiate(SPNEGO) HTTP authentication method. This method
is set to have a higher priority as Digest HTTP authentication method.

Bug: 428836
Change-Id: Ib181096d39f538df1dd7d3f36516843777bf12ae
Signed-off-by: Laurent Goujon <lgoujon@twitter.com>
Signed-off-by: Chris Aniszczyk <caniszczyk@gmail.com>
stable-3.4
Laurent Goujon 11 years ago committed by Chris Aniszczyk
parent
commit
4cb0bd8a43
  1. 9
      org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/HttpAuthTest.java
  2. 63
      org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java

9
org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/HttpAuthTest.java

@ -64,22 +64,31 @@ public class HttpAuthTest {
private static String bearerHeader = "WWW-Authenticate: Bearer"; private static String bearerHeader = "WWW-Authenticate: Bearer";
private static String negotiateHeader = "WWW-Authenticate: Negotiate";
private static String URL_SAMPLE = "http://everyones.loves.git/u/2"; private static String URL_SAMPLE = "http://everyones.loves.git/u/2";
private static String BASIC = "Basic"; private static String BASIC = "Basic";
private static String DIGEST = "Digest"; private static String DIGEST = "Digest";
private static String NEGOTIATE = "Negotiate";
@Test @Test
public void testHttpAuthScanResponse() { public void testHttpAuthScanResponse() {
checkResponse(new String[] { basicHeader }, BASIC); checkResponse(new String[] { basicHeader }, BASIC);
checkResponse(new String[] { digestHeader }, DIGEST); checkResponse(new String[] { digestHeader }, DIGEST);
checkResponse(new String[] { negotiateHeader }, NEGOTIATE);
checkResponse(new String[] { basicHeader, digestHeader }, DIGEST); checkResponse(new String[] { basicHeader, digestHeader }, DIGEST);
checkResponse(new String[] { digestHeader, basicHeader }, DIGEST); checkResponse(new String[] { digestHeader, basicHeader }, DIGEST);
checkResponse(new String[] { digestHeader, negotiateHeader }, NEGOTIATE);
checkResponse(new String[] { negotiateHeader, digestHeader }, NEGOTIATE);
checkResponse(new String[] { ntlmHeader, basicHeader, digestHeader, checkResponse(new String[] { ntlmHeader, basicHeader, digestHeader,
bearerHeader }, DIGEST); bearerHeader }, DIGEST);
checkResponse(new String[] { ntlmHeader, basicHeader, bearerHeader }, checkResponse(new String[] { ntlmHeader, basicHeader, bearerHeader },
BASIC); BASIC);
checkResponse(new String[] { ntlmHeader, basicHeader, digestHeader,
negotiateHeader, bearerHeader }, NEGOTIATE);
} }
private static void checkResponse(String[] headers, private static void checkResponse(String[] headers,

63
org.eclipse.jgit/src/org/eclipse/jgit/transport/HttpAuthMethod.java

@ -61,6 +61,12 @@ import java.util.Random;
import org.eclipse.jgit.transport.http.HttpConnection; import org.eclipse.jgit.transport.http.HttpConnection;
import org.eclipse.jgit.util.Base64; import org.eclipse.jgit.util.Base64;
import org.eclipse.jgit.util.GSSManagerFactory;
import org.ietf.jgss.GSSContext;
import org.ietf.jgss.GSSException;
import org.ietf.jgss.GSSManager;
import org.ietf.jgss.GSSName;
import org.ietf.jgss.Oid;
/** /**
* Support class to populate user authentication data on a connection. * Support class to populate user authentication data on a connection.
@ -91,6 +97,12 @@ abstract class HttpAuthMethod {
public HttpAuthMethod method(String hdr) { public HttpAuthMethod method(String hdr) {
return new Digest(hdr); return new Digest(hdr);
} }
},
NEGOTIATE {
@Override
public HttpAuthMethod method(String hdr) {
return new Negotiate(hdr);
}
}; };
/** /**
* Creates a HttpAuthMethod instance configured with the provided HTTP * Creates a HttpAuthMethod instance configured with the provided HTTP
@ -458,4 +470,55 @@ abstract class HttpAuthMethod {
return p; return p;
} }
} }
private static class Negotiate extends HttpAuthMethod {
private static final GSSManagerFactory GSS_MANAGER_FACTORY = GSSManagerFactory
.detect();
private static final Oid OID;
static {
try {
// OID for SPNEGO
OID = new Oid("1.3.6.1.5.5.2"); //$NON-NLS-1$
} catch (GSSException e) {
throw new Error("Cannot create NEGOTIATE oid.", e); //$NON-NLS-1$
}
}
private final byte[] prevToken;
public Negotiate(String hdr) {
super(Type.NEGOTIATE);
prevToken = Base64.decode(hdr);
}
@Override
void authorize(String user, String pass) {
// not used
}
@Override
void configureRequest(HttpConnection conn) throws IOException {
GSSManager gssManager = GSS_MANAGER_FACTORY.newInstance(conn
.getURL());
String host = conn.getURL().getHost();
String peerName = "HTTP@" + host.toLowerCase(); //$NON-NLS-1$
try {
GSSName gssName = gssManager.createName(peerName,
GSSName.NT_HOSTBASED_SERVICE);
GSSContext context = gssManager.createContext(gssName, OID,
null, GSSContext.DEFAULT_LIFETIME);
// Respect delegation policy in HTTP/SPNEGO.
context.requestCredDeleg(true);
byte[] token = context.initSecContext(prevToken, 0,
prevToken.length);
conn.setRequestProperty(HDR_AUTHORIZATION, getType().name()
+ " " + Base64.encodeBytes(token)); //$NON-NLS-1$
} catch (GSSException e) {
throw new IOException(e);
}
}
}
} }

Loading…
Cancel
Save