libfreerdp-core: PER and BER encoding, along with unit tests
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Mon, 4 Jul 2011 21:05:58 +0000 (17:05 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Mon, 4 Jul 2011 21:05:58 +0000 (17:05 -0400)
14 files changed:
cunit/CMakeLists.txt
cunit/test_ber.c [new file with mode: 0644]
cunit/test_ber.h [new file with mode: 0644]
cunit/test_freerdp.c
cunit/test_freerdp.h
cunit/test_per.c [new file with mode: 0644]
cunit/test_per.h [new file with mode: 0644]
include/freerdp/utils/stream.h
libfreerdp-core/CMakeLists.txt
libfreerdp-core/ber.c
libfreerdp-core/gcc.c [new file with mode: 0644]
libfreerdp-core/gcc.h [new file with mode: 0644]
libfreerdp-core/per.c [new file with mode: 0644]
libfreerdp-core/per.h [new file with mode: 0644]

index 3c1ef1a..769199c 100644 (file)
@@ -23,6 +23,10 @@ include_directories(../libfreerdp-core)
 include_directories(../libfreerdp-gdi)
 
 add_executable(test_freerdp
+       test_per.c
+       test_per.h
+       test_ber.c
+       test_ber.h
        test_color.c
        test_color.h
        test_libgdi.c
diff --git a/cunit/test_ber.c b/cunit/test_ber.c
new file mode 100644 (file)
index 0000000..719f79f
--- /dev/null
@@ -0,0 +1,95 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * Basic Encoding Rules (BER) Unit Tests
+ *
+ * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed 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.
+ */
+
+#include <freerdp/freerdp.h>
+#include <freerdp/utils/hexdump.h>
+#include <freerdp/utils/stream.h>
+
+#include "test_ber.h"
+
+int init_ber_suite(void)
+{
+       return 0;
+}
+
+int clean_ber_suite(void)
+{
+       return 0;
+}
+
+int add_ber_suite(void)
+{
+       add_test_suite(ber);
+
+       add_test_function(ber_write_length);
+       add_test_function(ber_write_universal_tag);
+       add_test_function(ber_write_application_tag);
+
+       return 0;
+}
+
+uint8 ber_length_expected_1[1] = "\x40"; /* 64 */
+uint8 ber_length_expected_2[3] = "\x82\x01\x94"; /* 404 */
+
+void test_ber_write_length(void)
+{
+       STREAM *s1, *s2;
+
+       s1 = stream_new(sizeof(ber_length_expected_1));
+       s2 = stream_new(sizeof(ber_length_expected_2));
+
+       ber_write_length(s1, 64);
+       ASSERT_STREAM(s1, (uint8*) ber_length_expected_1, sizeof(ber_length_expected_1));
+
+       ber_write_length(s2, 404);
+       ASSERT_STREAM(s2, (uint8*) ber_length_expected_2, sizeof(ber_length_expected_2));
+
+       stream_free(s1);
+       stream_free(s2);
+}
+
+/* BOOLEAN, length 1, without value */
+uint8 ber_universal_tag_expected[2] = "\x01\x01";
+
+void test_ber_write_universal_tag(void)
+{
+       STREAM* s;
+
+       s = stream_new(sizeof(ber_universal_tag_expected));
+       ber_write_universal_tag(s, 1, 1);
+
+       ASSERT_STREAM(s, (uint8*) ber_universal_tag_expected, sizeof(ber_universal_tag_expected));
+
+       stream_free(s);
+}
+
+/* T.125 MCS Application 101 (Connect-Initial), length 404 */
+uint8 ber_application_tag_expected[5] = "\x7F\x65\x82\x01\x94";
+
+void test_ber_write_application_tag(void)
+{
+       STREAM* s;
+
+       s = stream_new(sizeof(ber_application_tag_expected));
+       ber_write_application_tag(s, 101, 404);
+
+       ASSERT_STREAM(s, (uint8*) ber_application_tag_expected, sizeof(ber_application_tag_expected));
+
+       stream_free(s);
+}
diff --git a/cunit/test_ber.h b/cunit/test_ber.h
new file mode 100644 (file)
index 0000000..0cc9228
--- /dev/null
@@ -0,0 +1,28 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * Basic Encoding Rules (BER) Unit Tests
+ *
+ * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed 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.
+ */
+
+#include "test_freerdp.h"
+
+int init_ber_suite(void);
+int clean_ber_suite(void);
+int add_ber_suite(void);
+
+void test_ber_write_length(void);
+void test_ber_write_universal_tag(void);
+void test_ber_write_application_tag(void);
index 23ba54c..0e22a01 100644 (file)
  * limitations under the License.
  */
 
-#include "CUnit/Basic.h"
+#include <CUnit/Basic.h>
 
+#include "test_per.h"
+#include "test_ber.h"
 #include "test_color.h"
 #include "test_libgdi.h"
 #include "test_stream.h"
@@ -51,6 +53,41 @@ void dump_data(unsigned char * p, int len, int width, char* name)
        printf("\n");
 }
 
+void assert_stream(STREAM* s, uint8* data, int length, const char* func, int line)
+{
+       int i;
+       char* str;
+       int actual_length;
+       uint8* actual_data;
+
+       actual_length = stream_get_length(s);
+
+       if (actual_length != length)
+       {
+               printf("\n %s (%d): length mismatch, actual:%d, expected:%d", func, line, actual_length, length);
+               CU_FAIL("assert_stream, length mismatch");
+               return;
+       }
+
+       actual_data = s->buffer;
+       for (i = 0; i < length; i++)
+       {
+               if (actual_data[i] != data[i])
+               {
+                       printf("\n %s (%d): buffer mismatch:\n", func, line);
+
+                       printf("\nActual:\n");
+                       freerdp_hexdump(actual_data, length);
+
+                       printf("Expected:\n");
+                       freerdp_hexdump(data, length);
+
+                       CU_FAIL("assert_stream, buffer mismatch");
+                       return;
+               }
+       }
+}
+
 int main(int argc, char* argv[])
 {
        int index = 1;
@@ -61,6 +98,8 @@ int main(int argc, char* argv[])
 
        if (argc < *pindex + 1)
        {
+               add_per_suite();
+               add_ber_suite();
                add_color_suite();
                add_libgdi_suite();
                add_stream_suite();
@@ -86,6 +125,14 @@ int main(int argc, char* argv[])
                        {
                                add_transport_suite();
                        }
+                       else if (strcmp("per", argv[*pindex]) == 0)
+                       {
+                               add_per_suite();
+                       }
+                       else if (strcmp("ber", argv[*pindex]) == 0)
+                       {
+                               add_ber_suite();
+                       }
 
                        *pindex = *pindex + 1;
                }
index ca8e029..f1068f4 100644 (file)
  */
 
 #include <stdio.h>
-#include "CUnit/Basic.h"
+#include <stdlib.h>
+#include <string.h>
+#include <CUnit/Basic.h>
+#include <freerdp/types/base.h>
+#include <freerdp/utils/stream.h>
+#include <freerdp/utils/hexdump.h>
 
 #define add_test_suite(name) \
        CU_pSuite pSuite; \
@@ -33,3 +38,6 @@
        }
 
 void dump_data(unsigned char * p, int len, int width, char* name);
+void assert_stream(STREAM* s, uint8* data, int length, const char* func, int line);
+
+#define ASSERT_STREAM(_s, _data, _length) assert_stream(_s, _data, _length, __FUNCTION__, __LINE__)
diff --git a/cunit/test_per.c b/cunit/test_per.c
new file mode 100644 (file)
index 0000000..ad8392b
--- /dev/null
@@ -0,0 +1,63 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * Packed Encoding Rules (PER) Unit Tests
+ *
+ * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed 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.
+ */
+
+#include <freerdp/freerdp.h>
+#include <freerdp/utils/hexdump.h>
+#include <freerdp/utils/stream.h>
+
+#include "test_per.h"
+
+int init_per_suite(void)
+{
+       return 0;
+}
+
+int clean_per_suite(void)
+{
+       return 0;
+}
+
+int add_per_suite(void)
+{
+       add_test_suite(per);
+
+       add_test_function(per_write_length);
+       add_test_function(per_write_object_identifier);
+
+       return 0;
+}
+
+uint8 per_length_expected[2] = "\x81\x2A";
+
+void test_per_write_length(void)
+{
+       STREAM* s = stream_new(2);
+       per_write_length(s, 298);
+       ASSERT_STREAM(s, (uint8*) per_length_expected, sizeof(per_length_expected));
+}
+
+uint8 per_oid[6] = { 0, 0, 20, 124, 0, 1 };
+uint8 per_oid_expected[6] = "\x05\x00\x14\x7C\x00\x01";
+
+void test_per_write_object_identifier(void)
+{
+       STREAM* s = stream_new(6);
+       per_write_object_identifier(s, per_oid);
+       ASSERT_STREAM(s, (uint8*) per_oid_expected, sizeof(per_oid_expected));
+}
diff --git a/cunit/test_per.h b/cunit/test_per.h
new file mode 100644 (file)
index 0000000..30f8d6f
--- /dev/null
@@ -0,0 +1,27 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * Packed Encoding Rules (PER) Unit Tests
+ *
+ * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed 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.
+ */
+
+#include "test_freerdp.h"
+
+int init_per_suite(void);
+int clean_per_suite(void);
+int add_per_suite(void);
+
+void test_per_write_length(void);
+void test_per_write_object_identifier(void);
index e8f06c8..d4a5617 100644 (file)
@@ -45,10 +45,12 @@ stream_extend(STREAM * stream);
 #define stream_get_pos(_s) (_s->ptr - _s->buffer)
 #define stream_set_pos(_s,_m) _s->ptr = _s->buffer + (_m)
 #define stream_seek(_s,_offset) _s->ptr += (_offset)
+#define stream_rewind(_s,_offset) _s->ptr -= (_offset)
 #define stream_get_mark(_s,_mark) _mark = _s->ptr
 #define stream_set_mark(_s,_mark) _s->ptr = _mark
 #define stream_get_head(_s) _s->buffer
 #define stream_get_tail(_s) _s->ptr
+#define stream_get_length(_s) (_s->ptr - _s->buffer)
 
 #define stream_read_uint8(_s, _v) do { _v = *_s->ptr++; } while (0)
 #define stream_read_uint16(_s, _v) do { _v = \
index e6bb1a2..9209a74 100644 (file)
@@ -22,6 +22,8 @@ add_definitions(-DEXT_PATH="/usr/lib/freerdp/extensions")
 set(LIBFREERDP_CORE_SRCS
        ber.c
        ber.h
+       gcc.c
+       gcc.h
        mcs.c
        mcs.h
        nego.c
@@ -30,6 +32,8 @@ set(LIBFREERDP_CORE_SRCS
 #      credssp.h
 #      ntlmssp.c
 #      ntlmssp.h
+       per.c
+       per.h
        tcp.c
        tcp.h
        tls.c
index cc5c756..ac1bae7 100644 (file)
@@ -22,7 +22,7 @@
 void
 ber_write_length(STREAM* s, int length)
 {
-       if (length > 0xFF)
+       if (length > 0x7F)
        {
                stream_write_uint8(s, 0x82);
                stream_write_uint16_be(s, length);
@@ -36,14 +36,22 @@ ber_write_length(STREAM* s, int length)
 void
 ber_write_universal_tag(STREAM* s, uint8 tag, int length)
 {
-       stream_write_uint8(s, (BER_CLASS_UNIV | BER_PRIMITIVE) & (BER_TAG_MASK & tag));
+       stream_write_uint8(s, (BER_CLASS_UNIV | BER_PRIMITIVE) | (BER_TAG_MASK & tag));
        ber_write_length(s, length);
 }
 
 void
 ber_write_application_tag(STREAM* s, uint8 tag, int length)
 {
-       stream_write_uint8(s, (BER_CLASS_APPL | BER_CONSTRUCT) & BER_TAG_MASK);
-       stream_write_uint8(s, tag);
-       ber_write_length(s, length);
+       if (tag > 30)
+       {
+               stream_write_uint8(s, (BER_CLASS_APPL | BER_CONSTRUCT) | BER_TAG_MASK);
+               stream_write_uint8(s, tag);
+               ber_write_length(s, length);
+       }
+       else
+       {
+               stream_write_uint8(s, (BER_CLASS_APPL | BER_CONSTRUCT) | (BER_TAG_MASK & tag));
+               ber_write_length(s, length);
+       }
 }
diff --git a/libfreerdp-core/gcc.c b/libfreerdp-core/gcc.c
new file mode 100644 (file)
index 0000000..3a117bc
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * T.124 Generic Conference Control (GCC)
+ *
+ * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed 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.
+ */
+
+#include "gcc.h"
+
+/**
+ * T.124 GCC is defined in:
+ *
+ * http://www.itu.int/rec/T-REC-T.124-199802-S/en
+ * ITU-T T.124 (02/98): Generic Conference Control
+ */
+
+/**
+ * ConnectData ::= SEQUENCE
+ * {
+ *     t124Identifier  Key,
+ *     connectPDU      OCTET_STRING
+ * }
+ *
+ * ConnectGCCPDU ::= CHOICE
+ * {
+ *     conferenceCreateRequest         ConferenceCreateRequest,
+ *     conferenceCreateResponse        ConferenceCreateResponse,
+ *     conferenceQueryRequest          ConferenceQueryRequest,
+ *     conferenceQueryResponse         ConferenceQueryResponse,
+ *     conferenceJoinRequest           ConferenceJoinRequest,
+ *     conferenceJoinResponse          ConferenceJoinResponse,
+ *     conferenceInviteRequest         ConferenceInviteRequest,
+ *     conferenceInviteResponse        ConferenceInviteResponse,
+ *     ...
+ * }
+ */
+
+/* http://msdn.microsoft.com/en-us/library/cc240836/ */
+
+uint8 t124_oid[6] = { 0, 0, 20, 124, 0, 1 };
+
+
diff --git a/libfreerdp-core/gcc.h b/libfreerdp-core/gcc.h
new file mode 100644 (file)
index 0000000..69714b9
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * T.124 Generic Conference Control (GCC)
+ *
+ * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed 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.
+ */
+
+#ifndef __GCC_H
+#define __GCC_H
+
+#include "per.h"
+
+#include <freerdp/utils/stream.h>
+
+
+
+#endif /* __GCC_H */
diff --git a/libfreerdp-core/per.c b/libfreerdp-core/per.c
new file mode 100644 (file)
index 0000000..8228ab1
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * ASN.1 Packed Encoding Rules (BER)
+ *
+ * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed 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.
+ */
+
+#include "per.h"
+
+void
+per_write_length(STREAM* s, int length)
+{
+       if (length > 0x7F)
+               stream_write_uint16_be(s, (length | 0x8000));
+       else
+               stream_write_uint8(s, length);
+}
+
+void
+per_write_object_identifier(STREAM* s, uint8 oid[6])
+{
+       uint8 t12 = (oid[0] << 4) & (oid[1] & 0x0F);
+       stream_write_uint8(s, 5); /* length */
+       stream_write_uint8(s, t12); /* first two tuples */
+       stream_write_uint8(s, oid[2]); /* tuple 3 */
+       stream_write_uint8(s, oid[3]); /* tuple 4 */
+       stream_write_uint8(s, oid[4]); /* tuple 5 */
+       stream_write_uint8(s, oid[5]); /* tuple 6 */
+}
diff --git a/libfreerdp-core/per.h b/libfreerdp-core/per.h
new file mode 100644 (file)
index 0000000..cbb8261
--- /dev/null
@@ -0,0 +1,30 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * ASN.1 Packed Encoding Rules (BER)
+ *
+ * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed 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.
+ */
+
+#ifndef __PER_H
+#define __PER_H
+
+#include <freerdp/utils/stream.h>
+
+void
+per_write_length(STREAM* s, int length);
+void
+per_write_object_identifier(STREAM* s, uint8 oid[6]);
+
+#endif /* __PER_H */