libfreerdp-core: cleanup RTS header encoding
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Thu, 19 Apr 2012 19:43:20 +0000 (15:43 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Thu, 19 Apr 2012 19:43:20 +0000 (15:43 -0400)
include/freerdp/crypto/crypto.h
libfreerdp-core/rpc.c
libfreerdp-core/rpc.h
libfreerdp-core/rts.c
libfreerdp-core/rts.h
libfreerdp-crypto/crypto.c

index 5cbd074..d3c3d74 100644 (file)
@@ -142,8 +142,7 @@ FREERDP_API void crypto_rsa_private_decrypt(const uint8* input, int length, uint
 FREERDP_API void crypto_reverse(uint8* data, int length);
 FREERDP_API void crypto_nonce(uint8* nonce, int size);
 
-FREERDP_API char* crypto_encode_base64(uint8* data, int length);
-FREERDP_API void crypto_base64_encode(uint8* data, int length, uint8** enc_data, int* res_length);
+FREERDP_API char* crypto_base64_encode(uint8* data, int length);
 FREERDP_API void crypto_base64_decode(uint8* enc_data, int length, uint8** dec_data, int* res_length);
 
 #endif /* FREERDP_CRYPTO_H */
index 42b0709..a6ab3b1 100644 (file)
@@ -184,7 +184,7 @@ STREAM* rpc_ntlm_http_data(rdpRpc* rpc, char* command, SecBuffer* ntlm_token, ui
        HttpContext* http_context;
        HttpRequest* http_request;
 
-       base64_ntlm_token = crypto_encode_base64(ntlm_token->pvBuffer, ntlm_token->cbBuffer);
+       base64_ntlm_token = crypto_base64_encode(ntlm_token->pvBuffer, ntlm_token->cbBuffer);
 
        if (strcmp(command, "RPC_IN_DATA") == 0)
                http_context = rpc->http_in->context;
@@ -349,24 +349,39 @@ uint8* rpc_create_cookie()
 boolean rpc_out_send_CONN_A1(rdpRpc* rpc)
 {
        STREAM* s;
+       RTS_PDU_HEADER header;
        uint32 ReceiveWindowSize;
 
+       header.rpc_vers = 5;
+       header.rpc_vers_minor = 0;
+       header.ptype = PTYPE_RTS;
+       header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
+       header.packed_drep[0] = 0x10;
+       header.packed_drep[1] = 0x00;
+       header.packed_drep[2] = 0x00;
+       header.packed_drep[3] = 0x00;
+       header.frag_length = 76;
+       header.auth_length = 0;
+       header.call_id = 0;
+       header.flags = 0;
+       header.numberOfCommands = 4;
+
        DEBUG_RPC("Sending CONN_A1");
 
-       s = stream_new(76);
+       s = stream_new(header.frag_length);
        ReceiveWindowSize = 0x00010000;
        rpc->virtualConnectionCookie = rpc_create_cookie(); /* 16 bytes */
        rpc->OUTChannelCookie = rpc_create_cookie(); /* 16 bytes */
        rpc->AwailableWindow = ReceiveWindowSize;
 
-       rts_pdu_header_write(s, PFC_FIRST_FRAG | PFC_LAST_FRAG, 76, 0, 0, 0, 4); /* RTS Header (20 bytes) */
+       rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */
        rts_version_command_write(s); /* Version (8 bytes) */
        rts_cookie_command_write(s, rpc->virtualConnectionCookie); /* VirtualConnectionCookie (20 bytes) */
        rts_cookie_command_write(s, rpc->OUTChannelCookie); /* OUTChannelCookie (20 bytes) */
        rts_receive_window_size_command_write(s, ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */
        stream_seal(s);
 
-       rpc_out_write(rpc, s->data, stream_get_length(s));
+       rpc_out_write(rpc, s->data, s->size);
 
        stream_free(s);
 
@@ -376,15 +391,30 @@ boolean rpc_out_send_CONN_A1(rdpRpc* rpc)
 boolean rpc_in_send_CONN_B1(rdpRpc* rpc)
 {
        STREAM* s;
+       RTS_PDU_HEADER header;
        uint8* AssociationGroupId;
 
+       header.rpc_vers = 5;
+       header.rpc_vers_minor = 0;
+       header.ptype = PTYPE_RTS;
+       header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
+       header.packed_drep[0] = 0x10;
+       header.packed_drep[1] = 0x00;
+       header.packed_drep[2] = 0x00;
+       header.packed_drep[3] = 0x00;
+       header.frag_length = 104;
+       header.auth_length = 0;
+       header.call_id = 0;
+       header.flags = 0;
+       header.numberOfCommands = 6;
+
        DEBUG_RPC("Sending CONN_B1");
 
-       s = stream_new(104);
+       s = stream_new(header.frag_length);
        rpc->INChannelCookie = rpc_create_cookie(); /* 16 bytes */
        AssociationGroupId = rpc_create_cookie(); /* 16 bytes */
 
-       rts_pdu_header_write(s, PFC_FIRST_FRAG | PFC_LAST_FRAG, 104, 0, 0, 0, 6); /* RTS Header (20 bytes) */
+       rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */
        rts_version_command_write(s); /* Version (8 bytes) */
        rts_cookie_command_write(s, rpc->virtualConnectionCookie); /* VirtualConnectionCookie (20 bytes) */
        rts_cookie_command_write(s, rpc->INChannelCookie); /* INChannelCookie (20 bytes) */
@@ -402,35 +432,29 @@ boolean rpc_in_send_CONN_B1(rdpRpc* rpc)
 
 boolean rpc_in_send_keep_alive(rdpRpc* rpc)
 {
-       STREAM* s = stream_new(28);
-
-       uint8 rpc_vers = 0x05;
-       uint8 rpc_vers_minor = 0x00;
-       uint8 ptype = PTYPE_RTS;
-       uint8 pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
-       uint32 packet_drep = 0x00000010;
-       uint16 frag_length = 28;
-       uint16 auth_length = 0;
-       uint32 call_id = 0x00000000;
-       uint16 flags = 0x0002;
-       uint16 num_commands = 0x0001;
-       uint32 ckCommandType = 0x00000005;
-       uint32 ClientKeepalive = 0x00007530;
-
-       stream_write_uint8(s, rpc_vers);
-       stream_write_uint8(s, rpc_vers_minor);
-       stream_write_uint8(s, ptype);
-       stream_write_uint8(s, pfc_flags);
-       stream_write_uint32(s, packet_drep);
-       stream_write_uint16(s, frag_length);
-       stream_write_uint16(s, auth_length);
-       stream_write_uint32(s, call_id);
-       stream_write_uint16(s, flags);
-       stream_write_uint16(s, num_commands);
-       stream_write_uint32(s, ckCommandType);
-       stream_write_uint32(s, ClientKeepalive);
+       STREAM* s;
+       RTS_PDU_HEADER header;
+
+       header.rpc_vers = 5;
+       header.rpc_vers_minor = 0;
+       header.ptype = PTYPE_RTS;
+       header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG;
+       header.packed_drep[0] = 0x10;
+       header.packed_drep[1] = 0x00;
+       header.packed_drep[2] = 0x00;
+       header.packed_drep[3] = 0x00;
+       header.frag_length = 28;
+       header.auth_length = 0;
+       header.call_id = 0;
+       header.flags = 2;
+       header.numberOfCommands = 1;
+
+       s = stream_new(header.frag_length);
+       rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */
+       rts_client_keepalive_command_write(s, 0x00007530); /* ClientKeepalive (8 bytes) */
+       stream_seal(s);
 
-       rpc_in_write(rpc, s->data, stream_get_length(s));
+       rpc_in_write(rpc, s->data, s->size);
 
        stream_free(s);
 
@@ -709,96 +733,9 @@ int rpc_out_read_http_header(rdpRpc* rpc)
        return status;
 }
 
-int rpc_rts_recv(rdpRpc* rpc, uint8* pdu, int length)
-{
-       int i;
-       uint32 CommandType;
-       uint16 flags = *(uint16*)(pdu + 16);
-       uint16 num_commands = *(uint16*)(pdu + 18);
-       uint8* iterator = pdu + 20;
-
-       if (flags & RTS_FLAG_PING)
-       {
-               rpc_in_send_keep_alive(rpc);
-               return 0;
-       }
-
-       for (i = 0; i < num_commands; i++)
-       {
-               CommandType = *(uint32*) iterator;
-
-               switch (CommandType)
-               {
-                       case 0x00000000: /* ReceiveWindowSize */
-                               iterator += 8;
-                               break;
-
-                       case 0x00000001: /* FlowControlAck */
-                               iterator += 28;
-                               break;
-
-                       case 0x00000002: /* ConnectionTimeout */
-                               iterator += 8;
-                               break;
-
-                       case 0x00000003: /* Cookie */
-                               iterator += 20;
-                               break;
-
-                       case 0x00000004: /* ChannelLifetime */
-                               iterator += 8;
-                               break;
-
-                       case 0x00000005: /* ClientKeepalive */
-                               iterator += 8;
-                               break;
-
-                       case 0x00000006: /* Version */
-                               iterator += 8;
-                               break;
-
-                       case 0x00000007: /* Empty */
-                               iterator += 4;
-                               break;
-
-                       case 0x00000008: /* Padding */
-                               iterator += 8 + *(uint32*) (iterator + 4);
-                               break;
-
-                       case 0x00000009: /* NegativeANCE */
-                               iterator += 4;
-                               break;
-
-                       case 0x0000000a: /* ANCE */
-                               iterator += 4;
-                               break;
-
-                       case 0x0000000b: /* ClientAddress */
-                               iterator += 4 + 4 + (12 * (*(uint32*) (iterator + 4))) + 12;
-                               break;
-
-                       case 0x0000000c: /* AssociationGroupId */
-                               iterator += 20;
-                               break;
-
-                       case 0x0000000d: /* Destination */
-                               iterator += 8;
-                               break;
-
-                       case 0x0000000e: /* PingTrafficSentNotify */
-                               iterator += 8;
-                               break;
-
-                       default:
-                               printf(" Error: Unknown RTS CommandType: 0x%x\n", CommandType);
-                               return -1;
-               }
-       }
-       return 0;
-}
-
 int rpc_out_read(rdpRpc* rpc, uint8* data, int length)
 {
+       STREAM* s;
        int status;
        uint8* pdu;
        uint8 ptype;
@@ -831,7 +768,9 @@ int rpc_out_read(rdpRpc* rpc, uint8* data, int length)
 
        if (ptype == 0x14) /* RTS PDU */
        {
-               rpc_rts_recv(rpc, pdu, frag_length);
+               s = stream_new(0);
+               stream_attach(s, pdu, frag_length);
+               rts_pdu_recv(rpc, s);
                xfree(pdu);
                return 0;
        }
index 8d8453a..00307e7 100644 (file)
@@ -593,6 +593,8 @@ void ntlm_free(rdpNtlm* ntlm);
 boolean rpc_attach(rdpRpc* rpc, rdpTcp* tcp_in, rdpTcp* tcp_out, rdpTls* tls_in, rdpTls* tls_out);
 boolean rpc_connect(rdpRpc* rpc);
 
+boolean rpc_in_send_keep_alive(rdpRpc* rpc);
+
 int rpc_write(rdpRpc* rpc, uint8* data, int length, uint16 opnum);
 int rpc_read(rdpRpc* rpc, uint8* data, int length);
 
index dc62b2b..1139b1c 100644 (file)
 
 #include "rts.h"
 
-void rts_pdu_header_write(STREAM* s, uint8 pfc_flags, uint16 frag_length,
-               uint16 auth_length, uint32 call_id, uint16 flags, uint16 numberOfCommands)
+void rts_pdu_header_write(STREAM* s, RTS_PDU_HEADER* header)
 {
-       stream_write_uint8(s, 5); /* rpc_vers (1 byte) */
-       stream_write_uint8(s, 0); /* rpc_vers_minor (1 byte) */
-       stream_write_uint8(s, PTYPE_RTS); /* PTYPE (1 byte) */
-       stream_write_uint8(s, pfc_flags); /* pfc_flags (1 byte) */
-       stream_write_uint32(s, 0x00000010); /* packet_drep (4 bytes) */
-       stream_write_uint16(s, frag_length); /* frag_length (2 bytes) */
-       stream_write_uint16(s, auth_length); /* auth_length (2 bytes) */
-       stream_write_uint32(s, call_id); /* call_id (4 bytes) */
-       stream_write_uint16(s, flags); /* flags (2 bytes) */
-       stream_write_uint16(s, numberOfCommands); /* numberOfCommands (2 bytes) */
+       stream_write_uint8(s, header->rpc_vers); /* rpc_vers (1 byte) */
+       stream_write_uint8(s, header->rpc_vers_minor); /* rpc_vers_minor (1 byte) */
+       stream_write_uint8(s, header->ptype); /* PTYPE (1 byte) */
+       stream_write_uint8(s, header->pfc_flags); /* pfc_flags (1 byte) */
+       stream_write_uint8(s, header->packed_drep[0]); /* packet_drep[0] (1 byte) */
+       stream_write_uint8(s, header->packed_drep[1]); /* packet_drep[1] (1 byte) */
+       stream_write_uint8(s, header->packed_drep[2]); /* packet_drep[2] (1 byte) */
+       stream_write_uint8(s, header->packed_drep[3]); /* packet_drep[3] (1 byte) */
+       stream_write_uint16(s, header->frag_length); /* frag_length (2 bytes) */
+       stream_write_uint16(s, header->auth_length); /* auth_length (2 bytes) */
+       stream_write_uint32(s, header->call_id); /* call_id (4 bytes) */
+       stream_write_uint16(s, header->flags); /* flags (2 bytes) */
+       stream_write_uint16(s, header->numberOfCommands); /* numberOfCommands (2 bytes) */
 }
 
 void rts_receive_window_size_command_write(STREAM* s, uint32 receiveWindowSize)
@@ -64,8 +66,131 @@ void rts_version_command_write(STREAM* s)
        stream_write_uint32(s, 1); /* Version (4 bytes) */
 }
 
+void rts_padding_command_read(STREAM* s)
+{
+       uint32 ConformanceCount;
+
+       stream_read_uint32(s, ConformanceCount); /* ConformanceCount (4 bytes) */
+       stream_seek(s, ConformanceCount); /* Padding (variable) */
+}
+
 void rts_association_group_id_command_write(STREAM* s, uint8* associationGroupId)
 {
        stream_write_uint32(s, RTS_CMD_ASSOCIATION_GROUP_ID); /* CommandType (4 bytes) */
        stream_write(s, associationGroupId, 16); /* AssociationGroupId (16 bytes) */
 }
+
+void rts_client_address_command_read(STREAM* s)
+{
+       uint32 AddressType;
+
+       stream_read_uint32(s, AddressType); /* ConformanceCount (4 bytes) */
+
+       if (AddressType == 0)
+       {
+               stream_seek(s, 4); /* ClientAddress (4 bytes) */
+       }
+       else
+       {
+               stream_seek(s, 16); /* ClientAddress (16 bytes) */
+       }
+
+       stream_seek(s, 12); /* padding (12 bytes) */
+}
+
+int rts_pdu_recv(rdpRpc* rpc, STREAM* s)
+{
+       int i;
+       uint16 flags;
+       uint32 CommandType;
+       uint16 numberOfCommands;
+
+       stream_seek_uint8(s); /* rpc_vers (1 byte) */
+       stream_seek_uint8(s); /* rpc_vers_minor (1 byte) */
+       stream_seek_uint8(s); /* PTYPE (1 byte) */
+       stream_seek_uint8(s); /* pfc_flags (1 byte) */
+       stream_seek_uint32(s); /* packet_drep (4 bytes) */
+       stream_seek_uint16(s); /* frag_length (2 bytes) */
+       stream_seek_uint16(s); /* auth_length (2 bytes) */
+       stream_seek_uint32(s); /* call_id (4 bytes) */
+       stream_read_uint16(s, flags); /* flags (2 bytes) */
+       stream_read_uint16(s, numberOfCommands); /* numberOfCommands (2 bytes) */
+
+       if (flags & RTS_FLAG_PING)
+       {
+               rpc_in_send_keep_alive(rpc);
+               return 0;
+       }
+
+       for (i = 0; i < numberOfCommands; i++)
+       {
+               stream_read_uint32(s, CommandType); /* CommandType (4 bytes) */
+
+               switch (CommandType)
+               {
+                       case RTS_CMD_RECEIVE_WINDOW_SIZE:
+                               stream_seek(s, 4);
+                               break;
+
+                       case RTS_CMD_FLOW_CONTROL_ACK:
+                               stream_seek(s, 24);
+                               break;
+
+                       case RTS_CMD_CONNECTION_TIMEOUT:
+                               stream_seek(s, 4);
+                               break;
+
+                       case RTS_CMD_COOKIE:
+                               stream_seek(s, 16);
+                               break;
+
+                       case RTS_CMD_CHANNEL_LIFETIME:
+                               stream_seek(s, 4);
+                               break;
+
+                       case RTS_CMD_CLIENT_KEEPALIVE:
+                               stream_seek(s, 4);
+                               break;
+
+                       case RTS_CMD_VERSION:
+                               stream_seek(s, 4);
+                               break;
+
+                       case RTS_CMD_EMPTY:
+                               break;
+
+                       case RTS_CMD_PADDING:
+                               rts_padding_command_read(s);
+                               break;
+
+                       case RTS_CMD_NEGATIVE_ANCE:
+                               break;
+
+                       case RTS_CMD_ANCE:
+                               break;
+
+                       case RTS_CMD_CLIENT_ADDRESS:
+                               rts_client_address_command_read(s);
+                               break;
+
+                       case RTS_CMD_ASSOCIATION_GROUP_ID:
+                               stream_seek(s, 16);
+                               break;
+
+                       case RTS_CMD_DESTINATION:
+                               stream_seek(s, 4);
+                               break;
+
+                       case RTS_CMD_PING_TRAFFIC_SENT_NOTIFY:
+                               stream_seek(s, 4);
+                               break;
+
+                       default:
+                               printf(" Error: Unknown RTS Command Type: 0x%x\n", CommandType);
+                               return -1;
+                               break;
+               }
+       }
+
+       return 0;
+}
index 9ce8cfb..f29208a 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef FREERDP_CORE_RTS_H
 #define FREERDP_CORE_RTS_H
 
+#include "rpc.h"
+
 #include <freerdp/types.h>
 #include <freerdp/utils/stream.h>
 
 #define RTS_CMD_DESTINATION                    0x0000000D
 #define RTS_CMD_PING_TRAFFIC_SENT_NOTIFY       0x0000000E
 
-void rts_pdu_header_write(STREAM* s, uint8 pfc_flags, uint16 frag_length,
-               uint16 auth_length, uint32 call_id, uint16 flags, uint16 numberOfCommands);
+struct _rts_pdu_header
+{
+       uint8 rpc_vers;
+       uint8 rpc_vers_minor;
+       uint8 ptype;
+       uint8 pfc_flags;
+       uint8 packed_drep[4];
+       uint16 frag_length;
+       uint16 auth_length;
+       uint32 call_id;
+       uint16 flags;
+       uint16 numberOfCommands;
+};
+typedef struct _rts_pdu_header RTS_PDU_HEADER;
+
+void rts_pdu_header_write(STREAM* s, RTS_PDU_HEADER* header);
 
 void rts_receive_window_size_command_write(STREAM* s, uint32 receiveWindowSize);
 void rts_cookie_command_write(STREAM* s, uint8* cookie);
 void rts_channel_lifetime_command_write(STREAM* s, uint32 channelLifetime);
 void rts_client_keepalive_command_write(STREAM* s, uint32 clientKeepalive);
 void rts_version_command_write(STREAM* s);
+void rts_padding_command_read(STREAM* s);
 void rts_association_group_id_command_write(STREAM* s, uint8* associationGroupId);
+void rts_client_address_command_read(STREAM* s);
+
+int rts_pdu_recv(rdpRpc* rpc, STREAM* s);
 
 #endif /* FREERDP_CORE_RTS_H */
index 3b38a0c..93a114e 100644 (file)
@@ -511,27 +511,7 @@ void crypto_cert_print_info(X509* xcert)
        xfree(fp);
 }
 
-void crypto_base64_encode(uint8* data, int length, uint8** enc_data, int* res_length)
-{
-      BIO *bmem, *b64;
-      BUF_MEM *bptr;
-
-      b64 = BIO_new(BIO_f_base64());
-      BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
-      bmem = BIO_new(BIO_s_mem());
-      b64 = BIO_push(b64, bmem);
-      BIO_write(b64, data, length);
-      BIO_flush(b64);
-      BIO_get_mem_ptr(b64, &bptr);
-
-      *res_length = bptr->length - 1;
-      *enc_data = xmalloc(*res_length);
-      memcpy(*enc_data, bptr->data, *res_length);
-
-      BIO_free_all(b64);
-}
-
-char* crypto_encode_base64(uint8* data, int length)
+char* crypto_base64_encode(uint8* data, int length)
 {
        BIO* bmem;
        BIO* b64;
@@ -543,7 +523,10 @@ char* crypto_encode_base64(uint8* data, int length)
        bmem = BIO_new(BIO_s_mem());
        b64 = BIO_push(b64, bmem);
        BIO_write(b64, data, length);
-       BIO_flush(b64);
+
+       if (BIO_flush(b64) < 1)
+               return NULL;
+
        BIO_get_mem_ptr(b64, &bptr);
 
        base64_string = xmalloc(bptr->length);