]> git.sesse.net Git - rdpsrv/blobdiff - mcs.c
Fill in some blanks on our crypto header. Change to tsstud again for protodiff.
[rdpsrv] / mcs.c
diff --git a/mcs.c b/mcs.c
index 460e0d4b6610957900c42c8dc2514807b5265583..4190e49772d297ffd49ddd299645e82f6b22cae7 100644 (file)
--- a/mcs.c
+++ b/mcs.c
@@ -89,19 +89,37 @@ ber_out_integer(STREAM s, int value)
        out_uint16_be(s, value);
 }
 
+static void
+ber_out_uint8(STREAM s, uint8 value)
+{
+       ber_out_header(s, BER_TAG_INTEGER, 1);
+       out_uint8(s, value);
+}
+
+static void
+ber_in_integer(STREAM s, int *value)
+{
+       int length;
+       ber_parse_header(s, BER_TAG_INTEGER, &length);
+       in_uint16_be(s, *value);
+}
+
 /* Output a DOMAIN_PARAMS structure (ASN.1 BER) */
 static void
 mcs_out_domain_params(STREAM s, int max_channels, int max_users, int max_tokens, int max_pdusize)
 {
-       ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 32);
-       ber_out_integer(s, max_channels);
-       ber_out_integer(s, max_users);
-       ber_out_integer(s, max_tokens);
-       ber_out_integer(s, 1);  /* num_priorities */
-       ber_out_integer(s, 0);  /* min_throughput */
-       ber_out_integer(s, 1);  /* max_height */
-       ber_out_integer(s, max_pdusize);
-       ber_out_integer(s, 2);  /* ver_protocol */
+       ber_out_header(s, MCS_TAG_DOMAIN_PARAMS, 26);
+       ber_out_uint8(s, 34); // max_channels
+       ber_out_uint8(s, 3);  // max_users
+       ber_out_uint8(s, 0);  // max_tokens
+       ber_out_uint8(s, 1);  // num_priorities 
+       ber_out_uint8(s, 0);  // min_throughput
+       ber_out_uint8(s, 1);  // max_height
+       ber_out_header(s, BER_TAG_INTEGER, 3); // pdu size
+       out_uint8(s, 0x00);
+       out_uint8(s, 0xff);
+       out_uint8(s, 0xf8);
+       ber_out_uint8(s, 2);  // ver_protocol
 }
 
 /* Parse a DOMAIN_PARAMS structure (ASN.1 BER) */
@@ -109,10 +127,34 @@ static BOOL
 mcs_parse_domain_params(STREAM s)
 {
        int length;
+       int max_channels, max_users, max_tokens, max_pdusize;
+       int num_priorities, min_throughput, max_height;
+       int ver_protocol;
 
        ber_parse_header(s, MCS_TAG_DOMAIN_PARAMS, &length);
-       in_uint8s(s, length);
-
+       printf("MCS_TAG_DOMAIN_PARAMS, len %u (expected 32)\n", length);
+       if (length == 32) {
+               ber_in_integer(s, &max_channels);
+               ber_in_integer(s, &max_users);
+               ber_in_integer(s, &max_tokens);
+               ber_in_integer(s, &num_priorities);
+               ber_in_integer(s, &min_throughput);
+               ber_in_integer(s, &max_height);
+               ber_in_integer(s, &max_pdusize);
+               ber_in_integer(s, &ver_protocol);
+
+               printf("max_channels=%u\n", max_channels);
+               printf("max_users=%u\n", max_users);
+               printf("max_tokens=%u\n", max_tokens);
+               printf("num_priorities=%u\n", num_priorities);
+               printf("min_throughput=%u\n", min_throughput);
+               printf("max_pdusize=%u\n", max_pdusize);
+               printf("ver_protocol=%u\n", ver_protocol);
+       } else {
+               hexdump(s->p, length);
+               in_uint8s(s, length);
+       }
+       
        return s_check(s);
 }
 
