From c1c2e9cc82ab818494070709b0ed0b546d2985ed Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Tue, 16 Jan 2018 09:51:51 +0100 Subject: [PATCH] Removed classes committed by mistake --- .../apache/http/impl/auth/CredSspScheme.java | 1126 ----------------- .../http/impl/auth/CredSspSchemeFactory.java | 44 - .../org/apache/http/impl/auth/DebugUtil.java | 96 -- 3 files changed, 1266 deletions(-) delete mode 100644 httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java delete mode 100644 httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java delete mode 100644 httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java b/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java deleted file mode 100644 index 9cc5fc84e..000000000 --- a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspScheme.java +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * ==================================================================== - * 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.nio.ByteBuffer; -import java.nio.charset.Charset; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.PublicKey; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.Arrays; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLEngineResult; -import javax.net.ssl.SSLEngineResult.HandshakeStatus; -import javax.net.ssl.SSLEngineResult.Status; -import javax.net.ssl.SSLException; -import javax.net.ssl.SSLPeerUnverifiedException; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManager; -import javax.net.ssl.X509TrustManager; - -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.http.Consts; -import org.apache.http.Header; -import org.apache.http.HttpRequest; -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.auth.NTCredentials; -import org.apache.http.message.BufferedHeader; -import org.apache.http.protocol.HttpContext; -import org.apache.http.ssl.SSLContexts; -import org.apache.http.util.CharArrayBuffer; -import org.apache.http.util.CharsetUtils; - -/** - *

- * Client implementation of the CredSSP protocol specified in [MS-CSSP]. - *

- *

- * Note: This is implementation is NOT GSS based. It should be. But there is no Java NTLM - * implementation as GSS module. Maybe the NTLMEngine can be converted to GSS and then this - * can be also switched to GSS. In fact it only works in CredSSP+NTLM case. - *

- *

- * Based on [MS-CSSP]: Credential Security Support Provider (CredSSP) Protocol (Revision 13.0, 7/14/2016). - * The implementation was inspired by Python CredSSP and NTLM implementation by Jordan Borean. - *

- */ -public class CredSspScheme extends AuthSchemeBase -{ - private static final Charset UNICODE_LITTLE_UNMARKED = CharsetUtils.lookup( "UnicodeLittleUnmarked" ); - public static final String SCHEME_NAME = "CredSSP"; - - private final Log log = LogFactory.getLog( CredSspScheme.class ); - - enum State - { - // Nothing sent, nothing received - UNINITIATED, - - // We are handshaking. Several messages are exchanged in this state - TLS_HANDSHAKE, - - // TLS handshake finished. Channel established - TLS_HANDSHAKE_FINISHED, - - // NTLM NEGOTIATE message sent (strictly speaking this should be SPNEGO) - NEGO_TOKEN_SENT, - - // NTLM CHALLENGE message received (strictly speaking this should be SPNEGO) - NEGO_TOKEN_RECEIVED, - - // NTLM AUTHENTICATE message sent together with a server public key - PUB_KEY_AUTH_SENT, - - // Server public key authentication message received - PUB_KEY_AUTH_RECEIVED, - - // Credentials message sent. Protocol exchange finished. - CREDENTIALS_SENT; - } - - private State state; - private SSLEngine sslEngine; - private NTLMEngineImpl.Type1Message type1Message; - private NTLMEngineImpl.Type2Message type2Message; - private NTLMEngineImpl.Type3Message type3Message; - private CredSspTsRequest lastReceivedTsRequest; - private NTLMEngineImpl.Handle ntlmOutgoingHandle; - private NTLMEngineImpl.Handle ntlmIncomingHandle; - private byte[] peerPublicKey; - - - public CredSspScheme() { - state = State.UNINITIATED; - } - - - @Override - public String getSchemeName() - { - return SCHEME_NAME; - } - - - @Override - public String getParameter( final String name ) - { - return null; - } - - - @Override - public String getRealm() - { - return null; - } - - - @Override - public boolean isConnectionBased() - { - return true; - } - - - private SSLEngine getSSLEngine() - { - if ( sslEngine == null ) - { - sslEngine = createSSLEngine(); - } - return sslEngine; - } - - - private SSLEngine createSSLEngine() - { - final SSLContext sslContext; - try - { - sslContext = SSLContexts.custom().build(); - } - catch ( final NoSuchAlgorithmException e ) - { - throw new RuntimeException( "Error creating SSL Context: " + e.getMessage(), e ); - } - catch ( final KeyManagementException e ) - { - throw new RuntimeException( "Error creating SSL Context: " + e.getMessage(), e ); - } - - final X509TrustManager tm = new X509TrustManager() - { - - @Override - public void checkClientTrusted( final X509Certificate[] chain, final String authType ) - throws CertificateException - { - // Nothing to do. - } - - - @Override - public void checkServerTrusted( final X509Certificate[] chain, final String authType ) - throws CertificateException - { - // Nothing to do, accept all. CredSSP server is using its own certificate without any - // binding to the PKI trust chains. The public key is verified as part of the CredSSP - // protocol exchange. - } - - - @Override - public X509Certificate[] getAcceptedIssuers() - { - return null; - } - - }; - try - { - sslContext.init( null, new TrustManager[] - { tm }, null ); - } - catch ( final KeyManagementException e ) - { - throw new RuntimeException( "SSL Context initialization error: " + e.getMessage(), e ); - } - final SSLEngine sslEngine = sslContext.createSSLEngine(); - sslEngine.setUseClientMode( true ); - return sslEngine; - } - - - @Override - protected void parseChallenge( final CharArrayBuffer buffer, final int beginIndex, final int endIndex ) - throws MalformedChallengeException - { - final String inputString = buffer.substringTrimmed( beginIndex, endIndex ); - - if ( inputString.isEmpty() ) - { - if ( state == State.UNINITIATED ) - { - // This is OK, just send out first message. That should start TLS handshake - } - else - { - final String msg = "Received unexpected empty input in state " + state; - log.error( msg ); - throw new MalformedChallengeException( msg ); - } - } - - if ( state == State.TLS_HANDSHAKE ) - { - unwrapHandshake( inputString ); - if ( getSSLEngine().getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING ) - { - log.trace( "TLS handshake finished" ); - state = State.TLS_HANDSHAKE_FINISHED; - } - } - - if ( state == State.NEGO_TOKEN_SENT ) - { - final ByteBuffer buf = unwrap( inputString ); - state = State.NEGO_TOKEN_RECEIVED; - lastReceivedTsRequest = CredSspTsRequest.createDecoded( buf ); - } - - if ( state == State.PUB_KEY_AUTH_SENT ) - { - final ByteBuffer buf = unwrap( inputString ); - state = State.PUB_KEY_AUTH_RECEIVED; - lastReceivedTsRequest = CredSspTsRequest.createDecoded( buf ); - } - } - - - @Override - @Deprecated - public Header authenticate( - final Credentials credentials, - final HttpRequest request ) throws AuthenticationException - { - return authenticate( credentials, request, null ); - } - - - @Override - public Header authenticate( - final Credentials credentials, - final HttpRequest request, - final HttpContext context ) throws AuthenticationException - { - NTCredentials ntcredentials = null; - try - { - ntcredentials = ( NTCredentials ) credentials; - } - catch ( final ClassCastException e ) - { - throw new InvalidCredentialsException( - "Credentials cannot be used for CredSSP authentication: " - + credentials.getClass().getName() ); - } - - String outputString = null; - - if ( state == State.UNINITIATED ) - { - beginTlsHandshake(); - outputString = wrapHandshake(); - state = State.TLS_HANDSHAKE; - - } - else if ( state == State.TLS_HANDSHAKE ) - { - outputString = wrapHandshake(); - - } - else if ( state == State.TLS_HANDSHAKE_FINISHED ) - { - - final int ntlmFlags = getNtlmFlags(); - final ByteBuffer buf = allocateOutBuffer(); - type1Message = new NTLMEngineImpl.Type1Message( - ntcredentials.getDomain(), ntcredentials.getWorkstation(), ntlmFlags); - final byte[] ntlmNegoMessageEncoded = type1Message.getBytes(); - final CredSspTsRequest req = CredSspTsRequest.createNegoToken( ntlmNegoMessageEncoded ); - req.encode( buf ); - buf.flip(); - outputString = wrap( buf ); - state = State.NEGO_TOKEN_SENT; - - } - else if ( state == State.NEGO_TOKEN_RECEIVED ) - { - final ByteBuffer buf = allocateOutBuffer(); - type2Message = new NTLMEngineImpl.Type2Message( - lastReceivedTsRequest.getNegoToken()); - - final Certificate peerServerCertificate = getPeerServerCertificate(); - - type3Message = new NTLMEngineImpl.Type3Message( - ntcredentials.getDomain(), - ntcredentials.getWorkstation(), - ntcredentials.getUserName(), - ntcredentials.getPassword(), - type2Message.getChallenge(), - type2Message.getFlags(), - type2Message.getTarget(), - type2Message.getTargetInfo(), - peerServerCertificate, - type1Message.getBytes(), - type2Message.getBytes()); - - final byte[] ntlmAuthenticateMessageEncoded = type3Message.getBytes(); - - final byte[] exportedSessionKey = type3Message.getExportedSessionKey(); - - ntlmOutgoingHandle = new NTLMEngineImpl.Handle(exportedSessionKey, NTLMEngineImpl.Mode.CLIENT, true); - ntlmIncomingHandle = new NTLMEngineImpl.Handle(exportedSessionKey, NTLMEngineImpl.Mode.SERVER, true); - - final CredSspTsRequest req = CredSspTsRequest.createNegoToken( ntlmAuthenticateMessageEncoded ); - peerPublicKey = getSubjectPublicKeyDer( peerServerCertificate.getPublicKey() ); - final byte[] pubKeyAuth = createPubKeyAuth(); - req.setPubKeyAuth( pubKeyAuth ); - - req.encode( buf ); - buf.flip(); - outputString = wrap( buf ); - state = State.PUB_KEY_AUTH_SENT; - - } - else if ( state == State.PUB_KEY_AUTH_RECEIVED ) - { - verifyPubKeyAuthResponse( lastReceivedTsRequest.getPubKeyAuth() ); - final byte[] authInfo = createAuthInfo( ntcredentials ); - final CredSspTsRequest req = CredSspTsRequest.createAuthInfo( authInfo ); - - final ByteBuffer buf = allocateOutBuffer(); - req.encode( buf ); - buf.flip(); - outputString = wrap( buf ); - state = State.CREDENTIALS_SENT; - } - else - { - throw new AuthenticationException( "Wrong state " + state ); - } - final CharArrayBuffer buffer = new CharArrayBuffer( 32 ); - if ( isProxy() ) - { - buffer.append( AUTH.PROXY_AUTH_RESP ); - } - else - { - buffer.append( AUTH.WWW_AUTH_RESP ); - } - buffer.append( ": CredSSP " ); - buffer.append( outputString ); - return new BufferedHeader( buffer ); - } - - - private int getNtlmFlags() - { - return NTLMEngineImpl.FLAG_REQUEST_OEM_ENCODING | - NTLMEngineImpl.FLAG_REQUEST_SIGN | - NTLMEngineImpl.FLAG_REQUEST_SEAL | - NTLMEngineImpl.FLAG_DOMAIN_PRESENT | - NTLMEngineImpl.FLAG_REQUEST_ALWAYS_SIGN | - NTLMEngineImpl.FLAG_REQUEST_NTLM2_SESSION | - NTLMEngineImpl.FLAG_TARGETINFO_PRESENT | - NTLMEngineImpl.FLAG_REQUEST_VERSION | - NTLMEngineImpl.FLAG_REQUEST_128BIT_KEY_EXCH | - NTLMEngineImpl.FLAG_REQUEST_EXPLICIT_KEY_EXCH | - NTLMEngineImpl.FLAG_REQUEST_56BIT_ENCRYPTION; - } - - - private Certificate getPeerServerCertificate() throws AuthenticationException - { - final Certificate[] peerCertificates; - try - { - peerCertificates = sslEngine.getSession().getPeerCertificates(); - } - catch ( final SSLPeerUnverifiedException e ) - { - throw new AuthenticationException( e.getMessage(), e ); - } - for ( final Certificate peerCertificate : peerCertificates ) - { - if ( !( peerCertificate instanceof X509Certificate ) ) - { - continue; - } - final X509Certificate peerX509Cerificate = ( X509Certificate ) peerCertificate; - if ( peerX509Cerificate.getBasicConstraints() != -1 ) - { - continue; - } - return peerX509Cerificate; - } - return null; - } - - - private byte[] createPubKeyAuth() throws AuthenticationException - { - return ntlmOutgoingHandle.signAndEncryptMessage( peerPublicKey ); - } - - - private void verifyPubKeyAuthResponse( final byte[] pubKeyAuthResponse ) throws AuthenticationException - { - final byte[] pubKeyReceived = ntlmIncomingHandle.decryptAndVerifySignedMessage( pubKeyAuthResponse ); - - // assert: pubKeyReceived = peerPublicKey + 1 - // The following algorithm is a bit simplified. But due to the ASN.1 encoding the first byte - // of the public key will be 0x30 we can pretty much rely on a fact that there will be no carry - if ( peerPublicKey.length != pubKeyReceived.length ) - { - throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); - } - if ( ( peerPublicKey[0] + 1 ) != pubKeyReceived[0] ) - { - throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); - } - for ( int i = 1; i < peerPublicKey.length; i++ ) - { - if ( peerPublicKey[i] != pubKeyReceived[i] ) - { - throw new AuthenticationException( "Public key mismatch in pubKeyAuth response" ); - } - } - log.trace( "Received public key response is valid" ); - } - - - private byte[] createAuthInfo( final NTCredentials ntcredentials ) throws AuthenticationException - { - - final byte[] domainBytes = encodeUnicode( ntcredentials.getDomain() ); - final byte[] domainOctetStringBytesLengthBytes = encodeLength( domainBytes.length ); - final int domainNameLength = 1 + domainOctetStringBytesLengthBytes.length + domainBytes.length; - final byte[] domainNameLengthBytes = encodeLength( domainNameLength ); - - final byte[] usernameBytes = encodeUnicode( ntcredentials.getUserName() ); - final byte[] usernameOctetStringBytesLengthBytes = encodeLength( usernameBytes.length ); - final int userNameLength = 1 + usernameOctetStringBytesLengthBytes.length + usernameBytes.length; - final byte[] userNameLengthBytes = encodeLength( userNameLength ); - - final byte[] passwordBytes = encodeUnicode( ntcredentials.getPassword() ); - final byte[] passwordOctetStringBytesLengthBytes = encodeLength( passwordBytes.length ); - final int passwordLength = 1 + passwordOctetStringBytesLengthBytes.length + passwordBytes.length; - final byte[] passwordLengthBytes = encodeLength( passwordLength ); - - final int tsPasswordLength = 1 + domainNameLengthBytes.length + domainNameLength + - 1 + userNameLengthBytes.length + userNameLength + - 1 + passwordLengthBytes.length + passwordLength; - final byte[] tsPasswordLengthBytes = encodeLength( tsPasswordLength ); - final int credentialsOctetStringLength = 1 + tsPasswordLengthBytes.length + tsPasswordLength; - final byte[] credentialsOctetStringLengthBytes = encodeLength( credentialsOctetStringLength ); - final int credentialsLength = 1 + credentialsOctetStringLengthBytes.length + credentialsOctetStringLength; - final byte[] credentialsLengthBytes = encodeLength( credentialsLength ); - final int tsCredentialsLength = 5 + 1 + credentialsLengthBytes.length + credentialsLength; - final byte[] tsCredentialsLengthBytes = encodeLength( tsCredentialsLength ); - - final ByteBuffer buf = ByteBuffer.allocate( 1 + tsCredentialsLengthBytes.length + tsCredentialsLength ); - - // TSCredentials structure [MS-CSSP] section 2.2.1.2 - buf.put( ( byte ) 0x30 ); // seq - buf.put( tsCredentialsLengthBytes ); - - buf.put( ( byte ) ( 0x00 | 0xa0 ) ); // credType tag [0] - buf.put( ( byte ) 3 ); // credType length - buf.put( ( byte ) 0x02 ); // type: INTEGER - buf.put( ( byte ) 1 ); // credType inner length - buf.put( ( byte ) 1 ); // credType value: 1 (password) - - buf.put( ( byte ) ( 0x01 | 0xa0 ) ); // credentials tag [1] - buf.put( credentialsLengthBytes ); - buf.put( ( byte ) 0x04 ); // type: OCTET STRING - buf.put( credentialsOctetStringLengthBytes ); - - // TSPasswordCreds structure [MS-CSSP] section 2.2.1.2.1 - buf.put( ( byte ) 0x30 ); // seq - buf.put( tsPasswordLengthBytes ); - - buf.put( ( byte ) ( 0x00 | 0xa0 ) ); // domainName tag [0] - buf.put( domainNameLengthBytes ); - buf.put( ( byte ) 0x04 ); // type: OCTET STRING - buf.put( domainOctetStringBytesLengthBytes ); - buf.put( domainBytes ); - - buf.put( ( byte ) ( 0x01 | 0xa0 ) ); // userName tag [1] - buf.put( userNameLengthBytes ); - buf.put( ( byte ) 0x04 ); // type: OCTET STRING - buf.put( usernameOctetStringBytesLengthBytes ); - buf.put( usernameBytes ); - - buf.put( ( byte ) ( 0x02 | 0xa0 ) ); // password tag [2] - buf.put( passwordLengthBytes ); - buf.put( ( byte ) 0x04 ); // type: OCTET STRING - buf.put( passwordOctetStringBytesLengthBytes ); - buf.put( passwordBytes ); - - final byte[] authInfo = buf.array(); - try - { - return ntlmOutgoingHandle.signAndEncryptMessage( authInfo ); - } - catch ( final NTLMEngineException e ) - { - throw new AuthenticationException( e.getMessage(), e ); - } - } - - private final static byte[] EMPTYBUFFER = new byte[0]; - - private byte[] encodeUnicode( final String string ) - { - if (string == null) { - return EMPTYBUFFER; - } - return string.getBytes( UNICODE_LITTLE_UNMARKED ); - } - - - private byte[] getSubjectPublicKeyDer( final PublicKey publicKey ) throws AuthenticationException - { - // The publicKey.getEncoded() returns encoded SubjectPublicKeyInfo structure. But the CredSSP expects - // SubjectPublicKey subfield. I have found no easy way how to get just the SubjectPublicKey from - // java.security libraries. So let's use a primitive way and parse it out from the DER. - - try - { - final byte[] encodedPubKeyInfo = publicKey.getEncoded(); - - final ByteBuffer buf = ByteBuffer.wrap( encodedPubKeyInfo ); - getByteAndAssert( buf, 0x30, "initial sequence" ); - parseLength( buf ); - getByteAndAssert( buf, 0x30, "AlgorithmIdentifier sequence" ); - final int algIdSeqLength = parseLength( buf ); - buf.position( buf.position() + algIdSeqLength ); - getByteAndAssert( buf, 0x03, "subjectPublicKey type" ); - int subjectPublicKeyLegth = parseLength( buf ); - // There may be leading padding byte ... or whatever that is. Skip that. - final byte b = buf.get(); - if ( b == 0 ) - { - subjectPublicKeyLegth--; - } - else - { - buf.position( buf.position() - 1 ); - } - final byte[] subjectPublicKey = new byte[subjectPublicKeyLegth]; - buf.get( subjectPublicKey ); - return subjectPublicKey; - } - catch ( final MalformedChallengeException e ) - { - throw new AuthenticationException( e.getMessage(), e ); - } - } - - - private void beginTlsHandshake() throws AuthenticationException - { - try - { - getSSLEngine().beginHandshake(); - } - catch ( final SSLException e ) - { - throw new AuthenticationException( "SSL Engine error: " + e.getMessage(), e ); - } - } - - - private ByteBuffer allocateOutBuffer() - { - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - return ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); - } - - - private String wrapHandshake() throws AuthenticationException - { - final ByteBuffer src = allocateOutBuffer(); - src.flip(); - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - // Needs to be twice the size as there may be two wraps during handshake. - // Primitive and inefficient solution, but it works. - final ByteBuffer dst = ByteBuffer.allocate( sslSession.getPacketBufferSize() * 2 ); - while ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP ) - { - wrap( src, dst ); - } - dst.flip(); - return encodeBase64( dst ); - } - - - private String wrap( final ByteBuffer src ) throws AuthenticationException - { - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - final ByteBuffer dst = ByteBuffer.allocate( sslSession.getPacketBufferSize() ); - wrap( src, dst ); - dst.flip(); - return encodeBase64( dst ); - } - - - private void wrap( final ByteBuffer src, final ByteBuffer dst ) throws AuthenticationException - { - final SSLEngine sslEngine = getSSLEngine(); - try - { - final SSLEngineResult engineResult = sslEngine.wrap( src, dst ); - if ( engineResult.getStatus() != Status.OK ) - { - throw new AuthenticationException( "SSL Engine error status: " + engineResult.getStatus() ); - } - } - catch ( final SSLException e ) - { - throw new AuthenticationException( "SSL Engine wrap error: " + e.getMessage(), e ); - } - } - - - private void unwrapHandshake( final String inputString ) throws MalformedChallengeException - { - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - final ByteBuffer src = decodeBase64( inputString ); - final ByteBuffer dst = ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); - while ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP ) - { - unwrap( src, dst ); - } - } - - - private ByteBuffer unwrap( final String inputString ) throws MalformedChallengeException - { - final SSLEngine sslEngine = getSSLEngine(); - final SSLSession sslSession = sslEngine.getSession(); - final ByteBuffer src = decodeBase64( inputString ); - final ByteBuffer dst = ByteBuffer.allocate( sslSession.getApplicationBufferSize() ); - unwrap( src, dst ); - dst.flip(); - return dst; - } - - - private void unwrap( final ByteBuffer src, final ByteBuffer dst ) throws MalformedChallengeException - { - - try - { - final SSLEngineResult engineResult = sslEngine.unwrap( src, dst ); - if ( engineResult.getStatus() != Status.OK ) - { - throw new MalformedChallengeException( "SSL Engine error status: " + engineResult.getStatus() ); - } - - if ( sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_TASK ) - { - final Runnable task = sslEngine.getDelegatedTask(); - task.run(); - } - - } - catch ( final SSLException e ) - { - throw new MalformedChallengeException( "SSL Engine unwrap error: " + e.getMessage(), e ); - } - } - - - private String encodeBase64( final ByteBuffer buffer ) - { - final int limit = buffer.limit(); - final byte[] bytes = new byte[limit]; - buffer.get( bytes ); - return new String(Base64.encodeBase64(bytes), Consts.ASCII); - } - - - private ByteBuffer decodeBase64( final String inputString ) - { - final byte[] inputBytes = Base64.decodeBase64(inputString.getBytes(Consts.ASCII)); - final ByteBuffer buffer = ByteBuffer.wrap( inputBytes ); - return buffer; - } - - - @Override - public boolean isComplete() - { - return state == State.CREDENTIALS_SENT; - } - - /** - * Implementation of the TsRequest structure used in CredSSP protocol. - * It is specified in [MS-CPPS] section 2.2.1. - */ - static class CredSspTsRequest - { - - private static final int VERSION = 3; - - private byte[] negoToken; - private byte[] authInfo; - private byte[] pubKeyAuth; - - - protected CredSspTsRequest() - { - super(); - } - - - public static CredSspTsRequest createNegoToken( final byte[] negoToken ) - { - final CredSspTsRequest req = new CredSspTsRequest(); - req.negoToken = negoToken; - return req; - } - - - public static CredSspTsRequest createAuthInfo( final byte[] authInfo ) - { - final CredSspTsRequest req = new CredSspTsRequest(); - req.authInfo = authInfo; - return req; - } - - - public static CredSspTsRequest createDecoded( final ByteBuffer buf ) throws MalformedChallengeException - { - final CredSspTsRequest req = new CredSspTsRequest(); - req.decode( buf ); - return req; - } - - - public byte[] getNegoToken() - { - return negoToken; - } - - - public void setNegoToken( final byte[] negoToken ) - { - this.negoToken = negoToken; - } - - - public byte[] getAuthInfo() - { - return authInfo; - } - - - public void setAuthInfo( final byte[] authInfo ) - { - this.authInfo = authInfo; - } - - - public byte[] getPubKeyAuth() - { - return pubKeyAuth; - } - - - public void setPubKeyAuth( final byte[] pubKeyAuth ) - { - this.pubKeyAuth = pubKeyAuth; - } - - - public void decode( final ByteBuffer buf ) throws MalformedChallengeException - { - negoToken = null; - authInfo = null; - pubKeyAuth = null; - - getByteAndAssert( buf, 0x30, "initial sequence" ); - parseLength( buf ); - - while ( buf.hasRemaining() ) - { - final int contentTag = getAndAssertContentSpecificTag( buf, "content tag" ); - parseLength( buf ); - switch ( contentTag ) - { - case 0: - processVersion( buf ); - break; - case 1: - parseNegoTokens( buf ); - break; - case 2: - parseAuthInfo( buf ); - break; - case 3: - parsePubKeyAuth( buf ); - break; - case 4: - processErrorCode( buf ); - break; - default: - parseError( buf, "unexpected content tag " + contentTag ); - } - } - } - - - private void processVersion( final ByteBuffer buf ) throws MalformedChallengeException - { - getByteAndAssert( buf, 0x02, "version type" ); - getLengthAndAssert( buf, 1, "version length" ); - getByteAndAssert( buf, VERSION, "wrong protocol version" ); - } - - - private void parseNegoTokens( final ByteBuffer buf ) throws MalformedChallengeException - { - getByteAndAssert( buf, 0x30, "negoTokens sequence" ); - parseLength( buf ); - // I have seen both 0x30LL encoding and 0x30LL0x30LL encoding. Accept both. - byte bufByte = buf.get(); - if ( bufByte == 0x30 ) - { - parseLength( buf ); - bufByte = buf.get(); - } - if ( ( bufByte & 0xff ) != 0xa0 ) - { - parseError( buf, "negoTokens: wrong content-specific tag " + String.format( "%02X", bufByte ) ); - } - parseLength( buf ); - getByteAndAssert( buf, 0x04, "negoToken type" ); - - final int tokenLength = parseLength( buf ); - negoToken = new byte[tokenLength]; - buf.get( negoToken ); - } - - - private void parseAuthInfo( final ByteBuffer buf ) throws MalformedChallengeException - { - getByteAndAssert( buf, 0x04, "authInfo type" ); - final int length = parseLength( buf ); - authInfo = new byte[length]; - buf.get( authInfo ); - } - - - private void parsePubKeyAuth( final ByteBuffer buf ) throws MalformedChallengeException - { - getByteAndAssert( buf, 0x04, "pubKeyAuth type" ); - final int length = parseLength( buf ); - pubKeyAuth = new byte[length]; - buf.get( pubKeyAuth ); - } - - - private void processErrorCode( final ByteBuffer buf ) throws MalformedChallengeException - { - getLengthAndAssert( buf, 3, "error code length" ); - getByteAndAssert( buf, 0x02, "error code type" ); - getLengthAndAssert( buf, 1, "error code length" ); - final byte errorCode = buf.get(); - parseError( buf, "Error code " + errorCode ); - } - - - public void encode( final ByteBuffer buf ) - { - final ByteBuffer inner = ByteBuffer.allocate( buf.capacity() ); - - // version tag [0] - inner.put( ( byte ) ( 0x00 | 0xa0 ) ); - inner.put( ( byte ) 3 ); // length - - inner.put( ( byte ) ( 0x02 ) ); // INTEGER tag - inner.put( ( byte ) 1 ); // length - inner.put( ( byte ) VERSION ); // value - - if ( negoToken != null ) - { - int len = negoToken.length; - final byte[] negoTokenLengthBytes = encodeLength( len ); - len += 1 + negoTokenLengthBytes.length; - final byte[] negoTokenLength1Bytes = encodeLength( len ); - len += 1 + negoTokenLength1Bytes.length; - final byte[] negoTokenLength2Bytes = encodeLength( len ); - len += 1 + negoTokenLength2Bytes.length; - final byte[] negoTokenLength3Bytes = encodeLength( len ); - len += 1 + negoTokenLength3Bytes.length; - final byte[] negoTokenLength4Bytes = encodeLength( len ); - - inner.put( ( byte ) ( 0x01 | 0xa0 ) ); // negoData tag [1] - inner.put( negoTokenLength4Bytes ); // length - - inner.put( ( byte ) ( 0x30 ) ); // SEQUENCE tag - inner.put( negoTokenLength3Bytes ); // length - - inner.put( ( byte ) ( 0x30 ) ); // .. of SEQUENCE tag - inner.put( negoTokenLength2Bytes ); // length - - inner.put( ( byte ) ( 0x00 | 0xa0 ) ); // negoToken tag [0] - inner.put( negoTokenLength1Bytes ); // length - - inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag - inner.put( negoTokenLengthBytes ); // length - - inner.put( negoToken ); - } - - if ( authInfo != null ) - { - final byte[] authInfoEncodedLength = encodeLength( authInfo.length ); - - inner.put( ( byte ) ( 0x02 | 0xa0 ) ); // authInfo tag [2] - inner.put( encodeLength( 1 + authInfoEncodedLength.length + authInfo.length ) ); // length - - inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag - inner.put( authInfoEncodedLength ); - inner.put( authInfo ); - } - - if ( pubKeyAuth != null ) - { - final byte[] pubKeyAuthEncodedLength = encodeLength( pubKeyAuth.length ); - - inner.put( ( byte ) ( 0x03 | 0xa0 ) ); // pubKeyAuth tag [3] - inner.put( encodeLength( 1 + pubKeyAuthEncodedLength.length + pubKeyAuth.length ) ); // length - - inner.put( ( byte ) ( 0x04 ) ); // OCTET STRING tag - inner.put( pubKeyAuthEncodedLength ); - inner.put( pubKeyAuth ); - } - - inner.flip(); - - // SEQUENCE tag - buf.put( ( byte ) ( 0x10 | 0x20 ) ); - buf.put( encodeLength( inner.limit() ) ); - buf.put( inner ); - } - - - public String debugDump() - { - final StringBuilder sb = new StringBuilder( "TsRequest\n" ); - sb.append( " negoToken:\n" ); - sb.append( " " ); - DebugUtil.dump( sb, negoToken ); - sb.append( "\n" ); - sb.append( " authInfo:\n" ); - sb.append( " " ); - DebugUtil.dump( sb, authInfo ); - sb.append( "\n" ); - sb.append( " pubKeyAuth:\n" ); - sb.append( " " ); - DebugUtil.dump( sb, pubKeyAuth ); - return sb.toString(); - } - - - @Override - public String toString() - { - return "TsRequest(negoToken=" + Arrays.toString( negoToken ) + ", authInfo=" - + Arrays.toString( authInfo ) + ", pubKeyAuth=" + Arrays.toString( pubKeyAuth ) + ")"; - } - } - - static void getByteAndAssert( final ByteBuffer buf, final int expectedValue, final String errorMessage ) - throws MalformedChallengeException - { - final byte bufByte = buf.get(); - if ( bufByte != expectedValue ) - { - parseError( buf, errorMessage + expectMessage( expectedValue, bufByte ) ); - } - } - - private static String expectMessage( final int expectedValue, final int realValue ) - { - return "(expected " + String.format( "%02X", expectedValue ) + ", got " + String.format( "%02X", realValue ) - + ")"; - } - - static int parseLength( final ByteBuffer buf ) - { - byte bufByte = buf.get(); - if ( bufByte == 0x80 ) - { - return -1; // infinite - } - if ( ( bufByte & 0x80 ) == 0x80 ) - { - final int size = bufByte & 0x7f; - int length = 0; - for ( int i = 0; i < size; i++ ) - { - bufByte = buf.get(); - length = ( length << 8 ) + ( bufByte & 0xff ); - } - return length; - } - else - { - return bufByte; - } - } - - static void getLengthAndAssert( final ByteBuffer buf, final int expectedValue, final String errorMessage ) - throws MalformedChallengeException - { - final int bufLength = parseLength( buf ); - if ( expectedValue != bufLength ) - { - parseError( buf, errorMessage + expectMessage( expectedValue, bufLength ) ); - } - } - - static int getAndAssertContentSpecificTag( final ByteBuffer buf, final String errorMessage ) throws MalformedChallengeException - { - final byte bufByte = buf.get(); - if ( ( bufByte & 0xe0 ) != 0xa0 ) - { - parseError( buf, errorMessage + ": wrong content-specific tag " + String.format( "%02X", bufByte ) ); - } - final int tag = bufByte & 0x1f; - return tag; - } - - static void parseError( final ByteBuffer buf, final String errorMessage ) throws MalformedChallengeException - { - throw new MalformedChallengeException( - "Error parsing TsRequest (position:" + buf.position() + "): " + errorMessage ); - } - - static byte[] encodeLength( final int length ) - { - if ( length < 128 ) - { - final byte[] encoded = new byte[1]; - encoded[0] = ( byte ) length; - return encoded; - } - - int size = 1; - - int val = length; - while ( ( val >>>= 8 ) != 0 ) - { - size++; - } - - final byte[] encoded = new byte[1 + size]; - encoded[0] = ( byte ) ( size | 0x80 ); - - int shift = ( size - 1 ) * 8; - for ( int i = 0; i < size; i++ ) - { - encoded[i + 1] = ( byte ) ( length >> shift ); - shift -= 8; - } - - return encoded; - } - -} diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java b/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java deleted file mode 100644 index 3953b5758..000000000 --- a/httpclient/src/main/java/org/apache/http/impl/auth/CredSspSchemeFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * ==================================================================== - * 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.auth.AuthScheme; -import org.apache.http.auth.AuthSchemeProvider; -import org.apache.http.protocol.HttpContext; - - -public class CredSspSchemeFactory implements AuthSchemeProvider -{ - - @Override - public AuthScheme create( final HttpContext context ) - { - return new CredSspScheme(); - } -} diff --git a/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java b/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java deleted file mode 100644 index 2c8110e29..000000000 --- a/httpclient/src/main/java/org/apache/http/impl/auth/DebugUtil.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * ==================================================================== - * 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.nio.ByteBuffer; - - -/** - * Simple debugging utility class for CredSSP and NTLM implementations. - */ -class DebugUtil -{ - - public static String dump( final ByteBuffer buf ) - { - final ByteBuffer dup = buf.duplicate(); - final StringBuilder sb = new StringBuilder( dup.toString() ); - sb.append( ": " ); - while ( dup.position() < dup.limit() ) - { - sb.append( String.format( "%02X ", dup.get() ) ); - } - return sb.toString(); - } - - - public static void dump( final StringBuilder sb, final byte[] bytes ) - { - if ( bytes == null ) - { - sb.append( "null" ); - return; - } - for ( final byte b : bytes ) - { - sb.append( String.format( "%02X ", b ) ); - } - } - - - public static String dump( final byte[] bytes ) - { - final StringBuilder sb = new StringBuilder(); - dump( sb, bytes ); - return sb.toString(); - } - - - public static byte[] fromHex( final String hex ) - { - int i = 0; - final byte[] bytes = new byte[200000]; - int h = 0; - while ( h < hex.length() ) - { - if ( hex.charAt( h ) == ' ' ) - { - h++; - } - final String str = hex.substring( h, h + 2 ); - bytes[i] = ( byte ) Integer.parseInt( str, 16 ); - i++; - h = h + 2; - } - final byte[] outbytes = new byte[i]; - System.arraycopy( bytes, 0, outbytes, 0, i ); - return outbytes; - } - -}