#include #include #include #include #include #include #include #include #include #include #include #include static BOOL g_ClientWait = FALSE; static BOOL g_ServerWait = FALSE; static HANDLE g_ClientReadPipe = NULL; static HANDLE g_ClientWritePipe = NULL; static HANDLE g_ServerReadPipe = NULL; static HANDLE g_ServerWritePipe = NULL; static const BYTE test_localhost_crt[1029] = { 0x2D,0x2D,0x2D,0x2D,0x2D,0x42,0x45,0x47,0x49,0x4E,0x20,0x43,0x45,0x52,0x54, 0x49,0x46,0x49,0x43,0x41,0x54,0x45,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A,0x4D,0x49, 0x49,0x43,0x79,0x6A,0x43,0x43,0x41,0x62,0x4B,0x67,0x41,0x77,0x49,0x42,0x41, 0x67,0x49,0x45,0x63,0x61,0x64,0x63,0x72,0x7A,0x41,0x4E,0x42,0x67,0x6B,0x71, 0x68,0x6B,0x69,0x47,0x39,0x77,0x30,0x42,0x41,0x51,0x55,0x46,0x41,0x44,0x41, 0x55,0x4D,0x52,0x49,0x77,0x45,0x41,0x59,0x44,0x56,0x51,0x51,0x44,0x45,0x77, 0x6C,0x73,0x0A,0x62,0x32,0x4E,0x68,0x62,0x47,0x68,0x76,0x63,0x33,0x51,0x77, 0x48,0x68,0x63,0x4E,0x4D,0x54,0x4D,0x78,0x4D,0x44,0x45,0x78,0x4D,0x44,0x59, 0x78,0x4E,0x7A,0x55,0x31,0x57,0x68,0x63,0x4E,0x4D,0x54,0x51,0x78,0x4D,0x44, 0x45,0x78,0x4D,0x44,0x59,0x78,0x4E,0x7A,0x55,0x31,0x57,0x6A,0x41,0x55,0x4D, 0x52,0x49,0x77,0x45,0x41,0x59,0x44,0x0A,0x56,0x51,0x51,0x44,0x45,0x77,0x6C, 0x73,0x62,0x32,0x4E,0x68,0x62,0x47,0x68,0x76,0x63,0x33,0x51,0x77,0x67,0x67, 0x45,0x69,0x4D,0x41,0x30,0x47,0x43,0x53,0x71,0x47,0x53,0x49,0x62,0x33,0x44, 0x51,0x45,0x42,0x41,0x51,0x55,0x41,0x41,0x34,0x49,0x42,0x44,0x77,0x41,0x77, 0x67,0x67,0x45,0x4B,0x41,0x6F,0x49,0x42,0x41,0x51,0x43,0x33,0x0A,0x65,0x6E, 0x33,0x68,0x5A,0x4F,0x53,0x33,0x6B,0x51,0x2F,0x55,0x54,0x30,0x53,0x45,0x6C, 0x30,0x48,0x6E,0x50,0x79,0x64,0x48,0x75,0x35,0x39,0x61,0x69,0x71,0x64,0x73, 0x64,0x53,0x55,0x74,0x6E,0x43,0x41,0x37,0x46,0x66,0x74,0x30,0x4F,0x36,0x51, 0x79,0x68,0x49,0x71,0x58,0x7A,0x30,0x47,0x32,0x53,0x76,0x77,0x4C,0x54,0x62, 0x79,0x68,0x0A,0x59,0x54,0x68,0x31,0x36,0x78,0x31,0x72,0x45,0x48,0x68,0x31, 0x57,0x47,0x5A,0x6D,0x36,0x77,0x64,0x2B,0x4B,0x76,0x38,0x6B,0x31,0x6B,0x2F, 0x36,0x6F,0x41,0x2F,0x4F,0x51,0x76,0x65,0x61,0x38,0x6B,0x63,0x45,0x64,0x53, 0x72,0x54,0x64,0x75,0x71,0x4A,0x33,0x65,0x66,0x74,0x48,0x4A,0x4A,0x6E,0x43, 0x4B,0x30,0x41,0x62,0x68,0x34,0x39,0x0A,0x41,0x47,0x41,0x50,0x39,0x79,0x58, 0x77,0x77,0x59,0x41,0x6A,0x51,0x49,0x52,0x6E,0x38,0x2B,0x4F,0x63,0x63,0x48, 0x74,0x6F,0x4E,0x75,0x75,0x79,0x52,0x63,0x6B,0x49,0x50,0x71,0x75,0x70,0x78, 0x79,0x31,0x4A,0x5A,0x4B,0x39,0x64,0x76,0x76,0x62,0x34,0x79,0x53,0x6B,0x49, 0x75,0x7A,0x62,0x79,0x50,0x6F,0x54,0x41,0x79,0x61,0x55,0x2B,0x0A,0x51,0x72, 0x70,0x34,0x78,0x67,0x64,0x4B,0x46,0x54,0x70,0x6B,0x50,0x46,0x34,0x33,0x6A, 0x32,0x4D,0x6D,0x5A,0x72,0x46,0x63,0x42,0x76,0x79,0x6A,0x69,0x35,0x6A,0x4F, 0x37,0x74,0x66,0x6F,0x56,0x61,0x6B,0x59,0x47,0x53,0x2F,0x4C,0x63,0x78,0x77, 0x47,0x2B,0x77,0x51,0x77,0x63,0x4F,0x43,0x54,0x42,0x45,0x78,0x2F,0x7A,0x31, 0x53,0x30,0x0A,0x37,0x49,0x2F,0x6A,0x62,0x44,0x79,0x53,0x4E,0x68,0x44,0x35, 0x63,0x61,0x63,0x54,0x75,0x4E,0x36,0x50,0x68,0x33,0x58,0x30,0x71,0x70,0x47, 0x73,0x37,0x79,0x50,0x6B,0x4E,0x79,0x69,0x4A,0x33,0x57,0x52,0x69,0x6C,0x35, 0x75,0x57,0x73,0x4B,0x65,0x79,0x63,0x64,0x71,0x42,0x4E,0x72,0x34,0x75,0x32, 0x62,0x49,0x52,0x6E,0x63,0x54,0x51,0x0A,0x46,0x72,0x68,0x73,0x58,0x39,0x69, 0x77,0x37,0x35,0x76,0x75,0x53,0x64,0x35,0x46,0x39,0x37,0x56,0x70,0x41,0x67, 0x4D,0x42,0x41,0x41,0x47,0x6A,0x4A,0x44,0x41,0x69,0x4D,0x42,0x4D,0x47,0x41, 0x31,0x55,0x64,0x4A,0x51,0x51,0x4D,0x4D,0x41,0x6F,0x47,0x43,0x43,0x73,0x47, 0x41,0x51,0x55,0x46,0x42,0x77,0x4D,0x42,0x4D,0x41,0x73,0x47,0x0A,0x41,0x31, 0x55,0x64,0x44,0x77,0x51,0x45,0x41,0x77,0x49,0x45,0x4D,0x44,0x41,0x4E,0x42, 0x67,0x6B,0x71,0x68,0x6B,0x69,0x47,0x39,0x77,0x30,0x42,0x41,0x51,0x55,0x46, 0x41,0x41,0x4F,0x43,0x41,0x51,0x45,0x41,0x49,0x51,0x66,0x75,0x2F,0x77,0x39, 0x45,0x34,0x4C,0x6F,0x67,0x30,0x71,0x35,0x4B,0x53,0x38,0x71,0x46,0x78,0x62, 0x36,0x6F,0x0A,0x36,0x31,0x62,0x35,0x37,0x6F,0x6D,0x6E,0x46,0x59,0x52,0x34, 0x47,0x43,0x67,0x33,0x6F,0x6A,0x4F,0x4C,0x54,0x66,0x38,0x7A,0x6A,0x4D,0x43, 0x52,0x6D,0x75,0x59,0x32,0x76,0x30,0x4E,0x34,0x78,0x66,0x68,0x69,0x35,0x4B, 0x69,0x59,0x67,0x64,0x76,0x4E,0x4C,0x4F,0x33,0x52,0x42,0x6D,0x4E,0x50,0x76, 0x59,0x58,0x50,0x52,0x46,0x41,0x76,0x0A,0x66,0x61,0x76,0x66,0x57,0x75,0x6C, 0x44,0x31,0x64,0x50,0x36,0x31,0x69,0x35,0x62,0x36,0x59,0x66,0x56,0x6C,0x78, 0x62,0x31,0x61,0x57,0x46,0x37,0x4C,0x5A,0x44,0x32,0x55,0x6E,0x63,0x41,0x6A, 0x37,0x4E,0x38,0x78,0x38,0x2B,0x36,0x58,0x6B,0x30,0x6B,0x63,0x70,0x58,0x46, 0x38,0x6C,0x77,0x58,0x48,0x55,0x57,0x57,0x55,0x6D,0x73,0x2B,0x0A,0x4B,0x56, 0x44,0x34,0x34,0x39,0x68,0x6F,0x4D,0x2B,0x77,0x4E,0x4A,0x49,0x61,0x4F,0x52, 0x39,0x4C,0x46,0x2B,0x6B,0x6F,0x32,0x32,0x37,0x7A,0x74,0x37,0x54,0x41,0x47, 0x64,0x56,0x35,0x4A,0x75,0x7A,0x71,0x38,0x32,0x2F,0x6B,0x75,0x73,0x6F,0x65, 0x32,0x69,0x75,0x57,0x77,0x54,0x65,0x42,0x6C,0x53,0x5A,0x6E,0x6B,0x42,0x38, 0x63,0x64,0x0A,0x77,0x4D,0x30,0x5A,0x42,0x58,0x6D,0x34,0x35,0x48,0x38,0x6F, 0x79,0x75,0x36,0x4A,0x71,0x59,0x71,0x45,0x6D,0x75,0x4A,0x51,0x64,0x67,0x79, 0x52,0x2B,0x63,0x53,0x53,0x41,0x7A,0x2B,0x4F,0x32,0x6D,0x61,0x62,0x68,0x50, 0x5A,0x65,0x49,0x76,0x78,0x65,0x67,0x6A,0x6A,0x61,0x5A,0x61,0x46,0x4F,0x71, 0x74,0x73,0x2B,0x64,0x33,0x72,0x39,0x0A,0x79,0x71,0x4A,0x78,0x67,0x75,0x39, 0x43,0x38,0x39,0x5A,0x69,0x33,0x39,0x57,0x34,0x38,0x46,0x66,0x46,0x63,0x49, 0x58,0x4A,0x4F,0x6B,0x39,0x43,0x4E,0x46,0x41,0x2F,0x69,0x70,0x54,0x57,0x6A, 0x74,0x74,0x4E,0x2F,0x6B,0x4F,0x6B,0x5A,0x42,0x70,0x6F,0x6A,0x2F,0x32,0x6A, 0x4E,0x45,0x62,0x4F,0x59,0x7A,0x7A,0x6E,0x4B,0x77,0x3D,0x3D,0x0A,0x2D,0x2D, 0x2D,0x2D,0x2D,0x45,0x4E,0x44,0x20,0x43,0x45,0x52,0x54,0x49,0x46,0x49,0x43, 0x41,0x54,0x45,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A }; static const BYTE test_localhost_key[1704] = { 0x2D,0x2D,0x2D,0x2D,0x2D,0x42,0x45,0x47,0x49,0x4E,0x20,0x50,0x52,0x49,0x56, 0x41,0x54,0x45,0x20,0x4B,0x45,0x59,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A,0x4D,0x49, 0x49,0x45,0x76,0x51,0x49,0x42,0x41,0x44,0x41,0x4E,0x42,0x67,0x6B,0x71,0x68, 0x6B,0x69,0x47,0x39,0x77,0x30,0x42,0x41,0x51,0x45,0x46,0x41,0x41,0x53,0x43, 0x42,0x4B,0x63,0x77,0x67,0x67,0x53,0x6A,0x41,0x67,0x45,0x41,0x41,0x6F,0x49, 0x42,0x41,0x51,0x43,0x33,0x65,0x6E,0x33,0x68,0x5A,0x4F,0x53,0x33,0x6B,0x51, 0x2F,0x55,0x0A,0x54,0x30,0x53,0x45,0x6C,0x30,0x48,0x6E,0x50,0x79,0x64,0x48, 0x75,0x35,0x39,0x61,0x69,0x71,0x64,0x73,0x64,0x53,0x55,0x74,0x6E,0x43,0x41, 0x37,0x46,0x66,0x74,0x30,0x4F,0x36,0x51,0x79,0x68,0x49,0x71,0x58,0x7A,0x30, 0x47,0x32,0x53,0x76,0x77,0x4C,0x54,0x62,0x79,0x68,0x59,0x54,0x68,0x31,0x36, 0x78,0x31,0x72,0x45,0x48,0x68,0x31,0x0A,0x57,0x47,0x5A,0x6D,0x36,0x77,0x64, 0x2B,0x4B,0x76,0x38,0x6B,0x31,0x6B,0x2F,0x36,0x6F,0x41,0x2F,0x4F,0x51,0x76, 0x65,0x61,0x38,0x6B,0x63,0x45,0x64,0x53,0x72,0x54,0x64,0x75,0x71,0x4A,0x33, 0x65,0x66,0x74,0x48,0x4A,0x4A,0x6E,0x43,0x4B,0x30,0x41,0x62,0x68,0x34,0x39, 0x41,0x47,0x41,0x50,0x39,0x79,0x58,0x77,0x77,0x59,0x41,0x6A,0x0A,0x51,0x49, 0x52,0x6E,0x38,0x2B,0x4F,0x63,0x63,0x48,0x74,0x6F,0x4E,0x75,0x75,0x79,0x52, 0x63,0x6B,0x49,0x50,0x71,0x75,0x70,0x78,0x79,0x31,0x4A,0x5A,0x4B,0x39,0x64, 0x76,0x76,0x62,0x34,0x79,0x53,0x6B,0x49,0x75,0x7A,0x62,0x79,0x50,0x6F,0x54, 0x41,0x79,0x61,0x55,0x2B,0x51,0x72,0x70,0x34,0x78,0x67,0x64,0x4B,0x46,0x54, 0x70,0x6B,0x0A,0x50,0x46,0x34,0x33,0x6A,0x32,0x4D,0x6D,0x5A,0x72,0x46,0x63, 0x42,0x76,0x79,0x6A,0x69,0x35,0x6A,0x4F,0x37,0x74,0x66,0x6F,0x56,0x61,0x6B, 0x59,0x47,0x53,0x2F,0x4C,0x63,0x78,0x77,0x47,0x2B,0x77,0x51,0x77,0x63,0x4F, 0x43,0x54,0x42,0x45,0x78,0x2F,0x7A,0x31,0x53,0x30,0x37,0x49,0x2F,0x6A,0x62, 0x44,0x79,0x53,0x4E,0x68,0x44,0x35,0x0A,0x63,0x61,0x63,0x54,0x75,0x4E,0x36, 0x50,0x68,0x33,0x58,0x30,0x71,0x70,0x47,0x73,0x37,0x79,0x50,0x6B,0x4E,0x79, 0x69,0x4A,0x33,0x57,0x52,0x69,0x6C,0x35,0x75,0x57,0x73,0x4B,0x65,0x79,0x63, 0x64,0x71,0x42,0x4E,0x72,0x34,0x75,0x32,0x62,0x49,0x52,0x6E,0x63,0x54,0x51, 0x46,0x72,0x68,0x73,0x58,0x39,0x69,0x77,0x37,0x35,0x76,0x75,0x0A,0x53,0x64, 0x35,0x46,0x39,0x37,0x56,0x70,0x41,0x67,0x4D,0x42,0x41,0x41,0x45,0x43,0x67, 0x67,0x45,0x41,0x42,0x36,0x6A,0x6C,0x65,0x48,0x4E,0x74,0x32,0x50,0x77,0x46, 0x58,0x53,0x65,0x79,0x42,0x4A,0x63,0x4C,0x2B,0x55,0x74,0x35,0x71,0x46,0x54, 0x38,0x34,0x68,0x72,0x48,0x77,0x6F,0x39,0x68,0x62,0x66,0x59,0x47,0x6F,0x6E, 0x44,0x59,0x0A,0x66,0x70,0x47,0x2B,0x32,0x52,0x30,0x50,0x62,0x43,0x63,0x4B, 0x35,0x30,0x46,0x61,0x4A,0x46,0x36,0x71,0x63,0x56,0x4A,0x4E,0x75,0x52,0x36, 0x48,0x71,0x2B,0x43,0x55,0x4A,0x74,0x48,0x35,0x39,0x48,0x48,0x37,0x62,0x68, 0x6A,0x39,0x62,0x64,0x78,0x45,0x6D,0x6F,0x48,0x30,0x4A,0x76,0x68,0x45,0x76, 0x67,0x4D,0x2F,0x55,0x38,0x42,0x51,0x0A,0x65,0x57,0x4F,0x4E,0x68,0x78,0x50, 0x73,0x69,0x73,0x6D,0x57,0x6B,0x78,0x61,0x5A,0x6F,0x6C,0x72,0x32,0x69,0x44, 0x56,0x72,0x7A,0x54,0x37,0x55,0x4A,0x71,0x6A,0x74,0x59,0x49,0x74,0x67,0x2B, 0x37,0x59,0x43,0x32,0x70,0x55,0x58,0x6B,0x64,0x49,0x35,0x4A,0x4D,0x67,0x6C, 0x44,0x47,0x4D,0x52,0x5A,0x35,0x55,0x5A,0x48,0x75,0x63,0x7A,0x0A,0x41,0x56, 0x2B,0x71,0x77,0x77,0x33,0x65,0x45,0x52,0x74,0x78,0x44,0x50,0x61,0x61,0x61, 0x34,0x54,0x39,0x50,0x64,0x33,0x44,0x31,0x6D,0x62,0x71,0x58,0x66,0x75,0x45, 0x68,0x42,0x6D,0x33,0x51,0x6F,0x2B,0x75,0x7A,0x51,0x32,0x36,0x76,0x73,0x66, 0x48,0x75,0x56,0x76,0x61,0x39,0x38,0x32,0x4F,0x6A,0x41,0x55,0x6A,0x6E,0x64, 0x30,0x70,0x0A,0x77,0x43,0x53,0x6E,0x42,0x49,0x48,0x67,0x70,0x73,0x30,0x79, 0x61,0x45,0x50,0x63,0x37,0x46,0x78,0x39,0x71,0x45,0x63,0x6D,0x33,0x70,0x7A, 0x41,0x56,0x31,0x69,0x72,0x31,0x4E,0x4E,0x63,0x51,0x47,0x55,0x45,0x75,0x45, 0x6C,0x4A,0x78,0x76,0x2B,0x69,0x57,0x34,0x6D,0x35,0x70,0x7A,0x4C,0x6A,0x64, 0x53,0x63,0x49,0x30,0x59,0x45,0x73,0x0A,0x4D,0x61,0x33,0x78,0x32,0x79,0x48, 0x74,0x6E,0x77,0x79,0x65,0x4C,0x4D,0x54,0x4B,0x6C,0x72,0x46,0x4B,0x70,0x55, 0x4E,0x4A,0x62,0x78,0x73,0x35,0x32,0x62,0x5A,0x4B,0x71,0x49,0x56,0x33,0x33, 0x4A,0x53,0x34,0x41,0x51,0x4B,0x42,0x67,0x51,0x44,0x73,0x4C,0x54,0x49,0x68, 0x35,0x59,0x38,0x4C,0x2F,0x48,0x33,0x64,0x74,0x68,0x63,0x62,0x0A,0x53,0x43, 0x45,0x77,0x32,0x64,0x42,0x49,0x76,0x49,0x79,0x54,0x7A,0x39,0x53,0x72,0x62, 0x33,0x58,0x37,0x37,0x41,0x77,0x57,0x45,0x4C,0x53,0x4D,0x49,0x57,0x53,0x50, 0x55,0x43,0x4B,0x54,0x49,0x70,0x6A,0x4D,0x73,0x6E,0x7A,0x6B,0x46,0x67,0x32, 0x32,0x59,0x32,0x53,0x75,0x47,0x38,0x4C,0x72,0x50,0x6D,0x76,0x73,0x46,0x4A, 0x34,0x30,0x0A,0x32,0x67,0x35,0x44,0x55,0x6C,0x59,0x33,0x59,0x6D,0x53,0x4F, 0x46,0x61,0x45,0x4A,0x54,0x70,0x55,0x47,0x44,0x4D,0x79,0x65,0x33,0x74,0x36, 0x4F,0x30,0x6C,0x63,0x51,0x41,0x66,0x79,0x6D,0x58,0x66,0x41,0x38,0x74,0x50, 0x42,0x48,0x6A,0x5A,0x78,0x56,0x61,0x38,0x78,0x78,0x52,0x5A,0x6E,0x56,0x43, 0x31,0x41,0x62,0x75,0x49,0x49,0x52,0x0A,0x6E,0x77,0x72,0x4E,0x46,0x2B,0x42, 0x6F,0x53,0x4B,0x55,0x41,0x73,0x78,0x2B,0x46,0x75,0x35,0x5A,0x4A,0x4B,0x4F, 0x66,0x79,0x4D,0x51,0x4B,0x42,0x67,0x51,0x44,0x47,0x34,0x50,0x52,0x39,0x2F, 0x58,0x58,0x6B,0x51,0x54,0x36,0x6B,0x7A,0x4B,0x64,0x34,0x50,0x6C,0x50,0x4D, 0x63,0x2B,0x4B,0x51,0x79,0x4C,0x45,0x6C,0x4B,0x39,0x71,0x47,0x0A,0x41,0x6D, 0x6E,0x2F,0x31,0x68,0x64,0x69,0x57,0x57,0x4F,0x52,0x57,0x46,0x62,0x32,0x38, 0x30,0x4D,0x77,0x76,0x77,0x41,0x64,0x78,0x72,0x66,0x65,0x4C,0x57,0x4D,0x57, 0x32,0x66,0x76,0x4C,0x59,0x4B,0x66,0x6C,0x4F,0x35,0x50,0x51,0x44,0x59,0x67, 0x4B,0x4A,0x78,0x35,0x79,0x50,0x37,0x52,0x64,0x38,0x2F,0x64,0x50,0x79,0x5A, 0x59,0x36,0x0A,0x7A,0x56,0x37,0x47,0x47,0x6B,0x51,0x5A,0x42,0x4B,0x36,0x79, 0x74,0x61,0x66,0x32,0x35,0x44,0x50,0x67,0x50,0x72,0x32,0x77,0x73,0x59,0x4D, 0x43,0x6C,0x53,0x74,0x6C,0x56,0x74,0x72,0x6D,0x4F,0x78,0x59,0x55,0x56,0x77, 0x42,0x59,0x4F,0x69,0x36,0x45,0x62,0x50,0x69,0x6B,0x78,0x47,0x48,0x5A,0x70, 0x59,0x6F,0x5A,0x5A,0x70,0x68,0x4A,0x0A,0x4E,0x61,0x38,0x4F,0x4C,0x31,0x69, 0x77,0x75,0x51,0x4B,0x42,0x67,0x51,0x44,0x42,0x55,0x55,0x31,0x54,0x79,0x5A, 0x2B,0x4A,0x5A,0x43,0x64,0x79,0x72,0x33,0x58,0x43,0x63,0x77,0x77,0x58,0x2F, 0x48,0x49,0x73,0x31,0x34,0x6B,0x4B,0x42,0x48,0x68,0x44,0x79,0x33,0x78,0x37, 0x74,0x50,0x38,0x2F,0x6F,0x48,0x54,0x6F,0x72,0x76,0x79,0x74,0x0A,0x41,0x68, 0x38,0x4B,0x36,0x4B,0x72,0x43,0x41,0x75,0x65,0x50,0x6D,0x79,0x32,0x6D,0x4F, 0x54,0x31,0x54,0x39,0x6F,0x31,0x61,0x47,0x55,0x49,0x6C,0x66,0x38,0x72,0x76, 0x33,0x2F,0x30,0x45,0x78,0x67,0x53,0x6B,0x57,0x50,0x6D,0x4F,0x41,0x38,0x35, 0x49,0x32,0x2F,0x58,0x48,0x65,0x66,0x71,0x54,0x6F,0x45,0x48,0x30,0x44,0x65, 0x41,0x4E,0x0A,0x7A,0x6C,0x4B,0x4C,0x71,0x79,0x44,0x56,0x30,0x42,0x56,0x4E, 0x76,0x48,0x42,0x57,0x79,0x32,0x49,0x51,0x35,0x62,0x50,0x42,0x57,0x76,0x30, 0x37,0x63,0x34,0x2B,0x6A,0x39,0x4E,0x62,0x57,0x67,0x64,0x44,0x43,0x43,0x35, 0x52,0x6B,0x4F,0x6A,0x70,0x33,0x4D,0x4E,0x45,0x58,0x47,0x56,0x43,0x69,0x51, 0x51,0x4B,0x42,0x67,0x43,0x7A,0x4D,0x0A,0x77,0x65,0x61,0x62,0x73,0x50,0x48, 0x68,0x44,0x4B,0x5A,0x38,0x2F,0x34,0x43,0x6A,0x73,0x61,0x62,0x4E,0x75,0x41, 0x7A,0x62,0x57,0x4B,0x52,0x42,0x38,0x37,0x44,0x61,0x58,0x46,0x78,0x6F,0x4D, 0x73,0x35,0x52,0x79,0x6F,0x38,0x55,0x4D,0x6B,0x72,0x67,0x30,0x35,0x4C,0x6F, 0x67,0x37,0x4D,0x78,0x62,0x33,0x76,0x61,0x42,0x34,0x63,0x2F,0x0A,0x52,0x57, 0x77,0x7A,0x38,0x72,0x34,0x39,0x70,0x48,0x64,0x71,0x68,0x4F,0x6D,0x63,0x6C, 0x45,0x77,0x79,0x4D,0x34,0x51,0x79,0x6A,0x39,0x52,0x6D,0x57,0x62,0x51,0x58, 0x54,0x54,0x45,0x63,0x2B,0x35,0x67,0x54,0x4B,0x50,0x4E,0x53,0x33,0x6D,0x70, 0x4D,0x54,0x36,0x39,0x46,0x45,0x74,0x2F,0x35,0x72,0x4D,0x52,0x70,0x4B,0x2B, 0x52,0x68,0x0A,0x49,0x32,0x42,0x58,0x6B,0x51,0x71,0x31,0x36,0x6E,0x72,0x31, 0x61,0x45,0x4D,0x6D,0x64,0x51,0x42,0x51,0x79,0x4B,0x59,0x4A,0x6C,0x30,0x6C, 0x50,0x68,0x69,0x42,0x2F,0x75,0x6C,0x5A,0x63,0x72,0x67,0x4C,0x70,0x41,0x6F, 0x47,0x41,0x65,0x30,0x65,0x74,0x50,0x4A,0x77,0x6D,0x51,0x46,0x6B,0x6A,0x4D, 0x70,0x66,0x4D,0x44,0x61,0x4E,0x34,0x0A,0x70,0x7A,0x71,0x45,0x51,0x72,0x52, 0x35,0x4B,0x35,0x4D,0x6E,0x54,0x48,0x76,0x47,0x67,0x2F,0x70,0x6A,0x57,0x6A, 0x43,0x57,0x58,0x56,0x48,0x67,0x35,0x76,0x36,0x46,0x6F,0x5A,0x48,0x35,0x6E, 0x59,0x2B,0x56,0x2F,0x57,0x75,0x57,0x38,0x38,0x6A,0x6C,0x4B,0x53,0x50,0x6C, 0x77,0x6A,0x50,0x7A,0x41,0x67,0x7A,0x47,0x33,0x45,0x41,0x55,0x0A,0x71,0x57, 0x6B,0x42,0x67,0x30,0x71,0x75,0x50,0x4D,0x72,0x54,0x6B,0x73,0x69,0x6E,0x58, 0x50,0x2B,0x58,0x6B,0x51,0x65,0x46,0x66,0x58,0x61,0x33,0x38,0x6A,0x72,0x70, 0x62,0x4B,0x46,0x4F,0x72,0x7A,0x49,0x6F,0x6A,0x69,0x65,0x6C,0x4B,0x55,0x4D, 0x50,0x4D,0x78,0x2F,0x78,0x70,0x53,0x6A,0x63,0x55,0x42,0x68,0x62,0x4E,0x34, 0x45,0x54,0x0A,0x4F,0x30,0x66,0x63,0x57,0x47,0x6F,0x61,0x56,0x50,0x72,0x63, 0x6E,0x38,0x62,0x58,0x4D,0x54,0x45,0x4E,0x53,0x31,0x41,0x3D,0x0A,0x2D,0x2D, 0x2D,0x2D,0x2D,0x45,0x4E,0x44,0x20,0x50,0x52,0x49,0x56,0x41,0x54,0x45,0x20, 0x4B,0x45,0x59,0x2D,0x2D,0x2D,0x2D,0x2D,0x0A }; static const BYTE test_DummyMessage[64] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD }; static const BYTE test_LastDummyMessage[64] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static int schannel_send(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext, BYTE* buffer, UINT32 length) { BYTE* ioBuffer; UINT32 ioBufferLength; BYTE* pMessageBuffer; SecBuffer Buffers[4]; SecBufferDesc Message; SECURITY_STATUS status; DWORD NumberOfBytesWritten; SecPkgContext_StreamSizes StreamSizes; ZeroMemory(&StreamSizes, sizeof(SecPkgContext_StreamSizes)); status = table->QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &StreamSizes); ioBufferLength = StreamSizes.cbHeader + StreamSizes.cbMaximumMessage + StreamSizes.cbTrailer; ioBuffer = (BYTE*) calloc(1, ioBufferLength); if (!ioBuffer) return -1; pMessageBuffer = ioBuffer + StreamSizes.cbHeader; CopyMemory(pMessageBuffer, buffer, length); Buffers[0].pvBuffer = ioBuffer; Buffers[0].cbBuffer = StreamSizes.cbHeader; Buffers[0].BufferType = SECBUFFER_STREAM_HEADER; Buffers[1].pvBuffer = pMessageBuffer; Buffers[1].cbBuffer = length; Buffers[1].BufferType = SECBUFFER_DATA; Buffers[2].pvBuffer = pMessageBuffer + length; Buffers[2].cbBuffer = StreamSizes.cbTrailer; Buffers[2].BufferType = SECBUFFER_STREAM_TRAILER; Buffers[3].pvBuffer = NULL; Buffers[3].cbBuffer = 0; Buffers[3].BufferType = SECBUFFER_EMPTY; Message.ulVersion = SECBUFFER_VERSION; Message.cBuffers = 4; Message.pBuffers = Buffers; ioBufferLength = Message.pBuffers[0].cbBuffer + Message.pBuffers[1].cbBuffer + Message.pBuffers[2].cbBuffer; status = table->EncryptMessage(phContext, 0, &Message, 0); printf("EncryptMessage status: 0x%08"PRIX32"\n", status); printf("EncryptMessage output: cBuffers: %"PRIu32" [0]: %"PRIu32" / %"PRIu32" [1]: %"PRIu32" / %"PRIu32" [2]: %"PRIu32" / %"PRIu32" [3]: %"PRIu32" / %"PRIu32"\n", Message.cBuffers, Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType, Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType, Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType, Message.pBuffers[3].cbBuffer, Message.pBuffers[3].BufferType); if (status != SEC_E_OK) return -1; printf("Client > Server (%"PRIu32")\n", ioBufferLength); winpr_HexDump("sspi.test", WLOG_DEBUG, ioBuffer, ioBufferLength); if (!WriteFile(hPipe, ioBuffer, ioBufferLength, &NumberOfBytesWritten, NULL)) { printf("schannel_send: failed to write to pipe\n"); return -1; } return 0; } static int schannel_recv(PSecurityFunctionTable table, HANDLE hPipe, PCtxtHandle phContext) { BYTE* ioBuffer; UINT32 ioBufferLength; //BYTE* pMessageBuffer; SecBuffer Buffers[4]; SecBufferDesc Message; SECURITY_STATUS status; DWORD NumberOfBytesRead; SecPkgContext_StreamSizes StreamSizes; ZeroMemory(&StreamSizes, sizeof(SecPkgContext_StreamSizes)); status = table->QueryContextAttributes(phContext, SECPKG_ATTR_STREAM_SIZES, &StreamSizes); ioBufferLength = StreamSizes.cbHeader + StreamSizes.cbMaximumMessage + StreamSizes.cbTrailer; ioBuffer = (BYTE*) calloc(1, ioBufferLength); if (!ioBuffer) return -1; if (!ReadFile(hPipe, ioBuffer, ioBufferLength, &NumberOfBytesRead, NULL)) { printf("schannel_recv: failed to read from pipe\n"); return -1; } Buffers[0].pvBuffer = ioBuffer; Buffers[0].cbBuffer = NumberOfBytesRead; Buffers[0].BufferType = SECBUFFER_DATA; Buffers[1].pvBuffer = NULL; Buffers[1].cbBuffer = 0; Buffers[1].BufferType = SECBUFFER_EMPTY; Buffers[2].pvBuffer = NULL; Buffers[2].cbBuffer = 0; Buffers[2].BufferType = SECBUFFER_EMPTY; Buffers[3].pvBuffer = NULL; Buffers[3].cbBuffer = 0; Buffers[3].BufferType = SECBUFFER_EMPTY; Message.ulVersion = SECBUFFER_VERSION; Message.cBuffers = 4; Message.pBuffers = Buffers; status = table->DecryptMessage(phContext, &Message, 0, NULL); printf("DecryptMessage status: 0x%08"PRIX32"\n", status); printf("DecryptMessage output: cBuffers: %"PRIu32" [0]: %"PRIu32" / %"PRIu32" [1]: %"PRIu32" / %"PRIu32" [2]: %"PRIu32" / %"PRIu32" [3]: %"PRIu32" / %"PRIu32"\n", Message.cBuffers, Message.pBuffers[0].cbBuffer, Message.pBuffers[0].BufferType, Message.pBuffers[1].cbBuffer, Message.pBuffers[1].BufferType, Message.pBuffers[2].cbBuffer, Message.pBuffers[2].BufferType, Message.pBuffers[3].cbBuffer, Message.pBuffers[3].BufferType); if (status != SEC_E_OK) return -1; printf("Decrypted Message (%"PRIu32")\n", Message.pBuffers[1].cbBuffer); winpr_HexDump("sspi.test", WLOG_DEBUG, (BYTE*) Message.pBuffers[1].pvBuffer, Message.pBuffers[1].cbBuffer); if (memcmp(Message.pBuffers[1].pvBuffer, test_LastDummyMessage, sizeof(test_LastDummyMessage)) == 0) return -1; return 0; } static DWORD WINAPI schannel_test_server_thread(LPVOID arg) { BOOL extraData; BYTE* lpTokenIn; BYTE* lpTokenOut; TimeStamp expiry; UINT32 cbMaxToken; UINT32 fContextReq; ULONG fContextAttr; SCHANNEL_CRED cred; CtxtHandle context; CredHandle credentials; DWORD cchNameString; LPTSTR pszNameString; HCERTSTORE hCertStore; PCCERT_CONTEXT pCertContext; PSecBuffer pSecBuffer; SecBuffer SecBuffer_in[2]; SecBuffer SecBuffer_out[2]; SecBufferDesc SecBufferDesc_in; SecBufferDesc SecBufferDesc_out; DWORD NumberOfBytesRead; SECURITY_STATUS status; PSecPkgInfo pPackageInfo; PSecurityFunctionTable table; DWORD NumberOfBytesWritten; printf("Starting Server\n"); SecInvalidateHandle(&context); SecInvalidateHandle(&credentials); table = InitSecurityInterface(); status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo); if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo failure: 0x%08"PRIX32"\n", status); return 0; } cbMaxToken = pPackageInfo->cbMaxToken; hCertStore = CertOpenSystemStore(0, _T("MY")); if (!hCertStore) { printf("Error opening system store\n"); //return NULL; } #ifdef CERT_FIND_HAS_PRIVATE_KEY pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_HAS_PRIVATE_KEY, NULL, NULL); #else pCertContext = CertFindCertificateInStore(hCertStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, NULL); #endif if (!pCertContext) { printf("Error finding certificate in store\n"); //return NULL; } cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, NULL, 0); pszNameString = (LPTSTR) malloc(cchNameString * sizeof(TCHAR)); if (!pszNameString) { printf("Memory allocation failed\n"); return 0; } cchNameString = CertGetNameString(pCertContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, NULL, pszNameString, cchNameString); _tprintf(_T("Certificate Name: %s\n"), pszNameString); ZeroMemory(&cred, sizeof(SCHANNEL_CRED)); cred.dwVersion = SCHANNEL_CRED_VERSION; cred.cCreds = 1; cred.paCred = &pCertContext; cred.cSupportedAlgs = 0; cred.palgSupportedAlgs = NULL; cred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER; cred.dwFlags = SCH_CRED_NO_SYSTEM_MAPPER; status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME, SECPKG_CRED_INBOUND, NULL, &cred, NULL, NULL, &credentials, NULL); if (status != SEC_E_OK) { printf("AcquireCredentialsHandle failure: 0x%08"PRIX32"\n", status); return 0; } extraData = FALSE; g_ServerWait = TRUE; if (!(lpTokenIn = (BYTE*) malloc(cbMaxToken))) { printf("Memory allocation failed\n"); return 0; } if (!(lpTokenOut = (BYTE*) malloc(cbMaxToken))) { printf("Memory allocation failed\n"); free(lpTokenIn); return 0; } fContextReq = ASC_REQ_STREAM | ASC_REQ_SEQUENCE_DETECT | ASC_REQ_REPLAY_DETECT | ASC_REQ_CONFIDENTIALITY | ASC_REQ_EXTENDED_ERROR; do { if (!extraData) { if (g_ServerWait) { if (!ReadFile(g_ServerReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL)) { printf("Failed to read from server pipe\n"); return NULL; } } else { NumberOfBytesRead = 0; } } extraData = FALSE; g_ServerWait = TRUE; SecBuffer_in[0].BufferType = SECBUFFER_TOKEN; SecBuffer_in[0].pvBuffer = lpTokenIn; SecBuffer_in[0].cbBuffer = NumberOfBytesRead; SecBuffer_in[1].BufferType = SECBUFFER_EMPTY; SecBuffer_in[1].pvBuffer = NULL; SecBuffer_in[1].cbBuffer = 0; SecBufferDesc_in.ulVersion = SECBUFFER_VERSION; SecBufferDesc_in.cBuffers = 2; SecBufferDesc_in.pBuffers = SecBuffer_in; SecBuffer_out[0].BufferType = SECBUFFER_TOKEN; SecBuffer_out[0].pvBuffer = lpTokenOut; SecBuffer_out[0].cbBuffer = cbMaxToken; SecBufferDesc_out.ulVersion = SECBUFFER_VERSION; SecBufferDesc_out.cBuffers = 1; SecBufferDesc_out.pBuffers = SecBuffer_out; status = table->AcceptSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, &SecBufferDesc_in, fContextReq, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry); if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE)) { printf("AcceptSecurityContext unexpected status: 0x%08"PRIX32"\n", status); return NULL; } NumberOfBytesWritten = 0; if (status == SEC_E_OK) printf("AcceptSecurityContext status: SEC_E_OK\n"); else if (status == SEC_I_CONTINUE_NEEDED) printf("AcceptSecurityContext status: SEC_I_CONTINUE_NEEDED\n"); else if (status == SEC_E_INCOMPLETE_MESSAGE) printf("AcceptSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n"); printf("Server cBuffers: %"PRIu32" pBuffers[0]: %"PRIu32" type: %"PRIu32"\n", SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType); printf("Server Input cBuffers: %"PRIu32" pBuffers[0]: %"PRIu32" type: %"PRIu32" pBuffers[1]: %"PRIu32" type: %"PRIu32"\n", SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[0].cbBuffer, SecBufferDesc_in.pBuffers[0].BufferType, SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType); if (SecBufferDesc_in.pBuffers[1].BufferType == SECBUFFER_EXTRA) { printf("AcceptSecurityContext SECBUFFER_EXTRA\n"); pSecBuffer = &SecBufferDesc_in.pBuffers[1]; CopyMemory(lpTokenIn, &lpTokenIn[NumberOfBytesRead - pSecBuffer->cbBuffer], pSecBuffer->cbBuffer); NumberOfBytesRead = pSecBuffer->cbBuffer; continue; } if (status != SEC_E_INCOMPLETE_MESSAGE) { pSecBuffer = &SecBufferDesc_out.pBuffers[0]; if (pSecBuffer->cbBuffer > 0) { printf("Server > Client (%"PRIu32")\n", pSecBuffer->cbBuffer); winpr_HexDump("sspi.test", WLOG_DEBUG, (BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer); if (!WriteFile(g_ClientWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL)) { printf("failed to write to client pipe\n"); return NULL; } } } if (status == SEC_E_OK) { printf("Server Handshake Complete\n"); break; } } while (1); do { if (schannel_recv(table, g_ServerReadPipe, &context) < 0) break; } while (1); return 0; } static int dump_test_certificate_files(void) { FILE* fp; char* fullpath = NULL; int ret = -1; /* * Output Certificate File */ fullpath = GetCombinedPath("/tmp", "localhost.crt"); if (!fullpath) return -1; fp = fopen(fullpath, "w+"); if (fp) { if (fwrite((void*) test_localhost_crt, sizeof(test_localhost_crt), 1, fp) != 1) goto out_fail; fclose(fp); fp = NULL; } free(fullpath); /* * Output Private Key File */ fullpath = GetCombinedPath("/tmp", "localhost.key"); if (!fullpath) return -1; fp = fopen(fullpath, "w+"); if (fp && fwrite((void*) test_localhost_key, sizeof(test_localhost_key), 1, fp) != 1) goto out_fail; ret = 1; out_fail: free(fullpath); if (fp) fclose(fp); return ret; } int TestSchannel(int argc, char* argv[]) { int count; DWORD index; ALG_ID algId; HANDLE thread; BYTE* lpTokenIn; BYTE* lpTokenOut; TimeStamp expiry; UINT32 cbMaxToken; SCHANNEL_CRED cred; UINT32 fContextReq; ULONG fContextAttr; CtxtHandle context; CredHandle credentials; SECURITY_STATUS status; PSecPkgInfo pPackageInfo; PSecBuffer pSecBuffer; SecBuffer SecBuffer_in[2]; SecBuffer SecBuffer_out[1]; SecBufferDesc SecBufferDesc_in; SecBufferDesc SecBufferDesc_out; PSecurityFunctionTable table; DWORD NumberOfBytesRead; DWORD NumberOfBytesWritten; SecPkgCred_SupportedAlgs SupportedAlgs; SecPkgCred_CipherStrengths CipherStrengths; SecPkgCred_SupportedProtocols SupportedProtocols; return 0; /* disable by default - causes crash */ sspi_GlobalInit(); dump_test_certificate_files(); SecInvalidateHandle(&context); SecInvalidateHandle(&credentials); if (!CreatePipe(&g_ClientReadPipe, &g_ClientWritePipe, NULL, 0)) { printf("Failed to create client pipe\n"); return -1; } if (!CreatePipe(&g_ServerReadPipe, &g_ServerWritePipe, NULL, 0)) { printf("Failed to create server pipe\n"); return -1; } if (!(thread = CreateThread(NULL, 0, schannel_test_server_thread, NULL, 0, NULL))) { printf("Failed to create server thread\n"); return -1; } table = InitSecurityInterface(); status = QuerySecurityPackageInfo(SCHANNEL_NAME, &pPackageInfo); if (status != SEC_E_OK) { printf("QuerySecurityPackageInfo failure: 0x%08"PRIX32"\n", status); return -1; } cbMaxToken = pPackageInfo->cbMaxToken; ZeroMemory(&cred, sizeof(SCHANNEL_CRED)); cred.dwVersion = SCHANNEL_CRED_VERSION; cred.cCreds = 0; cred.paCred = NULL; cred.cSupportedAlgs = 0; cred.palgSupportedAlgs = NULL; cred.grbitEnabledProtocols = SP_PROT_SSL3TLS1_CLIENTS; cred.dwFlags = SCH_CRED_NO_DEFAULT_CREDS; cred.dwFlags |= SCH_CRED_MANUAL_CRED_VALIDATION; cred.dwFlags |= SCH_CRED_NO_SERVERNAME_CHECK; status = table->AcquireCredentialsHandle(NULL, SCHANNEL_NAME, SECPKG_CRED_OUTBOUND, NULL, &cred, NULL, NULL, &credentials, NULL); if (status != SEC_E_OK) { printf("AcquireCredentialsHandle failure: 0x%08"PRIX32"\n", status); return -1; } ZeroMemory(&SupportedAlgs, sizeof(SecPkgCred_SupportedAlgs)); status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_ALGS, &SupportedAlgs); if (status != SEC_E_OK) { printf("QueryCredentialsAttributes SECPKG_ATTR_SUPPORTED_ALGS failure: 0x%08"PRIX32"\n", status); return -1; } /** * SupportedAlgs: 15 * 0x660E 0x6610 0x6801 0x6603 0x6601 0x8003 0x8004 * 0x800C 0x800D 0x800E 0x2400 0xAA02 0xAE06 0x2200 0x2203 */ printf("SupportedAlgs: %"PRIu32"\n", SupportedAlgs.cSupportedAlgs); for (index = 0; index < SupportedAlgs.cSupportedAlgs; index++) { algId = SupportedAlgs.palgSupportedAlgs[index]; printf("\t0x%08"PRIX32" CLASS: %"PRIu32" TYPE: %"PRIu32" SID: %"PRIu32"\n", algId, ((GET_ALG_CLASS(algId)) >> 13), ((GET_ALG_TYPE(algId)) >> 9), GET_ALG_SID(algId)); } printf("\n"); ZeroMemory(&CipherStrengths, sizeof(SecPkgCred_CipherStrengths)); status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_CIPHER_STRENGTHS, &CipherStrengths); if (status != SEC_E_OK) { printf("QueryCredentialsAttributes SECPKG_ATTR_CIPHER_STRENGTHS failure: 0x%08"PRIX32"\n", status); return -1; } /* CipherStrengths: Minimum: 40 Maximum: 256 */ printf("CipherStrengths: Minimum: %"PRIu32" Maximum: %"PRIu32"\n", CipherStrengths.dwMinimumCipherStrength, CipherStrengths.dwMaximumCipherStrength); ZeroMemory(&SupportedProtocols, sizeof(SecPkgCred_SupportedProtocols)); status = table->QueryCredentialsAttributes(&credentials, SECPKG_ATTR_SUPPORTED_PROTOCOLS, &SupportedProtocols); if (status != SEC_E_OK) { printf("QueryCredentialsAttributes SECPKG_ATTR_SUPPORTED_PROTOCOLS failure: 0x%08"PRIX32"\n", status); return -1; } /* SupportedProtocols: 0x208A0 */ printf("SupportedProtocols: 0x%08"PRIX32"\n", SupportedProtocols.grbitProtocol); fContextReq = ISC_REQ_STREAM | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT | ISC_REQ_CONFIDENTIALITY | ISC_RET_EXTENDED_ERROR | ISC_REQ_MANUAL_CRED_VALIDATION | ISC_REQ_INTEGRITY; if (!(lpTokenIn = (BYTE*) malloc(cbMaxToken))) { printf("Memory allocation failed\n"); return -1; } if (!(lpTokenOut = (BYTE*) malloc(cbMaxToken))) { printf("Memory allocation failed\n"); return -1; } ZeroMemory(&SecBuffer_in, sizeof(SecBuffer_in)); ZeroMemory(&SecBuffer_out, sizeof(SecBuffer_out)); ZeroMemory(&SecBufferDesc_in, sizeof(SecBufferDesc)); ZeroMemory(&SecBufferDesc_out, sizeof(SecBufferDesc)); g_ClientWait = FALSE; do { if (g_ClientWait) { if (!ReadFile(g_ClientReadPipe, lpTokenIn, cbMaxToken, &NumberOfBytesRead, NULL)) { printf("failed to read from server pipe\n"); return -1; } } else { NumberOfBytesRead = 0; } g_ClientWait = TRUE; printf("NumberOfBytesRead: %"PRIu32"\n", NumberOfBytesRead); SecBuffer_in[0].BufferType = SECBUFFER_TOKEN; SecBuffer_in[0].pvBuffer = lpTokenIn; SecBuffer_in[0].cbBuffer = NumberOfBytesRead; SecBuffer_in[1].pvBuffer = NULL; SecBuffer_in[1].cbBuffer = 0; SecBuffer_in[1].BufferType = SECBUFFER_EMPTY; SecBufferDesc_in.ulVersion = SECBUFFER_VERSION; SecBufferDesc_in.cBuffers = 2; SecBufferDesc_in.pBuffers = SecBuffer_in; SecBuffer_out[0].BufferType = SECBUFFER_TOKEN; SecBuffer_out[0].pvBuffer = lpTokenOut; SecBuffer_out[0].cbBuffer = cbMaxToken; SecBufferDesc_out.ulVersion = SECBUFFER_VERSION; SecBufferDesc_out.cBuffers = 1; SecBufferDesc_out.pBuffers = SecBuffer_out; status = table->InitializeSecurityContext(&credentials, SecIsValidHandle(&context) ? &context : NULL, _T("localhost"), fContextReq, 0, 0, &SecBufferDesc_in, 0, &context, &SecBufferDesc_out, &fContextAttr, &expiry); if ((status != SEC_E_OK) && (status != SEC_I_CONTINUE_NEEDED) && (status != SEC_E_INCOMPLETE_MESSAGE)) { printf("InitializeSecurityContext unexpected status: 0x%08"PRIX32"\n", status); return -1; } NumberOfBytesWritten = 0; if (status == SEC_E_OK) printf("InitializeSecurityContext status: SEC_E_OK\n"); else if (status == SEC_I_CONTINUE_NEEDED) printf("InitializeSecurityContext status: SEC_I_CONTINUE_NEEDED\n"); else if (status == SEC_E_INCOMPLETE_MESSAGE) printf("InitializeSecurityContext status: SEC_E_INCOMPLETE_MESSAGE\n"); printf("Client Output cBuffers: %"PRIu32" pBuffers[0]: %"PRIu32" type: %"PRIu32"\n", SecBufferDesc_out.cBuffers, SecBufferDesc_out.pBuffers[0].cbBuffer, SecBufferDesc_out.pBuffers[0].BufferType); printf("Client Input cBuffers: %"PRIu32" pBuffers[0]: %"PRIu32" type: %"PRIu32" pBuffers[1]: %"PRIu32" type: %"PRIu32"\n", SecBufferDesc_in.cBuffers, SecBufferDesc_in.pBuffers[0].cbBuffer, SecBufferDesc_in.pBuffers[0].BufferType, SecBufferDesc_in.pBuffers[1].cbBuffer, SecBufferDesc_in.pBuffers[1].BufferType); if (status != SEC_E_INCOMPLETE_MESSAGE) { pSecBuffer = &SecBufferDesc_out.pBuffers[0]; if (pSecBuffer->cbBuffer > 0) { printf("Client > Server (%"PRIu32")\n", pSecBuffer->cbBuffer); winpr_HexDump("sspi.test", WLOG_DEBUG, (BYTE*) pSecBuffer->pvBuffer, pSecBuffer->cbBuffer); if (!WriteFile(g_ServerWritePipe, pSecBuffer->pvBuffer, pSecBuffer->cbBuffer, &NumberOfBytesWritten, NULL)) { printf("failed to write to server pipe\n"); return -1; } } } if (status == SEC_E_OK) { printf("Client Handshake Complete\n"); break; } } while (1); count = 0; do { if (schannel_send(table, g_ServerWritePipe, &context, test_DummyMessage, sizeof(test_DummyMessage)) < 0) break; for (index = 0; index < sizeof(test_DummyMessage); index++) { BYTE b, ln, hn; b = test_DummyMessage[index]; ln = (b & 0x0F); hn = ((b & 0xF0) >> 4); ln = (ln + 1) % 0xF; hn = (ln + 1) % 0xF; b = (ln | (hn << 4)); test_DummyMessage[index] = b; } Sleep(100); count++; } while (count < 3); schannel_send(table, g_ServerWritePipe, &context, test_LastDummyMessage, sizeof(test_LastDummyMessage)); WaitForSingleObject(thread, INFINITE); sspi_GlobalFinish(); return 0; }