Index: httpclient/pom.xml
===================================================================
--- httpclient/pom.xml (revision 1517999)
+++ httpclient/pom.xml (working copy)
@@ -57,6 +57,16 @@
compile
+ net.java.dev.jna
+ jna
+ compile
+
+
+ net.java.dev.jna
+ jna-platform
+ compile
+
+
junit
junit
test
Index: httpclient/src/main/java/org/apache/http/impl/auth/CurrentUserCredentials.java
===================================================================
--- httpclient/src/main/java/org/apache/http/impl/auth/CurrentUserCredentials.java (revision 0)
+++ httpclient/src/main/java/org/apache/http/impl/auth/CurrentUserCredentials.java (working copy)
@@ -0,0 +1,108 @@
+/*
+ * ====================================================================
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import java.io.Serializable;
+import java.security.Principal;
+
+import org.apache.http.annotation.Immutable;
+import org.apache.http.auth.Credentials;
+
+import com.sun.jna.platform.win32.Secur32Util;
+import com.sun.jna.platform.win32.Secur32.EXTENDED_NAME_FORMAT;
+
+
+/**
+ * Returns the current user credentials
+ */
+@Immutable
+public class CurrentUserCredentials implements Credentials, Serializable, Principal {
+
+ private static final long serialVersionUID = 4361166468529298169L;
+
+ /**
+ * Get the SAM-compatible username of the currently logged-on user.
+ *
+ * @return String.
+ */
+ public static String getCurrentUsername() {
+ return Secur32Util.getUserNameEx(EXTENDED_NAME_FORMAT.NameSamCompatible);
+ }
+
+ /**
+ * The constructor with the fully qualified username and password combined
+ * string argument.
+ *
+ * @param usernamePassword the domain/username:password formed string
+ */
+ private CurrentUserCredentials() {
+
+ }
+
+ // singleton
+ private static CurrentUserCredentials INSTANCE = null;
+ public static synchronized CurrentUserCredentials get() {
+ if(INSTANCE==null) {
+ INSTANCE = new CurrentUserCredentials();
+ }
+ return INSTANCE;
+ }
+
+ public Principal getUserPrincipal() {
+ return this;
+ }
+
+ @Override
+ public int hashCode() {
+ return 245678; // always the same?
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o instanceof CurrentUserCredentials) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return getCurrentUsername();
+ }
+
+ /**
+ * Returns an empty password
+ */
+ public String getPassword() {
+ return "";
+ }
+
+ public String getName() {
+ return getCurrentUsername();
+ }
+}
Property changes on: httpclient/src/main/java/org/apache/http/impl/auth/CurrentUserCredentials.java
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: httpclient/src/main/java/org/apache/http/impl/auth/WindowsNTLMSchemeFactory.java
===================================================================
--- httpclient/src/main/java/org/apache/http/impl/auth/WindowsNTLMSchemeFactory.java (revision 0)
+++ httpclient/src/main/java/org/apache/http/impl/auth/WindowsNTLMSchemeFactory.java (working copy)
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import org.apache.http.annotation.Immutable;
+import org.apache.http.auth.*;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * {@link AuthSchemeProvider} implementation that creates and initializes
+ * {@link WindowsNegotiateScheme} using JNA to implement NTLM
+ *
+ * @since 4.3
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class WindowsNTLMSchemeFactory implements AuthSchemeFactory, AuthSchemeProvider {
+
+ public static final String SCHEME = "NTLM";
+
+ public AuthScheme newInstance(final HttpParams params) {
+ return new WindowsNegotiateScheme(SCHEME);
+ }
+
+ public AuthScheme create(final HttpContext context) {
+ return new WindowsNegotiateScheme(SCHEME);
+ }
+}
Property changes on: httpclient/src/main/java/org/apache/http/impl/auth/WindowsNTLMSchemeFactory.java
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: httpclient/src/main/java/org/apache/http/impl/auth/WindowsNegotiateScheme.java
===================================================================
--- httpclient/src/main/java/org/apache/http/impl/auth/WindowsNegotiateScheme.java (revision 0)
+++ httpclient/src/main/java/org/apache/http/impl/auth/WindowsNegotiateScheme.java (working copy)
@@ -0,0 +1,252 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+package org.apache.http.impl.auth;
+
+import java.util.Locale;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.http.Header;
+import org.apache.http.HttpRequest;
+import org.apache.http.annotation.NotThreadSafe;
+import org.apache.http.auth.AUTH;
+import org.apache.http.auth.AuthenticationException;
+import org.apache.http.auth.Credentials;
+import org.apache.http.auth.InvalidCredentialsException;
+import org.apache.http.auth.MalformedChallengeException;
+import org.apache.http.impl.auth.AuthSchemeBase;
+import org.apache.http.message.BufferedHeader;
+import org.apache.http.util.CharArrayBuffer;
+
+
+import com.sun.jna.platform.win32.Secur32;
+import com.sun.jna.platform.win32.Sspi.CredHandle;
+import com.sun.jna.platform.win32.Sspi.CtxtHandle;
+import com.sun.jna.platform.win32.Sspi.SecBufferDesc;
+import com.sun.jna.platform.win32.Sspi.TimeStamp;
+import com.sun.jna.platform.win32.Sspi;
+import com.sun.jna.platform.win32.Win32Exception;
+import com.sun.jna.platform.win32.WinError;
+import com.sun.jna.ptr.IntByReference;
+
+
+/**
+ * Use JNA to implement Negotiate & NTLM
+ *
+ * This will delegate negotiation to the windows machine.
+ */
+@NotThreadSafe
+public class WindowsNegotiateScheme extends AuthSchemeBase {
+
+ public static boolean isAvaliable() {
+ String os = System.getProperty("os.name").toLowerCase(Locale.ROOT);
+ if(os.indexOf("windows")>=0) {
+ try {
+ return Sspi.MAX_TOKEN_SIZE > 0;
+ }
+ catch(Throwable t) { // Likely ClassNotFound
+ return false;
+ }
+ }
+ return false;
+ }
+
+ // NTLM or Negotiate
+ private final String scheme;
+
+ private CredHandle clientCred = null;
+ private CtxtHandle context = null;
+ private boolean continueNeeded = true;
+ private String challenge;
+
+ public WindowsNegotiateScheme(String scheme) {
+ super();
+
+ if(scheme==null) {
+ scheme = WindowsNegotiateSchemeFactory.SCHEME;
+ }
+ this.scheme = scheme;
+ this.challenge = null;
+ }
+
+ public void dispose() {
+ if (clientCred != null && !clientCred.isNull()) {
+ int rc = Secur32.INSTANCE.FreeCredentialsHandle(clientCred);
+ if (WinError.SEC_E_OK != rc) {
+ throw new Win32Exception(rc);
+ }
+ }
+ if (context != null && !context.isNull()) {
+ int rc = Secur32.INSTANCE.DeleteSecurityContext(context);
+ if (WinError.SEC_E_OK != rc) {
+ throw new Win32Exception(rc);
+ }
+ }
+ continueNeeded = true; // waiting
+ clientCred = null;
+ context = null;
+ }
+
+ @Override
+ public void finalize() {
+ dispose();
+ }
+
+ public String getSchemeName() {
+ return scheme;
+ }
+
+ // String parameters not supported
+ public String getParameter(final String name) {
+ return null;
+ }
+
+ // NTLM/Negotiate do not support authentication realms
+ public String getRealm() {
+ return null;
+ }
+
+ public boolean isConnectionBased() {
+ return true;
+ }
+
+
+ @Override
+ protected void parseChallenge(
+ final CharArrayBuffer buffer,
+ final int beginIndex,
+ final int endIndex) throws MalformedChallengeException {
+ this.challenge = buffer.substringTrimmed(beginIndex, endIndex);
+
+ if (this.challenge.length() == 0) {
+ if(clientCred==null) {
+ // OK
+ }
+ else {
+ if(continueNeeded) {
+ throw new RuntimeException("Unexpected token");
+ }
+ dispose();
+ }
+ }
+ }
+
+ public Header authenticate(
+ final Credentials credentials,
+ final HttpRequest request) throws AuthenticationException {
+
+ String response = null;
+ if(clientCred==null) {
+ // ?? We don't use the credentials, should we allow anything?
+ if(!(credentials instanceof CurrentUserCredentials)) {
+ throw new InvalidCredentialsException(
+ "Credentials cannot be used for "+getSchemeName()+" authentication: "
+ + credentials.getClass().getName());
+ }
+
+ // client credentials handle
+ try {
+ String username = CurrentUserCredentials.getCurrentUsername();
+ TimeStamp lifetime = new TimeStamp();
+
+ clientCred = new CredHandle();
+ int rc = Secur32.INSTANCE.AcquireCredentialsHandle(username,
+ scheme, Sspi.SECPKG_CRED_OUTBOUND, null, null, null, null,
+ clientCred, lifetime);
+
+ if (WinError.SEC_E_OK != rc) {
+ throw new Win32Exception(rc);
+ }
+
+ response = getToken(null, null,username);
+ }
+ catch(Throwable t) {
+ dispose();
+ throw new AuthenticationException("Authentication Failed", t);
+ }
+ }
+ else if(this.challenge==null || this.challenge.length()==0){
+ dispose();
+ throw new AuthenticationException("Authentication Failed");
+ }
+ else {
+ try {
+ byte[] continueTokenBytes = Base64.decodeBase64(this.challenge);
+ SecBufferDesc continueTokenBuffer = new SecBufferDesc(
+ Sspi.SECBUFFER_TOKEN, continueTokenBytes);
+ response = getToken(context, continueTokenBuffer, "localhost");
+ }
+ catch(Throwable t) {
+ dispose();
+ throw new AuthenticationException("Authentication Failed", t);
+ }
+ }
+
+ final CharArrayBuffer buffer = new CharArrayBuffer(scheme.length()+30);
+ if (isProxy()) {
+ buffer.append(AUTH.PROXY_AUTH_RESP);
+ } else {
+ buffer.append(AUTH.WWW_AUTH_RESP);
+ }
+ buffer.append(": ");
+ buffer.append(scheme); // NTLM or Negotiate
+ buffer.append(" ");
+ buffer.append(response);
+ return new BufferedHeader(buffer);
+ }
+
+ /**
+ * @see http://msdn.microsoft.com/en-us/library/windows/desktop/aa375506(v=vs.85).aspx
+ */
+ private String getToken(CtxtHandle continueCtx, SecBufferDesc continueToken, String targetName) {
+ IntByReference attr = new IntByReference();
+ SecBufferDesc token = new SecBufferDesc(
+ Sspi.SECBUFFER_TOKEN, Sspi.MAX_TOKEN_SIZE);
+
+ context = new CtxtHandle();
+ int rc = Secur32.INSTANCE.InitializeSecurityContext(clientCred,
+ continueCtx, targetName, Sspi.ISC_REQ_CONNECTION, 0,
+ Sspi.SECURITY_NATIVE_DREP, continueToken, 0, context, token,
+ attr, null);
+ switch (rc) {
+ case WinError.SEC_I_CONTINUE_NEEDED:
+ continueNeeded = true;
+ break;
+ case WinError.SEC_E_OK:
+ dispose(); // Don't keep the context
+ continueNeeded = false;
+ break;
+ default:
+ dispose();
+ throw new Win32Exception(rc);
+ }
+ return Base64.encodeBase64String(token.getBytes());
+ }
+
+ public boolean isComplete() {
+ return !continueNeeded;
+ }
+}
Property changes on: httpclient/src/main/java/org/apache/http/impl/auth/WindowsNegotiateScheme.java
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: httpclient/src/main/java/org/apache/http/impl/auth/WindowsNegotiateSchemeFactory.java
===================================================================
--- httpclient/src/main/java/org/apache/http/impl/auth/WindowsNegotiateSchemeFactory.java (revision 0)
+++ httpclient/src/main/java/org/apache/http/impl/auth/WindowsNegotiateSchemeFactory.java (working copy)
@@ -0,0 +1,54 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+
+package org.apache.http.impl.auth;
+
+import org.apache.http.annotation.Immutable;
+import org.apache.http.auth.*;
+import org.apache.http.params.HttpParams;
+import org.apache.http.protocol.HttpContext;
+
+/**
+ * {@link AuthSchemeProvider} implementation that creates and initializes
+ * {@link WindowsNegotiateScheme} using JNA to Negotiate credentials
+ *
+ * @since 4.3
+ */
+@Immutable
+@SuppressWarnings("deprecation")
+public class WindowsNegotiateSchemeFactory implements AuthSchemeFactory, AuthSchemeProvider {
+
+ public static final String SCHEME = "Negotiate";
+
+ public AuthScheme newInstance(final HttpParams params) {
+ return new WindowsNegotiateScheme(SCHEME);
+ }
+
+ public AuthScheme create(final HttpContext context) {
+ return new WindowsNegotiateScheme(SCHEME);
+ }
+}
Property changes on: httpclient/src/main/java/org/apache/http/impl/auth/WindowsNegotiateSchemeFactory.java
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: httpclient/src/test/java/org/apache/http/impl/auth/TestWindowsNegotiateScheme.java
===================================================================
--- httpclient/src/test/java/org/apache/http/impl/auth/TestWindowsNegotiateScheme.java (revision 0)
+++ httpclient/src/test/java/org/apache/http/impl/auth/TestWindowsNegotiateScheme.java (working copy)
@@ -0,0 +1,87 @@
+/*
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * .
+ *
+ */
+package org.apache.http.impl.auth;
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthSchemeRegistry;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.util.EntityUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * This class needs obvious help -- it hits a running server
+ */
+public class TestWindowsNegotiateScheme {
+
+ @Test
+ public void testAuthenticationRequested() throws Exception {
+ if(!WindowsNegotiateScheme.isAvaliable()) {
+ // skip the test
+ return;
+ }
+
+ AuthSchemeRegistry authSchemeRegistry = new AuthSchemeRegistry();
+ authSchemeRegistry.register(WindowsNegotiateSchemeFactory.SCHEME, new WindowsNegotiateSchemeFactory());
+ authSchemeRegistry.register(WindowsNTLMSchemeFactory.SCHEME, new WindowsNTLMSchemeFactory());
+
+ DefaultHttpClient httpclient = new DefaultHttpClient();
+ httpclient.setAuthSchemes(authSchemeRegistry);
+
+ try {
+ httpclient.getCredentialsProvider().setCredentials(
+ AuthScope.ANY,
+ CurrentUserCredentials.get());
+
+ HttpGet httpget = new HttpGet("http://localhost:8888/account/login");
+
+ System.out.println("executing request" + httpget.getRequestLine());
+ HttpResponse response = httpclient.execute(httpget);
+ HttpEntity entity = response.getEntity();
+
+ System.out.println("----------------------------------------");
+ System.out.println(response.getStatusLine());
+ if (entity != null) {
+ System.out.println("Response content length: " + entity.getContentLength());
+ }
+ String body = EntityUtils.toString(entity);
+ System.out.println("----------------------------------------");
+ System.out.println(body);
+
+ Assert.assertTrue(body.indexOf(CurrentUserCredentials.getCurrentUsername())>0);
+ }
+ finally {
+ // When HttpClient instance is no longer needed,
+ // shut down the connection manager to ensure
+ // immediate deallocation of all system resources
+ httpclient.getConnectionManager().shutdown();
+ }
+ }
+}
Property changes on: httpclient/src/test/java/org/apache/http/impl/auth/TestWindowsNegotiateScheme.java
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: pom.xml
===================================================================
--- pom.xml (revision 1517999)
+++ pom.xml (working copy)
@@ -74,6 +74,7 @@
4.9
2.5.2
1.8.5
+ 4.0.0
1
4.2
@@ -123,6 +124,16 @@
${memcached.version}
+ net.java.dev.jna
+ jna
+ ${jna.version}
+
+
+ net.java.dev.jna
+ jna-platform
+ ${jna.version}
+
+
junit
junit
${junit.version}