?? ntlm.java
字號(hào):
/* * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/auth/NTLM.java,v 1.11 2004/05/13 04:02:00 mbecke Exp $ * $Revision: 480424 $ * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $ * * ==================================================================== * * 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 * <http://www.apache.org/>. * */package org.apache.commons.httpclient.auth;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;import javax.crypto.spec.SecretKeySpec;import org.apache.commons.codec.binary.Base64;import org.apache.commons.httpclient.util.EncodingUtil;/** * Provides an implementation of the NTLM authentication protocol. * <p> * This class provides methods for generating authentication * challenge responses for the NTLM authentication protocol. The NTLM * protocol is a proprietary Microsoft protocol and as such no RFC * exists for it. This class is based upon the reverse engineering * efforts of a wide range of people.</p> * * <p>Please note that an implementation of JCE must be correctly installed and configured when * using NTLM support.</p> * * <p>This class should not be used externally to HttpClient as it's API is specifically * designed to work with HttpClient's use case, in particular it's connection management.</p> * * @author <a href="mailto:adrian@ephox.com">Adrian Sutton</a> * @author <a href="mailto:jsdever@apache.org">Jeff Dever</a> * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a> * * @version $Revision: 480424 $ $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $ * @since 3.0 */final class NTLM { /** Character encoding */ public static final String DEFAULT_CHARSET = "ASCII"; /** The current response */ private byte[] currentResponse; /** The current position */ private int currentPosition = 0; /** The character set to use for encoding the credentials */ private String credentialCharset = DEFAULT_CHARSET; /** * Returns the response for the given message. * * @param message the message that was received from the server. * @param username the username to authenticate with. * @param password the password to authenticate with. * @param host The host. * @param domain the NT domain to authenticate in. * @return The response. * @throws HttpException If the messages cannot be retrieved. */ public final String getResponseFor(String message, String username, String password, String host, String domain) throws AuthenticationException { final String response; if (message == null || message.trim().equals("")) { response = getType1Message(host, domain); } else { response = getType3Message(username, password, host, domain, parseType2Message(message)); } return response; } /** * Return the cipher for the specified key. * @param key The key. * @return Cipher The cipher. * @throws AuthenticationException If the cipher cannot be retrieved. */ private Cipher getCipher(byte[] key) throws AuthenticationException { try { final Cipher ecipher = Cipher.getInstance("DES/ECB/NoPadding"); key = setupKey(key); ecipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "DES")); return ecipher; } catch (NoSuchAlgorithmException e) { throw new AuthenticationException("DES encryption is not available.", e); } catch (InvalidKeyException e) { throw new AuthenticationException("Invalid key for DES encryption.", e); } catch (NoSuchPaddingException e) { throw new AuthenticationException( "NoPadding option for DES is not available.", e); } } /** * Adds parity bits to the key. * @param key56 The key * @return The modified key. */ private byte[] setupKey(byte[] key56) { byte[] key = new byte[8]; key[0] = (byte) ((key56[0] >> 1) & 0xff); key[1] = (byte) ((((key56[0] & 0x01) << 6) | (((key56[1] & 0xff) >> 2) & 0xff)) & 0xff); key[2] = (byte) ((((key56[1] & 0x03) << 5) | (((key56[2] & 0xff) >> 3) & 0xff)) & 0xff); key[3] = (byte) ((((key56[2] & 0x07) << 4) | (((key56[3] & 0xff) >> 4) & 0xff)) & 0xff); key[4] = (byte) ((((key56[3] & 0x0f) << 3) | (((key56[4] & 0xff) >> 5) & 0xff)) & 0xff); key[5] = (byte) ((((key56[4] & 0x1f) << 2) | (((key56[5] & 0xff) >> 6) & 0xff)) & 0xff); key[6] = (byte) ((((key56[5] & 0x3f) << 1) | (((key56[6] & 0xff) >> 7) & 0xff)) & 0xff); key[7] = (byte) (key56[6] & 0x7f); for (int i = 0; i < key.length; i++) { key[i] = (byte) (key[i] << 1); } return key; } /** * Encrypt the data. * @param key The key. * @param bytes The data * @return byte[] The encrypted data * @throws HttpException If {@link Cipher.doFinal(byte[])} fails */ private byte[] encrypt(byte[] key, byte[] bytes) throws AuthenticationException { Cipher ecipher = getCipher(key); try { byte[] enc = ecipher.doFinal(bytes); return enc; } catch (IllegalBlockSizeException e) { throw new AuthenticationException("Invalid block size for DES encryption.", e); } catch (BadPaddingException e) { throw new AuthenticationException("Data not padded correctly for DES encryption.", e); } } /** * Prepares the object to create a response of the given length. * @param length the length of the response to prepare. */ private void prepareResponse(int length) { currentResponse = new byte[length]; currentPosition = 0; } /** * Adds the given byte to the response. * @param b the byte to add. */ private void addByte(byte b) { currentResponse[currentPosition] = b; currentPosition++; } /** * Adds the given bytes to the response. * @param bytes the bytes to add. */ private void addBytes(byte[] bytes) { for (int i = 0; i < bytes.length; i++) { currentResponse[currentPosition] = bytes[i]; currentPosition++; } } /** * Returns the response that has been generated after shrinking the array if * required and base64 encodes the response. * @return The response as above. */ private String getResponse() { byte[] resp; if (currentResponse.length > currentPosition) { byte[] tmp = new byte[currentPosition]; for (int i = 0; i < currentPosition; i++) { tmp[i] = currentResponse[i]; } resp = tmp; } else { resp = currentResponse; } return EncodingUtil.getAsciiString(Base64.encodeBase64(resp)); } /** * Creates the first message (type 1 message) in the NTLM authentication sequence. * This message includes the user name, domain and host for the authentication session. * * @param host the computer name of the host requesting authentication. * @param domain The domain to authenticate with. * @return String the message to add to the HTTP request header. */ public String getType1Message(String host, String domain) { host = host.toUpperCase(); domain = domain.toUpperCase(); byte[] hostBytes = EncodingUtil.getBytes(host, DEFAULT_CHARSET); byte[] domainBytes = EncodingUtil.getBytes(domain, DEFAULT_CHARSET); int finalLength = 32 + hostBytes.length + domainBytes.length; prepareResponse(finalLength); // The initial id string. byte[] protocol = EncodingUtil.getBytes("NTLMSSP", DEFAULT_CHARSET); addBytes(protocol); addByte((byte) 0); // Type addByte((byte) 1); addByte((byte) 0); addByte((byte) 0); addByte((byte) 0); // Flags addByte((byte) 6); addByte((byte) 82); addByte((byte) 0); addByte((byte) 0); // Domain length (first time). int iDomLen = domainBytes.length; byte[] domLen = convertShort(iDomLen); addByte(domLen[0]); addByte(domLen[1]); // Domain length (second time). addByte(domLen[0]); addByte(domLen[1]); // Domain offset. byte[] domOff = convertShort(hostBytes.length + 32); addByte(domOff[0]); addByte(domOff[1]); addByte((byte) 0); addByte((byte) 0); // Host length (first time). byte[] hostLen = convertShort(hostBytes.length); addByte(hostLen[0]); addByte(hostLen[1]); // Host length (second time). addByte(hostLen[0]); addByte(hostLen[1]);
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -