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 
schannel_send(PSecurityFunctionTable table,HANDLE hPipe,PCtxtHandle phContext,BYTE * buffer,UINT32 length)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];
222 	SecBufferDesc Message;
223 	SECURITY_STATUS status;
224 	DWORD NumberOfBytesWritten;
225 	SecPkgContext_StreamSizes StreamSizes;
226 	ZeroMemory(&StreamSizes, sizeof(SecPkgContext_StreamSizes));
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 
schannel_recv(PSecurityFunctionTable table,HANDLE hPipe,PCtxtHandle phContext)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];
282 	SecBufferDesc Message;
283 	SECURITY_STATUS status;
284 	DWORD NumberOfBytesRead;
285 	SecPkgContext_StreamSizes StreamSizes;
286 	ZeroMemory(&StreamSizes, sizeof(SecPkgContext_StreamSizes));
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 
schannel_test_server_thread(LPVOID arg)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;
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];
356 	SecBuffer SecBuffer_out[2];
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 	ZeroMemory(&cred, sizeof(SCHANNEL_CRED));
411 	cred.dwVersion = SCHANNEL_CRED_VERSION;
412 	cred.cCreds = 1;
413 	cred.paCred = &pCertContext;
414 	cred.cSupportedAlgs = 0;
415 	cred.palgSupportedAlgs = NULL;
416 	cred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER;
417 	cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER;
418 	status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME, SECPKG_CRED_INBOUND, NULL, &cred,
419 	                                         NULL, NULL, &credentials, NULL);
420 
421 	if (status != SEC_E_OK)
422 	{
423 		printf("AcquireCredentialsHandle failure: 0x%08" PRIX32 "\n", status);
424 		return 0;
425 	}
426 
427 	extraData = FALSE;
428 	g_ServerWait = TRUE;
429 	if (!(lpTokenIn = (BYTE*)malloc(cbMaxToken)))
430 	{
431 		printf("Memory allocation failed\n");
432 		return 0;
433 	}
434 	if (!(lpTokenOut = (BYTE*)malloc(cbMaxToken)))
435 	{
436 		printf("Memory allocation failed\n");
437 		free(lpTokenIn);
438 		return 0;
439 	}
440 	fContextReq = ASC_REQ_STREAM | ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT |
441 	              ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR;
442 
443 	do
444 	{
445 		if (!extraData)
446 		{
447 			if (g_ServerWait)
448 			{
449 				if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL))
450 				{
451 					printf("Failed to read from server pipe\n");
452 					return NULL;
453 				}
454 			}
455 			else
456 			{
457 				NumberOfBytesRead = 0;
458 			}
459 		}
460 
461 		extraData = FALSE;
462 		g_ServerWait = TRUE;
463 		SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
464 		SecBuffer_in[0].pvBuffer = lpTokenIn;
465 		SecBuffer_in[0].cbBuffer = NumberOfBytesRead;
466 		SecBuffer_in[1].BufferType = SECBUFFER_EMPTY;
467 		SecBuffer_in[1].pvBuffer = NULL;
468 		SecBuffer_in[1].cbBuffer = 0;
469 		SecBufferDesc_in.ulVersion = SECBUFFER_VERSION;
470 		SecBufferDesc_in.cBuffers = 2;
471 		SecBufferDesc_in.pBuffers = SecBuffer_in;
472 		SecBuffer_out[0].BufferType = SECBUFFER_TOKEN;
473 		SecBuffer_out[0].pvBuffer = lpTokenOut;
474 		SecBuffer_out[0].cbBuffer = cbMaxToken;
475 		SecBufferDesc_out.ulVersion = SECBUFFER_VERSION;
476 		SecBufferDesc_out.cBuffers = 1;
477 		SecBufferDesc_out.pBuffers = SecBuffer_out;
478 		status = table->AcceptSecurityContext(
479 		    &credentials, SecIsValidHandle(&context) ? &context : NULL, &SecBufferDesc_in,
480 		    fContextReq, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry);
481 
482 		if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED) &&
483 		    (status != SEC_E_INCOMPLETE_MESSAGE))
484 		{
485 			printf("AcceptSecurityContext unexpected status: 0x%08" PRIX32 "\n", status);
486 			return NULL;
487 		}
488 
489 		NumberOfBytesWritten = 0;
490 
491 		if (status == SEC_E_OK)
492 			printf("AcceptSecurityContext status: SEC_E_OK\n");
493 		else if (status == SEC_I_CONTINUE_NEEDED)
494 			printf("AcceptSecurityContext status: SEC_I_CONTINUE_NEEDED\n");
495 		else if (status == SEC_E_INCOMPLETE_MESSAGE)
496 			printf("AcceptSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
497 
498 		printf("Server cBuffers: %" PRIu32 " pBuffers[0]: %" PRIu32 " type: %" PRIu32 "\n",
499 		       SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer,
500 		       SecBufferDesc_out.pBuffers[0].BufferType);
501 		printf("Server Input cBuffers: %" PRIu32 " pBuffers[0]: %" PRIu32 " type: %" PRIu32
502 		       " pBuffers[1]: %" PRIu32 " type: %" PRIu32 "\n",
503 		       SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[0].cbBuffer,
504 		       SecBufferDesc_in.pBuffers[0].BufferType, SecBufferDesc_in.pBuffers[1].cbBuffer,
505 		       SecBufferDesc_in.pBuffers[1].BufferType);
506 
507 		if (SecBufferDesc_in.pBuffers[1].BufferType == SECBUFFER_EXTRA)
508 		{
509 			printf("AcceptSecurityContext SECBUFFER_EXTRA\n");
510 			pSecBuffer = &SecBufferDesc_in.pBuffers[1];
511 			CopyMemory(lpTokenIn, &lpTokenIn[NumberOfBytesRead - pSecBuffer->cbBuffer],
512 			           pSecBuffer->cbBuffer);
513 			NumberOfBytesRead = pSecBuffer->cbBuffer;
514 			continue;
515 		}
516 
517 		if (status != SEC_E_INCOMPLETE_MESSAGE)
518 		{
519 			pSecBuffer = &SecBufferDesc_out.pBuffers[0];
520 
521 			if (pSecBuffer->cbBuffer > 0)
522 			{
523 				printf("Server > Client (%" PRIu32 ")\n", pSecBuffer->cbBuffer);
524 				winpr_HexDump("sspi.test", WLOG_DEBUG, (BYTE*)pSecBuffer->pvBuffer,
525 				              pSecBuffer->cbBuffer);
526 
527 				if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer,
528 				               &NumberOfBytesWritten, NULL))
529 				{
530 					printf("failed to write to client pipe\n");
531 					return NULL;
532 				}
533 			}
534 		}
535 
536 		if (status == SEC_E_OK)
537 		{
538 			printf("Server Handshake Complete\n");
539 			break;
540 		}
541 	} while (1);
542 
543 	do
544 	{
545 		if (schannel_recv(table, g_ServerReadPipe, &context) < 0)
546 			break;
547 	} while (1);
548 
549 	return 0;
550 }
551 
dump_test_certificate_files(void)552 static int dump_test_certificate_files(void)
553 {
554 	FILE* fp;
555 	char* fullpath = NULL;
556 	int ret = -1;
557 
558 	/*
559 	 * Output Certificate File
560 	 */
561 	fullpath = GetCombinedPath("/tmp", "localhost.crt");
562 	if (!fullpath)
563 		return -1;
564 
565 	fp = winpr_fopen(fullpath, "w+");
566 	if (fp)
567 	{
568 		if (fwrite((void*)test_localhost_crt, sizeof(test_localhost_crt), 1, fp) != 1)
569 			goto out_fail;
570 		fclose(fp);
571 		fp = NULL;
572 	}
573 	free(fullpath);
574 
575 	/*
576 	 * Output Private Key File
577 	 */
578 	fullpath = GetCombinedPath("/tmp", "localhost.key");
579 	if (!fullpath)
580 		return -1;
581 	fp = winpr_fopen(fullpath, "w+");
582 	if (fp && fwrite((void*)test_localhost_key, sizeof(test_localhost_key), 1, fp) != 1)
583 		goto out_fail;
584 
585 	ret = 1;
586 out_fail:
587 	free(fullpath);
588 	if (fp)
589 		fclose(fp);
590 	return ret;
591 }
592 
TestSchannel(int argc,char * argv[])593 int TestSchannel(int argc, char* argv[])
594 {
595 	int count;
596 	DWORD index;
597 	ALG_ID algId;
598 	HANDLE thread;
599 	BYTE* lpTokenIn;
600 	BYTE* lpTokenOut;
601 	TimeStamp expiry;
602 	UINT32 cbMaxToken;
603 	SCHANNEL_CRED cred;
604 	UINT32 fContextReq;
605 	ULONG fContextAttr;
606 	CtxtHandle context;
607 	CredHandle credentials;
608 	SECURITY_STATUS status;
609 	PSecPkgInfo pPackageInfo;
610 	PSecBuffer pSecBuffer;
611 	SecBuffer SecBuffer_in[2];
612 	SecBuffer SecBuffer_out[1];
613 	SecBufferDesc SecBufferDesc_in;
614 	SecBufferDesc SecBufferDesc_out;
615 	PSecurityFunctionTable table;
616 	DWORD NumberOfBytesRead;
617 	DWORD NumberOfBytesWritten;
618 	SecPkgCred_SupportedAlgs SupportedAlgs;
619 	SecPkgCred_CipherStrengths CipherStrengths;
620 	SecPkgCred_SupportedProtocols SupportedProtocols;
621 	return 0; /* disable by default - causes crash */
622 	sspi_GlobalInit();
623 	dump_test_certificate_files();
624 	SecInvalidateHandle(&context);
625 	SecInvalidateHandle(&credentials);
626 
627 	if (!CreatePipe(&g_ClientReadPipe, &g_ClientWritePipe, NULL, 0))
628 	{
629 		printf("Failed to create client pipe\n");
630 		return -1;
631 	}
632 
633 	if (!CreatePipe(&g_ServerReadPipe, &g_ServerWritePipe, NULL, 0))
634 	{
635 		printf("Failed to create server pipe\n");
636 		return -1;
637 	}
638 
639 	if (!(thread = CreateThread(NULL, 0, schannel_test_server_thread, NULL, 0, NULL)))
640 	{
641 		printf("Failed to create server thread\n");
642 		return -1;
643 	}
644 
645 	table = InitSecurityInterface();
646 	status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo);
647 
648 	if (status != SEC_E_OK)
649 	{
650 		printf("QuerySecurityPackageInfo failure: 0x%08" PRIX32 "\n", status);
651 		return -1;
652 	}
653 
654 	cbMaxToken = pPackageInfo->cbMaxToken;
655 	ZeroMemory(&cred, sizeof(SCHANNEL_CRED));
656 	cred.dwVersion = SCHANNEL_CRED_VERSION;
657 	cred.cCreds = 0;
658 	cred.paCred = NULL;
659 	cred.cSupportedAlgs = 0;
660 	cred.palgSupportedAlgs = NULL;
661 	cred.grbitEnabledProtocols = SP_PROT_SSL3TLS1_CLIENTS;
662 	cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS;
663 	cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION;
664 	cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK;
665 	status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME, SECPKG_CRED_OUTBOUND, NULL, &cred,
666 	                                         NULL, NULL, &credentials, NULL);
667 
668 	if (status != SEC_E_OK)
669 	{
670 		printf("AcquireCredentialsHandle failure: 0x%08" PRIX32 "\n", status);
671 		return -1;
672 	}
673 
674 	ZeroMemory(&SupportedAlgs, sizeof(SecPkgCred_SupportedAlgs));
675 	status =
676 	    table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_ALGS, &SupportedAlgs);
677 
678 	if (status != SEC_E_OK)
679 	{
680 		printf("QueryCredentialsAttributes SECPKG_ATTR_SUPPORTED_ALGS failure: 0x%08" PRIX32 "\n",
681 		       status);
682 		return -1;
683 	}
684 
685 	/**
686 	 * SupportedAlgs: 15
687 	 * 0x660E 0x6610 0x6801 0x6603 0x6601 0x8003 0x8004
688 	 * 0x800C 0x800D 0x800E 0x2400 0xAA02 0xAE06 0x2200 0x2203
689 	 */
690 	printf("SupportedAlgs: %" PRIu32 "\n", SupportedAlgs.cSupportedAlgs);
691 
692 	for (index = 0; index < SupportedAlgs.cSupportedAlgs; index++)
693 	{
694 		algId = SupportedAlgs.palgSupportedAlgs[index];
695 		printf("\t0x%08" PRIX32 " CLASS: %" PRIu32 " TYPE: %" PRIu32 " SID: %" PRIu32 "\n", algId,
696 		       ((GET_ALG_CLASS(algId)) >> 13), ((GET_ALG_TYPE(algId)) >> 9), GET_ALG_SID(algId));
697 	}
698 
699 	printf("\n");
700 	ZeroMemory(&CipherStrengths, sizeof(SecPkgCred_CipherStrengths));
701 	status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_CIPHER_STRENGTHS,
702 	                                           &CipherStrengths);
703 
704 	if (status != SEC_E_OK)
705 	{
706 		printf("QueryCredentialsAttributes SECPKG_ATTR_CIPHER_STRENGTHS failure: 0x%08" PRIX32 "\n",
707 		       status);
708 		return -1;
709 	}
710 
711 	/* CipherStrengths: Minimum: 40 Maximum: 256 */
712 	printf("CipherStrengths: Minimum: %" PRIu32 " Maximum: %" PRIu32 "\n",
713 	       CipherStrengths.dwMinimumCipherStrength, CipherStrengths.dwMaximumCipherStrength);
714 	ZeroMemory(&SupportedProtocols, sizeof(SecPkgCred_SupportedProtocols));
715 	status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_PROTOCOLS,
716 	                                           &SupportedProtocols);
717 
718 	if (status != SEC_E_OK)
719 	{
720 		printf("QueryCredentialsAttributes SECPKG_ATTR_SUPPORTED_PROTOCOLS failure: 0x%08" PRIX32
721 		       "\n",
722 		       status);
723 		return -1;
724 	}
725 
726 	/* SupportedProtocols: 0x208A0 */
727 	printf("SupportedProtocols: 0x%08" PRIX32 "\n", SupportedProtocols.grbitProtocol);
728 	fContextReq = ISC_REQ_STREAM | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT |
729 	              ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR |
730 	              ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY;
731 	if (!(lpTokenIn = (BYTE*)malloc(cbMaxToken)))
732 	{
733 		printf("Memory allocation failed\n");
734 		return -1;
735 	}
736 	if (!(lpTokenOut = (BYTE*)malloc(cbMaxToken)))
737 	{
738 		printf("Memory allocation failed\n");
739 		return -1;
740 	}
741 	ZeroMemory(&SecBuffer_in, sizeof(SecBuffer_in));
742 	ZeroMemory(&SecBuffer_out, sizeof(SecBuffer_out));
743 	ZeroMemory(&SecBufferDesc_in, sizeof(SecBufferDesc));
744 	ZeroMemory(&SecBufferDesc_out, sizeof(SecBufferDesc));
745 	g_ClientWait = FALSE;
746 
747 	do
748 	{
749 		if (g_ClientWait)
750 		{
751 			if (!ReadFile(g_ClientReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL))
752 			{
753 				printf("failed to read from server pipe\n");
754 				return -1;
755 			}
756 		}
757 		else
758 		{
759 			NumberOfBytesRead = 0;
760 		}
761 
762 		g_ClientWait = TRUE;
763 		printf("NumberOfBytesRead: %" PRIu32 "\n", NumberOfBytesRead);
764 		SecBuffer_in[0].BufferType = SECBUFFER_TOKEN;
765 		SecBuffer_in[0].pvBuffer = lpTokenIn;
766 		SecBuffer_in[0].cbBuffer = NumberOfBytesRead;
767 		SecBuffer_in[1].pvBuffer = NULL;
768 		SecBuffer_in[1].cbBuffer = 0;
769 		SecBuffer_in[1].BufferType = SECBUFFER_EMPTY;
770 		SecBufferDesc_in.ulVersion = SECBUFFER_VERSION;
771 		SecBufferDesc_in.cBuffers = 2;
772 		SecBufferDesc_in.pBuffers = SecBuffer_in;
773 		SecBuffer_out[0].BufferType = SECBUFFER_TOKEN;
774 		SecBuffer_out[0].pvBuffer = lpTokenOut;
775 		SecBuffer_out[0].cbBuffer = cbMaxToken;
776 		SecBufferDesc_out.ulVersion = SECBUFFER_VERSION;
777 		SecBufferDesc_out.cBuffers = 1;
778 		SecBufferDesc_out.pBuffers = SecBuffer_out;
779 		status = table->InitializeSecurityContext(
780 		    &credentials, SecIsValidHandle(&context) ? &context : NULL, _T("localhost"),
781 		    fContextReq, 0, 0, &SecBufferDesc_in, 0, &context, &SecBufferDesc_out, &fContextAttr,
782 		    &expiry);
783 
784 		if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED) &&
785 		    (status != SEC_E_INCOMPLETE_MESSAGE))
786 		{
787 			printf("InitializeSecurityContext unexpected status: 0x%08" PRIX32 "\n", status);
788 			return -1;
789 		}
790 
791 		NumberOfBytesWritten = 0;
792 
793 		if (status == SEC_E_OK)
794 			printf("InitializeSecurityContext status: SEC_E_OK\n");
795 		else if (status == SEC_I_CONTINUE_NEEDED)
796 			printf("InitializeSecurityContext status: SEC_I_CONTINUE_NEEDED\n");
797 		else if (status == SEC_E_INCOMPLETE_MESSAGE)
798 			printf("InitializeSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n");
799 
800 		printf("Client Output cBuffers: %" PRIu32 " pBuffers[0]: %" PRIu32 " type: %" PRIu32 "\n",
801 		       SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer,
802 		       SecBufferDesc_out.pBuffers[0].BufferType);
803 		printf("Client Input cBuffers: %" PRIu32 " pBuffers[0]: %" PRIu32 " type: %" PRIu32
804 		       " pBuffers[1]: %" PRIu32 " type: %" PRIu32 "\n",
805 		       SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[0].cbBuffer,
806 		       SecBufferDesc_in.pBuffers[0].BufferType, SecBufferDesc_in.pBuffers[1].cbBuffer,
807 		       SecBufferDesc_in.pBuffers[1].BufferType);
808 
809 		if (status != SEC_E_INCOMPLETE_MESSAGE)
810 		{
811 			pSecBuffer = &SecBufferDesc_out.pBuffers[0];
812 
813 			if (pSecBuffer->cbBuffer > 0)
814 			{
815 				printf("Client > Server (%" PRIu32 ")\n", pSecBuffer->cbBuffer);
816 				winpr_HexDump("sspi.test", WLOG_DEBUG, (BYTE*)pSecBuffer->pvBuffer,
817 				              pSecBuffer->cbBuffer);
818 
819 				if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer,
820 				               &NumberOfBytesWritten, NULL))
821 				{
822 					printf("failed to write to server pipe\n");
823 					return -1;
824 				}
825 			}
826 		}
827 
828 		if (status == SEC_E_OK)
829 		{
830 			printf("Client Handshake Complete\n");
831 			break;
832 		}
833 	} while (1);
834 
835 	count = 0;
836 
837 	do
838 	{
839 		if (schannel_send(table, g_ServerWritePipe, &context, test_DummyMessage,
840 		                  sizeof(test_DummyMessage)) < 0)
841 			break;
842 
843 		for (index = 0; index < sizeof(test_DummyMessage); index++)
844 		{
845 			BYTE b, ln, hn;
846 			b = test_DummyMessage[index];
847 			ln = (b & 0x0F);
848 			hn = ((b & 0xF0) >> 4);
849 			ln = (ln + 1) % 0xF;
850 			hn = (ln + 1) % 0xF;
851 			b = (ln | (hn << 4));
852 			test_DummyMessage[index] = b;
853 		}
854 
855 		Sleep(100);
856 		count++;
857 	} while (count < 3);
858 
859 	schannel_send(table, g_ServerWritePipe, &context, test_LastDummyMessage,
860 	              sizeof(test_LastDummyMessage));
861 	WaitForSingleObject(thread, INFINITE);
862 	sspi_GlobalFinish();
863 	return 0;
864 }
865