FreeRDP
TestSchannel.c
1 
2 #include <winpr/crt.h>
3 #include <winpr/sspi.h>
4 #include <winpr/file.h>
5 #include <winpr/pipe.h>
6 #include <winpr/path.h>
7 #include <winpr/tchar.h>
8 #include <winpr/print.h>
9 #include <winpr/synch.h>
10 #include <winpr/thread.h>
11 #include <winpr/crypto.h>
12 #include <winpr/wlog.h>
13 #include <winpr/schannel.h>
14 
15 static BOOL g_ClientWait = FALSE;
16 static BOOL g_ServerWait = FALSE;
17 
18 static HANDLE g_ClientReadPipe = NULL;
19 static HANDLE g_ClientWritePipe = NULL;
20 static HANDLE g_ServerReadPipe = NULL;
21 static HANDLE g_ServerWritePipe = NULL;
22 
23 static const BYTE test_localhost_crt[1029] = {
24  0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49,
25  0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x43,
26  0x79, 0x6A, 0x43, 0x43, 0x41, 0x62, 0x4B, 0x67, 0x41, 0x77, 0x49, 0x42, 0x41, 0x67, 0x49, 0x45,
27  0x63, 0x61, 0x64, 0x63, 0x72, 0x7A, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47,
28  0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x44, 0x41, 0x55, 0x4D, 0x52, 0x49, 0x77,
29  0x45, 0x41, 0x59, 0x44, 0x56, 0x51, 0x51, 0x44, 0x45, 0x77, 0x6C, 0x73, 0x0A, 0x62, 0x32, 0x4E,
30  0x68, 0x62, 0x47, 0x68, 0x76, 0x63, 0x33, 0x51, 0x77, 0x48, 0x68, 0x63, 0x4E, 0x4D, 0x54, 0x4D,
31  0x78, 0x4D, 0x44, 0x45, 0x78, 0x4D, 0x44, 0x59, 0x78, 0x4E, 0x7A, 0x55, 0x31, 0x57, 0x68, 0x63,
32  0x4E, 0x4D, 0x54, 0x51, 0x78, 0x4D, 0x44, 0x45, 0x78, 0x4D, 0x44, 0x59, 0x78, 0x4E, 0x7A, 0x55,
33  0x31, 0x57, 0x6A, 0x41, 0x55, 0x4D, 0x52, 0x49, 0x77, 0x45, 0x41, 0x59, 0x44, 0x0A, 0x56, 0x51,
34  0x51, 0x44, 0x45, 0x77, 0x6C, 0x73, 0x62, 0x32, 0x4E, 0x68, 0x62, 0x47, 0x68, 0x76, 0x63, 0x33,
35  0x51, 0x77, 0x67, 0x67, 0x45, 0x69, 0x4D, 0x41, 0x30, 0x47, 0x43, 0x53, 0x71, 0x47, 0x53, 0x49,
36  0x62, 0x33, 0x44, 0x51, 0x45, 0x42, 0x41, 0x51, 0x55, 0x41, 0x41, 0x34, 0x49, 0x42, 0x44, 0x77,
37  0x41, 0x77, 0x67, 0x67, 0x45, 0x4B, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x33, 0x0A, 0x65,
38  0x6E, 0x33, 0x68, 0x5A, 0x4F, 0x53, 0x33, 0x6B, 0x51, 0x2F, 0x55, 0x54, 0x30, 0x53, 0x45, 0x6C,
39  0x30, 0x48, 0x6E, 0x50, 0x79, 0x64, 0x48, 0x75, 0x35, 0x39, 0x61, 0x69, 0x71, 0x64, 0x73, 0x64,
40  0x53, 0x55, 0x74, 0x6E, 0x43, 0x41, 0x37, 0x46, 0x66, 0x74, 0x30, 0x4F, 0x36, 0x51, 0x79, 0x68,
41  0x49, 0x71, 0x58, 0x7A, 0x30, 0x47, 0x32, 0x53, 0x76, 0x77, 0x4C, 0x54, 0x62, 0x79, 0x68, 0x0A,
42  0x59, 0x54, 0x68, 0x31, 0x36, 0x78, 0x31, 0x72, 0x45, 0x48, 0x68, 0x31, 0x57, 0x47, 0x5A, 0x6D,
43  0x36, 0x77, 0x64, 0x2B, 0x4B, 0x76, 0x38, 0x6B, 0x31, 0x6B, 0x2F, 0x36, 0x6F, 0x41, 0x2F, 0x4F,
44  0x51, 0x76, 0x65, 0x61, 0x38, 0x6B, 0x63, 0x45, 0x64, 0x53, 0x72, 0x54, 0x64, 0x75, 0x71, 0x4A,
45  0x33, 0x65, 0x66, 0x74, 0x48, 0x4A, 0x4A, 0x6E, 0x43, 0x4B, 0x30, 0x41, 0x62, 0x68, 0x34, 0x39,
46  0x0A, 0x41, 0x47, 0x41, 0x50, 0x39, 0x79, 0x58, 0x77, 0x77, 0x59, 0x41, 0x6A, 0x51, 0x49, 0x52,
47  0x6E, 0x38, 0x2B, 0x4F, 0x63, 0x63, 0x48, 0x74, 0x6F, 0x4E, 0x75, 0x75, 0x79, 0x52, 0x63, 0x6B,
48  0x49, 0x50, 0x71, 0x75, 0x70, 0x78, 0x79, 0x31, 0x4A, 0x5A, 0x4B, 0x39, 0x64, 0x76, 0x76, 0x62,
49  0x34, 0x79, 0x53, 0x6B, 0x49, 0x75, 0x7A, 0x62, 0x79, 0x50, 0x6F, 0x54, 0x41, 0x79, 0x61, 0x55,
50  0x2B, 0x0A, 0x51, 0x72, 0x70, 0x34, 0x78, 0x67, 0x64, 0x4B, 0x46, 0x54, 0x70, 0x6B, 0x50, 0x46,
51  0x34, 0x33, 0x6A, 0x32, 0x4D, 0x6D, 0x5A, 0x72, 0x46, 0x63, 0x42, 0x76, 0x79, 0x6A, 0x69, 0x35,
52  0x6A, 0x4F, 0x37, 0x74, 0x66, 0x6F, 0x56, 0x61, 0x6B, 0x59, 0x47, 0x53, 0x2F, 0x4C, 0x63, 0x78,
53  0x77, 0x47, 0x2B, 0x77, 0x51, 0x77, 0x63, 0x4F, 0x43, 0x54, 0x42, 0x45, 0x78, 0x2F, 0x7A, 0x31,
54  0x53, 0x30, 0x0A, 0x37, 0x49, 0x2F, 0x6A, 0x62, 0x44, 0x79, 0x53, 0x4E, 0x68, 0x44, 0x35, 0x63,
55  0x61, 0x63, 0x54, 0x75, 0x4E, 0x36, 0x50, 0x68, 0x33, 0x58, 0x30, 0x71, 0x70, 0x47, 0x73, 0x37,
56  0x79, 0x50, 0x6B, 0x4E, 0x79, 0x69, 0x4A, 0x33, 0x57, 0x52, 0x69, 0x6C, 0x35, 0x75, 0x57, 0x73,
57  0x4B, 0x65, 0x79, 0x63, 0x64, 0x71, 0x42, 0x4E, 0x72, 0x34, 0x75, 0x32, 0x62, 0x49, 0x52, 0x6E,
58  0x63, 0x54, 0x51, 0x0A, 0x46, 0x72, 0x68, 0x73, 0x58, 0x39, 0x69, 0x77, 0x37, 0x35, 0x76, 0x75,
59  0x53, 0x64, 0x35, 0x46, 0x39, 0x37, 0x56, 0x70, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41, 0x47, 0x6A,
60  0x4A, 0x44, 0x41, 0x69, 0x4D, 0x42, 0x4D, 0x47, 0x41, 0x31, 0x55, 0x64, 0x4A, 0x51, 0x51, 0x4D,
61  0x4D, 0x41, 0x6F, 0x47, 0x43, 0x43, 0x73, 0x47, 0x41, 0x51, 0x55, 0x46, 0x42, 0x77, 0x4D, 0x42,
62  0x4D, 0x41, 0x73, 0x47, 0x0A, 0x41, 0x31, 0x55, 0x64, 0x44, 0x77, 0x51, 0x45, 0x41, 0x77, 0x49,
63  0x45, 0x4D, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47, 0x39, 0x77, 0x30,
64  0x42, 0x41, 0x51, 0x55, 0x46, 0x41, 0x41, 0x4F, 0x43, 0x41, 0x51, 0x45, 0x41, 0x49, 0x51, 0x66,
65  0x75, 0x2F, 0x77, 0x39, 0x45, 0x34, 0x4C, 0x6F, 0x67, 0x30, 0x71, 0x35, 0x4B, 0x53, 0x38, 0x71,
66  0x46, 0x78, 0x62, 0x36, 0x6F, 0x0A, 0x36, 0x31, 0x62, 0x35, 0x37, 0x6F, 0x6D, 0x6E, 0x46, 0x59,
67  0x52, 0x34, 0x47, 0x43, 0x67, 0x33, 0x6F, 0x6A, 0x4F, 0x4C, 0x54, 0x66, 0x38, 0x7A, 0x6A, 0x4D,
68  0x43, 0x52, 0x6D, 0x75, 0x59, 0x32, 0x76, 0x30, 0x4E, 0x34, 0x78, 0x66, 0x68, 0x69, 0x35, 0x4B,
69  0x69, 0x59, 0x67, 0x64, 0x76, 0x4E, 0x4C, 0x4F, 0x33, 0x52, 0x42, 0x6D, 0x4E, 0x50, 0x76, 0x59,
70  0x58, 0x50, 0x52, 0x46, 0x41, 0x76, 0x0A, 0x66, 0x61, 0x76, 0x66, 0x57, 0x75, 0x6C, 0x44, 0x31,
71  0x64, 0x50, 0x36, 0x31, 0x69, 0x35, 0x62, 0x36, 0x59, 0x66, 0x56, 0x6C, 0x78, 0x62, 0x31, 0x61,
72  0x57, 0x46, 0x37, 0x4C, 0x5A, 0x44, 0x32, 0x55, 0x6E, 0x63, 0x41, 0x6A, 0x37, 0x4E, 0x38, 0x78,
73  0x38, 0x2B, 0x36, 0x58, 0x6B, 0x30, 0x6B, 0x63, 0x70, 0x58, 0x46, 0x38, 0x6C, 0x77, 0x58, 0x48,
74  0x55, 0x57, 0x57, 0x55, 0x6D, 0x73, 0x2B, 0x0A, 0x4B, 0x56, 0x44, 0x34, 0x34, 0x39, 0x68, 0x6F,
75  0x4D, 0x2B, 0x77, 0x4E, 0x4A, 0x49, 0x61, 0x4F, 0x52, 0x39, 0x4C, 0x46, 0x2B, 0x6B, 0x6F, 0x32,
76  0x32, 0x37, 0x7A, 0x74, 0x37, 0x54, 0x41, 0x47, 0x64, 0x56, 0x35, 0x4A, 0x75, 0x7A, 0x71, 0x38,
77  0x32, 0x2F, 0x6B, 0x75, 0x73, 0x6F, 0x65, 0x32, 0x69, 0x75, 0x57, 0x77, 0x54, 0x65, 0x42, 0x6C,
78  0x53, 0x5A, 0x6E, 0x6B, 0x42, 0x38, 0x63, 0x64, 0x0A, 0x77, 0x4D, 0x30, 0x5A, 0x42, 0x58, 0x6D,
79  0x34, 0x35, 0x48, 0x38, 0x6F, 0x79, 0x75, 0x36, 0x4A, 0x71, 0x59, 0x71, 0x45, 0x6D, 0x75, 0x4A,
80  0x51, 0x64, 0x67, 0x79, 0x52, 0x2B, 0x63, 0x53, 0x53, 0x41, 0x7A, 0x2B, 0x4F, 0x32, 0x6D, 0x61,
81  0x62, 0x68, 0x50, 0x5A, 0x65, 0x49, 0x76, 0x78, 0x65, 0x67, 0x6A, 0x6A, 0x61, 0x5A, 0x61, 0x46,
82  0x4F, 0x71, 0x74, 0x73, 0x2B, 0x64, 0x33, 0x72, 0x39, 0x0A, 0x79, 0x71, 0x4A, 0x78, 0x67, 0x75,
83  0x39, 0x43, 0x38, 0x39, 0x5A, 0x69, 0x33, 0x39, 0x57, 0x34, 0x38, 0x46, 0x66, 0x46, 0x63, 0x49,
84  0x58, 0x4A, 0x4F, 0x6B, 0x39, 0x43, 0x4E, 0x46, 0x41, 0x2F, 0x69, 0x70, 0x54, 0x57, 0x6A, 0x74,
85  0x74, 0x4E, 0x2F, 0x6B, 0x4F, 0x6B, 0x5A, 0x42, 0x70, 0x6F, 0x6A, 0x2F, 0x32, 0x6A, 0x4E, 0x45,
86  0x62, 0x4F, 0x59, 0x7A, 0x7A, 0x6E, 0x4B, 0x77, 0x3D, 0x3D, 0x0A, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D,
87  0x45, 0x4E, 0x44, 0x20, 0x43, 0x45, 0x52, 0x54, 0x49, 0x46, 0x49, 0x43, 0x41, 0x54, 0x45, 0x2D,
88  0x2D, 0x2D, 0x2D, 0x2D, 0x0A
89 };
90 
91 static const BYTE test_localhost_key[1704] = {
92  0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x42, 0x45, 0x47, 0x49, 0x4E, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41,
93  0x54, 0x45, 0x20, 0x4B, 0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A, 0x4D, 0x49, 0x49, 0x45,
94  0x76, 0x51, 0x49, 0x42, 0x41, 0x44, 0x41, 0x4E, 0x42, 0x67, 0x6B, 0x71, 0x68, 0x6B, 0x69, 0x47,
95  0x39, 0x77, 0x30, 0x42, 0x41, 0x51, 0x45, 0x46, 0x41, 0x41, 0x53, 0x43, 0x42, 0x4B, 0x63, 0x77,
96  0x67, 0x67, 0x53, 0x6A, 0x41, 0x67, 0x45, 0x41, 0x41, 0x6F, 0x49, 0x42, 0x41, 0x51, 0x43, 0x33,
97  0x65, 0x6E, 0x33, 0x68, 0x5A, 0x4F, 0x53, 0x33, 0x6B, 0x51, 0x2F, 0x55, 0x0A, 0x54, 0x30, 0x53,
98  0x45, 0x6C, 0x30, 0x48, 0x6E, 0x50, 0x79, 0x64, 0x48, 0x75, 0x35, 0x39, 0x61, 0x69, 0x71, 0x64,
99  0x73, 0x64, 0x53, 0x55, 0x74, 0x6E, 0x43, 0x41, 0x37, 0x46, 0x66, 0x74, 0x30, 0x4F, 0x36, 0x51,
100  0x79, 0x68, 0x49, 0x71, 0x58, 0x7A, 0x30, 0x47, 0x32, 0x53, 0x76, 0x77, 0x4C, 0x54, 0x62, 0x79,
101  0x68, 0x59, 0x54, 0x68, 0x31, 0x36, 0x78, 0x31, 0x72, 0x45, 0x48, 0x68, 0x31, 0x0A, 0x57, 0x47,
102  0x5A, 0x6D, 0x36, 0x77, 0x64, 0x2B, 0x4B, 0x76, 0x38, 0x6B, 0x31, 0x6B, 0x2F, 0x36, 0x6F, 0x41,
103  0x2F, 0x4F, 0x51, 0x76, 0x65, 0x61, 0x38, 0x6B, 0x63, 0x45, 0x64, 0x53, 0x72, 0x54, 0x64, 0x75,
104  0x71, 0x4A, 0x33, 0x65, 0x66, 0x74, 0x48, 0x4A, 0x4A, 0x6E, 0x43, 0x4B, 0x30, 0x41, 0x62, 0x68,
105  0x34, 0x39, 0x41, 0x47, 0x41, 0x50, 0x39, 0x79, 0x58, 0x77, 0x77, 0x59, 0x41, 0x6A, 0x0A, 0x51,
106  0x49, 0x52, 0x6E, 0x38, 0x2B, 0x4F, 0x63, 0x63, 0x48, 0x74, 0x6F, 0x4E, 0x75, 0x75, 0x79, 0x52,
107  0x63, 0x6B, 0x49, 0x50, 0x71, 0x75, 0x70, 0x78, 0x79, 0x31, 0x4A, 0x5A, 0x4B, 0x39, 0x64, 0x76,
108  0x76, 0x62, 0x34, 0x79, 0x53, 0x6B, 0x49, 0x75, 0x7A, 0x62, 0x79, 0x50, 0x6F, 0x54, 0x41, 0x79,
109  0x61, 0x55, 0x2B, 0x51, 0x72, 0x70, 0x34, 0x78, 0x67, 0x64, 0x4B, 0x46, 0x54, 0x70, 0x6B, 0x0A,
110  0x50, 0x46, 0x34, 0x33, 0x6A, 0x32, 0x4D, 0x6D, 0x5A, 0x72, 0x46, 0x63, 0x42, 0x76, 0x79, 0x6A,
111  0x69, 0x35, 0x6A, 0x4F, 0x37, 0x74, 0x66, 0x6F, 0x56, 0x61, 0x6B, 0x59, 0x47, 0x53, 0x2F, 0x4C,
112  0x63, 0x78, 0x77, 0x47, 0x2B, 0x77, 0x51, 0x77, 0x63, 0x4F, 0x43, 0x54, 0x42, 0x45, 0x78, 0x2F,
113  0x7A, 0x31, 0x53, 0x30, 0x37, 0x49, 0x2F, 0x6A, 0x62, 0x44, 0x79, 0x53, 0x4E, 0x68, 0x44, 0x35,
114  0x0A, 0x63, 0x61, 0x63, 0x54, 0x75, 0x4E, 0x36, 0x50, 0x68, 0x33, 0x58, 0x30, 0x71, 0x70, 0x47,
115  0x73, 0x37, 0x79, 0x50, 0x6B, 0x4E, 0x79, 0x69, 0x4A, 0x33, 0x57, 0x52, 0x69, 0x6C, 0x35, 0x75,
116  0x57, 0x73, 0x4B, 0x65, 0x79, 0x63, 0x64, 0x71, 0x42, 0x4E, 0x72, 0x34, 0x75, 0x32, 0x62, 0x49,
117  0x52, 0x6E, 0x63, 0x54, 0x51, 0x46, 0x72, 0x68, 0x73, 0x58, 0x39, 0x69, 0x77, 0x37, 0x35, 0x76,
118  0x75, 0x0A, 0x53, 0x64, 0x35, 0x46, 0x39, 0x37, 0x56, 0x70, 0x41, 0x67, 0x4D, 0x42, 0x41, 0x41,
119  0x45, 0x43, 0x67, 0x67, 0x45, 0x41, 0x42, 0x36, 0x6A, 0x6C, 0x65, 0x48, 0x4E, 0x74, 0x32, 0x50,
120  0x77, 0x46, 0x58, 0x53, 0x65, 0x79, 0x42, 0x4A, 0x63, 0x4C, 0x2B, 0x55, 0x74, 0x35, 0x71, 0x46,
121  0x54, 0x38, 0x34, 0x68, 0x72, 0x48, 0x77, 0x6F, 0x39, 0x68, 0x62, 0x66, 0x59, 0x47, 0x6F, 0x6E,
122  0x44, 0x59, 0x0A, 0x66, 0x70, 0x47, 0x2B, 0x32, 0x52, 0x30, 0x50, 0x62, 0x43, 0x63, 0x4B, 0x35,
123  0x30, 0x46, 0x61, 0x4A, 0x46, 0x36, 0x71, 0x63, 0x56, 0x4A, 0x4E, 0x75, 0x52, 0x36, 0x48, 0x71,
124  0x2B, 0x43, 0x55, 0x4A, 0x74, 0x48, 0x35, 0x39, 0x48, 0x48, 0x37, 0x62, 0x68, 0x6A, 0x39, 0x62,
125  0x64, 0x78, 0x45, 0x6D, 0x6F, 0x48, 0x30, 0x4A, 0x76, 0x68, 0x45, 0x76, 0x67, 0x4D, 0x2F, 0x55,
126  0x38, 0x42, 0x51, 0x0A, 0x65, 0x57, 0x4F, 0x4E, 0x68, 0x78, 0x50, 0x73, 0x69, 0x73, 0x6D, 0x57,
127  0x6B, 0x78, 0x61, 0x5A, 0x6F, 0x6C, 0x72, 0x32, 0x69, 0x44, 0x56, 0x72, 0x7A, 0x54, 0x37, 0x55,
128  0x4A, 0x71, 0x6A, 0x74, 0x59, 0x49, 0x74, 0x67, 0x2B, 0x37, 0x59, 0x43, 0x32, 0x70, 0x55, 0x58,
129  0x6B, 0x64, 0x49, 0x35, 0x4A, 0x4D, 0x67, 0x6C, 0x44, 0x47, 0x4D, 0x52, 0x5A, 0x35, 0x55, 0x5A,
130  0x48, 0x75, 0x63, 0x7A, 0x0A, 0x41, 0x56, 0x2B, 0x71, 0x77, 0x77, 0x33, 0x65, 0x45, 0x52, 0x74,
131  0x78, 0x44, 0x50, 0x61, 0x61, 0x61, 0x34, 0x54, 0x39, 0x50, 0x64, 0x33, 0x44, 0x31, 0x6D, 0x62,
132  0x71, 0x58, 0x66, 0x75, 0x45, 0x68, 0x42, 0x6D, 0x33, 0x51, 0x6F, 0x2B, 0x75, 0x7A, 0x51, 0x32,
133  0x36, 0x76, 0x73, 0x66, 0x48, 0x75, 0x56, 0x76, 0x61, 0x39, 0x38, 0x32, 0x4F, 0x6A, 0x41, 0x55,
134  0x6A, 0x6E, 0x64, 0x30, 0x70, 0x0A, 0x77, 0x43, 0x53, 0x6E, 0x42, 0x49, 0x48, 0x67, 0x70, 0x73,
135  0x30, 0x79, 0x61, 0x45, 0x50, 0x63, 0x37, 0x46, 0x78, 0x39, 0x71, 0x45, 0x63, 0x6D, 0x33, 0x70,
136  0x7A, 0x41, 0x56, 0x31, 0x69, 0x72, 0x31, 0x4E, 0x4E, 0x63, 0x51, 0x47, 0x55, 0x45, 0x75, 0x45,
137  0x6C, 0x4A, 0x78, 0x76, 0x2B, 0x69, 0x57, 0x34, 0x6D, 0x35, 0x70, 0x7A, 0x4C, 0x6A, 0x64, 0x53,
138  0x63, 0x49, 0x30, 0x59, 0x45, 0x73, 0x0A, 0x4D, 0x61, 0x33, 0x78, 0x32, 0x79, 0x48, 0x74, 0x6E,
139  0x77, 0x79, 0x65, 0x4C, 0x4D, 0x54, 0x4B, 0x6C, 0x72, 0x46, 0x4B, 0x70, 0x55, 0x4E, 0x4A, 0x62,
140  0x78, 0x73, 0x35, 0x32, 0x62, 0x5A, 0x4B, 0x71, 0x49, 0x56, 0x33, 0x33, 0x4A, 0x53, 0x34, 0x41,
141  0x51, 0x4B, 0x42, 0x67, 0x51, 0x44, 0x73, 0x4C, 0x54, 0x49, 0x68, 0x35, 0x59, 0x38, 0x4C, 0x2F,
142  0x48, 0x33, 0x64, 0x74, 0x68, 0x63, 0x62, 0x0A, 0x53, 0x43, 0x45, 0x77, 0x32, 0x64, 0x42, 0x49,
143  0x76, 0x49, 0x79, 0x54, 0x7A, 0x39, 0x53, 0x72, 0x62, 0x33, 0x58, 0x37, 0x37, 0x41, 0x77, 0x57,
144  0x45, 0x4C, 0x53, 0x4D, 0x49, 0x57, 0x53, 0x50, 0x55, 0x43, 0x4B, 0x54, 0x49, 0x70, 0x6A, 0x4D,
145  0x73, 0x6E, 0x7A, 0x6B, 0x46, 0x67, 0x32, 0x32, 0x59, 0x32, 0x53, 0x75, 0x47, 0x38, 0x4C, 0x72,
146  0x50, 0x6D, 0x76, 0x73, 0x46, 0x4A, 0x34, 0x30, 0x0A, 0x32, 0x67, 0x35, 0x44, 0x55, 0x6C, 0x59,
147  0x33, 0x59, 0x6D, 0x53, 0x4F, 0x46, 0x61, 0x45, 0x4A, 0x54, 0x70, 0x55, 0x47, 0x44, 0x4D, 0x79,
148  0x65, 0x33, 0x74, 0x36, 0x4F, 0x30, 0x6C, 0x63, 0x51, 0x41, 0x66, 0x79, 0x6D, 0x58, 0x66, 0x41,
149  0x38, 0x74, 0x50, 0x42, 0x48, 0x6A, 0x5A, 0x78, 0x56, 0x61, 0x38, 0x78, 0x78, 0x52, 0x5A, 0x6E,
150  0x56, 0x43, 0x31, 0x41, 0x62, 0x75, 0x49, 0x49, 0x52, 0x0A, 0x6E, 0x77, 0x72, 0x4E, 0x46, 0x2B,
151  0x42, 0x6F, 0x53, 0x4B, 0x55, 0x41, 0x73, 0x78, 0x2B, 0x46, 0x75, 0x35, 0x5A, 0x4A, 0x4B, 0x4F,
152  0x66, 0x79, 0x4D, 0x51, 0x4B, 0x42, 0x67, 0x51, 0x44, 0x47, 0x34, 0x50, 0x52, 0x39, 0x2F, 0x58,
153  0x58, 0x6B, 0x51, 0x54, 0x36, 0x6B, 0x7A, 0x4B, 0x64, 0x34, 0x50, 0x6C, 0x50, 0x4D, 0x63, 0x2B,
154  0x4B, 0x51, 0x79, 0x4C, 0x45, 0x6C, 0x4B, 0x39, 0x71, 0x47, 0x0A, 0x41, 0x6D, 0x6E, 0x2F, 0x31,
155  0x68, 0x64, 0x69, 0x57, 0x57, 0x4F, 0x52, 0x57, 0x46, 0x62, 0x32, 0x38, 0x30, 0x4D, 0x77, 0x76,
156  0x77, 0x41, 0x64, 0x78, 0x72, 0x66, 0x65, 0x4C, 0x57, 0x4D, 0x57, 0x32, 0x66, 0x76, 0x4C, 0x59,
157  0x4B, 0x66, 0x6C, 0x4F, 0x35, 0x50, 0x51, 0x44, 0x59, 0x67, 0x4B, 0x4A, 0x78, 0x35, 0x79, 0x50,
158  0x37, 0x52, 0x64, 0x38, 0x2F, 0x64, 0x50, 0x79, 0x5A, 0x59, 0x36, 0x0A, 0x7A, 0x56, 0x37, 0x47,
159  0x47, 0x6B, 0x51, 0x5A, 0x42, 0x4B, 0x36, 0x79, 0x74, 0x61, 0x66, 0x32, 0x35, 0x44, 0x50, 0x67,
160  0x50, 0x72, 0x32, 0x77, 0x73, 0x59, 0x4D, 0x43, 0x6C, 0x53, 0x74, 0x6C, 0x56, 0x74, 0x72, 0x6D,
161  0x4F, 0x78, 0x59, 0x55, 0x56, 0x77, 0x42, 0x59, 0x4F, 0x69, 0x36, 0x45, 0x62, 0x50, 0x69, 0x6B,
162  0x78, 0x47, 0x48, 0x5A, 0x70, 0x59, 0x6F, 0x5A, 0x5A, 0x70, 0x68, 0x4A, 0x0A, 0x4E, 0x61, 0x38,
163  0x4F, 0x4C, 0x31, 0x69, 0x77, 0x75, 0x51, 0x4B, 0x42, 0x67, 0x51, 0x44, 0x42, 0x55, 0x55, 0x31,
164  0x54, 0x79, 0x5A, 0x2B, 0x4A, 0x5A, 0x43, 0x64, 0x79, 0x72, 0x33, 0x58, 0x43, 0x63, 0x77, 0x77,
165  0x58, 0x2F, 0x48, 0x49, 0x73, 0x31, 0x34, 0x6B, 0x4B, 0x42, 0x48, 0x68, 0x44, 0x79, 0x33, 0x78,
166  0x37, 0x74, 0x50, 0x38, 0x2F, 0x6F, 0x48, 0x54, 0x6F, 0x72, 0x76, 0x79, 0x74, 0x0A, 0x41, 0x68,
167  0x38, 0x4B, 0x36, 0x4B, 0x72, 0x43, 0x41, 0x75, 0x65, 0x50, 0x6D, 0x79, 0x32, 0x6D, 0x4F, 0x54,
168  0x31, 0x54, 0x39, 0x6F, 0x31, 0x61, 0x47, 0x55, 0x49, 0x6C, 0x66, 0x38, 0x72, 0x76, 0x33, 0x2F,
169  0x30, 0x45, 0x78, 0x67, 0x53, 0x6B, 0x57, 0x50, 0x6D, 0x4F, 0x41, 0x38, 0x35, 0x49, 0x32, 0x2F,
170  0x58, 0x48, 0x65, 0x66, 0x71, 0x54, 0x6F, 0x45, 0x48, 0x30, 0x44, 0x65, 0x41, 0x4E, 0x0A, 0x7A,
171  0x6C, 0x4B, 0x4C, 0x71, 0x79, 0x44, 0x56, 0x30, 0x42, 0x56, 0x4E, 0x76, 0x48, 0x42, 0x57, 0x79,
172  0x32, 0x49, 0x51, 0x35, 0x62, 0x50, 0x42, 0x57, 0x76, 0x30, 0x37, 0x63, 0x34, 0x2B, 0x6A, 0x39,
173  0x4E, 0x62, 0x57, 0x67, 0x64, 0x44, 0x43, 0x43, 0x35, 0x52, 0x6B, 0x4F, 0x6A, 0x70, 0x33, 0x4D,
174  0x4E, 0x45, 0x58, 0x47, 0x56, 0x43, 0x69, 0x51, 0x51, 0x4B, 0x42, 0x67, 0x43, 0x7A, 0x4D, 0x0A,
175  0x77, 0x65, 0x61, 0x62, 0x73, 0x50, 0x48, 0x68, 0x44, 0x4B, 0x5A, 0x38, 0x2F, 0x34, 0x43, 0x6A,
176  0x73, 0x61, 0x62, 0x4E, 0x75, 0x41, 0x7A, 0x62, 0x57, 0x4B, 0x52, 0x42, 0x38, 0x37, 0x44, 0x61,
177  0x58, 0x46, 0x78, 0x6F, 0x4D, 0x73, 0x35, 0x52, 0x79, 0x6F, 0x38, 0x55, 0x4D, 0x6B, 0x72, 0x67,
178  0x30, 0x35, 0x4C, 0x6F, 0x67, 0x37, 0x4D, 0x78, 0x62, 0x33, 0x76, 0x61, 0x42, 0x34, 0x63, 0x2F,
179  0x0A, 0x52, 0x57, 0x77, 0x7A, 0x38, 0x72, 0x34, 0x39, 0x70, 0x48, 0x64, 0x71, 0x68, 0x4F, 0x6D,
180  0x63, 0x6C, 0x45, 0x77, 0x79, 0x4D, 0x34, 0x51, 0x79, 0x6A, 0x39, 0x52, 0x6D, 0x57, 0x62, 0x51,
181  0x58, 0x54, 0x54, 0x45, 0x63, 0x2B, 0x35, 0x67, 0x54, 0x4B, 0x50, 0x4E, 0x53, 0x33, 0x6D, 0x70,
182  0x4D, 0x54, 0x36, 0x39, 0x46, 0x45, 0x74, 0x2F, 0x35, 0x72, 0x4D, 0x52, 0x70, 0x4B, 0x2B, 0x52,
183  0x68, 0x0A, 0x49, 0x32, 0x42, 0x58, 0x6B, 0x51, 0x71, 0x31, 0x36, 0x6E, 0x72, 0x31, 0x61, 0x45,
184  0x4D, 0x6D, 0x64, 0x51, 0x42, 0x51, 0x79, 0x4B, 0x59, 0x4A, 0x6C, 0x30, 0x6C, 0x50, 0x68, 0x69,
185  0x42, 0x2F, 0x75, 0x6C, 0x5A, 0x63, 0x72, 0x67, 0x4C, 0x70, 0x41, 0x6F, 0x47, 0x41, 0x65, 0x30,
186  0x65, 0x74, 0x50, 0x4A, 0x77, 0x6D, 0x51, 0x46, 0x6B, 0x6A, 0x4D, 0x70, 0x66, 0x4D, 0x44, 0x61,
187  0x4E, 0x34, 0x0A, 0x70, 0x7A, 0x71, 0x45, 0x51, 0x72, 0x52, 0x35, 0x4B, 0x35, 0x4D, 0x6E, 0x54,
188  0x48, 0x76, 0x47, 0x67, 0x2F, 0x70, 0x6A, 0x57, 0x6A, 0x43, 0x57, 0x58, 0x56, 0x48, 0x67, 0x35,
189  0x76, 0x36, 0x46, 0x6F, 0x5A, 0x48, 0x35, 0x6E, 0x59, 0x2B, 0x56, 0x2F, 0x57, 0x75, 0x57, 0x38,
190  0x38, 0x6A, 0x6C, 0x4B, 0x53, 0x50, 0x6C, 0x77, 0x6A, 0x50, 0x7A, 0x41, 0x67, 0x7A, 0x47, 0x33,
191  0x45, 0x41, 0x55, 0x0A, 0x71, 0x57, 0x6B, 0x42, 0x67, 0x30, 0x71, 0x75, 0x50, 0x4D, 0x72, 0x54,
192  0x6B, 0x73, 0x69, 0x6E, 0x58, 0x50, 0x2B, 0x58, 0x6B, 0x51, 0x65, 0x46, 0x66, 0x58, 0x61, 0x33,
193  0x38, 0x6A, 0x72, 0x70, 0x62, 0x4B, 0x46, 0x4F, 0x72, 0x7A, 0x49, 0x6F, 0x6A, 0x69, 0x65, 0x6C,
194  0x4B, 0x55, 0x4D, 0x50, 0x4D, 0x78, 0x2F, 0x78, 0x70, 0x53, 0x6A, 0x63, 0x55, 0x42, 0x68, 0x62,
195  0x4E, 0x34, 0x45, 0x54, 0x0A, 0x4F, 0x30, 0x66, 0x63, 0x57, 0x47, 0x6F, 0x61, 0x56, 0x50, 0x72,
196  0x63, 0x6E, 0x38, 0x62, 0x58, 0x4D, 0x54, 0x45, 0x4E, 0x53, 0x31, 0x41, 0x3D, 0x0A, 0x2D, 0x2D,
197  0x2D, 0x2D, 0x2D, 0x45, 0x4E, 0x44, 0x20, 0x50, 0x52, 0x49, 0x56, 0x41, 0x54, 0x45, 0x20, 0x4B,
198  0x45, 0x59, 0x2D, 0x2D, 0x2D, 0x2D, 0x2D, 0x0A
199 };
200 
201 static const BYTE test_DummyMessage[64] = {
202  0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
203  0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB,
204  0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
205  0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD
206 };
207 
208 static const BYTE test_LastDummyMessage[64] = {
209  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
210  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
212  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
213 };
214 
215 static int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext,
216  BYTE* buffer, UINT32 length)
217 {
218  BYTE* ioBuffer;
219  UINT32 ioBufferLength;
220  BYTE* pMessageBuffer;
221  SecBuffer Buffers[4] = { 0 };
222  SecBufferDesc Message;
223  SECURITY_STATUS status;
224  DWORD NumberOfBytesWritten;
225  SecPkgContext_StreamSizes StreamSizes = { 0 };
226 
227  status = table->QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &StreamSizes);
228  ioBufferLength = StreamSizes.cbHeader + StreamSizes.cbMaximumMessage + StreamSizes.cbTrailer;
229  ioBuffer = (BYTE*)calloc(1, ioBufferLength);
230  if (!ioBuffer)
231  return -1;
232  pMessageBuffer = ioBuffer + StreamSizes.cbHeader;
233  CopyMemory(pMessageBuffer, buffer, length);
234  Buffers[0].pvBuffer = ioBuffer;
235  Buffers[0].cbBuffer = StreamSizes.cbHeader;
236  Buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
237  Buffers[1].pvBuffer = pMessageBuffer;
238  Buffers[1].cbBuffer = length;
239  Buffers[1].BufferType = SECBUFFER_DATA;
240  Buffers[2].pvBuffer = pMessageBuffer + length;
241  Buffers[2].cbBuffer = StreamSizes.cbTrailer;
242  Buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
243  Buffers[3].pvBuffer = NULL;
244  Buffers[3].cbBuffer = 0;
245  Buffers[3].BufferType = SECBUFFER_EMPTY;
246  Message.ulVersion = SECBUFFER_VERSION;
247  Message.cBuffers = 4;
248  Message.pBuffers = Buffers;
249  ioBufferLength =
250  Message.pBuffers[0].cbBuffer + Message.pBuffers[1].cbBuffer + Message.pBuffers[2].cbBuffer;
251  status = table->EncryptMessage(phContext, 0, &Message, 0);
252  printf("EncryptMessage status: 0x%08" PRIX32 "\n", status);
253  printf("EncryptMessage output: cBuffers: %" PRIu32 " [0]: %" PRIu32 " / %" PRIu32
254  " [1]: %" PRIu32 " / %" PRIu32 " [2]: %" PRIu32 " / %" PRIu32 " [3]: %" PRIu32
255  " / %" PRIu32 "\n",
256  Message.cBuffers, Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType,
257  Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType,
258  Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType,
259  Message.pBuffers[3].cbBuffer, Message.pBuffers[3].BufferType);
260 
261  if (status != SEC_E_OK)
262  return -1;
263 
264  printf("Client > Server (%" PRIu32 ")\n", ioBufferLength);
265  winpr_HexDump("sspi.test", WLOG_DEBUG, ioBuffer, ioBufferLength);
266 
267  if (!WriteFile(hPipe, ioBuffer, ioBufferLength, &NumberOfBytesWritten, NULL))
268  {
269  printf("schannel_send: failed to write to pipe\n");
270  return -1;
271  }
272 
273  return 0;
274 }
275 
276 static int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext)
277 {
278  BYTE* ioBuffer;
279  UINT32 ioBufferLength;
280  // BYTE* pMessageBuffer;
281  SecBuffer Buffers[4] = { 0 };
282  SecBufferDesc Message;
283  SECURITY_STATUS status;
284  DWORD NumberOfBytesRead;
285  SecPkgContext_StreamSizes StreamSizes = { 0 };
286 
287  status = table->QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &StreamSizes);
288  ioBufferLength = StreamSizes.cbHeader + StreamSizes.cbMaximumMessage + StreamSizes.cbTrailer;
289  ioBuffer = (BYTE*)calloc(1, ioBufferLength);
290  if (!ioBuffer)
291  return -1;
292 
293  if (!ReadFile(hPipe, ioBuffer, ioBufferLength, &NumberOfBytesRead, NULL))
294  {
295  printf("schannel_recv: failed to read from pipe\n");
296  return -1;
297  }
298 
299  Buffers[0].pvBuffer = ioBuffer;
300  Buffers[0].cbBuffer = NumberOfBytesRead;
301  Buffers[0].BufferType = SECBUFFER_DATA;
302  Buffers[1].pvBuffer = NULL;
303  Buffers[1].cbBuffer = 0;
304  Buffers[1].BufferType = SECBUFFER_EMPTY;
305  Buffers[2].pvBuffer = NULL;
306  Buffers[2].cbBuffer = 0;
307  Buffers[2].BufferType = SECBUFFER_EMPTY;
308  Buffers[3].pvBuffer = NULL;
309  Buffers[3].cbBuffer = 0;
310  Buffers[3].BufferType = SECBUFFER_EMPTY;
311  Message.ulVersion = SECBUFFER_VERSION;
312  Message.cBuffers = 4;
313  Message.pBuffers = Buffers;
314  status = table->DecryptMessage(phContext, &Message, 0, NULL);
315  printf("DecryptMessage status: 0x%08" PRIX32 "\n", status);
316  printf("DecryptMessage output: cBuffers: %" PRIu32 " [0]: %" PRIu32 " / %" PRIu32
317  " [1]: %" PRIu32 " / %" PRIu32 " [2]: %" PRIu32 " / %" PRIu32 " [3]: %" PRIu32
318  " / %" PRIu32 "\n",
319  Message.cBuffers, Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType,
320  Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType,
321  Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType,
322  Message.pBuffers[3].cbBuffer, Message.pBuffers[3].BufferType);
323 
324  if (status != SEC_E_OK)
325  return -1;
326 
327  printf("Decrypted Message (%" PRIu32 ")\n", Message.pBuffers[1].cbBuffer);
328  winpr_HexDump("sspi.test", WLOG_DEBUG, (BYTE*)Message.pBuffers[1].pvBuffer,
329  Message.pBuffers[1].cbBuffer);
330 
331  if (memcmp(Message.pBuffers[1].pvBuffer, test_LastDummyMessage,
332  sizeof(test_LastDummyMessage)) == 0)
333  return -1;
334 
335  return 0;
336 }
337 
338 static DWORD WINAPI schannel_test_server_thread(LPVOID arg)
339 {
340  BOOL extraData;
341  BYTE* lpTokenIn;
342  BYTE* lpTokenOut;
343  TimeStamp expiry;
344  UINT32 cbMaxToken;
345  UINT32 fContextReq;
346  ULONG fContextAttr;
347  SCHANNEL_CRED cred = { 0 };
348  CtxtHandle context;
349  CredHandle credentials;
350  DWORD cchNameString;
351  LPTSTR pszNameString;
352  HCERTSTORE hCertStore;
353  PCCERT_CONTEXT pCertContext;
354  PSecBuffer pSecBuffer;
355  SecBuffer SecBuffer_in[2] = { 0 };
356  SecBuffer SecBuffer_out[2] = { 0 };
357  SecBufferDesc SecBufferDesc_in;
358  SecBufferDesc SecBufferDesc_out;
359  DWORD NumberOfBytesRead;
360  SECURITY_STATUS status;
361  PSecPkgInfo pPackageInfo;
362  PSecurityFunctionTable table;
363  DWORD NumberOfBytesWritten;
364  printf("Starting Server\n");
365  SecInvalidateHandle(&context);
366  SecInvalidateHandle(&credentials);
367  table = InitSecurityInterface();
368  status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo);
369 
370  if (status != SEC_E_OK)
371  {
372  printf("QuerySecurityPackageInfo failure: 0x%08" PRIX32 "\n", status);
373  return 0;
374  }
375 
376  cbMaxToken = pPackageInfo->cbMaxToken;
377  hCertStore = CertOpenSystemStore(0, _T("MY"));
378 
379  if (!hCertStore)
380  {
381  printf("Error opening system store\n");
382  // return NULL;
383  }
384 
385 #ifdef CERT_FIND_HAS_PRIVATE_KEY
386  pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0,
387  CERT_FIND_HAS_PRIVATE_KEY, NULL, NULL);
388 #else
389  pCertContext =
390  CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL);
391 #endif
392 
393  if (!pCertContext)
394  {
395  printf("Error finding certificate in store\n");
396  // return NULL;
397  }
398 
399  cchNameString =
400  CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0);
401  pszNameString = (LPTSTR)malloc(cchNameString * sizeof(TCHAR));
402  if (!pszNameString)
403  {
404  printf("Memory allocation failed\n");
405  return 0;
406  }
407  cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL,
408  pszNameString, cchNameString);
409  _tprintf(_T("Certificate Name: %s\n"), pszNameString);
410  cred.dwVersion = SCHANNEL_CRED_VERSION;
411  cred.cCreds = 1;
412  cred.paCred = &pCertContext;
413  cred.cSupportedAlgs = 0;
414  cred.palgSupportedAlgs = NULL;
415  cred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER;
416  cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER;
417  status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME, SECPKG_CRED_INBOUND, NULL, &cred,
418  NULL, NULL, &credentials, NULL);
419 
420  if (status != SEC_E_OK)
421  {
422  printf("AcquireCredentialsHandle failure: 0x%08" PRIX32 "\n", status);
423  return 0;
424  }
425 
426  extraData = FALSE;
427  g_ServerWait = TRUE;
428  if (!(lpTokenIn = (BYTE*)malloc(cbMaxToken)))
429  {
430  printf("Memory allocation failed\n");
431  return 0;
432  }
433  if (!(lpTokenOut = (BYTE*)malloc(cbMaxToken)))
434  {
435  printf("Memory allocation failed\n");
436  free(lpTokenIn);
437  return 0;
438  }
439  fContextReq = ASC_REQ_STREAM | ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT |
440  ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR;
441 
442  do
443  {
444  if (!extraData)
445  {
446  if (g_ServerWait)
447  {
448  if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL))
449  {
450  printf("Failed to read from server pipe\n");
451  return NULL;
452  }
453  }
454  else
455  {
456  NumberOfBytesRead = 0;
457  }
458  }
459 
460  extraData = FALSE;
461  g_ServerWait = TRUE;
462  SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
463  SecBuffer_in[0].pvBuffer = lpTokenIn;
464  SecBuffer_in[0].cbBuffer = NumberOfBytesRead;
465  SecBuffer_in[1].BufferType = SECBUFFER_EMPTY;
466  SecBuffer_in[1].pvBuffer = NULL;
467  SecBuffer_in[1].cbBuffer = 0;
468  SecBufferDesc_in.ulVersion = SECBUFFER_VERSION;
469  SecBufferDesc_in.cBuffers = 2;
470  SecBufferDesc_in.pBuffers = SecBuffer_in;
471  SecBuffer_out[0].BufferType = SECBUFFER_TOKEN;
472  SecBuffer_out[0].pvBuffer = lpTokenOut;
473  SecBuffer_out[0].cbBuffer = cbMaxToken;
474  SecBufferDesc_out.ulVersion = SECBUFFER_VERSION;
475  SecBufferDesc_out.cBuffers = 1;
476  SecBufferDesc_out.pBuffers = SecBuffer_out;
477  status = table->AcceptSecurityContext(
478  &credentials, SecIsValidHandle(&context) ? &context : NULL, &SecBufferDesc_in,
479  fContextReq, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry);
480 
481  if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED) &&
482  (status != SEC_E_INCOMPLETE_MESSAGE))
483  {
484  printf("AcceptSecurityContext unexpected status: 0x%08" PRIX32 "\n", status);
485  return NULL;
486  }
487 
488  NumberOfBytesWritten = 0;
489 
490  if (status == SEC_E_OK)
491  printf("AcceptSecurityContext status: SEC_E_OK\n");
492  else if (status == SEC_I_CONTINUE_NEEDED)
493  printf("AcceptSecurityContext status: SEC_I_CONTINUE_NEEDED\n");
494  else if (status == SEC_E_INCOMPLETE_MESSAGE)
495  printf("AcceptSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
496 
497  printf("Server cBuffers: %" PRIu32 " pBuffers[0]: %" PRIu32 " type: %" PRIu32 "\n",
498  SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer,
499  SecBufferDesc_out.pBuffers[0].BufferType);
500  printf("Server Input cBuffers: %" PRIu32 " pBuffers[0]: %" PRIu32 " type: %" PRIu32
501  " pBuffers[1]: %" PRIu32 " type: %" PRIu32 "\n",
502  SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[0].cbBuffer,
503  SecBufferDesc_in.pBuffers[0].BufferType, SecBufferDesc_in.pBuffers[1].cbBuffer,
504  SecBufferDesc_in.pBuffers[1].BufferType);
505 
506  if (SecBufferDesc_in.pBuffers[1].BufferType == SECBUFFER_EXTRA)
507  {
508  printf("AcceptSecurityContext SECBUFFER_EXTRA\n");
509  pSecBuffer = &SecBufferDesc_in.pBuffers[1];
510  CopyMemory(lpTokenIn, &lpTokenIn[NumberOfBytesRead - pSecBuffer->cbBuffer],
511  pSecBuffer->cbBuffer);
512  NumberOfBytesRead = pSecBuffer->cbBuffer;
513  continue;
514  }
515 
516  if (status != SEC_E_INCOMPLETE_MESSAGE)
517  {
518  pSecBuffer = &SecBufferDesc_out.pBuffers[0];
519 
520  if (pSecBuffer->cbBuffer > 0)
521  {
522  printf("Server > Client (%" PRIu32 ")\n", pSecBuffer->cbBuffer);
523  winpr_HexDump("sspi.test", WLOG_DEBUG, (BYTE*)pSecBuffer->pvBuffer,
524  pSecBuffer->cbBuffer);
525 
526  if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer,
527  &NumberOfBytesWritten, NULL))
528  {
529  printf("failed to write to client pipe\n");
530  return NULL;
531  }
532  }
533  }
534 
535  if (status == SEC_E_OK)
536  {
537  printf("Server Handshake Complete\n");
538  break;
539  }
540  } while (1);
541 
542  do
543  {
544  if (schannel_recv(table, g_ServerReadPipe, &context) < 0)
545  break;
546  } while (1);
547 
548  return 0;
549 }
550 
551 static int dump_test_certificate_files(void)
552 {
553  FILE* fp;
554  char* fullpath = NULL;
555  int ret = -1;
556 
557  /*
558  * Output Certificate File
559  */
560  fullpath = GetCombinedPath("/tmp", "localhost.crt");
561  if (!fullpath)
562  return -1;
563 
564  fp = winpr_fopen(fullpath, "w+");
565  if (fp)
566  {
567  if (fwrite((void*)test_localhost_crt, sizeof(test_localhost_crt), 1, fp) != 1)
568  goto out_fail;
569  fclose(fp);
570  fp = NULL;
571  }
572  free(fullpath);
573 
574  /*
575  * Output Private Key File
576  */
577  fullpath = GetCombinedPath("/tmp", "localhost.key");
578  if (!fullpath)
579  return -1;
580  fp = winpr_fopen(fullpath, "w+");
581  if (fp && fwrite((void*)test_localhost_key, sizeof(test_localhost_key), 1, fp) != 1)
582  goto out_fail;
583 
584  ret = 1;
585 out_fail:
586  free(fullpath);
587  if (fp)
588  fclose(fp);
589  return ret;
590 }
591 
592 int TestSchannel(int argc, char* argv[])
593 {
594  int count;
595  ALG_ID algId;
596  HANDLE thread;
597  BYTE* lpTokenIn;
598  BYTE* lpTokenOut;
599  TimeStamp expiry;
600  UINT32 cbMaxToken;
601  SCHANNEL_CRED cred = { 0 };
602  UINT32 fContextReq;
603  ULONG fContextAttr;
604  CtxtHandle context;
605  CredHandle credentials;
606  SECURITY_STATUS status;
607  PSecPkgInfo pPackageInfo;
608  PSecBuffer pSecBuffer;
609  PSecurityFunctionTable table;
610  DWORD NumberOfBytesRead;
611  DWORD NumberOfBytesWritten;
612  SecPkgCred_SupportedAlgs SupportedAlgs = { 0 };
613  SecPkgCred_CipherStrengths CipherStrengths = { 0 };
614  SecPkgCred_SupportedProtocols SupportedProtocols = { 0 };
615  return 0; /* disable by default - causes crash */
616  sspi_GlobalInit();
617  dump_test_certificate_files();
618  SecInvalidateHandle(&context);
619  SecInvalidateHandle(&credentials);
620 
621  if (!CreatePipe(&g_ClientReadPipe, &g_ClientWritePipe, NULL, 0))
622  {
623  printf("Failed to create client pipe\n");
624  return -1;
625  }
626 
627  if (!CreatePipe(&g_ServerReadPipe, &g_ServerWritePipe, NULL, 0))
628  {
629  printf("Failed to create server pipe\n");
630  return -1;
631  }
632 
633  if (!(thread = CreateThread(NULL, 0, schannel_test_server_thread, NULL, 0, NULL)))
634  {
635  printf("Failed to create server thread\n");
636  return -1;
637  }
638 
639  table = InitSecurityInterface();
640  status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo);
641 
642  if (status != SEC_E_OK)
643  {
644  printf("QuerySecurityPackageInfo failure: 0x%08" PRIX32 "\n", status);
645  return -1;
646  }
647 
648  cbMaxToken = pPackageInfo->cbMaxToken;
649  cred.dwVersion = SCHANNEL_CRED_VERSION;
650  cred.cCreds = 0;
651  cred.paCred = NULL;
652  cred.cSupportedAlgs = 0;
653  cred.palgSupportedAlgs = NULL;
654  cred.grbitEnabledProtocols = SP_PROT_SSL3TLS1_CLIENTS;
655  cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS;
656  cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
657  cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
658  status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME, SECPKG_CRED_OUTBOUND, NULL, &cred,
659  NULL, NULL, &credentials, NULL);
660 
661  if (status != SEC_E_OK)
662  {
663  printf("AcquireCredentialsHandle failure: 0x%08" PRIX32 "\n", status);
664  return -1;
665  }
666 
667  status =
668  table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_ALGS, &SupportedAlgs);
669 
670  if (status != SEC_E_OK)
671  {
672  printf("QueryCredentialsAttributes SECPKG_ATTR_SUPPORTED_ALGS failure: 0x%08" PRIX32 "\n",
673  status);
674  return -1;
675  }
676 
682  printf("SupportedAlgs: %" PRIu32 "\n", SupportedAlgs.cSupportedAlgs);
683 
684  for (DWORD index = 0; index < SupportedAlgs.cSupportedAlgs; index++)
685  {
686  algId = SupportedAlgs.palgSupportedAlgs[index];
687  printf("\t0x%08" PRIX32 " CLASS: %" PRIu32 " TYPE: %" PRIu32 " SID: %" PRIu32 "\n", algId,
688  ((GET_ALG_CLASS(algId)) >> 13), ((GET_ALG_TYPE(algId)) >> 9), GET_ALG_SID(algId));
689  }
690 
691  printf("\n");
692  status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_CIPHER_STRENGTHS,
693  &CipherStrengths);
694 
695  if (status != SEC_E_OK)
696  {
697  printf("QueryCredentialsAttributes SECPKG_ATTR_CIPHER_STRENGTHS failure: 0x%08" PRIX32 "\n",
698  status);
699  return -1;
700  }
701 
702  /* CipherStrengths: Minimum: 40 Maximum: 256 */
703  printf("CipherStrengths: Minimum: %" PRIu32 " Maximum: %" PRIu32 "\n",
704  CipherStrengths.dwMinimumCipherStrength, CipherStrengths.dwMaximumCipherStrength);
705  status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_PROTOCOLS,
706  &SupportedProtocols);
707 
708  if (status != SEC_E_OK)
709  {
710  printf("QueryCredentialsAttributes SECPKG_ATTR_SUPPORTED_PROTOCOLS failure: 0x%08" PRIX32
711  "\n",
712  status);
713  return -1;
714  }
715 
716  /* SupportedProtocols: 0x208A0 */
717  printf("SupportedProtocols: 0x%08" PRIX32 "\n", SupportedProtocols.grbitProtocol);
718  fContextReq = ISC_REQ_STREAM | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
719  ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR |
720  ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY;
721  if (!(lpTokenIn = (BYTE*)malloc(cbMaxToken)))
722  {
723  printf("Memory allocation failed\n");
724  return -1;
725  }
726  if (!(lpTokenOut = (BYTE*)malloc(cbMaxToken)))
727  {
728  printf("Memory allocation failed\n");
729  return -1;
730  }
731  g_ClientWait = FALSE;
732 
733  do
734  {
735  SecBuffer SecBuffer_in[2] = { 0 };
736  SecBuffer SecBuffer_out[1] = { 0 };
737  SecBufferDesc SecBufferDesc_in = { 0 };
738  SecBufferDesc SecBufferDesc_out = { 0 };
739  if (g_ClientWait)
740  {
741  if (!ReadFile(g_ClientReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL))
742  {
743  printf("failed to read from server pipe\n");
744  return -1;
745  }
746  }
747  else
748  {
749  NumberOfBytesRead = 0;
750  }
751 
752  g_ClientWait = TRUE;
753  printf("NumberOfBytesRead: %" PRIu32 "\n", NumberOfBytesRead);
754  SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
755  SecBuffer_in[0].pvBuffer = lpTokenIn;
756  SecBuffer_in[0].cbBuffer = NumberOfBytesRead;
757  SecBuffer_in[1].pvBuffer = NULL;
758  SecBuffer_in[1].cbBuffer = 0;
759  SecBuffer_in[1].BufferType = SECBUFFER_EMPTY;
760  SecBufferDesc_in.ulVersion = SECBUFFER_VERSION;
761  SecBufferDesc_in.cBuffers = 2;
762  SecBufferDesc_in.pBuffers = SecBuffer_in;
763  SecBuffer_out[0].BufferType = SECBUFFER_TOKEN;
764  SecBuffer_out[0].pvBuffer = lpTokenOut;
765  SecBuffer_out[0].cbBuffer = cbMaxToken;
766  SecBufferDesc_out.ulVersion = SECBUFFER_VERSION;
767  SecBufferDesc_out.cBuffers = 1;
768  SecBufferDesc_out.pBuffers = SecBuffer_out;
769  status = table->InitializeSecurityContext(
770  &credentials, SecIsValidHandle(&context) ? &context : NULL, _T("localhost"),
771  fContextReq, 0, 0, &SecBufferDesc_in, 0, &context, &SecBufferDesc_out, &fContextAttr,
772  &expiry);
773 
774  if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED) &&
775  (status != SEC_E_INCOMPLETE_MESSAGE))
776  {
777  printf("InitializeSecurityContext unexpected status: 0x%08" PRIX32 "\n", status);
778  return -1;
779  }
780 
781  NumberOfBytesWritten = 0;
782 
783  if (status == SEC_E_OK)
784  printf("InitializeSecurityContext status: SEC_E_OK\n");
785  else if (status == SEC_I_CONTINUE_NEEDED)
786  printf("InitializeSecurityContext status: SEC_I_CONTINUE_NEEDED\n");
787  else if (status == SEC_E_INCOMPLETE_MESSAGE)
788  printf("InitializeSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
789 
790  printf("Client Output cBuffers: %" PRIu32 " pBuffers[0]: %" PRIu32 " type: %" PRIu32 "\n",
791  SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer,
792  SecBufferDesc_out.pBuffers[0].BufferType);
793  printf("Client Input cBuffers: %" PRIu32 " pBuffers[0]: %" PRIu32 " type: %" PRIu32
794  " pBuffers[1]: %" PRIu32 " type: %" PRIu32 "\n",
795  SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[0].cbBuffer,
796  SecBufferDesc_in.pBuffers[0].BufferType, SecBufferDesc_in.pBuffers[1].cbBuffer,
797  SecBufferDesc_in.pBuffers[1].BufferType);
798 
799  if (status != SEC_E_INCOMPLETE_MESSAGE)
800  {
801  pSecBuffer = &SecBufferDesc_out.pBuffers[0];
802 
803  if (pSecBuffer->cbBuffer > 0)
804  {
805  printf("Client > Server (%" PRIu32 ")\n", pSecBuffer->cbBuffer);
806  winpr_HexDump("sspi.test", WLOG_DEBUG, (BYTE*)pSecBuffer->pvBuffer,
807  pSecBuffer->cbBuffer);
808 
809  if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer,
810  &NumberOfBytesWritten, NULL))
811  {
812  printf("failed to write to server pipe\n");
813  return -1;
814  }
815  }
816  }
817 
818  if (status == SEC_E_OK)
819  {
820  printf("Client Handshake Complete\n");
821  break;
822  }
823  } while (1);
824 
825  count = 0;
826 
827  do
828  {
829  if (schannel_send(table, g_ServerWritePipe, &context, test_DummyMessage,
830  sizeof(test_DummyMessage)) < 0)
831  break;
832 
833  for (DWORD index = 0; index < sizeof(test_DummyMessage); index++)
834  {
835  BYTE b, ln, hn;
836  b = test_DummyMessage[index];
837  ln = (b & 0x0F);
838  hn = ((b & 0xF0) >> 4);
839  ln = (ln + 1) % 0xF;
840  hn = (ln + 1) % 0xF;
841  b = (ln | (hn << 4));
842  test_DummyMessage[index] = b;
843  }
844 
845  Sleep(100);
846  count++;
847  } while (count < 3);
848 
849  schannel_send(table, g_ServerWritePipe, &context, test_LastDummyMessage,
850  sizeof(test_LastDummyMessage));
851  (void)WaitForSingleObject(thread, INFINITE);
852  sspi_GlobalFinish();
853  return 0;
854 }