⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 secure.java

📁 cygwin 是一个在windows平台上运行的unix模拟环境
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/* Secure.java
 * Component: ProperJavaRDP
 * 
 * Revision: $Revision: 1.7 $
 * Author: $Author: telliott $
 * Date: $Date: 2005/09/27 14:15:39 $
 *
 * Copyright (c) 2005 Propero Limited
 *
 * Purpose: Secure layer of communication
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA
 * 
 * (See gpl.txt for details of the GNU General Public License.)
 * 
 */
package net.propero.rdp;
import java.io.*;
import java.util.*;
import java.net.*;
import java.math.*;
import org.apache.log4j.Logger;

import net.propero.rdp.crypto.*;
import net.propero.rdp.rdp5.VChannels;

public class Secure {
	boolean readCert = false;
	static Logger logger = Logger.getLogger(Secure.class);
	private Licence licence = new Licence(this);
    /* constants for the secure layer */
    public static final int SEC_ENCRYPT = 0x0008;
    public static final int SEC_LOGON_INFO = 0x0040;

    static final int SEC_RANDOM_SIZE = 32;
    static final int SEC_MODULUS_SIZE = 64;
    static final int SEC_PADDING_SIZE = 8;
    private static final int SEC_EXPONENT_SIZE = 4;

    private static final int SEC_CLIENT_RANDOM = 0x0001;
    static final int SEC_LICENCE_NEG = 0x0080;

    private static final int SEC_TAG_SRV_INFO = 0x0c01;
    private static final int SEC_TAG_SRV_CRYPT = 0x0c02;
    private static final int SEC_TAG_SRV_3 = 0x0c03;
    private static final int SEC_TAG_SRV_CHANNELS = 0x0c03;

    private static final int SEC_TAG_CLI_INFO = 0xc001;
    private static final int SEC_TAG_CLI_CRYPT = 0xc002;
    private static final int SEC_TAG_CLI_CHANNELS = 0xc003;
    private static final int SEC_TAG_CLI_4 = 0xc004;

    private static final int SEC_TAG_PUBKEY = 0x0006;
    private static final int SEC_TAG_KEYSIG = 0x0008;

    private static final int SEC_RSA_MAGIC = 0x31415352; /* RSA1 */
 
    private MCS McsLayer=null;
 //   private String hostname=null;
   // private String username=null;
    boolean licenceIssued = false;
    private RC4 rc4_enc = null;
    private RC4 rc4_dec = null;
    private RC4 rc4_update = null;
    private BlockMessageDigest sha1 = null;
    private BlockMessageDigest md5 = null;
    private int keylength = 0;
    private int enc_count = 0;
    private int dec_count = 0;
    
    private byte[] sec_sign_key = null;

    private byte[] sec_decrypt_key = null;

    private byte[] sec_encrypt_key = null;

    private byte[] sec_decrypt_update_key = null;

    private byte[] sec_encrypt_update_key = null;
    private byte[] sec_crypted_random=null;

    private byte[] exponent = null;
    private byte[] modulus = null;
    private byte[] server_random = null;
    private byte[] client_random = new byte[SEC_RANDOM_SIZE];

    private static final byte[] pad_54 = {
	54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
	54, 54, 54,
	54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
	54, 54, 54
    };
    
    private static final byte[] pad_92 = {
	92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
	92, 92, 92, 92, 92, 92, 92,
	92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
	92, 92, 92, 92, 92, 92, 92
    };
    
    private VChannels channels;
    
    /**
     * Initialise Secure layer of communications
     * @param channels Virtual channels for this connection
     */
    public Secure(VChannels channels) {
        this.channels = channels;
	McsLayer = new MCS(channels);
	Common.mcs = McsLayer;
	rc4_dec = new RC4();
	rc4_enc = new RC4();
	rc4_update = new RC4();
	sha1 = new SHA1();
	md5 = new MD5();
	sec_sign_key = new byte[16]; // changed from 8 - rdesktop 1.2.0
	sec_decrypt_key = new byte[16];
	sec_encrypt_key = new byte[16];
	sec_decrypt_update_key = new byte[16]; // changed from 8 - rdesktop 1.2.0
	sec_encrypt_update_key = new byte[16]; // changed from 8 - rdesktop 1.2.0
	sec_crypted_random = new byte[64];
	
    }
    
