diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e5d96325..aae3e6268 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,6 +79,7 @@ if(MSVC) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /O2 /Ob2") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_X86_") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_UNICODE") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWINPR_EXPORTS") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DFREERDP_EXPORTS") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWIN32_LEAN_AND_MEAN") @@ -155,11 +156,13 @@ add_subdirectory(libfreerdp-rail) add_subdirectory(libfreerdp-cache) add_subdirectory(libfreerdp-codec) add_subdirectory(libfreerdp-crypto) -add_subdirectory(libfreerdp-sspi) add_subdirectory(libfreerdp-channels) add_subdirectory(libfreerdp-locale) add_subdirectory(libfreerdp-core) +add_subdirectory(libwinpr-rpc) +add_subdirectory(libwinpr-sspi) + if(NOT WIN32) add_subdirectory(channels) endif() diff --git a/client/Windows/wfreerdp.c b/client/Windows/wfreerdp.c index 7c1d79144..4b1b97118 100644 --- a/client/Windows/wfreerdp.c +++ b/client/Windows/wfreerdp.c @@ -19,7 +19,7 @@ * limitations under the License. */ -#include +#include #include #include diff --git a/client/Windows/wfreerdp.h b/client/Windows/wfreerdp.h index 099bd6cdc..062618019 100644 --- a/client/Windows/wfreerdp.h +++ b/client/Windows/wfreerdp.h @@ -22,7 +22,7 @@ #ifndef __WFREERDP_H #define __WFREERDP_H -#include +#include #include #include diff --git a/cmake/ConfigOptions.cmake b/cmake/ConfigOptions.cmake index 11c65b3f7..0e1951674 100644 --- a/cmake/ConfigOptions.cmake +++ b/cmake/ConfigOptions.cmake @@ -14,6 +14,7 @@ option(WITH_DEBUG_LICENSE "Print license debug messages." OFF) option(WITH_DEBUG_NEGO "Print negotiation related debug messages." OFF) option(WITH_DEBUG_NLA "Print authentication related debug messages." OFF) option(WITH_DEBUG_NTLM "Print NTLM debug messages" OFF) +option(WITH_DEBUG_TSG "Print Terminal Server Gateway debug messages" OFF) option(WITH_DEBUG_ORDERS "Print drawing orders debug messages" OFF) option(WITH_DEBUG_RAIL "Print RemoteApp debug messages" OFF) option(WITH_DEBUG_RDP "Print RDP debug messages" OFF) diff --git a/config.h.in b/config.h.in index d250bedda..9b1f92599 100644 --- a/config.h.in +++ b/config.h.in @@ -37,6 +37,7 @@ #cmakedefine WITH_DEBUG_NEGO #cmakedefine WITH_DEBUG_NLA #cmakedefine WITH_DEBUG_NTLM +#cmakedefine WITH_DEBUG_TSG #cmakedefine WITH_DEBUG_ORDERS #cmakedefine WITH_DEBUG_RAIL #cmakedefine WITH_DEBUG_RDP diff --git a/include/freerdp/crypto/crypto.h b/include/freerdp/crypto/crypto.h index dafbeaa1f..e3baa6079 100644 --- a/include/freerdp/crypto/crypto.h +++ b/include/freerdp/crypto/crypto.h @@ -21,7 +21,7 @@ #define FREERDP_CRYPTO_H /* OpenSSL includes windows.h */ -#include +#include #include #include @@ -142,4 +142,7 @@ FREERDP_API void crypto_rsa_private_decrypt(const uint8* input, int length, uint FREERDP_API void crypto_reverse(uint8* data, int length); FREERDP_API void crypto_nonce(uint8* nonce, int size); +FREERDP_API char* crypto_base64_encode(uint8* data, int length); +FREERDP_API void crypto_base64_decode(uint8* enc_data, int length, uint8** dec_data, int* res_length); + #endif /* FREERDP_CRYPTO_H */ diff --git a/include/freerdp/crypto/tls.h b/include/freerdp/crypto/tls.h index 0b2931e1f..fa9f155d7 100644 --- a/include/freerdp/crypto/tls.h +++ b/include/freerdp/crypto/tls.h @@ -49,6 +49,8 @@ FREERDP_API boolean tls_disconnect(rdpTls* tls); FREERDP_API int tls_read(rdpTls* tls, uint8* data, int length); FREERDP_API int tls_write(rdpTls* tls, uint8* data, int length); +FREERDP_API int tls_write_all(rdpTls* tls, uint8* data, int length); + FREERDP_API boolean tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname); FREERDP_API void tls_print_certificate_error(char* hostname, char* fingerprint); FREERDP_API void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name, char** alt_names, int alt_names_count); diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 5ff5a0d4e..2426d3a4c 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -288,7 +288,11 @@ struct rdp_settings ALIGN64 rdpBlob* password_cookie; /* 61 */ ALIGN64 char* kerberos_kdc; /* 62 */ ALIGN64 char* kerberos_realm; /* 63 */ - ALIGN64 uint64 paddingC[80 - 64]; /* 64 */ + ALIGN64 boolean ts_gateway; /* 64 */ + ALIGN64 char* tsg_hostname; /* 65 */ + ALIGN64 char* tsg_username; /* 66 */ + ALIGN64 char* tsg_password; /* 67 */ + ALIGN64 uint64 paddingC[80 - 68]; /* 68 */ /* User Interface Parameters */ ALIGN64 boolean sw_gdi; /* 80 */ diff --git a/include/freerdp/types.h b/include/freerdp/types.h index 0934fa7f0..bce09650f 100644 --- a/include/freerdp/types.h +++ b/include/freerdp/types.h @@ -119,6 +119,16 @@ typedef int boolean; #include +typedef struct +{ + uint32 time_low; + uint16 time_mid; + uint16 time_hi_and_version; + uint8 clock_seq_hi_and_reserved; + uint8 clock_seq_low; + uint8 node[6]; +} uuid; + struct _RDP_PLUGIN_DATA { uint16 size; diff --git a/include/freerdp/utils/unicode.h b/include/freerdp/utils/unicode.h index 7268a8ecb..0dabc9309 100644 --- a/include/freerdp/utils/unicode.h +++ b/include/freerdp/utils/unicode.h @@ -48,7 +48,7 @@ typedef struct _UNICONV UNICONV; FREERDP_API UNICONV* freerdp_uniconv_new(); FREERDP_API void freerdp_uniconv_free(UNICONV *uniconv); FREERDP_API char* freerdp_uniconv_in(UNICONV *uniconv, unsigned char* pin, size_t in_len); -FREERDP_API char* freerdp_uniconv_out(UNICONV *uniconv, char *str, size_t *pout_len); +FREERDP_API char* freerdp_uniconv_out(UNICONV *uniconv, const char *str, size_t *pout_len); FREERDP_API void freerdp_uniconv_uppercase(UNICONV *uniconv, char *wstr, int length); #endif /* __UNICODE_UTILS_H */ diff --git a/include/freerdp/sspi/credssp.h b/include/winpr/credssp.h similarity index 98% rename from include/freerdp/sspi/credssp.h rename to include/winpr/credssp.h index ffc470ed9..2e690ccd0 100644 --- a/include/freerdp/sspi/credssp.h +++ b/include/winpr/credssp.h @@ -28,7 +28,7 @@ typedef struct rdp_credssp rdpCredssp; #include #include -#include +#include #include #include diff --git a/include/winpr/midl.h b/include/winpr/midl.h new file mode 100644 index 000000000..75a87eb38 --- /dev/null +++ b/include/winpr/midl.h @@ -0,0 +1,28 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_RPC_MIDL_H +#define WINPR_RPC_MIDL_H + +#include + +WINPR_API void* MIDL_user_allocate(size_t cBytes); +WINPR_API void MIDL_user_free(void* p); + +#endif /* WINPR_RPC_MIDL_H */ diff --git a/include/winpr/ndr.h b/include/winpr/ndr.h new file mode 100644 index 000000000..85a357645 --- /dev/null +++ b/include/winpr/ndr.h @@ -0,0 +1,530 @@ +/** + * WinPR: Windows Portable Runtime + * Network Data Representation (NDR) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_RPC_NDR_H +#define WINPR_RPC_NDR_H + +#include +#include + +#define __RPC_WIN32__ 1 +#define TARGET_IS_NT50_OR_LATER 1 + +typedef union _CLIENT_CALL_RETURN +{ + void* Pointer; + LONG_PTR Simple; +} CLIENT_CALL_RETURN; + +typedef void* RPC_IF_HANDLE; + +typedef struct _RPC_VERSION +{ + unsigned short MajorVersion; + unsigned short MinorVersion; +} RPC_VERSION; + +typedef struct _RPC_SYNTAX_IDENTIFIER +{ + GUID SyntaxGUID; + RPC_VERSION SyntaxVersion; +} RPC_SYNTAX_IDENTIFIER, PRPC_SYNTAX_IDENTIFIER; + +#define RPC_MGR_EPV void + +typedef struct _RPC_MESSAGE +{ + RPC_BINDING_HANDLE Handle; + unsigned long DataRepresentation; + void* Buffer; + unsigned int BufferLength; + unsigned int ProcNum; + PRPC_SYNTAX_IDENTIFIER TransferSyntax; + void* RpcInterfaceInformation; + void* ReservedForRuntime; + RPC_MGR_EPV* ManagerEpv; + void* ImportContext; + unsigned long RpcFlags; +} RPC_MESSAGE, *PRPC_MESSAGE; + +typedef void (*RPC_DISPATCH_FUNCTION)(PRPC_MESSAGE Message); + +typedef struct +{ + unsigned int DispatchTableCount; + RPC_DISPATCH_FUNCTION* DispatchTable; + LONG_PTR Reserved; +} RPC_DISPATCH_TABLE, *PRPC_DISPATCH_TABLE; + +typedef struct _RPC_PROTSEQ_ENDPOINT +{ + unsigned char* RpcProtocolSequence; + unsigned char* Endpoint; +} RPC_PROTSEQ_ENDPOINT, * PRPC_PROTSEQ_ENDPOINT; + +typedef struct _RPC_SERVER_INTERFACE +{ + unsigned int Length; + RPC_SYNTAX_IDENTIFIER InterfaceId; + RPC_SYNTAX_IDENTIFIER TransferSyntax; + PRPC_DISPATCH_TABLE DispatchTable; + unsigned int RpcProtseqEndpointCount; + PRPC_PROTSEQ_ENDPOINT RpcProtseqEndpoint; + RPC_MGR_EPV* DefaultManagerEpv; + void const* InterpreterInfo; + unsigned int Flags; +} RPC_SERVER_INTERFACE, *PRPC_SERVER_INTERFACE; + +typedef struct _RPC_CLIENT_INTERFACE +{ + unsigned int Length; + RPC_SYNTAX_IDENTIFIER InterfaceId; + RPC_SYNTAX_IDENTIFIER TransferSyntax; + PRPC_DISPATCH_TABLE DispatchTable; + unsigned int RpcProtseqEndpointCount; + PRPC_PROTSEQ_ENDPOINT RpcProtseqEndpoint; + ULONG_PTR Reserved; + void const* InterpreterInfo; + unsigned int Flags; +} RPC_CLIENT_INTERFACE, *PRPC_CLIENT_INTERFACE; + +typedef void* (*GENERIC_BINDING_ROUTINE)(void*); +typedef void (*GENERIC_UNBIND_ROUTINE)(void*, unsigned char*); + +typedef struct _GENERIC_BINDING_ROUTINE_PAIR +{ + GENERIC_BINDING_ROUTINE pfnBind; + GENERIC_UNBIND_ROUTINE pfnUnbind; +} GENERIC_BINDING_ROUTINE_PAIR, *PGENERIC_BINDING_ROUTINE_PAIR; + +typedef struct __GENERIC_BINDING_INFO +{ + void* pObj; + unsigned int Size; + GENERIC_BINDING_ROUTINE pfnBind; + GENERIC_UNBIND_ROUTINE pfnUnbind; +} GENERIC_BINDING_INFO, *PGENERIC_BINDING_INFO; + +typedef void (*NDR_RUNDOWN)(void* context); +typedef void (*NDR_NOTIFY_ROUTINE)(void); + +typedef const unsigned char* PFORMAT_STRING; + +typedef struct _MIDL_STUB_DESC MIDL_STUB_DESC; +typedef MIDL_STUB_DESC* PMIDL_STUB_DESC; + +typedef struct _MIDL_STUB_MESSAGE +{ + PRPC_MESSAGE RpcMsg; + unsigned char* Buffer; + unsigned char* BufferStart; + unsigned char* BufferEnd; + unsigned char* BufferMark; + unsigned long BufferLength; + unsigned long MemorySize; + unsigned char* Memory; + int IsClient; + int ReuseBuffer; + struct NDR_ALLOC_ALL_NODES_CONTEXT* pAllocAllNodesContext; + struct NDR_POINTER_QUEUE_STATE* pPointerQueueState; + int IgnoreEmbeddedPointers; + unsigned char* PointerBufferMark; + unsigned char fBufferValid; + unsigned char uFlags; + unsigned short Unused2; + ULONG_PTR MaxCount; + unsigned long Offset; + unsigned long ActualCount; + void *(*pfnAllocate)(size_t); + void (*pfnFree)(void*); + unsigned char* StackTop; + unsigned char* pPresentedType; + unsigned char* pTransmitType; + handle_t SavedHandle; + const struct _MIDL_STUB_DESC* StubDesc; + struct _FULL_PTR_XLAT_TABLES* FullPtrXlatTables; + unsigned long FullPtrRefId; + unsigned long PointerLength; + int fInDontFree : 1; + int fDontCallFreeInst : 1; + int fInOnlyParam : 1; + int fHasReturn : 1; + int fHasExtensions : 1; + int fHasNewCorrDesc : 1; + int fUnused : 10; + int fUnused2 : 16; + unsigned long dwDestContext; + void* pvDestContext; + //NDR_SCONTEXT* SavedContextHandles; + long ParamNumber; + struct IRpcChannelBuffer* pRpcChannelBuffer; + //PARRAY_INFO pArrayInfo; + unsigned long* SizePtrCountArray; + unsigned long* SizePtrOffsetArray; + unsigned long* SizePtrLengthArray; + void* pArgQueue; + unsigned long dwStubPhase; + void* LowStackMark; + //PNDR_ASYNC_MESSAGE pAsyncMsg; + //PNDR_CORRELATION_INFO pCorrInfo; + unsigned char* pCorrMemory; + void* pMemoryList; + //CS_STUB_INFO* pCSInfo; + unsigned char* ConformanceMark; + unsigned char* VarianceMark; + void* BackingStoreLowMark; + INT_PTR Unused; + struct _NDR_PROC_CONTEXT* pContext; + INT_PTR Reserved51_1; + INT_PTR Reserved51_2; + INT_PTR Reserved51_3; + INT_PTR Reserved51_4; + INT_PTR Reserved51_5; +} MIDL_STUB_MESSAGE, *PMIDL_STUB_MESSAGE; + +typedef struct _MIDL_STUB_MESSAGE MIDL_STUB_MESSAGE, *PMIDL_STUB_MESSAGE; + +typedef void (*EXPR_EVAL)(struct _MIDL_STUB_MESSAGE*); + +typedef void (*XMIT_HELPER_ROUTINE)(PMIDL_STUB_MESSAGE); + +typedef struct _XMIT_ROUTINE_QUINTUPLE +{ + XMIT_HELPER_ROUTINE pfnTranslateToXmit; + XMIT_HELPER_ROUTINE pfnTranslateFromXmit; + XMIT_HELPER_ROUTINE pfnFreeXmit; + XMIT_HELPER_ROUTINE pfnFreeInst; +} XMIT_ROUTINE_QUINTUPLE, *PXMIT_ROUTINE_QUINTUPLE; + +typedef unsigned long (*USER_MARSHAL_SIZING_ROUTINE)(unsigned long*, unsigned long, void*); +typedef unsigned char* (*USER_MARSHAL_MARSHALLING_ROUTINE)(unsigned long*, unsigned char*, void*); +typedef unsigned char* (*USER_MARSHAL_UNMARSHALLING_ROUTINE)(unsigned long*, unsigned char*, void*); +typedef void (*USER_MARSHAL_FREEING_ROUTINE)(unsigned long*, void*); + +typedef struct _USER_MARSHAL_ROUTINE_QUADRUPLE +{ + USER_MARSHAL_SIZING_ROUTINE pfnBufferSize; + USER_MARSHAL_MARSHALLING_ROUTINE pfnMarshall; + USER_MARSHAL_UNMARSHALLING_ROUTINE pfnUnmarshall; + USER_MARSHAL_FREEING_ROUTINE pfnFree; +} USER_MARSHAL_ROUTINE_QUADRUPLE; + +typedef struct _MALLOC_FREE_STRUCT +{ + void* (*pfnAllocate)(size_t); + void (*pfnFree)(void*); +} MALLOC_FREE_STRUCT; + +typedef struct _COMM_FAULT_OFFSETS +{ + short CommOffset; + short FaultOffset; +} COMM_FAULT_OFFSETS; + +typedef void* NDR_CS_ROUTINES; +typedef void* NDR_EXPR_DESC; + +struct _MIDL_STUB_DESC +{ + void* RpcInterfaceInformation; + void* (*pfnAllocate)(size_t); + void (*pfnFree)(void*); + + union + { + handle_t* pAutoHandle; + handle_t* pPrimitiveHandle; + PGENERIC_BINDING_INFO pGenericBindingInfo; + } IMPLICIT_HANDLE_INFO; + + const NDR_RUNDOWN* apfnNdrRundownRoutines; + const GENERIC_BINDING_ROUTINE_PAIR* aGenericBindingRoutinePairs; + const EXPR_EVAL* apfnExprEval; + const XMIT_ROUTINE_QUINTUPLE* aXmitQuintuple; + const unsigned char* pFormatTypes; + + int fCheckBounds; + unsigned long Version; + MALLOC_FREE_STRUCT* pMallocFreeStruct; + + long MIDLVersion; + const COMM_FAULT_OFFSETS* CommFaultOffsets; + const USER_MARSHAL_ROUTINE_QUADRUPLE* aUserMarshalQuadruple; + + const NDR_NOTIFY_ROUTINE* NotifyRoutineTable; + ULONG_PTR mFlags; + const NDR_CS_ROUTINES* CsRoutineTables; + void* ProxyServerInfo; + const NDR_EXPR_DESC* pExprInfo; +}; + +typedef struct +{ + unsigned char FullPtrUsed : 1; + unsigned char RpcSsAllocUsed : 1; + unsigned char ObjectProc : 1; + unsigned char HasRpcFlags : 1; + unsigned char IgnoreObjectException : 1; + unsigned char HasCommOrFault : 1; + unsigned char UseNewInitRoutines : 1; + unsigned char Unused : 1; +} INTERPRETER_FLAGS, *PINTERPRETER_FLAGS; + +typedef struct +{ + unsigned short MustSize : 1; + unsigned short MustFree : 1; + unsigned short IsPipe : 1; + unsigned short IsIn : 1; + unsigned short IsOut : 1; + unsigned short IsReturn : 1; + unsigned short IsBasetype : 1; + unsigned short IsByValue : 1; + unsigned short IsSimpleRef : 1; + unsigned short IsDontCallFreeInst : 1; + unsigned short SaveForAsyncFinish : 1; + unsigned short Unused : 2; + unsigned short ServerAllocSize : 3; +} PARAM_ATTRIBUTES, *PPARAM_ATTRIBUTES; + +typedef struct +{ + unsigned char ServerMustSize : 1; + unsigned char ClientMustSize : 1; + unsigned char HasReturn : 1; + unsigned char HasPipes : 1; + unsigned char Unused : 1; + unsigned char HasAsyncUuid : 1; + unsigned char HasExtensions : 1; + unsigned char HasAsyncHandle : 1; +} INTERPRETER_OPT_FLAGS, *PINTERPRETER_OPT_FLAGS; + +typedef struct +{ + unsigned char HasNewCorrDesc : 1; + unsigned char ClientCorrCheck : 1; + unsigned char ServerCorrCheck : 1; + unsigned char HasNotify : 1; + unsigned char HasNotify2 : 1; + unsigned char Unused : 3; +} INTERPRETER_OPT_FLAGS2, *PINTERPRETER_OPT_FLAGS2; + +typedef struct _NDR_CORRELATION_FLAGS +{ + unsigned char Early : 1; + unsigned char Split : 1; + unsigned char IsIidIs : 1; + unsigned char DontCheck : 1; + unsigned char Unused : 4; +} NDR_CORRELATION_FLAGS; + +#define FC_ALLOCATE_ALL_NODES 0x01 +#define FC_DONT_FREE 0x02 +#define FC_ALLOCED_ON_STACK 0x03 +#define FC_SIMPLE_POINTER 0x04 +#define FC_POINTER_DEREF 0x05 + +#define HANDLE_PARAM_IS_VIA_PTR 0x80 +#define HANDLE_PARAM_IS_IN 0x40 +#define HANDLE_PARAM_IS_OUT 0x20 +#define HANDLE_PARAM_IS_RETURN 0x21 +#define NDR_STRICT_CONTEXT_HANDLE 0x08 +#define NDR_CONTEXT_HANDLE_NO_SERIALIZE 0x04 +#define NDR_CONTEXT_HANDLE_SERIALIZE 0x02 +#define NDR_CONTEXT_HANDLE_CANNOT_BE_NULL 0x01 + +typedef struct +{ + PARAM_ATTRIBUTES Attributes; + unsigned short StackOffset; + + union + { + unsigned char FormatChar; + unsigned short Offset; + } Type; + +} NDR_PARAM; + +typedef struct +{ + unsigned char Size; + INTERPRETER_OPT_FLAGS2 Flags2; + unsigned short ClientCorrHint; + unsigned short ServerCorrHint; + unsigned short NotifyIndex; +} NDR_PROC_HEADER_EXTS; + +typedef struct _NDR_PROC_HEADER +{ + unsigned char HandleType; + INTERPRETER_FLAGS OldOiFlags; + unsigned short RpcFlagsLow; + unsigned short RpcFlagsHi; + unsigned short ProcNum; + unsigned short StackSize; +} NDR_PROC_HEADER, *PNDR_PROC_HEADER; + +typedef struct _NDR_OI2_PROC_HEADER +{ + unsigned short ClientBufferSize; + unsigned short ServerBufferSize; + INTERPRETER_OPT_FLAGS Oi2Flags; + unsigned char NumberParams; +} NDR_OI2_PROC_HEADER, *PNDR_OI2_PROC_HEADER; + +typedef enum _NDR_PHASE +{ + NDR_PHASE_SIZE, + NDR_PHASE_MARSHALL, + NDR_PHASE_UNMARSHALL, + NDR_PHASE_FREE +} NDR_PHASE; + +#define FC_NORMAL_CONFORMANCE 0x00 +#define FC_POINTER_CONFORMANCE 0x10 +#define FC_TOP_LEVEL_CONFORMANCE 0x20 +#define FC_CONSTANT_CONFORMANCE 0x40 +#define FC_TOP_LEVEL_MULTID_CONFORMANCE 0x80 + +/* Type Format Strings: http://msdn.microsoft.com/en-us/library/windows/desktop/aa379093/ */ + +#define FC_ZERO 0x00 +#define FC_BYTE 0x01 +#define FC_CHAR 0x02 +#define FC_SMALL 0x03 +#define FC_USMALL 0x04 +#define FC_WCHAR 0x05 +#define FC_SHORT 0x06 +#define FC_USHORT 0x07 +#define FC_LONG 0x08 +#define FC_ULONG 0x09 +#define FC_FLOAT 0x0A +#define FC_HYPER 0x0B +#define FC_DOUBLE 0x0C +#define FC_ENUM16 0x0D +#define FC_ENUM32 0x0E +#define FC_IGNORE 0x0F +#define FC_ERROR_STATUS_T 0x10 +#define FC_RP 0x11 +#define FC_UP 0x12 +#define FC_OP 0x13 +#define FC_FP 0x14 +#define FC_STRUCT 0x15 +#define FC_PSTRUCT 0x16 +#define FC_CSTRUCT 0x17 +#define FC_CPSTRUCT 0x18 +#define FC_CVSTRUCT 0x19 +#define FC_BOGUS_STRUCT 0x1A +#define FC_CARRAY 0x1B +#define FC_CVARRAY 0x1C +#define FC_SMFARRAY 0x1D +#define FC_LGFARRAY 0x1E +#define FC_SMVARRAY 0x1F +#define FC_LGVARRAY 0x20 +#define FC_BOGUS_ARRAY 0x21 +#define FC_C_CSTRING 0x22 +#define FC_C_BSTRING 0x23 +#define FC_C_SSTRING 0x24 +#define FC_C_WSTRING 0x25 +#define FC_CSTRING 0x26 +#define FC_BSTRING 0x27 +#define FC_SSTRING 0x28 +#define FC_WSTRING 0x29 +#define FC_ENCAPSULATED_UNION 0x2A +#define FC_NON_ENCAPSULATED_UNION 0x2B +#define FC_BYTE_COUNT_POINTER 0x2C +#define FC_TRANSMIT_AS 0x2D +#define FC_REPRESENT_AS 0x2E +#define FC_IP 0x2F +#define FC_BIND_CONTEXT 0x30 +#define FC_BIND_GENERIC 0x31 +#define FC_BIND_PRIMITIVE 0x32 +#define FC_AUTO_HANDLE 0x33 +#define FC_CALLBACK_HANDLE 0x34 +#define FC_UNUSED1 0x35 +#define FC_POINTER 0x36 +#define FC_ALIGNM2 0x37 +#define FC_ALIGNM4 0x38 +#define FC_ALIGNM8 0x39 +#define FC_UNUSED2 0x3A +#define FC_UNUSED3 0x3B +#define FC_UNUSED4 0x3C +#define FC_STRUCTPAD1 0x3D +#define FC_STRUCTPAD2 0x3E +#define FC_STRUCTPAD3 0x3F +#define FC_STRUCTPAD4 0x40 +#define FC_STRUCTPAD5 0x41 +#define FC_STRUCTPAD6 0x42 +#define FC_STRUCTPAD7 0x43 +#define FC_STRING_SIZED 0x44 +#define FC_UNUSED5 0x45 +#define FC_NO_REPEAT 0x46 +#define FC_FIXED_REPEAT 0x47 +#define FC_VARIABLE_REPEAT 0x48 +#define FC_FIXED_OFFSET 0x49 +#define FC_VARIABLE_OFFSET 0x4A +#define FC_PP 0x4B +#define FC_EMBEDDED_COMPLEX 0x4C +#define FC_IN_PARAM 0x4D +#define FC_IN_PARAM_BASETYPE 0x4E +#define FC_IN_PARAM_NO_FREE_INST 0x4F +#define FC_IN_OUT_PARAM 0x50 +#define FC_OUT_PARAM 0x51 +#define FC_RETURN_PARAM 0x52 +#define FC_RETURN_PARAM_BASETYPE 0x53 +#define FC_DEREFERENCE 0x54 +#define FC_DIV_2 0x55 +#define FC_MULT_2 0x56 +#define FC_ADD_1 0x57 +#define FC_SUB_1 0x58 +#define FC_CALLBACK 0x59 +#define FC_CONSTANT_IID 0x5A +#define FC_END 0x5B +#define FC_PAD 0x5C +#define FC_SPLIT_DEREFERENCE 0x74 +#define FC_SPLIT_DIV_2 0x75 +#define FC_SPLIT_MULT_2 0x76 +#define FC_SPLIT_ADD_1 0x77 +#define FC_SPLIT_SUB_1 0x78 +#define FC_SPLIT_CALLBACK 0x79 +#define FC_HARD_STRUCT 0xB1 +#define FC_TRANSMIT_AS_PTR 0xB2 +#define FC_REPRESENT_AS_PTR 0xB3 +#define FC_USER_MARSHAL 0xB4 +#define FC_PIPE 0xB5 +#define FC_BLKHOLE 0xB6 +#define FC_RANGE 0xB7 +#define FC_INT3264 0xB8 +#define FC_UINT3264 0xB9 +#define FC_END_OF_UNIVERSE 0xBA + +#define NdrFcShort(s) (byte)(s & 0xFF), (byte)(s >> 8) + +#define NdrFcLong(s) (byte)(s & 0xFF), (byte)((s & 0x0000FF00) >> 8), \ + (byte)((s & 0x00FF0000) >> 16), (byte)(s >> 24) + +typedef void (*NDR_TYPE_SIZE_ROUTINE)(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +typedef void (*NDR_TYPE_MARSHALL_ROUTINE)(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, unsigned char FormatChar); +typedef void (*NDR_TYPE_UNMARSHALL_ROUTINE)(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, unsigned char FormatChar); +typedef void (*NDR_TYPE_FREE_ROUTINE)(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); + +WINPR_API CLIENT_CALL_RETURN NdrClientCall2(PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, ...); + +#endif /* WINPR_RPC_NDR_H */ diff --git a/include/winpr/rpc.h b/include/winpr/rpc.h new file mode 100644 index 000000000..31257d2ce --- /dev/null +++ b/include/winpr/rpc.h @@ -0,0 +1,45 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_RPC_H +#define WINPR_RPC_H + +#include +#include + +#define RPC_VAR_ENTRY __cdecl + +typedef long RPC_STATUS; + +typedef void* I_RPC_HANDLE; +typedef I_RPC_HANDLE RPC_BINDING_HANDLE; +typedef RPC_BINDING_HANDLE handle_t; + +typedef PCONTEXT_HANDLE PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE; +typedef PCONTEXT_HANDLE PTUNNEL_CONTEXT_HANDLE_SERIALIZE; + +typedef PCONTEXT_HANDLE PCHANNEL_CONTEXT_HANDLE_NOSERIALIZE; +typedef PCONTEXT_HANDLE PCHANNEL_CONTEXT_HANDLE_SERIALIZE; + +#include +#include + +void RpcRaiseException(RPC_STATUS exception); + +#endif /* WINPR_RPC_H */ diff --git a/include/freerdp/sspi/sspi.h b/include/winpr/sspi.h similarity index 99% rename from include/freerdp/sspi/sspi.h rename to include/winpr/sspi.h index 31a234c57..5be7642b3 100644 --- a/include/freerdp/sspi/sspi.h +++ b/include/winpr/sspi.h @@ -21,10 +21,10 @@ #define FREERDP_SSPI_H #include +#include #include #include -#include #ifdef _WIN32 @@ -43,7 +43,7 @@ #else #define FREERDP_SSPI -#include +#include #endif @@ -953,7 +953,10 @@ FREERDP_API SECURITY_STATUS SEC_ENTRY VerifySignature(PCtxtHandle phContext, PSe /* Custom API */ -void sspi_GlobalInit(); -void sspi_GlobalFinish(); +FREERDP_API void sspi_GlobalInit(); +FREERDP_API void sspi_GlobalFinish(); + +FREERDP_API void sspi_SecBufferAlloc(PSecBuffer SecBuffer, size_t size); +FREERDP_API void sspi_SecBufferFree(PSecBuffer SecBuffer); #endif /* FREERDP_SSPI_H */ diff --git a/include/freerdp/utils/windows.h b/include/winpr/windows.h similarity index 83% rename from include/freerdp/utils/windows.h rename to include/winpr/windows.h index ecf95f66f..8daed265b 100644 --- a/include/freerdp/utils/windows.h +++ b/include/winpr/windows.h @@ -1,6 +1,6 @@ /** - * FreeRDP: A Remote Desktop Protocol Client - * Windows Header Utils + * WinPR: Windows Portable Runtime + * Windows Header Include Wrapper * * Copyright 2012 Marc-Andre Moreau * @@ -17,8 +17,8 @@ * limitations under the License. */ -#ifndef FREERDP_WINDOWS_UTILS_H -#define FREERDP_WINDOWS_UTILS_H +#ifndef WINPR_WINDOWS_H +#define WINPR_WINDOWS_H /* Windows header include order is important, use this instead of including windows.h directly */ @@ -34,4 +34,4 @@ #endif -#endif /* FREERDP_WINDOWS_UTILS_H */ +#endif /* WINPR_WINDOWS_H */ diff --git a/include/winpr/winpr.h b/include/winpr/winpr.h new file mode 100644 index 000000000..479b19b6e --- /dev/null +++ b/include/winpr/winpr.h @@ -0,0 +1,52 @@ +/** + * WinPR: Windows Portable Runtime + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_H +#define WINPR_H + +#include "config.h" + +#if defined _WIN32 || defined __CYGWIN__ + #ifdef WINPR_EXPORTS + #ifdef __GNUC__ + #define WINPR_API __attribute__((dllexport)) + #else + #define WINPR_API __declspec(dllexport) + #endif + #else + #ifdef __GNUC__ + #define WINPR_API __attribute__((dllimport)) + #else + #define WINPR_API __declspec(dllimport) + #endif + #endif +#else + #if __GNUC__ >= 4 + #define WINPR_API __attribute__ ((visibility("default"))) + #else + #define WINPR_API + #endif +#endif + +#ifdef _WIN32 +#define INLINE __inline +#else +#define INLINE inline +#endif + +#endif /* WINPR_H */ diff --git a/include/freerdp/wtypes.h b/include/winpr/wtypes.h similarity index 92% rename from include/freerdp/wtypes.h rename to include/winpr/wtypes.h index 4503d224b..3df5897b9 100644 --- a/include/freerdp/wtypes.h +++ b/include/winpr/wtypes.h @@ -1,5 +1,5 @@ /** - * FreeRDP: A Remote Desktop Protocol Client + * WinPR: Windows Portable Runtime * Windows Data Types * * Copyright 2012 Marc-Andre Moreau @@ -17,15 +17,14 @@ * limitations under the License. */ -#ifndef FREERDP_WINDOWS_TYPES_H -#define FREERDP_WINDOWS_TYPES_H +#ifndef WINPR_WTYPES_H +#define WINPR_WTYPES_H /* MSDN: Windows Data Types - http://msdn.microsoft.com/en-us/library/aa383751/ */ /* [MS-DTYP]: Windows Data Types - http://msdn.microsoft.com/en-us/library/cc230273/ */ #include -#include -#include +#include #ifndef _WIN32 @@ -42,12 +41,10 @@ typedef int BOOL, *PBOOL, *LPBOOL; typedef unsigned char BYTE, *PBYTE, *LPBYTE; -typedef BYTE byte; typedef BYTE BOOLEAN, *PBOOLEAN; typedef wchar_t WCHAR, *PWCHAR; typedef WCHAR* BSTR; typedef char CHAR, *PCHAR; -typedef double DOUBLE; typedef unsigned long DWORD, *PDWORD, *LPDWORD; typedef unsigned int DWORD32; typedef unsigned __int64 DWORD64; @@ -103,15 +100,20 @@ typedef void VOID, *PVOID, *LPVOID; typedef const void *LPCVOID; typedef unsigned short WORD, *PWORD, *LPWORD; -typedef void* PCONTEXT_HANDLE; -typedef PCONTEXT_HANDLE* PPCONTEXT_HANDLE; +#if __x86_64__ +typedef __int64 INT_PTR; +typedef unsigned __int64 UINT_PTR; +#else +typedef int INT_PTR; +typedef unsigned int UINT_PTR; +#endif typedef struct _GUID { unsigned long Data1; unsigned short Data2; unsigned short Data3; - byte Data4[8]; + BYTE Data4[8]; } GUID, UUID, *PGUID; #ifdef UNICODE @@ -171,4 +173,12 @@ typedef struct _SECURITY_DESCRIPTOR #endif -#endif /* FREERDP_WINDOWS_TYPES_H */ +typedef BYTE byte; +typedef double DOUBLE; + +typedef void* PCONTEXT_HANDLE; +typedef PCONTEXT_HANDLE* PPCONTEXT_HANDLE; + +typedef unsigned long error_status_t; + +#endif /* WINPR_WTYPES_H */ diff --git a/libfreerdp-core/CMakeLists.txt b/libfreerdp-core/CMakeLists.txt index d6fddb530..4161e101e 100644 --- a/libfreerdp-core/CMakeLists.txt +++ b/libfreerdp-core/CMakeLists.txt @@ -35,6 +35,12 @@ set(LIBFREERDP_CORE_SRCS nego.h info.c info.h + http.c + http.h + rpc.c + rpc.h + rts.c + rts.h input.c input.h license.c @@ -62,6 +68,8 @@ set(LIBFREERDP_CORE_SRCS rdp.h tcp.c tcp.h + tsg.c + tsg.h tpdu.c tpdu.h tpkt.c @@ -97,9 +105,11 @@ endif() target_link_libraries(freerdp-core freerdp-utils) target_link_libraries(freerdp-core freerdp-codec) target_link_libraries(freerdp-core freerdp-crypto) -target_link_libraries(freerdp-core freerdp-sspi) target_link_libraries(freerdp-core freerdp-locale) target_link_libraries(freerdp-core ${OPENSSL_LIBRARIES}) +target_link_libraries(freerdp-core winpr-rpc) +target_link_libraries(freerdp-core winpr-sspi) + install(TARGETS freerdp-core DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/libfreerdp-core/connection.c b/libfreerdp-core/connection.c index 65e0b03c6..98ab48e08 100644 --- a/libfreerdp-core/connection.c +++ b/libfreerdp-core/connection.c @@ -69,8 +69,12 @@ boolean rdp_client_connect(rdpRdp* rdp) nego_set_target(rdp->nego, settings->hostname, settings->port); nego_set_cookie(rdp->nego, settings->username); nego_enable_rdp(rdp->nego, settings->rdp_security); - nego_enable_nla(rdp->nego, settings->nla_security); - nego_enable_tls(rdp->nego, settings->tls_security); + + if (!settings->ts_gateway) + { + nego_enable_nla(rdp->nego, settings->nla_security); + nego_enable_tls(rdp->nego, settings->tls_security); + } if (nego_connect(rdp->nego) != true) { diff --git a/libfreerdp-core/extension.h b/libfreerdp-core/extension.h index 27aafdfcc..25273023f 100644 --- a/libfreerdp-core/extension.h +++ b/libfreerdp-core/extension.h @@ -21,10 +21,11 @@ #ifndef __EXTENSION_H #define __EXTENSION_H +#include + #include #include #include -#include #define FREERDP_EXT_MAX_COUNT 16 diff --git a/libfreerdp-core/http.c b/libfreerdp-core/http.c new file mode 100644 index 000000000..862cd2f20 --- /dev/null +++ b/libfreerdp-core/http.c @@ -0,0 +1,432 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Hypertext Transfer Protocol (HTTP) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "http.h" + +HttpContext* http_context_new() +{ + HttpContext* http_context = xnew(HttpContext); + + if (http_context != NULL) + { + + } + + return http_context; +} + +void http_context_set_method(HttpContext* http_context, char* method) +{ + http_context->Method = xstrdup(method); +} + +void http_context_set_uri(HttpContext* http_context, char* uri) +{ + http_context->URI = xstrdup(uri); +} + +void http_context_set_user_agent(HttpContext* http_context, char* user_agent) +{ + http_context->UserAgent = xstrdup(user_agent); +} + +void http_context_set_host(HttpContext* http_context, char* host) +{ + http_context->Host = xstrdup(host); +} + +void http_context_set_accept(HttpContext* http_context, char* accept) +{ + http_context->Accept = xstrdup(accept); +} + +void http_context_set_cache_control(HttpContext* http_context, char* cache_control) +{ + http_context->CacheControl = xstrdup(cache_control); +} + +void http_context_set_connection(HttpContext* http_context, char* connection) +{ + http_context->Connection = xstrdup(connection); +} + +void http_context_set_pragma(HttpContext* http_context, char* pragma) +{ + http_context->Pragma = xstrdup(pragma); +} + +void http_context_free(HttpContext* http_context) +{ + if (http_context != NULL) + { + xfree(http_context->UserAgent); + xfree(http_context->Host); + xfree(http_context->Accept); + xfree(http_context->CacheControl); + xfree(http_context->Connection); + xfree(http_context->Pragma); + xfree(http_context); + } +} + +void http_request_set_method(HttpRequest* http_request, char* method) +{ + http_request->Method = xstrdup(method); +} + +void http_request_set_uri(HttpRequest* http_request, char* uri) +{ + http_request->URI = xstrdup(uri); +} + +void http_request_set_auth_scheme(HttpRequest* http_request, char* auth_scheme) +{ + http_request->AuthScheme = xstrdup(auth_scheme); +} + +void http_request_set_auth_param(HttpRequest* http_request, char* auth_param) +{ + http_request->AuthParam = xstrdup(auth_param); +} + +#ifdef _WIN32 +#define http_encode_line(_str, _fmt, ...) \ + _str = xmalloc(sprintf_s(NULL, 0, _fmt, ## __VA_ARGS__) + 1); \ + sprintf_s(_str, sprintf_s(NULL, 0, _fmt, ## __VA_ARGS__) + 1, _fmt, ## __VA_ARGS__); +#else +#define http_encode_line(_str, _fmt, ...) \ + _str = xmalloc(snprintf(NULL, 0, _fmt, ## __VA_ARGS__) + 1); \ + snprintf(_str, snprintf(NULL, 0, _fmt, ## __VA_ARGS__) + 1, _fmt, ## __VA_ARGS__); +#endif + +STREAM* http_request_write(HttpContext* http_context, HttpRequest* http_request) +{ + int i; + STREAM* s; + int length = 0; + + http_request->count = 9; + http_request->lines = (char**) xmalloc(sizeof(char*) * http_request->count); + + http_encode_line(http_request->lines[0], "%s %s HTTP/1.1", http_request->Method, http_request->URI); + http_encode_line(http_request->lines[1], "Cache-Control: %s", http_context->CacheControl); + http_encode_line(http_request->lines[2], "Connection: %s", http_context->Connection); + http_encode_line(http_request->lines[3], "Pragma: %s", http_context->Pragma); + http_encode_line(http_request->lines[4], "Accept: %s", http_context->Accept); + http_encode_line(http_request->lines[5], "User-Agent: %s", http_context->UserAgent); + http_encode_line(http_request->lines[6], "Content-Length: %d", http_request->ContentLength); + http_encode_line(http_request->lines[7], "Host: %s", http_context->Host); + + if (http_request->Authorization != NULL) + { + http_encode_line(http_request->lines[8], "Authorization: %s", http_request->Authorization); + } + else if ((http_request->AuthScheme != NULL) && (http_request->AuthParam != NULL)) + { + http_encode_line(http_request->lines[8], "Authorization: %s %s", + http_request->AuthScheme, http_request->AuthParam); + } + + for (i = 0; i < http_request->count; i++) + { + length += (strlen(http_request->lines[i]) + 1); /* add +1 for each '\n' character */ + } + length += 1; /* empty line "\n" at end of header */ + length += 1; /* null terminator */ + + s = stream_new(length); + + for (i = 0; i < http_request->count; i++) + { + stream_write(s, http_request->lines[i], strlen(http_request->lines[i])); + stream_write(s, "\n", 1); + xfree(http_request->lines[i]); + } + stream_write(s, "\n", 1); + + xfree(http_request->lines); + + stream_write(s, "\0", 1); /* append null terminator */ + stream_rewind(s, 1); /* don't include null terminator in length */ + stream_seal(s); + + return s; +} + +HttpRequest* http_request_new() +{ + HttpRequest* http_request = xnew(HttpRequest); + + if (http_request != NULL) + { + + } + + return http_request; +} + +void http_request_free(HttpRequest* http_request) +{ + if (http_request != NULL) + { + xfree(http_request->Method); + xfree(http_request->URI); + xfree(http_request); + } +} + +void http_response_parse_header_status_line(HttpResponse* http_response, char* status_line) +{ + char* separator; + char* status_code; + char* reason_phrase; + + separator = strchr(status_line, ' '); + status_code = separator + 1; + + separator = strchr(status_code, ' '); + reason_phrase = separator + 1; + + *separator = '\0'; + http_response->StatusCode = atoi(status_code); + http_response->ReasonPhrase = xstrdup(reason_phrase); + *separator = ' '; +} + +void http_response_parse_header_field(HttpResponse* http_response, char* name, char* value) +{ + if (strcmp(name, "Content-Length") == 0) + { + http_response->ContentLength = atoi(value); + } + else if (strcmp(name, "Authorization") == 0) + { + char* separator; + + http_response->Authorization = xstrdup(value); + + separator = strchr(value, ' '); + + if (separator != NULL) + { + *separator = '\0'; + http_response->AuthScheme = xstrdup(value); + http_response->AuthParam = xstrdup(separator + 1); + *separator = ' '; + } + } + else if (strcmp(name, "WWW-Authenticate") == 0) + { + char* separator; + + separator = strstr(value, "=\""); + + if (separator != NULL) + { + /* WWW-Authenticate: parameter with spaces="value" */ + return; + } + + separator = strchr(value, ' '); + + if (separator != NULL) + { + /* WWW-Authenticate: NTLM base64token */ + + *separator = '\0'; + http_response->AuthScheme = xstrdup(value); + http_response->AuthParam = xstrdup(separator + 1); + *separator = ' '; + + return; + } + } +} + +void http_response_parse_header(HttpResponse* http_response) +{ + int count; + char* line; + char* name; + char* value; + char* separator; + + http_response_parse_header_status_line(http_response, http_response->lines[0]); + + for (count = 1; count < http_response->count; count++) + { + line = http_response->lines[count]; + + separator = strstr(line, ": "); + + if (separator == NULL) + continue; + + separator[0] = '\0'; + separator[1] = '\0'; + + name = line; + value = separator + 2; + + http_response_parse_header_field(http_response, name, value); + + separator[0] = ':'; + separator[1] = ' '; + } +} + +void http_response_print(HttpResponse* http_response) +{ + int i; + + for (i = 0; i < http_response->count; i++) + { + printf("%s\n", http_response->lines[i]); + } + printf("\n"); +} + +HttpResponse* http_response_recv(rdpTls* tls) +{ + uint8* p; + int nbytes; + int length; + int status; + uint8* buffer; + char* content; + char* header_end; + HttpResponse* http_response; + + nbytes = 0; + length = 0xFFFF; + buffer = xmalloc(length); + http_response = http_response_new(); + + p = buffer; + + while (true) + { + status = tls_read(tls, p, length - nbytes); + + if (status > 0) + { + nbytes += status; + p = (uint8*) &buffer[nbytes]; + } + else if (status == 0) + { + continue; + } + else + { + return NULL; + break; + } + + header_end = strstr((char*) buffer, "\r\n\r\n") + 2; + + if (header_end != NULL) + { + int count; + char* line; + + header_end[0] = '\0'; + header_end[1] = '\0'; + content = &header_end[2]; + + count = 0; + line = (char*) buffer; + + while ((line = strstr(line, "\r\n")) != NULL) + { + line++; + count++; + } + + http_response->count = count; + http_response->lines = (char**) xmalloc(sizeof(char*) * http_response->count); + + count = 0; + line = strtok((char*) buffer, "\r\n"); + + while (line != NULL) + { + http_response->lines[count] = xstrdup(line); + line = strtok(NULL, "\r\n"); + count++; + } + + http_response_parse_header(http_response); + + if (http_response->ContentLength > 0) + { + http_response->Content = xstrdup(content); + } + + break; + } + + if ((length - nbytes) <= 0) + { + length *= 2; + buffer = xrealloc(buffer, length); + p = (uint8*) &buffer[nbytes]; + } + } + + return http_response; +} + +HttpResponse* http_response_new() +{ + HttpResponse* http_response = xnew(HttpResponse); + + if (http_response != NULL) + { + + } + + return http_response; +} + +void http_response_free(HttpResponse* http_response) +{ + int i; + + if (http_response != NULL) + { + for (i = 0; i < http_response->count; i++) + xfree(http_response->lines[i]); + + xfree(http_response->lines); + + xfree(http_response->ReasonPhrase); + + xfree(http_response->AuthParam); + xfree(http_response->AuthScheme); + xfree(http_response->Authorization); + + if (http_response->ContentLength > 0) + xfree(http_response->Content); + + xfree(http_response); + } +} diff --git a/libfreerdp-core/http.h b/libfreerdp-core/http.h new file mode 100644 index 000000000..2b3bee83c --- /dev/null +++ b/libfreerdp-core/http.h @@ -0,0 +1,101 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Hypertext Transfer Protocol (HTTP) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CORE_HTTP_H +#define FREERDP_CORE_HTTP_H + +typedef struct _http_context HttpContext; +typedef struct _http_request HttpRequest; +typedef struct _http_response HttpResponse; + +#include +#include +#include + +struct _http_context +{ + char* Method; + char* URI; + char* UserAgent; + char* Host; + char* Accept; + char* CacheControl; + char* Connection; + char* Pragma; +}; + +void http_context_set_method(HttpContext* http_context, char* method); +void http_context_set_uri(HttpContext* http_context, char* uri); +void http_context_set_user_agent(HttpContext* http_context, char* user_agent); +void http_context_set_host(HttpContext* http_context, char* host); +void http_context_set_accept(HttpContext* http_context, char* accept); +void http_context_set_cache_control(HttpContext* http_context, char* cache_control); +void http_context_set_connection(HttpContext* http_context, char* connection); +void http_context_set_pragma(HttpContext* http_context, char* pragma); + +HttpContext* http_context_new(); +void http_context_free(HttpContext* http_context); + +struct _http_request +{ + int count; + char** lines; + + char* Method; + char* URI; + char* AuthScheme; + char* AuthParam; + char* Authorization; + int ContentLength; + char* Content; +}; + +void http_request_set_method(HttpRequest* http_request, char* method); +void http_request_set_uri(HttpRequest* http_request, char* uri); +void http_request_set_auth_scheme(HttpRequest* http_request, char* auth_scheme); +void http_request_set_auth_param(HttpRequest* http_request, char* auth_param); + +STREAM* http_request_write(HttpContext* http_context, HttpRequest* http_request); + +HttpRequest* http_request_new(); +void http_request_free(HttpRequest* http_request); + +struct _http_response +{ + int count; + char** lines; + + int StatusCode; + char* ReasonPhrase; + + char* AuthScheme; + char* AuthParam; + char* Authorization; + int ContentLength; + char* Content; +}; + +void http_response_print(HttpResponse* http_response); + +HttpResponse* http_response_recv(rdpTls* tls); + +HttpResponse* http_response_new(); +void http_response_free(HttpResponse* http_response); + +#endif /* FREERDP_CORE_HTTP_H */ diff --git a/libfreerdp-core/rpc.c b/libfreerdp-core/rpc.c new file mode 100644 index 000000000..805529002 --- /dev/null +++ b/libfreerdp-core/rpc.c @@ -0,0 +1,990 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * RPC over HTTP + * + * Copyright 2012 Fujitsu Technology Solutions GmbH + * Copyright 2012 Dmitrij Jasnov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "config.h" +#include +#include +#include + +#include + +#include "http.h" + +#include "rpc.h" + +#define NTLM_PACKAGE_NAME _T("NTLM") + +boolean ntlm_client_init(rdpNtlm* ntlm, boolean confidentiality, char* user, char* domain, char* password) +{ + size_t size; + SECURITY_STATUS status; + + sspi_GlobalInit(); + + ntlm->confidentiality = confidentiality; + + ntlm->table = InitSecurityInterface(); + + ntlm->identity.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; + + ntlm->identity.User = (uint16*) freerdp_uniconv_out(ntlm->uniconv, user, &size); + ntlm->identity.UserLength = (uint32) size; + + if (domain) + { + ntlm->identity.Domain = (uint16*) freerdp_uniconv_out(ntlm->uniconv, domain, &size); + ntlm->identity.DomainLength = (uint32) size; + } + else + { + ntlm->identity.Domain = (uint16*) NULL; + ntlm->identity.DomainLength = 0; + } + + ntlm->identity.Password = (uint16*) freerdp_uniconv_out(ntlm->uniconv, (char*) password, &size); + ntlm->identity.PasswordLength = (uint32) size; + + status = QuerySecurityPackageInfo(NTLM_PACKAGE_NAME, &ntlm->pPackageInfo); + + if (status != SEC_E_OK) + { + printf("QuerySecurityPackageInfo status: 0x%08X\n", status); + return false; + } + + ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken; + + status = ntlm->table->AcquireCredentialsHandle(NULL, NTLM_PACKAGE_NAME, + SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration); + + if (status != SEC_E_OK) + { + printf("AcquireCredentialsHandle status: 0x%08X\n", status); + return false; + } + + ntlm->haveContext = false; + ntlm->haveInputBuffer = false; + memset(&ntlm->inputBuffer, 0, sizeof(SecBuffer)); + memset(&ntlm->outputBuffer, 0, sizeof(SecBuffer)); + memset(&ntlm->ContextSizes, 0, sizeof(SecPkgContext_Sizes)); + + ntlm->fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_DELEGATE; + + if (ntlm->confidentiality) + ntlm->fContextReq |= ISC_REQ_CONFIDENTIALITY; + + return true; +} + +boolean ntlm_authenticate(rdpNtlm* ntlm) +{ + SECURITY_STATUS status; + + ntlm->outputBufferDesc.ulVersion = SECBUFFER_VERSION; + ntlm->outputBufferDesc.cBuffers = 1; + ntlm->outputBufferDesc.pBuffers = &ntlm->outputBuffer; + ntlm->outputBuffer.BufferType = SECBUFFER_TOKEN; + ntlm->outputBuffer.cbBuffer = ntlm->cbMaxToken; + ntlm->outputBuffer.pvBuffer = xmalloc(ntlm->outputBuffer.cbBuffer); + + if (ntlm->haveInputBuffer) + { + ntlm->inputBufferDesc.ulVersion = SECBUFFER_VERSION; + ntlm->inputBufferDesc.cBuffers = 1; + ntlm->inputBufferDesc.pBuffers = &ntlm->inputBuffer; + ntlm->inputBuffer.BufferType = SECBUFFER_TOKEN; + } + + status = ntlm->table->InitializeSecurityContext(&ntlm->credentials, + (ntlm->haveContext) ? &ntlm->context : NULL, + NULL, ntlm->fContextReq, 0, SECURITY_NATIVE_DREP, + (ntlm->haveInputBuffer) ? &ntlm->inputBufferDesc : NULL, + 0, &ntlm->context, &ntlm->outputBufferDesc, + &ntlm->pfContextAttr, &ntlm->expiration); + + if ((status == SEC_I_COMPLETE_AND_CONTINUE) || (status == SEC_I_COMPLETE_NEEDED) || (status == SEC_E_OK)) + { + if (ntlm->table->CompleteAuthToken != NULL) + ntlm->table->CompleteAuthToken(&ntlm->context, &ntlm->outputBufferDesc); + + if (ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES, &ntlm->ContextSizes) != SEC_E_OK) + { + printf("QueryContextAttributes SECPKG_ATTR_SIZES failure\n"); + return 0; + } + + if (status == SEC_I_COMPLETE_NEEDED) + status = SEC_E_OK; + else if (status == SEC_I_COMPLETE_AND_CONTINUE) + status = SEC_I_CONTINUE_NEEDED; + } + + ntlm->haveInputBuffer = true; + ntlm->haveContext = true; + + return true; +} + +void ntlm_client_uninit(rdpNtlm* ntlm) +{ + FreeCredentialsHandle(&ntlm->credentials); + FreeContextBuffer(ntlm->pPackageInfo); +} + +rdpNtlm* ntlm_new() +{ + rdpNtlm* ntlm = xnew(rdpNtlm); + + if (ntlm != NULL) + { + ntlm->uniconv = freerdp_uniconv_new(); + } + + return ntlm; +} + +void ntlm_free(rdpNtlm* ntlm) +{ + if (ntlm != NULL) + { + freerdp_uniconv_free(ntlm->uniconv); + } +} + +STREAM* rpc_ntlm_http_request(rdpRpc* rpc, SecBuffer* ntlm_token, int content_length, TSG_CHANNEL channel) +{ + STREAM* s; + char* base64_ntlm_token; + HttpContext* http_context; + HttpRequest* http_request; + + http_request = http_request_new(); + base64_ntlm_token = crypto_base64_encode(ntlm_token->pvBuffer, ntlm_token->cbBuffer); + + if (channel == TSG_CHANNEL_IN) + { + http_context = rpc->ntlm_http_in->context; + http_request_set_method(http_request, "RPC_IN_DATA"); + } + else if (channel == TSG_CHANNEL_OUT) + { + http_context = rpc->ntlm_http_out->context; + http_request_set_method(http_request, "RPC_OUT_DATA"); + } + else + { + return NULL; + } + + http_request->ContentLength = content_length; + http_request_set_uri(http_request, http_context->URI); + + http_request_set_auth_scheme(http_request, "NTLM"); + http_request_set_auth_param(http_request, base64_ntlm_token); + + s = http_request_write(http_context, http_request); + http_request_free(http_request); + + return s; +} + +boolean rpc_ntlm_http_out_connect(rdpRpc* rpc) +{ + STREAM* s; + int ntlm_token_length; + uint8* ntlm_token_data; + HttpResponse* http_response; + rdpNtlm* ntlm = rpc->ntlm_http_out->ntlm; + + ntlm_client_init(ntlm, true, rpc->settings->username, + rpc->settings->domain, rpc->settings->password); + + ntlm_authenticate(ntlm); + + s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer, 0, TSG_CHANNEL_OUT); + + /* Send OUT Channel Request */ + + DEBUG_RPC("\n%s", s->data); + tls_write_all(rpc->tls_out, s->data, s->size); + stream_free(s); + + /* Receive OUT Channel Response */ + + http_response = http_response_recv(rpc->tls_out); + + ntlm_token_data = NULL; + crypto_base64_decode((uint8*) http_response->AuthParam, strlen(http_response->AuthParam), + &ntlm_token_data, &ntlm_token_length); + + ntlm->inputBuffer.pvBuffer = ntlm_token_data; + ntlm->inputBuffer.cbBuffer = ntlm_token_length; + + ntlm_authenticate(ntlm); + + http_response_free(http_response); + + s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer, 76, TSG_CHANNEL_OUT); + + /* Send OUT Channel Request */ + + DEBUG_RPC("\n%s", s->data); + tls_write_all(rpc->tls_out, s->data, s->size); + stream_free(s); + + ntlm_client_uninit(ntlm); + ntlm_free(ntlm); + + return true; +} + +boolean rpc_ntlm_http_in_connect(rdpRpc* rpc) +{ + STREAM* s; + int ntlm_token_length; + uint8* ntlm_token_data; + HttpResponse* http_response; + rdpNtlm* ntlm = rpc->ntlm_http_in->ntlm; + + ntlm_client_init(ntlm, true, rpc->settings->username, + rpc->settings->domain, rpc->settings->password); + + ntlm_authenticate(ntlm); + + s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer, 0, TSG_CHANNEL_IN); + + /* Send IN Channel Request */ + + DEBUG_RPC("\n%s", s->data); + tls_write_all(rpc->tls_in, s->data, s->size); + stream_free(s); + + /* Receive IN Channel Response */ + + http_response = http_response_recv(rpc->tls_in); + + ntlm_token_data = NULL; + crypto_base64_decode((uint8*) http_response->AuthParam, strlen(http_response->AuthParam), + &ntlm_token_data, &ntlm_token_length); + + ntlm->inputBuffer.pvBuffer = ntlm_token_data; + ntlm->inputBuffer.cbBuffer = ntlm_token_length; + + ntlm_authenticate(ntlm); + + http_response_free(http_response); + + s = rpc_ntlm_http_request(rpc, &ntlm->outputBuffer, 0x40000000, TSG_CHANNEL_IN); + + /* Send IN Channel Request */ + + DEBUG_RPC("\n%s", s->data); + tls_write_all(rpc->tls_in, s->data, s->size); + stream_free(s); + + ntlm_client_uninit(ntlm); + ntlm_free(ntlm); + + return true; +} + +void rpc_pdu_header_read(STREAM* s, RPC_PDU_HEADER* header) +{ + stream_read_uint8(s, header->rpc_vers); /* rpc_vers (1 byte) */ + stream_read_uint8(s, header->rpc_vers_minor); /* rpc_vers_minor (1 byte) */ + stream_read_uint8(s, header->ptype); /* PTYPE (1 byte) */ + stream_read_uint8(s, header->pfc_flags); /* pfc_flags (1 byte) */ + stream_read_uint8(s, header->packed_drep[0]); /* packet_drep[0] (1 byte) */ + stream_read_uint8(s, header->packed_drep[1]); /* packet_drep[1] (1 byte) */ + stream_read_uint8(s, header->packed_drep[2]); /* packet_drep[2] (1 byte) */ + stream_read_uint8(s, header->packed_drep[3]); /* packet_drep[3] (1 byte) */ + stream_read_uint16(s, header->frag_length); /* frag_length (2 bytes) */ + stream_read_uint16(s, header->auth_length); /* auth_length (2 bytes) */ + stream_read_uint32(s, header->call_id); /* call_id (4 bytes) */ +} + +int rpc_out_write(rdpRpc* rpc, uint8* data, int length) +{ + int status; + +#ifdef WITH_DEBUG_RPC + printf("rpc_out_write(): length: %d\n", length); + freerdp_hexdump(data, length); + printf("\n"); +#endif + + status = tls_write_all(rpc->tls_out, data, length); + + return status; +} + +int rpc_in_write(rdpRpc* rpc, uint8* data, int length) +{ + int status; + +#ifdef WITH_DEBUG_RPC + printf("rpc_in_write() length: %d\n", length); + freerdp_hexdump(data, length); + printf("\n"); +#endif + + status = tls_write_all(rpc->tls_in, data, length); + + if (status > 0) + rpc->VirtualConnection->DefaultInChannel->BytesSent += status; + + return status; +} + +boolean rpc_send_bind_pdu(rdpRpc* rpc) +{ + STREAM* pdu; + rpcconn_bind_hdr_t* bind_pdu; + rdpSettings* settings = rpc->settings; + STREAM* ntlm_stream = stream_new(0xFFFF); + + rpc->ntlm = ntlm_new(); + + DEBUG_RPC("Sending bind PDU"); + + ntlm_client_init(rpc->ntlm, false, settings->username, settings->domain, settings->password); + + ntlm_authenticate(rpc->ntlm); + ntlm_stream->size = rpc->ntlm->outputBuffer.cbBuffer; + ntlm_stream->p = ntlm_stream->data = rpc->ntlm->outputBuffer.pvBuffer; + + bind_pdu = xnew(rpcconn_bind_hdr_t); + bind_pdu->rpc_vers = 5; + bind_pdu->rpc_vers_minor = 0; + bind_pdu->PTYPE = PTYPE_BIND; + bind_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_PENDING_CANCEL | PFC_CONC_MPX; + bind_pdu->packed_drep[0] = 0x10; + bind_pdu->packed_drep[1] = 0x00; + bind_pdu->packed_drep[2] = 0x00; + bind_pdu->packed_drep[3] = 0x00; + bind_pdu->frag_length = 124 + ntlm_stream->size; + bind_pdu->auth_length = ntlm_stream->size; + bind_pdu->call_id = 2; + bind_pdu->max_xmit_frag = 0x0FF8; + bind_pdu->max_recv_frag = 0x0FF8; + bind_pdu->assoc_group_id = 0; + bind_pdu->p_context_elem.n_context_elem = 2; + bind_pdu->p_context_elem.reserved = 0; + bind_pdu->p_context_elem.reserved2 = 0; + bind_pdu->p_context_elem.p_cont_elem = xmalloc(sizeof(p_cont_elem_t) * bind_pdu->p_context_elem.n_context_elem); + bind_pdu->p_context_elem.p_cont_elem[0].p_cont_id = 0; + bind_pdu->p_context_elem.p_cont_elem[0].n_transfer_syn = 1; + bind_pdu->p_context_elem.p_cont_elem[0].reserved = 0; + bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.time_low = 0x44e265dd; + bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.time_mid = 0x7daf; + bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.time_hi_and_version = 0x42cd; + bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.clock_seq_hi_and_reserved = 0x85; + bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.clock_seq_low = 0x60; + bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[0] = 0x3c; + bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[1] = 0xdb; + bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[2] = 0x6e; + bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[3] = 0x7a; + bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[4] = 0x27; + bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_uuid.node[5] = 0x29; + bind_pdu->p_context_elem.p_cont_elem[0].abstract_syntax.if_version = 0x00030001; + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes = xmalloc(sizeof(p_syntax_id_t)); + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.time_low = 0x8a885d04; + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.time_mid = 0x1ceb; + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.time_hi_and_version = 0x11c9; + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.clock_seq_hi_and_reserved = 0x9f; + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.clock_seq_low = 0xe8; + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[0] = 0x08; + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[1] = 0x00; + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[2] = 0x2b; + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[3] = 0x10; + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[4] = 0x48; + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_uuid.node[5] = 0x60; + bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes[0].if_version = 0x00000002; + bind_pdu->p_context_elem.p_cont_elem[1].p_cont_id = 1; + bind_pdu->p_context_elem.p_cont_elem[1].n_transfer_syn = 1; + bind_pdu->p_context_elem.p_cont_elem[1].reserved = 0; + bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.time_low = 0x44e265dd; + bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.time_mid = 0x7daf; + bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.time_hi_and_version = 0x42cd; + bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.clock_seq_hi_and_reserved = 0x85; + bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.clock_seq_low = 0x60; + bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[0] = 0x3c; + bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[1] = 0xdb; + bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[2] = 0x6e; + bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[3] = 0x7a; + bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[4] = 0x27; + bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_uuid.node[5] = 0x29; + bind_pdu->p_context_elem.p_cont_elem[1].abstract_syntax.if_version = 0x00030001; + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes = xmalloc(sizeof(p_syntax_id_t)); + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.time_low = 0x6cb71c2c; + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.time_mid = 0x9812; + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.time_hi_and_version = 0x4540; + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.clock_seq_hi_and_reserved = 0x03; + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.clock_seq_low = 0x00; + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[0] = 0x00; + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[1] = 0x00; + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[2] = 0x00; + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[3] = 0x00; + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[4] = 0x00; + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_uuid.node[5] = 0x00; + bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes[0].if_version = 0x00000001; + bind_pdu->auth_verifier.auth_pad = NULL; /* align(4); size_is(auth_pad_length) p*/ + bind_pdu->auth_verifier.auth_type = 0x0a; /* :01 which authent service */ + bind_pdu->auth_verifier.auth_level = 0x05; /* :01 which level within service */ + bind_pdu->auth_verifier.auth_pad_length = 0x00; /* :01 */ + bind_pdu->auth_verifier.auth_reserved = 0x00; /* :01 reserved, m.b.z. */ + bind_pdu->auth_verifier.auth_context_id = 0x00000000; /* :04 */ + bind_pdu->auth_verifier.auth_value = xmalloc(bind_pdu->auth_length); /* credentials; size_is(auth_length) p*/; + memcpy(bind_pdu->auth_verifier.auth_value, ntlm_stream->data, bind_pdu->auth_length); + + stream_free(ntlm_stream); + + pdu = stream_new(bind_pdu->frag_length); + + stream_write(pdu, bind_pdu, 24); + stream_write(pdu, &bind_pdu->p_context_elem, 4); + stream_write(pdu, bind_pdu->p_context_elem.p_cont_elem, 24); + stream_write(pdu, bind_pdu->p_context_elem.p_cont_elem[0].transfer_syntaxes, 20); + stream_write(pdu, bind_pdu->p_context_elem.p_cont_elem + 1, 24); + stream_write(pdu, bind_pdu->p_context_elem.p_cont_elem[1].transfer_syntaxes, 20); + + if (bind_pdu->auth_verifier.auth_pad_length > 0) + stream_write(pdu, bind_pdu->auth_verifier.auth_pad, bind_pdu->auth_verifier.auth_pad_length); + + stream_write(pdu, &bind_pdu->auth_verifier.auth_type, 8); /* assumed that uint8 pointer is 32bit long (4 bytes) */ + stream_write(pdu, bind_pdu->auth_verifier.auth_value, bind_pdu->auth_length); + stream_seal(pdu); + + rpc_in_write(rpc, pdu->data, pdu->size); + + xfree(bind_pdu); + + return true; +} + +int rpc_recv_bind_ack_pdu(rdpRpc* rpc) +{ + uint8* p; + STREAM* s; + int status; + uint8* pdu; + uint8* auth_data; + RPC_PDU_HEADER header; + int pdu_length = 0x8FFF; + + pdu = xmalloc(pdu_length); + status = rpc_out_read(rpc, pdu, pdu_length); + + if (status > 0) + { + s = stream_new(0); + stream_attach(s, pdu, pdu_length); + rpc_pdu_header_read(s, &header); + stream_detach(s); + stream_free(s); + + auth_data = xmalloc(header.auth_length); + p = (pdu + (header.frag_length - header.auth_length)); + memcpy(auth_data, p, header.auth_length); + + rpc->ntlm->inputBuffer.pvBuffer = auth_data; + rpc->ntlm->inputBuffer.cbBuffer = header.auth_length; + + ntlm_authenticate(rpc->ntlm); + } + + xfree(pdu); + return status; +} + +boolean rpc_send_rpc_auth_3_pdu(rdpRpc* rpc) +{ + STREAM* pdu; + STREAM* s = stream_new(0); + rpcconn_rpc_auth_3_hdr_t* rpc_auth_3_pdu; + + DEBUG_RPC("Sending auth_3 PDU"); + + s->size = rpc->ntlm->outputBuffer.cbBuffer; + s->p = s->data = rpc->ntlm->outputBuffer.pvBuffer; + + rpc_auth_3_pdu = xnew(rpcconn_rpc_auth_3_hdr_t); + rpc_auth_3_pdu->rpc_vers = 5; + rpc_auth_3_pdu->rpc_vers_minor = 0; + rpc_auth_3_pdu->PTYPE = PTYPE_RPC_AUTH_3; + rpc_auth_3_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG | PFC_CONC_MPX; + rpc_auth_3_pdu->packed_drep[0] = 0x10; + rpc_auth_3_pdu->packed_drep[1] = 0x00; + rpc_auth_3_pdu->packed_drep[2] = 0x00; + rpc_auth_3_pdu->packed_drep[3] = 0x00; + rpc_auth_3_pdu->frag_length = 28 + s->size; + rpc_auth_3_pdu->auth_length = s->size; + rpc_auth_3_pdu->call_id = 2; + + rpc_auth_3_pdu->max_xmit_frag = 0x0FF8; + rpc_auth_3_pdu->max_recv_frag = 0x0FF8; + rpc_auth_3_pdu->auth_verifier.auth_pad = NULL; /* align(4); size_is(auth_pad_length) p */ + rpc_auth_3_pdu->auth_verifier.auth_type = 0x0a; /* :01 which authent service */ + rpc_auth_3_pdu->auth_verifier.auth_level = 0x05; /* :01 which level within service */ + rpc_auth_3_pdu->auth_verifier.auth_pad_length = 0x00; /* :01 */ + rpc_auth_3_pdu->auth_verifier.auth_reserved = 0x00; /* :01 reserved, m.b.z. */ + rpc_auth_3_pdu->auth_verifier.auth_context_id = 0x00000000; /* :04 */ + rpc_auth_3_pdu->auth_verifier.auth_value = xmalloc(rpc_auth_3_pdu->auth_length); /* credentials; size_is(auth_length) p */ + memcpy(rpc_auth_3_pdu->auth_verifier.auth_value, s->data, rpc_auth_3_pdu->auth_length); + + stream_free(s); + + pdu = stream_new(rpc_auth_3_pdu->frag_length); + + stream_write(pdu, rpc_auth_3_pdu, 20); + + if (rpc_auth_3_pdu->auth_verifier.auth_pad_length > 0) + stream_write(pdu, rpc_auth_3_pdu->auth_verifier.auth_pad, rpc_auth_3_pdu->auth_verifier.auth_pad_length); + + stream_write(pdu, &rpc_auth_3_pdu->auth_verifier.auth_type, 8); + stream_write(pdu, rpc_auth_3_pdu->auth_verifier.auth_value, rpc_auth_3_pdu->auth_length); + + rpc_in_write(rpc, pdu->data, stream_get_length(pdu)); + + xfree(rpc_auth_3_pdu); + + return true; +} + +int rpc_out_read(rdpRpc* rpc, uint8* data, int length) +{ + STREAM* s; + int status; + uint8* pdu; + int content_length; + RPC_PDU_HEADER header; + + if (rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow < 0x00008FFF) /* Just a simple workaround */ + rts_send_flow_control_ack_pdu(rpc); /* Send FlowControlAck every time AvailableWindow reaches the half */ + + pdu = xmalloc(0xFFFF); + + status = tls_read(rpc->tls_out, pdu, 16); /* read first 16 bytes to get RPC PDU Header */ + + if (status <= 0) + { + xfree(pdu); + return status; + } + + s = stream_new(0); + stream_attach(s, pdu, 16); + + rpc_pdu_header_read(s, &header); + + stream_detach(s); + stream_free(s); + + content_length = header.frag_length - 16; + status = tls_read(rpc->tls_out, pdu + 16, content_length); + + if (status < 0) + { + xfree(pdu); + return status; + } + + if (header.ptype == PTYPE_RTS) /* RTS PDU */ + { + printf("rpc_out_read error: Unexpected RTS PDU\n"); + return -1; + } + else + { + /* RTS PDUs are not subject to flow control */ + rpc->VirtualConnection->DefaultOutChannel->BytesReceived += header.frag_length; + rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow -= header.frag_length; + } + + if (length < header.frag_length) + { + printf("rpc_out_read error! receive buffer is not large enough\n"); + return -1; + } + + memcpy(data, pdu, header.frag_length); + +#ifdef WITH_DEBUG_RPC + printf("rpc_out_read(): length: %d\n", header.frag_length); + freerdp_hexdump(data, header.frag_length); + printf("\n"); +#endif + + xfree(pdu); + + return header.frag_length; +} + +int rpc_tsg_write(rdpRpc* rpc, uint8* data, int length, uint16 opnum) +{ + int i; + int status; + STREAM* pdu; + rdpNtlm* ntlm; + SecBuffer Buffers[2]; + SecBufferDesc Message; + SECURITY_STATUS encrypt_status; + rpcconn_request_hdr_t* request_pdu; + + uint8 auth_pad_length = 16 - ((24 + length + 8 + 16) % 16); + + ntlm = rpc->ntlm; + + if (auth_pad_length == 16) + auth_pad_length = 0; + + request_pdu = xnew(rpcconn_request_hdr_t); + request_pdu->rpc_vers = 5; + request_pdu->rpc_vers_minor = 0; + request_pdu->PTYPE = PTYPE_REQUEST; + request_pdu->pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; + request_pdu->packed_drep[0] = 0x10; + request_pdu->packed_drep[1] = 0x00; + request_pdu->packed_drep[2] = 0x00; + request_pdu->packed_drep[3] = 0x00; + request_pdu->frag_length = 24 + length + auth_pad_length + 8 + 16; + request_pdu->auth_length = 16; + request_pdu->call_id = ++rpc->call_id; + + /* opnum=8 means [MS-TSGU] TsProxySetupReceivePipe, save call_id for checking pipe responses */ + + if (opnum == 8) + rpc->pipe_call_id = rpc->call_id; + + request_pdu->alloc_hint = length; + request_pdu->p_cont_id = 0x0000; + request_pdu->opnum = opnum; + request_pdu->stub_data = data; + request_pdu->auth_verifier.auth_type = 0x0A; /* :01 which authentication service */ + request_pdu->auth_verifier.auth_level = 0x05; /* :01 which level within service */ + request_pdu->auth_verifier.auth_pad_length = auth_pad_length; /* :01 */ + request_pdu->auth_verifier.auth_pad = xmalloc(auth_pad_length); /* align(4); size_is(auth_pad_length) p */ + + for (i = 0; i < auth_pad_length; i++) + { + request_pdu->auth_verifier.auth_pad[i] = 0x00; + } + + request_pdu->auth_verifier.auth_reserved = 0x00; /* :01 reserved, m.b.z. */ + request_pdu->auth_verifier.auth_context_id = 0x00000000; /* :04 */ + request_pdu->auth_verifier.auth_value = xmalloc(request_pdu->auth_length); /* credentials; size_is(auth_length) p */ + + pdu = stream_new(request_pdu->frag_length); + + stream_write(pdu, request_pdu, 24); + stream_write(pdu, request_pdu->stub_data, request_pdu->alloc_hint); + + if (request_pdu->auth_verifier.auth_pad_length > 0) + stream_write(pdu, request_pdu->auth_verifier.auth_pad, request_pdu->auth_verifier.auth_pad_length); + + stream_write(pdu, &request_pdu->auth_verifier.auth_type, 8); + + if (ntlm->table->QueryContextAttributes(&ntlm->context, SECPKG_ATTR_SIZES, &ntlm->ContextSizes) != SEC_E_OK) + { + printf("QueryContextAttributes SECPKG_ATTR_SIZES failure\n"); + return 0; + } + + Buffers[0].BufferType = SECBUFFER_DATA; /* auth_data */ + Buffers[1].BufferType = SECBUFFER_TOKEN; /* signature */ + + Buffers[0].pvBuffer = pdu->data; + Buffers[0].cbBuffer = stream_get_length(pdu); + + Buffers[1].cbBuffer = ntlm->ContextSizes.cbMaxSignature; + Buffers[1].pvBuffer = xzalloc(Buffers[1].cbBuffer); + + Message.cBuffers = 2; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + + encrypt_status = ntlm->table->EncryptMessage(&ntlm->context, 0, &Message, rpc->send_seq_num++); + + if (encrypt_status != SEC_E_OK) + { + printf("EncryptMessage status: 0x%08X\n", encrypt_status); + return 0; + } + + stream_write(pdu, Buffers[1].pvBuffer, Buffers[1].cbBuffer); + + status = rpc_in_write(rpc, pdu->data, pdu->p - pdu->data); + + xfree(request_pdu->auth_verifier.auth_value); + xfree(request_pdu->auth_verifier.auth_pad); + xfree(request_pdu); + + if (status < 0) + { + printf("rpc_write(): Error! rpc_tsg_write returned negative value.\n"); + return -1; + } + + return length; +} + +int rpc_read(rdpRpc* rpc, uint8* data, int length) +{ + int status; + int read = 0; + int data_length; + uint16 frag_length; + uint16 auth_length; + uint8 auth_pad_length; + uint32 call_id = -1; + int rpc_length = length + 0xFF; + uint8* rpc_data = xmalloc(rpc_length); + + if (rpc->read_buffer_len > 0) + { + if (rpc->read_buffer_len > (uint32) length) + { + printf("rpc_read error: receiving buffer is not large enough\n"); + return -1; + } + + memcpy(data, rpc->read_buffer, rpc->read_buffer_len); + read += rpc->read_buffer_len; + xfree(rpc->read_buffer); + rpc->read_buffer_len = 0; + } + + while (true) + { + status = rpc_out_read(rpc, rpc_data, rpc_length); + + if (status == 0) + { + xfree(rpc_data); + return read; + } + else if (status < 0) + { + printf("Error! rpc_out_read() returned negative value. BytesSent: %d, BytesReceived: %d\n", + rpc->VirtualConnection->DefaultInChannel->BytesSent, + rpc->VirtualConnection->DefaultOutChannel->BytesReceived); + + xfree(rpc_data); + return status; + } + + frag_length = *(uint16*)(rpc_data + 8); + auth_length = *(uint16*)(rpc_data + 10); + call_id = *(uint32*)(rpc_data + 12); + status = *(uint32*)(rpc_data + 16); /* alloc_hint */ + auth_pad_length = *(rpc_data + frag_length - auth_length - 6); /* -6 = -8 + 2 (sec_trailer + 2) */ + + /* data_length must be calculated because alloc_hint carries size of more than one pdu */ + data_length = frag_length - auth_length - 24 - 8 - auth_pad_length; /* 24 is header; 8 is sec_trailer */ + + if (status == 4) + continue; + + if (read + data_length > length) /* if read data is greater then given buffer */ + { + rpc->read_buffer_len = read + data_length - length; + rpc->read_buffer = xmalloc(rpc->read_buffer_len); + + data_length -= rpc->read_buffer_len; + + memcpy(rpc->read_buffer, rpc_data + 24 + data_length, rpc->read_buffer_len); + } + + memcpy(data + read, rpc_data + 24, data_length); + + read += data_length; + + if (status > data_length && read < length) + continue; + + break; + } + + xfree(rpc_data); + + return read; +} + +boolean rpc_connect(rdpRpc* rpc) +{ + rpc->tls_in = rpc->transport->tls_in; + rpc->tls_out = rpc->transport->tls_out; + + if (!rts_connect(rpc)) + { + printf("rts_connect error!\n"); + return false; + } + + if (!rpc_send_bind_pdu(rpc)) + { + printf("rpc_send_bind_pdu error!\n"); + return false; + } + + if (!rpc_recv_bind_ack_pdu(rpc)) + { + printf("rpc_recv_bind_ack_pdu error!\n"); + return false; + } + + if (!rpc_send_rpc_auth_3_pdu(rpc)) + { + printf("rpc_send_rpc_auth_3 error!\n"); + return false; + } + + return true; +} + +void rpc_client_virtual_connection_init(rdpRpc* rpc, RpcVirtualConnection* virtual_connection) +{ + virtual_connection->DefaultInChannel->BytesSent = 0; + virtual_connection->DefaultOutChannel->BytesReceived = 0; + virtual_connection->DefaultOutChannel->ReceiverAvailableWindow = rpc->ReceiveWindow; + virtual_connection->DefaultOutChannel->ReceiveWindow = rpc->ReceiveWindow; + virtual_connection->DefaultOutChannel->ReceiveWindowSize = rpc->ReceiveWindow; + virtual_connection->DefaultInChannel->SenderAvailableWindow = rpc->ReceiveWindow; + virtual_connection->DefaultInChannel->PingOriginator.ConnectionTimeout = 30; + virtual_connection->DefaultInChannel->PingOriginator.KeepAliveInterval = 0; +} + +RpcVirtualConnection* rpc_client_virtual_connection_new(rdpRpc* rpc) +{ + RpcVirtualConnection* virtual_connection = xnew(RpcVirtualConnection); + + if (virtual_connection != NULL) + { + virtual_connection->State = VIRTUAL_CONNECTION_STATE_INITIAL; + virtual_connection->DefaultInChannel = xnew(RpcInChannel); + virtual_connection->DefaultOutChannel = xnew(RpcOutChannel); + rpc_client_virtual_connection_init(rpc, virtual_connection); + } + + return virtual_connection; +} + +void rpc_client_virtual_connection_free(RpcVirtualConnection* virtual_connection) +{ + if (virtual_connection != NULL) + { + xfree(virtual_connection); + } +} + +rdpNtlmHttp* ntlm_http_new() +{ + rdpNtlmHttp* ntlm_http; + + ntlm_http = xnew(rdpNtlmHttp); + + if (ntlm_http != NULL) + { + ntlm_http->ntlm = ntlm_new(); + ntlm_http->context = http_context_new(); + } + + return ntlm_http; +} + +void rpc_ntlm_http_init_channel(rdpRpc* rpc, rdpNtlmHttp* ntlm_http, TSG_CHANNEL channel) +{ + if (channel == TSG_CHANNEL_IN) + http_context_set_method(ntlm_http->context, "RPC_IN_DATA"); + else if (channel == TSG_CHANNEL_OUT) + http_context_set_method(ntlm_http->context, "RPC_OUT_DATA"); + + http_context_set_uri(ntlm_http->context, "/rpc/rpcproxy.dll?localhost:3388"); + http_context_set_accept(ntlm_http->context, "application/rpc"); + http_context_set_cache_control(ntlm_http->context, "no-cache"); + http_context_set_connection(ntlm_http->context, "Keep-Alive"); + http_context_set_user_agent(ntlm_http->context, "MSRPC"); + http_context_set_host(ntlm_http->context, rpc->settings->tsg_hostname); + + if (channel == TSG_CHANNEL_IN) + { + http_context_set_pragma(ntlm_http->context, + "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729"); + } + else if (channel == TSG_CHANNEL_OUT) + { + http_context_set_pragma(ntlm_http->context, + "ResourceTypeUuid=44e265dd-7daf-42cd-8560-3cdb6e7a2729" ", " + "SessionId=fbd9c34f-397d-471d-a109-1b08cc554624"); + } +} + +void ntlm_http_free(rdpNtlmHttp* ntlm_http) +{ + if (ntlm_http != NULL) + { + ntlm_free(ntlm_http->ntlm); + http_context_free(ntlm_http->context); + } +} + +rdpRpc* rpc_new(rdpTransport* transport) +{ + rdpRpc* rpc = (rdpRpc*) xnew(rdpRpc); + + if (rpc != NULL) + { + rpc->transport = transport; + rpc->settings = transport->settings; + + rpc->send_seq_num = 0; + rpc->ntlm = ntlm_new(); + + rpc->ntlm_http_in = ntlm_http_new(); + rpc->ntlm_http_out = ntlm_http_new(); + + rpc_ntlm_http_init_channel(rpc, rpc->ntlm_http_in, TSG_CHANNEL_IN); + rpc_ntlm_http_init_channel(rpc, rpc->ntlm_http_out, TSG_CHANNEL_OUT); + + rpc->read_buffer = NULL; + rpc->write_buffer = NULL; + rpc->read_buffer_len = 0; + rpc->write_buffer_len = 0; + + rpc->ReceiveWindow = 0x00010000; + rpc->VirtualConnection = rpc_client_virtual_connection_new(rpc); + + rpc->call_id = 0; + } + + return rpc; +} + +void rpc_free(rdpRpc* rpc) +{ + if (rpc != NULL) + { + ntlm_http_free(rpc->ntlm_http_in); + ntlm_http_free(rpc->ntlm_http_out); + rpc_client_virtual_connection_free(rpc->VirtualConnection); + xfree(rpc); + } +} diff --git a/libfreerdp-core/rpc.h b/libfreerdp-core/rpc.h new file mode 100644 index 000000000..ff9f2db82 --- /dev/null +++ b/libfreerdp-core/rpc.h @@ -0,0 +1,703 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * RPC over HTTP + * + * Copyright 2012 Fujitsu Technology Solutions GmbH + * Copyright 2012 Dmitrij Jasnov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CORE_RPC_H +#define FREERDP_CORE_RPC_H + +typedef struct rdp_rpc rdpRpc; +typedef struct rdp_ntlm_http rdpNtlmHttp; + +#include "tcp.h" +#include "rts.h" +#include "http.h" +#include "transport.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct _rpc_pdu_header +{ + uint8 rpc_vers; + uint8 rpc_vers_minor; + uint8 ptype; + uint8 pfc_flags; + uint8 packed_drep[4]; + uint16 frag_length; + uint16 auth_length; + uint32 call_id; +}; +typedef struct _rpc_pdu_header RPC_PDU_HEADER; + +typedef uint16 p_context_id_t; + +typedef struct { + uuid if_uuid; + uint32 if_version; +} p_syntax_id_t; + +typedef struct { + p_context_id_t p_cont_id; + uint8 n_transfer_syn; /* number of items */ + uint8 reserved; /* alignment pad, m.b.z. */ + p_syntax_id_t abstract_syntax; /* transfer syntax list */ + p_syntax_id_t* transfer_syntaxes; /*size_is(n_transfer_syn)*/ +} p_cont_elem_t; + +typedef struct { + uint8 n_context_elem; /* number of items */ + uint8 reserved; /* alignment pad, m.b.z. */ + uint16 reserved2; /* alignment pad, m.b.z. */ + p_cont_elem_t* p_cont_elem; /*size_is(n_cont_elem)*/ +} p_cont_list_t; + +typedef enum { + acceptance, user_rejection, provider_rejection +} p_cont_def_result_t; + +typedef enum { + reason_not_specified, + abstract_syntax_not_supported, + proposed_transfer_syntaxes_not_supported, + local_limit_exceeded +} p_provider_reason_t; + + +typedef struct { + p_cont_def_result_t result; + p_provider_reason_t reason; /* only relevant if result != + * acceptance */ + p_syntax_id_t transfer_syntax;/* tr syntax selected + * 0 if result not + * accepted */ +} p_result_t; + +/* Same order and number of elements as in bind request */ + +typedef struct { + uint8 n_results; /* count */ + uint8 reserved; /* alignment pad, m.b.z. */ + uint16 reserved2; /* alignment pad, m.b.z. */ + p_result_t* p_results; /*size_is(n_results)*/ +} p_result_list_t; + +typedef struct { + uint8 major; + uint8 minor; +} version_t; +typedef version_t p_rt_version_t; + +typedef struct { + uint8 n_protocols; /* count */ + p_rt_version_t* p_protocols; /* size_is(n_protocols) */ +} p_rt_versions_supported_t; + +typedef struct { + uint16 length; + char* port_spec; /* port string spec; size_is(length) */ +} port_any_t; + +#define REASON_NOT_SPECIFIED 0 +#define TEMPORARY_CONGESTION 1 +#define LOCAL_LIMIT_EXCEEDED 2 +#define CALLED_PADDR_UNKNOWN 3 /* not used */ +#define PROTOCOL_VERSION_NOT_SUPPORTED 4 +#define DEFAULT_CONTEXT_NOT_SUPPORTED 5 /* not used */ +#define USER_DATA_NOT_READABLE 6 /* not used */ +#define NO_PSAP_AVAILABLE 7 /* not used */ + +typedef uint16 rpcrt_reason_code_t;/* 0..65535 */ + +typedef struct { + uint8 rpc_vers; + uint8 rpc_vers_minor; + uint8 reserved[2];/* must be zero */ + uint8 packed_drep[4]; + uint32 reject_status; + uint8 reserved2[4]; +} rpcrt_optional_data_t; + +typedef struct { + rpcrt_reason_code_t reason_code; /* 0..65535 */ + rpcrt_optional_data_t rpc_info; /* may be RPC specific */ +} rpcconn_reject_optional_data_t; + +typedef struct { + rpcrt_reason_code_t reason_code; /* 0..65535 */ + rpcrt_optional_data_t rpc_info; /* may be RPC-specific */ +} rpcconn_disc_optional_data_t; + +typedef struct{ + /* restore 4 byte alignment */ + + uint8* auth_pad; /* align(4); size_is(auth_pad_length) */ + uint8 auth_type; /* :01 which authent service */ + uint8 auth_level; /* :01 which level within service */ + uint8 auth_pad_length; /* :01 */ + uint8 auth_reserved; /* :01 reserved, m.b.z. */ + uint32 auth_context_id; /* :04 */ + uint8* auth_value; /* credentials; size_is(auth_length) */ +} auth_verifier_co_t; + +/* Connection-oriented PDU Definitions */ + +typedef struct { + /* start 8-octet aligned */ + + /* common fields */ + uint8 rpc_vers; /* 00:01 RPC version */ + uint8 rpc_vers_minor ; /* 01:01 minor version */ + uint8 PTYPE; /* 02:01 alter context PDU */ + uint8 pfc_flags; /* 03:01 flags */ + uint8 packed_drep[4]; /* 04:04 NDR data rep format label*/ + uint16 frag_length; /* 08:02 total length of fragment */ + uint16 auth_length; /* 10:02 length of auth_value */ + uint32 call_id; /* 12:04 call identifier */ + + /* end common fields */ + + uint16 max_xmit_frag; /* ignored */ + uint16 max_recv_frag; /* ignored */ + uint32 assoc_group_id; /* ignored */ + + /* presentation context list */ + + p_cont_list_t p_context_elem; /* variable size */ + + /* optional authentication verifier */ + /* following fields present iff auth_length != 0 */ + + auth_verifier_co_t auth_verifier; + +} rpcconn_alter_context_hdr_t; + +typedef struct { + /* start 8-octet aligned */ + + /* common fields */ + uint8 rpc_vers; /* 00:01 RPC version */ + uint8 rpc_vers_minor; /* 01:01 minor version */ + uint8 PTYPE; /* 02:01 alter + context response PDU */ + uint8 pfc_flags; /* 03:01 flags */ + uint8 packed_drep[4]; /* 04:04 NDR data rep format label*/ + uint16 frag_length; /* 08:02 total length of fragment */ + uint16 auth_length; /* 10:02 length of auth_value */ + uint32 call_id; /* 12:04 call identifier */ + + /* end common fields */ + + uint16 max_xmit_frag; /* ignored */ + uint16 max_recv_frag; /* ignored */ + uint32 assoc_group_id; /* ignored */ + port_any_t sec_addr; /* ignored */ + + /* restore 4-octet alignment */ + + uint8* pad2; /* size_is(align(4)) */ + + /* presentation context result list, including hints */ + + p_result_list_t p_result_list; /* variable size */ + + /* optional authentication verifier */ + /* following fields present iff auth_length != 0 */ + + auth_verifier_co_t auth_verifier; /* xx:yy */ +} rpcconn_alter_context_response_hdr_t; + +/* bind header */ +typedef struct { + /* start 8-octet aligned */ + + /* common fields */ + uint8 rpc_vers; /* 00:01 RPC version */ + uint8 rpc_vers_minor; /* 01:01 minor version */ + uint8 PTYPE; /* 02:01 bind PDU */ + uint8 pfc_flags; /* 03:01 flags */ + uint8 packed_drep[4]; /* 04:04 NDR data rep format label*/ + uint16 frag_length; /* 08:02 total length of fragment */ + uint16 auth_length; /* 10:02 length of auth_value */ + uint32 call_id; /* 12:04 call identifier */ + + /* end common fields */ + + uint16 max_xmit_frag; /* 16:02 max transmit frag size, bytes */ + uint16 max_recv_frag; /* 18:02 max receive frag size, bytes */ + uint32 assoc_group_id; /* 20:04 incarnation of client-server + * assoc group */ + /* presentation context list */ + + p_cont_list_t p_context_elem; /* variable size */ + + /* optional authentication verifier */ + /* following fields present iff auth_length != 0 */ + + auth_verifier_co_t auth_verifier; +} rpcconn_bind_hdr_t; + +typedef struct { + /* start 8-octet aligned */ + + /* common fields */ + uint8 rpc_vers; /* 00:01 RPC version */ + uint8 rpc_vers_minor ; /* 01:01 minor version */ + uint8 PTYPE; /* 02:01 bind ack PDU */ + uint8 pfc_flags; /* 03:01 flags */ + uint8 packed_drep[4]; /* 04:04 NDR data rep format label*/ + uint16 frag_length; /* 08:02 total length of fragment */ + uint16 auth_length; /* 10:02 length of auth_value */ + uint32 call_id; /* 12:04 call identifier */ + + /* end common fields */ + + uint16 max_xmit_frag; /* 16:02 max transmit frag size */ + uint16 max_recv_frag; /* 18:02 max receive frag size */ + uint32 assoc_group_id; /* 20:04 returned assoc_group_id */ + port_any_t sec_addr; /* 24:yy optional secondary address + * for process incarnation; local port + * part of address only */ + /* restore 4-octet alignment */ + + uint8* pad2; /* size_is(align(4)) */ + + /* presentation context result list, including hints */ + + p_result_list_t p_result_list; /* variable size */ + + /* optional authentication verifier */ + /* following fields present iff auth_length != 0 */ + + auth_verifier_co_t auth_verifier; /* xx:yy */ +} rpcconn_bind_ack_hdr_t; + +typedef struct { + /* start 8-octet aligned */ + + /* common fields */ + uint8 rpc_vers; /* 00:01 RPC version */ + uint8 rpc_vers_minor ; /* 01:01 minor version */ + uint8 PTYPE; /* 02:01 bind ack PDU */ + uint8 pfc_flags; /* 03:01 flags */ + uint8 packed_drep[4]; /* 04:04 NDR data rep format label*/ + uint16 frag_length; /* 08:02 total length of fragment */ + uint16 auth_length; /* 10:02 length of auth_value */ + uint32 call_id; /* 12:04 call identifier */ + + /* end common fields */ + + uint16 max_xmit_frag; /* 16:02 max transmit frag size */ + uint16 max_recv_frag; /* 18:02 max receive frag size */ + + /* optional authentication verifier */ + /* following fields present iff auth_length != 0 */ + + auth_verifier_co_t auth_verifier; /* xx:yy */ +} rpcconn_rpc_auth_3_hdr_t; + +typedef struct { + /* start 8-octet aligned */ + + /* common fields */ + uint8 rpc_vers; /* 00:01 RPC version */ + uint8 rpc_vers_minor ; /* 01:01 minor version */ + uint8 PTYPE; /* 02:01 bind nak PDU */ + uint8 pfc_flags; /* 03:01 flags */ + uint8 packed_drep[4]; /* 04:04 NDR data rep format label*/ + uint16 frag_length; /* 08:02 total length of fragment */ + uint16 auth_length; /* 10:02 length of auth_value */ + uint32 call_id; /* 12:04 call identifier */ + + /* end common fields */ + + /*p_reject_reason_t*/uint16 provider_reject_reason; /* 16:02 presentation (TODO search definition of p_reject_reason_t) + context reject */ + + p_rt_versions_supported_t versions; /* 18:yy array of protocol + * versions supported */ +} rpcconn_bind_nak_hdr_t; + + +typedef struct { + /* start 8-octet aligned */ + + /* common fields */ + uint8 rpc_vers; /* 00:01 RPC version */ + uint8 rpc_vers_minor; /* 01:01 minor version */ + uint8 PTYPE; /* 02:01 CO cancel PDU */ + uint8 pfc_flags; /* 03:01 flags */ + uint8 packed_drep[4]; /* 04:04 NDR data rep format label*/ + uint16 frag_length; /* 08:02 total length of fragment */ + uint16 auth_length; /* 10:02 length of auth_value */ + uint32 call_id; /* 12:04 call identifier */ + + /* end common fields */ + + /* optional authentication verifier + * following fields present iff auth_length != 0 */ + + auth_verifier_co_t auth_verifier; /* xx:yy */ + +} rpcconn_cancel_hdr_t; + +typedef struct { + /* start 8-octet aligned */ + + /* common fields */ + uint8 rpc_vers; /* 00:01 RPC version */ + uint8 rpc_vers_minor; /* 01:01 minor version */ + uint8 PTYPE; /* 02:01 fault PDU */ + uint8 pfc_flags; /* 03:01 flags */ + uint8 packed_drep[4]; /* 04:04 NDR data rep format label*/ + uint16 frag_length; /* 08:02 total length of fragment */ + uint16 auth_length; /* 10:02 length of auth_value */ + uint32 call_id; /* 12:04 call identifier */ + + /* end common fields */ + + /* needed for request, response, fault */ + + uint32 alloc_hint; /* 16:04 allocation hint */ + p_context_id_t p_cont_id; /* 20:02 pres context, i.e. data rep */ + + /* needed for response or fault */ + + uint8 cancel_count; /* 22:01 received cancel count */ + uint8 reserved; /* 23:01 reserved, m.b.z. */ + + /* fault code */ + + uint32 status; /* 24:04 run-time fault code or zero */ + + /* always pad to next 8-octet boundary */ + + uint8 reserved2[4]; /* 28:04 reserved padding, m.b.z. */ + + /* stub data here, 8-octet aligned + . + . + . */ + uint8* stub_data; + + /* optional authentication verifier */ + /* following fields present iff auth_length != 0 */ + + auth_verifier_co_t auth_verifier; /* xx:yy */ +} rpcconn_fault_hdr_t; + + +typedef struct { + /* start 8-octet aligned */ + + /* common fields */ + uint8 rpc_vers; /* 00:01 RPC version */ + uint8 rpc_vers_minor; /* 01:01 minor version */ + uint8 PTYPE; /* 02:01 orphaned PDU */ + uint8 pfc_flags; /* 03:01 flags */ + uint8 packed_drep[4]; /* 04:04 NDR data rep format label*/ + uint16 frag_length; /* 08:02 total length of fragment */ + uint16 auth_length; /* 10:02 length of auth_value */ + uint32 call_id; /* 12:04 call identifier */ + + /* end common fields */ + + /* optional authentication verifier + * following fields present iff auth_length != 0 */ + + auth_verifier_co_t auth_verifier; /* xx:yy */ +} rpcconn_orphaned_hdr_t; + + +typedef struct { + /* start 8-octet aligned */ + + /* common fields */ + uint8 rpc_vers; /* 00:01 RPC version */ + uint8 rpc_vers_minor; /* 01:01 minor version */ + uint8 PTYPE; /* 02:01 request PDU */ + uint8 pfc_flags; /* 03:01 flags */ + uint8 packed_drep[4]; /* 04:04 NDR data rep format label*/ + uint16 frag_length; /* 08:02 total length of fragment */ + uint16 auth_length; /* 10:02 length of auth_value */ + uint32 call_id; /* 12:04 call identifier */ + + /* end common fields */ + + /* needed on request, response, fault */ + + uint32 alloc_hint; /* 16:04 allocation hint */ + p_context_id_t p_cont_id; /* 20:02 pres context, i.e. data rep */ + uint16 opnum; /* 22:02 operation # + * within the interface */ + + /* optional field for request, only present if the PFC_OBJECT_UUID + * field is non-zero */ + + uuid object; /* 24:16 object UID */ + + /* stub data, 8-octet aligned + . + . + . */ + uint8* stub_data; + + /* optional authentication verifier */ + /* following fields present iff auth_length != 0 */ + + auth_verifier_co_t auth_verifier; /* xx:yy */ +} rpcconn_request_hdr_t; + +typedef struct { + /* start 8-octet aligned */ + + /* common fields */ + uint8 rpc_vers; /* 00:01 RPC version */ + uint8 rpc_vers_minor; /* 01:01 minor version */ + uint8 PTYPE; /* 02:01 response PDU */ + uint8 pfc_flags; /* 03:01 flags */ + uint8 packed_drep[4]; /* 04:04 NDR data rep format label*/ + uint16 frag_length; /* 08:02 total length of fragment */ + uint16 auth_length; /* 10:02 length of auth_value */ + uint32 call_id; /* 12:04 call identifier */ + + /* end common fields */ + + /* needed for request, response, fault */ + + uint32 alloc_hint; /* 16:04 allocation hint */ + p_context_id_t p_cont_id; /* 20:02 pres context, i.e. + * data rep */ + + /* needed for response or fault */ + + uint8 cancel_count; /* 22:01 cancel count */ + uint8 reserved; /* 23:01 reserved, m.b.z. */ + + /* stub data here, 8-octet aligned + . + . + . */ + uint8* stub_data; + + /* optional authentication verifier */ + /* following fields present iff auth_length != 0 */ + + auth_verifier_co_t auth_verifier; /* xx:yy */ +} rpcconn_response_hdr_t; + + +typedef struct { + /* start 8-octet aligned */ + + /* common fields */ + uint8 rpc_vers; /* 00:01 RPC version */ + uint8 rpc_vers_minor; /* 01:01 minor version */ + uint8 PTYPE; /* 02:01 shutdown PDU */ + uint8 pfc_flags; /* 03:01 flags */ + uint8 packed_drep[4]; /* 04:04 NDR data rep format label*/ + uint16 frag_length; /* 08:02 total length of fragment */ + uint16 auth_length; /* 10:02 */ + uint32 call_id; /* 12:04 call identifier */ + + /* end common fields */ +} rpcconn_shutdown_hdr_t; + +struct rdp_ntlm +{ + UNICONV* uniconv; + CtxtHandle context; + uint32 cbMaxToken; + uint32 fContextReq; + uint32 pfContextAttr; + TimeStamp expiration; + PSecBuffer pBuffer; + SecBuffer inputBuffer; + SecBuffer outputBuffer; + boolean haveContext; + boolean haveInputBuffer; + SecBufferDesc inputBufferDesc; + SecBufferDesc outputBufferDesc; + CredHandle credentials; + boolean confidentiality; + SecPkgInfo* pPackageInfo; + SecurityFunctionTable* table; + SEC_WINNT_AUTH_IDENTITY identity; + SecPkgContext_Sizes ContextSizes; +}; +typedef struct rdp_ntlm rdpNtlm; + +enum _TSG_CHANNEL +{ + TSG_CHANNEL_IN, + TSG_CHANNEL_OUT +}; +typedef enum _TSG_CHANNEL TSG_CHANNEL; + +struct rdp_ntlm_http +{ + rdpNtlm* ntlm; + HttpContext* context; +}; + +/* Ping Originator */ + +struct rpc_ping_originator +{ + uint32 ConnectionTimeout; + uint32 LastPacketSentTimestamp; + uint32 KeepAliveInterval; +}; +typedef struct rpc_ping_originator RpcPingOriginator; + +/* Client In Channel */ + +struct rpc_in_channel +{ + /* Sending Channel */ + + uint32 PlugState; + void* SendQueue; + uint32 BytesSent; + uint32 SenderAvailableWindow; + uint32 PeerReceiveWindow; + + /* Ping Originator */ + + RpcPingOriginator PingOriginator; +}; +typedef struct rpc_in_channel RpcInChannel; + +/* Client Out Channel */ + +struct rpc_out_channel +{ + /* Receiving Channel */ + + uint32 ReceiveWindow; + uint32 ReceiveWindowSize; + uint32 ReceiverAvailableWindow; + uint32 BytesReceived; + uint32 AvailableWindowAdvertised; +}; +typedef struct rpc_out_channel RpcOutChannel; + +/* Client Virtual Connection */ + +enum _VIRTUAL_CONNECTION_STATE +{ + VIRTUAL_CONNECTION_STATE_INITIAL, + VIRTUAL_CONNECTION_STATE_OUT_CHANNEL_WAIT, + VIRTUAL_CONNECTION_STATE_WAIT_A3W, + VIRTUAL_CONNECTION_STATE_WAIT_C2, + VIRTUAL_CONNECTION_STATE_OPENED, + VIRTUAL_CONNECTION_STATE_FINAL +}; +typedef enum _VIRTUAL_CONNECTION_STATE VIRTUAL_CONNECTION_STATE; + +struct rpc_virtual_connection +{ + uint8 Cookie[16]; /* Virtual Connection Cookie */ + VIRTUAL_CONNECTION_STATE State; /* Virtual Connection State */ + RpcInChannel* DefaultInChannel; /* Default IN Channel */ + RpcInChannel* NonDefaultInChannel; /* Non-Default IN Channel */ + uint8 DefaultInChannelCookie[16]; /* Default IN Channel Cookie */ + uint8 NonDefaultInChannelCookie[16]; /* Non-Default Default IN Channel Cookie */ + RpcOutChannel* DefaultOutChannel; /* Default OUT Channel */ + RpcOutChannel* NonDefaultOutChannel; /* Non-Default OUT Channel */ + uint8 DefaultOutChannelCookie[16]; /* Default OUT Channel Cookie */ + uint8 NonDefaultOutChannelCookie[16]; /* Non-Default Default OUT Channel Cookie */ + uint8 AssociationGroupId[16]; /* AssociationGroupId */ +}; +typedef struct rpc_virtual_connection RpcVirtualConnection; + +struct rdp_rpc +{ + rdpTls* tls_in; + rdpTls* tls_out; + + rdpNtlm* ntlm; + int send_seq_num; + + rdpNtlmHttp* ntlm_http_in; + rdpNtlmHttp* ntlm_http_out; + + UNICONV* uniconv; + rdpSettings* settings; + rdpTransport* transport; + + uint8* write_buffer; + uint32 write_buffer_len; + uint8* read_buffer; + uint32 read_buffer_len; + + uint32 call_id; + uint32 pipe_call_id; + + uint32 ReceiveWindow; + + RpcVirtualConnection* VirtualConnection; +}; + +boolean ntlm_authenticate(rdpNtlm* ntlm); + +boolean ntlm_client_init(rdpNtlm* ntlm, boolean confidentiality, char* user, char* domain, char* password); +void ntlm_client_uninit(rdpNtlm* ntlm); + +rdpNtlm* ntlm_new(); +void ntlm_free(rdpNtlm* ntlm); + +boolean rpc_connect(rdpRpc* rpc); + +boolean rpc_ntlm_http_out_connect(rdpRpc* rpc); +boolean rpc_ntlm_http_in_connect(rdpRpc* rpc); + +void rpc_pdu_header_read(STREAM* s, RPC_PDU_HEADER* header); + +int rpc_out_write(rdpRpc* rpc, uint8* data, int length); +int rpc_in_write(rdpRpc* rpc, uint8* data, int length); + +int rpc_out_read(rdpRpc* rpc, uint8* data, int length); + +int rpc_tsg_write(rdpRpc* rpc, uint8* data, int length, uint16 opnum); +int rpc_read(rdpRpc* rpc, uint8* data, int length); + +rdpRpc* rpc_new(rdpTransport* transport); +void rpc_free(rdpRpc* rpc); + +#ifdef WITH_DEBUG_TSG +#define WITH_DEBUG_RPC +#endif + +#ifdef WITH_DEBUG_RPC +#define DEBUG_RPC(fmt, ...) DEBUG_CLASS(RPC, fmt, ## __VA_ARGS__) +#else +#define DEBUG_RPC(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) +#endif + +#endif /* FREERDP_CORE_RPC_H */ diff --git a/libfreerdp-core/rts.c b/libfreerdp-core/rts.c new file mode 100644 index 000000000..2ad76fcc1 --- /dev/null +++ b/libfreerdp-core/rts.c @@ -0,0 +1,709 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Request To Send (RTS) PDUs + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rts.h" + +/** + * Connection Establishment\n + * + * Client Outbound Proxy Inbound Proxy Server\n + * | | | |\n + * |-----------------IN Channel Request--------------->| |\n + * |---OUT Channel Request-->| |<-Legacy Server Response-|\n + * | |<--------------Legacy Server Response--------------|\n + * | | | |\n + * |---------CONN_A1-------->| | |\n + * |----------------------CONN_B1--------------------->| |\n + * | |----------------------CONN_A2--------------------->|\n + * | | | |\n + * |<--OUT Channel Response--| |---------CONN_B2-------->|\n + * |<--------CONN_A3---------| | |\n + * | |<---------------------CONN_C1----------------------|\n + * | | |<--------CONN_B3---------|\n + * |<--------CONN_C2---------| | |\n + * | | | |\n + * + */ + +boolean rts_connect(rdpRpc* rpc) +{ + int status; + RTS_PDU rts_pdu; + HttpResponse* http_response; + + if (!rpc_ntlm_http_out_connect(rpc)) + { + printf("rpc_out_connect_http error!\n"); + return false; + } + + if (!rts_send_CONN_A1_pdu(rpc)) + { + printf("rpc_send_CONN_A1_pdu error!\n"); + return false; + } + + if (!rpc_ntlm_http_in_connect(rpc)) + { + printf("rpc_in_connect_http error!\n"); + return false; + } + + if (!rts_send_CONN_B1_pdu(rpc)) + { + printf("rpc_send_CONN_B1_pdu error!\n"); + return false; + } + + /* Receive OUT Channel Response */ + http_response = http_response_recv(rpc->tls_out); + + if (http_response->StatusCode != 200) + { + printf("rts_connect error!\n"); + http_response_print(http_response); + return false; + } + + http_response_print(http_response); + + http_response_free(http_response); + + /* Receive CONN_A3 RTS PDU */ + status = rts_recv_pdu(rpc, &rts_pdu); + + /* Receive CONN_C2 RTS PDU */ + status = rts_recv_pdu(rpc, &rts_pdu); + + return true; +} + +#ifdef WITH_DEBUG_RTS + +static const char* const RTS_CMD_STRINGS[] = +{ + "ReceiveWindowSize", + "FlowControlAck", + "ConnectionTimeout", + "Cookie", + "ChannelLifetime", + "ClientKeepalive", + "Version", + "Empty", + "Padding", + "NegativeANCE", + "ANCE", + "ClientAddress", + "AssociationGroupId", + "Destination", + "PingTrafficSentNotify" +}; + +#endif + +void rts_pdu_header_read(STREAM* s, RTS_PDU_HEADER* header) +{ + stream_read_uint8(s, header->rpc_vers); /* rpc_vers (1 byte) */ + stream_read_uint8(s, header->rpc_vers_minor); /* rpc_vers_minor (1 byte) */ + stream_read_uint8(s, header->ptype); /* PTYPE (1 byte) */ + stream_read_uint8(s, header->pfc_flags); /* pfc_flags (1 byte) */ + stream_read_uint8(s, header->packed_drep[0]); /* packet_drep[0] (1 byte) */ + stream_read_uint8(s, header->packed_drep[1]); /* packet_drep[1] (1 byte) */ + stream_read_uint8(s, header->packed_drep[2]); /* packet_drep[2] (1 byte) */ + stream_read_uint8(s, header->packed_drep[3]); /* packet_drep[3] (1 byte) */ + stream_read_uint16(s, header->frag_length); /* frag_length (2 bytes) */ + stream_read_uint16(s, header->auth_length); /* auth_length (2 bytes) */ + stream_read_uint32(s, header->call_id); /* call_id (4 bytes) */ + stream_read_uint16(s, header->flags); /* flags (2 bytes) */ + stream_read_uint16(s, header->numberOfCommands); /* numberOfCommands (2 bytes) */ +} + +void rts_pdu_header_write(STREAM* s, RTS_PDU_HEADER* header) +{ + stream_write_uint8(s, header->rpc_vers); /* rpc_vers (1 byte) */ + stream_write_uint8(s, header->rpc_vers_minor); /* rpc_vers_minor (1 byte) */ + stream_write_uint8(s, header->ptype); /* PTYPE (1 byte) */ + stream_write_uint8(s, header->pfc_flags); /* pfc_flags (1 byte) */ + stream_write_uint8(s, header->packed_drep[0]); /* packet_drep[0] (1 byte) */ + stream_write_uint8(s, header->packed_drep[1]); /* packet_drep[1] (1 byte) */ + stream_write_uint8(s, header->packed_drep[2]); /* packet_drep[2] (1 byte) */ + stream_write_uint8(s, header->packed_drep[3]); /* packet_drep[3] (1 byte) */ + stream_write_uint16(s, header->frag_length); /* frag_length (2 bytes) */ + stream_write_uint16(s, header->auth_length); /* auth_length (2 bytes) */ + stream_write_uint32(s, header->call_id); /* call_id (4 bytes) */ + stream_write_uint16(s, header->flags); /* flags (2 bytes) */ + stream_write_uint16(s, header->numberOfCommands); /* numberOfCommands (2 bytes) */ +} + +void rts_receive_window_size_command_read(rdpRpc* rpc, STREAM* s) +{ + stream_seek_uint32(s); /* ReceiveWindowSize (4 bytes) */ +} + +void rts_receive_window_size_command_write(STREAM* s, uint32 ReceiveWindowSize) +{ + stream_write_uint32(s, RTS_CMD_RECEIVE_WINDOW_SIZE); /* CommandType (4 bytes) */ + stream_write_uint32(s, ReceiveWindowSize); /* ReceiveWindowSize (4 bytes) */ +} + +void rts_flow_control_ack_command_read(rdpRpc* rpc, STREAM* s) +{ + /* Ack (24 bytes) */ + stream_seek_uint32(s); /* BytesReceived (4 bytes) */ + stream_seek_uint32(s); /* AvailableWindow (4 bytes) */ + stream_seek(s, 16); /* ChannelCookie (16 bytes) */ +} + +void rts_flow_control_ack_command_write(STREAM* s, uint32 BytesReceived, uint32 AvailableWindow, uint8* ChannelCookie) +{ + stream_write_uint32(s, RTS_CMD_FLOW_CONTROL_ACK); /* CommandType (4 bytes) */ + + /* Ack (24 bytes) */ + stream_write_uint32(s, BytesReceived); /* BytesReceived (4 bytes) */ + stream_write_uint32(s, AvailableWindow); /* AvailableWindow (4 bytes) */ + stream_write(s, ChannelCookie, 16); /* ChannelCookie (16 bytes) */ +} + +void rts_connection_timeout_command_read(rdpRpc* rpc, STREAM* s) +{ + stream_seek_uint32(s); /* ConnectionTimeout (4 bytes) */ +} + +void rts_connection_timeout_command_write(STREAM* s, uint32 ConnectionTimeout) +{ + stream_write_uint32(s, RTS_CMD_CONNECTION_TIMEOUT); /* CommandType (4 bytes) */ + stream_write_uint32(s, ConnectionTimeout); /* ConnectionTimeout (4 bytes) */ +} + +void rts_cookie_command_read(rdpRpc* rpc, STREAM* s) +{ + stream_seek(s, 16); /* Cookie (16 bytes) */ +} + +void rts_cookie_command_write(STREAM* s, uint8* Cookie) +{ + stream_write_uint32(s, RTS_CMD_COOKIE); /* CommandType (4 bytes) */ + stream_write(s, Cookie, 16); /* Cookie (16 bytes) */ +} + +void rts_channel_lifetime_command_read(rdpRpc* rpc, STREAM* s) +{ + stream_seek_uint32(s); /* ChannelLifetime (4 bytes) */ +} + +void rts_channel_lifetime_command_write(STREAM* s, uint32 ChannelLifetime) +{ + stream_write_uint32(s, RTS_CMD_CHANNEL_LIFETIME); /* CommandType (4 bytes) */ + stream_write_uint32(s, ChannelLifetime); /* ChannelLifetime (4 bytes) */ +} + +void rts_client_keepalive_command_read(rdpRpc* rpc, STREAM* s) +{ + stream_seek_uint32(s); /* ClientKeepalive (4 bytes) */ +} + +void rts_client_keepalive_command_write(STREAM* s, uint32 ClientKeepalive) +{ + stream_write_uint32(s, RTS_CMD_CLIENT_KEEPALIVE); /* CommandType (4 bytes) */ + stream_write_uint32(s, ClientKeepalive); /* ClientKeepalive (4 bytes) */ +} + +void rts_version_command_read(rdpRpc* rpc, STREAM* s) +{ + stream_seek_uint32(s); /* Version (4 bytes) */ +} + +void rts_version_command_write(STREAM* s) +{ + stream_write_uint32(s, RTS_CMD_VERSION); /* CommandType (4 bytes) */ + stream_write_uint32(s, 1); /* Version (4 bytes) */ +} + +void rts_empty_command_read(rdpRpc* rpc, STREAM* s) +{ + +} + +void rts_empty_command_write(STREAM* s) +{ + stream_write_uint32(s, RTS_CMD_EMPTY); /* CommandType (4 bytes) */ +} + +void rts_padding_command_read(rdpRpc* rpc, STREAM* s) +{ + uint32 ConformanceCount; + + stream_read_uint32(s, ConformanceCount); /* ConformanceCount (4 bytes) */ + stream_seek(s, ConformanceCount); /* Padding (variable) */ +} + +void rts_padding_command_write(STREAM* s, uint32 ConformanceCount) +{ + stream_write_uint32(s, ConformanceCount); /* ConformanceCount (4 bytes) */ + stream_write_zero(s, ConformanceCount); /* Padding (variable) */ +} + +void rts_negative_ance_command_read(rdpRpc* rpc, STREAM* s) +{ + +} + +void rts_negative_ance_command_write(STREAM* s) +{ + stream_write_uint32(s, RTS_CMD_NEGATIVE_ANCE); /* CommandType (4 bytes) */ +} + +void rts_ance_command_read(rdpRpc* rpc, STREAM* s) +{ + +} + +void rts_ance_command_write(STREAM* s) +{ + stream_write_uint32(s, RTS_CMD_ANCE); /* CommandType (4 bytes) */ +} + +void rts_client_address_command_read(rdpRpc* rpc, STREAM* s) +{ + uint32 AddressType; + + stream_read_uint32(s, AddressType); /* AddressType (4 bytes) */ + + if (AddressType == 0) + { + stream_seek(s, 4); /* ClientAddress (4 bytes) */ + } + else + { + stream_seek(s, 16); /* ClientAddress (16 bytes) */ + } + + stream_seek(s, 12); /* padding (12 bytes) */ +} + +void rts_client_address_command_write(STREAM* s, uint32 AddressType, uint8* ClientAddress) +{ + stream_write_uint32(s, RTS_CMD_CLIENT_ADDRESS); /* CommandType (4 bytes) */ + stream_write_uint32(s, AddressType); /* AddressType (4 bytes) */ + + if (AddressType == 0) + { + stream_write(s, ClientAddress, 4); /* ClientAddress (4 bytes) */ + } + else + { + stream_write(s, ClientAddress, 16); /* ClientAddress (16 bytes) */ + } + + stream_write_zero(s, 12); /* padding (12 bytes) */ +} + +void rts_association_group_id_command_read(rdpRpc* rpc, STREAM* s) +{ + stream_seek(s, 16); /* AssociationGroupId (16 bytes) */ +} + +void rts_association_group_id_command_write(STREAM* s, uint8* associationGroupId) +{ + stream_write_uint32(s, RTS_CMD_ASSOCIATION_GROUP_ID); /* CommandType (4 bytes) */ + stream_write(s, associationGroupId, 16); /* AssociationGroupId (16 bytes) */ +} + +void rts_destination_command_read(rdpRpc* rpc, STREAM* s) +{ + stream_seek_uint32(s); /* Destination (4 bytes) */ +} + +void rts_destination_command_write(STREAM* s, uint32 Destination) +{ + stream_write_uint32(s, RTS_CMD_DESTINATION); /* CommandType (4 bytes) */ + stream_write_uint32(s, Destination); /* Destination (4 bytes) */ +} + +void rts_ping_traffic_sent_notify_command_read(rdpRpc* rpc, STREAM* s) +{ + stream_seek_uint32(s); /* PingTrafficSent (4 bytes) */ +} + +void rts_ping_traffic_sent_notify_command_write(STREAM* s, uint32 PingTrafficSent) +{ + stream_write_uint32(s, RTS_CMD_PING_TRAFFIC_SENT_NOTIFY); /* CommandType (4 bytes) */ + stream_write_uint32(s, PingTrafficSent); /* PingTrafficSent (4 bytes) */ +} + +void rpc_generate_cookie(uint8* cookie) +{ + RAND_pseudo_bytes(cookie, 16); +} + +boolean rts_send_CONN_A1_pdu(rdpRpc* rpc) +{ + STREAM* s; + RTS_PDU_HEADER header; + uint32 ReceiveWindowSize; + uint8* OUTChannelCookie; + uint8* VirtualConnectionCookie; + + header.rpc_vers = 5; + header.rpc_vers_minor = 0; + header.ptype = PTYPE_RTS; + header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; + header.packed_drep[0] = 0x10; + header.packed_drep[1] = 0x00; + header.packed_drep[2] = 0x00; + header.packed_drep[3] = 0x00; + header.frag_length = 76; + header.auth_length = 0; + header.call_id = 0; + header.flags = 0; + header.numberOfCommands = 4; + + DEBUG_RPC("Sending CONN_A1 RTS PDU"); + + s = stream_new(header.frag_length); + + rpc_generate_cookie((uint8*) &(rpc->VirtualConnection->Cookie)); + rpc_generate_cookie((uint8*) &(rpc->VirtualConnection->DefaultOutChannelCookie)); + + VirtualConnectionCookie = (uint8*) &(rpc->VirtualConnection->Cookie); + OUTChannelCookie = (uint8*) &(rpc->VirtualConnection->DefaultOutChannelCookie); + ReceiveWindowSize = rpc->VirtualConnection->DefaultOutChannel->ReceiveWindow; + + rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */ + rts_version_command_write(s); /* Version (8 bytes) */ + rts_cookie_command_write(s, VirtualConnectionCookie); /* VirtualConnectionCookie (20 bytes) */ + rts_cookie_command_write(s, OUTChannelCookie); /* OUTChannelCookie (20 bytes) */ + rts_receive_window_size_command_write(s, ReceiveWindowSize); /* ReceiveWindowSize (8 bytes) */ + stream_seal(s); + + rpc_out_write(rpc, s->data, s->size); + + stream_free(s); + + return true; +} + +boolean rts_send_CONN_B1_pdu(rdpRpc* rpc) +{ + STREAM* s; + RTS_PDU_HEADER header; + uint8* INChannelCookie; + uint8* AssociationGroupId; + uint8* VirtualConnectionCookie; + + header.rpc_vers = 5; + header.rpc_vers_minor = 0; + header.ptype = PTYPE_RTS; + header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; + header.packed_drep[0] = 0x10; + header.packed_drep[1] = 0x00; + header.packed_drep[2] = 0x00; + header.packed_drep[3] = 0x00; + header.frag_length = 104; + header.auth_length = 0; + header.call_id = 0; + header.flags = 0; + header.numberOfCommands = 6; + + DEBUG_RPC("Sending CONN_B1 RTS PDU"); + + s = stream_new(header.frag_length); + + rpc_generate_cookie((uint8*) &(rpc->VirtualConnection->DefaultInChannelCookie)); + rpc_generate_cookie((uint8*) &(rpc->VirtualConnection->AssociationGroupId)); + + VirtualConnectionCookie = (uint8*) &(rpc->VirtualConnection->Cookie); + INChannelCookie = (uint8*) &(rpc->VirtualConnection->DefaultInChannelCookie); + AssociationGroupId = (uint8*) &(rpc->VirtualConnection->AssociationGroupId); + + rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */ + rts_version_command_write(s); /* Version (8 bytes) */ + rts_cookie_command_write(s, VirtualConnectionCookie); /* VirtualConnectionCookie (20 bytes) */ + rts_cookie_command_write(s, INChannelCookie); /* INChannelCookie (20 bytes) */ + rts_channel_lifetime_command_write(s, 0x40000000); /* ChannelLifetime (8 bytes) */ + rts_client_keepalive_command_write(s, 0x000493E0); /* ClientKeepalive (8 bytes) */ + rts_association_group_id_command_write(s, AssociationGroupId); /* AssociationGroupId (20 bytes) */ + stream_seal(s); + + rpc_in_write(rpc, s->data, s->size); + + stream_free(s); + + return true; +} + +boolean rts_send_keep_alive_pdu(rdpRpc* rpc) +{ + STREAM* s; + RTS_PDU_HEADER header; + + header.rpc_vers = 5; + header.rpc_vers_minor = 0; + header.ptype = PTYPE_RTS; + header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; + header.packed_drep[0] = 0x10; + header.packed_drep[1] = 0x00; + header.packed_drep[2] = 0x00; + header.packed_drep[3] = 0x00; + header.frag_length = 28; + header.auth_length = 0; + header.call_id = 0; + header.flags = 2; + header.numberOfCommands = 1; + + DEBUG_RPC("Sending Keep-Alive RTS PDU"); + + s = stream_new(header.frag_length); + rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */ + rts_client_keepalive_command_write(s, 0x00007530); /* ClientKeepalive (8 bytes) */ + stream_seal(s); + + rpc_in_write(rpc, s->data, s->size); + + stream_free(s); + + return true; +} + +boolean rts_send_flow_control_ack_pdu(rdpRpc* rpc) +{ + STREAM* s; + RTS_PDU_HEADER header; + uint32 BytesReceived; + uint32 AvailableWindow; + uint8* ChannelCookie; + + header.rpc_vers = 5; + header.rpc_vers_minor = 0; + header.ptype = PTYPE_RTS; + header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; + header.packed_drep[0] = 0x10; + header.packed_drep[1] = 0x00; + header.packed_drep[2] = 0x00; + header.packed_drep[3] = 0x00; + header.frag_length = 56; + header.auth_length = 0; + header.call_id = 0; + header.flags = 2; + header.numberOfCommands = 2; + + DEBUG_RPC("Sending FlowControlAck RTS PDU"); + + BytesReceived = rpc->VirtualConnection->DefaultOutChannel->BytesReceived; + AvailableWindow = rpc->VirtualConnection->DefaultOutChannel->ReceiverAvailableWindow; + ChannelCookie = (uint8*) &(rpc->VirtualConnection->DefaultOutChannelCookie); + + s = stream_new(header.frag_length); + rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */ + rts_destination_command_write(s, FDOutProxy); /* Destination Command (8 bytes) */ + + /* FlowControlAck Command (28 bytes) */ + rts_flow_control_ack_command_write(s, BytesReceived, AvailableWindow, ChannelCookie); + + stream_seal(s); + + rpc_in_write(rpc, s->data, s->size); + + stream_free(s); + + return true; +} + +boolean rts_send_ping_pdu(rdpRpc* rpc) +{ + STREAM* s; + RTS_PDU_HEADER header; + + header.rpc_vers = 5; + header.rpc_vers_minor = 0; + header.ptype = PTYPE_RTS; + header.pfc_flags = PFC_FIRST_FRAG | PFC_LAST_FRAG; + header.packed_drep[0] = 0x10; + header.packed_drep[1] = 0x00; + header.packed_drep[2] = 0x00; + header.packed_drep[3] = 0x00; + header.frag_length = 20; + header.auth_length = 0; + header.call_id = 0; + header.flags = 1; + header.numberOfCommands = 0; + + DEBUG_RPC("Sending Ping RTS PDU"); + + s = stream_new(header.frag_length); + rts_pdu_header_write(s, &header); /* RTS Header (20 bytes) */ + stream_seal(s); + + rpc_in_write(rpc, s->data, s->size); + + stream_free(s); + + return true; +} + +int rts_recv_pdu_commands(rdpRpc* rpc, RTS_PDU* rts_pdu) +{ + int i; + STREAM* s; + uint32 CommandType; + + s = stream_new(0); + stream_attach(s, rts_pdu->content, rts_pdu->header.frag_length); + + DEBUG_RTS("numberOfCommands:%d", rts_pdu->header.numberOfCommands); + + if (rts_pdu->header.flags & RTS_FLAG_PING) + { + rts_send_keep_alive_pdu(rpc); + return 0; + } + + for (i = 0; i < rts_pdu->header.numberOfCommands; i++) + { + stream_read_uint32(s, CommandType); /* CommandType (4 bytes) */ + + DEBUG_RTS("CommandType: %s (0x%08X)", RTS_CMD_STRINGS[CommandType % 14], CommandType); + + switch (CommandType) + { + case RTS_CMD_RECEIVE_WINDOW_SIZE: + rts_receive_window_size_command_read(rpc, s); + break; + + case RTS_CMD_FLOW_CONTROL_ACK: + rts_flow_control_ack_command_read(rpc, s); + break; + + case RTS_CMD_CONNECTION_TIMEOUT: + rts_connection_timeout_command_read(rpc, s); + break; + + case RTS_CMD_COOKIE: + rts_cookie_command_read(rpc, s); + break; + + case RTS_CMD_CHANNEL_LIFETIME: + rts_channel_lifetime_command_read(rpc, s); + break; + + case RTS_CMD_CLIENT_KEEPALIVE: + rts_client_keepalive_command_read(rpc, s); + break; + + case RTS_CMD_VERSION: + rts_version_command_read(rpc, s); + break; + + case RTS_CMD_EMPTY: + rts_empty_command_read(rpc, s); + break; + + case RTS_CMD_PADDING: + rts_padding_command_read(rpc, s); + break; + + case RTS_CMD_NEGATIVE_ANCE: + rts_negative_ance_command_read(rpc, s); + break; + + case RTS_CMD_ANCE: + rts_ance_command_read(rpc, s); + break; + + case RTS_CMD_CLIENT_ADDRESS: + rts_client_address_command_read(rpc, s); + break; + + case RTS_CMD_ASSOCIATION_GROUP_ID: + rts_association_group_id_command_read(rpc, s); + break; + + case RTS_CMD_DESTINATION: + rts_destination_command_read(rpc, s); + break; + + case RTS_CMD_PING_TRAFFIC_SENT_NOTIFY: + rts_ping_traffic_sent_notify_command_read(rpc, s); + break; + + default: + printf("Error: Unknown RTS Command Type: 0x%x\n", CommandType); + return -1; + break; + } + } + + stream_detach(s); + stream_free(s); + + return 0; +} + +int rts_recv_pdu(rdpRpc* rpc, RTS_PDU* rts_pdu) +{ + STREAM* s; + int status; + int length; + uint8 header_buffer[20]; + rdpTls* tls_out = rpc->tls_out; + + /* read first 20 bytes to get RTS PDU Header */ + status = tls_read(tls_out, (uint8*) &header_buffer, 20); + + if (status <= 0) + { + printf("rts_recv error\n"); + return status; + } + + s = stream_new(0); + stream_attach(s, header_buffer, 20); + + rts_pdu_header_read(s, &(rts_pdu->header)); + + stream_detach(s); + stream_free(s); + + length = rts_pdu->header.frag_length - 20; + rts_pdu->content = (uint8*) xmalloc(length); + + status = tls_read(tls_out, rts_pdu->content, length); + + if (status < 0) + { + printf("rts_recv error\n"); + return status; + } + + if (rts_pdu->header.ptype != PTYPE_RTS) + { + printf("rts_recv error: unexpected ptype:%d\n", rts_pdu->header.ptype); + return -1; + } + +#ifdef WITH_DEBUG_RTS + printf("rts_recv(): length: %d\n", length); + freerdp_hexdump(rts_pdu->content, length); + printf("\n"); +#endif + + rts_recv_pdu_commands(rpc, rts_pdu); + + return rts_pdu->header.frag_length; +} diff --git a/libfreerdp-core/rts.h b/libfreerdp-core/rts.h new file mode 100644 index 000000000..b7ce7ae2b --- /dev/null +++ b/libfreerdp-core/rts.h @@ -0,0 +1,168 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Request To Send (RTS) PDUs + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CORE_RTS_H +#define FREERDP_CORE_RTS_H + +#include "rpc.h" + +#include "config.h" + +#include +#include +#include + +#define PTYPE_REQUEST 0x00 +#define PTYPE_PING 0x01 +#define PTYPE_RESPONSE 0x02 +#define PTYPE_FAULT 0x03 +#define PTYPE_WORKING 0x04 +#define PTYPE_NOCALL 0x05 +#define PTYPE_REJECT 0x06 +#define PTYPE_ACK 0x07 +#define PTYPE_CL_CANCEL 0x08 +#define PTYPE_FACK 0x09 +#define PTYPE_CANCEL_ACK 0x0A +#define PTYPE_BIND 0x0B +#define PTYPE_BIND_ACK 0x0C +#define PTYPE_BIND_NAK 0x0D +#define PTYPE_ALTER_CONTEXT 0x0E +#define PTYPE_ALTER_CONTEXT_RESP 0x0F +#define PTYPE_RPC_AUTH_3 0x10 +#define PTYPE_SHUTDOWN 0x11 +#define PTYPE_CO_CANCEL 0x12 +#define PTYPE_ORPHANED 0x13 +#define PTYPE_RTS 0x14 + +#define PFC_FIRST_FRAG 0x01 +#define PFC_LAST_FRAG 0x02 +#define PFC_PENDING_CANCEL 0x04 +#define PFC_RESERVED_1 0x08 +#define PFC_CONC_MPX 0x10 +#define PFC_DID_NOT_EXECUTE 0x20 +#define PFC_MAYBE 0x40 +#define PFC_OBJECT_UUID 0x80 + +#define RTS_FLAG_NONE 0x0000 +#define RTS_FLAG_PING 0x0001 +#define RTS_FLAG_OTHER_CMD 0x0002 +#define RTS_FLAG_RECYCLE_CHANNEL 0x0004 +#define RTS_FLAG_IN_CHANNEL 0x0008 +#define RTS_FLAG_OUT_CHANNEL 0x0010 +#define RTS_FLAG_EOF 0x0020 +#define RTS_FLAG_ECHO 0x0040 + +#define RTS_CMD_RECEIVE_WINDOW_SIZE 0x00000000 +#define RTS_CMD_FLOW_CONTROL_ACK 0x00000001 +#define RTS_CMD_CONNECTION_TIMEOUT 0x00000002 +#define RTS_CMD_COOKIE 0x00000003 +#define RTS_CMD_CHANNEL_LIFETIME 0x00000004 +#define RTS_CMD_CLIENT_KEEPALIVE 0x00000005 +#define RTS_CMD_VERSION 0x00000006 +#define RTS_CMD_EMPTY 0x00000007 +#define RTS_CMD_PADDING 0x00000008 +#define RTS_CMD_NEGATIVE_ANCE 0x00000009 +#define RTS_CMD_ANCE 0x0000000A +#define RTS_CMD_CLIENT_ADDRESS 0x0000000B +#define RTS_CMD_ASSOCIATION_GROUP_ID 0x0000000C +#define RTS_CMD_DESTINATION 0x0000000D +#define RTS_CMD_PING_TRAFFIC_SENT_NOTIFY 0x0000000E + +#define FDClient 0x00000000 +#define FDInProxy 0x00000001 +#define FDServer 0x00000002 +#define FDOutProxy 0x00000003 + +struct _rts_pdu_header +{ + uint8 rpc_vers; + uint8 rpc_vers_minor; + uint8 ptype; + uint8 pfc_flags; + uint8 packed_drep[4]; + uint16 frag_length; + uint16 auth_length; + uint32 call_id; + uint16 flags; + uint16 numberOfCommands; +}; +typedef struct _rts_pdu_header RTS_PDU_HEADER; + +struct _rts_pdu +{ + RTS_PDU_HEADER header; + uint8* content; +}; +typedef struct _rts_pdu RTS_PDU; + +boolean rts_connect(rdpRpc* rpc); + +void rts_pdu_header_read(STREAM* s, RTS_PDU_HEADER* header); +void rts_pdu_header_write(STREAM* s, RTS_PDU_HEADER* header); + +void rts_receive_window_size_command_read(rdpRpc* rpc, STREAM* s); +void rts_receive_window_size_command_write(STREAM* s, uint32 ReceiveWindowSize); +void rts_flow_control_ack_command_read(rdpRpc* rpc, STREAM* s); +void rts_flow_control_ack_command_write(STREAM* s, uint32 BytesReceived, uint32 AvailableWindow, uint8* ChannelCookie); +void rts_connection_timeout_command_read(rdpRpc* rpc, STREAM* s); +void rts_connection_timeout_command_write(STREAM* s, uint32 ConnectionTimeout); +void rts_cookie_command_read(rdpRpc* rpc, STREAM* s); +void rts_cookie_command_write(STREAM* s, uint8* Cookie); +void rts_channel_lifetime_command_read(rdpRpc* rpc, STREAM* s); +void rts_channel_lifetime_command_write(STREAM* s, uint32 ChannelLifetime); +void rts_client_keepalive_command_read(rdpRpc* rpc, STREAM* s); +void rts_client_keepalive_command_write(STREAM* s, uint32 ClientKeepalive); +void rts_version_command_read(rdpRpc* rpc, STREAM* s); +void rts_version_command_write(STREAM* s); +void rts_empty_command_read(rdpRpc* rpc, STREAM* s); +void rts_empty_command_write(STREAM* s); +void rts_padding_command_read(rdpRpc* rpc, STREAM* s); +void rts_padding_command_write(STREAM* s, uint32 ConformanceCount); +void rts_negative_ance_command_read(rdpRpc* rpc, STREAM* s); +void rts_negative_ance_command_write(STREAM* s); +void rts_ance_command_read(rdpRpc* rpc, STREAM* s); +void rts_ance_command_write(STREAM* s); +void rts_client_address_command_read(rdpRpc* rpc, STREAM* s); +void rts_client_address_command_write(STREAM* s, uint32 AddressType, uint8* ClientAddress); +void rts_association_group_id_command_read(rdpRpc* rpc, STREAM* s); +void rts_association_group_id_command_write(STREAM* s, uint8* AssociationGroupId); +void rts_destination_command_read(rdpRpc* rpc, STREAM* s); +void rts_destination_command_write(STREAM* s, uint32 Destination); +void rts_ping_traffic_sent_notify_command_read(rdpRpc* rpc, STREAM* s); +void rts_ping_traffic_sent_notify_command_write(STREAM* s, uint32 PingTrafficSent); + +boolean rts_send_CONN_A1_pdu(rdpRpc* rpc); +boolean rts_send_CONN_B1_pdu(rdpRpc* rpc); +boolean rts_send_keep_alive_pdu(rdpRpc* rpc); +boolean rts_send_flow_control_ack_pdu(rdpRpc* rpc); +boolean rts_send_ping_pdu(rdpRpc* rpc); + +int rts_recv_pdu(rdpRpc* rpc, RTS_PDU* rts_pdu); + +#ifdef WITH_DEBUG_TSG +#define WITH_DEBUG_RTS +#endif + +#ifdef WITH_DEBUG_RTS +#define DEBUG_RTS(fmt, ...) DEBUG_CLASS(RTS, fmt, ## __VA_ARGS__) +#else +#define DEBUG_RTS(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) +#endif + +#endif /* FREERDP_CORE_RTS_H */ diff --git a/libfreerdp-core/tcp.h b/libfreerdp-core/tcp.h index 1db16959a..45c32a83c 100644 --- a/libfreerdp-core/tcp.h +++ b/libfreerdp-core/tcp.h @@ -21,7 +21,7 @@ #ifndef __TCP_H #define __TCP_H -#include +#include #include #include diff --git a/libfreerdp-core/transport.c b/libfreerdp-core/transport.c index 06dab0ee0..46c21652d 100644 --- a/libfreerdp-core/transport.c +++ b/libfreerdp-core/transport.c @@ -39,7 +39,7 @@ #include "fastpath.h" #include "transport.h" -#include +#include #define BUFFER_SIZE 16384 @@ -59,11 +59,6 @@ STREAM* transport_send_stream_init(rdpTransport* transport, int size) return s; } -boolean transport_connect(rdpTransport* transport, const char* hostname, uint16 port) -{ - return tcp_connect(transport->tcp, hostname, port); -} - void transport_attach(rdpTransport* transport, int sockfd) { transport->tcp->sockfd = sockfd; @@ -143,6 +138,61 @@ boolean transport_connect_nla(rdpTransport* transport) return true; } +boolean transport_tsg_connect(rdpTransport* transport, const char* hostname, uint16 port) +{ + rdpTsg* tsg = tsg_new(transport); + + tsg->transport = transport; + transport->tsg = tsg; + + if (transport->tls_in == NULL) + transport->tls_in = tls_new(transport->settings); + + transport->tls_in->sockfd = transport->tcp_in->sockfd; + + if (transport->tls_out == NULL) + transport->tls_out = tls_new(transport->settings); + + transport->tls_out->sockfd = transport->tcp_out->sockfd; + + if (tls_connect(transport->tls_in) != true) + return false; + + if (tls_connect(transport->tls_out) != true) + return false; + + if (!tsg_connect(tsg, hostname, port)) + return false; + + return true; +} + +boolean transport_connect(rdpTransport* transport, const char* hostname, uint16 port) +{ + boolean status = false; + rdpSettings* settings = transport->settings; + + if (transport->settings->ts_gateway) + { + transport->layer = TRANSPORT_LAYER_TSG; + transport->tcp_out = tcp_new(settings); + + status = tcp_connect(transport->tcp_in, settings->tsg_hostname, 443); + + if (status) + status = tcp_connect(transport->tcp_out, settings->tsg_hostname, 443); + + if (status) + status = transport_tsg_connect(transport, hostname, port); + } + else + { + status = tcp_connect(transport->tcp, hostname, port); + } + + return status; +} + boolean transport_accept_rdp(rdpTransport* transport) { /* RDP encryption */ @@ -211,6 +261,8 @@ int transport_read(rdpTransport* transport, STREAM* s) status = tls_read(transport->tls, stream_get_tail(s), stream_get_left(s)); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_read(transport->tcp, stream_get_tail(s), stream_get_left(s)); + else if (transport->layer == TRANSPORT_LAYER_TSG) + status = tsg_read(transport->tsg, stream_get_tail(s), stream_get_left(s)); if (status == 0 && transport->blocking) { @@ -269,6 +321,8 @@ int transport_write(rdpTransport* transport, STREAM* s) status = tls_write(transport->tls, stream_get_tail(s), length); else if (transport->layer == TRANSPORT_LAYER_TCP) status = tcp_write(transport->tcp, stream_get_tail(s), length); + else if (transport->layer == TRANSPORT_LAYER_TSG) + status = tsg_write(transport->tsg, stream_get_tail(s), length); if (status < 0) break; /* error occurred */ @@ -424,6 +478,8 @@ rdpTransport* transport_new(rdpSettings* settings) if (transport != NULL) { transport->tcp = tcp_new(settings); + transport->tcp_in = tcp_new(settings); + transport->settings = settings; /* a small 0.1ms delay when transport is blocking. */ @@ -453,9 +509,13 @@ void transport_free(rdpTransport* transport) stream_free(transport->recv_stream); stream_free(transport->send_stream); wait_obj_free(transport->recv_event); + if (transport->tls) tls_free(transport->tls); + tcp_free(transport->tcp); + tsg_free(transport->tsg); + xfree(transport); } } diff --git a/libfreerdp-core/transport.h b/libfreerdp-core/transport.h index 97ba4ddaf..e774cadce 100644 --- a/libfreerdp-core/transport.h +++ b/libfreerdp-core/transport.h @@ -24,14 +24,17 @@ typedef enum { TRANSPORT_LAYER_TCP, TRANSPORT_LAYER_TLS, + TRANSPORT_LAYER_TSG, TRANSPORT_LAYER_CLOSED } TRANSPORT_LAYER; typedef struct rdp_transport rdpTransport; #include "tcp.h" +#include "tsg.h" + +#include #include -#include #include #include @@ -48,8 +51,13 @@ struct rdp_transport TRANSPORT_LAYER layer; struct rdp_tcp* tcp; struct rdp_tls* tls; - struct rdp_settings* settings; + struct rdp_tsg* tsg; + struct rdp_tcp* tcp_in; + struct rdp_tcp* tcp_out; + struct rdp_tls* tls_in; + struct rdp_tls* tls_out; struct rdp_credssp* credssp; + struct rdp_settings* settings; uint32 usleep_interval; void* recv_extra; STREAM* recv_buffer; @@ -67,6 +75,7 @@ boolean transport_disconnect(rdpTransport* transport); boolean transport_connect_rdp(rdpTransport* transport); boolean transport_connect_tls(rdpTransport* transport); boolean transport_connect_nla(rdpTransport* transport); +boolean transport_connect_tsg(rdpTransport* transport); boolean transport_accept_rdp(rdpTransport* transport); boolean transport_accept_tls(rdpTransport* transport); boolean transport_accept_nla(rdpTransport* transport); diff --git a/libfreerdp-core/tsg.c b/libfreerdp-core/tsg.c new file mode 100644 index 000000000..f340f2bac --- /dev/null +++ b/libfreerdp-core/tsg.c @@ -0,0 +1,2032 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Terminal Server Gateway (TSG) + * + * Copyright 2012 Fujitsu Technology Solutions GmbH + * Copyright 2012 Dmitrij Jasnov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "tsg.h" + +/** + * RPC Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378623/ + * Remote Procedure Call: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378651/ + * RPC NDR Interface Reference: http://msdn.microsoft.com/en-us/library/windows/desktop/hh802752/ + */ + +/** + * START OF GENERATED CODE + */ + +#define TYPE_FORMAT_STRING_SIZE 833 +#define PROC_FORMAT_STRING_SIZE 449 +#define EXPR_FORMAT_STRING_SIZE 1 +#define TRANSMIT_AS_TABLE_SIZE 0 +#define WIRE_MARSHAL_TABLE_SIZE 0 + +typedef struct _ms2Dtsgu_MIDL_TYPE_FORMAT_STRING + { + short Pad; + unsigned char Format[ TYPE_FORMAT_STRING_SIZE ]; + } ms2Dtsgu_MIDL_TYPE_FORMAT_STRING; + +typedef struct _ms2Dtsgu_MIDL_PROC_FORMAT_STRING + { + short Pad; + unsigned char Format[ PROC_FORMAT_STRING_SIZE ]; + } ms2Dtsgu_MIDL_PROC_FORMAT_STRING; + +typedef struct _ms2Dtsgu_MIDL_EXPR_FORMAT_STRING + { + long Pad; + unsigned char Format[ EXPR_FORMAT_STRING_SIZE ]; + } ms2Dtsgu_MIDL_EXPR_FORMAT_STRING; + + +static const RPC_SYNTAX_IDENTIFIER _RpcTransferSyntax = +{{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}; + +static const ms2Dtsgu_MIDL_TYPE_FORMAT_STRING ms2Dtsgu__MIDL_TypeFormatString; +static const ms2Dtsgu_MIDL_PROC_FORMAT_STRING ms2Dtsgu__MIDL_ProcFormatString; +static const ms2Dtsgu_MIDL_EXPR_FORMAT_STRING ms2Dtsgu__MIDL_ExprFormatString; + +#define GENERIC_BINDING_TABLE_SIZE 0 + +static const RPC_CLIENT_INTERFACE TsProxyRpcInterface___RpcClientInterface = + { + sizeof(RPC_CLIENT_INTERFACE), + {{0x44e265dd,0x7daf,0x42cd,{0x85,0x60,0x3c,0xdb,0x6e,0x7a,0x27,0x29}},{1,3}}, + {{0x8A885D04,0x1CEB,0x11C9,{0x9F,0xE8,0x08,0x00,0x2B,0x10,0x48,0x60}},{2,0}}, + 0, + 0, + 0, + 0, + 0, + 0x00000000 + }; +RPC_IF_HANDLE TsProxyRpcInterface_v1_3_c_ifspec = (RPC_IF_HANDLE)& TsProxyRpcInterface___RpcClientInterface; + +static const MIDL_STUB_DESC TsProxyRpcInterface_StubDesc; + +static RPC_BINDING_HANDLE TsProxyRpcInterface__MIDL_AutoBindHandle; + + +void Opnum0NotUsedOnWire( + /* [in] */ handle_t IDL_handle) +{ + + NdrClientCall2( + ( PMIDL_STUB_DESC )&TsProxyRpcInterface_StubDesc, + (PFORMAT_STRING) &ms2Dtsgu__MIDL_ProcFormatString.Format[0], + ( unsigned char * )&IDL_handle); + +} + + +HRESULT TsProxyCreateTunnel( + /* [ref][in] */ PTSG_PACKET tsgPacket, + /* [ref][out] */ PTSG_PACKET *tsgPacketResponse, + /* [out] */ PTUNNEL_CONTEXT_HANDLE_SERIALIZE *tunnelContext, + /* [out] */ unsigned long *tunnelId) +{ + + CLIENT_CALL_RETURN _RetVal; + + _RetVal = NdrClientCall2( + ( PMIDL_STUB_DESC )&TsProxyRpcInterface_StubDesc, + (PFORMAT_STRING) &ms2Dtsgu__MIDL_ProcFormatString.Format[28], + ( unsigned char * )&tsgPacket); + return ( HRESULT )_RetVal.Simple; + +} + + +HRESULT TsProxyAuthorizeTunnel( + /* [in] */ PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, + /* [ref][in] */ PTSG_PACKET tsgPacket, + /* [ref][out] */ PTSG_PACKET *tsgPacketResponse) +{ + + CLIENT_CALL_RETURN _RetVal; + + _RetVal = NdrClientCall2( + ( PMIDL_STUB_DESC )&TsProxyRpcInterface_StubDesc, + (PFORMAT_STRING) &ms2Dtsgu__MIDL_ProcFormatString.Format[82], + ( unsigned char * )&tunnelContext); + return ( HRESULT )_RetVal.Simple; + +} + + +HRESULT TsProxyMakeTunnelCall( + /* [in] */ PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, + /* [in] */ unsigned long procId, + /* [ref][in] */ PTSG_PACKET tsgPacket, + /* [ref][out] */ PTSG_PACKET *tsgPacketResponse) +{ + + CLIENT_CALL_RETURN _RetVal; + + _RetVal = NdrClientCall2( + ( PMIDL_STUB_DESC )&TsProxyRpcInterface_StubDesc, + (PFORMAT_STRING) &ms2Dtsgu__MIDL_ProcFormatString.Format[136], + ( unsigned char * )&tunnelContext); + return ( HRESULT )_RetVal.Simple; + +} + + +HRESULT TsProxyCreateChannel( + /* [in] */ PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, + /* [ref][in] */ PTSENDPOINTINFO tsEndPointInfo, + /* [out] */ PCHANNEL_CONTEXT_HANDLE_SERIALIZE *channelContext, + /* [out] */ unsigned long *channelId) +{ + + CLIENT_CALL_RETURN _RetVal; + + _RetVal = NdrClientCall2( + ( PMIDL_STUB_DESC )&TsProxyRpcInterface_StubDesc, + (PFORMAT_STRING) &ms2Dtsgu__MIDL_ProcFormatString.Format[196], + ( unsigned char * )&tunnelContext); + return ( HRESULT )_RetVal.Simple; + +} + + +void Opnum5NotUsedOnWire( + /* [in] */ handle_t IDL_handle) +{ + + NdrClientCall2( + ( PMIDL_STUB_DESC )&TsProxyRpcInterface_StubDesc, + (PFORMAT_STRING) &ms2Dtsgu__MIDL_ProcFormatString.Format[256], + ( unsigned char * )&IDL_handle); + +} + + +HRESULT TsProxyCloseChannel( + /* [out][in] */ PCHANNEL_CONTEXT_HANDLE_NOSERIALIZE *context) +{ + + CLIENT_CALL_RETURN _RetVal; + + _RetVal = NdrClientCall2( + ( PMIDL_STUB_DESC )&TsProxyRpcInterface_StubDesc, + (PFORMAT_STRING) &ms2Dtsgu__MIDL_ProcFormatString.Format[284], + ( unsigned char * )&context); + return ( HRESULT )_RetVal.Simple; + +} + + +HRESULT TsProxyCloseTunnel( + /* [out][in] */ PTUNNEL_CONTEXT_HANDLE_SERIALIZE *context) +{ + + CLIENT_CALL_RETURN _RetVal; + + _RetVal = NdrClientCall2( + ( PMIDL_STUB_DESC )&TsProxyRpcInterface_StubDesc, + (PFORMAT_STRING) &ms2Dtsgu__MIDL_ProcFormatString.Format[326], + ( unsigned char * )&context); + return ( HRESULT )_RetVal.Simple; + +} + + +DWORD TsProxySetupReceivePipe( + /* [in] */ handle_t IDL_handle, + /* [max_is][in] */ byte pRpcMessage[ ]) +{ + + CLIENT_CALL_RETURN _RetVal; + + _RetVal = NdrClientCall2( + ( PMIDL_STUB_DESC )&TsProxyRpcInterface_StubDesc, + (PFORMAT_STRING) &ms2Dtsgu__MIDL_ProcFormatString.Format[368], + ( unsigned char * )&IDL_handle); + return ( DWORD )_RetVal.Simple; + +} + +static const ms2Dtsgu_MIDL_PROC_FORMAT_STRING ms2Dtsgu__MIDL_ProcFormatString = + { + 0, + { + + /* Procedure Opnum0NotUsedOnWire */ + + 0x0, /* 0 */ + 0x48, /* Old Flags: */ +/* 2 */ NdrFcLong( 0x0 ), /* 0 */ +/* 6 */ NdrFcShort( 0x0 ), /* 0 */ +/* 8 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 10 */ 0x32, /* FC_BIND_PRIMITIVE */ + 0x0, /* 0 */ +/* 12 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 14 */ NdrFcShort( 0x0 ), /* 0 */ +/* 16 */ NdrFcShort( 0x0 ), /* 0 */ +/* 18 */ 0x40, /* Oi2 Flags: has ext, */ + 0x0, /* 0 */ +/* 20 */ 0x8, /* 8 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 22 */ NdrFcShort( 0x0 ), /* 0 */ +/* 24 */ NdrFcShort( 0x0 ), /* 0 */ +/* 26 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Procedure TsProxyCreateTunnel */ + + + /* Parameter IDL_handle */ + +/* 28 */ 0x33, /* FC_AUTO_HANDLE */ + 0x48, /* Old Flags: */ +/* 30 */ NdrFcLong( 0x0 ), /* 0 */ +/* 34 */ NdrFcShort( 0x1 ), /* 1 */ +/* 36 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 38 */ NdrFcShort( 0x0 ), /* 0 */ +/* 40 */ NdrFcShort( 0x5c ), /* 92 */ +/* 42 */ 0x47, /* Oi2 Flags: srv must size, clt must size, has return, has ext, */ + 0x5, /* 5 */ +/* 44 */ 0x8, /* 8 */ + 0x7, /* Ext Flags: new corr desc, clt corr check, srv corr check, */ +/* 46 */ NdrFcShort( 0x1 ), /* 1 */ +/* 48 */ NdrFcShort( 0x1 ), /* 1 */ +/* 50 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter tsgPacket */ + +/* 52 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 54 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 56 */ NdrFcShort( 0x280 ), /* Type Offset=640 */ + + /* Parameter tsgPacketResponse */ + +/* 58 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */ +/* 60 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 62 */ NdrFcShort( 0x28e ), /* Type Offset=654 */ + + /* Parameter tunnelContext */ + +/* 64 */ NdrFcShort( 0x110 ), /* Flags: out, simple ref, */ +/* 66 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 68 */ NdrFcShort( 0x29a ), /* Type Offset=666 */ + + /* Parameter tunnelId */ + +/* 70 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 72 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 74 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Return value */ + +/* 76 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 78 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ +/* 80 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure TsProxyAuthorizeTunnel */ + +/* 82 */ 0x0, /* 0 */ + 0x48, /* Old Flags: */ +/* 84 */ NdrFcLong( 0x0 ), /* 0 */ +/* 88 */ NdrFcShort( 0x2 ), /* 2 */ +/* 90 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ +/* 92 */ 0x30, /* FC_BIND_CONTEXT */ + 0x40, /* Ctxt flags: in, */ +/* 94 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 96 */ 0x1, /* 1 */ + 0x0, /* 0 */ +/* 98 */ NdrFcShort( 0x24 ), /* 36 */ +/* 100 */ NdrFcShort( 0x8 ), /* 8 */ +/* 102 */ 0x47, /* Oi2 Flags: srv must size, clt must size, has return, has ext, */ + 0x4, /* 4 */ +/* 104 */ 0x8, /* 8 */ + 0x7, /* Ext Flags: new corr desc, clt corr check, srv corr check, */ +/* 106 */ NdrFcShort( 0x1 ), /* 1 */ +/* 108 */ NdrFcShort( 0x1 ), /* 1 */ +/* 110 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter tunnelContext */ + +/* 112 */ NdrFcShort( 0x8 ), /* Flags: in, */ +/* 114 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 116 */ NdrFcShort( 0x2a2 ), /* Type Offset=674 */ + + /* Parameter tsgPacket */ + +/* 118 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 120 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 122 */ NdrFcShort( 0x280 ), /* Type Offset=640 */ + + /* Parameter tsgPacketResponse */ + +/* 124 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */ +/* 126 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 128 */ NdrFcShort( 0x28e ), /* Type Offset=654 */ + + /* Return value */ + +/* 130 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 132 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 134 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure TsProxyMakeTunnelCall */ + +/* 136 */ 0x0, /* 0 */ + 0x48, /* Old Flags: */ +/* 138 */ NdrFcLong( 0x0 ), /* 0 */ +/* 142 */ NdrFcShort( 0x3 ), /* 3 */ +/* 144 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 146 */ 0x30, /* FC_BIND_CONTEXT */ + 0x40, /* Ctxt flags: in, */ +/* 148 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 150 */ 0x1, /* 1 */ + 0x0, /* 0 */ +/* 152 */ NdrFcShort( 0x2c ), /* 44 */ +/* 154 */ NdrFcShort( 0x8 ), /* 8 */ +/* 156 */ 0x47, /* Oi2 Flags: srv must size, clt must size, has return, has ext, */ + 0x5, /* 5 */ +/* 158 */ 0x8, /* 8 */ + 0x7, /* Ext Flags: new corr desc, clt corr check, srv corr check, */ +/* 160 */ NdrFcShort( 0x1 ), /* 1 */ +/* 162 */ NdrFcShort( 0x1 ), /* 1 */ +/* 164 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter tunnelContext */ + +/* 166 */ NdrFcShort( 0x8 ), /* Flags: in, */ +/* 168 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 170 */ NdrFcShort( 0x2a2 ), /* Type Offset=674 */ + + /* Parameter procId */ + +/* 172 */ NdrFcShort( 0x48 ), /* Flags: in, base type, */ +/* 174 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 176 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Parameter tsgPacket */ + +/* 178 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 180 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 182 */ NdrFcShort( 0x280 ), /* Type Offset=640 */ + + /* Parameter tsgPacketResponse */ + +/* 184 */ NdrFcShort( 0x2013 ), /* Flags: must size, must free, out, srv alloc size=8 */ +/* 186 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 188 */ NdrFcShort( 0x28e ), /* Type Offset=654 */ + + /* Return value */ + +/* 190 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 192 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ +/* 194 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure TsProxyCreateChannel */ + +/* 196 */ 0x0, /* 0 */ + 0x48, /* Old Flags: */ +/* 198 */ NdrFcLong( 0x0 ), /* 0 */ +/* 202 */ NdrFcShort( 0x4 ), /* 4 */ +/* 204 */ NdrFcShort( 0x14 ), /* x86 Stack size/offset = 20 */ +/* 206 */ 0x30, /* FC_BIND_CONTEXT */ + 0x40, /* Ctxt flags: in, */ +/* 208 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 210 */ 0x1, /* 1 */ + 0x0, /* 0 */ +/* 212 */ NdrFcShort( 0x24 ), /* 36 */ +/* 214 */ NdrFcShort( 0x5c ), /* 92 */ +/* 216 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x5, /* 5 */ +/* 218 */ 0x8, /* 8 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 220 */ NdrFcShort( 0x0 ), /* 0 */ +/* 222 */ NdrFcShort( 0x1 ), /* 1 */ +/* 224 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter tunnelContext */ + +/* 226 */ NdrFcShort( 0x8 ), /* Flags: in, */ +/* 228 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 230 */ NdrFcShort( 0x2a2 ), /* Type Offset=674 */ + + /* Parameter tsEndPointInfo */ + +/* 232 */ NdrFcShort( 0x10b ), /* Flags: must size, must free, in, simple ref, */ +/* 234 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 236 */ NdrFcShort( 0x2fe ), /* Type Offset=766 */ + + /* Parameter channelContext */ + +/* 238 */ NdrFcShort( 0x110 ), /* Flags: out, simple ref, */ +/* 240 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 242 */ NdrFcShort( 0x320 ), /* Type Offset=800 */ + + /* Parameter channelId */ + +/* 244 */ NdrFcShort( 0x2150 ), /* Flags: out, base type, simple ref, srv alloc size=8 */ +/* 246 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 248 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Return value */ + +/* 250 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 252 */ NdrFcShort( 0x10 ), /* x86 Stack size/offset = 16 */ +/* 254 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure Opnum5NotUsedOnWire */ + +/* 256 */ 0x0, /* 0 */ + 0x48, /* Old Flags: */ +/* 258 */ NdrFcLong( 0x0 ), /* 0 */ +/* 262 */ NdrFcShort( 0x5 ), /* 5 */ +/* 264 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 266 */ 0x32, /* FC_BIND_PRIMITIVE */ + 0x0, /* 0 */ +/* 268 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 270 */ NdrFcShort( 0x0 ), /* 0 */ +/* 272 */ NdrFcShort( 0x0 ), /* 0 */ +/* 274 */ 0x40, /* Oi2 Flags: has ext, */ + 0x0, /* 0 */ +/* 276 */ 0x8, /* 8 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 278 */ NdrFcShort( 0x0 ), /* 0 */ +/* 280 */ NdrFcShort( 0x0 ), /* 0 */ +/* 282 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Procedure TsProxyCloseChannel */ + + + /* Parameter IDL_handle */ + +/* 284 */ 0x0, /* 0 */ + 0x48, /* Old Flags: */ +/* 286 */ NdrFcLong( 0x0 ), /* 0 */ +/* 290 */ NdrFcShort( 0x6 ), /* 6 */ +/* 292 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 294 */ 0x30, /* FC_BIND_CONTEXT */ + 0xe0, /* Ctxt flags: via ptr, in, out, */ +/* 296 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 298 */ 0x3, /* 3 */ + 0x0, /* 0 */ +/* 300 */ NdrFcShort( 0x38 ), /* 56 */ +/* 302 */ NdrFcShort( 0x40 ), /* 64 */ +/* 304 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 306 */ 0x8, /* 8 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 308 */ NdrFcShort( 0x0 ), /* 0 */ +/* 310 */ NdrFcShort( 0x0 ), /* 0 */ +/* 312 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter context */ + +/* 314 */ NdrFcShort( 0x118 ), /* Flags: in, out, simple ref, */ +/* 316 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 318 */ NdrFcShort( 0x328 ), /* Type Offset=808 */ + + /* Return value */ + +/* 320 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 322 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 324 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure TsProxyCloseTunnel */ + +/* 326 */ 0x0, /* 0 */ + 0x48, /* Old Flags: */ +/* 328 */ NdrFcLong( 0x0 ), /* 0 */ +/* 332 */ NdrFcShort( 0x7 ), /* 7 */ +/* 334 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 336 */ 0x30, /* FC_BIND_CONTEXT */ + 0xe0, /* Ctxt flags: via ptr, in, out, */ +/* 338 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 340 */ 0x0, /* 0 */ + 0x0, /* 0 */ +/* 342 */ NdrFcShort( 0x38 ), /* 56 */ +/* 344 */ NdrFcShort( 0x40 ), /* 64 */ +/* 346 */ 0x44, /* Oi2 Flags: has return, has ext, */ + 0x2, /* 2 */ +/* 348 */ 0x8, /* 8 */ + 0x1, /* Ext Flags: new corr desc, */ +/* 350 */ NdrFcShort( 0x0 ), /* 0 */ +/* 352 */ NdrFcShort( 0x0 ), /* 0 */ +/* 354 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter context */ + +/* 356 */ NdrFcShort( 0x118 ), /* Flags: in, out, simple ref, */ +/* 358 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 360 */ NdrFcShort( 0x330 ), /* Type Offset=816 */ + + /* Return value */ + +/* 362 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 364 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 366 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure TsProxySetupReceivePipe */ + +/* 368 */ 0x0, /* 0 */ + 0x48, /* Old Flags: */ +/* 370 */ NdrFcLong( 0x0 ), /* 0 */ +/* 374 */ NdrFcShort( 0x8 ), /* 8 */ +/* 376 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 378 */ 0x32, /* FC_BIND_PRIMITIVE */ + 0x0, /* 0 */ +/* 380 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 382 */ NdrFcShort( 0x0 ), /* 0 */ +/* 384 */ NdrFcShort( 0x8 ), /* 8 */ +/* 386 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 388 */ 0x8, /* 8 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 390 */ NdrFcShort( 0x0 ), /* 0 */ +/* 392 */ NdrFcShort( 0x1 ), /* 1 */ +/* 394 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter IDL_handle */ + +/* 396 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 398 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 400 */ NdrFcShort( 0x334 ), /* Type Offset=820 */ + + /* Parameter pRpcMessage */ + +/* 402 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 404 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 406 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + /* Procedure TsProxySendToServer */ + + + /* Return value */ + +/* 408 */ 0x0, /* 0 */ + 0x48, /* Old Flags: */ +/* 410 */ NdrFcLong( 0x0 ), /* 0 */ +/* 414 */ NdrFcShort( 0x9 ), /* 9 */ +/* 416 */ NdrFcShort( 0xc ), /* x86 Stack size/offset = 12 */ +/* 418 */ 0x32, /* FC_BIND_PRIMITIVE */ + 0x0, /* 0 */ +/* 420 */ NdrFcShort( 0x0 ), /* x86 Stack size/offset = 0 */ +/* 422 */ NdrFcShort( 0x0 ), /* 0 */ +/* 424 */ NdrFcShort( 0x8 ), /* 8 */ +/* 426 */ 0x46, /* Oi2 Flags: clt must size, has return, has ext, */ + 0x2, /* 2 */ +/* 428 */ 0x8, /* 8 */ + 0x5, /* Ext Flags: new corr desc, srv corr check, */ +/* 430 */ NdrFcShort( 0x0 ), /* 0 */ +/* 432 */ NdrFcShort( 0x1 ), /* 1 */ +/* 434 */ NdrFcShort( 0x0 ), /* 0 */ + + /* Parameter IDL_handle */ + +/* 436 */ NdrFcShort( 0xb ), /* Flags: must size, must free, in, */ +/* 438 */ NdrFcShort( 0x4 ), /* x86 Stack size/offset = 4 */ +/* 440 */ NdrFcShort( 0x334 ), /* Type Offset=820 */ + + /* Parameter pRpcMessage */ + +/* 442 */ NdrFcShort( 0x70 ), /* Flags: out, return, base type, */ +/* 444 */ NdrFcShort( 0x8 ), /* x86 Stack size/offset = 8 */ +/* 446 */ 0x8, /* FC_LONG */ + 0x0, /* 0 */ + + 0x0 + } + }; + +static const ms2Dtsgu_MIDL_TYPE_FORMAT_STRING ms2Dtsgu__MIDL_TypeFormatString = + { + 0, + { + NdrFcShort( 0x0 ), /* 0 */ +/* 2 */ + 0x11, 0x0, /* FC_RP */ +/* 4 */ NdrFcShort( 0x27c ), /* Offset= 636 (640) */ +/* 6 */ + 0x2b, /* FC_NON_ENCAPSULATED_UNION */ + 0x9, /* FC_ULONG */ +/* 8 */ 0x9, /* Corr desc: FC_ULONG */ + 0x0, /* */ +/* 10 */ NdrFcShort( 0xfffc ), /* -4 */ +/* 12 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 14 */ NdrFcShort( 0x2 ), /* Offset= 2 (16) */ +/* 16 */ NdrFcShort( 0x4 ), /* 4 */ +/* 18 */ NdrFcShort( 0xb ), /* 11 */ +/* 20 */ NdrFcLong( 0x4844 ), /* 18500 */ +/* 24 */ NdrFcShort( 0x40 ), /* Offset= 64 (88) */ +/* 26 */ NdrFcLong( 0x5643 ), /* 22083 */ +/* 30 */ NdrFcShort( 0x46 ), /* Offset= 70 (100) */ +/* 32 */ NdrFcLong( 0x5143 ), /* 20803 */ +/* 36 */ NdrFcShort( 0xa8 ), /* Offset= 168 (204) */ +/* 38 */ NdrFcLong( 0x5152 ), /* 20818 */ +/* 42 */ NdrFcShort( 0xa6 ), /* Offset= 166 (208) */ +/* 44 */ NdrFcLong( 0x5052 ), /* 20562 */ +/* 48 */ NdrFcShort( 0xe8 ), /* Offset= 232 (280) */ +/* 50 */ NdrFcLong( 0x4552 ), /* 17746 */ +/* 54 */ NdrFcShort( 0x122 ), /* Offset= 290 (344) */ +/* 56 */ NdrFcLong( 0x4350 ), /* 17232 */ +/* 60 */ NdrFcShort( 0x160 ), /* Offset= 352 (412) */ +/* 62 */ NdrFcLong( 0x4752 ), /* 18258 */ +/* 66 */ NdrFcShort( 0x8a ), /* Offset= 138 (204) */ +/* 68 */ NdrFcLong( 0x4750 ), /* 18256 */ +/* 72 */ NdrFcShort( 0x1d4 ), /* Offset= 468 (540) */ +/* 74 */ NdrFcLong( 0x4054 ), /* 16468 */ +/* 78 */ NdrFcShort( 0x1d2 ), /* Offset= 466 (544) */ +/* 80 */ NdrFcLong( 0x5250 ), /* 21072 */ +/* 84 */ NdrFcShort( 0x1fc ), /* Offset= 508 (592) */ +/* 86 */ NdrFcShort( 0xffff ), /* Offset= -1 (85) */ +/* 88 */ + 0x12, 0x0, /* FC_UP */ +/* 90 */ NdrFcShort( 0x2 ), /* Offset= 2 (92) */ +/* 92 */ + 0x15, /* FC_STRUCT */ + 0x1, /* 1 */ +/* 94 */ NdrFcShort( 0x4 ), /* 4 */ +/* 96 */ 0x6, /* FC_SHORT */ + 0x6, /* FC_SHORT */ +/* 98 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 100 */ + 0x12, 0x0, /* FC_UP */ +/* 102 */ NdrFcShort( 0x4c ), /* Offset= 76 (178) */ +/* 104 */ 0xb7, /* FC_RANGE */ + 0x8, /* 8 */ +/* 106 */ NdrFcLong( 0x0 ), /* 0 */ +/* 110 */ NdrFcLong( 0x20 ), /* 32 */ +/* 114 */ + 0x2b, /* FC_NON_ENCAPSULATED_UNION */ + 0x9, /* FC_ULONG */ +/* 116 */ 0x9, /* Corr desc: FC_ULONG */ + 0x0, /* */ +/* 118 */ NdrFcShort( 0xfffc ), /* -4 */ +/* 120 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 122 */ NdrFcShort( 0x2 ), /* Offset= 2 (124) */ +/* 124 */ NdrFcShort( 0x4 ), /* 4 */ +/* 126 */ NdrFcShort( 0x1 ), /* 1 */ +/* 128 */ NdrFcLong( 0x1 ), /* 1 */ +/* 132 */ NdrFcShort( 0x4 ), /* Offset= 4 (136) */ +/* 134 */ NdrFcShort( 0xffff ), /* Offset= -1 (133) */ +/* 136 */ + 0x15, /* FC_STRUCT */ + 0x3, /* 3 */ +/* 138 */ NdrFcShort( 0x4 ), /* 4 */ +/* 140 */ 0x8, /* FC_LONG */ + 0x5b, /* FC_END */ +/* 142 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 144 */ NdrFcShort( 0x8 ), /* 8 */ +/* 146 */ NdrFcShort( 0x0 ), /* 0 */ +/* 148 */ NdrFcShort( 0x0 ), /* Offset= 0 (148) */ +/* 150 */ 0x8, /* FC_LONG */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 152 */ 0x0, /* 0 */ + NdrFcShort( 0xffd9 ), /* Offset= -39 (114) */ + 0x5b, /* FC_END */ +/* 156 */ + 0x21, /* FC_BOGUS_ARRAY */ + 0x3, /* 3 */ +/* 158 */ NdrFcShort( 0x0 ), /* 0 */ +/* 160 */ 0x19, /* Corr desc: field pointer, FC_ULONG */ + 0x0, /* */ +/* 162 */ NdrFcShort( 0x8 ), /* 8 */ +/* 164 */ NdrFcShort( 0x0 ), /* Corr flags: */ +/* 166 */ NdrFcLong( 0xffffffff ), /* -1 */ +/* 170 */ NdrFcShort( 0x0 ), /* Corr flags: */ +/* 172 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 174 */ NdrFcShort( 0xffe0 ), /* Offset= -32 (142) */ +/* 176 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 178 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 180 */ NdrFcShort( 0x14 ), /* 20 */ +/* 182 */ NdrFcShort( 0x0 ), /* 0 */ +/* 184 */ NdrFcShort( 0x10 ), /* Offset= 16 (200) */ +/* 186 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 188 */ NdrFcShort( 0xffa0 ), /* Offset= -96 (92) */ +/* 190 */ 0x36, /* FC_POINTER */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 192 */ 0x0, /* 0 */ + NdrFcShort( 0xffa7 ), /* Offset= -89 (104) */ + 0x6, /* FC_SHORT */ +/* 196 */ 0x6, /* FC_SHORT */ + 0x6, /* FC_SHORT */ +/* 198 */ 0x3e, /* FC_STRUCTPAD2 */ + 0x5b, /* FC_END */ +/* 200 */ + 0x12, 0x0, /* FC_UP */ +/* 202 */ NdrFcShort( 0xffd2 ), /* Offset= -46 (156) */ +/* 204 */ + 0x12, 0x0, /* FC_UP */ +/* 206 */ NdrFcShort( 0xffba ), /* Offset= -70 (136) */ +/* 208 */ + 0x12, 0x0, /* FC_UP */ +/* 210 */ NdrFcShort( 0x2a ), /* Offset= 42 (252) */ +/* 212 */ 0xb7, /* FC_RANGE */ + 0x8, /* 8 */ +/* 214 */ NdrFcLong( 0x0 ), /* 0 */ +/* 218 */ NdrFcLong( 0x201 ), /* 513 */ +/* 222 */ 0xb7, /* FC_RANGE */ + 0x8, /* 8 */ +/* 224 */ NdrFcLong( 0x0 ), /* 0 */ +/* 228 */ NdrFcLong( 0x1f40 ), /* 8000 */ +/* 232 */ + 0x25, /* FC_C_WSTRING */ + 0x44, /* FC_STRING_SIZED */ +/* 234 */ 0x19, /* Corr desc: field pointer, FC_ULONG */ + 0x0, /* */ +/* 236 */ NdrFcShort( 0x8 ), /* 8 */ +/* 238 */ NdrFcShort( 0x0 ), /* Corr flags: */ +/* 240 */ + 0x1b, /* FC_CARRAY */ + 0x0, /* 0 */ +/* 242 */ NdrFcShort( 0x1 ), /* 1 */ +/* 244 */ 0x19, /* Corr desc: field pointer, FC_ULONG */ + 0x0, /* */ +/* 246 */ NdrFcShort( 0x10 ), /* 16 */ +/* 248 */ NdrFcShort( 0x0 ), /* Corr flags: */ +/* 250 */ 0x1, /* FC_BYTE */ + 0x5b, /* FC_END */ +/* 252 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 254 */ NdrFcShort( 0x14 ), /* 20 */ +/* 256 */ NdrFcShort( 0x0 ), /* 0 */ +/* 258 */ NdrFcShort( 0xe ), /* Offset= 14 (272) */ +/* 260 */ 0x8, /* FC_LONG */ + 0x36, /* FC_POINTER */ +/* 262 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 264 */ NdrFcShort( 0xffcc ), /* Offset= -52 (212) */ +/* 266 */ 0x36, /* FC_POINTER */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 268 */ 0x0, /* 0 */ + NdrFcShort( 0xffd1 ), /* Offset= -47 (222) */ + 0x5b, /* FC_END */ +/* 272 */ + 0x12, 0x0, /* FC_UP */ +/* 274 */ NdrFcShort( 0xffd6 ), /* Offset= -42 (232) */ +/* 276 */ + 0x12, 0x0, /* FC_UP */ +/* 278 */ NdrFcShort( 0xffda ), /* Offset= -38 (240) */ +/* 280 */ + 0x12, 0x0, /* FC_UP */ +/* 282 */ NdrFcShort( 0x26 ), /* Offset= 38 (320) */ +/* 284 */ 0xb7, /* FC_RANGE */ + 0x8, /* 8 */ +/* 286 */ NdrFcLong( 0x0 ), /* 0 */ +/* 290 */ NdrFcLong( 0x5dc0 ), /* 24000 */ +/* 294 */ + 0x15, /* FC_STRUCT */ + 0x3, /* 3 */ +/* 296 */ NdrFcShort( 0x20 ), /* 32 */ +/* 298 */ 0x8, /* FC_LONG */ + 0x8, /* FC_LONG */ +/* 300 */ 0x8, /* FC_LONG */ + 0x8, /* FC_LONG */ +/* 302 */ 0x8, /* FC_LONG */ + 0x8, /* FC_LONG */ +/* 304 */ 0x8, /* FC_LONG */ + 0x8, /* FC_LONG */ +/* 306 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 308 */ + 0x1b, /* FC_CARRAY */ + 0x0, /* 0 */ +/* 310 */ NdrFcShort( 0x1 ), /* 1 */ +/* 312 */ 0x19, /* Corr desc: field pointer, FC_ULONG */ + 0x0, /* */ +/* 314 */ NdrFcShort( 0xc ), /* 12 */ +/* 316 */ NdrFcShort( 0x0 ), /* Corr flags: */ +/* 318 */ 0x1, /* FC_BYTE */ + 0x5b, /* FC_END */ +/* 320 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 322 */ NdrFcShort( 0x30 ), /* 48 */ +/* 324 */ NdrFcShort( 0x0 ), /* 0 */ +/* 326 */ NdrFcShort( 0xe ), /* Offset= 14 (340) */ +/* 328 */ 0x8, /* FC_LONG */ + 0x8, /* FC_LONG */ +/* 330 */ 0x36, /* FC_POINTER */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 332 */ 0x0, /* 0 */ + NdrFcShort( 0xffcf ), /* Offset= -49 (284) */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 336 */ 0x0, /* 0 */ + NdrFcShort( 0xffd5 ), /* Offset= -43 (294) */ + 0x5b, /* FC_END */ +/* 340 */ + 0x12, 0x0, /* FC_UP */ +/* 342 */ NdrFcShort( 0xffde ), /* Offset= -34 (308) */ +/* 344 */ + 0x12, 0x0, /* FC_UP */ +/* 346 */ NdrFcShort( 0x26 ), /* Offset= 38 (384) */ +/* 348 */ 0xb7, /* FC_RANGE */ + 0x8, /* 8 */ +/* 350 */ NdrFcLong( 0x0 ), /* 0 */ +/* 354 */ NdrFcLong( 0x5dc0 ), /* 24000 */ +/* 358 */ + 0x1d, /* FC_SMFARRAY */ + 0x0, /* 0 */ +/* 360 */ NdrFcShort( 0x8 ), /* 8 */ +/* 362 */ 0x1, /* FC_BYTE */ + 0x5b, /* FC_END */ +/* 364 */ + 0x15, /* FC_STRUCT */ + 0x3, /* 3 */ +/* 366 */ NdrFcShort( 0x10 ), /* 16 */ +/* 368 */ 0x8, /* FC_LONG */ + 0x6, /* FC_SHORT */ +/* 370 */ 0x6, /* FC_SHORT */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 372 */ 0x0, /* 0 */ + NdrFcShort( 0xfff1 ), /* Offset= -15 (358) */ + 0x5b, /* FC_END */ +/* 376 */ + 0x25, /* FC_C_WSTRING */ + 0x44, /* FC_STRING_SIZED */ +/* 378 */ 0x19, /* Corr desc: field pointer, FC_ULONG */ + 0x0, /* */ +/* 380 */ NdrFcShort( 0x4 ), /* 4 */ +/* 382 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 384 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 386 */ NdrFcShort( 0x20 ), /* 32 */ +/* 388 */ NdrFcShort( 0x0 ), /* 0 */ +/* 390 */ NdrFcShort( 0xe ), /* Offset= 14 (404) */ +/* 392 */ 0x8, /* FC_LONG */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 394 */ 0x0, /* 0 */ + NdrFcShort( 0xffd1 ), /* Offset= -47 (348) */ + 0x36, /* FC_POINTER */ +/* 398 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 400 */ NdrFcShort( 0xffdc ), /* Offset= -36 (364) */ +/* 402 */ 0x36, /* FC_POINTER */ + 0x5b, /* FC_END */ +/* 404 */ + 0x12, 0x0, /* FC_UP */ +/* 406 */ NdrFcShort( 0xffe2 ), /* Offset= -30 (376) */ +/* 408 */ + 0x12, 0x0, /* FC_UP */ +/* 410 */ NdrFcShort( 0xff18 ), /* Offset= -232 (178) */ +/* 412 */ + 0x12, 0x0, /* FC_UP */ +/* 414 */ NdrFcShort( 0x6c ), /* Offset= 108 (522) */ +/* 416 */ + 0x2b, /* FC_NON_ENCAPSULATED_UNION */ + 0x9, /* FC_ULONG */ +/* 418 */ 0x9, /* Corr desc: FC_ULONG */ + 0x0, /* */ +/* 420 */ NdrFcShort( 0xfff8 ), /* -8 */ +/* 422 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 424 */ NdrFcShort( 0x2 ), /* Offset= 2 (426) */ +/* 426 */ NdrFcShort( 0x4 ), /* 4 */ +/* 428 */ NdrFcShort( 0x3 ), /* 3 */ +/* 430 */ NdrFcLong( 0x1 ), /* 1 */ +/* 434 */ NdrFcShort( 0x10 ), /* Offset= 16 (450) */ +/* 436 */ NdrFcLong( 0x2 ), /* 2 */ +/* 440 */ NdrFcShort( 0xa ), /* Offset= 10 (450) */ +/* 442 */ NdrFcLong( 0x3 ), /* 3 */ +/* 446 */ NdrFcShort( 0x32 ), /* Offset= 50 (496) */ +/* 448 */ NdrFcShort( 0xffff ), /* Offset= -1 (447) */ +/* 450 */ + 0x12, 0x0, /* FC_UP */ +/* 452 */ NdrFcShort( 0x18 ), /* Offset= 24 (476) */ +/* 454 */ 0xb7, /* FC_RANGE */ + 0x8, /* 8 */ +/* 456 */ NdrFcLong( 0x0 ), /* 0 */ +/* 460 */ NdrFcLong( 0x10000 ), /* 65536 */ +/* 464 */ + 0x1b, /* FC_CARRAY */ + 0x1, /* 1 */ +/* 466 */ NdrFcShort( 0x2 ), /* 2 */ +/* 468 */ 0x19, /* Corr desc: field pointer, FC_ULONG */ + 0x0, /* */ +/* 470 */ NdrFcShort( 0x8 ), /* 8 */ +/* 472 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 474 */ 0x5, /* FC_WCHAR */ + 0x5b, /* FC_END */ +/* 476 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 478 */ NdrFcShort( 0x10 ), /* 16 */ +/* 480 */ NdrFcShort( 0x0 ), /* 0 */ +/* 482 */ NdrFcShort( 0xa ), /* Offset= 10 (492) */ +/* 484 */ 0x8, /* FC_LONG */ + 0x8, /* FC_LONG */ +/* 486 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 488 */ NdrFcShort( 0xffde ), /* Offset= -34 (454) */ +/* 490 */ 0x36, /* FC_POINTER */ + 0x5b, /* FC_END */ +/* 492 */ + 0x12, 0x0, /* FC_UP */ +/* 494 */ NdrFcShort( 0xffe2 ), /* Offset= -30 (464) */ +/* 496 */ + 0x12, 0x0, /* FC_UP */ +/* 498 */ NdrFcShort( 0x2 ), /* Offset= 2 (500) */ +/* 500 */ + 0x15, /* FC_STRUCT */ + 0x7, /* 7 */ +/* 502 */ NdrFcShort( 0x8 ), /* 8 */ +/* 504 */ 0xb, /* FC_HYPER */ + 0x5b, /* FC_END */ +/* 506 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 508 */ NdrFcShort( 0x10 ), /* 16 */ +/* 510 */ NdrFcShort( 0x0 ), /* 0 */ +/* 512 */ NdrFcShort( 0x0 ), /* Offset= 0 (512) */ +/* 514 */ 0x8, /* FC_LONG */ + 0x8, /* FC_LONG */ +/* 516 */ 0x8, /* FC_LONG */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 518 */ 0x0, /* 0 */ + NdrFcShort( 0xff99 ), /* Offset= -103 (416) */ + 0x5b, /* FC_END */ +/* 522 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 524 */ NdrFcShort( 0x30 ), /* 48 */ +/* 526 */ NdrFcShort( 0x0 ), /* 0 */ +/* 528 */ NdrFcShort( 0x0 ), /* Offset= 0 (528) */ +/* 530 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 532 */ NdrFcShort( 0xff6c ), /* Offset= -148 (384) */ +/* 534 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 536 */ NdrFcShort( 0xffe2 ), /* Offset= -30 (506) */ +/* 538 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 540 */ + 0x12, 0x0, /* FC_UP */ +/* 542 */ NdrFcShort( 0xffdc ), /* Offset= -36 (506) */ +/* 544 */ + 0x12, 0x0, /* FC_UP */ +/* 546 */ NdrFcShort( 0x18 ), /* Offset= 24 (570) */ +/* 548 */ 0xb7, /* FC_RANGE */ + 0x8, /* 8 */ +/* 550 */ NdrFcLong( 0x0 ), /* 0 */ +/* 554 */ NdrFcLong( 0x10000 ), /* 65536 */ +/* 558 */ + 0x1b, /* FC_CARRAY */ + 0x0, /* 0 */ +/* 560 */ NdrFcShort( 0x1 ), /* 1 */ +/* 562 */ 0x19, /* Corr desc: field pointer, FC_ULONG */ + 0x0, /* */ +/* 564 */ NdrFcShort( 0x14 ), /* 20 */ +/* 566 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 568 */ 0x1, /* FC_BYTE */ + 0x5b, /* FC_END */ +/* 570 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 572 */ NdrFcShort( 0x1c ), /* 28 */ +/* 574 */ NdrFcShort( 0x0 ), /* 0 */ +/* 576 */ NdrFcShort( 0xc ), /* Offset= 12 (588) */ +/* 578 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 580 */ NdrFcShort( 0xfe6e ), /* Offset= -402 (178) */ +/* 582 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 584 */ NdrFcShort( 0xffdc ), /* Offset= -36 (548) */ +/* 586 */ 0x36, /* FC_POINTER */ + 0x5b, /* FC_END */ +/* 588 */ + 0x12, 0x0, /* FC_UP */ +/* 590 */ NdrFcShort( 0xffe0 ), /* Offset= -32 (558) */ +/* 592 */ + 0x12, 0x0, /* FC_UP */ +/* 594 */ NdrFcShort( 0x1e ), /* Offset= 30 (624) */ +/* 596 */ + 0x2b, /* FC_NON_ENCAPSULATED_UNION */ + 0x9, /* FC_ULONG */ +/* 598 */ 0x9, /* Corr desc: FC_ULONG */ + 0x0, /* */ +/* 600 */ NdrFcShort( 0xfffc ), /* -4 */ +/* 602 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 604 */ NdrFcShort( 0x2 ), /* Offset= 2 (606) */ +/* 606 */ NdrFcShort( 0x4 ), /* 4 */ +/* 608 */ NdrFcShort( 0x2 ), /* 2 */ +/* 610 */ NdrFcLong( 0x5643 ), /* 22083 */ +/* 614 */ NdrFcShort( 0xfdfe ), /* Offset= -514 (100) */ +/* 616 */ NdrFcLong( 0x4054 ), /* 16468 */ +/* 620 */ NdrFcShort( 0xffb4 ), /* Offset= -76 (544) */ +/* 622 */ NdrFcShort( 0xffff ), /* Offset= -1 (621) */ +/* 624 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x7, /* 7 */ +/* 626 */ NdrFcShort( 0x10 ), /* 16 */ +/* 628 */ NdrFcShort( 0x0 ), /* 0 */ +/* 630 */ NdrFcShort( 0x0 ), /* Offset= 0 (630) */ +/* 632 */ 0xb, /* FC_HYPER */ + 0x8, /* FC_LONG */ +/* 634 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 636 */ NdrFcShort( 0xffd8 ), /* Offset= -40 (596) */ +/* 638 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 640 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 642 */ NdrFcShort( 0x8 ), /* 8 */ +/* 644 */ NdrFcShort( 0x0 ), /* 0 */ +/* 646 */ NdrFcShort( 0x0 ), /* Offset= 0 (646) */ +/* 648 */ 0x8, /* FC_LONG */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 650 */ 0x0, /* 0 */ + NdrFcShort( 0xfd7b ), /* Offset= -645 (6) */ + 0x5b, /* FC_END */ +/* 654 */ + 0x11, 0x14, /* FC_RP [alloced_on_stack] [pointer_deref] */ +/* 656 */ NdrFcShort( 0x2 ), /* Offset= 2 (658) */ +/* 658 */ + 0x12, 0x0, /* FC_UP */ +/* 660 */ NdrFcShort( 0xffec ), /* Offset= -20 (640) */ +/* 662 */ + 0x11, 0x4, /* FC_RP [alloced_on_stack] */ +/* 664 */ NdrFcShort( 0x2 ), /* Offset= 2 (666) */ +/* 666 */ 0x30, /* FC_BIND_CONTEXT */ + 0xa0, /* Ctxt flags: via ptr, out, */ +/* 668 */ 0x0, /* 0 */ + 0x0, /* 0 */ +/* 670 */ + 0x11, 0xc, /* FC_RP [alloced_on_stack] [simple_pointer] */ +/* 672 */ 0x8, /* FC_LONG */ + 0x5c, /* FC_PAD */ +/* 674 */ 0x30, /* FC_BIND_CONTEXT */ + 0x41, /* Ctxt flags: in, can't be null */ +/* 676 */ 0x1, /* 1 */ + 0x0, /* 0 */ +/* 678 */ + 0x11, 0x0, /* FC_RP */ +/* 680 */ NdrFcShort( 0x56 ), /* Offset= 86 (766) */ +/* 682 */ 0xb7, /* FC_RANGE */ + 0x8, /* 8 */ +/* 684 */ NdrFcLong( 0x0 ), /* 0 */ +/* 688 */ NdrFcLong( 0x32 ), /* 50 */ +/* 692 */ 0xb7, /* FC_RANGE */ + 0x6, /* 6 */ +/* 694 */ NdrFcLong( 0x0 ), /* 0 */ +/* 698 */ NdrFcLong( 0x3 ), /* 3 */ +/* 702 */ + 0x1b, /* FC_CARRAY */ + 0x3, /* 3 */ +/* 704 */ NdrFcShort( 0x4 ), /* 4 */ +/* 706 */ 0x19, /* Corr desc: field pointer, FC_ULONG */ + 0x0, /* */ +/* 708 */ NdrFcShort( 0x4 ), /* 4 */ +/* 710 */ NdrFcShort( 0x0 ), /* Corr flags: */ +/* 712 */ + 0x4b, /* FC_PP */ + 0x5c, /* FC_PAD */ +/* 714 */ + 0x48, /* FC_VARIABLE_REPEAT */ + 0x49, /* FC_FIXED_OFFSET */ +/* 716 */ NdrFcShort( 0x4 ), /* 4 */ +/* 718 */ NdrFcShort( 0x0 ), /* 0 */ +/* 720 */ NdrFcShort( 0x1 ), /* 1 */ +/* 722 */ NdrFcShort( 0x0 ), /* 0 */ +/* 724 */ NdrFcShort( 0x0 ), /* 0 */ +/* 726 */ 0x12, 0x8, /* FC_UP [simple_pointer] */ +/* 728 */ + 0x25, /* FC_C_WSTRING */ + 0x5c, /* FC_PAD */ +/* 730 */ + 0x5b, /* FC_END */ + + 0x8, /* FC_LONG */ +/* 732 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 734 */ + 0x1b, /* FC_CARRAY */ + 0x3, /* 3 */ +/* 736 */ NdrFcShort( 0x4 ), /* 4 */ +/* 738 */ 0x17, /* Corr desc: field pointer, FC_USHORT */ + 0x0, /* */ +/* 740 */ NdrFcShort( 0xc ), /* 12 */ +/* 742 */ NdrFcShort( 0x0 ), /* Corr flags: */ +/* 744 */ + 0x4b, /* FC_PP */ + 0x5c, /* FC_PAD */ +/* 746 */ + 0x48, /* FC_VARIABLE_REPEAT */ + 0x49, /* FC_FIXED_OFFSET */ +/* 748 */ NdrFcShort( 0x4 ), /* 4 */ +/* 750 */ NdrFcShort( 0x0 ), /* 0 */ +/* 752 */ NdrFcShort( 0x1 ), /* 1 */ +/* 754 */ NdrFcShort( 0x0 ), /* 0 */ +/* 756 */ NdrFcShort( 0x0 ), /* 0 */ +/* 758 */ 0x12, 0x8, /* FC_UP [simple_pointer] */ +/* 760 */ + 0x25, /* FC_C_WSTRING */ + 0x5c, /* FC_PAD */ +/* 762 */ + 0x5b, /* FC_END */ + + 0x8, /* FC_LONG */ +/* 764 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 766 */ + 0x1a, /* FC_BOGUS_STRUCT */ + 0x3, /* 3 */ +/* 768 */ NdrFcShort( 0x14 ), /* 20 */ +/* 770 */ NdrFcShort( 0x0 ), /* 0 */ +/* 772 */ NdrFcShort( 0x10 ), /* Offset= 16 (788) */ +/* 774 */ 0x36, /* FC_POINTER */ + 0x4c, /* FC_EMBEDDED_COMPLEX */ +/* 776 */ 0x0, /* 0 */ + NdrFcShort( 0xffa1 ), /* Offset= -95 (682) */ + 0x36, /* FC_POINTER */ +/* 780 */ 0x4c, /* FC_EMBEDDED_COMPLEX */ + 0x0, /* 0 */ +/* 782 */ NdrFcShort( 0xffa6 ), /* Offset= -90 (692) */ +/* 784 */ 0x3e, /* FC_STRUCTPAD2 */ + 0x8, /* FC_LONG */ +/* 786 */ 0x5c, /* FC_PAD */ + 0x5b, /* FC_END */ +/* 788 */ + 0x12, 0x0, /* FC_UP */ +/* 790 */ NdrFcShort( 0xffa8 ), /* Offset= -88 (702) */ +/* 792 */ + 0x12, 0x0, /* FC_UP */ +/* 794 */ NdrFcShort( 0xffc4 ), /* Offset= -60 (734) */ +/* 796 */ + 0x11, 0x4, /* FC_RP [alloced_on_stack] */ +/* 798 */ NdrFcShort( 0x2 ), /* Offset= 2 (800) */ +/* 800 */ 0x30, /* FC_BIND_CONTEXT */ + 0xa0, /* Ctxt flags: via ptr, out, */ +/* 802 */ 0x2, /* 2 */ + 0x1, /* 1 */ +/* 804 */ + 0x11, 0x4, /* FC_RP [alloced_on_stack] */ +/* 806 */ NdrFcShort( 0x2 ), /* Offset= 2 (808) */ +/* 808 */ 0x30, /* FC_BIND_CONTEXT */ + 0xe1, /* Ctxt flags: via ptr, in, out, can't be null */ +/* 810 */ 0x3, /* 3 */ + 0x0, /* 0 */ +/* 812 */ + 0x11, 0x4, /* FC_RP [alloced_on_stack] */ +/* 814 */ NdrFcShort( 0x2 ), /* Offset= 2 (816) */ +/* 816 */ 0x30, /* FC_BIND_CONTEXT */ + 0xe1, /* Ctxt flags: via ptr, in, out, can't be null */ +/* 818 */ 0x0, /* 0 */ + 0x0, /* 0 */ +/* 820 */ + 0x1b, /* FC_CARRAY */ + 0x0, /* 0 */ +/* 822 */ NdrFcShort( 0x1 ), /* 1 */ +/* 824 */ 0x40, /* Corr desc: constant, val=32768 */ + 0x0, /* 0 */ +/* 826 */ NdrFcShort( 0x8000 ), /* -32768 */ +/* 828 */ NdrFcShort( 0x1 ), /* Corr flags: early, */ +/* 830 */ 0x1, /* FC_BYTE */ + 0x5b, /* FC_END */ + + 0x0 + } + }; + +static const unsigned short TsProxyRpcInterface_FormatStringOffsetTable[] = + { + 0, + 28, + 82, + 136, + 196, + 256, + 284, + 326, + 368, + 408 + }; + + +static const MIDL_STUB_DESC TsProxyRpcInterface_StubDesc = + { + (void *)& TsProxyRpcInterface___RpcClientInterface, + MIDL_user_allocate, + MIDL_user_free, + { &TsProxyRpcInterface__MIDL_AutoBindHandle }, + 0, + 0, + 0, + 0, + ms2Dtsgu__MIDL_TypeFormatString.Format, + 1, /* -error bounds_check flag */ + 0x50002, /* Ndr library version */ + 0, + 0x700022b, /* MIDL Version 7.0.555 */ + 0, + 0, + 0, /* notify & notify_flag routine table */ + 0x1, /* MIDL flag */ + 0, /* cs routines */ + 0, /* proxy/server info */ + 0 + }; + +/** + * END OF GENERATED CODE + */ + +uint8 tsg_packet1[108] = +{ + 0x43, 0x56, 0x00, 0x00, 0x43, 0x56, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x52, 0x54, 0x43, 0x56, + 0x04, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, + 0x8A, 0xE3, 0x13, 0x71, 0x02, 0xF4, 0x36, 0x71, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x40, 0x28, 0x00, 0xDD, 0x65, 0xE2, 0x44, 0xAF, 0x7D, 0xCD, 0x42, 0x85, 0x60, 0x3C, 0xDB, + 0x6E, 0x7A, 0x27, 0x29, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C, 0xC9, 0x11, + 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00 +}; + +/** + TsProxyCreateTunnel + + 0x43, 0x56, 0x00, 0x00, packetId (TSG_PACKET_TYPE_VERSIONCAPS) + + TSG_PACKET + 0x43, 0x56, 0x00, 0x00, SwitchValue (TSG_PACKET_TYPE_VERSIONCAPS) + + 0x00, 0x00, 0x02, 0x00, NdrPtr + + 0x52, 0x54, componentId + 0x43, 0x56, packetId + + 0x04, 0x00, 0x02, 0x00, NdrPtr TsgCapsPtr + 0x01, 0x00, 0x00, 0x00, numCapabilities + + 0x01, 0x00, MajorVersion + 0x01, 0x00, MinorVersion + 0x00, 0x00, QuarantineCapabilities + + 0x00, 0x00, alignment pad? + + 0x01, 0x00, 0x00, 0x00, MaximumCount + 0x01, 0x00, 0x00, 0x00, TSG_CAPABILITY_TYPE_NAP + + 0x01, 0x00, 0x00, 0x00, SwitchValue (TSG_NAP_CAPABILITY_QUAR_SOH) + 0x1F, 0x00, 0x00, 0x00, idle value in minutes? + + 0x8A, 0xE3, 0x13, 0x71, 0x02, 0xF4, 0x36, 0x71, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x40, 0x28, 0x00, 0xDD, 0x65, 0xE2, 0x44, 0xAF, 0x7D, 0xCD, 0x42, 0x85, 0x60, 0x3C, 0xDB, + 0x6E, 0x7A, 0x27, 0x29, 0x01, 0x00, 0x03, 0x00, 0x04, 0x5D, 0x88, 0x8A, 0xEB, 0x1C, 0xC9, 0x11, + 0x9F, 0xE8, 0x08, 0x00, 0x2B, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00 + */ + +/** + * TsProxyCreateTunnelResponse + * + 05 00 02 03 10 00 00 00 50 09 10 00 01 00 00 00 + 14 09 00 00 00 00 00 00 00 00 02 00 + + 50 43 00 00 TSG_PACKET_TYPE_CAPS_RESPONSE + 50 43 00 00 TSG_PACKET_TYPE_CAPS_RESPONSE + Ptr: 04 00 02 00 + flags: 00 00 00 00 + certChainLen: 39 04 00 00 (1081 * 2 = 2162) + certChainDataPtr: 08 00 02 00 + + GUID? + 95 87 a1 e6 51 6e 6e 4f 90 66 49 4f 9b c2 40 ff + 0c 00 02 00 01 00 00 00 01 00 00 00 00 00 00 00 + 01 00 00 00 + + Ptr: 14 00 02 00 + MaxCount: 39 04 00 00 + Offset: 00 00 00 00 + ActualCount: 39 04 00 00 + + end offset = 105 + 2162 = 2267 (0x08DB) + + 2d 00 2d 00 2d 00 2d 00 ....9...-.-.-.-. + 0070 2d 00 42 00 45 00 47 00 49 00 4e 00 20 00 43 00 -.B.E.G.I.N. .C. + 0080 45 00 52 00 54 00 49 00 46 00 49 00 43 00 41 00 E.R.T.I.F.I.C.A. + 0090 54 00 45 00 2d 00 2d 00 2d 00 2d 00 2d 00 0d 00 T.E.-.-.-.-.-... + 00a0 0a 00 4d 00 49 00 49 00 43 00 34 00 6a 00 43 00 ..M.I.I.C.4.j.C. + 00b0 43 00 41 00 63 00 71 00 67 00 41 00 77 00 49 00 C.A.c.q.g.A.w.I. + 00c0 42 00 41 00 67 00 49 00 51 00 4a 00 38 00 4f 00 B.A.g.I.Q.J.8.O. + 00d0 48 00 6a 00 65 00 66 00 37 00 4e 00 34 00 78 00 H.j.e.f.7.N.4.x. + 00e0 43 00 39 00 30 00 36 00 49 00 53 00 33 00 34 00 C.9.0.6.I.S.3.4. + 00f0 75 00 76 00 54 00 41 00 4e 00 42 00 67 00 6b 00 u.v.T.A.N.B.g.k. + 0100 71 00 68 00 6b 00 69 00 47 00 39 00 77 00 30 00 q.h.k.i.G.9.w.0. + 0110 42 00 41 00 51 00 55 00 46 00 41 00 44 00 41 00 B.A.Q.U.F.A.D.A. + 0120 61 00 0d 00 0a 00 4d 00 52 00 67 00 77 00 46 00 a.....M.R.g.w.F. + 0130 67 00 59 00 44 00 56 00 51 00 51 00 44 00 45 00 g.Y.D.V.Q.Q.D.E. + 0140 77 00 39 00 58 00 53 00 55 00 34 00 74 00 4e 00 w.9.X.S.U.4.t.N. + 0150 7a 00 56 00 46 00 52 00 45 00 4e 00 51 00 52 00 z.V.F.R.E.N.Q.R. + 0160 30 00 64 00 4e 00 52 00 7a 00 6b 00 77 00 48 00 0.d.N.R.z.k.w.H. + 0170 68 00 63 00 4e 00 4d 00 54 00 49 00 77 00 4d 00 h.c.N.M.T.I.w.M. + 0180 7a 00 49 00 34 00 4d 00 44 00 4d 00 77 00 4d 00 z.I.4.M.D.M.w.M. + 0190 54 00 45 00 32 00 57 00 68 00 63 00 4e 00 4d 00 T.E.2.W.h.c.N.M. + 01a0 6a 00 49 00 77 00 0d 00 0a 00 4d 00 7a 00 49 00 j.I.w.....M.z.I. + 01b0 33 00 4d 00 44 00 41 00 77 00 4d 00 44 00 41 00 3.M.D.A.w.M.D.A. + 01c0 77 00 57 00 6a 00 41 00 61 00 4d 00 52 00 67 00 w.W.j.A.a.M.R.g. + 01d0 77 00 46 00 67 00 59 00 44 00 56 00 51 00 51 00 w.F.g.Y.D.V.Q.Q. + 01e0 44 00 45 00 77 00 39 00 58 00 53 00 55 00 34 00 D.E.w.9.X.S.U.4. + 01f0 74 00 4e 00 7a 00 56 00 46 00 52 00 45 00 4e 00 t.N.z.V.F.R.E.N. + 0200 51 00 52 00 30 00 64 00 4e 00 52 00 7a 00 6b 00 Q.R.0.d.N.R.z.k. + 0210 77 00 67 00 67 00 45 00 69 00 4d 00 41 00 30 00 w.g.g.E.i.M.A.0. + 0220 47 00 43 00 53 00 71 00 47 00 0d 00 0a 00 53 00 G.C.S.q.G.....S. + 0230 49 00 62 00 33 00 44 00 51 00 45 00 42 00 41 00 I.b.3.D.Q.E.B.A. + 0240 51 00 55 00 41 00 41 00 34 00 49 00 42 00 44 00 Q.U.A.A.4.I.B.D. + 0250 77 00 41 00 77 00 67 00 67 00 45 00 4b 00 41 00 w.A.w.g.g.E.K.A. + 0260 6f 00 49 00 42 00 41 00 51 00 43 00 6e 00 78 00 o.I.B.A.Q.C.n.x. + 0270 55 00 63 00 32 00 68 00 2b 00 4c 00 5a 00 64 00 U.c.2.h.+.L.Z.d. + 0280 42 00 65 00 56 00 61 00 79 00 35 00 52 00 36 00 B.e.V.a.y.5.R.6. + 0290 68 00 70 00 36 00 47 00 31 00 2b 00 75 00 2f 00 h.p.6.G.1.+.u./. + 02a0 59 00 33 00 7a 00 63 00 33 00 33 00 47 00 0d 00 Y.3.z.c.3.3.G... + 02b0 0a 00 66 00 4c 00 62 00 4f 00 53 00 62 00 48 00 ..f.L.b.O.S.b.H. + 02c0 71 00 6d 00 4e 00 31 00 42 00 4e 00 57 00 79 00 q.m.N.1.B.N.W.y. + 02d0 44 00 7a 00 51 00 66 00 5a 00 71 00 30 00 54 00 D.z.Q.f.Z.q.0.T. + 02e0 35 00 30 00 4b 00 70 00 54 00 61 00 49 00 71 00 5.0.K.p.T.a.I.q. + 02f0 65 00 33 00 58 00 65 00 51 00 4f 00 45 00 63 00 e.3.X.e.Q.O.E.c. + 0300 42 00 33 00 4b 00 78 00 56 00 6a 00 78 00 46 00 B.3.K.x.V.j.x.F. + 0310 46 00 75 00 47 00 67 00 6d 00 57 00 4d 00 55 00 F.u.G.g.m.W.M.U. + 0320 6d 00 7a 00 37 00 79 00 77 00 49 00 49 00 75 00 m.z.7.y.w.I.I.u. + 0330 38 00 0d 00 0a 00 33 00 52 00 56 00 44 00 39 00 8.....3.R.V.D.9. + 0340 36 00 73 00 42 00 30 00 6b 00 31 00 6a 00 37 00 6.s.B.0.k.1.j.7. + 0350 70 00 30 00 4d 00 54 00 6f 00 4a 00 6a 00 71 00 p.0.M.T.o.J.j.q. + 0360 4a 00 45 00 78 00 51 00 56 00 6d 00 48 00 44 00 J.E.x.Q.V.m.H.D. + 0370 72 00 56 00 46 00 2f 00 63 00 4f 00 77 00 6a 00 r.V.F./.c.O.w.j. + 0380 35 00 59 00 69 00 35 00 42 00 33 00 47 00 57 00 5.Y.i.5.B.3.G.W. + 0390 38 00 65 00 65 00 37 00 5a 00 45 00 52 00 30 00 8.e.e.7.Z.E.R.0. + 03a0 76 00 63 00 62 00 4f 00 34 00 59 00 70 00 4c 00 v.c.b.O.4.Y.p.L. + 03b0 64 00 58 00 41 00 0d 00 0a 00 65 00 6f 00 6f 00 d.X.A.....e.o.o. + 03c0 62 00 48 00 6f 00 37 00 7a 00 73 00 65 00 59 00 b.H.o.7.z.s.e.Y. + 03d0 57 00 31 00 37 00 72 00 54 00 4b 00 79 00 73 00 W.1.7.r.T.K.y.s. + 03e0 65 00 59 00 52 00 69 00 6a 00 32 00 6a 00 76 00 e.Y.R.i.j.2.j.v. + 03f0 63 00 6e 00 75 00 6f 00 52 00 72 00 4a 00 48 00 c.n.u.o.R.r.J.H. + 0400 58 00 78 00 36 00 41 00 44 00 64 00 6f 00 57 00 X.x.6.A.D.d.o.W. + 0410 37 00 58 00 4e 00 69 00 39 00 59 00 75 00 55 00 7.X.N.i.9.Y.u.U. + 0420 4a 00 46 00 35 00 6b 00 51 00 46 00 34 00 64 00 J.F.5.k.Q.F.4.d. + 0430 6b 00 73 00 6c 00 5a 00 72 00 0d 00 0a 00 49 00 k.s.l.Z.r.....I. + 0440 44 00 50 00 50 00 6b 00 30 00 68 00 44 00 78 00 D.P.P.k.0.h.D.x. + 0450 6d 00 61 00 49 00 6c 00 5a 00 6a 00 47 00 6a 00 m.a.I.l.Z.j.G.j. + 0460 70 00 55 00 65 00 69 00 47 00 50 00 2b 00 57 00 p.U.e.i.G.P.+.W. + 0470 46 00 68 00 72 00 4d 00 6d 00 6f 00 6b 00 6f 00 F.h.r.M.m.o.k.o. + 0480 46 00 78 00 7a 00 2f 00 70 00 7a 00 61 00 38 00 F.x.z./.p.z.a.8. + 0490 5a 00 4c 00 50 00 4f 00 4a 00 64 00 51 00 76 00 Z.L.P.O.J.d.Q.v. + 04a0 6c 00 31 00 52 00 78 00 34 00 61 00 6e 00 64 00 l.1.R.x.4.a.n.d. + 04b0 43 00 38 00 4d 00 79 00 59 00 47 00 2b 00 0d 00 C.8.M.y.Y.G.+... + 04c0 0a 00 50 00 57 00 62 00 74 00 62 00 44 00 43 00 ..P.W.b.t.b.D.C. + 04d0 31 00 33 00 41 00 71 00 2f 00 44 00 4d 00 4c 00 1.3.A.q./.D.M.L. + 04e0 49 00 56 00 6b 00 6c 00 41 00 65 00 4e 00 6f 00 I.V.k.l.A.e.N.o. + 04f0 78 00 32 00 43 00 61 00 4a 00 65 00 67 00 30 00 x.2.C.a.J.e.g.0. + 0500 56 00 2b 00 48 00 6d 00 46 00 6b 00 70 00 59 00 V.+.H.m.F.k.p.Y. + 0510 68 00 75 00 34 00 6f 00 33 00 6b 00 38 00 6e 00 h.u.4.o.3.k.8.n. + 0520 58 00 5a 00 37 00 7a 00 35 00 41 00 67 00 4d 00 X.Z.7.z.5.A.g.M. + 0530 42 00 41 00 41 00 47 00 6a 00 4a 00 44 00 41 00 B.A.A.G.j.J.D.A. + 0540 69 00 0d 00 0a 00 4d 00 41 00 73 00 47 00 41 00 i.....M.A.s.G.A. + 0550 31 00 55 00 64 00 44 00 77 00 51 00 45 00 41 00 1.U.d.D.w.Q.E.A. + 0560 77 00 49 00 45 00 4d 00 44 00 41 00 54 00 42 00 w.I.E.M.D.A.T.B. + 0570 67 00 4e 00 56 00 48 00 53 00 55 00 45 00 44 00 g.N.V.H.S.U.E.D. + 0580 44 00 41 00 4b 00 42 00 67 00 67 00 72 00 42 00 D.A.K.B.g.g.r.B. + 0590 67 00 45 00 46 00 42 00 51 00 63 00 44 00 41 00 g.E.F.B.Q.c.D.A. + 05a0 54 00 41 00 4e 00 42 00 67 00 6b 00 71 00 68 00 T.A.N.B.g.k.q.h. + 05b0 6b 00 69 00 47 00 39 00 77 00 30 00 42 00 41 00 k.i.G.9.w.0.B.A. + 05c0 51 00 55 00 46 00 0d 00 0a 00 41 00 41 00 4f 00 Q.U.F.....A.A.O. + 05d0 43 00 41 00 51 00 45 00 41 00 52 00 33 00 74 00 C.A.Q.E.A.R.3.t. + 05e0 67 00 2f 00 6e 00 41 00 69 00 73 00 41 00 46 00 g./.n.A.i.s.A.F. + 05f0 42 00 50 00 66 00 5a 00 42 00 68 00 5a 00 31 00 B.P.f.Z.B.h.Z.1. + 0600 71 00 55 00 53 00 74 00 55 00 52 00 32 00 5a 00 q.U.S.t.U.R.2.Z. + 0610 32 00 5a 00 6a 00 55 00 49 00 42 00 70 00 64 00 2.Z.j.U.I.B.p.d. + 0620 68 00 5a 00 4e 00 32 00 64 00 50 00 6b 00 6f 00 h.Z.N.2.d.P.k.o. + 0630 4d 00 6c 00 32 00 4b 00 4f 00 6b 00 66 00 4d 00 M.l.2.K.O.k.f.M. + 0640 4e 00 6d 00 45 00 44 00 45 00 0d 00 0a 00 68 00 N.m.E.D.E.....h. + 0650 72 00 6e 00 56 00 74 00 71 00 54 00 79 00 65 00 r.n.V.t.q.T.y.e. + 0660 50 00 32 00 4e 00 52 00 71 00 78 00 67 00 48 00 P.2.N.R.q.x.g.H. + 0670 46 00 2b 00 48 00 2f 00 6e 00 4f 00 78 00 37 00 F.+.H./.n.O.x.7. + 0680 78 00 6d 00 66 00 49 00 72 00 4c 00 31 00 77 00 x.m.f.I.r.L.1.w. + 0690 45 00 6a 00 63 00 37 00 41 00 50 00 6c 00 37 00 E.j.c.7.A.P.l.7. + 06a0 4b 00 61 00 39 00 4b 00 6a 00 63 00 65 00 6f 00 K.a.9.K.j.c.e.o. + 06b0 4f 00 4f 00 6f 00 68 00 31 00 32 00 6c 00 2f 00 O.O.o.h.1.2.l./. + 06c0 39 00 48 00 53 00 70 00 38 00 30 00 37 00 0d 00 9.H.S.p.8.0.7... + 06d0 0a 00 4f 00 57 00 4d 00 69 00 48 00 41 00 4a 00 ..O.W.M.i.H.A.J. + 06e0 6e 00 66 00 47 00 32 00 46 00 46 00 37 00 6e 00 n.f.G.2.F.F.7.n. + 06f0 51 00 61 00 74 00 63 00 35 00 4e 00 53 00 42 00 Q.a.t.c.5.N.S.B. + 0700 38 00 4e 00 75 00 4f 00 5a 00 67 00 64 00 62 00 8.N.u.O.Z.g.d.b. + 0710 67 00 51 00 2b 00 43 00 42 00 62 00 39 00 76 00 g.Q.+.C.B.b.9.v. + 0720 2b 00 4d 00 56 00 55 00 33 00 43 00 67 00 39 00 +.M.V.U.3.C.g.9. + 0730 4c 00 57 00 65 00 54 00 53 00 2b 00 51 00 78 00 L.W.e.T.S.+.Q.x. + 0740 79 00 59 00 6c 00 37 00 4f 00 30 00 4c 00 43 00 y.Y.l.7.O.0.L.C. + 0750 4d 00 0d 00 0a 00 76 00 45 00 37 00 77 00 4a 00 M.....v.E.7.w.J. + 0760 58 00 53 00 70 00 70 00 4a 00 4c 00 42 00 6b 00 X.S.p.p.J.L.B.k. + 0770 69 00 52 00 72 00 63 00 73 00 51 00 6e 00 34 00 i.R.r.c.s.Q.n.4. + 0780 61 00 39 00 62 00 64 00 67 00 56 00 67 00 6b 00 a.9.b.d.g.V.g.k. + 0790 57 00 32 00 78 00 70 00 7a 00 56 00 4e 00 6d 00 W.2.x.p.z.V.N.m. + 07a0 6e 00 62 00 42 00 35 00 73 00 49 00 49 00 38 00 n.b.B.5.s.I.I.8. + 07b0 35 00 75 00 7a 00 37 00 78 00 76 00 46 00 47 00 5.u.z.7.x.v.F.G. + 07c0 50 00 47 00 65 00 70 00 4c 00 55 00 55 00 55 00 P.G.e.p.L.U.U.U. + 07d0 76 00 66 00 66 00 0d 00 0a 00 36 00 76 00 68 00 v.f.f.....6.v.h. + 07e0 56 00 46 00 5a 00 76 00 62 00 53 00 47 00 73 00 V.F.Z.v.b.S.G.s. + 07f0 77 00 6f 00 72 00 32 00 5a 00 6c 00 54 00 6c 00 w.o.r.2.Z.l.T.l. + 0800 79 00 57 00 70 00 79 00 67 00 5a 00 67 00 71 00 y.W.p.y.g.Z.g.q. + 0810 49 00 46 00 56 00 6f 00 73 00 43 00 4f 00 33 00 I.F.V.o.s.C.O.3. + 0820 34 00 39 00 53 00 65 00 2b 00 55 00 45 00 72 00 4.9.S.e.+.U.E.r. + 0830 72 00 54 00 48 00 46 00 7a 00 71 00 38 00 63 00 r.T.H.F.z.q.8.c. + 0840 76 00 7a 00 4b 00 76 00 63 00 6b 00 4f 00 75 00 v.z.K.v.c.k.O.u. + 0850 4f 00 6b 00 42 00 72 00 42 00 0d 00 0a 00 6c 00 O.k.B.r.B.....l. + 0860 69 00 79 00 4e 00 32 00 47 00 42 00 41 00 6f 00 i.y.N.2.G.B.A.o. + 0870 50 00 45 00 67 00 79 00 4d 00 48 00 41 00 35 00 P.E.g.y.M.H.A.5. + 0880 53 00 78 00 39 00 5a 00 39 00 37 00 35 00 75 00 S.x.9.Z.9.7.5.u. + 0890 6e 00 7a 00 50 00 74 00 77 00 3d 00 3d 00 0d 00 n.z.P.t.w.=.=... + 08a0 0a 00 2d 00 2d 00 2d 00 2d 00 2d 00 45 00 4e 00 ..-.-.-.-.-.E.N. + 08b0 44 00 20 00 43 00 45 00 52 00 54 00 49 00 46 00 D. .C.E.R.T.I.F. + 08c0 49 00 43 00 41 00 54 00 45 00 2d 00 2d 00 2d 00 I.C.A.T.E.-.-.-. + 08d0 2d 00 2d 00 0d 00 0a 00 00 00 + + 00 00 alignment pad? + + 52 54 componentId + 43 56 packetId (TSG_PACKET_TYPE_VERSIONCAPS) + TsgCapsPtr: 10 00 02 00 + NumCapabilities: 01 00 00 00 + MajorVersion: 01 00 + MinorVersion: 01 00 + quarantineCapabilities: 01 00 + pad: 00 00 + NumCapabilitiesConf: + MaxCount: 01 00 00 00 + + tsgCaps: 01 00 00 00 (TSG_CAPABILITY_TYPE_NAP) + SwitchValue: 01 00 00 00 (TSG_CAPABILITY_TYPE_NAP) + capabilities: 1f 00 00 00 = + TSG_NAP_CAPABILITY_QUAR_SOH | + TSG_NAP_CAPABILITY_IDLE_TIMEOUT | + TSG_MESSAGING_CAP_CONSENT_SIGN | + TSG_MESSAGING_CAP_SERVICE_MSG | + TSG_MESSAGING_CAP_REAUTH + + 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ?? + + TunnelContext: + ContextType: 00 00 00 00 + ContextUuid: 81 1d 32 9f 3f ff 8d 41 ae 54 ba e4 7b b7 ef 43 + + 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ?? + 00 00 00 00 0a 05 0c 00 00 00 00 00 01 00 00 00 + 9d 13 89 41 + + UINT32 TunnelId: 2e 85 76 3f + HRESULT ReturnValue: 00 00 00 00 + */ + +uint8 tsg_packet2[112] = +{ + 0x00, 0x00, 0x00, 0x00, 0x6A, 0x78, 0xE9, 0xAB, 0x02, 0x90, 0x1C, 0x44, 0x8D, 0x99, 0x29, 0x30, + 0x53, 0x6C, 0x04, 0x33, 0x52, 0x51, 0x00, 0x00, 0x52, 0x51, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x15, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, + 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x2D, 0x00, 0x4E, 0x00, 0x48, 0x00, 0x35, 0x00, 0x37, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x43, 0x00, 0x53, 0x00, 0x4F, 0x00, 0x44, 0x00, 0x2E, 0x00, 0x6C, 0x00, + 0x6F, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +/** + TsProxyAuthorizeTunnel + + TunnelContext: + ContextType: 0x00, 0x00, 0x00, 0x00, + ContextUuid: 0x6A, 0x78, 0xE9, 0xAB, 0x02, 0x90, 0x1C, 0x44, + 0x8D, 0x99, 0x29, 0x30, 0x53, 0x6C, 0x04, 0x33, + + TsgPacket: + PacketId: 0x52, 0x51, 0x00, 0x00, + SwitchValue: 0x52, 0x51, 0x00, 0x00, + + PacketQuarRequestPtr: 0x00, 0x00, 0x02, 0x00, + PacketQuarRequest: + Flags: 0x00, 0x00, 0x00, 0x00, + MachineNamePtr: 0x04, 0x00, 0x02, 0x00, + NameLength: 0x15, 0x00, 0x00, 0x00, + DataPtr: 0x08, 0x00, 0x02, 0x00, + DataLen: 0x00, 0x00, 0x00, 0x00, + MachineName: + MaxCount: 0x15, 0x00, 0x00, 0x00, (21 elements) + Offset: 0x00, 0x00, 0x00, 0x00, + ActualCount: 0x15, 0x00, 0x00, 0x00, (21 elements) + Array: 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x2D, 0x00, + 0x4E, 0x00, 0x48, 0x00, 0x35, 0x00, 0x37, 0x00, + 0x30, 0x00, 0x2E, 0x00, 0x43, 0x00, 0x53, 0x00, + 0x4F, 0x00, 0x44, 0x00, 0x2E, 0x00, 0x6C, 0x00, + 0x6F, 0x00, 0x63, 0x00, 0x61, 0x00, 0x6C, 0x00, + 0x00, 0x00, + + DataLenConf: + MaxCount: 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + */ + +uint8 tsg_packet3[40] = +{ + 0x00, 0x00, 0x00, 0x00, 0x6A, 0x78, 0xE9, 0xAB, 0x02, 0x90, 0x1C, 0x44, 0x8D, 0x99, 0x29, 0x30, + 0x53, 0x6C, 0x04, 0x33, 0x01, 0x00, 0x00, 0x00, 0x52, 0x47, 0x00, 0x00, 0x52, 0x47, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00 +}; + +/** + TsProxyMakeTunnelCall + + 0x00, 0x00, 0x00, 0x00, 0x6A, 0x78, 0xE9, 0xAB, 0x02, 0x90, 0x1C, 0x44, 0x8D, 0x99, 0x29, 0x30, + 0x53, 0x6C, 0x04, 0x33, 0x01, 0x00, 0x00, 0x00, + + 0x52, 0x47, 0x00, 0x00, + 0x52, 0x47, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x00 + */ + +uint8 tsg_packet4[48] = +{ + 0x00, 0x00, 0x00, 0x00, 0x6A, 0x78, 0xE9, 0xAB, 0x02, 0x90, 0x1C, 0x44, 0x8D, 0x99, 0x29, 0x30, + 0x53, 0x6C, 0x04, 0x33, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00 +}; + +/** + TsProxyCreateChannel + + 0x00, 0x00, 0x00, 0x00, 0x6A, 0x78, 0xE9, 0xAB, 0x02, 0x90, 0x1C, 0x44, 0x8D, 0x99, 0x29, 0x30, + 0x53, 0x6C, 0x04, 0x33, 0x00, 0x00, 0x02, 0x00, + + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00 + */ + +uint8 tsg_packet5[20] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 +}; + +DWORD TsProxySendToServer(handle_t IDL_handle, byte pRpcMessage[], uint32 count, uint32* lengths) +{ + STREAM* s; + int status; + int length; + rdpTsg* tsg; + byte* buffer1; + byte* buffer2; + byte* buffer3; + uint32 buffer1Length; + uint32 buffer2Length; + uint32 buffer3Length; + uint32 numBuffers = 0; + uint32 totalDataBytes = 0; + + tsg = (rdpTsg*) IDL_handle; + buffer1Length = buffer2Length = buffer3Length = 0; + + if (count > 0) + { + numBuffers++; + buffer1 = &pRpcMessage[0]; + buffer1Length = lengths[0]; + totalDataBytes += lengths[0] + 4; + } + + if (count > 1) + { + numBuffers++; + buffer2 = &pRpcMessage[1]; + buffer2Length = lengths[1]; + totalDataBytes += lengths[1] + 4; + } + + if (count > 2) + { + numBuffers++; + buffer3 = &pRpcMessage[2]; + buffer3Length = lengths[2]; + totalDataBytes += lengths[2] + 4; + } + + s = stream_new(28 + totalDataBytes); + + /* PCHANNEL_CONTEXT_HANDLE_NOSERIALIZE_NR (20 bytes) */ + stream_write_uint32(s, 0); /* ContextType (4 bytes) */ + stream_write(s, tsg->ChannelContext, 16); /* ContextUuid (4 bytes) */ + + stream_write_uint32_be(s, totalDataBytes); /* totalDataBytes (4 bytes) */ + stream_write_uint32_be(s, numBuffers); /* numBuffers (4 bytes) */ + + if (buffer1Length > 0) + stream_write_uint32_be(s, buffer1Length); /* buffer1Length (4 bytes) */ + if (buffer2Length > 0) + stream_write_uint32_be(s, buffer2Length); /* buffer2Length (4 bytes) */ + if (buffer3Length > 0) + stream_write_uint32_be(s, buffer3Length); /* buffer3Length (4 bytes) */ + + if (buffer1Length > 0) + stream_write(s, buffer1, buffer1Length); /* buffer1 (variable) */ + if (buffer2Length > 0) + stream_write(s, buffer2, buffer2Length); /* buffer2 (variable) */ + if (buffer3Length > 0) + stream_write(s, buffer3, buffer3Length); /* buffer3 (variable) */ + + stream_seal(s); + + length = s->size; + status = rpc_tsg_write(tsg->rpc, s->data, s->size, 9); + + stream_free(s); + + if (status <= 0) + { + printf("rpc_tsg_write failed!\n"); + return -1; + } + + return length; +} + +#ifndef WITH_MSRPC +boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port) +{ + uint8* data; + uint32 length; + STREAM* s_p4; + int status = -1; + UNICONV* tsg_uniconv; + rdpRpc* rpc = tsg->rpc; + uint8* dest_addr_unic; + uint32 dest_addr_unic_len; + + if (!rpc_connect(rpc)) + { + printf("rpc_connect failed!\n"); + return false; + } + + DEBUG_TSG("rpc_connect success"); + + /** + * OpNum = 1 + * + * HRESULT TsProxyCreateTunnel( + * [in, ref] PTSG_PACKET tsgPacket, + * [out, ref] PTSG_PACKET* tsgPacketResponse, + * [out] PTUNNEL_CONTEXT_HANDLE_SERIALIZE* tunnelContext, + * [out] unsigned long* tunnelId + * ); + */ + + DEBUG_TSG("TsProxyCreateTunnel"); + status = rpc_tsg_write(rpc, tsg_packet1, sizeof(tsg_packet1), 1); + + if (status <= 0) + { + printf("rpc_write opnum=1 failed!\n"); + return false; + } + + length = 0x8FFF; + data = xmalloc(length); + status = rpc_read(rpc, data, length); + + if (status <= 0) + { + printf("rpc_recv failed!\n"); + return false; + } + + memcpy(tsg->TunnelContext, data + (status - 24), 16); + +#ifdef WITH_DEBUG_TSG + printf("TSG TunnelContext:\n"); + freerdp_hexdump(tsg->TunnelContext, 16); + printf("\n"); +#endif + + memcpy(tsg_packet2 + 4, tsg->TunnelContext, 16); + + /** + * OpNum = 2 + * + * HRESULT TsProxyAuthorizeTunnel( + * [in] PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, + * [in, ref] PTSG_PACKET tsgPacket, + * [out, ref] PTSG_PACKET* tsgPacketResponse + * ); + * + */ + + DEBUG_TSG("TsProxyAuthorizeTunnel"); + status = rpc_tsg_write(rpc, tsg_packet2, sizeof(tsg_packet2), 2); + + if (status <= 0) + { + printf("rpc_write opnum=2 failed!\n"); + return false; + } + + status = rpc_read(rpc, data, length); + + if (status <= 0) + { + printf("rpc_recv failed!\n"); + return false; + } + + memcpy(tsg_packet3 + 4, tsg->TunnelContext, 16); + + /** + * OpNum = 3 + * + * HRESULT TsProxyMakeTunnelCall( + * [in] PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, + * [in] unsigned long procId, + * [in, ref] PTSG_PACKET tsgPacket, + * [out, ref] PTSG_PACKET* tsgPacketResponse + * ); + */ + + DEBUG_TSG("TsProxyMakeTunnelCall"); + status = rpc_tsg_write(rpc, tsg_packet3, sizeof(tsg_packet3), 3); + + if (status <= 0) + { + printf("rpc_write opnum=3 failed!\n"); + return false; + } + status = -1; + + tsg_uniconv = freerdp_uniconv_new(); + dest_addr_unic = (uint8*) freerdp_uniconv_out(tsg_uniconv, hostname, (size_t*) &dest_addr_unic_len); + freerdp_uniconv_free(tsg_uniconv); + + memcpy(tsg_packet4 + 4, tsg->TunnelContext, 16); + memcpy(tsg_packet4 + 38, &port, 2); + + s_p4 = stream_new(60 + dest_addr_unic_len + 2); + stream_write(s_p4, tsg_packet4, 48); + stream_write_uint32(s_p4, (dest_addr_unic_len / 2) + 1); /* MaximumCount */ + stream_write_uint32(s_p4, 0x00000000); /* Offset */ + stream_write_uint32(s_p4, (dest_addr_unic_len / 2) + 1);/* ActualCount */ + stream_write(s_p4, dest_addr_unic, dest_addr_unic_len); + stream_write_uint16(s_p4, 0x0000); /* unicode zero to terminate hostname string */ + + /** + * OpNum = 4 + * + * HRESULT TsProxyCreateChannel( + * [in] PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, + * [in, ref] PTSENDPOINTINFO tsEndPointInfo, + * [out] PCHANNEL_CONTEXT_HANDLE_SERIALIZE* channelContext, + * [out] unsigned long* channelId + * ); + */ + + DEBUG_TSG("TsProxyCreateChannel"); + status = rpc_tsg_write(rpc, s_p4->data, s_p4->size, 4); + + if (status <= 0) + { + printf("rpc_write opnum=4 failed!\n"); + return false; + } + xfree(dest_addr_unic); + + status = rpc_read(rpc, data, length); + + if (status < 0) + { + printf("rpc_recv failed!\n"); + return false; + } + + memcpy(tsg->ChannelContext, data + 4, 16); + +#ifdef WITH_DEBUG_TSG + printf("TSG ChannelContext:\n"); + freerdp_hexdump(tsg->ChannelContext, 16); + printf("\n"); +#endif + + memcpy(tsg_packet5 + 4, tsg->ChannelContext, 16); + + /** + * OpNum = 8 + * + * DWORD TsProxySetupReceivePipe( + * [in, max_is(32767)] byte pRpcMessage[] + * ); + */ + + DEBUG_TSG("TsProxySetupReceivePipe"); + status = rpc_tsg_write(rpc, tsg_packet5, sizeof(tsg_packet5), 8); + + if (status <= 0) + { + printf("rpc_write opnum=8 failed!\n"); + return false; + } + + return true; +} +#else +boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port) +{ + uint8* data; + uint32 length; + STREAM* s_p4; + int status = -1; + UNICONV* tsg_uniconv; + rdpRpc* rpc = tsg->rpc; + uint8* dest_addr_unic; + uint32 dest_addr_unic_len; + + if (!rpc_connect(rpc)) + { + printf("rpc_connect failed!\n"); + return false; + } + + DEBUG_TSG("rpc_connect success"); + + /** + * OpNum = 1 + * + * HRESULT TsProxyCreateTunnel( + * [in, ref] PTSG_PACKET tsgPacket, + * [out, ref] PTSG_PACKET* tsgPacketResponse, + * [out] PTUNNEL_CONTEXT_HANDLE_SERIALIZE* tunnelContext, + * [out] unsigned long* tunnelId + * ); + */ + + DEBUG_TSG("TsProxyCreateTunnel"); + + { + TSG_PACKET tsgPacket; + PTSG_PACKET tsgPacketResponse; + PTUNNEL_CONTEXT_HANDLE_SERIALIZE tunnelContext; + unsigned long tunnelId; + + TsProxyCreateTunnel(&tsgPacket, &tsgPacketResponse, &tunnelContext, &tunnelId); + } + + /** + * OpNum = 2 + * + * HRESULT TsProxyAuthorizeTunnel( + * [in] PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, + * [in, ref] PTSG_PACKET tsgPacket, + * [out, ref] PTSG_PACKET* tsgPacketResponse + * ); + * + */ + + DEBUG_TSG("TsProxyAuthorizeTunnel"); + + { + TSG_PACKET tsgPacket; + PTSG_PACKET tsgPacketResponse; + PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext; + + TsProxyAuthorizeTunnel(&tunnelContext, &tsgPacket, &tsgPacketResponse); + } + + /** + * OpNum = 3 + * + * HRESULT TsProxyMakeTunnelCall( + * [in] PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, + * [in] unsigned long procId, + * [in, ref] PTSG_PACKET tsgPacket, + * [out, ref] PTSG_PACKET* tsgPacketResponse + * ); + */ + + DEBUG_TSG("TsProxyMakeTunnelCall"); + + { + TSG_PACKET tsgPacket; + PTSG_PACKET tsgPacketResponse; + PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext; + + TsProxyMakeTunnelCall(&tunnelContext, 0, &tsgPacket, &tsgPacketResponse); + } + + /** + * OpNum = 4 + * + * HRESULT TsProxyCreateChannel( + * [in] PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, + * [in, ref] PTSENDPOINTINFO tsEndPointInfo, + * [out] PCHANNEL_CONTEXT_HANDLE_SERIALIZE* channelContext, + * [out] unsigned long* channelId + * ); + */ + + DEBUG_TSG("TsProxyCreateChannel"); + + { + unsigned long channelId; + TSENDPOINTINFO tsEndPointInfo; + PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext; + PCHANNEL_CONTEXT_HANDLE_SERIALIZE channelContext; + + TsProxyCreateChannel(&tunnelContext, &tsEndPointInfo, &channelContext, &channelId); + } + + /** + * OpNum = 8 + * + * DWORD TsProxySetupReceivePipe( + * [in, max_is(32767)] byte pRpcMessage[] + * ); + */ + + DEBUG_TSG("TsProxySetupReceivePipe"); + + return true; +} +#endif + +int tsg_read(rdpTsg* tsg, uint8* data, uint32 length) +{ + int status; + + status = rpc_read(tsg->rpc, data, length); + + return status; +} + +int tsg_write(rdpTsg* tsg, uint8* data, uint32 length) +{ + return TsProxySendToServer((handle_t) tsg, data, 1, &length); +} + +rdpTsg* tsg_new(rdpTransport* transport) +{ + rdpTsg* tsg; + + tsg = xnew(rdpTsg); + + if (tsg != NULL) + { + tsg->transport = transport; + tsg->settings = transport->settings; + tsg->rpc = rpc_new(tsg->transport); + } + + return tsg; +} + +void tsg_free(rdpTsg* tsg) +{ + if (tsg != NULL) + { + rpc_free(tsg->rpc); + xfree(tsg); + } +} diff --git a/libfreerdp-core/tsg.h b/libfreerdp-core/tsg.h new file mode 100644 index 000000000..ad0adc1ba --- /dev/null +++ b/libfreerdp-core/tsg.h @@ -0,0 +1,279 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Terminal Server Gateway (TSG) + * + * Copyright 2012 Fujitsu Technology Solutions GmbH + * Copyright 2012 Dmitrij Jasnov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FREERDP_CORE_TSG_H +#define FREERDP_CORE_TSG_H + +typedef struct rdp_tsg rdpTsg; + +#include "rpc.h" +#include "transport.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +struct rdp_tsg +{ + rdpRpc* rpc; + rdpSettings* settings; + rdpTransport* transport; + uint8 TunnelContext[16]; + uint8 ChannelContext[16]; +}; + +typedef wchar_t* RESOURCENAME; + +#define MAX_RESOURCE_NAMES 50 + +typedef struct _tsendpointinfo +{ + RESOURCENAME* resourceName; + unsigned long numResourceNames; + RESOURCENAME* alternateResourceNames; + unsigned short numAlternateResourceNames; + unsigned long Port; +} TSENDPOINTINFO, *PTSENDPOINTINFO; + +#define TSG_PACKET_TYPE_HEADER 0x00004844 +#define TSG_PACKET_TYPE_VERSIONCAPS 0x00005643 +#define TSG_PACKET_TYPE_QUARCONFIGREQUEST 0x00005143 +#define TSG_PACKET_TYPE_QUARREQUEST 0x00005152 +#define TSG_PACKET_TYPE_RESPONSE 0x00005052 +#define TSG_PACKET_TYPE_QUARENC_RESPONSE 0x00004552 +#define TSG_CAPABILITY_TYPE_NAP 0x00000001 +#define TSG_PACKET_TYPE_CAPS_RESPONSE 0x00004350 +#define TSG_PACKET_TYPE_MSGREQUEST_PACKET 0x00004752 +#define TSG_PACKET_TYPE_MESSAGE_PACKET 0x00004750 +#define TSG_PACKET_TYPE_AUTH 0x00004054 +#define TSG_PACKET_TYPE_REAUTH 0x00005250 +#define TSG_ASYNC_MESSAGE_CONSENT_MESSAGE 0x00000001 +#define TSG_ASYNC_MESSAGE_SERVICE_MESSAGE 0x00000002 +#define TSG_ASYNC_MESSAGE_REAUTH 0x00000003 +#define TSG_TUNNEL_CALL_ASYNC_MSG_REQUEST 0x00000001 +#define TSG_TUNNEL_CANCEL_ASYNC_MSG_REQUEST 0x00000002 + +#define TSG_NAP_CAPABILITY_QUAR_SOH 0x00000001 +#define TSG_NAP_CAPABILITY_IDLE_TIMEOUT 0x00000002 +#define TSG_MESSAGING_CAP_CONSENT_SIGN 0x00000004 +#define TSG_MESSAGING_CAP_SERVICE_MSG 0x00000008 +#define TSG_MESSAGING_CAP_REAUTH 0x00000010 + +typedef struct _TSG_PACKET_HEADER +{ + unsigned short ComponentId; + unsigned short PacketId; +} TSG_PACKET_HEADER, *PTSG_PACKET_HEADER; + +typedef struct _TSG_CAPABILITY_NAP +{ + unsigned long capabilities; +} TSG_CAPABILITY_NAP, *PTSG_CAPABILITY_NAP; + +typedef union +{ + TSG_CAPABILITY_NAP tsgCapNap; +} TSG_CAPABILITIES_UNION, *PTSG_CAPABILITIES_UNION; + +typedef struct _TSG_PACKET_CAPABILITIES +{ + unsigned long capabilityType; + TSG_CAPABILITIES_UNION tsgPacket; +} TSG_PACKET_CAPABILITIES, *PTSG_PACKET_CAPABILITIES; + +typedef struct _TSG_PACKET_VERSIONCAPS +{ + TSG_PACKET_HEADER tsgHeader; + PTSG_PACKET_CAPABILITIES tsgCaps; + unsigned long numCapabilities; + unsigned short majorVersion; + unsigned short minorVersion; + unsigned short quarantineCapabilities; +} TSG_PACKET_VERSIONCAPS, *PTSG_PACKET_VERSIONCAPS; + +typedef struct _TSG_PACKET_QUARCONFIGREQUEST +{ + unsigned long flags; +} TSG_PACKET_QUARCONFIGREQUEST, *PTSG_PACKET_QUARCONFIGREQUEST; + +typedef struct _TSG_PACKET_QUARREQUEST +{ + unsigned long flags; + wchar_t* machineName; + unsigned long nameLength; + byte* data; + unsigned long dataLen; +} TSG_PACKET_QUARREQUEST, *PTSG_PACKET_QUARREQUEST; + +typedef struct _TSG_REDIRECTION_FLAGS +{ + BOOL enableAllRedirections; + BOOL disableAllRedirections; + BOOL driveRedirectionDisabled; + BOOL printerRedirectionDisabled; + BOOL portRedirectionDisabled; + BOOL reserved; + BOOL clipboardRedirectionDisabled; + BOOL pnpRedirectionDisabled; +} TSG_REDIRECTION_FLAGS, *PTSG_REDIRECTION_FLAGS; + +typedef struct _TSG_PACKET_RESPONSE +{ + unsigned long flags; + unsigned long reserved; + byte* responseData; + unsigned long responseDataLen; + TSG_REDIRECTION_FLAGS redirectionFlags; +} TSG_PACKET_RESPONSE, *PTSG_PACKET_RESPONSE; + +typedef struct _TSG_PACKET_QUARENC_RESPONSE +{ + unsigned long flags; + unsigned long certChainLen; + wchar_t* certChainData; + GUID nonce; + PTSG_PACKET_VERSIONCAPS versionCaps; +} TSG_PACKET_QUARENC_RESPONSE, *PTSG_PACKET_QUARENC_RESPONSE; + +typedef struct TSG_PACKET_STRING_MESSAGE +{ + long isDisplayMandatory; + long isConsentMandatory; + unsigned long msgBytes; + wchar_t* msgBuffer; +} TSG_PACKET_STRING_MESSAGE, *PTSG_PACKET_STRING_MESSAGE; + +typedef struct TSG_PACKET_REAUTH_MESSAGE +{ + unsigned __int64 tunnelContext; +} TSG_PACKET_REAUTH_MESSAGE, *PTSG_PACKET_REAUTH_MESSAGE; + +typedef union +{ + PTSG_PACKET_STRING_MESSAGE consentMessage; + PTSG_PACKET_STRING_MESSAGE serviceMessage; + PTSG_PACKET_REAUTH_MESSAGE reauthMessage; +} TSG_PACKET_TYPE_MESSAGE_UNION, *PTSG_PACKET_TYPE_MESSAGE_UNION; + +typedef struct _TSG_PACKET_MSG_RESPONSE +{ + unsigned long msgID; + unsigned long msgType; + long isMsgPresent; + TSG_PACKET_TYPE_MESSAGE_UNION messagePacket; +} TSG_PACKET_MSG_RESPONSE, *PTSG_PACKET_MSG_RESPONSE; + +typedef struct TSG_PACKET_CAPS_RESPONSE +{ + TSG_PACKET_QUARENC_RESPONSE pktQuarEncResponse; + TSG_PACKET_MSG_RESPONSE pktConsentMessage; +} TSG_PACKET_CAPS_RESPONSE, *PTSG_PACKET_CAPS_RESPONSE; + +typedef struct TSG_PACKET_MSG_REQUEST +{ + unsigned long maxMessagesPerBatch; +} TSG_PACKET_MSG_REQUEST, *PTSG_PACKET_MSG_REQUEST; + +typedef struct _TSG_PACKET_AUTH +{ + TSG_PACKET_VERSIONCAPS tsgVersionCaps; + unsigned long cookieLen; + byte* cookie; +} TSG_PACKET_AUTH, *PTSG_PACKET_AUTH; + +typedef union +{ + PTSG_PACKET_VERSIONCAPS packetVersionCaps; + PTSG_PACKET_AUTH packetAuth; +} TSG_INITIAL_PACKET_TYPE_UNION, *PTSG_INITIAL_PACKET_TYPE_UNION; + +typedef struct TSG_PACKET_REAUTH +{ + unsigned __int64 tunnelContext; + unsigned long packetId; + TSG_INITIAL_PACKET_TYPE_UNION tsgInitialPacket; +} TSG_PACKET_REAUTH, *PTSG_PACKET_REAUTH; + +typedef union +{ + PTSG_PACKET_HEADER packetHeader; + PTSG_PACKET_VERSIONCAPS packetVersionCaps; + PTSG_PACKET_QUARCONFIGREQUEST packetQuarConfigRequest; + PTSG_PACKET_QUARREQUEST packetQuarRequest; + PTSG_PACKET_RESPONSE packetResponse; + PTSG_PACKET_QUARENC_RESPONSE packetQuarEncResponse; + PTSG_PACKET_CAPS_RESPONSE packetCapsResponse; + PTSG_PACKET_MSG_REQUEST packetMsgRequest; + PTSG_PACKET_MSG_RESPONSE packetMsgResponse; + PTSG_PACKET_AUTH packetAuth; + PTSG_PACKET_REAUTH packetReauth; +} TSG_PACKET_TYPE_UNION; + +typedef struct _TSG_PACKET +{ + unsigned long packetId; + TSG_PACKET_TYPE_UNION tsgPacket; +} TSG_PACKET, *PTSG_PACKET; + +void Opnum0NotUsedOnWire(handle_t IDL_handle); + +HRESULT TsProxyCreateTunnel(PTSG_PACKET tsgPacket, PTSG_PACKET* tsgPacketResponse, + PTUNNEL_CONTEXT_HANDLE_SERIALIZE* tunnelContext, unsigned long* tunnelId); + +HRESULT TsProxyAuthorizeTunnel(PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, + PTSG_PACKET tsgPacket, PTSG_PACKET* tsgPacketResponse); + +HRESULT TsProxyMakeTunnelCall(PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, + unsigned long procId, PTSG_PACKET tsgPacket, PTSG_PACKET* tsgPacketResponse); + +HRESULT TsProxyCreateChannel(PTUNNEL_CONTEXT_HANDLE_NOSERIALIZE tunnelContext, + PTSENDPOINTINFO tsEndPointInfo, PCHANNEL_CONTEXT_HANDLE_SERIALIZE* channelContext, unsigned long* channelId); + +void Opnum5NotUsedOnWire(handle_t IDL_handle); + +HRESULT TsProxyCloseChannel(PCHANNEL_CONTEXT_HANDLE_NOSERIALIZE* context); + +HRESULT TsProxyCloseTunnel(PTUNNEL_CONTEXT_HANDLE_SERIALIZE* context); + +DWORD TsProxySetupReceivePipe(handle_t IDL_handle, byte pRpcMessage[]); + +DWORD TsProxySendToServer(handle_t IDL_handle, byte pRpcMessage[], uint32 count, uint32* lengths); + +boolean tsg_connect(rdpTsg* tsg, const char* hostname, uint16 port); + +int tsg_write(rdpTsg* tsg, uint8* data, uint32 length); +int tsg_read(rdpTsg* tsg, uint8* data, uint32 length); + +rdpTsg* tsg_new(rdpTransport* transport); +void tsg_free(rdpTsg* tsg); + +#ifdef WITH_DEBUG_TSG +#define DEBUG_TSG(fmt, ...) DEBUG_CLASS(TSG, fmt, ## __VA_ARGS__) +#else +#define DEBUG_TSG(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__) +#endif + +#endif /* FREERDP_CORE_TSG_H */ diff --git a/libfreerdp-crypto/crypto.c b/libfreerdp-crypto/crypto.c index 09b097a19..93a114e85 100644 --- a/libfreerdp-crypto/crypto.c +++ b/libfreerdp-crypto/crypto.c @@ -511,3 +511,46 @@ void crypto_cert_print_info(X509* xcert) xfree(fp); } +char* crypto_base64_encode(uint8* data, int length) +{ + BIO* bmem; + BIO* b64; + BUF_MEM *bptr; + char* base64_string; + + b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + bmem = BIO_new(BIO_s_mem()); + b64 = BIO_push(b64, bmem); + BIO_write(b64, data, length); + + if (BIO_flush(b64) < 1) + return NULL; + + BIO_get_mem_ptr(b64, &bptr); + + base64_string = xmalloc(bptr->length); + memcpy(base64_string, bptr->data, bptr->length - 1); + base64_string[bptr->length - 1] = '\0'; + + BIO_free_all(b64); + + return base64_string; +} + +void crypto_base64_decode(uint8* enc_data, int length, uint8** dec_data, int* res_length) +{ + BIO *b64, *bmem; + + *dec_data = xmalloc(length); + memset(*dec_data, 0, length); + + b64 = BIO_new(BIO_f_base64()); + BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL); + bmem = BIO_new_mem_buf(enc_data, length); + bmem = BIO_push(b64, bmem); + + *res_length = BIO_read(bmem, *dec_data, length); + + BIO_free_all(bmem); +} diff --git a/libfreerdp-crypto/tls.c b/libfreerdp-crypto/tls.c index 175106ba9..374a99551 100644 --- a/libfreerdp-crypto/tls.c +++ b/libfreerdp-crypto/tls.c @@ -255,6 +255,30 @@ int tls_write(rdpTls* tls, uint8* data, int length) return status; } + +int tls_write_all(rdpTls* tls, uint8* data, int length) +{ + int status; + int sent = 0; + + do + { + status = tls_write(tls, &data[sent], length - sent); + + if (status > 0) + sent += status; + + if (sent >= length) + break; + } + while (status >= 0); + + if (status > 0) + return length; + else + return status; +} + static void tls_errors(const char *prefix) { unsigned long error; diff --git a/libfreerdp-rail/window.c b/libfreerdp-rail/window.c index c8f25e536..7b39fa13b 100644 --- a/libfreerdp-rail/window.c +++ b/libfreerdp-rail/window.c @@ -17,11 +17,11 @@ * limitations under the License. */ +#include #include #include #include #include -#include #include "librail.h" diff --git a/libfreerdp-utils/args.c b/libfreerdp-utils/args.c index e90998636..ed922f201 100644 --- a/libfreerdp-utils/args.c +++ b/libfreerdp-utils/args.c @@ -102,11 +102,12 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, " --ignore-certificate: ignore verification of logon certificate\n" " --certificate-name: use this name for the logon certificate, instead of the server name\n" " --sec: force protocol security (rdp, tls or nla)\n" + " --tsg: Terminal Server Gateway ( )\n" " --kbd-list: list all keyboard layout ids used by -k\n" " --no-salted-checksum: disable salted checksums with Standard RDP encryption\n" " --version: print version information\n" "\n", argv[0]); - return FREERDP_ARGS_PARSE_HELP; //TODO: What is the correct return + return FREERDP_ARGS_PARSE_HELP; /* TODO: What is the correct return? */ } else if (strcmp("-a", argv[index]) == 0) { @@ -534,6 +535,31 @@ int freerdp_parse_args(rdpSettings* settings, int argc, char** argv, return FREERDP_ARGS_PARSE_FAILURE; } } + else if (strcmp("--tsg", argv[index]) == 0) + { + settings->ts_gateway = true; + index++; + if (index == argc) + { + printf("missing TSG username\n"); + return -1; + } + settings->tsg_username = xstrdup(argv[index]); + index++; + if (index == argc) + { + printf("missing TSG password\n"); + return -1; + } + settings->tsg_password = xstrdup(argv[index]); + index++; + if (index == argc) + { + printf("missing TSG server\n"); + return -1; + } + settings->tsg_hostname = xstrdup(argv[index]); + } else if (strcmp("--plugin", argv[index]) == 0) { index++; diff --git a/libfreerdp-utils/file.c b/libfreerdp-utils/file.c index 5a597f14c..f1985da0e 100644 --- a/libfreerdp-utils/file.c +++ b/libfreerdp-utils/file.c @@ -34,8 +34,8 @@ #define getcwd _getcwd #endif +#include #include -#include #ifndef _WIN32 #define PATH_SEPARATOR_STR "/" diff --git a/libfreerdp-utils/load_plugin.c b/libfreerdp-utils/load_plugin.c index 473640db1..08d80541a 100644 --- a/libfreerdp-utils/load_plugin.c +++ b/libfreerdp-utils/load_plugin.c @@ -22,11 +22,11 @@ #include #include #include +#include #include #include #include #include -#include #ifdef _WIN32 diff --git a/libfreerdp-utils/mutex.c b/libfreerdp-utils/mutex.c index 16003579d..a5e07ca8e 100644 --- a/libfreerdp-utils/mutex.c +++ b/libfreerdp-utils/mutex.c @@ -17,9 +17,9 @@ * limitations under the License. */ +#include #include #include -#include #ifdef _WIN32 #define freerdp_mutex_t HANDLE diff --git a/libfreerdp-utils/semaphore.c b/libfreerdp-utils/semaphore.c index 7e08a75d7..9cd87c422 100644 --- a/libfreerdp-utils/semaphore.c +++ b/libfreerdp-utils/semaphore.c @@ -17,9 +17,9 @@ * limitations under the License. */ +#include #include #include -#include #if defined __APPLE__ diff --git a/libfreerdp-utils/sleep.c b/libfreerdp-utils/sleep.c index 9752e0d2a..830cad615 100644 --- a/libfreerdp-utils/sleep.c +++ b/libfreerdp-utils/sleep.c @@ -17,8 +17,8 @@ * limitations under the License. */ +#include #include -#include #include diff --git a/libfreerdp-utils/tcp.c b/libfreerdp-utils/tcp.c index 695855d15..81ece04d7 100644 --- a/libfreerdp-utils/tcp.c +++ b/libfreerdp-utils/tcp.c @@ -45,7 +45,7 @@ #else /* ifdef _WIN32 */ -#include +#include #define SHUT_RDWR SD_BOTH #define close(_fd) closesocket(_fd) #endif diff --git a/libfreerdp-utils/thread.c b/libfreerdp-utils/thread.c index 2251cdd0d..d25125917 100644 --- a/libfreerdp-utils/thread.c +++ b/libfreerdp-utils/thread.c @@ -22,7 +22,7 @@ #include #include -#include +#include #ifdef _WIN32 #ifdef _MSC_VER diff --git a/libfreerdp-utils/time.c b/libfreerdp-utils/time.c index 2e50796d2..fbcf46971 100644 --- a/libfreerdp-utils/time.c +++ b/libfreerdp-utils/time.c @@ -17,8 +17,8 @@ * limitations under the License. */ +#include #include -#include uint64 freerdp_windows_gmtime() { diff --git a/libfreerdp-utils/unicode.c b/libfreerdp-utils/unicode.c index 6524a35ad..e06ccec2a 100644 --- a/libfreerdp-utils/unicode.c +++ b/libfreerdp-utils/unicode.c @@ -98,7 +98,7 @@ char* freerdp_uniconv_in(UNICONV* uniconv, unsigned char* pin, size_t in_len) /* Convert str from DEFAULT_CODEPAGE to WINDOWS_CODEPAGE and return buffer like xstrdup. * Buffer is 0-terminated but that is not included in the returned length. */ -char* freerdp_uniconv_out(UNICONV *uniconv, char *str, size_t *pout_len) +char* freerdp_uniconv_out(UNICONV* uniconv, const char *str, size_t* pout_len) { size_t ibl; size_t obl; @@ -114,7 +114,7 @@ char* freerdp_uniconv_out(UNICONV *uniconv, char *str, size_t *pout_len) ibl = strlen(str); obl = 2 * ibl; - pin = str; + pin = (char*) str; pout0 = xmalloc(obl + 2); pout = pout0; diff --git a/libfreerdp-utils/wait_obj.c b/libfreerdp-utils/wait_obj.c index 65f6fb880..a9f2e8ef2 100644 --- a/libfreerdp-utils/wait_obj.c +++ b/libfreerdp-utils/wait_obj.c @@ -18,12 +18,13 @@ */ #include "config.h" + #include #include #include +#include #include #include -#include #ifndef _WIN32 #include diff --git a/libwinpr-rpc/CMakeLists.txt b/libwinpr-rpc/CMakeLists.txt new file mode 100644 index 000000000..af607cbae --- /dev/null +++ b/libwinpr-rpc/CMakeLists.txt @@ -0,0 +1,49 @@ +# WinPR: Windows Portable Runtime +# libwinpr-rpc cmake build script +# +# Copyright 2011 O.S. Systems Software Ltda. +# Copyright 2011 Otavio Salvador +# Copyright 2011 Marc-Andre Moreau +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +set(WINPR_RPC_SRCS + rpc.c + ndr.c + ndr_array.c ndr_array.h + ndr_context.c ndr_context.h + ndr_correlation.c ndr_correlation.h + ndr_pointer.c ndr_pointer.h + ndr_private.c ndr_private.h + ndr_simple.c ndr_simple.h + ndr_string.c ndr_string.h + ndr_structure.c ndr_structure.h + ndr_union.c ndr_union.h + midl.c) + +add_library(winpr-rpc ${WINPR_RPC_SRCS}) + +include_directories(${OPENSSL_INCLUDE_DIR}) +include_directories(${ZLIB_INCLUDE_DIRS}) + +set_target_properties(winpr-rpc PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") + +if(WIN32) + target_link_libraries(winpr-rpc ws2_32) +else() + target_link_libraries(winpr-rpc ${ZLIB_LIBRARIES}) +endif() + +target_link_libraries(winpr-rpc ${OPENSSL_LIBRARIES}) + +install(TARGETS winpr-rpc DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/libwinpr-rpc/midl.c b/libwinpr-rpc/midl.c new file mode 100644 index 000000000..bdd5bde5e --- /dev/null +++ b/libwinpr-rpc/midl.c @@ -0,0 +1,33 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +void* MIDL_user_allocate(size_t cBytes) +{ + return (malloc(cBytes)); +} + +void MIDL_user_free(void* p) +{ + free(p); +} diff --git a/libwinpr-rpc/ndr.c b/libwinpr-rpc/ndr.c new file mode 100644 index 000000000..bca80d84a --- /dev/null +++ b/libwinpr-rpc/ndr.c @@ -0,0 +1,342 @@ +/** + * WinPR: Windows Portable Runtime + * Network Data Representation (NDR) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +#include + +#include "ndr_array.h" +#include "ndr_context.h" +#include "ndr_pointer.h" +#include "ndr_simple.h" +#include "ndr_string.h" +#include "ndr_structure.h" +#include "ndr_union.h" + +#include "ndr_private.h" + +/** + * MSRPC NDR Types Technical Overview: + * http://dvlabs.tippingpoint.com/blog/2007/11/24/msrpc-ndr-types/ + */ + +void NdrPrintParamAttributes(PARAM_ATTRIBUTES attributes) +{ + if (attributes.ServerAllocSize) + printf("ServerAllocSize, "); + if (attributes.SaveForAsyncFinish) + printf("SaveForAsyncFinish, "); + if (attributes.IsDontCallFreeInst) + printf("IsDontCallFreeInst, "); + if (attributes.IsSimpleRef) + printf("IsSimpleRef, "); + if (attributes.IsByValue) + printf("IsByValue, "); + if (attributes.IsBasetype) + printf("IsBaseType, "); + if (attributes.IsReturn) + printf("IsReturn, "); + if (attributes.IsOut) + printf("IsOut, "); + if (attributes.IsIn) + printf("IsIn, "); + if (attributes.IsPipe) + printf("IsPipe, "); + if (attributes.MustFree) + printf("MustFree, "); + if (attributes.MustSize) + printf("MustSize, "); +} + +void NdrProcessParam(PMIDL_STUB_MESSAGE pStubMsg, NDR_PHASE phase, unsigned char* pMemory, NDR_PARAM* param) +{ + unsigned char type; + PFORMAT_STRING pFormat; + + /* Parameter Descriptors: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374362/ */ + + if (param->Attributes.IsBasetype) + { + pFormat = ¶m->Type.FormatChar; + + if (param->Attributes.IsSimpleRef) + pMemory = *(unsigned char**) pMemory; + } + else + { + pFormat = &pStubMsg->StubDesc->pFormatTypes[param->Type.Offset]; + + if (!(param->Attributes.IsByValue)) + pMemory = *(unsigned char**) pMemory; + } + + type = (pFormat[0] & 0x7F); + + if (type > FC_PAD) + return; + + if (phase == NDR_PHASE_SIZE) + { + NDR_TYPE_SIZE_ROUTINE pfnSizeRoutine = pfnSizeRoutines[type]; + + if (pfnSizeRoutine) + pfnSizeRoutine(pStubMsg, pMemory, pFormat); + } + else if (phase == NDR_PHASE_MARSHALL) + { + NDR_TYPE_MARSHALL_ROUTINE pfnMarshallRoutine = pfnMarshallRoutines[type]; + + if (pfnMarshallRoutine) + pfnMarshallRoutine(pStubMsg, pMemory, *pFormat); + } + else if (phase == NDR_PHASE_UNMARSHALL) + { + NDR_TYPE_UNMARSHALL_ROUTINE pfnUnmarshallRoutine = pfnUnmarshallRoutines[type]; + + if (pfnUnmarshallRoutine) + pfnUnmarshallRoutine(pStubMsg, pMemory, *pFormat); + } + else if (phase == NDR_PHASE_FREE) + { + NDR_TYPE_FREE_ROUTINE pfnFreeRoutine = pfnFreeRoutines[type]; + + if (pfnFreeRoutine) + pfnFreeRoutine(pStubMsg, pMemory, pFormat); + } +} + +void NdrProcessParams(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat, NDR_PHASE phase, void** fpuArgs, unsigned short numberParams) +{ + unsigned int i; + NDR_PARAM* params; + PFORMAT_STRING fmt; + unsigned char* arg; + unsigned char type; + + params = (NDR_PARAM*) pFormat; + + printf("Params = \n{\n"); + + for (i = 0; i < numberParams; i++) + { + arg = pStubMsg->StackTop + params[i].StackOffset; + fmt = (PFORMAT_STRING) &pStubMsg->StubDesc->pFormatTypes[params[i].Type.Offset]; + +#ifdef __x86_64__ + if ((params[i].Attributes.IsBasetype) && + !(params[i].Attributes.IsSimpleRef) && + ((params[i].Type.FormatChar) == FC_FLOAT) && !fpuArgs) + { + float tmp = *(double*) arg; + arg = (unsigned char*) &tmp; + } +#endif + + printf("\t#%d\t", i); + + type = (params[i].Attributes.IsBasetype) ? params[i].Type.FormatChar : *fmt; + + printf(" type %s (0x%02X) ", FC_TYPE_STRINGS[type], type); + + NdrPrintParamAttributes(params[i].Attributes); + + if (params[i].Attributes.IsIn) + { + NdrProcessParam(pStubMsg, phase, arg, ¶ms[i]); + } + + printf("\n"); + } + + printf("}\n"); +} + +void NdrClientInitializeNew(PRPC_MESSAGE pRpcMessage, PMIDL_STUB_MESSAGE pStubMsg, + PMIDL_STUB_DESC pStubDesc, unsigned int ProcNum) +{ + pRpcMessage->Handle = NULL; + pRpcMessage->RpcFlags = 0; + pRpcMessage->ProcNum = ProcNum; + pRpcMessage->DataRepresentation = 0; + pRpcMessage->ReservedForRuntime = NULL; + pRpcMessage->RpcInterfaceInformation = pStubDesc->RpcInterfaceInformation; + + pStubMsg->RpcMsg = pRpcMessage; + pStubMsg->BufferStart = NULL; + pStubMsg->BufferEnd = NULL; + pStubMsg->BufferLength = 0; + pStubMsg->StackTop = NULL; + pStubMsg->StubDesc = pStubDesc; + pStubMsg->IgnoreEmbeddedPointers = 0; + pStubMsg->PointerLength = 0; +} + +void NdrPrintOptFlags(INTERPRETER_OPT_FLAGS optFlags) +{ + if (optFlags.ClientMustSize) + printf("ClientMustSize, "); + if (optFlags.ServerMustSize) + printf("ServerMustSize, "); + if (optFlags.HasAsyncUuid) + printf("HasAsyncUiid, "); + if (optFlags.HasAsyncHandle) + printf("HasAsyncHandle, "); + if (optFlags.HasReturn) + printf("HasReturn, "); + if (optFlags.HasPipes) + printf("HasPipes, "); + if (optFlags.HasExtensions) + printf("HasExtensions, "); +} + +void NdrPrintExtFlags(INTERPRETER_OPT_FLAGS2 extFlags) +{ + if (extFlags.HasNewCorrDesc) + printf("HasNewCorrDesc, "); + if (extFlags.ClientCorrCheck) + printf("ClientCorrCheck, "); + if (extFlags.ServerCorrCheck) + printf("ServerCorrCheck, "); + if (extFlags.HasNotify) + printf("HasNotify, "); + if (extFlags.HasNotify2) + printf("HasNotify2, "); +} + +CLIENT_CALL_RETURN NdrClientCall(PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, void** stackTop, void** fpuStack) +{ + RPC_MESSAGE rpcMsg; + unsigned short procNum; + unsigned short stackSize; + unsigned char numberParams; + unsigned char handleType; + MIDL_STUB_MESSAGE stubMsg; + INTERPRETER_FLAGS flags; + INTERPRETER_OPT_FLAGS optFlags; + INTERPRETER_OPT_FLAGS2 extFlags; + NDR_PROC_HEADER* procHeader; + NDR_OI2_PROC_HEADER* oi2ProcHeader; + CLIENT_CALL_RETURN client_call_return; + + procNum = stackSize = numberParams = 0; + procHeader = (NDR_PROC_HEADER*) &pFormat[0]; + + client_call_return.Pointer = NULL; + + handleType = procHeader->HandleType; + flags = procHeader->OldOiFlags; + procNum = procHeader->ProcNum; + stackSize = procHeader->StackSize; + pFormat += sizeof(NDR_PROC_HEADER); + + /* The Header: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378707/ */ + /* Procedure Header Descriptor: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374387/ */ + /* Handles: http://msdn.microsoft.com/en-us/library/windows/desktop/aa373932/ */ + + printf("Oi Header: HandleType: 0x%02X OiFlags: 0x%02X ProcNum: %d StackSize: 0x%04X\n", + handleType, *((unsigned char*) &flags), + (unsigned short) procNum, (unsigned short) stackSize); + + if (handleType > 0) + { + /* implicit handle */ + printf("Implicit Handle\n"); + oi2ProcHeader = (NDR_OI2_PROC_HEADER*) &pFormat[0]; + pFormat += sizeof(NDR_OI2_PROC_HEADER); + } + else + { + /* explicit handle */ + printf("Explicit Handle\n"); + oi2ProcHeader = (NDR_OI2_PROC_HEADER*) &pFormat[6]; + pFormat += sizeof(NDR_OI2_PROC_HEADER) + 6; + } + + optFlags = oi2ProcHeader->Oi2Flags; + numberParams = oi2ProcHeader->NumberParams; + + printf("Oi2 Header: Oi2Flags: 0x%02X, NumberParams: %d ClientBufferSize: %d ServerBufferSize: %d\n", + *((unsigned char*) &optFlags), + (unsigned char) numberParams, + oi2ProcHeader->ClientBufferSize, + oi2ProcHeader->ServerBufferSize); + + printf("Oi2Flags: "); + NdrPrintOptFlags(optFlags); + printf("\n"); + + NdrClientInitializeNew(&rpcMsg, &stubMsg, pStubDescriptor, procNum); + + if (optFlags.HasExtensions) + { + NDR_PROC_HEADER_EXTS* extensions = (NDR_PROC_HEADER_EXTS*) pFormat; + + pFormat += extensions->Size; + extFlags = extensions->Flags2; + + printf("Extensions: Size: %d, flags2: 0x%02X\n", + extensions->Size, *((unsigned char*) &extensions->Flags2)); + +#ifdef __x86_64__ + if (extensions->Size > sizeof(*extensions) && fpuStack) + { + int i; + unsigned short fpuMask = *(unsigned short*) (extensions + 1); + + for (i = 0; i < 4; i++, fpuMask >>= 2) + { + switch (fpuMask & 3) + { + case 1: *(float*) &stackTop[i] = *(float*) &fpuStack[i]; + break; + + case 2: *(double*) &stackTop[i] = *(double*) &fpuStack[i]; + break; + } + } + } +#endif + } + + stubMsg.StackTop = (unsigned char*) stackTop; + + printf("ExtFlags: "); + NdrPrintExtFlags(extFlags); + printf("\n"); + + NdrProcessParams(&stubMsg, pFormat, NDR_PHASE_SIZE, fpuStack, numberParams); + + printf("stubMsg BufferLength: %d\n", (int) stubMsg.BufferLength); + + return client_call_return; +} + +CLIENT_CALL_RETURN NdrClientCall2(PMIDL_STUB_DESC pStubDescriptor, PFORMAT_STRING pFormat, ...) +{ + va_list args; + CLIENT_CALL_RETURN client_call_return; + + va_start(args, pFormat); + client_call_return = NdrClientCall(pStubDescriptor, pFormat, va_arg(args, void**), NULL); + va_end(args); + + return client_call_return; +} diff --git a/libwinpr-rpc/ndr_array.c b/libwinpr-rpc/ndr_array.c new file mode 100644 index 000000000..3c800144d --- /dev/null +++ b/libwinpr-rpc/ndr_array.c @@ -0,0 +1,137 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include "ndr_array.h" + +void NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + /** + * FC_CARRAY + * alignment<1> + * element_size<2> + * conformance_description<> + * [pointer_layout<>] + * element_description<> + * FC_END + */ + + unsigned char type; + unsigned char alignment; + unsigned short element_size; + + type = pFormat[0]; + alignment = pFormat[1] + 1; + element_size = *(unsigned short*) &pFormat[2]; + + if (type != FC_CARRAY) + { + printf("error: expected FC_CARRAY, got 0x%02X\n", type); + return; + } + + printf("warning: NdrConformantArrayBufferSize unimplemented\n"); +} + +void NdrConformantVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + /** + * FC_CVARRAY + * alignment<1> + * element_size<2> + * conformance_description<> + * variance_description<> + * [pointer_layout<>] + * element_description<> + * FC_END + */ + + printf("warning: NdrConformantVaryingArrayBufferSize unimplemented\n"); +} + +void NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + /** + * FC_SMFARRAY + * alignment<1> + * total_size<2> + * [pointer_layout<>] + * element_description<> + * FC_END + */ + + /** + * FC_LGFARRAY + * alignment<1> + * total_size<4> + * [pointer_layout<>] + * element_description<> + * FC_END + */ + + printf("warning: NdrFixedArrayBufferSize unimplemented\n"); +} + +void NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + /** + * FC_SMVARRAY + * alignment<1> + * total_size<2> + * number_elements<2> + * element_size<2> + * variance_description<> + * [pointer_layout<>] + * element_description<> + * FC_END + */ + + /** + * FC_LGVARRAY + * alignment<1> + * total_size<4> + * number_elements<4> + * element_size<2> + * variance_description<4> + * [pointer_layout<>] + * element_description<> + * FC_END + */ + + printf("warning: NdrVaryingArrayBufferSize unimplemented\n"); +} + +void NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + /** + * FC_BOGUS_ARRAY + * alignment<1> + * number_of_elements<2> + * conformance_description<> + * variance_description<> + * element_description<> + * FC_END + */ + + printf("warning: NdrComplexArrayBufferSize unimplemented\n"); +} diff --git a/libwinpr-rpc/ndr_array.h b/libwinpr-rpc/ndr_array.h new file mode 100644 index 000000000..3a6bc2d44 --- /dev/null +++ b/libwinpr-rpc/ndr_array.h @@ -0,0 +1,31 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_RPC_NDR_ARRAY_H +#define WINPR_RPC_NDR_ARRAY_H + +#include + +void NdrConformantArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +void NdrConformantVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +void NdrFixedArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +void NdrVaryingArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +void NdrComplexArrayBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); + +#endif /* WINPR_RPC_NDR_ARRAY_H */ diff --git a/libwinpr-rpc/ndr_context.c b/libwinpr-rpc/ndr_context.c new file mode 100644 index 000000000..270074f95 --- /dev/null +++ b/libwinpr-rpc/ndr_context.c @@ -0,0 +1,66 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include "ndr_context.h" +#include "ndr_private.h" + +void NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + unsigned char type = *pFormat; + + if (type == FC_BIND_PRIMITIVE) + { + /** + * FC_BIND_PRIMITIVE + * flag<1> + * offset<2> + */ + + printf("warning: NdrContextHandleBufferSize FC_BIND_PRIMITIVE unimplemented\n"); + } + else if (type == FC_BIND_GENERIC) + { + /** + * FC_BIND_GENERIC + * flag_and_size<1> + * offset<2> + * binding_routine_pair_index<1> + * FC_PAD + */ + + printf("warning: NdrContextHandleBufferSize FC_BIND_GENERIC unimplemented\n"); + } + else if (type == FC_BIND_CONTEXT) + { + /** + * FC_BIND_CONTEXT + * flags<1> + * offset<2> + * context_rundown_routine_index<1> + * param_num<1> + */ + + NdrpAlignLength(&(pStubMsg->BufferLength), 4); + NdrpIncrementLength(&(pStubMsg->BufferLength), 20); + } +} diff --git a/libwinpr-rpc/ndr_context.h b/libwinpr-rpc/ndr_context.h new file mode 100644 index 000000000..7b8770c2a --- /dev/null +++ b/libwinpr-rpc/ndr_context.h @@ -0,0 +1,27 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_RPC_NDR_CONTEXT_H +#define WINPR_RPC_NDR_CONTEXT_H + +#include + +void NdrContextHandleBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); + +#endif /* WINPR_RPC_NDR_CONTEXT_H */ diff --git a/libwinpr-rpc/ndr_correlation.c b/libwinpr-rpc/ndr_correlation.c new file mode 100644 index 000000000..1a9383403 --- /dev/null +++ b/libwinpr-rpc/ndr_correlation.c @@ -0,0 +1,187 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include "ndr_correlation.h" +#include "ndr_private.h" + +/* + * Correlation Descriptors: http://msdn.microsoft.com/en-us/library/windows/desktop/aa373607/ + * + * correlation_type<1> + * correlation_operator<1> + * offset<2> + * [robust_flags<2>] + * + */ + +PFORMAT_STRING NdrpComputeCount(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat, ULONG_PTR* pCount) +{ + LPVOID ptr = NULL; + ULONG_PTR data = 0; + unsigned char type; + unsigned short offset; + unsigned char conformance; + unsigned char correlation_type; + unsigned char correlation_operator; + + correlation_type = pFormat[0]; + type = correlation_type & 0x0F; + conformance = correlation_type & 0xF0; + + correlation_operator = pFormat[1]; + offset = *(unsigned short*) & pFormat[2]; + + if (conformance == FC_NORMAL_CONFORMANCE) + { + ptr = pMemory; + } + else if (conformance == FC_POINTER_CONFORMANCE) + { + ptr = pStubMsg->Memory; + } + else if (conformance == FC_TOP_LEVEL_CONFORMANCE) + { + ptr = pStubMsg->StackTop; + } + else if (conformance == FC_CONSTANT_CONFORMANCE ) + { + data = offset | ((DWORD) pFormat[1] << 16); + *pCount = data; + } + else if (conformance == FC_TOP_LEVEL_MULTID_CONFORMANCE) + { + if (pStubMsg->StackTop) + ptr = pStubMsg->StackTop; + } + + switch (correlation_operator) + { + case FC_DEREFERENCE: + ptr = *(LPVOID*)((char*) ptr + offset); + break; + + case FC_DIV_2: + ptr = (char*) ptr + offset; + break; + + case FC_MULT_2: + ptr = (char*) ptr + offset; + break; + + case FC_SUB_1: + ptr = (char*) ptr + offset; + break; + + case FC_ADD_1: + ptr = (char*) ptr + offset; + break; + + case FC_CALLBACK: + { + printf("warning: NdrpComputeConformance FC_CALLBACK unimplemented\n"); + } + break; + } + + switch (type) + { + case FC_LONG: + data = *(LONG*) ptr; + break; + + case FC_ULONG: + data = *(ULONG*) ptr; + break; + + case FC_SHORT: + data = *(SHORT*) ptr; + break; + + case FC_USHORT: + data = *(USHORT*) ptr; + break; + + case FC_CHAR: + case FC_SMALL: + data = *(CHAR*) ptr; + break; + + case FC_BYTE: + case FC_USMALL: + data = *(BYTE*) ptr; + break; + + case FC_HYPER: + data = (ULONG_PTR) *(ULONGLONG*) ptr; + break; + } + + switch (correlation_operator) + { + case FC_ZERO: + case FC_DEREFERENCE: + *pCount = data; + break; + + case FC_DIV_2: + *pCount = data / 1; + break; + + case FC_MULT_2: + *pCount = data * 1; + break; + + case FC_SUB_1: + *pCount = data - 1; + break; + + case FC_ADD_1: + *pCount = data + 1; + break; + + case FC_CALLBACK: + break; + } + + if (pStubMsg->fHasNewCorrDesc) + pFormat += 6; + else + pFormat += 4; + + return pFormat; +} + +PFORMAT_STRING NdrpComputeConformance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + return NdrpComputeCount(pStubMsg, pMemory, pFormat, &pStubMsg->MaxCount); +} + +PFORMAT_STRING NdrpComputeVariance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + ULONG_PTR ActualCount = pStubMsg->ActualCount; + + pFormat = NdrpComputeCount(pStubMsg, pMemory, pFormat, &ActualCount); + pStubMsg->ActualCount = (ULONG) ActualCount; + + return pFormat; +} diff --git a/libwinpr-rpc/ndr_correlation.h b/libwinpr-rpc/ndr_correlation.h new file mode 100644 index 000000000..01724b408 --- /dev/null +++ b/libwinpr-rpc/ndr_correlation.h @@ -0,0 +1,29 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_RPC_NDR_CORRELATION_H +#define WINPR_RPC_NDR_CORRELATION_H + +#include + +PFORMAT_STRING NdrpComputeCount(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat, ULONG_PTR* pCount); +PFORMAT_STRING NdrpComputeConformance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +PFORMAT_STRING NdrpComputeVariance(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); + +#endif /* WINPR_RPC_NDR_CORRELATION_H */ diff --git a/libwinpr-rpc/ndr_pointer.c b/libwinpr-rpc/ndr_pointer.c new file mode 100644 index 000000000..b38dcbc3e --- /dev/null +++ b/libwinpr-rpc/ndr_pointer.c @@ -0,0 +1,322 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include "ndr_pointer.h" +#include "ndr_private.h" + +/** + * Pointer Layout: http://msdn.microsoft.com/en-us/library/windows/desktop/aa374376/ + * + * pointer_layout<>: + * + * FC_PP + * FC_PAD + * { pointer_instance_layout<> }* + * FC_END + * + * pointer_instance<8>: + * + * offset_to_pointer_in_memory<2> + * offset_to_pointer_in_buffer<2> + * pointer_description<4> + * + */ + +PFORMAT_STRING NdrpSkipPointerLayout(PFORMAT_STRING pFormat) +{ + pFormat += 2; + + while (*pFormat != FC_END) + { + if (*pFormat == FC_NO_REPEAT) + { + /** + * FC_NO_REPEAT + * FC_PAD + * pointer_instance<8> + */ + + pFormat += 10; + } + else if (*pFormat == FC_FIXED_REPEAT) + { + unsigned short number_of_pointers; + + /** + * FC_FIXED_REPEAT + * FC_PAD + * iterations<2> + * increment<2> + * offset_to_array<2> + * number_of_pointers<2> + * { pointer_instance<8> }* + */ + + pFormat += 8; + number_of_pointers = *(unsigned short*) pFormat; + pFormat += 2 + (number_of_pointers * 8); + } + else if (*pFormat == FC_VARIABLE_REPEAT) + { + unsigned short number_of_pointers; + + /** + * FC_VARIABLE_REPEAT (FC_FIXED_OFFSET | FC_VARIABLE_OFFSET) + * FC_PAD ?! + * increment<2> + * offset_to_array<2> + * number_of_pointers<2> + * { pointer_instance<8> }* + */ + + pFormat += 6; + number_of_pointers = *(unsigned short*) pFormat; + pFormat += 2 + (number_of_pointers * 8); + } + else + { + printf("error: NdrpSkipPointerLayout unexpected 0x%02X\n", *pFormat); + break; + } + } + + return pFormat + 1; +} + +/* Pointers: http://msdn.microsoft.com/en-us/library/windows/desktop/hh802750/ */ + +/** + * pointer_type<1> + * pointer_attributes<1> + * simple_type<1> + * FC_PAD + */ + +/** + * pointer_type<1> + * pointer_attributes<1> + * offset_to_complex_description<2> + */ + +void NdrpPointerBufferSize(unsigned char* pMemory, PFORMAT_STRING pFormat, PMIDL_STUB_MESSAGE pStubMsg) +{ + unsigned char type; + unsigned char attributes; + PFORMAT_STRING pNextFormat; + NDR_TYPE_SIZE_ROUTINE pfnSizeRoutine; + + type = pFormat[0]; + attributes = pFormat[1]; + pFormat += 2; + + if (attributes & FC_SIMPLE_POINTER) + pNextFormat = pFormat; + else + pNextFormat = pFormat + *(SHORT*) pFormat; + + switch (type) + { + case FC_RP: /* Reference Pointer */ + break; + + case FC_UP: /* Unique Pointer */ + case FC_OP: /* Unique Pointer in an object interface */ + + if (!pMemory) + return; + + break; + + case FC_FP: /* Full Pointer */ + printf("warning: FC_FP unimplemented\n"); + break; + } + + if (attributes & FC_POINTER_DEREF) + pMemory = *(unsigned char**) pMemory; + + pfnSizeRoutine = pfnSizeRoutines[*pNextFormat]; + + if (pfnSizeRoutine) + pfnSizeRoutine(pStubMsg, pMemory, pNextFormat); +} + +PFORMAT_STRING NdrpEmbeddedRepeatPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat, unsigned char** ppMemory) +{ + ULONG_PTR MaxCount; + unsigned char* Memory; + unsigned char* MemoryCopy; + unsigned char* MemoryPointer; + PFORMAT_STRING pFormatNext; + PFORMAT_STRING pFormatPointers; + unsigned short increment; + unsigned short pointer_count; + unsigned short offset_to_array; + unsigned short number_of_pointers; + + Memory = pStubMsg->Memory; + MemoryCopy = pStubMsg->Memory; + + if (*pFormat == FC_FIXED_REPEAT) + { + pFormat += 2; + MaxCount = *(unsigned short*) pFormat; + } + else + { + if (*pFormat != FC_VARIABLE_REPEAT) + { + RpcRaiseException(1766); + return pFormat; + } + + MaxCount = pStubMsg->MaxCount; + + if (pFormat[1] == FC_VARIABLE_OFFSET) + { + pMemory += pStubMsg->Offset * *((unsigned short*) &pFormat[1]); + } + } + + pFormat += 2; + increment = *(unsigned short*) pFormat; + + pFormat += 2; + offset_to_array = *(unsigned short*) pFormat; + pStubMsg->Memory = Memory + offset_to_array; + + pFormat += 2; + number_of_pointers = *(unsigned short*) pFormat; + + pFormat += 2; + + pFormatPointers = pFormat; + + if (MaxCount) + { + do + { + MaxCount--; + pFormatNext = pFormatPointers; + pointer_count = number_of_pointers; + + if (number_of_pointers) + { + do + { + pointer_count--; + MemoryPointer = &pMemory[*(unsigned short*) pFormatNext]; + NdrpPointerBufferSize(MemoryPointer, pFormatNext + 4, pStubMsg); + pFormatNext += 8; + } + while (pointer_count); + } + + pMemory += increment; + pStubMsg->Memory += increment; + } + while (MaxCount); + + Memory = MemoryCopy; + } + + pFormat = pFormatPointers + (number_of_pointers * 8); + pStubMsg->Memory = Memory; + + return pFormat; +} + +PFORMAT_STRING NdrpEmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + ULONG_PTR MaxCount; + unsigned long Offset; + unsigned char* Memory; + char PointerLengthSet; + PFORMAT_STRING pFormatCopy; + unsigned long BufferLength; + unsigned long BufferLengthCopy; + unsigned long PointerLength; + unsigned char* pMemoryPtr = NULL; + + pFormatCopy = pFormat; + + if (!pStubMsg->IgnoreEmbeddedPointers) + { + PointerLength = pStubMsg->PointerLength; + PointerLengthSet = (PointerLength != 0); + + if (PointerLengthSet) + { + BufferLength = pStubMsg->BufferLength; + pStubMsg->PointerLength = 0; + BufferLengthCopy = BufferLength; + pStubMsg->BufferLength = PointerLength; + } + + MaxCount = pStubMsg->MaxCount; + Offset = pStubMsg->Offset; + Memory = pStubMsg->Memory; + pStubMsg->Memory = pMemory; + pFormat = pFormatCopy + 2; + + while (*pFormat != FC_END) + { + if (*pFormat == FC_NO_REPEAT) + { + NdrpPointerBufferSize(&pMemory[pFormat[2]], &pFormat[6], pStubMsg); + pFormat += 10; + } + + pStubMsg->Offset = Offset; + pStubMsg->MaxCount = MaxCount; + + NdrpEmbeddedRepeatPointerBufferSize(pStubMsg, pMemory, pFormat, &pMemoryPtr); + } + + pStubMsg->Memory = Memory; + + if (PointerLengthSet) + { + pStubMsg->PointerLength = pStubMsg->BufferLength; + pStubMsg->BufferLength = BufferLengthCopy; + } + } + + return pFormat; +} + +void NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + if (*pFormat != FC_RP) + { + NdrpAlignLength((&pStubMsg->BufferLength), 4); + NdrpIncrementLength((&pStubMsg->BufferLength), 4); + } + + NdrpPointerBufferSize(pMemory, pFormat, pStubMsg); +} + +void NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + printf("warning: NdrByteCountPointerBufferSize unimplemented\n"); +} diff --git a/libwinpr-rpc/ndr_pointer.h b/libwinpr-rpc/ndr_pointer.h new file mode 100644 index 000000000..676832239 --- /dev/null +++ b/libwinpr-rpc/ndr_pointer.h @@ -0,0 +1,37 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_RPC_NDR_POINTER_H +#define WINPR_RPC_NDR_POINTER_H + +#include + +PFORMAT_STRING NdrpSkipPointerLayout(PFORMAT_STRING pFormat); + +void NdrpPointerBufferSize(unsigned char* pMemory, PFORMAT_STRING pFormat, PMIDL_STUB_MESSAGE pStubMsg); + +PFORMAT_STRING NdrpEmbeddedRepeatPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, + unsigned char* pMemory, PFORMAT_STRING pFormat, unsigned char** ppMemory); + +PFORMAT_STRING NdrpEmbeddedPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); + +void NdrPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +void NdrByteCountPointerBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); + +#endif /* WINPR_RPC_NDR_POINTER_H */ diff --git a/libwinpr-rpc/ndr_private.c b/libwinpr-rpc/ndr_private.c new file mode 100644 index 000000000..22fc59868 --- /dev/null +++ b/libwinpr-rpc/ndr_private.c @@ -0,0 +1,552 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include "ndr_array.h" +#include "ndr_context.h" +#include "ndr_pointer.h" +#include "ndr_simple.h" +#include "ndr_string.h" +#include "ndr_structure.h" +#include "ndr_union.h" + +#include "ndr_private.h" + +void NdrpAlignLength(unsigned long* length, unsigned int alignment) +{ + *length = (*length + alignment - 1) & ~(alignment - 1); +} + +void NdrpIncrementLength(unsigned long* length, unsigned int size) +{ + *length += size; +} + +const char* FC_TYPE_STRINGS[] = +{ + "FC_ZERO", + "FC_BYTE", + "FC_CHAR", + "FC_SMALL", + "FC_USMALL", + "FC_WCHAR", + "FC_SHORT", + "FC_USHORT", + "FC_LONG", + "FC_ULONG", + "FC_FLOAT", + "FC_HYPER", + "FC_DOUBLE", + "FC_ENUM16", + "FC_ENUM32", + "FC_IGNORE", + "FC_ERROR_STATUS_T", + "FC_RP", + "FC_UP", + "FC_OP", + "FC_FP", + "FC_STRUCT", + "FC_PSTRUCT", + "FC_CSTRUCT", + "FC_CPSTRUCT", + "FC_CVSTRUCT", + "FC_BOGUS_STRUCT", + "FC_CARRAY", + "FC_CVARRAY", + "FC_SMFARRAY", + "FC_LGFARRAY", + "FC_SMVARRAY", + "FC_LGVARRAY", + "FC_BOGUS_ARRAY", + "FC_C_CSTRING", + "FC_C_BSTRING", + "FC_C_SSTRING", + "FC_C_WSTRING", + "FC_CSTRING", + "FC_BSTRING", + "FC_SSTRING", + "FC_WSTRING", + "FC_ENCAPSULATED_UNION", + "FC_NON_ENCAPSULATED_UNION", + "FC_BYTE_COUNT_POINTER", + "FC_TRANSMIT_AS", + "FC_REPRESENT_AS", + "FC_IP", + "FC_BIND_CONTEXT", + "FC_BIND_GENERIC", + "FC_BIND_PRIMITIVE", + "FC_AUTO_HANDLE", + "FC_CALLBACK_HANDLE", + "FC_UNUSED1", + "FC_POINTER", + "FC_ALIGNM2", + "FC_ALIGNM4", + "FC_ALIGNM8", + "FC_UNUSED2", + "FC_UNUSED3", + "FC_UNUSED4", + "FC_STRUCTPAD1", + "FC_STRUCTPAD2", + "FC_STRUCTPAD3", + "FC_STRUCTPAD4", + "FC_STRUCTPAD5", + "FC_STRUCTPAD6", + "FC_STRUCTPAD7", + "FC_STRING_SIZED", + "FC_UNUSED5", + "FC_NO_REPEAT", + "FC_FIXED_REPEAT", + "FC_VARIABLE_REPEAT", + "FC_FIXED_OFFSET", + "FC_VARIABLE_OFFSET", + "FC_PP", + "FC_EMBEDDED_COMPLEX", + "FC_IN_PARAM", + "FC_IN_PARAM_BASETYPE", + "FC_IN_PARAM_NO_FREE_INST", + "FC_IN_OUT_PARAM", + "FC_OUT_PARAM", + "FC_RETURN_PARAM", + "FC_RETURN_PARAM_BASETYPE", + "FC_DEREFERENCE", + "FC_DIV_2", + "FC_MULT_2", + "FC_ADD_1", + "FC_SUB_1", + "FC_CALLBACK", + "FC_CONSTANT_IID", + "FC_END", + "FC_PAD", + "", "", "", "", "", "", + "", "", "", "", "", "", + "", "", "", "", "", "", + "", "", "", "", "", "", + "FC_SPLIT_DEREFERENCE", + "FC_SPLIT_DIV_2", + "FC_SPLIT_MULT_2", + "FC_SPLIT_ADD_1", + "FC_SPLIT_SUB_1", + "FC_SPLIT_CALLBACK", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "", "", "", "", "", "", "", "", "", "", "", "", "", "", + "FC_HARD_STRUCT", + "FC_TRANSMIT_AS_PTR", + "FC_REPRESENT_AS_PTR", + "FC_USER_MARSHAL", + "FC_PIPE", + "FC_BLKHOLE", + "FC_RANGE", + "FC_INT3264", + "FC_UINT3264", + "FC_END_OF_UNIVERSE", +}; + +const NDR_TYPE_SIZE_ROUTINE pfnSizeRoutines[] = +{ + NULL, /* FC_ZERO */ + NdrSimpleTypeBufferSize, /* FC_BYTE */ + NdrSimpleTypeBufferSize, /* FC_CHAR */ + NdrSimpleTypeBufferSize, /* FC_SMALL */ + NdrSimpleTypeBufferSize, /* FC_USMALL */ + NdrSimpleTypeBufferSize, /* FC_WCHAR */ + NdrSimpleTypeBufferSize, /* FC_SHORT */ + NdrSimpleTypeBufferSize, /* FC_USHORT */ + NdrSimpleTypeBufferSize, /* FC_LONG */ + NdrSimpleTypeBufferSize, /* FC_ULONG */ + NdrSimpleTypeBufferSize, /* FC_FLOAT */ + NdrSimpleTypeBufferSize, /* FC_HYPER */ + NdrSimpleTypeBufferSize, /* FC_DOUBLE */ + NdrSimpleTypeBufferSize, /* FC_ENUM16 */ + NdrSimpleTypeBufferSize, /* FC_ENUM32 */ + NdrSimpleTypeBufferSize, /* FC_IGNORE */ + NdrSimpleTypeBufferSize, /* FC_ERROR_STATUS_T */ + NdrPointerBufferSize, /* FC_RP */ + NdrPointerBufferSize, /* FC_UP */ + NdrPointerBufferSize, /* FC_OP */ + NdrPointerBufferSize, /* FC_FP */ + NdrSimpleStructBufferSize, /* FC_STRUCT */ + NdrSimpleStructBufferSize, /* FC_PSTRUCT */ + NdrConformantStructBufferSize, /* FC_CSTRUCT */ + NdrConformantStructBufferSize, /* FC_CPSTRUCT */ + NdrConformantVaryingStructBufferSize, /* FC_CVSTRUCT */ + NdrComplexStructBufferSize, /* FC_BOGUS_STRUCT */ + NdrConformantArrayBufferSize, /* FC_CARRAY */ + NdrConformantVaryingArrayBufferSize, /* FC_CVARRAY */ + NdrFixedArrayBufferSize, /* FC_SMFARRAY */ + NdrFixedArrayBufferSize, /* FC_LGFARRAY */ + NdrVaryingArrayBufferSize, /* FC_SMVARRAY */ + NdrVaryingArrayBufferSize, /* FC_LGVARRAY */ + NdrComplexArrayBufferSize, /* FC_BOGUS_ARRAY */ + NdrConformantStringBufferSize, /* FC_C_CSTRING */ + NULL, /* FC_C_BSTRING */ + NULL, /* FC_C_SSTRING */ + NdrConformantStringBufferSize, /* FC_C_WSTRING */ + NdrNonConformantStringBufferSize, /* FC_CSTRING */ + NULL, /* FC_BSTRING */ + NULL, /* FC_SSTRING */ + NULL, /* FC_WSTRING */ + NdrEncapsulatedUnionBufferSize, /* FC_ENCAPSULATED_UNION */ + NdrNonEncapsulatedUnionBufferSize, /* FC_NON_ENCAPSULATED_UNION */ + NdrByteCountPointerBufferSize, /* FC_BYTE_COUNT_POINTER */ + NULL, /* FC_TRANSMIT_AS */ + NULL, /* FC_REPRESENT_AS */ + NULL, /* FC_IP */ + NdrContextHandleBufferSize, /* FC_BIND_CONTEXT */ + NULL, /* FC_BIND_GENERIC */ + NULL, /* FC_BIND_PRIMITIVE */ + NULL, /* FC_AUTO_HANDLE */ + NULL, /* FC_CALLBACK_HANDLE */ + NULL, /* FC_UNUSED1 */ + NULL, /* FC_POINTER */ + NULL, /* FC_ALIGNM2 */ + NULL, /* FC_ALIGNM4 */ + NULL, /* FC_ALIGNM8 */ + NULL, /* FC_UNUSED2 */ + NULL, /* FC_UNUSED3 */ + NULL, /* FC_UNUSED4 */ + NULL, /* FC_STRUCTPAD1 */ + NULL, /* FC_STRUCTPAD2 */ + NULL, /* FC_STRUCTPAD3 */ + NULL, /* FC_STRUCTPAD4 */ + NULL, /* FC_STRUCTPAD5 */ + NULL, /* FC_STRUCTPAD6 */ + NULL, /* FC_STRUCTPAD7 */ + NULL, /* FC_STRING_SIZED */ + NULL, /* FC_UNUSED5 */ + NULL, /* FC_NO_REPEAT */ + NULL, /* FC_FIXED_REPEAT */ + NULL, /* FC_VARIABLE_REPEAT */ + NULL, /* FC_FIXED_OFFSET */ + NULL, /* FC_VARIABLE_OFFSET */ + NULL, /* FC_PP */ + NULL, /* FC_EMBEDDED_COMPLEX */ + NULL, /* FC_IN_PARAM */ + NULL, /* FC_IN_PARAM_BASETYPE */ + NULL, /* FC_IN_PARAM_NO_FREE_INST */ + NULL, /* FC_IN_OUT_PARAM */ + NULL, /* FC_OUT_PARAM */ + NULL, /* FC_RETURN_PARAM */ + NULL, /* FC_RETURN_PARAM_BASETYPE */ + NULL, /* FC_DEREFERENCE */ + NULL, /* FC_DIV_2 */ + NULL, /* FC_MULT_2 */ + NULL, /* FC_ADD_1 */ + NULL, /* FC_SUB_1 */ + NULL, /* FC_CALLBACK */ + NULL, /* FC_CONSTANT_IID */ + NULL, /* FC_END */ + NULL, /* FC_PAD */ +}; + +const NDR_TYPE_MARSHALL_ROUTINE pfnMarshallRoutines[] = +{ + NULL, /* FC_ZERO */ + NdrSimpleTypeMarshall, /* FC_BYTE */ + NdrSimpleTypeMarshall, /* FC_CHAR */ + NdrSimpleTypeMarshall, /* FC_SMALL */ + NdrSimpleTypeMarshall, /* FC_USMALL */ + NdrSimpleTypeMarshall, /* FC_WCHAR */ + NdrSimpleTypeMarshall, /* FC_SHORT */ + NdrSimpleTypeMarshall, /* FC_USHORT */ + NdrSimpleTypeMarshall, /* FC_LONG */ + NdrSimpleTypeMarshall, /* FC_ULONG */ + NdrSimpleTypeMarshall, /* FC_FLOAT */ + NdrSimpleTypeMarshall, /* FC_HYPER */ + NdrSimpleTypeMarshall, /* FC_DOUBLE */ + NdrSimpleTypeMarshall, /* FC_ENUM16 */ + NdrSimpleTypeMarshall, /* FC_ENUM32 */ + NdrSimpleTypeMarshall, /* FC_IGNORE */ + NULL, /* FC_ERROR_STATUS_T */ + NULL, /* FC_RP */ + NULL, /* FC_UP */ + NULL, /* FC_OP */ + NULL, /* FC_FP */ + NULL, /* FC_STRUCT */ + NULL, /* FC_PSTRUCT */ + NULL, /* FC_CSTRUCT */ + NULL, /* FC_CPSTRUCT */ + NULL, /* FC_CVSTRUCT */ + NULL, /* FC_BOGUS_STRUCT */ + NULL, /* FC_CARRAY */ + NULL, /* FC_CVARRAY */ + NULL, /* FC_SMFARRAY */ + NULL, /* FC_LGFARRAY */ + NULL, /* FC_SMVARRAY */ + NULL, /* FC_LGVARRAY */ + NULL, /* FC_BOGUS_ARRAY */ + NULL, /* FC_C_CSTRING */ + NULL, /* FC_C_BSTRING */ + NULL, /* FC_C_SSTRING */ + NULL, /* FC_C_WSTRING */ + NULL, /* FC_CSTRING */ + NULL, /* FC_BSTRING */ + NULL, /* FC_SSTRING */ + NULL, /* FC_WSTRING */ + NULL, /* FC_ENCAPSULATED_UNION */ + NULL, /* FC_NON_ENCAPSULATED_UNION */ + NULL, /* FC_BYTE_COUNT_POINTER */ + NULL, /* FC_TRANSMIT_AS */ + NULL, /* FC_REPRESENT_AS */ + NULL, /* FC_IP */ + NULL, /* FC_BIND_CONTEXT */ + NULL, /* FC_BIND_GENERIC */ + NULL, /* FC_BIND_PRIMITIVE */ + NULL, /* FC_AUTO_HANDLE */ + NULL, /* FC_CALLBACK_HANDLE */ + NULL, /* FC_UNUSED1 */ + NULL, /* FC_POINTER */ + NULL, /* FC_ALIGNM2 */ + NULL, /* FC_ALIGNM4 */ + NULL, /* FC_ALIGNM8 */ + NULL, /* FC_UNUSED2 */ + NULL, /* FC_UNUSED3 */ + NULL, /* FC_UNUSED4 */ + NULL, /* FC_STRUCTPAD1 */ + NULL, /* FC_STRUCTPAD2 */ + NULL, /* FC_STRUCTPAD3 */ + NULL, /* FC_STRUCTPAD4 */ + NULL, /* FC_STRUCTPAD5 */ + NULL, /* FC_STRUCTPAD6 */ + NULL, /* FC_STRUCTPAD7 */ + NULL, /* FC_STRING_SIZED */ + NULL, /* FC_UNUSED5 */ + NULL, /* FC_NO_REPEAT */ + NULL, /* FC_FIXED_REPEAT */ + NULL, /* FC_VARIABLE_REPEAT */ + NULL, /* FC_FIXED_OFFSET */ + NULL, /* FC_VARIABLE_OFFSET */ + NULL, /* FC_PP */ + NULL, /* FC_EMBEDDED_COMPLEX */ + NULL, /* FC_IN_PARAM */ + NULL, /* FC_IN_PARAM_BASETYPE */ + NULL, /* FC_IN_PARAM_NO_FREE_INST */ + NULL, /* FC_IN_OUT_PARAM */ + NULL, /* FC_OUT_PARAM */ + NULL, /* FC_RETURN_PARAM */ + NULL, /* FC_RETURN_PARAM_BASETYPE */ + NULL, /* FC_DEREFERENCE */ + NULL, /* FC_DIV_2 */ + NULL, /* FC_MULT_2 */ + NULL, /* FC_ADD_1 */ + NULL, /* FC_SUB_1 */ + NULL, /* FC_CALLBACK */ + NULL, /* FC_CONSTANT_IID */ + NULL, /* FC_END */ + NULL, /* FC_PAD */ +}; + +const NDR_TYPE_UNMARSHALL_ROUTINE pfnUnmarshallRoutines[] = +{ + NULL, /* FC_ZERO */ + NdrSimpleTypeUnmarshall, /* FC_BYTE */ + NdrSimpleTypeUnmarshall, /* FC_CHAR */ + NdrSimpleTypeUnmarshall, /* FC_SMALL */ + NdrSimpleTypeUnmarshall, /* FC_USMALL */ + NdrSimpleTypeUnmarshall, /* FC_WCHAR */ + NdrSimpleTypeUnmarshall, /* FC_SHORT */ + NdrSimpleTypeUnmarshall, /* FC_USHORT */ + NdrSimpleTypeUnmarshall, /* FC_LONG */ + NdrSimpleTypeUnmarshall, /* FC_ULONG */ + NdrSimpleTypeUnmarshall, /* FC_FLOAT */ + NdrSimpleTypeUnmarshall, /* FC_HYPER */ + NdrSimpleTypeUnmarshall, /* FC_DOUBLE */ + NdrSimpleTypeUnmarshall, /* FC_ENUM16 */ + NdrSimpleTypeUnmarshall, /* FC_ENUM32 */ + NdrSimpleTypeUnmarshall, /* FC_IGNORE */ + NULL, /* FC_ERROR_STATUS_T */ + NULL, /* FC_RP */ + NULL, /* FC_UP */ + NULL, /* FC_OP */ + NULL, /* FC_FP */ + NULL, /* FC_STRUCT */ + NULL, /* FC_PSTRUCT */ + NULL, /* FC_CSTRUCT */ + NULL, /* FC_CPSTRUCT */ + NULL, /* FC_CVSTRUCT */ + NULL, /* FC_BOGUS_STRUCT */ + NULL, /* FC_CARRAY */ + NULL, /* FC_CVARRAY */ + NULL, /* FC_SMFARRAY */ + NULL, /* FC_LGFARRAY */ + NULL, /* FC_SMVARRAY */ + NULL, /* FC_LGVARRAY */ + NULL, /* FC_BOGUS_ARRAY */ + NULL, /* FC_C_CSTRING */ + NULL, /* FC_C_BSTRING */ + NULL, /* FC_C_SSTRING */ + NULL, /* FC_C_WSTRING */ + NULL, /* FC_CSTRING */ + NULL, /* FC_BSTRING */ + NULL, /* FC_SSTRING */ + NULL, /* FC_WSTRING */ + NULL, /* FC_ENCAPSULATED_UNION */ + NULL, /* FC_NON_ENCAPSULATED_UNION */ + NULL, /* FC_BYTE_COUNT_POINTER */ + NULL, /* FC_TRANSMIT_AS */ + NULL, /* FC_REPRESENT_AS */ + NULL, /* FC_IP */ + NULL, /* FC_BIND_CONTEXT */ + NULL, /* FC_BIND_GENERIC */ + NULL, /* FC_BIND_PRIMITIVE */ + NULL, /* FC_AUTO_HANDLE */ + NULL, /* FC_CALLBACK_HANDLE */ + NULL, /* FC_UNUSED1 */ + NULL, /* FC_POINTER */ + NULL, /* FC_ALIGNM2 */ + NULL, /* FC_ALIGNM4 */ + NULL, /* FC_ALIGNM8 */ + NULL, /* FC_UNUSED2 */ + NULL, /* FC_UNUSED3 */ + NULL, /* FC_UNUSED4 */ + NULL, /* FC_STRUCTPAD1 */ + NULL, /* FC_STRUCTPAD2 */ + NULL, /* FC_STRUCTPAD3 */ + NULL, /* FC_STRUCTPAD4 */ + NULL, /* FC_STRUCTPAD5 */ + NULL, /* FC_STRUCTPAD6 */ + NULL, /* FC_STRUCTPAD7 */ + NULL, /* FC_STRING_SIZED */ + NULL, /* FC_UNUSED5 */ + NULL, /* FC_NO_REPEAT */ + NULL, /* FC_FIXED_REPEAT */ + NULL, /* FC_VARIABLE_REPEAT */ + NULL, /* FC_FIXED_OFFSET */ + NULL, /* FC_VARIABLE_OFFSET */ + NULL, /* FC_PP */ + NULL, /* FC_EMBEDDED_COMPLEX */ + NULL, /* FC_IN_PARAM */ + NULL, /* FC_IN_PARAM_BASETYPE */ + NULL, /* FC_IN_PARAM_NO_FREE_INST */ + NULL, /* FC_IN_OUT_PARAM */ + NULL, /* FC_OUT_PARAM */ + NULL, /* FC_RETURN_PARAM */ + NULL, /* FC_RETURN_PARAM_BASETYPE */ + NULL, /* FC_DEREFERENCE */ + NULL, /* FC_DIV_2 */ + NULL, /* FC_MULT_2 */ + NULL, /* FC_ADD_1 */ + NULL, /* FC_SUB_1 */ + NULL, /* FC_CALLBACK */ + NULL, /* FC_CONSTANT_IID */ + NULL, /* FC_END */ + NULL, /* FC_PAD */ +}; + +const NDR_TYPE_FREE_ROUTINE pfnFreeRoutines[] = +{ + NULL, /* FC_ZERO */ + NdrSimpleTypeFree, /* FC_BYTE */ + NdrSimpleTypeFree, /* FC_CHAR */ + NdrSimpleTypeFree, /* FC_SMALL */ + NdrSimpleTypeFree, /* FC_USMALL */ + NdrSimpleTypeFree, /* FC_WCHAR */ + NdrSimpleTypeFree, /* FC_SHORT */ + NdrSimpleTypeFree, /* FC_USHORT */ + NdrSimpleTypeFree, /* FC_LONG */ + NdrSimpleTypeFree, /* FC_ULONG */ + NdrSimpleTypeFree, /* FC_FLOAT */ + NdrSimpleTypeFree, /* FC_HYPER */ + NdrSimpleTypeFree, /* FC_DOUBLE */ + NdrSimpleTypeFree, /* FC_ENUM16 */ + NdrSimpleTypeFree, /* FC_ENUM32 */ + NdrSimpleTypeFree, /* FC_IGNORE */ + NULL, /* FC_ERROR_STATUS_T */ + NULL, /* FC_RP */ + NULL, /* FC_UP */ + NULL, /* FC_OP */ + NULL, /* FC_FP */ + NULL, /* FC_STRUCT */ + NULL, /* FC_PSTRUCT */ + NULL, /* FC_CSTRUCT */ + NULL, /* FC_CPSTRUCT */ + NULL, /* FC_CVSTRUCT */ + NULL, /* FC_BOGUS_STRUCT */ + NULL, /* FC_CARRAY */ + NULL, /* FC_CVARRAY */ + NULL, /* FC_SMFARRAY */ + NULL, /* FC_LGFARRAY */ + NULL, /* FC_SMVARRAY */ + NULL, /* FC_LGVARRAY */ + NULL, /* FC_BOGUS_ARRAY */ + NULL, /* FC_C_CSTRING */ + NULL, /* FC_C_BSTRING */ + NULL, /* FC_C_SSTRING */ + NULL, /* FC_C_WSTRING */ + NULL, /* FC_CSTRING */ + NULL, /* FC_BSTRING */ + NULL, /* FC_SSTRING */ + NULL, /* FC_WSTRING */ + NULL, /* FC_ENCAPSULATED_UNION */ + NULL, /* FC_NON_ENCAPSULATED_UNION */ + NULL, /* FC_BYTE_COUNT_POINTER */ + NULL, /* FC_TRANSMIT_AS */ + NULL, /* FC_REPRESENT_AS */ + NULL, /* FC_IP */ + NULL, /* FC_BIND_CONTEXT */ + NULL, /* FC_BIND_GENERIC */ + NULL, /* FC_BIND_PRIMITIVE */ + NULL, /* FC_AUTO_HANDLE */ + NULL, /* FC_CALLBACK_HANDLE */ + NULL, /* FC_UNUSED1 */ + NULL, /* FC_POINTER */ + NULL, /* FC_ALIGNM2 */ + NULL, /* FC_ALIGNM4 */ + NULL, /* FC_ALIGNM8 */ + NULL, /* FC_UNUSED2 */ + NULL, /* FC_UNUSED3 */ + NULL, /* FC_UNUSED4 */ + NULL, /* FC_STRUCTPAD1 */ + NULL, /* FC_STRUCTPAD2 */ + NULL, /* FC_STRUCTPAD3 */ + NULL, /* FC_STRUCTPAD4 */ + NULL, /* FC_STRUCTPAD5 */ + NULL, /* FC_STRUCTPAD6 */ + NULL, /* FC_STRUCTPAD7 */ + NULL, /* FC_STRING_SIZED */ + NULL, /* FC_UNUSED5 */ + NULL, /* FC_NO_REPEAT */ + NULL, /* FC_FIXED_REPEAT */ + NULL, /* FC_VARIABLE_REPEAT */ + NULL, /* FC_FIXED_OFFSET */ + NULL, /* FC_VARIABLE_OFFSET */ + NULL, /* FC_PP */ + NULL, /* FC_EMBEDDED_COMPLEX */ + NULL, /* FC_IN_PARAM */ + NULL, /* FC_IN_PARAM_BASETYPE */ + NULL, /* FC_IN_PARAM_NO_FREE_INST */ + NULL, /* FC_IN_OUT_PARAM */ + NULL, /* FC_OUT_PARAM */ + NULL, /* FC_RETURN_PARAM */ + NULL, /* FC_RETURN_PARAM_BASETYPE */ + NULL, /* FC_DEREFERENCE */ + NULL, /* FC_DIV_2 */ + NULL, /* FC_MULT_2 */ + NULL, /* FC_ADD_1 */ + NULL, /* FC_SUB_1 */ + NULL, /* FC_CALLBACK */ + NULL, /* FC_CONSTANT_IID */ + NULL, /* FC_END */ + NULL, /* FC_PAD */ +}; diff --git a/libwinpr-rpc/ndr_private.h b/libwinpr-rpc/ndr_private.h new file mode 100644 index 000000000..d5eb947b1 --- /dev/null +++ b/libwinpr-rpc/ndr_private.h @@ -0,0 +1,42 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_RPC_NDR_PRIVATE_H +#define WINPR_RPC_NDR_PRIVATE_H + +#include + +void NdrpAlignLength(unsigned long* length, unsigned int alignment); +void NdrpIncrementLength(unsigned long* length, unsigned int size); + +extern const NDR_TYPE_SIZE_ROUTINE pfnSizeRoutines[]; +extern const NDR_TYPE_MARSHALL_ROUTINE pfnMarshallRoutines[]; +extern const NDR_TYPE_UNMARSHALL_ROUTINE pfnUnmarshallRoutines[]; +extern const NDR_TYPE_FREE_ROUTINE pfnFreeRoutines[]; + +extern const char SimpleTypeAlignment[]; +extern const char SimpleTypeBufferSize[]; +extern const char SimpleTypeMemorySize[]; + +extern const char NdrTypeFlags[]; +extern const char* FC_TYPE_STRINGS[]; + +#include "ndr_correlation.h" + +#endif /* WINPR_RPC_NDR_PRIVATE_H */ diff --git a/libwinpr-rpc/ndr_simple.c b/libwinpr-rpc/ndr_simple.c new file mode 100644 index 000000000..97927f19e --- /dev/null +++ b/libwinpr-rpc/ndr_simple.c @@ -0,0 +1,193 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include "ndr_simple.h" +#include "ndr_private.h" + +const char SimpleTypeAlignment[] = +{ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x07, 0x07, 0x01, 0x03, 0x03, + 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x02, 0x04, 0x04, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const char SimpleTypeBufferSize[] = +{ + 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x02, 0x04, 0x04, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x04, 0x04, 0x04, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +const char SimpleTypeMemorySize[] = +{ + 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x04, 0x04, 0x04, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x04, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x92, 0x9D, 0x3A, 0x75, 0x92, 0x9D, 0x3A, 0x75, 0x92, 0x9D, 0x3A, 0x75, 0x92, 0x9D, 0x3A, 0x75, + 0x92, 0x9D, 0x3A, 0x75, 0x92, 0x9D, 0x3A, 0x75, 0x92, 0x9D, 0x3A, 0x75, 0x92, 0x9D, 0x3A, 0x75, + 0x92, 0x9D, 0x3A, 0x75, 0x92, 0x9D, 0x3A, 0x75, 0x92, 0x9D, 0x3A, 0x75, 0x92, 0x9D, 0x3A, 0x75, + 0x92, 0x9D, 0x3A, 0x75, 0x92, 0x9D, 0x3A, 0x75, 0x92, 0x9D, 0x3A, 0x75, 0x92, 0x9D, 0x3A, 0x75, +}; + +const char NdrTypeFlags[] = +{ + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x02, 0x02, 0x02, 0x02, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x08, 0x08, 0x08, 0x08, 0x08, + 0x08, 0x08, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0xA0, 0xA0, 0x00, 0xC0, 0xC0, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x84, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x04, 0x00, 0x01, + 0x03, 0x10, 0x01, 0x03, 0x2C, 0x01, 0x03, 0xE0, 0x90, 0x90, 0x8B, 0x57, 0x83, 0xE7, 0x6C, 0x01, + 0x09, 0x70, 0x3B, 0x86, 0x00, 0x0F, 0x01, 0x5A, 0x00, 0x80, 0x00, 0x30, 0x8D, 0x30, 0x84, 0x00, + 0x48, 0x6A, 0x00, 0x6A, 0x01, 0x06, 0xFF, 0x08, 0x5D, 0x90, 0x7D, 0x7D, 0x0F, 0x67, 0xBD, 0xAD, + 0xAD, 0xAD, 0x9B, 0xBA, 0x9B, 0x9B, 0x0D, 0xB9, 0xAD, 0x19, 0x19, 0xBA, 0xDB, 0x09, 0x86, 0xB1, +}; + +char NdrGetSimpleTypeBufferAlignment(unsigned char FormatChar) +{ + return SimpleTypeAlignment[FormatChar]; +} + +char NdrGetSimpleTypeBufferSize(unsigned char FormatChar) +{ + return SimpleTypeAlignment[FormatChar]; +} + +char NdrGetSimpleTypeMemorySize(unsigned char FormatChar) +{ + return SimpleTypeMemorySize[FormatChar]; +} + +int NdrGetTypeFlags(unsigned char FormatChar) +{ + return NdrTypeFlags[FormatChar]; +} + +void NdrSimpleTypeBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + switch (*pFormat) + { + case FC_BYTE: + case FC_CHAR: + case FC_SMALL: + case FC_USMALL: + NdrpIncrementLength(&(pStubMsg->BufferLength), sizeof(BYTE)); + break; + + case FC_WCHAR: + case FC_SHORT: + case FC_USHORT: + case FC_ENUM16: + NdrpAlignLength(&(pStubMsg->BufferLength), sizeof(USHORT)); + NdrpIncrementLength(&(pStubMsg->BufferLength), sizeof(USHORT)); + break; + + case FC_LONG: + case FC_ULONG: + case FC_ENUM32: + case FC_INT3264: + case FC_UINT3264: + NdrpAlignLength(&(pStubMsg->BufferLength), sizeof(ULONG)); + NdrpIncrementLength(&(pStubMsg->BufferLength), sizeof(ULONG)); + break; + + case FC_FLOAT: + NdrpAlignLength(&(pStubMsg->BufferLength), sizeof(FLOAT)); + NdrpIncrementLength(&(pStubMsg->BufferLength), sizeof(FLOAT)); + break; + + case FC_DOUBLE: + NdrpAlignLength(&(pStubMsg->BufferLength), sizeof(DOUBLE)); + NdrpIncrementLength(&(pStubMsg->BufferLength), sizeof(DOUBLE)); + break; + + case FC_HYPER: + NdrpAlignLength(&(pStubMsg->BufferLength), sizeof(ULONGLONG)); + NdrpIncrementLength(&(pStubMsg->BufferLength), sizeof(ULONGLONG)); + break; + + case FC_ERROR_STATUS_T: + NdrpAlignLength(&(pStubMsg->BufferLength), sizeof(error_status_t)); + NdrpIncrementLength(&(pStubMsg->BufferLength), sizeof(error_status_t)); + break; + + case FC_IGNORE: + break; + } +} + +void NdrSimpleTypeMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, unsigned char FormatChar) +{ + +} + +void NdrSimpleTypeUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, unsigned char FormatChar) +{ + +} + +void NdrSimpleTypeFree(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + +} diff --git a/libwinpr-rpc/ndr_simple.h b/libwinpr-rpc/ndr_simple.h new file mode 100644 index 000000000..bbd454209 --- /dev/null +++ b/libwinpr-rpc/ndr_simple.h @@ -0,0 +1,35 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_RPC_NDR_SIMPLE_H +#define WINPR_RPC_NDR_SIMPLE_H + +#include + +void NdrSimpleTypeBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +void NdrSimpleTypeMarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, unsigned char FormatChar); +void NdrSimpleTypeUnmarshall(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, unsigned char FormatChar); +void NdrSimpleTypeFree(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); + +char NdrGetSimpleTypeBufferAlignment(unsigned char FormatChar); +char NdrGetSimpleTypeBufferSize(unsigned char FormatChar); +char NdrGetSimpleTypeMemorySize(unsigned char FormatChar); +int NdrGetTypeFlags(unsigned char FormatChar); + +#endif /* WINPR_RPC_NDR_SIMPLE_H */ diff --git a/libwinpr-rpc/ndr_string.c b/libwinpr-rpc/ndr_string.c new file mode 100644 index 000000000..a52fb9923 --- /dev/null +++ b/libwinpr-rpc/ndr_string.c @@ -0,0 +1,35 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include "ndr_string.h" + +void NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + printf("warning: NdrConformantStringBufferSize unimplemented\n"); +} + +void NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + printf("warning: NdrNonConformantStringBufferSize unimplemented\n"); +} diff --git a/libwinpr-rpc/ndr_string.h b/libwinpr-rpc/ndr_string.h new file mode 100644 index 000000000..cbbd63308 --- /dev/null +++ b/libwinpr-rpc/ndr_string.h @@ -0,0 +1,28 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_RPC_NDR_STRING_H +#define WINPR_RPC_NDR_STRING_H + +#include + +void NdrConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +void NdrNonConformantStringBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); + +#endif /* WINPR_RPC_NDR_STRING_H */ diff --git a/libwinpr-rpc/ndr_structure.c b/libwinpr-rpc/ndr_structure.c new file mode 100644 index 000000000..d7f3957c2 --- /dev/null +++ b/libwinpr-rpc/ndr_structure.c @@ -0,0 +1,313 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include +#include "ndr_private.h" +#include "ndr_pointer.h" +#include "ndr_structure.h" + +/* Structures: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378695/ */ + +void NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + /** + * FC_STRUCT + * alignment<1> + * memory_size<2> + * member_layout<> + * FC_END + */ + + /** + * FC_PSTRUCT + * alignment<1> + * memory_size<2> + * pointer_layout<> + * member_layout<> + * FC_END + */ + + unsigned char type; + unsigned char alignment; + unsigned short memory_size; + + type = pFormat[0]; + alignment = pFormat[1] + 1; + memory_size = *(unsigned short*) &pFormat[2]; + + NdrpAlignLength(&(pStubMsg->BufferLength), alignment); + NdrpIncrementLength(&(pStubMsg->BufferLength), memory_size); + + pFormat += 4; + + if (*pFormat == FC_PSTRUCT) + NdrpEmbeddedPointerBufferSize(pStubMsg, pMemory, pFormat); + + printf("warning: NdrSimpleStructBufferSize unimplemented\n"); +} + +void NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + /** + * FC_CSTRUCT alignment<1> + * memory_size<2> + * offset_to_array_description<2> + * member_layout<> + * FC_END + */ + + /** + * FC_CPSTRUCT alignment<1> + * memory_size<2> + * offset_to_array_description<2> + * pointer_layout<> + * member_layout<> FC_END + */ + + printf("warning: NdrConformantStructBufferSize unimplemented\n"); +} + +void NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + /** + * FC_CVSTRUCT alignment<1> + * memory_size<2> + * offset_to_array_description<2> + * [pointer_layout<>] + * layout<> + * FC_END + */ + + printf("warning: NdrConformantVaryingStructBufferSize unimplemented\n"); +} + +ULONG NdrComplexStructMemberSize(PMIDL_STUB_MESSAGE pStubMsg, PFORMAT_STRING pFormat) +{ + ULONG size = 0; + + while (*pFormat != FC_END) + { + switch (*pFormat) + { + case FC_BYTE: + case FC_CHAR: + case FC_SMALL: + case FC_USMALL: + size += sizeof(BYTE); + break; + + case FC_WCHAR: + case FC_SHORT: + case FC_USHORT: + case FC_ENUM16: + size += sizeof(USHORT); + break; + + case FC_LONG: + case FC_ULONG: + case FC_ENUM32: + size += sizeof(ULONG); + break; + + case FC_INT3264: + case FC_UINT3264: + size += sizeof(INT_PTR); + break; + + case FC_FLOAT: + size += sizeof(FLOAT); + break; + + case FC_DOUBLE: + size += sizeof(DOUBLE); + break; + + case FC_HYPER: + size += sizeof(ULONGLONG); + break; + + case FC_ERROR_STATUS_T: + size += sizeof(error_status_t); + break; + + case FC_IGNORE: + break; + + case FC_RP: + case FC_UP: + case FC_OP: + case FC_FP: + case FC_POINTER: + size += sizeof(void*); + if (*pFormat != FC_POINTER) + pFormat += 4; + break; + + case FC_ALIGNM2: + NdrpAlignLength(&size, 2); + break; + + case FC_ALIGNM4: + NdrpAlignLength(&size, 4); + break; + + case FC_ALIGNM8: + NdrpAlignLength(&size, 8); + break; + + case FC_STRUCTPAD1: + case FC_STRUCTPAD2: + case FC_STRUCTPAD3: + case FC_STRUCTPAD4: + case FC_STRUCTPAD5: + case FC_STRUCTPAD6: + case FC_STRUCTPAD7: + size += *pFormat - FC_STRUCTPAD1 + 1; + break; + + case FC_PAD: + break; + + case FC_EMBEDDED_COMPLEX: + printf("warning: NdrComplexStructMemberSize FC_EMBEDDED_COMPLEX unimplemented\n"); + break; + + default: + printf("warning: NdrComplexStructMemberSize 0x%02X unimplemented\n", *pFormat); + break; + } + + pFormat++; + } + + return size; +} + +void NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + /** + * FC_BOGUS_STRUCT + * alignment<1> + * memory_size<2> + * offset_to_conformant_array_description<2> + * offset_to_pointer_layout<2> + * member_layout<> + * FC_END + * [pointer_layout<>] + */ + + ULONG_PTR MaxCount; + unsigned long Offset; + unsigned long ActualCount; + unsigned char* pMemoryCopy; + + unsigned char type; + unsigned char alignment; + unsigned short memory_size; + unsigned char* pointer_layout; + unsigned char* conformant_array_description; + unsigned short offset_to_pointer_layout; + unsigned short offset_to_conformant_array_description; + + type = pFormat[0]; + pMemoryCopy = pMemory; + pointer_layout = conformant_array_description = NULL; + + if (type != FC_BOGUS_STRUCT) + { + printf("error: expected FC_BOGUS_STRUCT, got 0x%02X\n", type); + return; + } + + alignment = pFormat[1] + 1; + memory_size = *(unsigned short*) &pFormat[2]; + + NdrpAlignLength(&(pStubMsg->BufferLength), alignment); + + if (!pStubMsg->IgnoreEmbeddedPointers && !pStubMsg->PointerLength) + { + unsigned long BufferLengthCopy = pStubMsg->BufferLength; + int IgnoreEmbeddedPointersCopy = pStubMsg->IgnoreEmbeddedPointers; + + pStubMsg->IgnoreEmbeddedPointers = 1; + NdrComplexStructBufferSize(pStubMsg, pMemory, pFormat); + pStubMsg->IgnoreEmbeddedPointers = IgnoreEmbeddedPointersCopy; + + pStubMsg->PointerLength = pStubMsg->BufferLength; + pStubMsg->BufferLength = BufferLengthCopy; + } + + pFormat += 4; + + offset_to_conformant_array_description = *(unsigned short*) &pFormat[0]; + + if (offset_to_conformant_array_description) + conformant_array_description = (unsigned char*) pFormat + offset_to_conformant_array_description; + pFormat += 2; + + offset_to_pointer_layout = *(unsigned short*) &pFormat[0]; + + if (offset_to_pointer_layout) + pointer_layout = (unsigned char*) pFormat + offset_to_pointer_layout; + pFormat += 2; + + pStubMsg->Memory = pMemory; + + if (conformant_array_description) + { + ULONG size; + unsigned char array_type; + + array_type = conformant_array_description[0]; + size = NdrComplexStructMemberSize(pStubMsg, pFormat); + + printf("warning: NdrComplexStructBufferSize array_type: 0x%02X unimplemented\n", array_type); + + NdrpComputeConformance(pStubMsg, pMemory + size, conformant_array_description); + NdrpComputeVariance(pStubMsg, pMemory + size, conformant_array_description); + + MaxCount = pStubMsg->MaxCount; + ActualCount = pStubMsg->ActualCount; + Offset = pStubMsg->Offset; + } + + if (conformant_array_description) + { + unsigned char array_type; + + array_type = conformant_array_description[0]; + + pStubMsg->MaxCount = MaxCount; + pStubMsg->ActualCount = ActualCount; + pStubMsg->Offset = Offset; + + printf("warning: NdrComplexStructBufferSize array_type: 0x%02X unimplemented\n", array_type); + } + + pStubMsg->Memory = pMemoryCopy; + + if (pStubMsg->PointerLength > 0) + { + pStubMsg->BufferLength = pStubMsg->PointerLength; + pStubMsg->PointerLength = 0; + } +} diff --git a/libwinpr-rpc/ndr_structure.h b/libwinpr-rpc/ndr_structure.h new file mode 100644 index 000000000..ca60c62fe --- /dev/null +++ b/libwinpr-rpc/ndr_structure.h @@ -0,0 +1,30 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_RPC_NDR_STRUCTURE_H +#define WINPR_RPC_NDR_STRUCTURE_H + +#include + +void NdrSimpleStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +void NdrConformantStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +void NdrConformantVaryingStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +void NdrComplexStructBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); + +#endif /* WINPR_RPC_NDR_STRUCTURE_H */ diff --git a/libwinpr-rpc/ndr_union.c b/libwinpr-rpc/ndr_union.c new file mode 100644 index 000000000..644ef5831 --- /dev/null +++ b/libwinpr-rpc/ndr_union.c @@ -0,0 +1,35 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#include + +#include "ndr_union.h" + +void NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + printf("warning: NdrEncapsulatedUnionBufferSize unimplemented\n"); +} + +void NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat) +{ + printf("warning: NdrNonEncapsulatedUnionBufferSize unimplemented\n"); +} diff --git a/libwinpr-rpc/ndr_union.h b/libwinpr-rpc/ndr_union.h new file mode 100644 index 000000000..7cd81d05b --- /dev/null +++ b/libwinpr-rpc/ndr_union.h @@ -0,0 +1,28 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WINPR_RPC_NDR_UNION_H +#define WINPR_RPC_NDR_UNION_H + +#include + +void NdrEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); +void NdrNonEncapsulatedUnionBufferSize(PMIDL_STUB_MESSAGE pStubMsg, unsigned char* pMemory, PFORMAT_STRING pFormat); + +#endif /* WINPR_RPC_NDR_UNION_H */ diff --git a/libwinpr-rpc/rpc.c b/libwinpr-rpc/rpc.c new file mode 100644 index 000000000..c76096627 --- /dev/null +++ b/libwinpr-rpc/rpc.c @@ -0,0 +1,27 @@ +/** + * WinPR: Windows Portable Runtime + * Microsoft Remote Procedure Call (MSRPC) + * + * Copyright 2012 Marc-Andre Moreau + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +void RpcRaiseException(RPC_STATUS exception) +{ + printf("RpcRaiseException: 0x%08luX\n", exception); +} diff --git a/libfreerdp-sspi/CMakeLists.txt b/libwinpr-sspi/CMakeLists.txt similarity index 64% rename from libfreerdp-sspi/CMakeLists.txt rename to libwinpr-sspi/CMakeLists.txt index d90f430a2..08f8c39c2 100644 --- a/libfreerdp-sspi/CMakeLists.txt +++ b/libwinpr-sspi/CMakeLists.txt @@ -1,5 +1,5 @@ -# FreeRDP: A Remote Desktop Protocol Client -# libfreerdp-sspi cmake build script +# WinPR: Windows Portable Runtime +# libwinpr-sspi cmake build script # # Copyright 2011 O.S. Systems Software Ltda. # Copyright 2011 Otavio Salvador @@ -17,7 +17,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -set(FREERDP_SSPI_NTLM_SRCS +set(WINPR_SSPI_NTLM_SRCS NTLM/ntlm_av_pairs.c NTLM/ntlm_av_pairs.h NTLM/ntlm_compute.c @@ -27,7 +27,7 @@ set(FREERDP_SSPI_NTLM_SRCS NTLM/ntlm.c NTLM/ntlm.h) -set(FREERDP_SSPI_KERBEROS_SRCS +set(WINPR_SSPI_KERBEROS_SRCS Kerberos/kerberos_crypto.c Kerberos/kerberos_crypto.h Kerberos/kerberos_decode.c @@ -37,36 +37,36 @@ set(FREERDP_SSPI_KERBEROS_SRCS Kerberos/kerberos.c Kerberos/kerberos.h) -set(FREERDP_SSPI_NEGOTIATE_SRCS +set(WINPR_SSPI_NEGOTIATE_SRCS Negotiate/negotiate.c Negotiate/negotiate.h) -set(FREERDP_SSPI_SRCS +set(WINPR_SSPI_SRCS sspi.c sspi.h credssp.c) if(NOT WITH_NATIVE_SSPI) - set(FREERDP_SSPI_SRCS - ${FREERDP_SSPI_NTLM_SRCS} - ${FREERDP_SSPI_KERBEROS_SRCS} - ${FREERDP_SSPI_NEGOTIATE_SRCS} - ${FREERDP_SSPI_SRCS}) + set(WINPR_SSPI_SRCS + ${WINPR_SSPI_NTLM_SRCS} + ${WINPR_SSPI_KERBEROS_SRCS} + ${WINPR_SSPI_NEGOTIATE_SRCS} + ${WINPR_SSPI_SRCS}) else() add_definitions(-DNATIVE_SSPI) endif() -add_library(freerdp-sspi ${FREERDP_SSPI_SRCS}) +add_library(winpr-sspi ${WINPR_SSPI_SRCS}) include_directories(${OPENSSL_INCLUDE_DIR}) include_directories(${ZLIB_INCLUDE_DIRS}) -set_target_properties(freerdp-sspi PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") +set_target_properties(winpr-sspi PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") -target_link_libraries(freerdp-sspi freerdp-utils) -target_link_libraries(freerdp-sspi freerdp-crypto) -target_link_libraries(freerdp-sspi ${ZLIB_LIBRARIES}) +target_link_libraries(winpr-sspi freerdp-utils) +target_link_libraries(winpr-sspi freerdp-crypto) +target_link_libraries(winpr-sspi ${ZLIB_LIBRARIES}) -install(TARGETS freerdp-sspi DESTINATION ${CMAKE_INSTALL_LIBDIR}) +install(TARGETS winpr-sspi DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/libfreerdp-sspi/Kerberos/kerberos.c b/libwinpr-sspi/Kerberos/kerberos.c similarity index 99% rename from libfreerdp-sspi/Kerberos/kerberos.c rename to libwinpr-sspi/Kerberos/kerberos.c index aa304b901..ef21bd3bf 100644 --- a/libfreerdp-sspi/Kerberos/kerberos.c +++ b/libwinpr-sspi/Kerberos/kerberos.c @@ -37,7 +37,7 @@ #include "kerberos_encode.h" #include "kerberos_decode.h" -#include +#include #include #include diff --git a/libfreerdp-sspi/Kerberos/kerberos.h b/libwinpr-sspi/Kerberos/kerberos.h similarity index 99% rename from libfreerdp-sspi/Kerberos/kerberos.h rename to libwinpr-sspi/Kerberos/kerberos.h index 6d65c244f..0f881bcc6 100644 --- a/libfreerdp-sspi/Kerberos/kerberos.h +++ b/libwinpr-sspi/Kerberos/kerberos.h @@ -34,11 +34,11 @@ #include +#include #include #include #include #include -#include #define MSKRB_OID "1.2.840.48018.1.2.2" #define STDKRB_OID "1.2.840.113554.1.2.2" diff --git a/libfreerdp-sspi/Kerberos/kerberos_crypto.c b/libwinpr-sspi/Kerberos/kerberos_crypto.c similarity index 100% rename from libfreerdp-sspi/Kerberos/kerberos_crypto.c rename to libwinpr-sspi/Kerberos/kerberos_crypto.c diff --git a/libfreerdp-sspi/Kerberos/kerberos_crypto.h b/libwinpr-sspi/Kerberos/kerberos_crypto.h similarity index 100% rename from libfreerdp-sspi/Kerberos/kerberos_crypto.h rename to libwinpr-sspi/Kerberos/kerberos_crypto.h diff --git a/libfreerdp-sspi/Kerberos/kerberos_decode.c b/libwinpr-sspi/Kerberos/kerberos_decode.c similarity index 100% rename from libfreerdp-sspi/Kerberos/kerberos_decode.c rename to libwinpr-sspi/Kerberos/kerberos_decode.c diff --git a/libfreerdp-sspi/Kerberos/kerberos_decode.h b/libwinpr-sspi/Kerberos/kerberos_decode.h similarity index 100% rename from libfreerdp-sspi/Kerberos/kerberos_decode.h rename to libwinpr-sspi/Kerberos/kerberos_decode.h diff --git a/libfreerdp-sspi/Kerberos/kerberos_encode.c b/libwinpr-sspi/Kerberos/kerberos_encode.c similarity index 100% rename from libfreerdp-sspi/Kerberos/kerberos_encode.c rename to libwinpr-sspi/Kerberos/kerberos_encode.c diff --git a/libfreerdp-sspi/Kerberos/kerberos_encode.h b/libwinpr-sspi/Kerberos/kerberos_encode.h similarity index 100% rename from libfreerdp-sspi/Kerberos/kerberos_encode.h rename to libwinpr-sspi/Kerberos/kerberos_encode.h diff --git a/libfreerdp-sspi/NTLM/ntlm.c b/libwinpr-sspi/NTLM/ntlm.c similarity index 98% rename from libfreerdp-sspi/NTLM/ntlm.c rename to libwinpr-sspi/NTLM/ntlm.c index 08c684aed..f2a9cb82f 100644 --- a/libfreerdp-sspi/NTLM/ntlm.c +++ b/libwinpr-sspi/NTLM/ntlm.c @@ -25,7 +25,7 @@ #include #include -#include +#include #include "ntlm.h" #include "../sspi.h" @@ -390,6 +390,9 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredenti { context = ntlm_ContextNew(); + if (fContextReq & ISC_REQ_CONFIDENTIALITY) + context->confidentiality = true; + credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); ntlm_SetContextIdentity(context, &credentials->identity); @@ -565,7 +568,12 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, uint32 fQOP HMAC_CTX_cleanup(&hmac); /* Encrypt message using with RC4, result overwrites original buffer */ - crypto_rc4(context->SendRc4Seal, length, data, data_buffer->pvBuffer); + + if (context->confidentiality) + crypto_rc4(context->SendRc4Seal, length, data, data_buffer->pvBuffer); + else + memcpy(data_buffer->pvBuffer, data, length); + xfree(data); #ifdef WITH_DEBUG_NTLM diff --git a/libfreerdp-sspi/NTLM/ntlm.h b/libwinpr-sspi/NTLM/ntlm.h similarity index 98% rename from libfreerdp-sspi/NTLM/ntlm.h rename to libwinpr-sspi/NTLM/ntlm.h index c960c00ca..333a577b4 100644 --- a/libfreerdp-sspi/NTLM/ntlm.h +++ b/libwinpr-sspi/NTLM/ntlm.h @@ -20,7 +20,7 @@ #ifndef FREERDP_SSPI_NTLM_PRIVATE_H #define FREERDP_SSPI_NTLM_PRIVATE_H -#include +#include #include #include @@ -83,6 +83,7 @@ struct _NTLM_CONTEXT UNICONV* uniconv; int SendSeqNum; int RecvSeqNum; + boolean confidentiality; CryptoRc4 SendRc4Seal; CryptoRc4 RecvRc4Seal; uint8* SendSigningKey; diff --git a/libfreerdp-sspi/NTLM/ntlm_av_pairs.c b/libwinpr-sspi/NTLM/ntlm_av_pairs.c similarity index 100% rename from libfreerdp-sspi/NTLM/ntlm_av_pairs.c rename to libwinpr-sspi/NTLM/ntlm_av_pairs.c diff --git a/libfreerdp-sspi/NTLM/ntlm_av_pairs.h b/libwinpr-sspi/NTLM/ntlm_av_pairs.h similarity index 100% rename from libfreerdp-sspi/NTLM/ntlm_av_pairs.h rename to libwinpr-sspi/NTLM/ntlm_av_pairs.h diff --git a/libfreerdp-sspi/NTLM/ntlm_compute.c b/libwinpr-sspi/NTLM/ntlm_compute.c similarity index 100% rename from libfreerdp-sspi/NTLM/ntlm_compute.c rename to libwinpr-sspi/NTLM/ntlm_compute.c diff --git a/libfreerdp-sspi/NTLM/ntlm_compute.h b/libwinpr-sspi/NTLM/ntlm_compute.h similarity index 100% rename from libfreerdp-sspi/NTLM/ntlm_compute.h rename to libwinpr-sspi/NTLM/ntlm_compute.h diff --git a/libfreerdp-sspi/NTLM/ntlm_message.c b/libwinpr-sspi/NTLM/ntlm_message.c similarity index 99% rename from libfreerdp-sspi/NTLM/ntlm_message.c rename to libwinpr-sspi/NTLM/ntlm_message.c index b00be61fb..c6824d8a9 100644 --- a/libfreerdp-sspi/NTLM/ntlm_message.c +++ b/libwinpr-sspi/NTLM/ntlm_message.c @@ -241,7 +241,6 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; NegotiateFlags |= NTLMSSP_NEGOTIATE_LM_KEY; - NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; NegotiateFlags |= NTLMSSP_REQUEST_TARGET; NegotiateFlags |= NTLMSSP_NEGOTIATE_OEM; @@ -254,12 +253,14 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; - NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; NegotiateFlags |= NTLMSSP_REQUEST_TARGET; NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; } + if (context->confidentiality) + NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; + context->NegotiateFlags = NegotiateFlags; stream_write_uint32(s, NegotiateFlags); /* NegotiateFlags (4 bytes) */ @@ -964,7 +965,6 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; - NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; NegotiateFlags |= NTLMSSP_REQUEST_TARGET; NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; @@ -976,12 +976,14 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer NegotiateFlags |= NTLMSSP_NEGOTIATE_EXTENDED_SESSION_SECURITY; NegotiateFlags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN; NegotiateFlags |= NTLMSSP_NEGOTIATE_NTLM; - NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; NegotiateFlags |= NTLMSSP_NEGOTIATE_SIGN; NegotiateFlags |= NTLMSSP_REQUEST_TARGET; NegotiateFlags |= NTLMSSP_NEGOTIATE_UNICODE; } + if (context->confidentiality) + NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; + if (context->ntlm_v2) PayloadBufferOffset = 80; /* starting buffer offset */ else diff --git a/libfreerdp-sspi/NTLM/ntlm_message.h b/libwinpr-sspi/NTLM/ntlm_message.h similarity index 100% rename from libfreerdp-sspi/NTLM/ntlm_message.h rename to libwinpr-sspi/NTLM/ntlm_message.h diff --git a/libfreerdp-sspi/Negotiate/negotiate.c b/libwinpr-sspi/Negotiate/negotiate.c similarity index 99% rename from libfreerdp-sspi/Negotiate/negotiate.c rename to libwinpr-sspi/Negotiate/negotiate.c index a37357e3a..a5e3c534a 100644 --- a/libfreerdp-sspi/Negotiate/negotiate.c +++ b/libwinpr-sspi/Negotiate/negotiate.c @@ -17,7 +17,7 @@ * limitations under the License. */ -#include +#include #include #include "negotiate.h" diff --git a/libfreerdp-sspi/Negotiate/negotiate.h b/libwinpr-sspi/Negotiate/negotiate.h similarity index 97% rename from libfreerdp-sspi/Negotiate/negotiate.h rename to libwinpr-sspi/Negotiate/negotiate.h index 5ce064a75..ab0e82bbb 100644 --- a/libfreerdp-sspi/Negotiate/negotiate.h +++ b/libwinpr-sspi/Negotiate/negotiate.h @@ -20,7 +20,7 @@ #ifndef FREERDP_SSPI_NEGOTIATE_PRIVATE_H #define FREERDP_SSPI_NEGOTIATE_PRIVATE_H -#include +#include #include #include "../Kerberos/kerberos.h" diff --git a/libfreerdp-sspi/credssp.c b/libwinpr-sspi/credssp.c similarity index 99% rename from libfreerdp-sspi/credssp.c rename to libwinpr-sspi/credssp.c index 8cf8b480a..151710e6b 100644 --- a/libfreerdp-sspi/credssp.c +++ b/libwinpr-sspi/credssp.c @@ -26,8 +26,8 @@ #include #include -#include -#include +#include +#include #include "sspi.h" diff --git a/libfreerdp-sspi/sspi.c b/libwinpr-sspi/sspi.c similarity index 99% rename from libfreerdp-sspi/sspi.c rename to libwinpr-sspi/sspi.c index a637f1e87..6b7ce5ee0 100644 --- a/libfreerdp-sspi/sspi.c +++ b/libwinpr-sspi/sspi.c @@ -19,7 +19,7 @@ #include -#include +#include #include "sspi.h" diff --git a/libfreerdp-sspi/sspi.h b/libwinpr-sspi/sspi.h similarity index 94% rename from libfreerdp-sspi/sspi.h rename to libwinpr-sspi/sspi.h index 0cac339c4..0de4ea092 100644 --- a/libfreerdp-sspi/sspi.h +++ b/libwinpr-sspi/sspi.h @@ -21,8 +21,9 @@ #define FREERDP_AUTH_SSPI_PRIVATE_H #include "config.h" + +#include #include -#include struct _CREDENTIALS { @@ -33,9 +34,6 @@ typedef struct _CREDENTIALS CREDENTIALS; CREDENTIALS* sspi_CredentialsNew(); void sspi_CredentialsFree(CREDENTIALS* credentials); -void sspi_SecBufferAlloc(PSecBuffer SecBuffer, size_t size); -void sspi_SecBufferFree(PSecBuffer SecBuffer); - SecHandle* sspi_SecureHandleAlloc(); void sspi_SecureHandleInit(SecHandle* handle); void sspi_SecureHandleInvalidate(SecHandle* handle);