865 lines
38 KiB
C
865 lines
38 KiB
C
|
|
#include <winpr/crt.h>
|
|
#include <winpr/sspi.h>
|
|
#include <winpr/file.h>
|
|
#include <winpr/pipe.h>
|
|
#include <winpr/path.h>
|
|
#include <winpr/tchar.h>
|
|
#include <winpr/print.h>
|
|
#include <winpr/synch.h>
|
|
#include <winpr/thread.h>
|
|
#include <winpr/crypto.h>
|
|
#include <winpr/wlog.h>
|
|
#include <winpr/schannel.h>
|
|
|
|
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;
|
|
}
|