@@ -151,36 +193,139 @@ mcs_recv_connect_initial()
        return s_check_end(s);
 }
 
+/* key generated with "openssl genrsa 512 | openssl rsa -text":
+modulus:
+    00:b1:e0:36:2f:fd:dd:8b:d6:64:e9:2b:14:f8:b9:
+    0b:ba:3b:b7:0a:f1:f3:97:56:93:38:01:2f:d1:31:
+    2d:70:59:de:97:6a:61:3f:cb:a4:b4:12:05:89:14:
+    d9:b0:8a:70:03:b6:f1:ad:c5:b9:19:9b:b9:8f:03:
+    51:bf:fe:f8:e5
+publicExponent: 65537 (0x10001)
+privateExponent:
+    00:a4:86:68:58:97:8d:f6:2c:06:06:8d:ac:c6:2a:
+    12:a8:dd:56:ff:2e:b0:4b:08:ee:fe:dc:4a:28:4a:
+    3e:67:2d:8e:08:6b:5f:87:69:a4:c5:a0:e7:50:1a:
+    f0:71:03:46:f2:52:7c:e6:09:40:40:61:51:76:32:
+    f8:28:72:99:41
+prime1:
+    00:db:46:d9:34:10:ce:0d:f6:f7:48:30:0f:2b:f6:
+    4d:66:40:27:00:97:db:48:77:cd:96:b5:a6:51:81:
+    a1:7c:ad
+prime2:
+    00:cf:aa:5c:d3:8a:0d:d4:91:a6:40:92:ff:2c:31:
+    d6:f9:08:8d:e8:d2:a8:2f:89:a6:88:2c:61:68:8e:
+    ee:7c:19
+*/
+unsigned char my_modulus[SEC_MODULUS_SIZE] = {
+       0xe5, 0xf8, 0xfe, 0xbf, 0x51,
+       0x03, 0x8f, 0xb9, 0x9b, 0x19, 0xb9, 0xc5, 0xad, 0xf1, 0xb6, 0x03, 0x70, 0x8a, 0xb0, 0xd9,
+       0x14, 0x89, 0x05, 0x12, 0xb4, 0xa4, 0xcb, 0x3f, 0x61, 0x6a, 0x97, 0xde, 0x59, 0x70, 0x2d,
+       0x31, 0xd1, 0x2f, 0x01, 0x38, 0x93, 0x56, 0x97, 0xf3, 0xf1, 0x0a, 0xb7, 0x3b, 0xba, 0x0b,
+       0xb9, 0xf8, 0x14, 0x2b, 0xe9, 0x64, 0xd6, 0x8b, 0xdd, 0xfd, 0x2f, 0x36, 0xe0, 0xb1
+};
+unsigned char my_exponent[SEC_EXPONENT_SIZE] = {
+       0x01, 0x00, 0x01, 0x00
+};
+unsigned char my_private_exponent[] = {
+       0x41, 0x99, 0x72, 0x28, 0xf8,
+       0x32, 0x76, 0x51, 0x61, 0x40, 0x40, 0x09, 0xe6, 0x7c, 0x52, 0xf2, 0x46, 0x03, 0x71, 0xf0,
+       0x1a, 0x50, 0xe7, 0xa0, 0xc5, 0xa4, 0x69, 0x87, 0x5f, 0x6b, 0x08, 0x8e, 0x2d, 0x67, 0x3e,
+       0x4a, 0x28, 0x4a, 0xdc, 0xfe, 0xee, 0x08, 0x4b, 0xb0, 0x2e, 0xff, 0x56, 0xdd, 0xa8, 0x12,
+       0x2a, 0xc6, 0xac, 0x8d, 0x06, 0x06, 0x2c, 0xf6, 0x8d, 0x97, 0x58, 0x68, 0x86, 0xa4
+};
+
 void
 mcs_send_connect_response()
 {
        STREAM s;
+       int i, length;
 
-       s = iso_init(80);  // FIXME
+       s = iso_init(250);
+       printf("INITLEN: %u\n", s->p - s->iso_hdr);
 
-       ber_out_header(s, MCS_CONNECT_RESPONSE, 80);
+       ber_out_header(s, MCS_CONNECT_RESPONSE, 245);
        ber_out_header(s, BER_TAG_RESULT, 1);
        out_uint8(s, 0);
 
        ber_out_header(s, BER_TAG_INTEGER, 1);
-       out_uint8(s, 1);  // connect id
+       out_uint8(s, 0);  // connect id
        
        mcs_out_domain_params(s, 34, 2, 0, 0xffff);  // dumdidum?
 
-       ber_out_header(s, BER_TAG_OCTET_STRING, 28);
-
-       out_uint8s(s, 21);   // ick
-       out_uint8(s, 0);
+       ber_out_header(s, BER_TAG_OCTET_STRING, 207);
+
+       // some unknown header of sorts
+       out_uint8(s, 0x00);
+       out_uint8(s, 0x05);
+       out_uint8(s, 0x00);
+       out_uint8(s, 0x14);
+       out_uint8(s, 0x7c);
+       out_uint8(s, 0x00);
+       out_uint8(s, 0x01);
+       out_uint8(s, 0x2a);
+       out_uint8(s, 0x14);
+       out_uint8(s, 0x76);
+       out_uint8(s, 0x0a); 
+       out_uint8(s, 0x01);
+       out_uint8(s, 0x01);
+       out_uint8(s, 0x00);
+       out_uint8(s, 0x01);
+       out_uint8(s, 0xc0);
+       out_uint8(s, 0x00);
+       out_uint8(s, 0x4d);
+       out_uint8(s, 0x63);
+       out_uint8(s, 0x44);
+       out_uint8(s, 0x6e);
+
+       length = 184;
+       
+       // two bytes of length
+       out_uint8(s, 0x80 | (length >> 7));
+       out_uint8(s, length & 0x7f);
 
        // server info -- we claim to support RDP5
        out_uint16_le(s, SEC_TAG_SRV_INFO);
-       out_uint16_le(s, 6);  // length
-       out_uint16_le(s, 5);
-
-       // aiee, no crypto info yet! :-)
+       out_uint16_le(s, 8);  // length
+       out_uint16_le(s, 4);  // version
+       out_uint16_le(s, 8);  // unknown
+
+       // channel info -- open a few channels
+       out_uint16_le(s, SEC_TAG_SRV_CHANNELS);
+       out_uint16_le(s, 16); // length
+       out_uint16_le(s, 1003);
+       out_uint16_le(s, 3);
+       out_uint16_le(s, 1004);
+       out_uint16_le(s, 1005);
+       out_uint16_le(s, 1006);
+       out_uint16_le(s, 0);
+       
+       // crypto info
+       out_uint16_le(s, SEC_TAG_SRV_CRYPT);
+       out_uint16_le(s, 156); // length
+       out_uint32_le(s, 2); // 128-bit
+       out_uint32_le(s, 3); // high
+
+       out_uint32_le(s, SEC_RANDOM_SIZE); // random_len
+       out_uint32_le(s, 92);              // rsa_info_len
+       out_uint8s(s, SEC_RANDOM_SIZE);    // server_random
+       out_uint32_le(s, 1);               // RDP4-style
+       // unknown
+       out_uint32_le(s, 1);            
+       out_uint32_le(s, 1);
+
+       out_uint16_le(s, SEC_TAG_PUBKEY);
+       out_uint16_le(s, 92);
+       out_uint32_le(s, SEC_RSA_MAGIC);
+       out_uint32_le(s, SEC_MODULUS_SIZE + SEC_PADDING_SIZE);  // modulus_len
+       out_uint32_le(s, SEC_MODULUS_SIZE * 8);                 // modulus_bits
+       out_uint32_le(s, 0x3f);                                 // unknown
+       out_uint8p(s, my_exponent, SEC_EXPONENT_SIZE);
+       out_uint8p(s, my_modulus, SEC_MODULUS_SIZE);
+       out_uint8s(s, SEC_PADDING_SIZE);
        
        s_mark_end(s);
-       printf("LEN: %u\n", s->p - s->iso_hdr);
        iso_send(s);
 
 }
