| // 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. | |
| package rdpclient.rdp; | |
| import streamer.ByteBuffer; | |
| import streamer.Element; | |
| import streamer.Link; | |
| import streamer.OneTimeSwitch; | |
| import streamer.Pipeline; | |
| import streamer.PipelineImpl; | |
| import streamer.debug.MockSink; | |
| import streamer.debug.MockSource; | |
| /** | |
| * @see http://msdn.microsoft.com/en-us/library/cc240470.aspx | |
| * @see http://msdn.microsoft.com/en-us/library/cc240663.aspx | |
| */ | |
| public class ClientX224ConnectionRequestPDU extends OneTimeSwitch { | |
| public static final int X224_TPDU_CONNECTION_REQUEST = 0xe0; | |
| public static final int X224_TPDU_CONNECTION_CONFIRM = 0xd0; | |
| public static final int X224_TPDU_DISCONNECTION_REQUEST = 0x80; | |
| public static final int X224_TPDU_DISCONNECTION_CONFIRM = 0xc0; | |
| public static final int X224_TPDU_EXPEDITED_DATA = 0x10; | |
| public static final int X224_TPDU_DATA_ACKNOWLEDGE = 0x61; | |
| public static final int X224_TPDU_EXPEDITET_ACKNOWLEDGE = 0x40; | |
| public static final int X224_TPDU_REJECT = 0x51; | |
| public static final int X224_TPDU_ERROR = 0x70; | |
| public static final int X224_TPDU_PROTOCOL_IDENTIFIER = 0x01; | |
| /** | |
| * Reconnection cookie. | |
| */ | |
| protected String userName; | |
| /** | |
| * Protocol to use: RDP_NEG_REQ_PROTOCOL_SSL or RDP_NEG_REQ_PROTOCOL_HYBRID. | |
| */ | |
| protected int protocol; | |
| public ClientX224ConnectionRequestPDU(String id, String userName, int protocol) { | |
| super(id); | |
| this.userName = userName; | |
| this.protocol = protocol; | |
| } | |
| @Override | |
| protected void handleOneTimeData(ByteBuffer buf, Link link) { | |
| if (buf == null) | |
| return; | |
| throw new RuntimeException("Unexpected packet: " + buf + "."); | |
| } | |
| @Override | |
| protected void onStart() { | |
| super.onStart(); | |
| // Length of packet without length field | |
| int length = 33 + userName.length(); | |
| ByteBuffer buf = new ByteBuffer(length, true); | |
| // Type (high nibble) = 0xe = CR TPDU; credit (low nibble) = 0 | |
| buf.writeByte(X224_TPDU_CONNECTION_REQUEST); | |
| buf.writeShort(0); // Destination reference = 0 | |
| buf.writeShort(0); // Source reference = 0 | |
| buf.writeByte(0); // Class and options = 0 | |
| buf.writeString("Cookie: mstshash=" + userName + "\r\n", RdpConstants.CHARSET_8); // Cookie | |
| // RDP_NEG_REQ::type | |
| buf.writeByte(RdpConstants.RDP_NEG_REQ_TYPE_NEG_REQ); | |
| // RDP_NEG_REQ::flags (0) | |
| buf.writeByte(RdpConstants.RDP_NEG_REQ_FLAGS); | |
| // RDP_NEG_REQ::length (constant: 8) short int in LE format | |
| buf.writeByte(0x08); | |
| buf.writeByte(0x00); | |
| // RDP_NEG_REQ: Requested protocols: PROTOCOL_SSL | |
| buf.writeIntLE(protocol); | |
| // Calculate length of packet and prepend it to buffer | |
| ByteBuffer data = new ByteBuffer(5); | |
| // Write length | |
| data.writeVariableIntLE(buf.length); | |
| // Reset length of buffer to actual length of data written | |
| data.length = data.cursor; | |
| buf.prepend(data); | |
| data.unref(); | |
| pushDataToOTOut(buf); | |
| switchOff(); | |
| } | |
| /** | |
| * Example. | |
| * | |
| * @see http://msdn.microsoft.com/en-us/library/cc240842.aspx | |
| * @see http://msdn.microsoft.com/en-us/library/cc240500.aspx | |
| */ | |
| public static void main(String args[]) { | |
| // System.setProperty("streamer.Link.debug", "true"); | |
| System.setProperty("streamer.Element.debug", "true"); | |
| // System.setProperty("streamer.Pipeline.debug", "true"); | |
| String cookie = "eltons"; | |
| byte[] packet = new byte[] { | |
| 0x03, // TPKT Header: version = 3 | |
| 0x00, // TPKT Header: Reserved = 0 | |
| 0x00, // TPKT Header: Packet length - high part | |
| 0x2c, // TPKT Header: Packet length - low part (total = 44 bytes) | |
| 0x27, // X.224: Length indicator (39 bytes) | |
| (byte)0xe0, // X.224: Type (high nibble) = 0xe = CR TPDU; | |
| // credit (low nibble) = 0 | |
| 0x00, 0x00, // X.224: Destination reference = 0 | |
| 0x00, 0x00, // X.224: Source reference = 0 | |
| 0x00, // X.224: Class and options = 0 | |
| 'C', 'o', 'o', 'k', 'i', 'e', ':', ' ', 'm', 's', 't', 's', 'h', 'a', 's', 'h', '=', 'e', 'l', 't', 'o', 'n', 's', // "Cookie: mstshash=eltons" | |
| '\r', '\n', // -Cookie terminator sequence | |
| 0x01, // RDP_NEG_REQ::type (TYPE_RDP_NEG_REQ) | |
| 0x00, // RDP_NEG_REQ::flags (0) | |
| 0x08, 0x00, // RDP_NEG_REQ::length (8 bytes) | |
| 0x01, 0x00, 0x00, 0x00 // RDP_NEG_REQ: Requested protocols | |
| // (PROTOCOL_SSL in little endian format) | |
| }; | |
| MockSource source = new MockSource("source", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3})); | |
| Element cr = new ClientX224ConnectionRequestPDU("cr", cookie, RdpConstants.RDP_NEG_REQ_PROTOCOL_SSL); | |
| Element tpkt = new ClientTpkt("tpkt"); | |
| Element sink = new MockSink("sink", ByteBuffer.convertByteArraysToByteBuffers(packet)); | |
| Element mainSink = new MockSink("mainSink", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3})); | |
| Pipeline pipeline = new PipelineImpl("test"); | |
| pipeline.add(source, cr, tpkt, sink, mainSink); | |
| pipeline.link("source", "cr", "mainSink"); | |
| pipeline.link("cr >" + OTOUT, "tpkt", "sink"); | |
| pipeline.runMainLoop("source", STDOUT, false, false); | |
| } | |
| } |