| // 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); |
| } |
| |
| } |