@@ -221,11 +366,11 @@ mcs_send_aucf(uint16 mcs_userid)
 {
        STREAM s;
 
-       s = iso_init(5);
+       s = iso_init(4);
 
        out_uint8(s, (MCS_AUCF << 2) | 2);  // | 2 = send user ID
        out_uint8(s, 0);  // success
-       out_uint16_be(s, 0);
+       out_uint16_be(s, 6);
        
        s_mark_end(s);
        iso_send(s);
@@ -250,35 +395,21 @@ mcs_send_cjrq(uint16 chanid)
 }
 
 /* Expect a CJcf message (ASN.1 PER) */
-static BOOL
-mcs_recv_cjcf(void)
+static void
+mcs_send_cjcf(uint16 userid, uint16 chanid)
 {
-       uint8 opcode, result;
        STREAM s;
 
-       s = iso_recv();
-       if (s == NULL)
-               return False;
+       s = iso_init(8);
 
-       in_uint8(s, opcode);
-       if ((opcode >> 2) != MCS_CJCF)
-       {
-               error("expected CJcf, got %d\n", opcode);
-               return False;
-       }
-
-       in_uint8(s, result);
-       if (result != 0)
-       {
-               error("CJrq: %d\n", result);
-               return False;
-       }
-
-       in_uint8s(s, 4);        /* mcs_userid, req_chanid */
-       if (opcode & 2)
-               in_uint8s(s, 2);        /* join_chanid */
+       out_uint8(s, (MCS_CJCF << 2) | 2);
+       out_uint8(s, 0); // success
+       out_uint16_be(s, 6);
+       out_uint16_be(s, chanid);
+       out_uint16_be(s, chanid);
 
-       return s_check_end(s);
+       s_mark_end(s);
+       iso_send(s);
 }
 
 /* Initialise an MCS transport data packet */
