You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by de...@apache.org on 2013/12/23 10:13:08 UTC

[14/22] CLOUDSTACK-5344: Update to allow rdp console to access hyper-v vm virtual framebuffer.

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/hyperv/ClientPreConnectionBlob.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/hyperv/ClientPreConnectionBlob.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/hyperv/ClientPreConnectionBlob.java
new file mode 100755
index 0000000..639ca50
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/hyperv/ClientPreConnectionBlob.java
@@ -0,0 +1,121 @@
+// 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.hyperv;
+
+import rdpclient.rdp.RdpConstants;
+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;
+
+/**
+ * For HyperV server, client must send VM ID before any other packet.
+ */
+public class ClientPreConnectionBlob extends OneTimeSwitch {
+
+    protected String data;
+
+    public ClientPreConnectionBlob(String id, String data) {
+        super(id);
+        this.data = data;
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        throw new RuntimeException("This element only sends data. This method must not be called. Unexpected packet: " + buf + ".");
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+        sendPreConnectionBlobData(data);
+    }
+
+    protected void sendPreConnectionBlobData(String data) {
+        // Length of packet
+        ByteBuffer buf = new ByteBuffer(1024, true);
+
+        // Header
+        buf.writeBytes(new byte[] {(byte)0x5e, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02,
+                (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,});
+
+        // Length of string in wide characters + two wide \0 (LE)
+        buf.writeShortLE(data.length() + 2);
+
+        // Wide string + two wide '\0' characters
+        buf.writeString(data + "\0\0", RdpConstants.CHARSET_16);
+
+        // Trim buffer to actual length of data written
+        buf.trimAtCursor();
+
+        pushDataToOTOut(buf);
+
+        switchOff();
+    }
+
+    /**
+     * Example.
+     */
+    public static void main(String[] args) {
+        // System.setProperty("streamer.Link.debug", "true");
+        System.setProperty("streamer.Element.debug", "true");
+        // System.setProperty("streamer.Pipeline.debug", "true");
+
+        /* @formatter:off */
+    byte[] packet = new byte[] {
+        // Header
+        (byte) 0x5e, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00, (byte) 0x02, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+        
+        // Length of string in wide characters + two wide \0 (LE)
+        (byte) 0x26, (byte) 0x00,
+
+        // Wide string
+        (byte) 0x33, (byte) 0x00, (byte) 0x39, (byte) 0x00, (byte) 0x34, (byte) 0x00, (byte) 0x31, (byte) 0x00, (byte) 0x38, (byte) 0x00, (byte) 0x46,
+        (byte) 0x00, (byte) 0x39, (byte) 0x00, (byte) 0x30, (byte) 0x00, (byte) 0x2d, (byte) 0x00, (byte) 0x36, (byte) 0x00, (byte) 0x44, (byte) 0x00,
+        (byte) 0x30, (byte) 0x00, (byte) 0x33, (byte) 0x00, (byte) 0x2d, (byte) 0x00, (byte) 0x34, (byte) 0x00, (byte) 0x36, (byte) 0x00, (byte) 0x38,
+        (byte) 0x00, (byte) 0x45, (byte) 0x00, (byte) 0x2d, (byte) 0x00, (byte) 0x42, (byte) 0x00, (byte) 0x37, (byte) 0x00, (byte) 0x39, (byte) 0x00,
+        (byte) 0x36, (byte) 0x00, (byte) 0x2d, (byte) 0x00, (byte) 0x39, (byte) 0x00, (byte) 0x31, (byte) 0x00, (byte) 0x43, (byte) 0x00, (byte) 0x36,
+        (byte) 0x00, (byte) 0x30, (byte) 0x00, (byte) 0x44, (byte) 0x00, (byte) 0x44, (byte) 0x00, (byte) 0x36, (byte) 0x00, (byte) 0x36, (byte) 0x00,
+        (byte) 0x35, (byte) 0x00, (byte) 0x33, (byte) 0x00, (byte) 0x41, (byte) 0x00,
+
+        // Two wide \0
+        (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+    };
+    /* @formatter:on */
+
+        MockSource source = new MockSource("source", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3}));
+        Element pcb = new ClientPreConnectionBlob("pcb", "39418F90-6D03-468E-B796-91C60DD6653A");
+        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, pcb, sink, mainSink);
+        pipeline.link("source", "pcb", "mainSink");
+        pipeline.link("pcb >" + OTOUT, "sink");
+        pipeline.runMainLoop("source", STDOUT, false, false);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/ClientNtlmsspNegotiate.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/ClientNtlmsspNegotiate.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/ClientNtlmsspNegotiate.java
new file mode 100755
index 0000000..d32c8ca
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/ClientNtlmsspNegotiate.java
@@ -0,0 +1,178 @@
+// 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.ntlmssp;
+
+import common.asn1.Tag;
+
+import rdpclient.ntlmssp.asn1.NegoItem;
+import rdpclient.ntlmssp.asn1.TSRequest;
+import rdpclient.rdp.RdpConstants;
+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/cc236641.aspx
+ */
+public class ClientNtlmsspNegotiate extends OneTimeSwitch {
+
+    /**
+     * The set of client configuration flags (section 2.2.2.5) that specify the
+     * full set of capabilities of the client.
+     */
+    public NegoFlags clientConfigFlags = new NegoFlags().set_NEGOTIATE_56().set_NEGOTIATE_KEY_EXCH().set_NEGOTIATE_128().set_NEGOTIATE_VERSION()
+            .set_NEGOTIATE_EXTENDED_SESSION_SECURITY().set_NEGOTIATE_ALWAYS_SIGN().set_NEGOTIATE_NTLM().set_NEGOTIATE_LM_KEY().set_NEGOTIATE_SEAL()
+            .set_NEGOTIATE_SIGN().set_REQUEST_TARGET().set_NEGOTIATE_OEM().set_NEGOTIATE_UNICODE();
+
+    protected NtlmState ntlmState;
+
+    public ClientNtlmsspNegotiate(String id, NtlmState state) {
+        super(id);
+        this.ntlmState = state;
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        throw new RuntimeException("Unexpected packet: " + buf + ".");
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+
+        ByteBuffer negoToken = generateNegotiateMessage();
+        ntlmState.negotiateMessage = negoToken.toByteArray(); // Store message for MIC calculation in AUTH message
+
+        // Length of packet
+        ByteBuffer buf = new ByteBuffer(1024, true);
+
+        TSRequest tsRequest = new TSRequest("TSRequest");
+        tsRequest.version.value = 2L;
+        NegoItem negoItem = new NegoItem("NegoItem");
+        negoItem.negoToken.value = negoToken;
+        tsRequest.negoTokens.tags = new Tag[] {negoItem};
+
+        tsRequest.writeTag(buf);
+
+        // Trim buffer to actual length of data written
+        buf.trimAtCursor();
+
+        pushDataToOTOut(buf);
+
+        switchOff();
+    }
+
+    private ByteBuffer generateNegotiateMessage() {
+        ByteBuffer buf = new ByteBuffer(1024);
+
+        // Signature
+        buf.writeString("NTLMSSP", RdpConstants.CHARSET_8);
+        buf.writeByte(0);
+
+        // Message type
+        buf.writeIntLE(NtlmConstants.NEGOTIATE);
+
+        buf.writeIntLE(clientConfigFlags.value); // Flags
+
+        // If the NTLMSSP_NEGOTIATE_VERSION flag is set by the client application,
+        // the Version field MUST be set to the current version (section 2.2.2.10),
+        // the DomainName field MUST be set to a zero-length string, and the
+        // Workstation field MUST be set to a zero-length string.
+
+        // Domain: ""
+        buf.writeShortLE(0); // Length
+        buf.writeShortLE(0); // Allocated space
+        buf.writeIntLE(0); // Offset
+
+        // Workstation: ""
+        buf.writeShortLE(0); // Length
+        buf.writeShortLE(0); // Allocated space
+        buf.writeIntLE(0); // Offset
+
+        // OS Version: 6.1 (Build 7601); NTLM Current Revision 15
+        buf.writeBytes(new byte[] {(byte)0x06, (byte)0x01, (byte)0xb1, (byte)0x1d, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0f});
+
+        // Trim buffer to actual length of data written
+        buf.trimAtCursor();
+
+        return buf;
+    }
+
+    /**
+     * Example.
+     */
+    public static void main(String args[]) {
+        // System.setProperty("streamer.Link.debug", "true");
+        System.setProperty("streamer.Element.debug", "true");
+        // System.setProperty("streamer.Pipeline.debug", "true");
+
+        /* @formatter:off */
+    byte[] packet = new byte[] {
+          // CredSSP BER header:
+
+          (byte)0x30, // Sequence
+          (byte)0x37, // Length, 55 bytes
+
+          (byte)0xa0, (byte)0x03, // TAG: [0] (constructed) LEN: 3 byte
+          (byte)0x02, (byte)0x01, (byte)0x02, // Version: (int, 1 byte, 0x02)
+
+          // Sequence of sequence
+          (byte)0xa1, (byte)0x30, // TAG: [1] (constructed) LEN: 48 bytes
+          (byte)0x30, (byte)0x2e, // TAG: [UNIVERSAL 16] (constructed) "SEQUENCE" LEN: 46 bytes
+          (byte)0x30, (byte)0x2c, // TAG: [UNIVERSAL 16] (constructed) "SEQUENCE" LEN: 44 bytes
+          (byte)0xa0, (byte)0x2a, // TAG: [0] (constructed) LEN: 42 bytes
+
+
+          (byte)0x04, (byte)0x28, // TAG: [UNIVERSAL 4] (primitive) "OCTET STRING" LEN: 40 bytes
+
+          // NTLM negotiate request
+
+          (byte)0x4e, (byte)0x54, (byte)0x4c, (byte)0x4d, (byte)0x53, (byte)0x53, (byte)0x50, (byte)0x00, // "NTLMSSP\0"
+
+          (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, // Message type: NEGOTIATE (0x1, LE) 
+
+          (byte)0xb7, (byte)0x82, (byte)0x08, (byte)0xe2, // Flags: 0xe20882b7 (LE)
+
+          (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Domain (security buffer, 8bit, 8 bytes): length: 0x0000 (LE), allocated space: 0x0000 (LE), offset: 0x00000000 (LE)
+          (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, // Workstation  (security buffer, 8bit, 8 bytes): length: 0x0000 (LE), allocated space: 0x0000 (LE), offset: 0x00000000 (LE)
+          (byte)0x06, (byte)0x01, (byte)0xb1, (byte)0x1d, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0f, // OS Version: 6.1 (Build 7601); NTLM Current Revision 15, 8 bytes
+        
+    };
+    /* @formatter:on */
+
+        NtlmState state = new NtlmState();
+
+        MockSource source = new MockSource("source", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3}));
+        Element ntlmssp_negotiate = new ClientNtlmsspNegotiate("ntlmssp_negotiate", state);
+        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, ntlmssp_negotiate, sink, mainSink);
+        pipeline.link("source", "ntlmssp_negotiate", "mainSink");
+        pipeline.link("ntlmssp_negotiate >" + OTOUT, "sink");
+        pipeline.runMainLoop("source", STDOUT, false, false);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/ClientNtlmsspPubKeyAuth.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/ClientNtlmsspPubKeyAuth.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/ClientNtlmsspPubKeyAuth.java
new file mode 100755
index 0000000..3d9e0c5
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/ClientNtlmsspPubKeyAuth.java
@@ -0,0 +1,681 @@
+// 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.ntlmssp;
+
+import java.nio.charset.Charset;
+
+import rdpclient.ntlmssp.asn1.NegoItem;
+import rdpclient.ntlmssp.asn1.SubjectPublicKeyInfo;
+import rdpclient.ntlmssp.asn1.TSRequest;
+import rdpclient.rdp.RdpConstants;
+import streamer.ByteBuffer;
+import streamer.Element;
+import streamer.Link;
+import streamer.OneTimeSwitch;
+import streamer.Pipeline;
+import streamer.PipelineImpl;
+import streamer.debug.Dumper;
+import streamer.debug.MockSink;
+import streamer.debug.MockSource;
+import streamer.ssl.SSLState;
+
+import common.asn1.Tag;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc236643.aspx
+ */
+public class ClientNtlmsspPubKeyAuth extends OneTimeSwitch implements NtlmConstants, Dumper {
+
+    /**
+     * Offset of first byte of allocated block after NTLMSSP header and block
+     * descriptors.
+     */
+    private static final int BLOCKS_OFFSET = 88;
+
+    protected NtlmState ntlmState;
+    protected SSLState sslState;
+
+    protected String targetDomain;
+    protected String user;
+    protected String password;
+    protected String workstation;
+    protected String serverHostName;
+
+    public ClientNtlmsspPubKeyAuth(String id, NtlmState ntlmState, SSLState sslState, String serverHostName, String targetDomain, String workstation,
+            String user, String password) {
+        super(id);
+        this.ntlmState = ntlmState;
+        this.sslState = sslState;
+        this.serverHostName = serverHostName;
+        this.targetDomain = targetDomain;
+        this.workstation = workstation;
+        this.user = user;
+        this.password = password;
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        throw new RuntimeException("Unexpected packet: " + buf + ".");
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+
+        /*
+         * @see
+         * http://blogs.msdn.com/b/openspecification/archive/2010/04/20/ntlm-keys
+         * -and-sundry-stuff.aspx
+         */
+        ntlmState.domain = this.targetDomain;
+        ntlmState.user = this.user;
+        ntlmState.password = this.password;
+        ntlmState.workstation = this.workstation;
+        ntlmState.generateServicePrincipalName(serverHostName);
+        ntlmState.ntlm_construct_authenticate_target_info();
+        ntlmState.ntlm_generate_timestamp();
+        ntlmState.ntlm_generate_client_challenge();
+        ntlmState.ntlm_compute_lm_v2_response();
+        ntlmState.ntlm_compute_ntlm_v2_response();
+        ntlmState.ntlm_generate_key_exchange_key();
+        ntlmState.ntlm_generate_random_session_key();
+        ntlmState.ntlm_generate_exported_session_key();
+        ntlmState.ntlm_encrypt_random_session_key();
+        ntlmState.ntlm_init_rc4_seal_states();
+
+        ByteBuffer authenticateMessage = generateAuthenticateMessage(ntlmState);
+        ByteBuffer messageSignatureAndEncryptedServerPublicKey = generateMessageSignatureAndEncryptedServerPublicKey(ntlmState);
+
+        // Length of packet
+        ByteBuffer buf = new ByteBuffer(4096, true);
+
+        TSRequest tsRequest = new TSRequest("TSRequest");
+        tsRequest.version.value = 2L;
+        NegoItem negoItem = new NegoItem("NegoItem");
+        negoItem.negoToken.value = authenticateMessage;
+
+        tsRequest.negoTokens.tags = new Tag[] {negoItem};
+
+        tsRequest.pubKeyAuth.value = messageSignatureAndEncryptedServerPublicKey;
+
+        tsRequest.writeTag(buf);
+
+        // Trim buffer to actual length of data written
+        buf.trimAtCursor();
+
+        pushDataToOTOut(buf);
+
+        switchOff();
+    }
+
+    private byte[] getServerPublicKey() {
+        // SSL certificate public key with algorithm
+        ByteBuffer subjectPublicKeyInfo = new ByteBuffer(sslState.serverCertificateSubjectPublicKeyInfo);
+
+        // Parse subjectPublicKeyInfo
+        SubjectPublicKeyInfo parser = new SubjectPublicKeyInfo("SubjectPublicKeyInfo");
+        parser.readTag(subjectPublicKeyInfo);
+
+        // Copy subjectPublicKey subfield to separate byte buffer
+        ByteBuffer subjectPublicKey = new ByteBuffer(subjectPublicKeyInfo.length);
+        parser.subjectPublicKey.writeTag(subjectPublicKey);
+
+        subjectPublicKeyInfo.unref();
+        subjectPublicKey.trimAtCursor();
+
+        // Skip tag:
+        // 03 82 01 0f (tag) 00 (padding byte)
+        subjectPublicKey.trimHeader(5);// FIXME: parse it properly
+        // * DEBUG */System.out.println("DEBUG: subjectPublicKey:\n" +
+        // subjectPublicKey.dump());
+
+        ntlmState.subjectPublicKey = subjectPublicKey.toByteArray();
+
+        return ntlmState.subjectPublicKey;
+    }
+
+    /**
+     * The client encrypts the public key it received from the server (contained
+     * in the X.509 certificate) in the TLS handshake from step 1, by using the
+     * confidentiality support of SPNEGO.
+     * 
+     * The public key that is encrypted is the ASN.1-encoded SubjectPublicKey
+     * sub-field of SubjectPublicKeyInfo from the X.509 certificate, as specified
+     * in [RFC3280] section 4.1. The encrypted key is encapsulated in the
+     * pubKeyAuth field of the TSRequest structure and is sent over the TLS
+     * channel to the server.
+     */
+    private ByteBuffer generateMessageSignatureAndEncryptedServerPublicKey(NtlmState ntlmState) {
+        return new ByteBuffer(ntlmState.ntlm_EncryptMessage(getServerPublicKey()));
+    }
+
+    public static ByteBuffer generateAuthenticateMessage(NtlmState ntlmState) {
+
+        // Allocate memory for blocks from given fixed offset
+        int blocksCursor = BLOCKS_OFFSET;
+
+        ByteBuffer buf = new ByteBuffer(4096);
+
+        // Signature: "NTLMSSP\0"
+        buf.writeString(NTLMSSP, RdpConstants.CHARSET_8);
+        buf.writeByte(0);
+
+        // NTLM Message Type: NTLMSSP_AUTH (0x00000003)
+        buf.writeIntLE(NtlmConstants.NTLMSSP_AUTH);
+
+        // Although the protocol allows authentication to succeed if the client
+        // provides either LmChallengeResponse or NtChallengeResponse, Windows
+        // implementations provide both.
+
+        // LM V2 response
+        blocksCursor = writeBlock(buf, ntlmState.lmChallengeResponse, blocksCursor);
+
+        // NT v2 response
+        blocksCursor = writeBlock(buf, ntlmState.ntChallengeResponse, blocksCursor);
+
+        // DomainName
+        blocksCursor = writeStringBlock(buf, ntlmState.domain, blocksCursor, RdpConstants.CHARSET_16);
+
+        // UserName
+        blocksCursor = writeStringBlock(buf, ntlmState.user, blocksCursor, RdpConstants.CHARSET_16);
+
+        // Workstation
+        blocksCursor = writeStringBlock(buf, ntlmState.workstation, blocksCursor, RdpConstants.CHARSET_16);
+
+        // EncryptedRandomSessionKey, 16 bytes
+        blocksCursor = writeBlock(buf, ntlmState.encryptedRandomSessionKey, blocksCursor);
+
+        // NegotiateFlags (4 bytes): In connection-oriented mode, a NEGOTIATE
+        // structure that contains the set of bit flags (section 2.2.2.5) negotiated
+        // in the previous messages.
+        buf.writeIntLE(/*ntlmState.negotiatedFlags.value*/0xe288b235); // FIXME: remove hardcoded value
+
+        buf.writeBytes(generateVersion());
+
+        // If the CHALLENGE_MESSAGE TargetInfo field (section 2.2.1.2) has an
+        // MsvAvTimestamp present, the client SHOULD provide a MIC(Message Integrity
+        // Check)
+
+        int savedCursorForMIC = buf.cursor; // Save cursor position to write MIC
+                                            // later
+        buf.writeBytes(new byte[16]); // Write 16 zeroes
+
+        if (BLOCKS_OFFSET != buf.cursor)
+            throw new RuntimeException("BUG: Actual offset of first byte of allocated blocks is not equal hardcoded offset. Hardcoded offset: " + BLOCKS_OFFSET
+                    + ", actual offset: " + buf.cursor + ". Update hardcoded offset to match actual offset.");
+
+        buf.cursor = blocksCursor;
+        buf.trimAtCursor();
+
+        ntlmState.authenticateMessage = buf.toByteArray();
+
+        // Calculate and write MIC to reserved position
+        ntlmState.ntlm_compute_message_integrity_check();
+        buf.cursor = savedCursorForMIC;
+        buf.writeBytes(ntlmState.messageIntegrityCheck);
+        buf.rewindCursor();
+
+        return buf;
+    }
+
+    /**
+     * Write string as security buffer, using given charset, without trailing '\0'
+     * character.
+     */
+    private static int writeStringBlock(ByteBuffer buf, String string, int blocksCursor, Charset charset) {
+        return writeBlock(buf, string.getBytes(charset), blocksCursor);
+    }
+
+    /**
+     * Write block to blocks buffer and block descriptor to main buffer.
+     */
+    private static int writeBlock(ByteBuffer buf, byte[] block, int blocksCursor) {
+
+        // Write block descriptor
+
+        // Length
+        buf.writeShortLE(block.length);
+        // Allocated
+        buf.writeShortLE(block.length);
+        // Offset
+        buf.writeIntLE(blocksCursor);
+
+        // Write block to position pointed by blocksCursor instead of buf.cursor
+        int savedCursor = buf.cursor;
+        buf.cursor = blocksCursor;
+        buf.writeBytes(block);
+        blocksCursor = buf.cursor;
+        buf.cursor = savedCursor;
+
+        return blocksCursor;
+    }
+
+    /**
+     * Version (8 bytes): A VERSION structure (section 2.2.2.10) that is present
+     * only when the NTLMSSP_NEGOTIATE_VERSION flag is set in the NegotiateFlags
+     * field. This structure is used for debugging purposes only. In normal
+     * protocol messages, it is ignored and does not affect the NTLM message
+     * processing.
+     */
+    private static byte[] generateVersion() {
+        // Version (6.1, Build 7601), NTLM current revision: 15
+        return new byte[] {0x06, 0x01, (byte)0xb1, 0x1d, 0x00, 0x00, 0x00, 0x0f};
+    }
+
+    /**
+     * Example.
+     */
+    public static void main(String args[]) {
+        System.setProperty("streamer.Element.debug", "true");
+
+        /* @formatter:off */
+    //
+ // Client NEGOTIATE
+ //
+    byte[] clientNegotiatePacket = new byte[] {
+        (byte)0x30, (byte)0x37, (byte)0xa0, (byte)0x03, (byte)0x02, (byte)0x01, (byte)0x02, (byte)0xa1, (byte)0x30, (byte)0x30, (byte)0x2e, (byte)0x30, (byte)0x2c, (byte)0xa0, (byte)0x2a, (byte)0x04,
+        (byte)0x28, (byte)0x4e, (byte)0x54, (byte)0x4c, (byte)0x4d, (byte)0x53, (byte)0x53, (byte)0x50, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xb7, (byte)0x82, (byte)0x08,
+        (byte)0xe2, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
+        (byte)0x00, (byte)0x06, (byte)0x01, (byte)0xb1, (byte)0x1d, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0f,
+    };
+    
+//
+// Server CHALLENGE
+//
+    byte[] serverChallengePacket = new byte[] {
+        0x30, (byte) 0x82, 0x01, 0x02, // TAG: [UNIVERSAL 16] (constructed) "SEQUENCE" LEN: 258 bytes
+
+        (byte) 0xa0, 0x03, // TAG: [0] (constructed) LEN: 3 bytes
+        0x02, 0x01, 0x03,  // TAG: [UNIVERSAL 2] (primitive) "INTEGER" LEN: 1 bytes, Version: 0x3
+        (byte) 0xa1, (byte) 0x81, (byte) 0xfa, // TAG: [1] (constructed) LEN: 250 bytes
+        0x30, (byte) 0x81, (byte) 0xf7, // TAG: [UNIVERSAL 16] (constructed) "SEQUENCE" LEN: 247 bytes
+        0x30, (byte) 0x81, (byte) 0xf4, // TAG: [UNIVERSAL 16] (constructed) "SEQUENCE" LEN: 244 bytes
+        (byte) 0xa0, (byte) 0x81, (byte) 0xf1, // TAG: [0] (constructed) LEN: 241 bytes
+        0x04, (byte) 0x81, (byte) 0xee, // TAG: [UNIVERSAL 4] (primitive) "OCTET STRING" LEN: 238 bytes
+
+        0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, // "NTLMSSP\0"
+
+        0x02, 0x00, 0x00, 0x00, // MessageType (CHALLENGE) 
+
+        0x1e, 0x00, 0x1e, 0x00, 0x38, 0x00, 0x00, 0x00, // TargetName (length: 30, allocated space: 30, offset: 56)
+        0x35, (byte) 0x82, (byte) 0x8a, (byte) 0xe2, // NegotiateFlags: NEGOTIATE_56 NEGOTIATE_KEY_EXCH NEGOTIATE_128 NEGOTIATE_VERSION NEGOTIATE_TARGET_INFO NEGOTIATE_EXTENDED_SESSION_SECURITY TARGET_TYPE_SERVER NEGOTIATE_ALWAYS_SIGN NEGOTIATE_NTLM NEGOTIATE_SEAL NEGOTIATE_SIGN REQUEST_TARGET NEGOTIATE_UNICODE
+
+        (byte)0xc1, (byte)0x4a, (byte)0xc8, (byte)0x98, (byte)0x2f, (byte)0xd1, (byte)0x93, (byte)0xd4, //  ServerChallenge 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //  Reserved
+        (byte) 0x98, 0x00, (byte) 0x98, 0x00, 0x56, 0x00, 0x00, 0x00, // TargetInfo (length: 152, allocated space: 152, offset: 86)
+        0x06, 0x03, (byte) 0xd7, 0x24, 0x00, 0x00, 0x00, 0x0f,  // Version (6.3, build 9431) , NTLM current revision: 15
+
+
+        0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x4c, 0x00, 0x4f, 0x00, 0x34, 0x00, 0x31, 0x00, 0x39, 0x00, 0x42, 0x00, 0x32, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x52, 0x00, 0x30, 0x00,  // Target name value: "WIN-LO419B2LSR0"
+
+        // Target Info value:
+        
+        // Attribute list
+
+        0x02, 0x00, // Item Type: NetBIOS domain name (0x0002, LE)
+        0x1e, 0x00, //  Item Length: 30 (LE)
+        0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x4c, 0x00, 0x4f, 0x00, 0x34, 0x00, 0x31, 0x00, 0x39, 0x00, 0x42, 0x00, 0x32, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x52, 0x00, 0x30, 0x00, // "WIN-LO419B2LSR0"
+
+        0x01, 0x00,  //  Item Type: NetBIOS computer name (0x0001, LE) 
+        0x1e, 0x00, //  Item Length: 30 (LE)
+        0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x4c, 0x00, 0x4f, 0x00, 0x34, 0x00, 0x31, 0x00, 0x39, 0x00, 0x42, 0x00, 0x32, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x52, 0x00, 0x30, 0x00, // "WIN-LO419B2LSR0"
+
+        0x04, 0x00,  // Item Type: DNS domain name (0x0004, LE)
+        0x1e, 0x00, //  Item Length: 30 (LE)
+        0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x4c, 0x00, 0x4f, 0x00, 0x34, 0x00, 0x31, 0x00, 0x39, 0x00, 0x42, 0x00, 0x32, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x52, 0x00, 0x30, 0x00, // "WIN-LO419B2LSR0"
+
+        0x03, 0x00,  // Item Type: DNS computer name (0x0003, LE)
+        0x1e, 0x00, //  Item Length: 30 (LE)
+        0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x4c, 0x00, 0x4f, 0x00, 0x34, 0x00, 0x31, 0x00, 0x39, 0x00, 0x42, 0x00, 0x32, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x52, 0x00, 0x30, 0x00, // "WIN-LO419B2LSR0"
+
+        0x07, 0x00,  // Item Type: Timestamp (0x0007, LE)
+        0x08, 0x00, //  Item Length: 8 (LE)
+        (byte)0x1d, (byte)0xea, (byte)0x6b, (byte)0x60, (byte)0xf8, (byte)0xc5, (byte)0xce, (byte)0x01, // Time: Oct 10, 2013 23:36:20.056937300 EEST
+
+        // Attribute: End of list
+        0x00, 0x00,
+        0x00, 0x00, 
+
+    };
+  
+//
+// Client NTLMSSP_AUTH
+//
+    byte[] clientAuthPacket = new byte[] {
+        0x30, (byte) 0x82, 0x03, 0x13, //  TAG: [UNIVERSAL 16] (constructed) "SEQUENCE" LEN: 787 bytes
+
+        //
+        // TSRequest.version
+        // 
+        (byte) 0xa0, 0x03, //  TAG: [0] (constructed) LEN: 3 bytes
+        0x02, 0x01, 0x02, //  TAG: [UNIVERSAL 2] (primitive) "INTEGER" LEN: 1 bytes
+
+        //
+        // TSRequest.negoData
+        // 
+        (byte) 0xa1, (byte) 0x82, 0x01, (byte) 0xe4, //  TAG: [1] (constructed) LEN: 484 bytes
+        0x30, (byte) 0x82, 0x01, (byte) 0xe0, //  TAG: [UNIVERSAL 16] (constructed) "SEQUENCE" LEN: 480 bytes
+        0x30, (byte) 0x82, 0x01, (byte) 0xdc, //  TAG: [UNIVERSAL 16] (constructed) "SEQUENCE" LEN: 476 bytes
+
+        //
+        // NegoItem.negoToken
+        // 
+        (byte) 0xa0, (byte) 0x82, 0x01, (byte) 0xd8, //  TAG: [0] (constructed) LEN: 472 bytes
+        0x04, (byte) 0x82, 0x01, (byte) 0xd4,  // TAG: [UNIVERSAL 4] (primitive) "OCTET STRING" LEN: 468 bytes
+
+        // NTLMSSP
+
+        0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, //  "NTLMSSP\0"
+
+        0x03, 0x00, 0x00, 0x00, //  NTLM Message Type: NTLMSSP_AUTH (0x00000003)
+        0x18, 0x00, 0x18, 0x00, (byte) 0x92, 0x00, 0x00, 0x00, //  LmChallengeResponse (length 24, allocated: 24, offset 146)
+        0x1a, 0x01, 0x1a, 0x01, (byte) 0xaa, 0x00, 0x00, 0x00, //  NtChallengeResponse (length 282, allocated: 282, offset 170) 
+        0x12, 0x00, 0x12, 0x00, 0x58, 0x00, 0x00, 0x00,  // DomainName (length 18, allocated: 88, offset 88) 
+        0x1a, 0x00, 0x1a, 0x00, 0x6a, 0x00, 0x00, 0x00,  // UserName (length 26, allocated:26, offset 106) 
+        0x0e, 0x00, 0x0e, 0x00, (byte) 0x84, 0x00, 0x00, 0x00,  // Workstation (length 14, offset 132) 
+        0x10, 0x00, 0x10, 0x00, (byte) 0xc4, 0x01, 0x00, 0x00,  // EncryptedRandomSessionKey (length 16, offset 452) 
+        0x35, (byte) 0xb2, (byte) 0x88, (byte) 0xe2,   // NegotiateFlags
+        0x06, 0x01, (byte) 0xb1, 0x1d, 0x00, 0x00, 0x00, 0x0f, //  Version (6.1, Build 7601), NTLM current revision: 15
+
+        (byte)0x8c, (byte)0x69, (byte)0x53, (byte)0x1c, (byte)0xbb, (byte)0x6f, (byte)0xfb, (byte)0x9a, (byte)0x5d, (byte)0x2c, (byte)0x63, (byte)0xf2, (byte)0xc9, (byte)0x51, (byte)0xc5, (byte)0x11, // Message integrity check
+
+        0x77, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x6b, 0x00, 0x67, 0x00, 0x72, 0x00, 0x6f, 0x00, 0x75, 0x00, 0x70, 0x00, // Domain name value: "Workgroup"
+
+        0x41, 0x00, 0x64, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00,  // User name value: "Administrator"
+
+        0x61, 0x00, 0x70, 0x00, 0x6f, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6f, 0x00, 0x33, 0x00, //  Workstation host name value: "apollo3"
+
+        // Lan manager challenge response value
+        // Response: HMAC_MD(ResponseKeyLM, concatenate(ServerChallenge, ClientChallenge), where ResponseKeyLM=ntlmv2Hash(target, user, password)
+        (byte)0x17, (byte)0x9b, (byte)0x7d, (byte)0x7b, (byte)0x2f, (byte)0x79, (byte)0x9f, (byte)0x19, (byte)0xa0, (byte)0x4b, (byte)0x00, (byte)0xed, (byte)0x2b, (byte)0x39, (byte)0xbb, (byte)0x23,
+        // Client challenge (fixed for debugging)
+        (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08,
+
+        //
+        // NTLM challenge response value:
+        //
+
+        (byte)0x49, (byte)0xea, (byte)0x27, (byte)0x4f, (byte)0xcc, (byte)0x05, (byte)0x8b, (byte)0x79, (byte)0x20, (byte)0x0b, (byte)0x08, (byte)0x42, (byte)0xa9, (byte)0xc8, (byte)0x0e, (byte)0xc7, //  HMAC
+
+        0x01, 0x01, 0x00, 0x00, // Header: 0x00000101 (LE)
+        0x00, 0x00, 0x00, 0x00, // Reserved: 0x00000000
+        (byte)0x1d, (byte)0xea, (byte)0x6b, (byte)0x60, (byte)0xf8, (byte)0xc5, (byte)0xce, (byte)0x01, // Time: Oct 10, 2013 23:36:20.056937300 EEST
+        (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08, // Client challenge (fixed)
+        0x00, 0x00, 0x00, 0x00, //  Reserved
+
+        // Target Info value:
+        
+        // Attribute list
+
+        0x02, 0x00, // Item Type: NetBIOS domain name (0x0002, LE)
+        0x1e, 0x00, //  Item Length: 30 (LE)
+        0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x4c, 0x00, 0x4f, 0x00, 0x34, 0x00, 0x31, 0x00, 0x39, 0x00, 0x42, 0x00, 0x32, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x52, 0x00, 0x30, 0x00,  //  "WIN-LO419B2LSR0 "
+
+        0x01, 0x00,  //  Item Type: NetBIOS computer name (0x0001, LE) 
+        0x1e, 0x00,  // Item Length: 30 (LE)
+        0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x4c, 0x00, 0x4f, 0x00, 0x34, 0x00, 0x31, 0x00, 0x39, 0x00, 0x42, 0x00, 0x32, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x52, 0x00, 0x30, 0x00, //  "WIN-LO419B2LSR0 "
+
+        0x04, 0x00,  // Item Type: DNS domain name (0x0004, LE)
+        0x1e, 0x00,  // Item Length: 30 (LE)
+        0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x4c, 0x00, 0x4f, 0x00, 0x34, 0x00, 0x31, 0x00, 0x39, 0x00, 0x42, 0x00, 0x32, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x52, 0x00, 0x30, 0x00, //  "WIN-LO419B2LSR0 "
+
+        0x03, 0x00,  // Item Type: DNS computer name (0x0003, LE)
+        0x1e, 0x00,  // Item Length: 30 (LE)
+        0x57, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x2d, 0x00, 0x4c, 0x00, 0x4f, 0x00, 0x34, 0x00, 0x31, 0x00, 0x39, 0x00, 0x42, 0x00, 0x32, 0x00, 0x4c, 0x00, 0x53, 0x00, 0x52, 0x00, 0x30, 0x00, //  "WIN-LO419B2LSR0 "
+
+        0x07, 0x00,  // Item Type: Timestamp (0x0007, LE)
+        0x08, 0x00,  // Item Length: 8 (LE)
+        (byte)0x1d, (byte)0xea, (byte)0x6b, (byte)0x60, (byte)0xf8, (byte)0xc5, (byte)0xce, (byte)0x01, // Timestamp: Oct 10, 2013 23:36:20.056937300 EEST
+
+        0x06, 0x00,  // Item Type: Flags (0x0006, LE)
+        0x04, 0x00, // Item Length: 4 (LE)
+        0x02, 0x00, 0x00, 0x00, // Flags: 0x00000002
+
+        0x0a, 0x00, // Item Type: Channel Bindings (0x000a, LE)
+        0x10, 0x00, // Item Length: 16 (LE) 
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Channel Bindings: 00000000000000000000000000000000
+
+        0x09, 0x00, // Item Type: Target Name (0x0009, LE)
+        0x2a, 0x00, // Item Length: 42 (LE)
+        0x54, 0x00, 0x45, 0x00, 0x52, 0x00, 0x4d, 0x00, 0x53, 0x00, 0x52, 0x00, 0x56, 0x00, 0x2f, 0x00, 0x31, 0x00, 0x39, 0x00, 0x32, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x36, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x30, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x30, 0x00, 0x31, 0x00, // Target Name: "TERMSRV/192.168.0.101" (UTF-16)
+
+        // Attribute: End of list
+        0x00, 0x00,  // 
+        0x00, 0x00,  // 
+        // Attribute: End of list
+        0x00, 0x00,  // 
+        0x00, 0x00,  // 
+        // Attribute: End of list
+        0x00, 0x00,  // 
+        0x00, 0x00,  // 
+        // Attribute: End of list
+        0x00, 0x00,  // 
+        0x00, 0x00,  // 
+
+        // Session Key
+        // RC4 key (Server KeyExchangeKey or SessionBaseKey):
+        // 6e bd e3 da 83 c2 fd f1 38 a2 78 be 8c e6 75 d6
+        //
+        // RC4 data (Client nonce):
+        // 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10
+        //
+        // RC4 encrypted:
+        // 2c 24 da 10 17 cf 40 69 35 49 6f 58 e1 29 9e 79
+        (byte)0x2c, (byte)0x24, (byte)0xda, (byte)0x10, (byte)0x17, (byte)0xcf, (byte)0x40, (byte)0x69, (byte)0x35, (byte)0x49, (byte)0x6f, (byte)0x58, (byte)0xe1, (byte)0x29, (byte)0x9e, (byte)0x79,
+
+        //
+        // TSRequest.publicKey 
+        // 
+        (byte) 0xa3, (byte) 0x82, 0x01, 0x22, // TAG: [3] (constructed) LEN: 290 bytes 
+        0x04, (byte) 0x82, 0x01, 0x1e,  // TAG: [UNIVERSAL 4] (primitive) "OCTET STRING" LEN: 286 bytes
+
+        // NTLMSSP_MESSAGE_SIGNATURE, @see http://msdn.microsoft.com/en-us/library/cc422952.aspx
+        
+        // Version: 0x00000001
+        (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00,  
+        
+        // Checksum (8 bytes): An 8-byte array that contains the checksum for the message.
+        (byte)0x72, (byte)0x76, (byte)0x1e, (byte)0x57, (byte)0x49, (byte)0xb5, (byte)0x0f, (byte)0xad, 
+        
+        // seqNum of the message: 0
+        (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, 
+        
+        // Encrypted public key
+        (byte)0x15, (byte)0xf7, (byte)0xf2, (byte)0x54, (byte)0xda, (byte)0xa9, (byte)0xe5, (byte)0xad, (byte)0x85, (byte)0x04, (byte)0x67, (byte)0x4d, (byte)0x0b, (byte)0xcb, (byte)0xf9, (byte)0xb1,
+        (byte)0xf8, (byte)0x02, (byte)0x8a, (byte)0x77, (byte)0xc2, (byte)0x63, (byte)0xab, (byte)0xd5, (byte)0x74, (byte)0x23, (byte)0x9f, (byte)0x9d, (byte)0x5d, (byte)0x1f, (byte)0xd3, (byte)0xb3,
+        (byte)0xa0, (byte)0xac, (byte)0x16, (byte)0x8a, (byte)0x4b, (byte)0x08, (byte)0xf5, (byte)0x47, (byte)0x70, (byte)0x58, (byte)0x10, (byte)0xb4, (byte)0xe7, (byte)0x87, (byte)0xb3, (byte)0x4b,
+        (byte)0xc9, (byte)0xa2, (byte)0xd5, (byte)0xd1, (byte)0xca, (byte)0x0f, (byte)0xd4, (byte)0xe3, (byte)0x8d, (byte)0x76, (byte)0x5a, (byte)0x60, (byte)0x28, (byte)0xf8, (byte)0x06, (byte)0x5d,
+        (byte)0xe4, (byte)0x7e, (byte)0x21, (byte)0xc8, (byte)0xbb, (byte)0xac, (byte)0xe5, (byte)0x79, (byte)0x85, (byte)0x30, (byte)0x9b, (byte)0x88, (byte)0x13, (byte)0x2f, (byte)0x8f, (byte)0xfc,
+        (byte)0x04, (byte)0x52, (byte)0xfe, (byte)0x87, (byte)0x94, (byte)0xcf, (byte)0xcb, (byte)0x49, (byte)0x4a, (byte)0xda, (byte)0x6f, (byte)0xdd, (byte)0xee, (byte)0x57, (byte)0xa5, (byte)0xe4,
+        (byte)0x4d, (byte)0x0e, (byte)0x5c, (byte)0x3d, (byte)0x0b, (byte)0x63, (byte)0x1f, (byte)0xf6, (byte)0x3d, (byte)0x1b, (byte)0xae, (byte)0x5a, (byte)0xf6, (byte)0x42, (byte)0x2a, (byte)0x46,
+        (byte)0xfa, (byte)0x42, (byte)0x71, (byte)0x67, (byte)0x46, (byte)0x02, (byte)0x71, (byte)0xea, (byte)0x51, (byte)0x98, (byte)0xf7, (byte)0xd4, (byte)0x43, (byte)0xbf, (byte)0x8e, (byte)0xe8,
+        (byte)0x3c, (byte)0xc8, (byte)0xfa, (byte)0x79, (byte)0x9d, (byte)0x8c, (byte)0xfc, (byte)0xc2, (byte)0x42, (byte)0xc9, (byte)0xbb, (byte)0xd0, (byte)0xab, (byte)0x81, (byte)0xc4, (byte)0x53,
+        (byte)0xfd, (byte)0x41, (byte)0xda, (byte)0xab, (byte)0x0f, (byte)0x25, (byte)0x79, (byte)0x5f, (byte)0xbd, (byte)0xa3, (byte)0x8c, (byte)0xd3, (byte)0xf5, (byte)0x1b, (byte)0xab, (byte)0x20,
+        (byte)0xd1, (byte)0xf4, (byte)0xd8, (byte)0x81, (byte)0x9c, (byte)0x18, (byte)0x4a, (byte)0xa4, (byte)0x77, (byte)0xee, (byte)0xe1, (byte)0x51, (byte)0xee, (byte)0x2a, (byte)0xc1, (byte)0x94,
+        (byte)0x37, (byte)0xc5, (byte)0x06, (byte)0x7a, (byte)0x3f, (byte)0x0f, (byte)0x25, (byte)0x5b, (byte)0x4e, (byte)0x6a, (byte)0xdc, (byte)0x0b, (byte)0x62, (byte)0x6f, (byte)0x12, (byte)0x83,
+        (byte)0x03, (byte)0xae, (byte)0x4e, (byte)0xce, (byte)0x2b, (byte)0x6e, (byte)0xd4, (byte)0xd5, (byte)0x23, (byte)0x27, (byte)0xf6, (byte)0xa6, (byte)0x38, (byte)0x67, (byte)0xec, (byte)0x95,
+        (byte)0x82, (byte)0xc6, (byte)0xba, (byte)0xd4, (byte)0xf6, (byte)0xe6, (byte)0x22, (byte)0x7d, (byte)0xb9, (byte)0xe4, (byte)0x81, (byte)0x97, (byte)0x24, (byte)0xff, (byte)0x40, (byte)0xb2,
+        (byte)0x42, (byte)0x3c, (byte)0x11, (byte)0x24, (byte)0xd0, (byte)0x3a, (byte)0x96, (byte)0xd9, (byte)0xc1, (byte)0x13, (byte)0xd6, (byte)0x62, (byte)0x45, (byte)0x21, (byte)0x60, (byte)0x5b,
+        (byte)0x7b, (byte)0x2b, (byte)0x62, (byte)0x44, (byte)0xf7, (byte)0x40, (byte)0x93, (byte)0x29, (byte)0x5b, (byte)0x44, (byte)0xb7, (byte)0xda, (byte)0x9c, (byte)0xa6, (byte)0xa9, (byte)0x3b,
+        (byte)0xe1, (byte)0x3b, (byte)0x9d, (byte)0x31, (byte)0xf2, (byte)0x21, (byte)0x53, (byte)0x0f, (byte)0xb3, (byte)0x70, (byte)0x55, (byte)0x84, (byte)0x2c, (byte)0xb4,
+    };
+
+    SSLState sslState = new SSLState();
+    
+    sslState.serverCertificateSubjectPublicKeyInfo = new byte[] {
+      0x30, (byte) 0x82, 0x01, 0x22, // Sequence, length: 290 bytes 
+        0x30, 0x0d, // Sequence, length: 13 bytes {
+          0x06, 0x09, // Object ID, length: 9 bytes
+          0x2a, (byte) 0x86, 0x48, (byte) 0x86, (byte) 0xf7, 0x0d, 0x01, 0x01, 0x01, 
+          0x05, 0x00, // NULL, length: 0 bytes
+        
+          (byte)0x03, (byte)0x82, (byte)0x01, (byte)0x0f, // Bit string, length: 271 bytes
+          
+          (byte)0x00, // Pading 
+          (byte)0x30, (byte)0x82, (byte)0x01, (byte)0x0a, // Sequence
+          (byte)0x02, (byte)0x82, (byte)0x01, (byte)0x01, // Integer, length: 257 bytes 
+          
+          (byte)0x00, (byte)0xa8, (byte)0x56,
+          (byte)0x65, (byte)0xd3, (byte)0xce, (byte)0x8a, (byte)0x54, (byte)0x4d, (byte)0x9d, (byte)0xb0,
+          (byte)0x84, (byte)0x31, (byte)0x19, (byte)0x71, (byte)0x7f, (byte)0xdd, (byte)0x42, (byte)0xfb,
+          (byte)0x2a, (byte)0x7a, (byte)0x72, (byte)0x13, (byte)0xa1, (byte)0xb9, (byte)0x72, (byte)0xbb,
+          (byte)0xd3, (byte)0x08, (byte)0xad, (byte)0x7d, (byte)0x6c, (byte)0x15, (byte)0x65, (byte)0x03,
+          (byte)0xd1, (byte)0xc4, (byte)0x54, (byte)0xc5, (byte)0x33, (byte)0x6b, (byte)0x7d, (byte)0x69,
+          (byte)0x89, (byte)0x5e, (byte)0xfe, (byte)0xe0, (byte)0x01, (byte)0xc0, (byte)0x7e, (byte)0x9b,
+          (byte)0xcb, (byte)0x5d, (byte)0x65, (byte)0x36, (byte)0xcd, (byte)0x77, (byte)0x5d, (byte)0xf3,
+          (byte)0x7a, (byte)0x5b, (byte)0x29, (byte)0x44, (byte)0x72, (byte)0xd5, (byte)0x38, (byte)0xe2,
+          (byte)0xcf, (byte)0xb1, (byte)0xc7, (byte)0x78, (byte)0x9b, (byte)0x58, (byte)0xb9, (byte)0x17,
+          (byte)0x7c, (byte)0xb7, (byte)0xd6, (byte)0xc7, (byte)0xc7, (byte)0xbf, (byte)0x90, (byte)0x4e,
+          (byte)0x7c, (byte)0x39, (byte)0x93, (byte)0xcb, (byte)0x2e, (byte)0xe0, (byte)0xc2, (byte)0x33,
+          (byte)0x2d, (byte)0xa5, (byte)0x7e, (byte)0xe0, (byte)0x7b, (byte)0xb6, (byte)0xf9, (byte)0x91,
+          (byte)0x32, (byte)0xb7, (byte)0xd4, (byte)0x85, (byte)0xb7, (byte)0x35, (byte)0x2d, (byte)0x2b,
+          (byte)0x00, (byte)0x6d, (byte)0xf8, (byte)0xea, (byte)0x8c, (byte)0x97, (byte)0x5f, (byte)0x51,
+          (byte)0x1d, (byte)0x68, (byte)0x04, (byte)0x3c, (byte)0x79, (byte)0x14, (byte)0x71, (byte)0xa7,
+          (byte)0xc7, (byte)0xd7, (byte)0x70, (byte)0x7a, (byte)0xe0, (byte)0xba, (byte)0x12, (byte)0x69,
+          (byte)0xc8, (byte)0xd3, (byte)0xd9, (byte)0x4e, (byte)0xab, (byte)0x51, (byte)0x47, (byte)0xa3,
+          (byte)0xec, (byte)0x99, (byte)0xd4, (byte)0x88, (byte)0xca, (byte)0xda, (byte)0xc2, (byte)0x7f,
+          (byte)0x79, (byte)0x4b, (byte)0x66, (byte)0xed, (byte)0x87, (byte)0xbe, (byte)0xc2, (byte)0x5f,
+          (byte)0xea, (byte)0xcf, (byte)0xe1, (byte)0xb5, (byte)0xf0, (byte)0x3d, (byte)0x9b, (byte)0xf2,
+          (byte)0x19, (byte)0xc3, (byte)0xe0, (byte)0xe1, (byte)0x7a, (byte)0x45, (byte)0x71, (byte)0x12,
+          (byte)0x3d, (byte)0x72, (byte)0x1d, (byte)0x6f, (byte)0x2b, (byte)0x1c, (byte)0x46, (byte)0x68,
+          (byte)0xc0, (byte)0x8f, (byte)0x4f, (byte)0xce, (byte)0x3a, (byte)0xc5, (byte)0xcd, (byte)0x22,
+          (byte)0x65, (byte)0x2d, (byte)0x43, (byte)0xb0, (byte)0x5c, (byte)0xdd, (byte)0x89, (byte)0xae,
+          (byte)0xbe, (byte)0x70, (byte)0x59, (byte)0x5e, (byte)0x0c, (byte)0xbd, (byte)0xf5, (byte)0x46,
+          (byte)0x82, (byte)0x1e, (byte)0xe4, (byte)0x86, (byte)0x95, (byte)0x7b, (byte)0x60, (byte)0xae,
+          (byte)0x45, (byte)0x50, (byte)0xc2, (byte)0x54, (byte)0x08, (byte)0x49, (byte)0x9a, (byte)0x9e,
+          (byte)0xfb, (byte)0xb2, (byte)0xb6, (byte)0x78, (byte)0xe5, (byte)0x2f, (byte)0x9c, (byte)0x5a,
+          (byte)0xd0, (byte)0x8a, (byte)0x03, (byte)0x77, (byte)0x68, (byte)0x30, (byte)0x93, (byte)0x78,
+          (byte)0x6d, (byte)0x90, (byte)0x6d, (byte)0x50, (byte)0xfa, (byte)0xa7, (byte)0x65, (byte)0xfe,
+          (byte)0x59, (byte)0x33, (byte)0x27, (byte)0x4e, (byte)0x4b, (byte)0xf8, (byte)0x38, (byte)0x44,
+          (byte)0x3a, (byte)0x12, (byte)0xf4, (byte)0x07, (byte)0xa0, (byte)0x8d, (byte)0x02, (byte)0x03,
+          (byte)0x01, (byte)0x00, (byte)0x01,
+    };
+    /* @formatter:on */
+
+        NtlmState ntlmState = new NtlmState();
+        MockSource source = new MockSource("source", ByteBuffer.convertByteArraysToByteBuffers(serverChallengePacket, new byte[] {1, 2, 3}));
+        Element ntlmssp_negotiate = new ClientNtlmsspNegotiate("ntlmssp_negotiate", ntlmState);
+        Element ntlmssp_challenge = new ServerNtlmsspChallenge("ntlmssp_challenge", ntlmState);
+        Element ntlmssp_auth = new ClientNtlmsspPubKeyAuth("ntlmssp_auth", ntlmState, sslState, "192.168.0.101", "workgroup", "apollo3", "Administrator",
+                "R2Preview!");
+        Element sink = new MockSink("sink", ByteBuffer.convertByteArraysToByteBuffers(clientNegotiatePacket, clientAuthPacket), (Dumper)ntlmssp_auth);
+        Element mainSink = new MockSink("mainSink", ByteBuffer.convertByteArraysToByteBuffers(new byte[] {1, 2, 3}));
+
+        Pipeline pipeline = new PipelineImpl("test");
+        pipeline.add(source, ntlmssp_negotiate, ntlmssp_challenge, ntlmssp_auth, sink, mainSink);
+        pipeline.link("source", "ntlmssp_negotiate", "ntlmssp_challenge", "ntlmssp_auth", "mainSink");
+        pipeline.link("ntlmssp_negotiate >" + OTOUT, "ntlmssp_negotiate< sink");
+        pipeline.link("ntlmssp_challenge >" + OTOUT, "ntlmssp_challenge< sink");
+        pipeline.link("ntlmssp_auth >" + OTOUT, "ntlmssp_auth< sink");
+        pipeline.runMainLoop("source", STDOUT, false, false);
+
+    }
+
+    @Override
+    public void dump(ByteBuffer buf) {
+        buf.rewindCursor();
+        TSRequest request = new TSRequest("TSRequest");
+        request.readTag(buf);
+        System.out.println("TSRequest version: " + request.version.value);
+        System.out.println("TSRequest pubKey: " + request.pubKeyAuth.value.toPlainHexString());
+
+        ByteBuffer negoToken = ((NegoItem)request.negoTokens.tags[0]).negoToken.value;
+        System.out.println("TSRequest negotoken: " + negoToken.toPlainHexString());
+        dumpNegoToken(negoToken);
+
+        negoToken.unref();
+    }
+
+    private void dumpNegoToken(ByteBuffer buf) {
+        String signature = buf.readVariableString(RdpConstants.CHARSET_8);
+        if (!signature.equals(NTLMSSP))
+            throw new RuntimeException("Unexpected NTLM message singature: \"" + signature + "\". Expected signature: \"" + NTLMSSP + "\". Data: " + buf + ".");
+
+        // MessageType (CHALLENGE)
+        int messageType = buf.readSignedIntLE();
+        if (messageType != NtlmConstants.NTLMSSP_AUTH)
+            throw new RuntimeException("Unexpected NTLM message type: " + messageType + ". Expected type: CHALLENGE (" + NtlmConstants.CHALLENGE + "). Data: " + buf
+                    + ".");
+
+        System.out.println("lmChallengeResponseFields: " + ServerNtlmsspChallenge.readBlockByDescription(buf).toPlainHexString());
+        ByteBuffer ntChallengeResponseBuf = ServerNtlmsspChallenge.readBlockByDescription(buf);
+        System.out.println("NtChallengeResponse: " + ntChallengeResponseBuf.toPlainHexString());
+        System.out.println("DomainName: " + ServerNtlmsspChallenge.readStringByDescription(buf));
+        System.out.println("UserName: " + ServerNtlmsspChallenge.readStringByDescription(buf));
+        System.out.println("Workstation: " + ServerNtlmsspChallenge.readStringByDescription(buf));
+        System.out.println("EncryptedRandomSessionKey: " + ServerNtlmsspChallenge.readBlockByDescription(buf).toPlainHexString());
+        System.out.println("NegotiateFlags: " + new NegoFlags(buf.readSignedIntLE()));
+        System.out.println("Version: " + buf.readBytes(8).toPlainHexString());
+
+        dumpNtChallengeResponse(ntChallengeResponseBuf);
+    }
+
+    private void dumpNtChallengeResponse(ByteBuffer buf) {
+        System.out.println("HMAC: " + buf.readBytes(16).toPlainHexString());
+        System.out.format("Header: 0x%08x\n", buf.readUnsignedIntLE());
+        System.out.format("Reserved: 0x%08x\n", buf.readUnsignedIntLE());
+        System.out.println("Time: " + buf.readBytes(8).toPlainHexString());
+        System.out.println("Client challenge: " + buf.readBytes(8).toPlainHexString());
+        System.out.format("Reserved: 0x%08x\n", buf.readUnsignedIntLE());
+
+        // Parse attribute list
+
+        while (buf.remainderLength() > 0) {
+            int type = buf.readUnsignedShortLE();
+            int length = buf.readUnsignedShortLE();
+
+            if (type == MSV_AV_EOL)
+                // End of list
+                break;
+
+            ByteBuffer data = buf.readBytes(length);
+            switch (type) {
+            case MSV_AV_NETBIOS_DOMAIN_NAME:
+                System.out.println("AV Netbios Domain name: " + data.readString(length, RdpConstants.CHARSET_16));
+                break;
+            case MSV_AV_NETBIOS_COMPUTER_NAME:
+                System.out.println("AV Netbios Computer name: " + data.readString(length, RdpConstants.CHARSET_16));
+                break;
+            case MSV_AV_DNS_DOMAIN_NAME:
+                System.out.println("AV DNS Domain name: " + data.readString(length, RdpConstants.CHARSET_16));
+                break;
+            case MSV_AV_DNS_COMPUTER_NAME:
+                System.out.println("AV DNS Computer name: " + data.readString(length, RdpConstants.CHARSET_16));
+                break;
+            case MSV_AV_CHANNEL_BINDINGS:
+                System.out.println("AV Channel Bindings: " + data.readBytes(length).toPlainHexString());
+                break;
+            case MSV_AV_TIMESTAMP:
+                System.out.println("AV Timestamp: " + data.readBytes(length).toPlainHexString());
+                break;
+            case MSV_AV_FLAGS:
+                System.out.println("AV Flags: " + data.readBytes(length).toPlainHexString());
+                break;
+            case MSV_AV_TARGET_NAME:
+                System.out.println("AV Target Name: " + data.readString(length, RdpConstants.CHARSET_16));
+                break;
+            default:
+                System.out.println("Unknown NTLM target info attribute: " + type + ". Data: " + data + ".");
+            }
+            data.unref();
+        }
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/ClientNtlmsspUserCredentials.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/ClientNtlmsspUserCredentials.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/ClientNtlmsspUserCredentials.java
new file mode 100755
index 0000000..50584c3
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/ClientNtlmsspUserCredentials.java
@@ -0,0 +1,128 @@
+// 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.ntlmssp;
+
+import rdpclient.ntlmssp.asn1.TSCredentials;
+import rdpclient.ntlmssp.asn1.TSPasswordCreds;
+import rdpclient.ntlmssp.asn1.TSRequest;
+import rdpclient.rdp.RdpConstants;
+import streamer.ByteBuffer;
+import streamer.Element;
+import streamer.Link;
+import streamer.OneTimeSwitch;
+
+public class ClientNtlmsspUserCredentials extends OneTimeSwitch implements Element {
+
+    protected NtlmState ntlmState;
+
+    public ClientNtlmsspUserCredentials(String id, NtlmState ntlmState) {
+        super(id);
+        this.ntlmState = ntlmState;
+    }
+
+    @Override
+    protected void handleOneTimeData(ByteBuffer buf, Link link) {
+        if (buf == null)
+            return;
+
+        throw new RuntimeException("Unexpected packet: " + buf + ".");
+    }
+
+    @Override
+    protected void onStart() {
+        super.onStart();
+
+        ByteBuffer buf = new ByteBuffer(4096, true);
+
+        TSRequest tsRequest = new TSRequest("TSRequest");
+        tsRequest.version.value = 2L;
+
+        ByteBuffer tsCredentialsBuf = generateTSCredentials();
+        tsRequest.authInfo.value = encryptTSCredentials(tsCredentialsBuf);
+        tsCredentialsBuf.unref();
+
+        tsRequest.writeTag(buf);
+
+        // Trim buffer to actual length of data written
+        buf.trimAtCursor();
+
+        pushDataToOTOut(buf);
+
+        switchOff();
+    }
+
+    private ByteBuffer encryptTSCredentials(ByteBuffer buf2) {
+        return new ByteBuffer(ntlmState.ntlm_EncryptMessage(buf2.toByteArray()));
+    }
+
+    private ByteBuffer generateTSCredentials() {
+        ByteBuffer buf = new ByteBuffer(4096);
+
+        TSCredentials tsCredentials = new TSCredentials("authInfo");
+        // 1 means that credentials field contains a TSPasswordCreds structure
+        tsCredentials.credType.value = 1L;
+
+        ByteBuffer tsPasswordCredsBuf = new ByteBuffer(4096, true);
+        TSPasswordCreds tsPasswordCreds = new TSPasswordCreds("credentials");
+        tsPasswordCreds.domainName.value = new ByteBuffer(ntlmState.domain.getBytes(RdpConstants.CHARSET_16));
+        tsPasswordCreds.userName.value = new ByteBuffer(ntlmState.user.getBytes(RdpConstants.CHARSET_16));
+        tsPasswordCreds.password.value = new ByteBuffer(ntlmState.password.getBytes(RdpConstants.CHARSET_16));
+        tsPasswordCreds.writeTag(tsPasswordCredsBuf);
+        tsPasswordCredsBuf.trimAtCursor();
+        //* DEBUG */System.out.println("TSPasswordCreds:\n" + tsPasswordCredsBuf.dump());
+
+        tsCredentials.credentials.value = tsPasswordCredsBuf;
+
+        tsCredentials.writeTag(buf);
+        tsPasswordCredsBuf.unref();
+
+        // Trim buffer to actual length of data written
+        buf.trimAtCursor();
+        //* DEBUG */System.out.println("TSCredentials:\n" + buf.dump());
+
+        return buf;
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) {
+        // TODO Auto-generated method stub
+
+        /* @formatter:off */
+    // TSCredentials
+//  30 57 // Sequence 
+//  a0 03 // TAG 0 
+//  02 01 01 // Integer: 1 : credentials contains a TSPasswordCreds structure
+//  a1 50 // TAG 1
+//  04 4e // OCTETSTRING
+    // TSPasswordCreds
+//  30 4c // SEQUENCE 
+//  a0 14 // TAG 0 
+//  04 12 // OCTETSTRING 
+//  77 00 6f 00 72 00 6b 00 67 00 72 00 6f 00 75 00 70 00 // "workgroup" 
+//  a1 1c // TAG 1 
+//  04 1a // OCTETSTRING
+//  41 00 64 00 6d 00 69 00 6e 00 69 00 73 00 74 00 72 00 61 00 74 00 6f 00 72 00 // "Administrator" 
+//  a2 16 // TAG 2 
+//  04 14 //
+//  52 00 32 00 50 00 72 00 65 00 76 00 69 00 65 00 77 00 21 00 // "R2Preview!"
+  /* @formatter:on */
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/CryptoAlgos.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/CryptoAlgos.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/CryptoAlgos.java
new file mode 100755
index 0000000..817dbd9
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/CryptoAlgos.java
@@ -0,0 +1,361 @@
+// 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.ntlmssp;
+
+import java.lang.reflect.Method;
+import java.security.Key;
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+import java.util.Arrays;
+
+import javax.crypto.Cipher;
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+
+import rdpclient.rdp.RdpConstants;
+
+/**
+ * @see http://msdn.microsoft.com/en-us/library/cc236717.aspx
+ */
+public class CryptoAlgos implements NtlmConstants {
+
+    /**
+     * Indicates the left-to-right concatenation of the string parameters, from
+     * the first string to the Nnth. Any numbers are converted to strings and all
+     * numeric conversions to strings retain all digits, even nonsignificant ones.
+     * The result is a string. For example, ConcatenationOf(0x00122, "XYZ",
+     * "Client") results in the string "00122XYZClient."
+     */
+    public static String concatenationOf(String... args) {
+        StringBuffer sb = new StringBuffer();
+        for (String arg : args) {
+            sb.append(arg);
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Concatenate byte arrays.
+     */
+    public static byte[] concatenationOf(byte[]... arrays) {
+        int length = 0;
+        for (byte[] array : arrays) {
+            length += array.length;
+        }
+
+        byte[] result = new byte[length];
+        int destPos = 0;
+        for (byte[] array : arrays) {
+            System.arraycopy(array, 0, result, destPos, array.length);
+            destPos += array.length;
+        }
+
+        return result;
+    }
+
+    /** Indicates a 32-bit CRC calculated over M. */
+    public static byte[] CRC32(byte[] M) {
+        throw new RuntimeException("FATAL: Not implemented.");
+    }
+
+    /**
+     * Indicates the encryption of an 8-byte data item D with the 7-byte key K
+     * using the Data Encryption Standard (DES) algorithm in Electronic Codebook
+     * (ECB) mode. The result is 8 bytes in length ([FIPS46-2]).
+     */
+    public static byte[] DES(byte[] K, byte[] D) {
+        throw new RuntimeException("FATAL: Not implemented.");
+    }
+
+    /**
+     * Indicates the encryption of an 8-byte data item D with the 16-byte key K
+     * using the Data Encryption Standard Long (DESL) algorithm. The result is 24
+     * bytes in length. DESL(K, D) is computed as follows.
+     * 
+     * <pre>
+     *   ConcatenationOf( DES(K[0..6], D), 
+     *     DES(K[7..13], D), DES(  
+     *       ConcatenationOf(K[14..15], Z(5)), D));
+     * </pre>
+     * 
+     * Note K[] implies a key represented as a character array.
+     */
+    public static byte[] DESL(byte[] K, byte[] D) {
+        throw new RuntimeException("FATAL: Not implemented.");
+    }
+
+    /**
+     * An auxiliary function that returns an operating system version-specific
+     * value (section 2.2.2.8).
+     */
+    public static byte[] getVersion() {
+        // Version (6.1, Build 7601), NTLM current revision: 15
+        return new byte[] {0x06, 0x01, (byte)0xb1, 0x1d, 0x00, 0x00, 0x00, 0x0f};
+    }
+
+    /**
+     * Retrieve the user's LM response key from the server database (directory or
+     * local database).
+     */
+    public static byte[] LMGETKEY(byte[] U, byte[] D) {
+        throw new RuntimeException("FATAL: Not implemented.");
+    }
+
+    /** Retrieve the user's NT response key from the server database. */
+    public static byte[] NTGETKEY(byte[] U, byte[] D) {
+        throw new RuntimeException("FATAL: Not implemented.");
+    }
+
+    /**
+     * Indicates the encryption of data item M with the key K using the HMAC
+     * algorithm ([RFC2104]).
+     */
+    public static byte[] HMAC(byte[] K, byte[] M) {
+        throw new RuntimeException("FATAL: Not implemented.");
+    }
+
+    /**
+     * Indicates the computation of a 16-byte HMAC-keyed MD5 message digest of the
+     * byte string M using the key K.
+     */
+    public static byte[] HMAC_MD5(byte[] K, byte[] M) {
+        try {
+            String algorithm = "HMacMD5";
+            Mac hashMac = Mac.getInstance(algorithm);
+
+            Key secretKey = new SecretKeySpec(K, 0, K.length, algorithm);
+            hashMac.init(secretKey);
+            return hashMac.doFinal(M);
+        } catch (Exception e) {
+            throw new RuntimeException("Cannot calculate HMAC-MD5.", e);
+        }
+    }
+
+    /**
+     * Produces a key exchange key from the session base key K, LM response and
+     * server challenge SC as defined in the sections KXKEY, SIGNKEY, and SEALKEY.
+     */
+    public static byte[] KXKEY(byte[] sessionBaseKey/*K, byte[] LM, byte[] SC*/) {
+        // Key eXchange Key is server challenge
+        /* In NTLMv2, KeyExchangeKey is the 128-bit SessionBaseKey */
+        return Arrays.copyOf(sessionBaseKey, sessionBaseKey.length);
+    }
+
+    /**
+     * Computes a one-way function of the user's password to use as the response
+     * key. NTLM v1 and NTLM v2 define separate LMOWF() functions in the NTLM v1
+     * authentication and NTLM v2 authentication sections, respectively.
+     */
+    public static byte[] LMOWF() {
+        throw new RuntimeException("FATAL: Not implemented.");
+    }
+
+    /**
+     * Indicates the computation of an MD4 message digest of the null-terminated
+     * byte string M ([RFC1320]).
+     */
+    public static byte[] MD4(byte[] M) {
+        try {
+            return sun.security.provider.MD4.getInstance().digest(M);
+        } catch (Exception e) {
+            throw new RuntimeException("Cannot calculate MD5.", e);
+        }
+    }
+
+    /**
+     * Indicates the computation of an MD5 message digest of the null-terminated
+     * byte string M ([RFC1321]).
+     */
+    public static byte[] MD5(byte[] M) {
+        try {
+            return MessageDigest.getInstance("MD5").digest(M);
+        } catch (Exception e) {
+            throw new RuntimeException("Cannot calculate MD5.", e);
+        }
+    }
+
+    /**
+     * Indicates the computation of an MD5 message digest of a binary blob
+     * ([RFC4121] section 4.1.1.2).
+     */
+    public static byte[] MD5_HASH(byte[] M) {
+        try {
+            return MessageDigest.getInstance("MD5").digest(M);
+        } catch (Exception e) {
+            throw new RuntimeException("Cannot calculate MD5.", e);
+        }
+    }
+
+    /** A zero-length string. */
+    public static final String NIL = "";
+
+    /**
+     * Indicates the computation of an N-byte cryptographic-strength random
+     * number.
+     * 
+     * Note The NTLM Authentication Protocol does not define the statistical
+     * properties of the random number generator. It is left to the discretion of
+     * the implementation to define the strength requirements of the NONCE(N)
+     * operation.
+     */
+    public static byte[] NONCE(int N) {
+        // Generate random nonce for LMv2 and NTv2 responses
+        byte[] nonce = new byte[N];
+        SecureRandom random = new SecureRandom();
+        random.nextBytes(nonce);
+
+        // Fixed nonce for debugging purposes
+        //* DEBUG */for (int i = 0; i < N; i++) nonce[i] = (byte) (i + 1);
+
+        return nonce;
+    }
+
+    /**
+     * Computes a one-way function of the user's password to use as the response
+     * key. NTLM v1 and NTLM v2 define separate NTOWF() functions in the NTLM v1
+     * authentication and NTLM v2 authentication sections, respectively.
+     */
+    public static byte[] NTOWF() {
+        throw new RuntimeException("FATAL: Not implemented.");
+    }
+
+    /**
+     * The RC4 Encryption Algorithm. To obtain this stream cipher that is licensed
+     * by RSA Data Security, Inc., contact this company.
+     * 
+     * Indicates the encryption of data item D with the current session or message
+     * key state, using the RC4 algorithm. H is the handle to a key state
+     * structure initialized by RC4INIT.
+     */
+    public static byte[] RC4(Cipher H, byte[] D) {
+        return H.update(D);
+    }
+
+    /**
+     * Indicates the encryption of data item D with the key K using the RC4
+     * algorithm.
+     * 
+     * Note The key sizes for RC4 encryption in NTLM are defined in sections
+     * KXKEY, SIGNKEY, and SEALKEY, where they are created.
+     */
+    public static byte[] RC4K(byte[] K, byte[] D) {
+        try {
+            Cipher cipher = Cipher.getInstance("RC4");
+            Key key = new SecretKeySpec(K, "RC4");
+            cipher.init(Cipher.ENCRYPT_MODE, key);
+            return cipher.doFinal(D);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Initialization of the RC4 key and handle to a key state structure for the
+     * session.
+     */
+    public static Cipher RC4Init(byte[] K) {
+        throw new RuntimeException("FATAL: Not implemented.");
+    }
+
+    /**
+     * Produces an encryption key from the session key as defined in sections
+     * KXKEY, SIGNKEY, and SEALKEY.
+     */
+    public static byte[] SEALKEY(byte[] F, byte[] K, byte[] string1) {
+        throw new RuntimeException("FATAL: Not implemented.");
+    }
+
+    /**
+     * Produces a signing key from the session key as defined in sections KXKEY,
+     * SIGNKEY, and SEALKEY.
+     */
+    public static byte[] SIGNKEY(int flag, byte[] K, byte[] string1) {
+        throw new RuntimeException("FATAL: Not implemented.");
+    }
+
+    /**
+     * Indicates the retrieval of the current time as a 64-bit value, represented
+     * as the number of 100-nanosecond ticks elapsed since midnight of January
+     * 1st, 1601 (UTC).
+     */
+    public static byte[] Currenttime() {
+        // (current time + milliseconds from 1.01.1601 to 1.01.1970) *
+        // 100-nanosecond ticks
+        long time = (System.currentTimeMillis() + 11644473600000L) * 10000;
+
+        // Convert 64bit value to byte array.
+        byte[] result = new byte[8];
+        for (int i = 0; i < 8; i++, time >>>= 8) {
+            result[i] = (byte)time;
+        }
+
+        return result;
+    }
+
+    /**
+     * Indicates the 2-byte little-endian byte order encoding of the Unicode
+     * UTF-16 representation of string. The Byte Order Mark (BOM) is not sent over
+     * the wire.
+     */
+    public static byte[] UNICODE(String string) {
+        return string.getBytes(RdpConstants.CHARSET_16);
+    }
+
+    /** Indicates the uppercase representation of string. */
+    public static String UpperCase(String string) {
+        return string.toUpperCase();
+    }
+
+    /**
+     * Indicates the creation of a byte array of length N. Each byte in the array
+     * is initialized to the value zero.
+     */
+    public static byte[] Z(int N) {
+        return new byte[N];
+    }
+
+    public static Cipher initRC4(byte[] key) {
+        try {
+            Cipher cipher = Cipher.getInstance("RC4");
+            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "RC4"));
+            return cipher;
+        } catch (Exception e) {
+            throw new RuntimeException("Cannot initialize RC4 sealing handle with client sealing key.", e);
+        }
+    }
+
+    /**
+     * Helper method for embedded test cases.
+     */
+    public static void callAll(Object obj) {
+        Method[] methods = obj.getClass().getDeclaredMethods();
+        for (Method m : methods) {
+            if (m.getName().startsWith("test")) {
+                try {
+                    m.invoke(obj, (Object[])null);
+                } catch (Exception e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+    }
+
+    public static void main(String args[]) {
+        callAll(new CryptoAlgos());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/4f3611f9/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/NegoFlags.java
----------------------------------------------------------------------
diff --git a/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/NegoFlags.java b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/NegoFlags.java
new file mode 100755
index 0000000..c35dbec
--- /dev/null
+++ b/services/console-proxy-rdp/rdpconsole/src/main/java/rdpclient/ntlmssp/NegoFlags.java
@@ -0,0 +1,492 @@
+// 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.ntlmssp;
+
+/**
+ * During NTLM authentication, each of the following flags is a possible value
+ * of the NegotiateFlags field of the NEGOTIATE_MESSAGE, CHALLENGE_MESSAGE, and
+ * AUTHENTICATE_MESSAGE, unless otherwise noted. These flags define client or
+ * server NTLM capabilities supported by the sender.
+ * 
+ * @see http://msdn.microsoft.com/en-us/library/cc236650.aspx
+ */
+public class NegoFlags {
+
+    /**
+     * 56-bit encryption. If the client sends NTLMSSP_NEGOTIATE_SEAL or
+     * NTLMSSP_NEGOTIATE_SIGN with NTLMSSP_NEGOTIATE_56 to the server in the
+     * NEGOTIATE_MESSAGE, the server MUST return NTLMSSP_NEGOTIATE_56 to the
+     * client in the CHALLENGE_MESSAGE. Otherwise it is ignored. If both
+     * NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 are requested and supported
+     * by the client and server, NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128
+     * will both be returned to the client. Clients and servers that set
+     * NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_56 if it is supported.
+     * An alternate name for this field is
+     */
+    public static final int NTLMSSP_NEGOTIATE_56 = 0x80000000;
+
+    /**
+     * Explicit key exchange. This capability SHOULD be used because it improves
+     * security for message integrity or confidentiality. See sections 3.2.5.1.2,
+     * 3.2.5.2.1, and 3.2.5.2.2 for details.
+     */
+    public static final int NTLMSSP_NEGOTIATE_KEY_EXCH = 0x40000000;
+
+    /**
+     * 128-bit session key negotiation. An alternate name for this field is
+     * NTLMSSP_NEGOTIATE_128. If the client sends NTLMSSP_NEGOTIATE_128 to the
+     * server in the NEGOTIATE_MESSAGE, the server MUST return
+     * NTLMSSP_NEGOTIATE_128 to the client in the CHALLENGE_MESSAGE only if the
+     * client sets NTLMSSP_NEGOTIATE_SEAL or NTLMSSP_NEGOTIATE_SIGN. Otherwise it
+     * is ignored. If both NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128 are
+     * requested and supported by the client and server, NTLMSSP_NEGOTIATE_56 and
+     * NTLMSSP_NEGOTIATE_128 will both be returned to the client. Clients and
+     * servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD set NTLMSSP_NEGOTIATE_128 if
+     * it is supported.
+     */
+    public static final int NTLMSSP_NEGOTIATE_128 = 0x20000000;
+
+    /**
+     * Protocol version number. The data corresponding to this flag is provided in
+     * the Version field of the NEGOTIATE_MESSAGE, the CHALLENGE_MESSAGE, and the
+     * AUTHENTICATE_MESSAGE.
+     */
+    public static final int NTLMSSP_NEGOTIATE_VERSION = 0x02000000;
+
+    /**
+     * TargetInfo fields in the CHALLENGE_MESSAGE (section 2.2.1.2) are populated.
+     */
+    public static final int NTLMSSP_NEGOTIATE_TARGET_INFO = 0x00800000;
+
+    /** LMOWF (section 3.3). */
+    public static final int NTLMSSP_REQUEST_NON_NT_SESSION_KEY = 0x00400000;
+
+    /** An identify level token. */
+    public static final int NTLMSSP_NEGOTIATE_IDENTIFY = 0x00100000;
+
+    /**
+     * NTLM v2 session security. NTLM v2 session security is a misnomer because it
+     * is not NTLM v2. It is NTLM v1 using the extended session security that is
+     * also in NTLM v2. NTLMSSP_NEGOTIATE_LM_KEY and
+     * NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both
+     * NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY and NTLMSSP_NEGOTIATE_LM_KEY are
+     * requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be
+     * returned to the client. NTLM v2 authentication session key generation MUST
+     * be supported by both the client and the DC in order to be used, and
+     * extended session security signing and sealing requires support from the
+     * client and the server in order to be used.
+     */
+    public static final int NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY = 0x00080000;
+
+    /**
+     * TargetName MUST be a server name. The data corresponding to this flag is
+     * provided by the server in the TargetName field of the CHALLENGE_MESSAGE. If
+     * this bit is set, then NTLMSSP_TARGET_TYPE_DOMAIN MUST NOT be set. This flag
+     * MUST be ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE.
+     */
+    public static final int NTLMSSP_TARGET_TYPE_SERVER = 0x00020000;
+
+    /**
+     * TargetName MUST be a domain name. The data corresponding to this flag is
+     * provided by the server in the TargetName field of the CHALLENGE_MESSAGE. If
+     * set, then NTLMSSP_TARGET_TYPE_SERVER MUST NOT be set. This flag MUST be
+     * ignored in the NEGOTIATE_MESSAGE and the AUTHENTICATE_MESSAGE.
+     */
+    public static final int NTLMSSP_TARGET_TYPE_DOMAIN = 0x00010000;
+
+    /**
+     * Signature block on all messages. NTLMSSP_NEGOTIATE_ALWAYS_SIGN MUST be set
+     * in the NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to the
+     * client. NTLMSSP_NEGOTIATE_ALWAYS_SIGN is overridden by
+     * NTLMSSP_NEGOTIATE_SIGN and NTLMSSP_NEGOTIATE_SEAL, if they are supported.
+     */
+    public static final int NTLMSSP_NEGOTIATE_ALWAYS_SIGN = 0x00008000;
+
+    /**
+     * Workstation field is present. If this flag is not set, the Workstation
+     * field MUST be ignored. If this flag is set, the length field of the
+     * Workstation field specifies whether the workstation name is nonempty or
+     * not.
+     */
+    public static final int NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED = 0x00002000;
+
+    /**
+     * Domain name is provided.
+     * 
+     * Sent by the client in the Type 1 message to indicate that the name of the
+     * domain in which the client workstation has membership is included in the
+     * message. This is used by the server to determine whether the client is
+     * eligible for local authentication.
+     */
+    public static final int NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED = 0x00001000;
+
+    /**
+     * Connection SHOULD be anonymous.
+     * 
+     * Sent by the client in the Type 3 message to indicate that an anonymous
+     * context has been established. This also affects the response fields (as
+     * detailed in the "Anonymous Response" section).
+     */
+    public static final int NTLMSSP_NEGOTIATE_ANONYMOUS = 0x00000800;
+
+    /**
+     * Usage of the NTLM v1 session security protocol. NTLMSSP_NEGOTIATE_NTLM MUST
+     * be set in the NEGOTIATE_MESSAGE to the server and the CHALLENGE_MESSAGE to
+     * the client.
+     */
+    public static final int NTLMSSP_NEGOTIATE_NTLM = 0x00000200;
+
+    /**
+     * LAN Manager (LM) session key computation. NTLMSSP_NEGOTIATE_LM_KEY and
+     * NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are mutually exclusive. If both
+     * NTLMSSP_NEGOTIATE_LM_KEY and NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY are
+     * requested, NTLMSSP_NEGOTIATE_EXTENDED_SESSIONSECURITY alone MUST be
+     * returned to the client. NTLM v2 authentication session key generation MUST
+     * be supported by both the client and the DC in order to be used, and
+     * extended session security signing and sealing requires support from the
+     * client and the server to be used.
+     */
+    public static final int NTLMSSP_NEGOTIATE_LM_KEY = 0x00000080;
+
+    /**
+     * Connectionless authentication. If NTLMSSP_NEGOTIATE_DATAGRAM is set, then
+     * NTLMSSP_NEGOTIATE_KEY_EXCH MUST always be set in the AUTHENTICATE_MESSAGE
+     * to the server and the CHALLENGE_MESSAGE to the client.
+     */
+    public static final int NTLMSSP_NEGOTIATE_DATAGRAM = 0x00000040;
+
+    /**
+     * Session key negotiation for message confidentiality. If the client sends
+     * NTLMSSP_NEGOTIATE_SEAL to the server in the NEGOTIATE_MESSAGE, the server
+     * MUST return NTLMSSP_NEGOTIATE_SEAL to the client in the CHALLENGE_MESSAGE.
+     * Clients and servers that set NTLMSSP_NEGOTIATE_SEAL SHOULD always set
+     * NTLMSSP_NEGOTIATE_56 and NTLMSSP_NEGOTIATE_128, if they are supported.
+     */
+    public static final int NTLMSSP_NEGOTIATE_SEAL = 0x00000020;
+
+    /**
+     * Session key negotiation for message signatures. If the client sends
+     * NTLMSSP_NEGOTIATE_SIGN to the server in the NEGOTIATE_MESSAGE, the server
+     * MUST return NTLMSSP_NEGOTIATE_SIGN to the client in the CHALLENGE_MESSAGE.
+     */
+    public static final int NTLMSSP_NEGOTIATE_SIGN = 0x00000010;
+
+    /**
+     * TargetName field of the CHALLENGE_MESSAGE (section 2.2.1.2) MUST be
+     * supplied.
+     */
+    public static final int NTLMSSP_REQUEST_TARGET = 0x00000004;
+
+    /**
+     * OEM character set encoding.
+     * 
+     * @see NTLMSSP_NEGOTIATE_UNICODE
+     */
+    public static final int NTLMSSP_NEGOTIATE_OEM = 0x00000002;
+
+    /**
+     * Unicode character set encoding.
+     * 
+     * The NTLMSSP_NEGOTIATE_UNICODE(A) and NTLM_NEGOTIATE_OEM(B) bits are
+     * evaluated together as follows:
+     * <ul>
+     * <li>A==1: The choice of character set encoding MUST be Unicode.
+     * 
+     * <li>A==0 and B==1: The choice of character set encoding MUST be OEM.
+     * 
+     * <li>A==0 and B==0: The protocol MUST return SEC_E_INVALID_TOKEN.
+     * <ul>
+     * */
+    public static final int NTLMSSP_NEGOTIATE_UNICODE = 0x00000001;
+
+    public int value;
+
+    public NegoFlags(int value) {
+        this.value = value;
+    }
+
+    public NegoFlags() {
+        this.value = 0;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("NegoFlags [value=0x%04x (%s)]", value, flagsToSting());
+    }
+
+    public String flagsToSting() {
+
+        String str = "";
+
+        if (NEGOTIATE_56())
+            str += "NEGOTIATE_56 ";
+        if (NEGOTIATE_KEY_EXCH())
+            str += "NEGOTIATE_KEY_EXCH ";
+        if (NEGOTIATE_128())
+            str += "NEGOTIATE_128 ";
+        if (NEGOTIATE_VERSION())
+            str += "NEGOTIATE_VERSION ";
+        if (NEGOTIATE_TARGET_INFO())
+            str += "NEGOTIATE_TARGET_INFO ";
+        if (REQUEST_NON_NT_SESSION_KEY())
+            str += "REQUEST_NON_NT_SESSION_KEY ";
+        if (NEGOTIATE_IDENTIFY())
+            str += "NEGOTIATE_IDENTIFY ";
+        if (NEGOTIATE_EXTENDED_SESSION_SECURITY())
+            str += "NEGOTIATE_EXTENDED_SESSION_SECURITY ";
+        if (TARGET_TYPE_SERVER())
+            str += "TARGET_TYPE_SERVER ";
+        if (TARGET_TYPE_DOMAIN())
+            str += "TARGET_TYPE_DOMAIN ";
+        if (NEGOTIATE_ALWAYS_SIGN())
+            str += "NEGOTIATE_ALWAYS_SIGN ";
+        if (NEGOTIATE_OEM_WORKSTATION_SUPPLIED())
+            str += "NEGOTIATE_OEM_WORKSTATION_SUPPLIED ";
+        if (NEGOTIATE_OEM_DOMAIN_SUPPLIED())
+            str += "NEGOTIATE_OEM_DOMAIN_SUPPLIED ";
+        if (NEGOTIATE_ANONYMOUS())
+            str += "NEGOTIATE_ANONYMOUS ";
+        if (NEGOTIATE_NTLM())
+            str += "NEGOTIATE_NTLM ";
+        if (NEGOTIATE_LM_KEY())
+            str += "NEGOTIATE_LM_KEY ";
+        if (NEGOTIATE_DATAGRAM())
+            str += "NEGOTIATE_DATAGRAM ";
+        if (NEGOTIATE_SEAL())
+            str += "NEGOTIATE_SEAL ";
+        if (NEGOTIATE_SIGN())
+            str += "NEGOTIATE_SIGN ";
+        if (REQUEST_TARGET())
+            str += "REQUEST_TARGET ";
+        if (NEGOTIATE_OEM())
+            str += "NEGOTIATE_OEM ";
+        if (NEGOTIATE_UNICODE())
+            str += "NEGOTIATE_UNICODE ";
+
+        return str;
+    }
+
+    public boolean NEGOTIATE_56() {
+        return ((value & NTLMSSP_NEGOTIATE_56) != 0);
+    }
+
+    public boolean NEGOTIATE_KEY_EXCH() {
+        return ((value & NTLMSSP_NEGOTIATE_KEY_EXCH) != 0);
+    }
+
+    public boolean NEGOTIATE_128() {
+        return ((value & NTLMSSP_NEGOTIATE_128) != 0);
+    }
+
+    public boolean NEGOTIATE_VERSION() {
+        return ((value & NTLMSSP_NEGOTIATE_VERSION) != 0);
+    }
+
+    public boolean NEGOTIATE_TARGET_INFO() {
+        return ((value & NTLMSSP_NEGOTIATE_TARGET_INFO) != 0);
+    }
+
+    public boolean REQUEST_NON_NT_SESSION_KEY() {
+        return ((value & NTLMSSP_REQUEST_NON_NT_SESSION_KEY) != 0);
+    }
+
+    public boolean NEGOTIATE_IDENTIFY() {
+        return ((value & NTLMSSP_NEGOTIATE_IDENTIFY) != 0);
+    }
+
+    public boolean NEGOTIATE_EXTENDED_SESSION_SECURITY() {
+        return ((value & NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY) != 0);
+    }
+
+    public boolean TARGET_TYPE_SERVER() {
+        return ((value & NTLMSSP_TARGET_TYPE_SERVER) != 0);
+    }
+
+    public boolean TARGET_TYPE_DOMAIN() {
+        return ((value & NTLMSSP_TARGET_TYPE_DOMAIN) != 0);
+    }
+
+    public boolean NEGOTIATE_ALWAYS_SIGN() {
+        return ((value & NTLMSSP_NEGOTIATE_ALWAYS_SIGN) != 0);
+    }
+
+    public boolean NEGOTIATE_OEM_WORKSTATION_SUPPLIED() {
+        return ((value & NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED) != 0);
+    }
+
+    public boolean NEGOTIATE_OEM_DOMAIN_SUPPLIED() {
+        return ((value & NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED) != 0);
+    }
+
+    public boolean NEGOTIATE_ANONYMOUS() {
+        return ((value & NTLMSSP_NEGOTIATE_ANONYMOUS) != 0);
+    }
+
+    public boolean NEGOTIATE_NTLM() {
+        return ((value & NTLMSSP_NEGOTIATE_NTLM) != 0);
+    }
+
+    public boolean NEGOTIATE_LM_KEY() {
+        return ((value & NTLMSSP_NEGOTIATE_LM_KEY) != 0);
+    }
+
+    public boolean NEGOTIATE_DATAGRAM() {
+        return ((value & NTLMSSP_NEGOTIATE_DATAGRAM) != 0);
+    }
+
+    public boolean NEGOTIATE_SEAL() {
+        return ((value & NTLMSSP_NEGOTIATE_SEAL) != 0);
+    }
+
+    public boolean NEGOTIATE_SIGN() {
+        return ((value & NTLMSSP_NEGOTIATE_SIGN) != 0);
+    }
+
+    public boolean REQUEST_TARGET() {
+        return ((value & NTLMSSP_REQUEST_TARGET) != 0);
+    }
+
+    public boolean NEGOTIATE_OEM() {
+        return ((value & NTLMSSP_NEGOTIATE_OEM) != 0);
+    }
+
+    public boolean NEGOTIATE_UNICODE() {
+        return ((value & NTLMSSP_NEGOTIATE_UNICODE) != 0);
+    }
+
+    public NegoFlags set_NEGOTIATE_56() {
+        value |= NTLMSSP_NEGOTIATE_56;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_KEY_EXCH() {
+        value |= NTLMSSP_NEGOTIATE_KEY_EXCH;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_128() {
+        value |= NTLMSSP_NEGOTIATE_128;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_VERSION() {
+        value |= NTLMSSP_NEGOTIATE_VERSION;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_TARGET_INFO() {
+        value |= NTLMSSP_NEGOTIATE_TARGET_INFO;
+        return this;
+    }
+
+    public NegoFlags set_REQUEST_NON_NT_SESSION_KEY() {
+        value |= NTLMSSP_REQUEST_NON_NT_SESSION_KEY;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_IDENTIFY() {
+        value |= NTLMSSP_NEGOTIATE_IDENTIFY;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_EXTENDED_SESSION_SECURITY() {
+        value |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY;
+        return this;
+    }
+
+    public NegoFlags set_TARGET_TYPE_SERVER() {
+        value |= NTLMSSP_TARGET_TYPE_SERVER;
+        return this;
+    }
+
+    public NegoFlags set_TARGET_TYPE_DOMAIN() {
+        value |= NTLMSSP_TARGET_TYPE_DOMAIN;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_ALWAYS_SIGN() {
+        value |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_OEM_WORKSTATION_SUPPLIED() {
+        value |= NTLMSSP_NEGOTIATE_OEM_WORKSTATION_SUPPLIED;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_OEM_DOMAIN_SUPPLIED() {
+        value |= NTLMSSP_NEGOTIATE_OEM_DOMAIN_SUPPLIED;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_ANONYMOUS() {
+        value |= NTLMSSP_NEGOTIATE_ANONYMOUS;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_NTLM() {
+        value |= NTLMSSP_NEGOTIATE_NTLM;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_LM_KEY() {
+        value |= NTLMSSP_NEGOTIATE_LM_KEY;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_DATAGRAM() {
+        value |= NTLMSSP_NEGOTIATE_DATAGRAM;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_SEAL() {
+        value |= NTLMSSP_NEGOTIATE_SEAL;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_SIGN() {
+        value |= NTLMSSP_NEGOTIATE_SIGN;
+        return this;
+    }
+
+    public NegoFlags set_REQUEST_TARGET() {
+        value |= NTLMSSP_REQUEST_TARGET;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_OEM() {
+        value |= NTLMSSP_NEGOTIATE_OEM;
+        return this;
+    }
+
+    public NegoFlags set_NEGOTIATE_UNICODE() {
+        value |= NTLMSSP_NEGOTIATE_UNICODE;
+        return this;
+    }
+
+    /**
+     * Example.
+     */
+
+    public static void main(String args[]) {
+
+        NegoFlags flags = new NegoFlags(0xe20882b7);
+        System.out.println("Negotiation flags: " + flags);
+
+    }
+
+}