    /**
     * Connect to server
     * @param host Address of server to connect to
     * @param port Port to connect to
     * @throws UnknownHostException
     * @throws IOException
     * @throws RdesktopException
     * @throws SocketException
     * @throws CryptoException
     * @throws OrderException
     */
    public void connect(InetAddress host, int port) throws UnknownHostException, IOException, RdesktopException, SocketException, CryptoException, OrderException {
	if(Options.hostname==""){
		InetAddress localhost = InetAddress.getLocalHost();
		String name = localhost.getHostName();
		StringTokenizer tok = new StringTokenizer(name, ".");
		Options.hostname = tok.nextToken();
		Options.hostname.trim();
	}

	RdpPacket_Localised mcs_data = this.sendMcsData();
	McsLayer.connect(host, port, mcs_data);
	
	this.processMcsData(mcs_data);

	if (Constants.encryption) {
	    this.establishKey();  
	}
    }
    
    /**
     * Connect to server on default port
     * @param host Server to connect to
     * @throws IOException
     * @throws RdesktopException
     * @throws OrderException
     * @throws CryptoException
     */
    public void connect(InetAddress host) throws IOException, RdesktopException, OrderException, CryptoException {
	this.connect(host, Options.port);
    }
    
    /**
     * Close connection
     */
    public void disconnect() {
	McsLayer.disconnect();
	}  

    /**
     * Construct MCS data, including channel, encryption and display options
     * @return Packet populated with MCS data
     */
    public RdpPacket_Localised sendMcsData() {
    	logger.debug("Secure.sendMcsData");
    
    RdpPacket_Localised buffer= new RdpPacket_Localised(512);
        
    int hostlen = 2 * (Options.hostname==null ? 0 : Options.hostname.length());
        
    if (hostlen > 30) { hostlen=30;}
            
	int length = 158;
	if(Options.use_rdp5) length += 76 + 12 + 4;

	if (Options.use_rdp5 && (channels.num_channels() > 0))
		length += channels.num_channels() * 12 + 8;

	buffer.setBigEndian16(5);	/* unknown */
	buffer.setBigEndian16(0x14);
	buffer.set8(0x7c);
	buffer.setBigEndian16(1);

	buffer.setBigEndian16(length | 0x8000);	// remaining length

	buffer.setBigEndian16(8);	// length?
	buffer.setBigEndian16(16);
	buffer.set8(0);
	buffer.setLittleEndian16(0xc001);
	buffer.set8(0);

	buffer.setLittleEndian32(0x61637544);	// "Duca" ?!
	buffer.setBigEndian16(length-14 | 0x8000);	// remaining length

	// Client information
	buffer.setLittleEndian16(SEC_TAG_CLI_INFO);
	buffer.setLittleEndian16(Options.use_rdp5 ? 212 : 136);	// length
	buffer.setLittleEndian16(Options.use_rdp5 ? 4 : 1);
	buffer.setLittleEndian16(8);
	buffer.setLittleEndian16(Options.width); 
	buffer.setLittleEndian16(Options.height); 
	buffer.setLittleEndian16(0xca01);
	buffer.setLittleEndian16(0xaa03);
	buffer.setLittleEndian32(Options.keylayout);
	buffer.setLittleEndian32(Options.use_rdp5 ? 2600 : 419); // or 0ece	// client build? we are 2600 compatible :-)

	/* Unicode name of client, padded to 32 bytes */
    buffer.outUnicodeString(Options.hostname.toUpperCase(), hostlen);
	buffer.incrementPosition(30 - hostlen);

	buffer.setLittleEndian32(4);
	buffer.setLittleEndian32(0);
	buffer.setLittleEndian32(12);
	buffer.incrementPosition(64);	/* reserved? 4 + 12 doublewords */

    buffer.setLittleEndian16(0xca01); // out_uint16_le(s, 0xca01);
	buffer.setLittleEndian16(Options.use_rdp5 ? 1 : 0);
    
	if(Options.use_rdp5){
	buffer.setLittleEndian32(0); // out_uint32(s, 0);
	buffer.set8(Options.server_bpp); // out_uint8(s, g_server_bpp);
	buffer.setLittleEndian16(0x0700); // out_uint16_le(s, 0x0700);
	buffer.set8(0); // out_uint8(s, 0);
	buffer.setLittleEndian32(1); // out_uint32_le(s, 1);
	
	buffer.incrementPosition(64);

	buffer.setLittleEndian16(SEC_TAG_CLI_4); // out_uint16_le(s, SEC_TAG_CLI_4);
	buffer.setLittleEndian16(12); // out_uint16_le(s, 12);
	buffer.setLittleEndian32(Options.console_session ? 0xb : 0xd); // out_uint32_le(s, g_console_session ? 0xb : 9);
	buffer.setLittleEndian32(0); // out_uint32(s, 0);
    }
    
	// Client encryption settings //
	buffer.setLittleEndian16(SEC_TAG_CLI_CRYPT);
	buffer.setLittleEndian16(Options.use_rdp5 ? 12 : 8);	// length
    
    //if(Options.use_rdp5) buffer.setLittleEndian32(Options.encryption ? 0x1b : 0);	// 128-bit encryption supported
    //else
    buffer.setLittleEndian32(Options.encryption ? (Options.console_session ? 0xb : 0x3) : 0);
    
	if(Options.use_rdp5) buffer.setLittleEndian32(0); // unknown
	
	if (Options.use_rdp5 && (channels.num_channels() > 0))
	{
	    logger.debug(("num_channels is " + channels.num_channels()));
		buffer.setLittleEndian16(SEC_TAG_CLI_CHANNELS); // out_uint16_le(s, SEC_TAG_CLI_CHANNELS);
		buffer.setLittleEndian16(channels.num_channels() * 12 + 8); // out_uint16_le(s, g_num_channels * 12 + 8);	// length 
		buffer.setLittleEndian32(channels.num_channels()); // out_uint32_le(s, g_num_channels);	// number of virtual channels 
		for (int i = 0; i < channels.num_channels(); i++)
		{
			logger.debug(("Requesting channel " + channels.channel(i).name()));
			buffer.out_uint8p(channels.channel(i).name(), 8); // out_uint8a(s, g_channels[i].name, 8);
			buffer.setBigEndian32(channels.channel(i).flags()); // out_uint32_be(s, g_channels[i].flags);
		}
	}
	
	buffer.markEnd();
	return buffer;
    }