@@ -303,7 +434,7 @@ mcs_send_to_channel(STREAM s, uint16 channel)
        length = s->end - s->p - 8;
        length |= 0x8000;
 
-       out_uint8(s, (MCS_SDRQ << 2));
+       out_uint8(s, (MCS_SDIN << 2));
        out_uint16_be(s, g_mcs_userid);
        out_uint16_be(s, channel);
        out_uint8(s, 0x70);     /* flags */
@@ -323,7 +454,7 @@ mcs_send(STREAM s)
 STREAM
 mcs_recv(uint16 * channel)
 {
-       uint8 opcode, appid, length;
+       uint8 opcode, appid, length, userid;
        STREAM s;
 
        s = iso_recv();
@@ -334,7 +465,7 @@ mcs_recv(uint16 * channel)
        appid = opcode >> 2;
 
        switch (appid) {
-       case MCS_SDIN:
+       case MCS_SDRQ:
                in_uint8s(s, 2);        /* userid */
                in_uint16_be(s, *channel);
                in_uint8s(s, 1);        /* flags */
@@ -344,6 +475,7 @@ mcs_recv(uint16 * channel)
 
                return s;
        case MCS_DPUM:
+               printf("Received DPUM (?)\n");
                return NULL;
        case MCS_EDRQ:
                // Erect Domain (ignore)
@@ -354,6 +486,13 @@ mcs_recv(uint16 * channel)
                printf("Received AUrq, sending AUcf\n");
                mcs_send_aucf(0);
                return NULL;
+       case MCS_CJRQ:
+               // Channel Join Request, respond with CJcf (Channel Join Confirm);
+               in_uint16_be(s, userid);
+               in_uint16_be(s, *channel);
+               printf("Received CJrq for channel %hu, sending CJcf\n", *channel);
+               mcs_send_cjcf(userid, *channel);
+               return NULL;
        default:
                error("expected data, got %d\n", opcode);
                return NULL;