    /**
     * Handle MCS info from server (server info, encryption info and channel information)
     * @param mcs_data Data received from server
     */    
    public void processMcsData(RdpPacket_Localised mcs_data) throws RdesktopException, CryptoException {
	logger.debug("Secure.processMcsData");
	int tag=0, len=0, length=0, nexttag=0;
	
	mcs_data.incrementPosition(21); // header (T.124 stuff, probably)
	len=mcs_data.get8();

	if ((len&0x00000080)!=0) {
	    len=mcs_data.get8();
	}

	while (mcs_data.getPosition() < mcs_data.getEnd()) {
	    tag=mcs_data.getLittleEndian16();
	    length=mcs_data.getLittleEndian16();

	    if (length <=4) return;
	    
	    nexttag=mcs_data.getPosition() + length -4;
	    
	    switch(tag) {
	    case (Secure.SEC_TAG_SRV_INFO): 
	    processSrvInfo(mcs_data);
	    break;
	    case (Secure.SEC_TAG_SRV_CRYPT):
		this.processCryptInfo(mcs_data);
		break;
		case (Secure.SEC_TAG_SRV_CHANNELS):
			/* FIXME: We should parse this information and
			   use it to map RDP5 channels to MCS 
			   channels */
			break;

	    default: throw new RdesktopException("Not implemented! Tag:"+tag+"not recognized!");
	    }

	    mcs_data.setPosition(nexttag);
	}
    }

    /**
     * Read server info from packet, specifically the RDP version of the server
     * @param mcs_data Packet to read
     */
	private void processSrvInfo(RdpPacket_Localised mcs_data) {
		Options.server_rdp_version = mcs_data.getLittleEndian16(); // in_uint16_le(s, g_server_rdp_version);
		logger.debug(("Server RDP version is " +  Options.server_rdp_version));
		if (1 == Options.server_rdp_version)
			Options.use_rdp5 = false;
	}

    public void establishKey()throws RdesktopException, IOException, CryptoException {
	int length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;
	int flags = SEC_CLIENT_RANDOM;
	RdpPacket_Localised buffer = this.init(flags, 76);

	buffer.setLittleEndian32(length);

	buffer.copyFromByteArray(this.sec_crypted_random, 0, buffer.getPosition(), SEC_MODULUS_SIZE);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -