diff --git a/client/test/CMakeLists.txt b/client/test/CMakeLists.txt index 4a4f6fca7..f07f72dc3 100644 --- a/client/test/CMakeLists.txt +++ b/client/test/CMakeLists.txt @@ -24,3 +24,4 @@ target_link_libraries(freerdp-test freerdp-core) target_link_libraries(freerdp-test freerdp-gdi) target_link_libraries(freerdp-test freerdp-utils) target_link_libraries(freerdp-test freerdp-channels ${CMAKE_DL_LIBS}) + diff --git a/config.h.in b/config.h.in index 9b1f92599..1dced6c30 100644 --- a/config.h.in +++ b/config.h.in @@ -25,6 +25,7 @@ #cmakedefine WITH_PROFILER #cmakedefine WITH_SSE2 #cmakedefine WITH_NEON +#cmakedefine WITH_NATIVE_SSPI /* Debug */ #cmakedefine WITH_DEBUG_CERTIFICATE diff --git a/include/freerdp/crypto/nla.h b/include/freerdp/crypto/nla.h index b869ed6a3..5975382c1 100644 --- a/include/freerdp/crypto/nla.h +++ b/include/freerdp/crypto/nla.h @@ -47,6 +47,7 @@ struct rdp_credssp SecBuffer PublicKey; SecBuffer ts_credentials; CryptoRc4 rc4_seal_state; + LPTSTR ServicePrincipalName; SEC_WINNT_AUTH_IDENTITY identity; PSecurityFunctionTable table; SecPkgContext_Sizes ContextSizes; diff --git a/include/freerdp/crypto/tls.h b/include/freerdp/crypto/tls.h index fa9f155d7..f0b2e8905 100644 --- a/include/freerdp/crypto/tls.h +++ b/include/freerdp/crypto/tls.h @@ -49,6 +49,7 @@ 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_read_all(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); diff --git a/include/winpr/handle.h b/include/winpr/handle.h new file mode 100644 index 000000000..284677ffa --- /dev/null +++ b/include/winpr/handle.h @@ -0,0 +1,45 @@ +/** + * WinPR: Windows Portable Runtime + * Handle Management + * + * 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_HANDLE_H +#define WINPR_HANDLE_H + +#include +#include +#include +#include +#include + +#ifndef _WIN32 + +#define HANDLE_FLAG_INHERIT 0x00000001 +#define HANDLE_FLAG_PROTECT_FROM_CLOSE 0x00000002 + +WINPR_API BOOL CloseHandle(HANDLE hObject); + +WINPR_API BOOL DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, + LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions); + +WINPR_API BOOL GetHandleInformation(HANDLE hObject, LPDWORD lpdwFlags); +WINPR_API BOOL SetHandleInformation(HANDLE hObject, DWORD dwMask, DWORD dwFlags); + +#endif + +#endif /* WINPR_HANDLE_H */ + diff --git a/include/winpr/heap.h b/include/winpr/heap.h new file mode 100644 index 000000000..2d5d256cd --- /dev/null +++ b/include/winpr/heap.h @@ -0,0 +1,44 @@ +/** + * WinPR: Windows Portable Runtime + * Heap Memory Allocation + * + * 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_HEAP_H +#define WINPR_HEAP_H + +#include +#include +#include +#include +#include + +#ifndef _WIN32 + +#define HEAP_GENERATE_EXCEPTIONS 0x00000004 +#define HEAP_NO_SERIALIZE 0x00000001 +#define HEAP_ZERO_MEMORY 0x00000008 +#define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010 + +WINPR_API HANDLE GetProcessHeap(void); +WINPR_API LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes); +WINPR_API LPVOID HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes); +WINPR_API BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem); + +#endif + +#endif /* WINPR_HEAP_H */ + diff --git a/include/winpr/memory.h b/include/winpr/memory.h index 32b7c1467..c1a9aa6a6 100644 --- a/include/winpr/memory.h +++ b/include/winpr/memory.h @@ -38,16 +38,9 @@ #define RtlFillMemory(Destination, Length, Fill) memset((Destination), (Fill), (Length)) #define RtlZeroMemory(Destination, Length) memset((Destination), 0, (Length)) -#define HEAP_GENERATE_EXCEPTIONS 0x00000004 -#define HEAP_NO_SERIALIZE 0x00000001 -#define HEAP_ZERO_MEMORY 0x00000008 -#define HEAP_REALLOC_IN_PLACE_ONLY 0x00000010 - -WINPR_API HANDLE GetProcessHeap(void); -WINPR_API LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes); -WINPR_API LPVOID HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes); -WINPR_API BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem); - #endif +#include + #endif /* WINPR_CRT_MEMORY_H */ + diff --git a/include/winpr/ntlm.h b/include/winpr/ntlm.h new file mode 100644 index 000000000..6e8759ceb --- /dev/null +++ b/include/winpr/ntlm.h @@ -0,0 +1,46 @@ +/** + * WinPR: Windows Portable Runtime + * NTLM Utils + * + * 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_UTILS_NTLM_H +#define WINPR_UTILS_NTLM_H + +#include +#include +#include +#include +#include + +WINPR_API BYTE* NTOWFv1W(LPWSTR Password, UINT32 PasswordLength, BYTE* NtHash); +WINPR_API BYTE* NTOWFv1A(LPSTR Password, UINT32 PasswordLength, BYTE* NtHash); + +WINPR_API BYTE* NTOWFv2W(LPWSTR Password, UINT32 PasswordLength, LPWSTR User, + UINT32 UserLength, LPWSTR Domain, UINT32 DomainLength, BYTE* NtHash); +WINPR_API BYTE* NTOWFv2A(LPSTR Password, UINT32 PasswordLength, LPSTR User, + UINT32 UserLength, LPSTR Domain, UINT32 DomainLength, BYTE* NtHash); + +#ifdef UNICODE +#define NTOWFv1 NTOWFv1W +#define NTOWFv2 NTOWFv2W +#else +#define NTOWFv1 NTOWFv1A +#define NTOWFv2 NTOWFv2W +#endif + +#endif /* WINPR_UTILS_NTLM_H */ + diff --git a/include/winpr/registry.h b/include/winpr/registry.h index 6cadc8c32..7facef76a 100644 --- a/include/winpr/registry.h +++ b/include/winpr/registry.h @@ -148,13 +148,6 @@ typedef ACCESS_MASK REGSAM; #define RRF_NOEXPAND 0x10000000 #define RRF_ZEROONFAILURE 0x20000000 -typedef struct _SECURITY_ATTRIBUTES -{ - DWORD nLength; - LPVOID lpSecurityDescriptor; - BOOL bInheritHandle; -} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; - struct val_context { int valuelen; @@ -214,15 +207,6 @@ typedef PVALENTA PVALENT; WINPR_API LONG RegCloseKey(HKEY hKey); -WINPR_API LONG RegConnectRegistryW(LPCWSTR lpMachineName, HKEY hKey, PHKEY phkResult); -WINPR_API LONG RegConnectRegistryA(LPCSTR lpMachineName, HKEY hKey, PHKEY phkResult); - -#ifdef UNICODE -#define RegConnectRegistry RegConnectRegistryW -#else -#define RegConnectRegistry RegConnectRegistryA -#endif - WINPR_API LONG RegCopyTreeW(HKEY hKeySrc, LPCWSTR lpSubKey, HKEY hKeyDest); WINPR_API LONG RegCopyTreeA(HKEY hKeySrc, LPCSTR lpSubKey, HKEY hKeyDest); @@ -243,28 +227,6 @@ WINPR_API LONG RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR #define RegCreateKeyEx RegCreateKeyExA #endif -WINPR_API LONG RegCreateKeyTransactedW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, - DWORD dwOptions, REGSAM samDesired, const LPSECURITY_ATTRIBUTES lpSecurityAttributes, - PHKEY phkResult, LPDWORD lpdwDisposition, HANDLE hTransaction, PVOID pExtendedParemeter); -WINPR_API LONG RegCreateKeyTransactedA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, - DWORD dwOptions, REGSAM samDesired, const LPSECURITY_ATTRIBUTES lpSecurityAttributes, - PHKEY phkResult, LPDWORD lpdwDisposition, HANDLE hTransaction, PVOID pExtendedParemeter); - -#ifdef UNICODE -#define RegCreateKeyTransacted RegCreateKeyTransactedW -#else -#define RegCreateKeyTransacted RegCreateKeyTransactedA -#endif - -WINPR_API LONG RegDeleteKeyW(HKEY hKey, LPCWSTR lpSubKey); -WINPR_API LONG RegDeleteKeyA(HKEY hKey, LPCSTR lpSubKey); - -#ifdef UNICODE -#define RegDeleteKey RegDeleteKeyW -#else -#define RegDeleteKey RegDeleteKeyA -#endif - WINPR_API LONG RegDeleteKeyExW(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved); WINPR_API LONG RegDeleteKeyExA(HKEY hKey, LPCSTR lpSubKey, REGSAM samDesired, DWORD Reserved); @@ -274,26 +236,6 @@ WINPR_API LONG RegDeleteKeyExA(HKEY hKey, LPCSTR lpSubKey, REGSAM samDesired, DW #define RegDeleteKeyEx RegDeleteKeyExA #endif -WINPR_API LONG RegDeleteKeyTransactedW(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, - DWORD Reserved, HANDLE hTransaction, PVOID pExtendedParameter); -WINPR_API LONG RegDeleteKeyTransactedA(HKEY hKey, LPCSTR lpSubKey, REGSAM samDesired, - DWORD Reserved, HANDLE hTransaction, PVOID pExtendedParameter); - -#ifdef UNICODE -#define RegDeleteKeyTransacted RegDeleteKeyTransactedW -#else -#define RegDeleteKeyTransacted RegDeleteKeyTransactedA -#endif - -WINPR_API LONG RegDeleteKeyValueW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName); -WINPR_API LONG RegDeleteKeyValueA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpValueName); - -#ifdef UNICODE -#define RegDeleteKeyValue RegDeleteKeyValueW -#else -#define RegDeleteKeyValue RegDeleteKeyValueA -#endif - WINPR_API LONG RegDeleteTreeW(HKEY hKey, LPCWSTR lpSubKey); WINPR_API LONG RegDeleteTreeA(HKEY hKey, LPCSTR lpSubKey); @@ -312,14 +254,8 @@ WINPR_API LONG RegDeleteValueA(HKEY hKey, LPCSTR lpValueName); #define RegDeleteValue RegDeleteValueA #endif -WINPR_API LONG RegDisablePredefinedCache(void); - WINPR_API LONG RegDisablePredefinedCacheEx(void); -WINPR_API LONG RegDisableReflectionKey(HKEY hBase); - -WINPR_API LONG RegEnableReflectionKey(HKEY hBase); - WINPR_API LONG RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcName, LPDWORD lpReserved, LPWSTR lpClass, LPDWORD lpcClass, PFILETIME lpftLastWriteTime); WINPR_API LONG RegEnumKeyExA(HKEY hKey, DWORD dwIndex, LPSTR lpName, LPDWORD lpcName, @@ -358,6 +294,17 @@ WINPR_API LONG RegGetValueA(HKEY hkey, LPCSTR lpSubKey, LPCSTR lpValue, #define RegGetValue RegGetValueA #endif +WINPR_API LONG RegLoadAppKeyW(LPCWSTR lpFile, PHKEY phkResult, + REGSAM samDesired, DWORD dwOptions, DWORD Reserved); +WINPR_API LONG RegLoadAppKeyA(LPCSTR lpFile, PHKEY phkResult, + REGSAM samDesired, DWORD dwOptions, DWORD Reserved); + +#ifdef UNICODE +#define RegLoadAppKey RegLoadAppKeyW +#else +#define RegLoadAppKey RegLoadAppKeyA +#endif + WINPR_API LONG RegLoadKeyW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpFile); WINPR_API LONG RegLoadKeyA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpFile); @@ -391,21 +338,8 @@ WINPR_API LONG RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM #define RegOpenKeyEx RegOpenKeyExA #endif -WINPR_API LONG RegOpenKeyTransactedW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, - REGSAM samDesired, PHKEY phkResult, HANDLE hTransaction, PVOID pExtendedParameter); -WINPR_API LONG RegOpenKeyTransactedA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, - REGSAM samDesired, PHKEY phkResult, HANDLE hTransaction, PVOID pExtendedParameter); - -#ifdef UNICODE -#define RegOpenKeyTransacted RegOpenKeyTransactedW -#else -#define RegOpenKeyTransacted RegOpenKeyTransactedA -#endif - WINPR_API LONG RegOpenUserClassesRoot(HANDLE hToken, DWORD dwOptions, REGSAM samDesired, PHKEY phkResult); -WINPR_API LONG RegOverridePredefKey(HKEY hKey, HKEY hNewHKey); - WINPR_API LONG RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, @@ -421,10 +355,6 @@ WINPR_API LONG RegQueryInfoKeyA(HKEY hKey, LPSTR lpClass, LPDWORD lpcClass, LPDW #define RegQueryInfoKey RegQueryInfoKeyA #endif -WINPR_API LONG RegQueryMultipleValues(HKEY hKey, PVALENT val_list, DWORD num_vals, LPTSTR lpValueBuf, LPDWORD ldwTotsize); - -WINPR_API LONG RegQueryReflectionKey(HKEY hBase, BOOL* bIsReflectionDisabled); - WINPR_API LONG RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData); WINPR_API LONG RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, @@ -436,15 +366,6 @@ WINPR_API LONG RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, #define RegQueryValueEx RegQueryValueExA #endif -WINPR_API LONG RegReplaceKeyW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpNewFile, LPCWSTR lpOldFile); -WINPR_API LONG RegReplaceKeyA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpNewFile, LPCSTR lpOldFile); - -#ifdef UNICODE -#define RegReplaceKey RegReplaceKeyW -#else -#define RegReplaceKey RegReplaceKeyA -#endif - WINPR_API LONG RegRestoreKeyW(HKEY hKey, LPCWSTR lpFile, DWORD dwFlags); WINPR_API LONG RegRestoreKeyA(HKEY hKey, LPCSTR lpFile, DWORD dwFlags); @@ -454,15 +375,6 @@ WINPR_API LONG RegRestoreKeyA(HKEY hKey, LPCSTR lpFile, DWORD dwFlags); #define RegRestoreKey RegRestoreKeyA #endif -WINPR_API LONG RegSaveKeyW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes); -WINPR_API LONG RegSaveKeyA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes); - -#ifdef UNICODE -#define RegSaveKey RegSaveKeyW -#else -#define RegSaveKey RegSaveKeyA -#endif - WINPR_API LONG RegSaveKeyExW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD Flags); WINPR_API LONG RegSaveKeyExA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD Flags); @@ -472,15 +384,6 @@ WINPR_API LONG RegSaveKeyExA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpS #define RegSaveKeyEx RegSaveKeyExA #endif -WINPR_API LONG RegSetKeyValueW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData); -WINPR_API LONG RegSetKeyValueA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData); - -#ifdef UNICODE -#define RegSetKeyValue RegSetKeyValueW -#else -#define RegSetKeyValue RegSetKeyValueA -#endif - WINPR_API LONG RegSetKeySecurity(HKEY hKey, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor); WINPR_API LONG RegSetValueExW(HKEY hKey, LPCWSTR lpValueName, DWORD Reserved, DWORD dwType, const BYTE* lpData, DWORD cbData); diff --git a/include/winpr/sam.h b/include/winpr/sam.h new file mode 100644 index 000000000..92475947f --- /dev/null +++ b/include/winpr/sam.h @@ -0,0 +1,55 @@ +/** + * WinPR: Windows Portable Runtime + * Security Accounts Manager (SAM) + * + * 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_UTILS_SAM_H +#define WINPR_UTILS_SAM_H + +#include +#include + +struct winpr_sam +{ + FILE* fp; + char* line; + char* buffer; + BOOL read_only; +}; +typedef struct winpr_sam WINPR_SAM; + +struct winpr_sam_entry +{ + LPSTR User; + UINT32 UserLength; + LPSTR Domain; + UINT32 DomainLength; + BYTE LmHash[16]; + BYTE NtHash[16]; +}; +typedef struct winpr_sam_entry WINPR_SAM_ENTRY; + +WINPR_API WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, LPSTR Domain, UINT32 DomainLength); +WINPR_API WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, LPWSTR Domain, UINT32 DomainLength); + +WINPR_API void SamFreeEntry(WINPR_SAM* sam, WINPR_SAM_ENTRY* entry); + +WINPR_API WINPR_SAM* SamOpen(BOOL read_only); +WINPR_API void SamClose(WINPR_SAM* sam); + +#endif /* WINPR_UTILS_SAM_H */ + diff --git a/include/winpr/sspi.h b/include/winpr/sspi.h index 4220d5cd6..2995ce747 100644 --- a/include/winpr/sspi.h +++ b/include/winpr/sspi.h @@ -22,8 +22,6 @@ #include "config.h" -//#define NATIVE_SSPI - #include #include #include @@ -34,7 +32,7 @@ #include #include -#ifdef NATIVE_SSPI +#ifdef WITH_NATIVE_SSPI #define SECURITY_WIN32 #include #include diff --git a/include/winpr/string.h b/include/winpr/string.h index f10840096..8dc0ae721 100644 --- a/include/winpr/string.h +++ b/include/winpr/string.h @@ -45,7 +45,7 @@ #define MB_ERR_INVALID_CHARS 0x00000008 WINPR_API char* _strdup(const char* strSource); -WINPR_API wchar_t* _wcsdup(const wchar_t* strSource); +WINPR_API WCHAR* _wcsdup(const WCHAR* strSource); WINPR_API LPSTR CharUpperA(LPSTR lpsz); WINPR_API LPWSTR CharUpperW(LPWSTR lpsz); @@ -125,6 +125,24 @@ WINPR_API int MultiByteToWideChar(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiBy WINPR_API int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar); +WINPR_API int lstrlenA(LPCSTR lpString); +WINPR_API int lstrlenW(LPCWSTR lpString); + +#ifdef UNICODE +#define lstrlen lstrlenW +#else +#define lstrlen lstrlenA +#endif + +WINPR_API int lstrcmpA(LPCSTR lpString1, LPCSTR lpString2); +WINPR_API int lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2); + +#ifdef UNICODE +#define lstrcmp lstrcmpW +#else +#define lstrcmp lstrcmpA +#endif + #endif #endif /* WINPR_CRT_STRING_H */ diff --git a/include/winpr/synch.h b/include/winpr/synch.h new file mode 100644 index 000000000..859289f23 --- /dev/null +++ b/include/winpr/synch.h @@ -0,0 +1,64 @@ +/** + * WinPR: Windows Portable Runtime + * Synchronization Functions + * + * 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_SYNCH_H +#define WINPR_SYNCH_H + +#include +#include +#include +#include +#include + +#include + +#ifndef _WIN32 + +WINPR_API HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCSTR lpName); +WINPR_API HANDLE CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName); + +#ifdef UNICODE +#define CreateSemaphore CreateSemaphoreW +#else +#define CreateSemaphore CreateSemaphoreA +#endif + +WINPR_API HANDLE OpenSemaphoreA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName); +WINPR_API HANDLE OpenSemaphoreW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName); + +#ifdef UNICODE +#define OpenSemaphore OpenSemaphoreW +#else +#define OpenSemaphore OpenSemaphoreA +#endif + +WINPR_API BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount); + +#define WAIT_OBJECT_0 0x00000000L +#define WAIT_ABANDONED 0x00000080L +#define WAIT_TIMEOUT 0x00000102L +#define WAIT_FAILED ((DWORD) 0xFFFFFFFF) + +WINPR_API DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds); +WINPR_API DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds); + +#endif + +#endif /* WINPR_SYNCH_H */ + diff --git a/winpr/registry/registry_xml.h b/include/winpr/tchar.h similarity index 69% rename from winpr/registry/registry_xml.h rename to include/winpr/tchar.h index 8ba74cb0c..e63633b63 100644 --- a/winpr/registry/registry_xml.h +++ b/include/winpr/tchar.h @@ -1,6 +1,6 @@ /** * WinPR: Windows Portable Runtime - * Windows Registry + * TCHAR * * Copyright 2012 Marc-Andre Moreau * @@ -17,16 +17,25 @@ * limitations under the License. */ -#include -#include +#ifndef WINPR_TCHAR_H +#define WINPR_TCHAR_H -struct _registry_xml -{ - xmlDocPtr doc; - xmlNodePtr node; -}; -typedef struct _registry_xml RegistryXml; +#include -RegistryXml* registry_xml_new(); -RegistryXml* registry_xml_open(); -void registry_xml_close(RegistryXml* registry); +#ifdef _WIN32 + +#include + +#else + +#ifdef UNICODE +typedef WCHAR TCHAR; +#define _tprintf wprintf +#else +typedef CHAR TCHAR; +#define _tprintf printf +#endif + +#endif + +#endif /* WINPR_TCHAR_H */ diff --git a/include/winpr/wtypes.h b/include/winpr/wtypes.h index a8a9b0ad9..94d5ac4a2 100644 --- a/include/winpr/wtypes.h +++ b/include/winpr/wtypes.h @@ -42,7 +42,7 @@ typedef int BOOL, *PBOOL, *LPBOOL; typedef unsigned char BYTE, *PBYTE, *LPBYTE; typedef BYTE BOOLEAN, *PBOOLEAN; -typedef wchar_t WCHAR, *PWCHAR; +typedef unsigned short WCHAR, *PWCHAR; typedef WCHAR* BSTR; typedef char CHAR, *PCHAR; typedef unsigned long DWORD, *PDWORD, *LPDWORD; @@ -54,14 +54,14 @@ typedef float FLOAT; typedef unsigned char UCHAR, *PUCHAR; typedef short SHORT; -typedef void* HANDLE; +typedef void* HANDLE, *LPHANDLE; typedef DWORD HCALL; typedef int INT, *LPINT; typedef signed char INT8; typedef signed short INT16; typedef signed int INT32; typedef signed __int64 INT64; -typedef const wchar_t* LMCSTR; +typedef const WCHAR* LMCSTR; typedef WCHAR* LMSTR; typedef long LONG, *PLONG, *LPLONG; typedef signed __int64 LONGLONG; @@ -74,10 +74,10 @@ typedef signed int LONG32; typedef signed __int64 LONG64; typedef const char* LPCSTR; -typedef const wchar_t* LPCWSTR; +typedef const WCHAR* LPCWSTR; typedef char* PSTR, *LPSTR; -typedef wchar_t* LPWSTR, *PWSTR; +typedef WCHAR* LPWSTR, *PWSTR; typedef unsigned __int64 QWORD; typedef UCHAR* STRING; @@ -176,6 +176,13 @@ typedef struct _SECURITY_DESCRIPTOR PACL Dacl; } SECURITY_DESCRIPTOR, *PSECURITY_DESCRIPTOR; +typedef struct _SECURITY_ATTRIBUTES +{ + DWORD nLength; + LPVOID lpSecurityDescriptor; + BOOL bInheritHandle; +} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; + #endif typedef BYTE byte; diff --git a/libfreerdp-core/gcc.c b/libfreerdp-core/gcc.c index 8db352fe6..60033e993 100644 --- a/libfreerdp-core/gcc.c +++ b/libfreerdp-core/gcc.c @@ -543,7 +543,7 @@ boolean gcc_read_client_core_data(STREAM* s, rdpSettings* settings, uint16 block break; str = freerdp_uniconv_in(settings->uniconv, stream_get_tail(s), 64); stream_seek(s, 64); - snprintf(settings->client_product_id, sizeof(settings->client_product_id), "%s", str); + snprintf(settings->client_product_id, 32, "%s", str); xfree(str); blockLength -= 64; diff --git a/libfreerdp-core/listener.c b/libfreerdp-core/listener.c index a39d96fec..4d2f109bc 100644 --- a/libfreerdp-core/listener.c +++ b/libfreerdp-core/listener.c @@ -40,7 +40,7 @@ static boolean freerdp_listener_open(freerdp_listener* instance, const char* bind_address, uint16 port) { - rdpListener* listener = (rdpListener*)instance->listener; + rdpListener* listener = (rdpListener*) instance->listener; int status; int sockfd; char servname[10]; @@ -56,14 +56,20 @@ static boolean freerdp_listener_open(freerdp_listener* instance, const char* bin hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; + if (bind_address == NULL) hints.ai_flags = AI_PASSIVE; snprintf(servname, sizeof(servname), "%d", port); status = getaddrinfo(bind_address, servname, &hints, &res); + if (status != 0) { +#ifdef _WIN32 + _tprintf(_T("getaddrinfo error: %s\n"), gai_strerror(status)); +#else perror("getaddrinfo"); +#endif return false; } @@ -73,6 +79,7 @@ static boolean freerdp_listener_open(freerdp_listener* instance, const char* bin continue; sockfd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sockfd == -1) { perror("socket"); @@ -92,14 +99,21 @@ static boolean freerdp_listener_open(freerdp_listener* instance, const char* bin #endif status = bind(sockfd, ai->ai_addr, ai->ai_addrlen); + if (status != 0) { +#ifdef _WIN32 + _tprintf(L"bind() failed with error: %u\n", WSAGetLastError()); + WSACleanup(); +#else perror("bind"); close(sockfd); +#endif continue; } status = listen(sockfd, 10); + if (status != 0) { perror("listen"); @@ -110,9 +124,9 @@ static boolean freerdp_listener_open(freerdp_listener* instance, const char* bin listener->sockfds[listener->num_sockfds++] = sockfd; if (ai->ai_family == AF_INET) - sin_addr = &(((struct sockaddr_in*)ai->ai_addr)->sin_addr); + sin_addr = &(((struct sockaddr_in*) ai->ai_addr)->sin_addr); else - sin_addr = &(((struct sockaddr_in6*)ai->ai_addr)->sin6_addr); + sin_addr = &(((struct sockaddr_in6*) ai->ai_addr)->sin6_addr); printf("Listening on %s port %s.\n", inet_ntop(ai->ai_family, sin_addr, buf, sizeof(buf)), servname); } @@ -125,12 +139,13 @@ static boolean freerdp_listener_open(freerdp_listener* instance, const char* bin static boolean freerdp_listener_open_local(freerdp_listener* instance, const char* path) { #ifndef _WIN32 - rdpListener* listener = (rdpListener*)instance->listener; int status; int sockfd; struct sockaddr_un addr; + rdpListener* listener = (rdpListener*) instance->listener; sockfd = socket(AF_UNIX, SOCK_STREAM, 0); + if (sockfd == -1) { perror("socket"); @@ -142,7 +157,9 @@ static boolean freerdp_listener_open_local(freerdp_listener* instance, const cha addr.sun_family = AF_UNIX; strncpy(addr.sun_path, path, sizeof(addr.sun_path)); unlink(path); - status = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)); + + status = bind(sockfd, (struct sockaddr*) &addr, sizeof(addr)); + if (status != 0) { perror("bind"); @@ -151,6 +168,7 @@ static boolean freerdp_listener_open_local(freerdp_listener* instance, const cha } status = listen(sockfd, 10); + if (status != 0) { perror("listen"); @@ -164,7 +182,7 @@ static boolean freerdp_listener_open_local(freerdp_listener* instance, const cha return true; #else - return false; + return true; #endif } @@ -172,19 +190,20 @@ static void freerdp_listener_close(freerdp_listener* instance) { int i; - rdpListener* listener = (rdpListener*)instance->listener; + rdpListener* listener = (rdpListener*) instance->listener; for (i = 0; i < listener->num_sockfds; i++) { close(listener->sockfds[i]); } + listener->num_sockfds = 0; } static boolean freerdp_listener_get_fds(freerdp_listener* instance, void** rfds, int* rcount) { - rdpListener* listener = (rdpListener*)instance->listener; int i; + rdpListener* listener = (rdpListener*) instance->listener; if (listener->num_sockfds < 1) return false; diff --git a/libfreerdp-core/rdp.c b/libfreerdp-core/rdp.c index b11ab2727..2170816fb 100644 --- a/libfreerdp-core/rdp.c +++ b/libfreerdp-core/rdp.c @@ -912,8 +912,10 @@ rdpRdp* rdp_new(freerdp* instance) { rdp->instance = instance; rdp->settings = settings_new((void*) instance); + if (instance != NULL) instance->settings = rdp->settings; + rdp->extension = extension_new(instance); rdp->transport = transport_new(rdp->settings); rdp->license = license_new(rdp); @@ -937,6 +939,8 @@ rdpRdp* rdp_new(freerdp* instance) void rdp_free(rdpRdp* rdp) { + return; + if (rdp != NULL) { crypto_rc4_free(rdp->rc4_decrypt_key); diff --git a/libfreerdp-core/rpc.c b/libfreerdp-core/rpc.c index aacc89c5f..874667488 100644 --- a/libfreerdp-core/rpc.c +++ b/libfreerdp-core/rpc.c @@ -38,7 +38,7 @@ boolean ntlm_client_init(rdpNtlm* ntlm, boolean confidentiality, char* user, cha ntlm->confidentiality = confidentiality; -#ifdef NATIVE_SSPI +#ifdef WITH_NATIVE_SSPI { HMODULE hSSPI; INIT_SECURITY_INTERFACE InitSecurityInterface; diff --git a/libfreerdp-core/tcp.c b/libfreerdp-core/tcp.c index 6c0390f31..7a40175eb 100644 --- a/libfreerdp-core/tcp.c +++ b/libfreerdp-core/tcp.c @@ -189,8 +189,14 @@ boolean tcp_set_blocking_mode(rdpTcp* tcp, boolean blocking) else fcntl(tcp->sockfd, F_SETFL, flags | O_NONBLOCK); #else + int status; u_long arg = blocking; - ioctlsocket(tcp->sockfd, FIONBIO, &arg); + + status = ioctlsocket(tcp->sockfd, FIONBIO, &arg); + + if (status != NO_ERROR) + printf("ioctlsocket() failed with error: %ld\n", status); + tcp->wsa_event = WSACreateEvent(); WSAEventSelect(tcp->sockfd, tcp->wsa_event, FD_READ); #endif diff --git a/libfreerdp-crypto/crypto.c b/libfreerdp-crypto/crypto.c index cd4693ff4..b6a73cc46 100644 --- a/libfreerdp-crypto/crypto.c +++ b/libfreerdp-crypto/crypto.c @@ -69,7 +69,8 @@ void crypto_rc4(CryptoRc4 rc4, uint32 length, const uint8* in_data, uint8* out_d void crypto_rc4_free(CryptoRc4 rc4) { - xfree(rc4); + if (rc4) + xfree(rc4); } CryptoDes3 crypto_des3_encrypt_init(const uint8* key, const uint8* ivec) diff --git a/libfreerdp-crypto/nla.c b/libfreerdp-crypto/nla.c index 9d82dc79e..b3e1024d7 100644 --- a/libfreerdp-crypto/nla.c +++ b/libfreerdp-crypto/nla.c @@ -76,6 +76,8 @@ #define WITH_DEBUG_CREDSSP #endif +#define TERMSRV_SPN_PREFIX "TERMSRV/" + void credssp_send(rdpCredssp* credssp); int credssp_recv(rdpCredssp* credssp); void credssp_buffer_print(rdpCredssp* credssp); @@ -92,8 +94,12 @@ SECURITY_STATUS credssp_decrypt_ts_credentials(rdpCredssp* credssp); int credssp_ntlm_client_init(rdpCredssp* credssp) { + char* spn; + int length; freerdp* instance; - rdpSettings* settings = credssp->settings; + rdpSettings* settings; + + settings = credssp->settings; instance = (freerdp*) settings->instance; if ((settings->password == NULL) || (settings->username == NULL)) @@ -112,6 +118,20 @@ int credssp_ntlm_client_init(rdpCredssp* credssp) sspi_SecBufferAlloc(&credssp->PublicKey, credssp->tls->public_key.length); CopyMemory(credssp->PublicKey.pvBuffer, credssp->tls->public_key.data, credssp->tls->public_key.length); + length = sizeof(TERMSRV_SPN_PREFIX) + strlen(settings->hostname); + + spn = (SEC_CHAR*) malloc(length + 1); + sprintf(spn, "%s%s", TERMSRV_SPN_PREFIX, settings->hostname); + +#ifdef UNICODE + credssp->ServicePrincipalName = (LPTSTR) malloc(length * 2 + 2); + MultiByteToWideChar(CP_ACP, 0, spn, length, + (LPWSTR) credssp->ServicePrincipalName, length); + free(spn); +#else + credssp->ServicePrincipalName = spn; +#endif + return 1; } @@ -126,8 +146,6 @@ int credssp_ntlm_server_init(rdpCredssp* credssp) rdpSettings* settings = credssp->settings; instance = (freerdp*) settings->instance; - sspi_SetAuthIdentity(&(credssp->identity), "username", NULL, NULL); - sspi_SecBufferAlloc(&credssp->PublicKey, credssp->tls->public_key.length); CopyMemory(credssp->PublicKey.pvBuffer, credssp->tls->public_key.data, credssp->tls->public_key.length); @@ -157,13 +175,13 @@ int credssp_client_authenticate(rdpCredssp* credssp) if (credssp_ntlm_client_init(credssp) == 0) return 0; -#ifdef NATIVE_SSPI +#ifdef WITH_NATIVE_SSPI { HMODULE hSSPI; INIT_SECURITY_INTERFACE InitSecurityInterface; PSecurityFunctionTable pSecurityInterface = NULL; - hSSPI = LoadLibrary(_T("secur32.dll")); + hSSPI = LoadLibrary(_T("security.dll")); #ifdef UNICODE InitSecurityInterface = (INIT_SECURITY_INTERFACE) GetProcAddress(hSSPI, "InitSecurityInterfaceW"); @@ -202,8 +220,8 @@ int credssp_client_authenticate(rdpCredssp* credssp) memset(&output_buffer, 0, sizeof(SecBuffer)); memset(&credssp->ContextSizes, 0, sizeof(SecPkgContext_Sizes)); - fContextReq = ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT | - ISC_REQ_CONFIDENTIALITY | ISC_REQ_DELEGATE; + fContextReq = ISC_REQ_CONFIDENTIALITY | ISC_REQ_INTEGRITY | ISC_REQ_IDENTIFY | + ISC_REQ_EXTENDED_ERROR | ISC_REQ_SEQUENCE_DETECT | ISC_REQ_REPLAY_DETECT; while (true) { @@ -216,8 +234,8 @@ int credssp_client_authenticate(rdpCredssp* credssp) status = credssp->table->InitializeSecurityContext(&credentials, (have_context) ? &credssp->context : NULL, - NULL, fContextReq, 0, SECURITY_NETWORK_DREP, - (have_input_buffer) ? &input_buffer_desc : NULL, + credssp->ServicePrincipalName, fContextReq, 0, + SECURITY_NATIVE_DREP, (have_input_buffer) ? &input_buffer_desc : NULL, 0, &credssp->context, &output_buffer_desc, &pfContextAttr, &expiration); if (input_buffer.pvBuffer != NULL) @@ -324,7 +342,7 @@ int credssp_client_authenticate(rdpCredssp* credssp) return -1; #ifdef WITH_DEBUG_CREDSSP - printf("Receiving Authentication Token\n"); + printf("Receiving Authentication Token (%d)\n", credssp->negoToken.cbBuffer); winpr_HexDump(credssp->negoToken.pvBuffer, credssp->negoToken.cbBuffer); #endif @@ -398,7 +416,7 @@ int credssp_server_authenticate(rdpCredssp* credssp) if (credssp_ntlm_server_init(credssp) == 0) return 0; -#ifdef NATIVE_SSPI +#ifdef WITH_NATIVE_SSPI { HMODULE hSSPI; INIT_SECURITY_INTERFACE InitSecurityInterface; @@ -439,9 +457,9 @@ int credssp_server_authenticate(rdpCredssp* credssp) have_context = false; have_input_buffer = false; have_pub_key_auth = false; - memset(&input_buffer, 0, sizeof(SecBuffer)); - memset(&output_buffer, 0, sizeof(SecBuffer)); - memset(&credssp->ContextSizes, 0, sizeof(SecPkgContext_Sizes)); + ZeroMemory(&input_buffer, sizeof(SecBuffer)); + ZeroMemory(&output_buffer, sizeof(SecBuffer)); + ZeroMemory(&credssp->ContextSizes, sizeof(SecPkgContext_Sizes)); fContextReq = ASC_REQ_REPLAY_DETECT | ASC_REQ_SEQUENCE_DETECT | ASC_REQ_CONFIDENTIALITY | ASC_REQ_DELEGATE; @@ -472,6 +490,12 @@ int credssp_server_authenticate(rdpCredssp* credssp) p_buffer->pvBuffer = credssp->negoToken.pvBuffer; p_buffer->cbBuffer = credssp->negoToken.cbBuffer; + if (credssp->negoToken.cbBuffer < 1) + { + printf("CredSSP: invalid negoToken!\n"); + return -1; + } + output_buffer_desc.ulVersion = SECBUFFER_VERSION; output_buffer_desc.cBuffers = 1; output_buffer_desc.pBuffers = &output_buffer; @@ -688,15 +712,15 @@ int credssp_skip_ts_password_creds(rdpCredssp* credssp) int length; int ts_password_creds_length = 0; - length = ber_skip_octet_string(credssp->identity.DomainLength); + length = ber_skip_octet_string(credssp->identity.DomainLength * 2); length += ber_skip_contextual_tag(length); ts_password_creds_length += length; - length = ber_skip_octet_string(credssp->identity.UserLength); + length = ber_skip_octet_string(credssp->identity.UserLength * 2); length += ber_skip_contextual_tag(length); ts_password_creds_length += length; - length = ber_skip_octet_string(credssp->identity.PasswordLength); + length = ber_skip_octet_string(credssp->identity.PasswordLength * 2); length += ber_skip_contextual_tag(length); ts_password_creds_length += length; @@ -719,6 +743,7 @@ void credssp_read_ts_password_creds(rdpCredssp* credssp, STREAM* s) credssp->identity.Domain = (UINT16*) malloc(length); CopyMemory(credssp->identity.Domain, s->p, credssp->identity.DomainLength); stream_seek(s, credssp->identity.DomainLength); + credssp->identity.DomainLength /= 2; /* [1] userName (OCTET STRING) */ ber_read_contextual_tag(s, 1, &length, true); @@ -727,6 +752,7 @@ void credssp_read_ts_password_creds(rdpCredssp* credssp, STREAM* s) credssp->identity.User = (UINT16*) malloc(length); CopyMemory(credssp->identity.User, s->p, credssp->identity.UserLength); stream_seek(s, credssp->identity.UserLength); + credssp->identity.UserLength /= 2; /* [2] password (OCTET STRING) */ ber_read_contextual_tag(s, 2, &length, true); @@ -735,6 +761,7 @@ void credssp_read_ts_password_creds(rdpCredssp* credssp, STREAM* s) credssp->identity.Password = (UINT16*) malloc(length); CopyMemory(credssp->identity.Password, s->p, credssp->identity.PasswordLength); stream_seek(s, credssp->identity.PasswordLength); + credssp->identity.PasswordLength /= 2; } void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s) @@ -748,16 +775,16 @@ void credssp_write_ts_password_creds(rdpCredssp* credssp, STREAM* s) ber_write_sequence_tag(s, length); /* [0] domainName (OCTET STRING) */ - ber_write_contextual_tag(s, 0, credssp->identity.DomainLength + 2, true); - ber_write_octet_string(s, (BYTE*) credssp->identity.Domain, credssp->identity.DomainLength); + ber_write_contextual_tag(s, 0, credssp->identity.DomainLength * 2 + 2, true); + ber_write_octet_string(s, (BYTE*) credssp->identity.Domain, credssp->identity.DomainLength * 2); /* [1] userName (OCTET STRING) */ - ber_write_contextual_tag(s, 1, credssp->identity.UserLength + 2, true); - ber_write_octet_string(s, (BYTE*) credssp->identity.User, credssp->identity.UserLength); + ber_write_contextual_tag(s, 1, credssp->identity.UserLength * 2 + 2, true); + ber_write_octet_string(s, (BYTE*) credssp->identity.User, credssp->identity.UserLength * 2); /* [2] password (OCTET STRING) */ - ber_write_contextual_tag(s, 2, credssp->identity.PasswordLength + 2, true); - ber_write_octet_string(s, (BYTE*) credssp->identity.Password, credssp->identity.PasswordLength); + ber_write_contextual_tag(s, 2, credssp->identity.PasswordLength * 2 + 2, true); + ber_write_octet_string(s, (BYTE*) credssp->identity.Password, credssp->identity.PasswordLength * 2); } int credssp_skip_ts_credentials(rdpCredssp* credssp) @@ -1039,12 +1066,14 @@ int credssp_recv(rdpCredssp* credssp) int status; UINT32 version; - s = stream_new(2048); - status = tls_read(credssp->tls, s->data, stream_get_left(s)); + s = stream_new(4096); + + status = tls_read_all(credssp->tls, s->p, stream_get_left(s)); if (status < 0) { - stream_free(s) ; + printf("credssp_recv() error: %d\n", status); + stream_free(s); return -1; } diff --git a/libfreerdp-crypto/tls.c b/libfreerdp-crypto/tls.c index 26855e0b3..beba56bc8 100644 --- a/libfreerdp-crypto/tls.c +++ b/libfreerdp-crypto/tls.c @@ -53,7 +53,6 @@ static void tls_free_certificate(CryptoCert cert) xfree(cert); } - boolean tls_connect(rdpTls* tls) { CryptoCert cert; @@ -116,7 +115,8 @@ boolean tls_connect(rdpTls* tls) return false; } - if (!tls_verify_certificate(tls, cert, tls->settings->hostname)) { + if (!tls_verify_certificate(tls, cert, tls->settings->hostname)) + { printf("tls_connect: certificate not trusted, aborting.\n"); tls_disconnect(tls); tls_free_certificate(cert); @@ -188,12 +188,29 @@ boolean tls_accept(rdpTls* tls, const char* cert_file, const char* privatekey_fi return false; } - connection_status = SSL_accept(tls->ssl); - - if (connection_status <= 0) + while (1) { - if (tls_print_error("SSL_accept", tls->ssl, connection_status)) - return false; + connection_status = SSL_accept(tls->ssl); + + if (connection_status <= 0) + { + switch (SSL_get_error(tls->ssl, connection_status)) + { + case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_WRITE: + break; + + default: + if (tls_print_error("SSL_accept", tls->ssl, connection_status)) + return false; + break; + + } + } + else + { + break; + } } printf("TLS connection accepted\n"); @@ -232,6 +249,19 @@ int tls_read(rdpTls* tls, uint8* data, int length) return status; } +int tls_read_all(rdpTls* tls, uint8* data, int length) +{ + int status; + + do + { + status = tls_read(tls, data, length); + } + while (status == 0); + + return status; +} + int tls_write(rdpTls* tls, uint8* data, int length) { int status; @@ -298,11 +328,11 @@ boolean tls_print_error(char* func, SSL* connection, int value) return true; case SSL_ERROR_WANT_READ: - printf("SSL_ERROR_WANT_READ\n"); + printf("%s: SSL_ERROR_WANT_READ\n", func); return false; case SSL_ERROR_WANT_WRITE: - printf("SSL_ERROR_WANT_WRITE\n"); + printf("%s: SSL_ERROR_WANT_WRITE\n", func); return false; case SSL_ERROR_SYSCALL: diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index b208f64dd..cf7f3e743 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -32,4 +32,6 @@ if(NOT WIN32) # Build Server Channels library add_subdirectory(channels) +else() + add_subdirectory(Windows) endif() diff --git a/server/Windows/CMakeLists.txt b/server/Windows/CMakeLists.txt new file mode 100644 index 000000000..1de211f5d --- /dev/null +++ b/server/Windows/CMakeLists.txt @@ -0,0 +1,26 @@ +# FreeRDP: A Remote Desktop Protocol Client +# FreeRDP Windows Server 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. + +add_executable(wfreerdp-server + wfreerdp.c) + +target_link_libraries(wfreerdp-server freerdp-core) +target_link_libraries(wfreerdp-server freerdp-utils) +target_link_libraries(wfreerdp-server freerdp-codec) +target_link_libraries(wfreerdp-server freerdp-channels) diff --git a/server/Windows/server.crt b/server/Windows/server.crt new file mode 100644 index 000000000..7ce931c26 --- /dev/null +++ b/server/Windows/server.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICyzCCAbOgAwIBAgIJANbqtAWwlQZuMA0GCSqGSIb3DQEBBQUAMBIxEDAOBgNV +BAMTB0ZyZWVSRFAwHhcNMDkxMDI5MDA0MTQ5WhcNMDkxMTI4MDA0MTQ5WjASMRAw +DgYDVQQDEwdGcmVlUkRQMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +q7mxFgRbS2FYJZX7BzpNd4T/n4nEVDBY6YaObLjGpaB1TptzXTcmfDrDslTGwcEY +hTFAC4ZvY6yOURExqbph4LSgvkoa6J722RjVPfshGa4mlh2SXvTiaV26VPPxddGb +o6fbs2u029lbtBlpIVbhx5RN9vstNkll26oSZ6wfEdBNHQJLd2SU4ItWHj8zjz1f +eGxjgChHihUlwcBYKDJsKFkzHZmLrMgB37KsGlXi/WV+eEsjgvz4yP7I3TL8+GsN +MjV8fRGVEKTbKSmgunO67d5u+IaqUQb0Ad1ha1jzDQ+a6hdymrulJSIhoOVfKkwi +ptTe43FgwxVRIygJP9HjHQIDAQABoyQwIjATBgNVHSUEDDAKBggrBgEFBQcDATAL +BgNVHQ8EBAMCBDAwDQYJKoZIhvcNAQEFBQADggEBAIOdEDhOX2kbl02znltd9hCr +nV4kRPKm979RKwBNkrEuwYSlcsjAHg5MZ5itH3wFOUo2s5pjt7/vMOAg+6rOBbIa +nqr22/gKBtOmuaJLG1yjxDC2vfez7f3B26pKgxa/krM8oxiFdT9n8QbdxdkN7/D9 +3RLU/aCfgrMzXxRus7eq3kR00jnSs6ggnAfE1E9gric3vFgr1wCzdcriRXmXDfUb +hRq+4VG+ZWk16TwCofV5GVU39XWCv5HNO2swAdjkNXgI5e3tQbV3wWLZLqqYzBco +iWulAXtoCGmE81+u1Ms7hLLzpXitLZSGPu1r+sDdkKPLCmOvkAaljDQ4nBz7fIA= +-----END CERTIFICATE----- diff --git a/server/Windows/server.key b/server/Windows/server.key new file mode 100644 index 000000000..5c2f2c803 --- /dev/null +++ b/server/Windows/server.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAq7mxFgRbS2FYJZX7BzpNd4T/n4nEVDBY6YaObLjGpaB1Tptz +XTcmfDrDslTGwcEYhTFAC4ZvY6yOURExqbph4LSgvkoa6J722RjVPfshGa4mlh2S +XvTiaV26VPPxddGbo6fbs2u029lbtBlpIVbhx5RN9vstNkll26oSZ6wfEdBNHQJL +d2SU4ItWHj8zjz1feGxjgChHihUlwcBYKDJsKFkzHZmLrMgB37KsGlXi/WV+eEsj +gvz4yP7I3TL8+GsNMjV8fRGVEKTbKSmgunO67d5u+IaqUQb0Ad1ha1jzDQ+a6hdy +mrulJSIhoOVfKkwiptTe43FgwxVRIygJP9HjHQIDAQABAoIBAAVv5K54xtc1JtBR +1lfdPbSqDlnjx8aOnVIPg5TnqMp3sR8jBt0NsPc/+RA9ZOmfjoIxFAEJaZ9zSDJC +5BqmnxC5R1mfCQkSd2haQ+4pdFvWyrv4Bblh8YU6hXrJGn0LfO0KlIcywtAvKpsi +LtTyZkWmaW2HeF/+pO32jYygw38R1wd8Tl6GwjOXwTF6lFACJXOT4YAzcfp3FKSB +AiKBIGuMzozoSND7KPFNRrhGhNumJpdS5A8Fb8D2c/ZMv6Cq5IbwOgTfKun+Bz+s +mFbnzeb1uWRqQbsVXOBBW/zHfuG3SU5qeZsaAyuu4DTy+LE1oAHF9uhBSHuT5C6i +vCJ8A8ECgYEA1iaOmiEJYBrs25iAc4SjCKqhY0mwR3wtu3I06vmgUoML5fhPMv36 +SvYQIqDyNw3p7TE6mZtw9+G+kK3PqhuJhogwSwg0a6o51RdKnhXH3/68oNWtKCLC +1AmR8q/Gd3FwAR3b49CuOIZ9uOiJrc/ejzKdFEJTDR1/TX1frWfZznECgYEAzUiz +XxFf7YrGel7JgmfRD2eZRYngOoteFlg5Tee42UjeAY2Pt2aiDLk+2TqQEdI9+Xg7 +LcFdBqcSNd8bh33xSzgNthIkX+lTDzx0SmKGfyxfFBJcY8nzsLvvnNt3YeuMeaJQ +CPszwoZ0jcD46jTCjbrKhaLyEWmUkDp1O71NTW0CgYAXKF49Xpsz8FVyvcAOPeaf +dkwzf3F3mX8ciRId4taqdY9g1AREgGCDoK5IAF2RBIkqZCtxFvUVaS0BWjpdq9Ko +YKvQQVfh2KueVoF0LOjLWTGutsydzXyCD3Lf6pAstHCnPkJcFWHxrOGFkGfrCtKH +a7K+0RlIDsuIZqllCBjukQKBgA31+MTpYJW+D1t5IMkumEgs6n6RLt+sZLyuSU9k +B+03CGogn3qAj1rAKmcJlYywuKhDpfqpoNL3/8QMJUokpYlRCZWtTC39pzltCheY +9b6mXNz3lrLupBUL4vLO9iKBq28GO90wgEelbz3ItuTuq6CJ6IYIG+BVRtY8M4bZ +i+1NAoGANXZjYnJYDnh8Je9SDxDSc5byzK7ddkQoId64RCIfNHqNKH63P81vjgnH +YBIPtagY75ZVVNxujCF7m8Rety+d8tEFwfQKDin2EVI7PD2rOJra385/izp7HuBR +vqxvLzG9Xv3cNOU2l7PttVw4Pa2i5E37atKi3V3Zp2kMW+KaKPQ= +-----END RSA PRIVATE KEY----- diff --git a/server/Windows/wfreerdp.c b/server/Windows/wfreerdp.c new file mode 100644 index 000000000..bd7c7b63a --- /dev/null +++ b/server/Windows/wfreerdp.c @@ -0,0 +1,289 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * FreeRDP Windows Server + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +HANDLE g_done_event; +int g_thread_count = 0; + +struct wf_peer_context +{ + rdpContext _p; + boolean activated; +}; +typedef struct wf_peer_context wfPeerContext; + +void wf_peer_context_new(freerdp_peer* client, wfPeerContext* context) +{ + +} + +void wf_peer_context_free(freerdp_peer* client, wfPeerContext* context) +{ + if (context) + { + xfree(context); + } +} + +static void wf_peer_init(freerdp_peer* client) +{ + client->context_size = sizeof(wfPeerContext); + client->ContextNew = (psPeerContextNew) wf_peer_context_new; + client->ContextFree = (psPeerContextFree) wf_peer_context_free; + freerdp_peer_context_new(client); +} + +boolean wf_peer_post_connect(freerdp_peer* client) +{ + wfPeerContext* context = (wfPeerContext*) client->context; + + /** + * This callback is called when the entire connection sequence is done, i.e. we've received the + * Font List PDU from the client and sent out the Font Map PDU. + * The server may start sending graphics output and receiving keyboard/mouse input after this + * callback returns. + */ + + printf("Client %s is activated (osMajorType %d osMinorType %d)", client->local ? "(local)" : client->hostname, + client->settings->os_major_type, client->settings->os_minor_type); + + if (client->settings->autologon) + { + printf(" and wants to login automatically as %s\\%s", + client->settings->domain ? client->settings->domain : "", + client->settings->username); + + /* A real server may perform OS login here if NLA is not executed previously. */ + } + printf("\n"); + + printf("Client requested desktop: %dx%dx%d\n", + client->settings->width, client->settings->height, client->settings->color_depth); + + /* A real server should tag the peer as activated here and start sending updates in main loop. */ + + /* Return false here would stop the execution of the peer mainloop. */ + return true; +} + +boolean wf_peer_activate(freerdp_peer* client) +{ + wfPeerContext* context = (wfPeerContext*) client->context; + + context->activated = true; + + return true; +} + +void wf_peer_synchronize_event(rdpInput* input, uint32 flags) +{ + printf("Client sent a synchronize event (flags:0x%X)\n", flags); +} + +void wf_peer_keyboard_event(rdpInput* input, uint16 flags, uint16 code) +{ + freerdp_peer* client = input->context->peer; + rdpUpdate* update = client->update; + wfPeerContext* context = (wfPeerContext*) input->context; + + printf("Client sent a keyboard event (flags:0x%X code:0x%X)\n", flags, code); + + if ((flags & 0x4000) && code == 0x1F) /* 's' key */ + { + if (client->settings->width != 800) + { + client->settings->width = 800; + client->settings->height = 600; + } + else + { + client->settings->width = 640; + client->settings->height = 480; + } + update->DesktopResize(update->context); + context->activated = false; + } + else if ((flags & 0x4000) && code == 0x2D) /* 'x' key */ + { + client->Close(client); + } +} + +void wf_peer_unicode_keyboard_event(rdpInput* input, uint16 flags, uint16 code) +{ + printf("Client sent a unicode keyboard event (flags:0x%X code:0x%X)\n", flags, code); +} + +void wf_peer_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) +{ + printf("Client sent a mouse event (flags:0x%X pos:%d,%d)\n", flags, x, y); +} + +void wf_peer_extended_mouse_event(rdpInput* input, uint16 flags, uint16 x, uint16 y) +{ + printf("Client sent an extended mouse event (flags:0x%X pos:%d,%d)\n", flags, x, y); +} + +static DWORD WINAPI wf_peer_main_loop(LPVOID lpParam) +{ + int rcount; + void* rfds[32]; + wfPeerContext* context; + freerdp_peer* client = (freerdp_peer*) lpParam; + + memset(rfds, 0, sizeof(rfds)); + + wf_peer_init(client); + + /* Initialize the real server settings here */ + client->settings->cert_file = xstrdup("server.crt"); + client->settings->privatekey_file = xstrdup("server.key"); + + client->settings->nla_security = true; + client->settings->tls_security = false; + client->settings->rdp_security = false; + + client->PostConnect = wf_peer_post_connect; + client->Activate = wf_peer_activate; + + client->input->SynchronizeEvent = wf_peer_synchronize_event; + client->input->KeyboardEvent = wf_peer_keyboard_event; + client->input->UnicodeKeyboardEvent = wf_peer_unicode_keyboard_event; + client->input->MouseEvent = wf_peer_mouse_event; + client->input->ExtendedMouseEvent = wf_peer_extended_mouse_event; + + client->Initialize(client); + context = (wfPeerContext*) client->context; + + printf("We've got a client %s\n", client->local ? "(local)" : client->hostname); + + while (1) + { + rcount = 0; + + if (client->GetFileDescriptor(client, rfds, &rcount) != true) + { + printf("Failed to get FreeRDP file descriptor\n"); + break; + } + + if (client->CheckFileDescriptor(client) != true) + { + printf("Failed to check FreeRDP file descriptor\n"); + break; + } + } + + printf("Client %s disconnected.\n", client->local ? "(local)" : client->hostname); + + client->Disconnect(client); + freerdp_peer_context_free(client); + freerdp_peer_free(client); + + return 0; +} + +static void wf_peer_accepted(freerdp_listener* instance, freerdp_peer* client) +{ + /* start peer main loop thread */ + + if (CreateThread(NULL, 0, wf_peer_main_loop, client, 0, NULL) != 0) + g_thread_count++; +} + +static void wf_server_main_loop(freerdp_listener* instance) +{ + int rcount; + void* rfds[32]; + + memset(rfds, 0, sizeof(rfds)); + + while (1) + { + rcount = 0; + + if (instance->GetFileDescriptor(instance, rfds, &rcount) != true) + { + printf("Failed to get FreeRDP file descriptor\n"); + break; + } + + if (instance->CheckFileDescriptor(instance) != true) + { + printf("Failed to check FreeRDP file descriptor\n"); + break; + } + } + + instance->Close(instance); +} + +int main(int argc, char* argv[]) +{ + int port = 3389; + WSADATA wsa_data; + freerdp_listener* instance; + + instance = freerdp_listener_new(); + + instance->PeerAccepted = wf_peer_accepted; + + if (WSAStartup(0x101, &wsa_data) != 0) + return 1; + + g_done_event = CreateEvent(0, 1, 0, 0); + + if (argc == 2) + port = atoi(argv[1]); + + /* Open the server socket and start listening. */ + + if (instance->Open(instance, NULL, port)) + { + /* Entering the server main loop. In a real server the listener can be run in its own thread. */ + wf_server_main_loop(instance); + } + + if (g_thread_count > 0) + WaitForSingleObject(g_done_event, INFINITE); + else + MessageBox(GetConsoleWindow(), + L"Failed to start wfreerdp-server.\n\nPlease check the debug output.", + L"FreeRDP Error", MB_ICONSTOP); + + WSACleanup(); + + freerdp_listener_free(instance); + + return 0; +} + diff --git a/winpr/.gitignore b/winpr/.gitignore new file mode 100644 index 000000000..68936e807 --- /dev/null +++ b/winpr/.gitignore @@ -0,0 +1,3 @@ +tools/hash/winpr-hash +tools/reg/winpr-reg + diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index e06e66934..1b4e1b5f9 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -19,8 +19,13 @@ add_subdirectory(crt) add_subdirectory(utils) +add_subdirectory(heap) +add_subdirectory(handle) +add_subdirectory(synch) add_subdirectory(bcrypt) add_subdirectory(rpc) add_subdirectory(sspi) add_subdirectory(registry) +add_subdirectory(tools) + diff --git a/winpr/crt/memory.c b/winpr/crt/memory.c index cb859e056..0f9b16f39 100644 --- a/winpr/crt/memory.c +++ b/winpr/crt/memory.c @@ -24,36 +24,6 @@ #ifndef _WIN32 -HANDLE GetProcessHeap(void) -{ - return NULL; -} -LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes) -{ - LPVOID lpMem = NULL; - - if (dwFlags & HEAP_ZERO_MEMORY) - lpMem = calloc(1, dwBytes); - else - lpMem = malloc(dwBytes); - - return lpMem; -} - -LPVOID HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes) -{ - LPVOID lpNewMem; - - lpNewMem = realloc(lpMem, dwBytes); - - return lpNewMem; -} - -BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) -{ - free(lpMem); - return 1; -} #endif diff --git a/winpr/crt/string.c b/winpr/crt/string.c index a507a3bf9..5415bb5a3 100644 --- a/winpr/crt/string.c +++ b/winpr/crt/string.c @@ -41,9 +41,9 @@ char* _strdup(const char* strSource) return strDestination; } -wchar_t* _wcsdup(const wchar_t* strSource) +WCHAR* _wcsdup(const WCHAR* strSource) { - wchar_t* strDestination; + WCHAR* strDestination; if (strSource == NULL) return NULL; @@ -56,7 +56,7 @@ wchar_t* _wcsdup(const wchar_t* strSource) if (strDestination != NULL) wcscpy(strDestination, strSource); #else - strDestination = wcsdup(strSource); + strDestination = (WCHAR*) wcsdup((wchar_t*) strSource); #endif if (strDestination == NULL) @@ -505,4 +505,40 @@ int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int return conv_out_len; } +int lstrlenA(LPCSTR lpString) +{ + return strlen(lpString); +} + +int lstrlenW(LPCWSTR lpString) +{ + LPWSTR p; + + if (!lpString) + return 0; + + p = (LPWSTR) lpString; + + while (*p) + p++; + + return p - lpString; +} + +int lstrcmpA(LPCSTR lpString1, LPCSTR lpString2) +{ + return strcmp(lpString1, lpString2); +} + +int lstrcmpW(LPCWSTR lpString1, LPCWSTR lpString2) +{ + while (*lpString1 && (*lpString1 == *lpString2)) + { + lpString1++; + lpString2++; + } + + return *lpString1 - *lpString2; +} + #endif diff --git a/winpr/handle/CMakeLists.txt b/winpr/handle/CMakeLists.txt new file mode 100644 index 000000000..16edeb710 --- /dev/null +++ b/winpr/handle/CMakeLists.txt @@ -0,0 +1,28 @@ +# WinPR: Windows Portable Runtime +# libwinpr-handle 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_HANDLE_SRCS + handle.c) + +add_library(winpr-handle ${WINPR_HANDLE_SRCS}) + +set_target_properties(winpr-handle PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") + +install(TARGETS winpr-handle DESTINATION ${CMAKE_INSTALL_LIBDIR}) + diff --git a/winpr/handle/handle.c b/winpr/handle/handle.c new file mode 100644 index 000000000..098f2e331 --- /dev/null +++ b/winpr/handle/handle.c @@ -0,0 +1,66 @@ +/** + * WinPR: Windows Portable Runtime + * Handle Management + * + * 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 + +#ifndef _WIN32 + +#if defined __APPLE__ +#include +#include +#include +#include +#include +#define winpr_sem_t semaphore_td +#else +#include +#include +#define winpr_sem_t sem_t +#endif + +BOOL CloseHandle(HANDLE hObject) +{ +#if defined __APPLE__ + semaphore_destroy(mach_task_self(), *((winpr_sem_t*) hObject)); +#else + sem_destroy((winpr_sem_t*) hObject); +#endif + + free(hObject); + + return 1; +} + +BOOL DuplicateHandle(HANDLE hSourceProcessHandle, HANDLE hSourceHandle, HANDLE hTargetProcessHandle, + LPHANDLE lpTargetHandle, DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwOptions) +{ + return 1; +} + +BOOL GetHandleInformation(HANDLE hObject, LPDWORD lpdwFlags) +{ + return 1; +} + +BOOL SetHandleInformation(HANDLE hObject, DWORD dwMask, DWORD dwFlags) +{ + return 1; +} + +#endif diff --git a/winpr/heap/CMakeLists.txt b/winpr/heap/CMakeLists.txt new file mode 100644 index 000000000..4f708b521 --- /dev/null +++ b/winpr/heap/CMakeLists.txt @@ -0,0 +1,28 @@ +# WinPR: Windows Portable Runtime +# libwinpr-heap 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_HEAP_SRCS + heap.c) + +add_library(winpr-heap ${WINPR_HEAP_SRCS}) + +set_target_properties(winpr-heap PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") + +install(TARGETS winpr-heap DESTINATION ${CMAKE_INSTALL_LIBDIR}) + diff --git a/winpr/heap/heap.c b/winpr/heap/heap.c new file mode 100644 index 000000000..cb859e056 --- /dev/null +++ b/winpr/heap/heap.c @@ -0,0 +1,59 @@ +/** + * WinPR: Windows Portable Runtime + * Memory Allocation + * + * 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 + +/* Memory Allocation: http://msdn.microsoft.com/en-us/library/hk1k7x6x.aspx */ +/* Memory Management Functions: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366781/ */ + +#ifndef _WIN32 + +HANDLE GetProcessHeap(void) +{ + return NULL; +} + +LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes) +{ + LPVOID lpMem = NULL; + + if (dwFlags & HEAP_ZERO_MEMORY) + lpMem = calloc(1, dwBytes); + else + lpMem = malloc(dwBytes); + + return lpMem; +} + +LPVOID HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes) +{ + LPVOID lpNewMem; + + lpNewMem = realloc(lpMem, dwBytes); + + return lpNewMem; +} + +BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) +{ + free(lpMem); + return 1; +} + +#endif diff --git a/winpr/registry/CMakeLists.txt b/winpr/registry/CMakeLists.txt index 4cbbcb04a..cb4b0be76 100644 --- a/winpr/registry/CMakeLists.txt +++ b/winpr/registry/CMakeLists.txt @@ -17,32 +17,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -if(NOT WIN32) - set(WITH_REGISTRY_XML true) -endif() - set(WINPR_REGISTRY_SRCS + registry_reg.c + registry_reg.h registry.c) -set(WINPR_REGISTRY_XML_SRCS - registry_xml.c - registry_xml.h) - -if(WITH_REGISTRY_XML) - set(WINPR_REGISTRY_SRCS ${WINPR_REGISTRY_SRCS} ${WINPR_REGISTRY_XML_SRCS}) -endif() - add_library(winpr-registry ${WINPR_REGISTRY_SRCS}) set_target_properties(winpr-registry PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") -if(WITH_REGISTRY_XML) - find_required_package(LibXml2) - add_definitions("${LIBXML2_DEFINITIONS}") - include_directories(SYSTEM ${LIBXML2_INCLUDE_DIR}) - target_link_libraries(winpr-registry ${LIBXML2_LIBRARIES}) -endif() - target_link_libraries(winpr-registry winpr-utils) install(TARGETS winpr-registry DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/winpr/registry/registry.c b/winpr/registry/registry.c index 67041c12c..fa865b0fd 100644 --- a/winpr/registry/registry.c +++ b/winpr/registry/registry.c @@ -27,23 +27,29 @@ #ifndef _WIN32 -#include "registry_xml.h" +#include +#include +#include + +#include "registry_reg.h" + +static Reg* instance = NULL; + +static Reg* RegGetInstance() +{ + if (!instance) + { + instance = reg_open(1); + } + + return instance; +} LONG RegCloseKey(HKEY hKey) { return 0; } -LONG RegConnectRegistryW(LPCWSTR lpMachineName, HKEY hKey, PHKEY phkResult) -{ - return 0; -} - -LONG RegConnectRegistryA(LPCSTR lpMachineName, HKEY hKey, PHKEY phkResult) -{ - return 0; -} - LONG RegCopyTreeW(HKEY hKeySrc, LPCWSTR lpSubKey, HKEY hKeyDest) { return 0; @@ -66,30 +72,6 @@ LONG RegCreateKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, return 0; } -LONG RegCreateKeyTransactedW(HKEY hKey, LPCWSTR lpSubKey, DWORD Reserved, LPWSTR lpClass, - DWORD dwOptions, REGSAM samDesired, const LPSECURITY_ATTRIBUTES lpSecurityAttributes, - PHKEY phkResult, LPDWORD lpdwDisposition, HANDLE hTransaction, PVOID pExtendedParemeter) -{ - return 0; -} - -LONG RegCreateKeyTransactedA(HKEY hKey, LPCSTR lpSubKey, DWORD Reserved, LPSTR lpClass, - DWORD dwOptions, REGSAM samDesired, const LPSECURITY_ATTRIBUTES lpSecurityAttributes, - PHKEY phkResult, LPDWORD lpdwDisposition, HANDLE hTransaction, PVOID pExtendedParemeter) -{ - return 0; -} - -LONG RegDeleteKeyW(HKEY hKey, LPCWSTR lpSubKey) -{ - return 0; -} - -LONG RegDeleteKeyA(HKEY hKey, LPCSTR lpSubKey) -{ - return 0; -} - LONG RegDeleteKeyExW(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, DWORD Reserved) { return 0; @@ -100,28 +82,6 @@ LONG RegDeleteKeyExA(HKEY hKey, LPCSTR lpSubKey, REGSAM samDesired, DWORD Reserv return 0; } -LONG RegDeleteKeyTransactedW(HKEY hKey, LPCWSTR lpSubKey, REGSAM samDesired, - DWORD Reserved, HANDLE hTransaction, PVOID pExtendedParameter) -{ - return 0; -} - -LONG RegDeleteKeyTransactedA(HKEY hKey, LPCSTR lpSubKey, REGSAM samDesired, - DWORD Reserved, HANDLE hTransaction, PVOID pExtendedParameter) -{ - return 0; -} - -LONG RegDeleteKeyValueW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName) -{ - return 0; -} - -LONG RegDeleteKeyValueA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpValueName) -{ - return 0; -} - LONG RegDeleteTreeW(HKEY hKey, LPCWSTR lpSubKey) { return 0; @@ -142,26 +102,11 @@ LONG RegDeleteValueA(HKEY hKey, LPCSTR lpValueName) return 0; } -LONG RegDisablePredefinedCache(void) -{ - return 0; -} - LONG RegDisablePredefinedCacheEx(void) { return 0; } -LONG RegDisableReflectionKey(HKEY hBase) -{ - return 0; -} - -LONG RegEnableReflectionKey(HKEY hBase) -{ - return 0; -} - LONG RegEnumKeyExW(HKEY hKey, DWORD dwIndex, LPWSTR lpName, LPDWORD lpcName, LPDWORD lpReserved, LPWSTR lpClass, LPDWORD lpcClass, PFILETIME lpftLastWriteTime) { @@ -209,6 +154,18 @@ LONG RegGetValueA(HKEY hkey, LPCSTR lpSubKey, LPCSTR lpValue, return 0; } +LONG RegLoadAppKeyW(LPCWSTR lpFile, PHKEY phkResult, + REGSAM samDesired, DWORD dwOptions, DWORD Reserved) +{ + return 0; +} + +LONG RegLoadAppKeyA(LPCSTR lpFile, PHKEY phkResult, + REGSAM samDesired, DWORD dwOptions, DWORD Reserved) +{ + return 0; +} + LONG RegLoadKeyW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpFile) { return 0; @@ -248,18 +205,25 @@ LONG RegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesir LONG RegOpenKeyExA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult) { - return 0; -} + Reg* reg; + RegKey* pKey; -LONG RegOpenKeyTransactedW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, - REGSAM samDesired, PHKEY phkResult, HANDLE hTransaction, PVOID pExtendedParameter) -{ - return 0; -} + reg = RegGetInstance(); + pKey = reg->root_key->subkeys; + + while (pKey != NULL) + { + if (strcmp(pKey->subname, lpSubKey) == 0) + { + *phkResult = pKey; + return ERROR_SUCCESS; + } + + pKey = pKey->next; + } + + *phkResult = NULL; -LONG RegOpenKeyTransactedA(HKEY hKey, LPCSTR lpSubKey, DWORD ulOptions, - REGSAM samDesired, PHKEY phkResult, HANDLE hTransaction, PVOID pExtendedParameter) -{ return 0; } @@ -268,11 +232,6 @@ LONG RegOpenUserClassesRoot(HANDLE hToken, DWORD dwOptions, REGSAM samDesired, P return 0; } -LONG RegOverridePredefKey(HKEY hKey, HKEY hNewHKey) -{ - return 0; -} - LONG RegQueryInfoKeyW(HKEY hKey, LPWSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen, LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, @@ -289,16 +248,6 @@ LONG RegQueryInfoKeyA(HKEY hKey, LPSTR lpClass, LPDWORD lpcClass, LPDWORD lpRese return 0; } -LONG RegQueryMultipleValues(HKEY hKey, PVALENT val_list, DWORD num_vals, LPTSTR lpValueBuf, LPDWORD ldwTotsize) -{ - return 0; -} - -LONG RegQueryReflectionKey(HKEY hBase, BOOL* bIsReflectionDisabled) -{ - return 0; -} - LONG RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) { @@ -308,16 +257,52 @@ LONG RegQueryValueExW(HKEY hKey, LPCWSTR lpValueName, LONG RegQueryValueExA(HKEY hKey, LPCSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData) { - return 0; -} + Reg* reg; + RegKey* key; + RegVal* pValue; -LONG RegReplaceKeyW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpNewFile, LPCWSTR lpOldFile) -{ - return 0; -} + key = (RegKey*) hKey; + reg = RegGetInstance(); + + pValue = key->values; + + while (pValue != NULL) + { + if (strcmp(pValue->name, lpValueName) == 0) + { + if (pValue->type == REG_DWORD) + { + DWORD* pData = (DWORD*) lpData; + + if (pData != NULL) + { + *pData = pValue->data.dword; + } + + *lpcbData = sizeof(DWORD); + + return ERROR_SUCCESS; + } + else if (pValue->type == REG_SZ) + { + int length; + char* pData = (char*) lpData; + + length = strlen(pValue->data.string); + + if (pData != NULL) + { + memcpy(pData, pValue->data.string, length); + pData[length] = '\0'; + } + + *lpcbData = length; + } + } + + pValue = pValue->next; + } -LONG RegReplaceKeyA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpNewFile, LPCSTR lpOldFile) -{ return 0; } @@ -331,16 +316,6 @@ LONG RegRestoreKeyA(HKEY hKey, LPCSTR lpFile, DWORD dwFlags) return 0; } -LONG RegSaveKeyW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes) -{ - return 0; -} - -LONG RegSaveKeyA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes) -{ - return 0; -} - LONG RegSaveKeyExW(HKEY hKey, LPCWSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD Flags) { return 0; @@ -351,16 +326,6 @@ LONG RegSaveKeyExA(HKEY hKey, LPCSTR lpFile, LPSECURITY_ATTRIBUTES lpSecurityAtt return 0; } -LONG RegSetKeyValueW(HKEY hKey, LPCWSTR lpSubKey, LPCWSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData) -{ - return 0; -} - -LONG RegSetKeyValueA(HKEY hKey, LPCSTR lpSubKey, LPCSTR lpValueName, DWORD dwType, LPCVOID lpData, DWORD cbData) -{ - return 0; -} - LONG RegSetKeySecurity(HKEY hKey, SECURITY_INFORMATION SecurityInformation, PSECURITY_DESCRIPTOR pSecurityDescriptor) { return 0; diff --git a/winpr/registry/registry_reg.c b/winpr/registry/registry_reg.c new file mode 100644 index 000000000..c391555b2 --- /dev/null +++ b/winpr/registry/registry_reg.c @@ -0,0 +1,437 @@ +/** + * WinPR: Windows Portable Runtime + * Windows Registry (.reg file format) + * + * 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 "registry_reg.h" + +#define WINPR_HKLM_HIVE "/etc/winpr/HKLM.reg" + +struct reg_data_type +{ + char* tag; + int length; + DWORD type; +}; + +struct reg_data_type REG_DATA_TYPE_TABLE[] = +{ + { "\"", 1, REG_SZ }, + { "dword:", 6, REG_DWORD }, + { "str:\"", 5, REG_SZ }, + { "str(2):\"", 8, REG_EXPAND_SZ }, + { "str(7):\"", 8, REG_MULTI_SZ }, + { "hex:", 4, REG_BINARY }, + { "hex(2):\"", 8, REG_EXPAND_SZ }, + { "hex(7):\"", 8, REG_MULTI_SZ }, + { "hex(b):\"", 8, REG_QWORD }, + { NULL, 0, 0 } +}; + +char* REG_DATA_TYPE_STRINGS[] = +{ + "REG_NONE", + "REG_SZ", + "REG_EXPAND_SZ", + "REG_BINARY", + "REG_DWORD", + "REG_DWORD_BIG_ENDIAN", + "REG_LINK", + "REG_MULTI_SZ", + "REG_RESOURCE_LIST", + "REG_FULL_RESOURCE_DESCRIPTOR", + "REG_RESOURCE_REQUIREMENTS_LIST", + "REG_QWORD" +}; + +void reg_load_start(Reg* reg) +{ + long int file_size; + + fseek(reg->fp, 0, SEEK_END); + file_size = ftell(reg->fp); + fseek(reg->fp, 0, SEEK_SET); + + if (file_size < 1) + return; + + reg->buffer = (char*) malloc(file_size + 2); + + if (fread(reg->buffer, file_size, 1, reg->fp) != 1) + { + free(reg->buffer); + return; + } + + reg->buffer[file_size] = '\n'; + reg->buffer[file_size + 1] = '\0'; + + reg->line = NULL; + reg->next_line = strtok(reg->buffer, "\n"); +} + +void reg_load_finish(Reg* reg) +{ + free(reg->buffer); + reg->buffer = NULL; + reg->line = NULL; +} + +RegVal* reg_load_value(Reg* reg, RegKey* key) +{ + int index; + char* p[5]; + int length; + char* name; + char* type; + char* data; + RegVal* value; + + p[0] = reg->line + 1; + p[1] = strstr(p[0], "\"="); + p[2] = p[1] + 2; + type = p[2]; + + if (p[2][0] == '"') + p[3] = p[2]; + else + p[3] = strchr(p[2], ':'); + + data = p[3] + 1; + + length = p[1] - p[0]; + name = (char*) malloc(length + 1); + memcpy(name, p[0], length); + name[length] = '\0'; + + value = (RegVal*) malloc(sizeof(RegVal)); + + value->name = name; + value->type = REG_NONE; + value->next = value->prev = NULL; + + for (index = 0; REG_DATA_TYPE_TABLE[index].length > 0; index++) + { + if (strncmp(type, REG_DATA_TYPE_TABLE[index].tag, REG_DATA_TYPE_TABLE[index].length) == 0) + { + value->type = REG_DATA_TYPE_TABLE[index].type; + break; + } + } + + if (value->type == REG_DWORD) + { + value->data.dword = strtoul(data, NULL, 0); + } + else if (value->type == REG_SZ) + { + p[4] = strchr(data, '"'); + p[4][0] = '\0'; + value->data.string = _strdup(data); + } + else + { + printf("unimplemented format: %s\n", REG_DATA_TYPE_STRINGS[value->type]); + } + + if (!key->values) + { + key->values = value; + } + else + { + RegVal* pValue = key->values; + + while (pValue->next != NULL) + { + pValue = pValue->next; + } + + pValue->next = value; + value->prev = pValue; + } + + return value; +} + +BOOL reg_load_has_next_line(Reg* reg) +{ + return (reg->next_line != NULL) ? 1 : 0; +} + +char* reg_load_get_next_line(Reg* reg) +{ + reg->line = reg->next_line; + reg->next_line = strtok(NULL, "\n"); + reg->line_length = strlen(reg->line); + + return reg->line; +} + +char* reg_load_peek_next_line(Reg* reg) +{ + return reg->next_line; +} + +void reg_insert_key(Reg* reg, RegKey* key, RegKey* subkey) +{ + char* name; + char* path; + int length; + + path = _strdup(subkey->name); + + name = strtok(path, "\\"); + + while (name != NULL) + { + if (strcmp(key->name, name) == 0) + { + length = strlen(name); + name += length + 1; + subkey->subname = _strdup(name); + } + + name = strtok(NULL, "\\"); + } + + free(path); +} + +RegKey* reg_load_key(Reg* reg, RegKey* key) +{ + char* p[2]; + int length; + char* line; + RegKey* subkey; + + p[0] = reg->line + 1; + p[1] = strrchr(p[0], ']'); + + subkey = (RegKey*) malloc(sizeof(RegKey)); + + subkey->values = NULL; + subkey->prev = subkey->next = NULL; + + length = p[1] - p[0]; + subkey->name = (char*) malloc(length + 1); + memcpy(subkey->name, p[0], length); + subkey->name[length] = '\0'; + + while (reg_load_has_next_line(reg)) + { + line = reg_load_peek_next_line(reg); + + if (line[0] == '[') + break; + + reg_load_get_next_line(reg); + + if (reg->line[0] == '"') + { + reg_load_value(reg, subkey); + } + } + + reg_insert_key(reg, key, subkey); + + if (!key->subkeys) + { + key->subkeys = subkey; + } + else + { + RegKey* pKey = key->subkeys; + + while (pKey->next != NULL) + { + pKey = pKey->next; + } + + pKey->next = subkey; + subkey->prev = pKey; + } + + return subkey; +} + +void reg_load(Reg* reg) +{ + reg_load_start(reg); + + while (reg_load_has_next_line(reg)) + { + reg_load_get_next_line(reg); + + if (reg->line[0] == '[') + { + reg_load_key(reg, reg->root_key); + } + } + + reg_load_finish(reg); +} + +void reg_unload_value(Reg* reg, RegVal* value) +{ + if (value->type == REG_DWORD) + { + + } + else if (value->type == REG_SZ) + { + free(value->data.string); + } + else + { + printf("unimplemented format: %s\n", REG_DATA_TYPE_STRINGS[value->type]); + } + + free(value); +} + +void reg_unload_key(Reg* reg, RegKey* key) +{ + RegVal* pValue; + RegVal* pValueNext; + + pValue = key->values; + + while (pValue != NULL) + { + pValueNext = pValue->next; + reg_unload_value(reg, pValue); + pValue = pValueNext; + } + + free(key->name); + free(key); +} + +void reg_unload(Reg* reg) +{ + RegKey* pKey; + RegKey* pKeyNext; + + pKey = reg->root_key->subkeys; + + while (pKey != NULL) + { + pKeyNext = pKey->next; + reg_unload_key(reg, pKey); + pKey = pKeyNext; + } + + free(reg->root_key); +} + +Reg* reg_open(BOOL read_only) +{ + Reg* reg; + + reg = (Reg*) malloc(sizeof(Reg)); + + if (reg) + { + reg->read_only = read_only; + reg->filename = WINPR_HKLM_HIVE; + + if (reg->read_only) + { + reg->fp = fopen(reg->filename, "r"); + } + else + { + reg->fp = fopen(reg->filename, "r+"); + + if (!reg->fp) + reg->fp = fopen(reg->filename, "w+"); + } + + reg->root_key = (RegKey*) malloc(sizeof(RegKey)); + + reg->root_key->values = NULL; + reg->root_key->subkeys = NULL; + reg->root_key->name = "HKEY_LOCAL_MACHINE"; + + reg_load(reg); + } + + return reg; +} + +void reg_close(Reg* reg) +{ + if (reg) + { + reg_unload(reg); + fclose(reg->fp); + free(reg); + } +} + +void reg_print_value(Reg* reg, RegVal* value) +{ + printf("\"%s\"=", value->name); + + if (value->type == REG_DWORD) + { + printf("dword:%08lX\n", value->data.dword); + } + else if (value->type == REG_SZ) + { + printf("%s\"\n", value->data.string); + } + else + { + printf("unimplemented format: %s\n", REG_DATA_TYPE_STRINGS[value->type]); + } +} + +void reg_print_key(Reg* reg, RegKey* key) +{ + RegVal* pValue; + + pValue = key->values; + + printf("[%s]\n", key->name); + + while (pValue != NULL) + { + reg_print_value(reg, pValue); + pValue = pValue->next; + } +} + +void reg_print(Reg* reg) +{ + RegKey* pKey; + + pKey = reg->root_key->subkeys; + + while (pKey != NULL) + { + reg_print_key(reg, pKey); + pKey = pKey->next; + } +} diff --git a/winpr/registry/registry_reg.h b/winpr/registry/registry_reg.h new file mode 100644 index 000000000..ac5192629 --- /dev/null +++ b/winpr/registry/registry_reg.h @@ -0,0 +1,64 @@ +/** + * WinPR: Windows Portable Runtime + * Windows Registry (.reg file format) + * + * 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 + +typedef struct _reg Reg; +typedef struct _reg_key RegKey; +typedef struct _reg_val RegVal; + +struct _reg +{ + FILE* fp; + char* line; + char* next_line; + int line_length; + char* buffer; + char* filename; + BOOL read_only; + RegKey* root_key; +}; + +struct _reg_val +{ + char* name; + DWORD type; + RegVal* prev; + RegVal* next; + + union reg_data + { + DWORD dword; + char* string; + } data; +}; + +struct _reg_key +{ + char* name; + DWORD type; + RegKey* prev; + RegKey* next; + + char* subname; + RegVal* values; + RegKey* subkeys; +}; + +Reg* reg_open(BOOL read_only); diff --git a/winpr/registry/registry_xml.c b/winpr/registry/registry_xml.c deleted file mode 100644 index 3cc85bc57..000000000 --- a/winpr/registry/registry_xml.c +++ /dev/null @@ -1,127 +0,0 @@ -/** - * WinPR: Windows Portable Runtime - * Windows Registry - * - * 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 "registry_xml.h" - -#include -#include -#include - -#include - -#ifndef _WIN32 -#define PATH_SEPARATOR_STR "/" -#define PATH_SEPARATOR_CHR '/' -#define HOME_ENV_VARIABLE "HOME" -#else -#define PATH_SEPARATOR_STR "\\" -#define PATH_SEPARATOR_CHR '\\' -#define HOME_ENV_VARIABLE "HOME" -#endif - -char* construct_path(char* base_path, char* relative_path) -{ - char* path; - int length; - int base_path_length; - int relative_path_length; - - base_path_length = strlen(base_path); - relative_path_length = strlen(relative_path); - length = base_path_length + relative_path_length + 1; - - path = malloc(length + 1); - sprintf(path, "%s" PATH_SEPARATOR_STR "%s", base_path, relative_path); - - return path; -} - -char* find_registry_path() -{ - char* path; - char* home_path; - - home_path = getenv("HOME"); - path = construct_path(home_path, "registry.xml"); - - return path; -} - -RegistryXml* registry_xml_new() -{ - char* filename; - RegistryXml* registry; - - registry = (RegistryXml*) malloc(sizeof(RegistryXml)); - ZeroMemory(registry, sizeof(RegistryXml)); - - filename = find_registry_path(); - registry->doc = xmlParseFile(filename); - - if (registry->doc == NULL) - { - fprintf(stderr, "xmlParseFile error\n"); - return NULL; - } - - registry->node = xmlDocGetRootElement(registry->doc); - - if (registry->node == NULL) - { - fprintf(stderr, "empty document\n"); - xmlFreeDoc(registry->doc); - return NULL; - } - - if (xmlStrcmp(registry->node->name, (const xmlChar*) "registry")) - { - fprintf(stderr, "document of the wrong type, root node != registry"); - xmlFreeDoc(registry->doc); - return NULL; - } - - registry->node = registry->node->xmlChildrenNode; - - while (registry->node != NULL) - { - if ((!xmlStrcmp(registry->node->name, (const xmlChar*) "key"))) - { - //read_registry_key(doc, node, 0); - } - - registry->node = registry->node->next; - } - - return NULL; -} - -static RegistryXml* instance = NULL; - -RegistryXml* registry_xml_open() -{ - if (instance == NULL) - instance = registry_xml_new(); - - return instance; -} - -void registry_xml_close(RegistryXml* registry) -{ - xmlFreeDoc(registry->doc); -} diff --git a/winpr/sspi/CMakeLists.txt b/winpr/sspi/CMakeLists.txt index 8ac379c97..283822edc 100644 --- a/winpr/sspi/CMakeLists.txt +++ b/winpr/sspi/CMakeLists.txt @@ -50,8 +50,6 @@ if(NOT WITH_NATIVE_SSPI) ${WINPR_SSPI_NEGOTIATE_SRCS} ${WINPR_SSPI_SCHANNEL_SRCS} ${WINPR_SSPI_SRCS}) -else() - add_definitions(-DNATIVE_SSPI) endif() add_library(winpr-sspi ${WINPR_SSPI_SRCS}) diff --git a/winpr/sspi/CredSSP/credssp.c b/winpr/sspi/CredSSP/credssp.c index 8b60670e5..e92d53841 100644 --- a/winpr/sspi/CredSSP/credssp.c +++ b/winpr/sspi/CredSSP/credssp.c @@ -251,12 +251,22 @@ const SecPkgInfoA CREDSSP_SecPkgInfoA = "Microsoft CredSSP Security Provider" /* Comment */ }; +WCHAR CREDSSP_SecPkgInfoW_Name[] = { 'C','R','E','D','S','S','P','\0' }; + +WCHAR CREDSSP_SecPkgInfoW_Comment[] = +{ + 'M','i','c','r','o','s','o','f','t',' ', + 'C','r','e','d','S','S','P',' ', + 'S','e','c','u','r','i','t','y',' ', + 'P','r','o','v','i','d','e','r','\0' +}; + const SecPkgInfoW CREDSSP_SecPkgInfoW = { 0x000110733, /* fCapabilities */ 1, /* wVersion */ 0xFFFF, /* wRPCID */ 0x000090A8, /* cbMaxToken */ - L"CREDSSP", /* Name */ - L"Microsoft CredSSP Security Provider" /* Comment */ + CREDSSP_SecPkgInfoW_Name, /* Name */ + CREDSSP_SecPkgInfoW_Comment /* Comment */ }; diff --git a/winpr/sspi/NTLM/ntlm.c b/winpr/sspi/NTLM/ntlm.c index 4680c650e..ba3480d31 100644 --- a/winpr/sspi/NTLM/ntlm.c +++ b/winpr/sspi/NTLM/ntlm.c @@ -62,7 +62,10 @@ NTLM_CONTEXT* ntlm_ContextNew() { context->ntlm_v2 = 0; context->NegotiateFlags = 0; + context->SendVersionInfo = 0; + context->LmCompatibilityLevel = 3; context->state = NTLM_STATE_INITIAL; + context->SuppressExtendedProtection = 1; context->av_pairs = (AV_PAIRS*) malloc(sizeof(AV_PAIRS)); ZeroMemory(context->av_pairs, sizeof(AV_PAIRS)); } @@ -183,14 +186,6 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesW(PCredHandle phCredent { if (ulAttribute == SECPKG_CRED_ATTR_NAMES) { - CREDENTIALS* credentials; - //SecPkgCredentials_Names* credential_names = (SecPkgCredentials_Names*) pBuffer; - - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); - - //if (credentials->identity.Flags == SEC_WINNT_AUTH_IDENTITY_ANSI) - // credential_names->sUserName = xstrdup((char*) credentials->identity.User); - return SEC_E_OK; } @@ -201,14 +196,6 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryCredentialsAttributesA(PCredHandle phCredent { if (ulAttribute == SECPKG_CRED_ATTR_NAMES) { - CREDENTIALS* credentials; - //SecPkgCredentials_Names* credential_names = (SecPkgCredentials_Names*) pBuffer; - - credentials = (CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); - - //if (credentials->identity.Flags == SEC_WINNT_AUTH_IDENTITY_ANSI) - // credential_names->sUserName = xstrdup((char*) credentials->identity.User); - return SEC_E_OK; } @@ -228,7 +215,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle phCredential, P PSecBuffer input_buffer; PSecBuffer output_buffer; - context = sspi_SecureHandleGetLowerPointer(phContext); + context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) { @@ -343,7 +330,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextA(PCredHandle phCredenti PSecBuffer input_buffer; PSecBuffer output_buffer; - context = sspi_SecureHandleGetLowerPointer(phContext); + context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) { @@ -434,7 +421,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle phContext) { NTLM_CONTEXT* context; - context = sspi_SecureHandleGetLowerPointer(phContext); + context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) return SEC_E_INVALID_HANDLE; @@ -493,7 +480,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBuffer data_buffer = NULL; PSecBuffer signature_buffer = NULL; - context = sspi_SecureHandleGetLowerPointer(phContext); + context = (NTLM_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); for (index = 0; index < (int) pMessage->cBuffers; index++) { @@ -732,12 +719,21 @@ const SecPkgInfoA NTLM_SecPkgInfoA = "NTLM Security Package" /* Comment */ }; +WCHAR NTLM_SecPkgInfoW_Name[] = { 'N','T','L','M','\0' }; + +WCHAR NTLM_SecPkgInfoW_Comment[] = +{ + 'N','T','L','M',' ', + 'S','e','c','u','r','i','t','y',' ', + 'P','a','c','k','a','g','e','\0' +}; + const SecPkgInfoW NTLM_SecPkgInfoW = { 0x00082B37, /* fCapabilities */ 1, /* wVersion */ 0x000A, /* wRPCID */ 0x00000B48, /* cbMaxToken */ - L"NTLM", /* Name */ - L"NTLM Security Package" /* Comment */ + NTLM_SecPkgInfoW_Name, /* Name */ + NTLM_SecPkgInfoW_Comment /* Comment */ }; diff --git a/winpr/sspi/NTLM/ntlm.h b/winpr/sspi/NTLM/ntlm.h index 4081a4480..3288319f2 100644 --- a/winpr/sspi/NTLM/ntlm.h +++ b/winpr/sspi/NTLM/ntlm.h @@ -89,6 +89,7 @@ struct _NTLM_CONTEXT NTLM_STATE state; int SendSeqNum; int RecvSeqNum; + int SendVersionInfo; BOOL confidentiality; RC4_KEY SendRc4Seal; RC4_KEY RecvRc4Seal; @@ -100,6 +101,8 @@ struct _NTLM_CONTEXT UINT32 NegotiateFlags; UINT16* Workstation; UINT32 WorkstationLength; + int LmCompatibilityLevel; + int SuppressExtendedProtection; SEC_WINNT_AUTH_IDENTITY identity; SecBuffer NegotiateMessage; SecBuffer ChallengeMessage; diff --git a/winpr/sspi/NTLM/ntlm_compute.c b/winpr/sspi/NTLM/ntlm_compute.c index dc4f27de2..ae17013a9 100644 --- a/winpr/sspi/NTLM/ntlm_compute.c +++ b/winpr/sspi/NTLM/ntlm_compute.c @@ -21,6 +21,8 @@ #include "../sspi.h" #include +#include +#include #include #include "ntlm_compute.h" @@ -159,155 +161,39 @@ void ntlm_generate_timestamp(NTLM_CONTEXT* context) } } -void ntlm_compute_ntlm_hash(UINT16* password, UINT32 length, char* hash) -{ - /* NTLMv1("password") = 8846F7EAEE8FB117AD06BDD830B7586C */ - - MD4_CTX md4_ctx; - - /* Password needs to be in unicode */ - - /* Apply the MD4 digest algorithm on the password in unicode, the result is the NTLM hash */ - - MD4_Init(&md4_ctx); - MD4_Update(&md4_ctx, password, length); - MD4_Final((void*) hash, &md4_ctx); -} - -static void ascii_hex_string_to_binary(char* str, unsigned char* hex) -{ - int i; - int length; - - CharUpperA(str); - - length = strlen(str); - - for (i = 0; i < length / 2; i++) - { - hex[i] = 0; - - if ((str[i * 2] >= '0') && (str[i * 2] <= '9')) - hex[i] |= (str[i * 2] - '0') << 4; - - if ((str[i * 2] >= 'A') && (str[i * 2] <= 'F')) - hex[i] |= (str[i * 2] - 'A' + 10) << 4; - - if ((str[i * 2 + 1] >= '0') && (str[i * 2 + 1] <= '9')) - hex[i] |= (str[i * 2 + 1] - '0'); - - if ((str[i * 2 + 1] >= 'A') && (str[i * 2 + 1] <= 'F')) - hex[i] |= (str[i * 2 + 1] - 'A' + 10); - } -} - -/* - * username // password - * username:661e58eb6743798326f388fc5edb0b3a - */ - void ntlm_fetch_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash) { - FILE* fp; - char* data; - char* line; - int length; - char* db_user; - char* db_hash; - UINT16* User; - UINT32 UserLength; - long int file_size; - BYTE db_hash_bin[16]; + WINPR_SAM* sam; + WINPR_SAM_ENTRY* entry; - /* Fetch NTLMv2 hash from database */ + sam = SamOpen(1); - fp = fopen("/etc/winpr/SAM.txt", "r"); + entry = SamLookupUserW(sam, + (LPWSTR) context->identity.User, context->identity.UserLength * 2, + (LPWSTR) context->identity.Domain, context->identity.DomainLength * 2); - fseek(fp, 0, SEEK_END); - file_size = ftell(fp); - fseek(fp, 0, SEEK_SET); - - if (file_size < 1) - return; - - data = (char*) malloc(file_size + 2); - - if (fread(data, file_size, 1, fp) != 1) + if (entry != NULL) { - free(data); - return; + CopyMemory(hash, entry->NtHash, 16); } - data[file_size] = '\n'; - data[file_size + 1] = '\0'; - line = strtok(data, "\n"); + SamFreeEntry(sam, entry); - while (line != NULL) - { - length = strlen(line); - - if (length > 0) - { - length = strcspn(line, ":"); - line[length] = '\0'; - - db_user = line; - db_hash = &line[length + 1]; - - UserLength = strlen(db_user) * 2; - User = (UINT16*) malloc(UserLength); - MultiByteToWideChar(CP_ACP, 0, db_user, strlen(db_user), - (LPWSTR) User, UserLength / 2); - - if (UserLength == context->identity.UserLength) - { - if (memcmp(User, context->identity.User, UserLength) == 0) - { - ascii_hex_string_to_binary(db_hash, db_hash_bin); - CopyMemory(hash, db_hash_bin, 16); - } - } - } - - line = strtok(NULL, "\n"); - } - - fclose(fp); - free(data); + SamClose(sam); } void ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, char* hash) { - char* p; - SecBuffer buffer; - char ntlm_hash[16]; - if (context->identity.PasswordLength > 0) { - /* First, compute the NTLMv1 hash of the password */ - ntlm_compute_ntlm_hash(context->identity.Password, context->identity.PasswordLength, ntlm_hash); - } - - sspi_SecBufferAlloc(&buffer, context->identity.UserLength + context->identity.DomainLength); - p = (char*) buffer.pvBuffer; - - /* Concatenate(Uppercase(username),domain)*/ - CopyMemory(p, context->identity.User, context->identity.UserLength); - CharUpperBuffW((LPWSTR) p, context->identity.UserLength / 2); - - CopyMemory(&p[context->identity.UserLength], context->identity.Domain, context->identity.DomainLength); - - if (context->identity.PasswordLength > 0) - { - /* Compute the HMAC-MD5 hash of the above value using the NTLMv1 hash as the key, the result is the NTLMv2 hash */ - HMAC(EVP_md5(), (void*) ntlm_hash, 16, buffer.pvBuffer, buffer.cbBuffer, (void*) hash, NULL); + NTOWFv2W((LPWSTR) context->identity.Password, context->identity.PasswordLength * 2, + (LPWSTR) context->identity.User, context->identity.UserLength * 2, + (LPWSTR) context->identity.Domain, context->identity.DomainLength * 2, (BYTE*) hash); } else { ntlm_fetch_ntlm_v2_hash(context, hash); } - - sspi_SecBufferFree(&buffer); } void ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) diff --git a/winpr/sspi/NTLM/ntlm_message.c b/winpr/sspi/NTLM/ntlm_message.c index ebd28fd9c..8a7451ee2 100644 --- a/winpr/sspi/NTLM/ntlm_message.c +++ b/winpr/sspi/NTLM/ntlm_message.c @@ -118,11 +118,11 @@ static const char* const NTLM_NEGOTIATE_STRINGS[] = void ntlm_output_version(PStream s) { - /* The following version information was observed with Windows 7 */ + /* Version Info for Windows 7 SP1 */ StreamWrite_UINT8(s, WINDOWS_MAJOR_VERSION_6); /* ProductMajorVersion (1 byte) */ StreamWrite_UINT8(s, WINDOWS_MINOR_VERSION_1); /* ProductMinorVersion (1 byte) */ - StreamWrite_UINT16(s, 7600); /* ProductBuild (2 bytes) */ + StreamWrite_UINT16(s, 7601); /* ProductBuild (2 bytes) */ StreamZero(s, 3); /* Reserved (3 bytes) */ StreamWrite_UINT8(s, NTLMSSP_REVISION_W2K3); /* NTLMRevisionCurrent (1 byte) */ } @@ -263,6 +263,9 @@ SECURITY_STATUS ntlm_write_NegotiateMessage(NTLM_CONTEXT* context, PSecBuffer bu if (context->confidentiality) NegotiateFlags |= NTLMSSP_NEGOTIATE_SEAL; + if (context->SendVersionInfo) + NegotiateFlags |= NTLMSSP_NEGOTIATE_VERSION; + context->NegotiateFlags = NegotiateFlags; StreamWrite_UINT32(s, NegotiateFlags); /* NegotiateFlags (4 bytes) */ @@ -431,10 +434,9 @@ SECURITY_STATUS ntlm_read_ChallengeMessage(NTLM_CONTEXT* context, PSecBuffer buf ntlm_generate_timestamp(context); /* LmChallengeResponse */ - ntlm_compute_lm_v2_response(context); - if (context->ntlm_v2) - memset(context->LmChallengeResponse.pvBuffer, 0, context->LmChallengeResponse.cbBuffer); + if (context->LmCompatibilityLevel < 2) + ntlm_compute_lm_v2_response(context); /* NtChallengeResponse */ ntlm_compute_ntlm_v2_response(context); @@ -820,11 +822,24 @@ SECURITY_STATUS ntlm_read_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer #endif } - /* LmChallengeResponse */ - ntlm_compute_lm_v2_response(context); + if (UserNameLen > 0) + { + context->identity.User = (UINT16*) malloc(UserNameLen); + CopyMemory(context->identity.User, UserNameBuffer, UserNameLen); + context->identity.UserLength = UserNameLen; + } - if (context->ntlm_v2) - memset(context->LmChallengeResponse.pvBuffer, 0, context->LmChallengeResponse.cbBuffer); + if (DomainNameLen > 0) + { + context->identity.Domain = (UINT16*) malloc(DomainNameLen); + CopyMemory(context->identity.Domain, DomainNameBuffer, DomainNameLen); + context->identity.DomainLength = DomainNameLen; + } + + /* LmChallengeResponse */ + + if (context->LmCompatibilityLevel < 2) + ntlm_compute_lm_v2_response(context); /* NtChallengeResponse */ ntlm_compute_ntlm_v2_response(context); @@ -944,13 +959,13 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer if (context->ntlm_v2 < 1) WorkstationLen = 0; - DomainNameLen = (UINT16) context->identity.DomainLength; + DomainNameLen = (UINT16) context->identity.DomainLength * 2; DomainNameBuffer = (BYTE*) context->identity.Domain; - UserNameLen = (UINT16) context->identity.UserLength; + UserNameLen = (UINT16) context->identity.UserLength * 2; UserNameBuffer = (BYTE*) context->identity.User; - LmChallengeResponseLen = (UINT16) context->LmChallengeResponse.cbBuffer; + LmChallengeResponseLen = (UINT16) 24; NtChallengeResponseLen = (UINT16) context->NtChallengeResponse.cbBuffer; EncryptedRandomSessionKeyLen = 16; @@ -1095,13 +1110,21 @@ SECURITY_STATUS ntlm_write_AuthenticateMessage(NTLM_CONTEXT* context, PSecBuffer } /* LmChallengeResponse */ - StreamWrite(s, context->LmChallengeResponse.pvBuffer, LmChallengeResponseLen); + + if (context->LmCompatibilityLevel < 2) + { + StreamWrite(s, context->LmChallengeResponse.pvBuffer, LmChallengeResponseLen); #ifdef WITH_DEBUG_NTLM - printf("LmChallengeResponse (length = %d, offset = %d)\n", LmChallengeResponseLen, LmChallengeResponseBufferOffset); - winpr_HexDump(context->LmChallengeResponse.pvBuffer, LmChallengeResponseLen); - printf("\n"); + printf("LmChallengeResponse (length = %d, offset = %d)\n", LmChallengeResponseLen, LmChallengeResponseBufferOffset); + winpr_HexDump(context->LmChallengeResponse.pvBuffer, LmChallengeResponseLen); + printf("\n"); #endif + } + else + { + StreamZero(s, LmChallengeResponseLen); + } /* NtChallengeResponse */ StreamWrite(s, context->NtChallengeResponse.pvBuffer, NtChallengeResponseLen); diff --git a/winpr/sspi/Negotiate/negotiate.c b/winpr/sspi/Negotiate/negotiate.c index eb9aeff43..c8bc191dd 100644 --- a/winpr/sspi/Negotiate/negotiate.c +++ b/winpr/sspi/Negotiate/negotiate.c @@ -26,26 +26,6 @@ char* NEGOTIATE_PACKAGE_NAME = "Negotiate"; -const SecPkgInfoA NEGOTIATE_SecPkgInfoA = -{ - 0x00083BB3, /* fCapabilities */ - 1, /* wVersion */ - 0x0009, /* wRPCID */ - 0x00002FE0, /* cbMaxToken */ - "Negotiate", /* Name */ - "Microsoft Package Negotiator" /* Comment */ -}; - -const SecPkgInfoW NEGOTIATE_SecPkgInfoW = -{ - 0x00083BB3, /* fCapabilities */ - 1, /* wVersion */ - 0x0009, /* wRPCID */ - 0x00002FE0, /* cbMaxToken */ - L"Negotiate", /* Name */ - L"Microsoft Package Negotiator" /* Comment */ -}; - SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, @@ -277,3 +257,32 @@ const SecurityFunctionTableW NEGOTIATE_SecurityFunctionTableW = negotiate_DecryptMessage, /* DecryptMessage */ NULL, /* SetContextAttributes */ }; + +const SecPkgInfoA NEGOTIATE_SecPkgInfoA = +{ + 0x00083BB3, /* fCapabilities */ + 1, /* wVersion */ + 0x0009, /* wRPCID */ + 0x00002FE0, /* cbMaxToken */ + "Negotiate", /* Name */ + "Microsoft Package Negotiator" /* Comment */ +}; + +WCHAR NEGOTIATE_SecPkgInfoW_Name[] = { 'N','e','g','o','t','i','a','t','e','\0' }; + +WCHAR NEGOTIATE_SecPkgInfoW_Comment[] = +{ + 'M','i','c','r','o','s','o','f','t',' ', + 'P','a','c','k','a','g','e',' ', + 'N','e','g','o','t','i','a','t','o','r','\0' +}; + +const SecPkgInfoW NEGOTIATE_SecPkgInfoW = +{ + 0x00083BB3, /* fCapabilities */ + 1, /* wVersion */ + 0x0009, /* wRPCID */ + 0x00002FE0, /* cbMaxToken */ + NEGOTIATE_SecPkgInfoW_Name, /* Name */ + NEGOTIATE_SecPkgInfoW_Comment /* Comment */ +}; diff --git a/winpr/sspi/Schannel/schannel.c b/winpr/sspi/Schannel/schannel.c index a4dc3e357..2f94c41c2 100644 --- a/winpr/sspi/Schannel/schannel.c +++ b/winpr/sspi/Schannel/schannel.c @@ -251,13 +251,21 @@ const SecPkgInfoA SCHANNEL_SecPkgInfoA = "Schannel Security Package" /* Comment */ }; +WCHAR SCHANNEL_SecPkgInfoW_Name[] = { 'S','c','h','a','n','n','e','l','\0' }; + +WCHAR SCHANNEL_SecPkgInfoW_Comment[] = +{ + 'S','c','h','a','n','n','e','l',' ', + 'S','e','c','u','r','i','t','y',' ', + 'P','a','c','k','a','g','e','\0' +}; + const SecPkgInfoW SCHANNEL_SecPkgInfoW = { 0x000107B3, /* fCapabilities */ 1, /* wVersion */ 0x000E, /* wRPCID */ 0x00006000, /* cbMaxToken */ - L"Schannel", /* Name */ - L"Schannel Security Package" /* Comment */ + SCHANNEL_SecPkgInfoW_Name, /* Name */ + SCHANNEL_SecPkgInfoW_Comment /* Comment */ }; - diff --git a/winpr/sspi/sspi.c b/winpr/sspi/sspi.c index 40a1bb9f8..6d30464d5 100644 --- a/winpr/sspi/sspi.c +++ b/winpr/sspi/sspi.c @@ -21,6 +21,7 @@ #include #include +#include #include "sspi.h" @@ -73,10 +74,13 @@ const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] = { "CREDSSP", &CREDSSP_SecurityFunctionTableA } }; +WCHAR NTLM_NAME_W[] = { 'N','T','L','M','\0' }; +WCHAR CREDSSP_NAME_W[] = { 'C','r','e','d','S','S','P','\0' }; + const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] = { - { L"NTLM", &NTLM_SecurityFunctionTableW }, - { L"CREDSSP", &CREDSSP_SecurityFunctionTableW } + { NTLM_NAME_W, &NTLM_SecurityFunctionTableW }, + { CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW } }; #endif @@ -122,8 +126,8 @@ void sspi_ContextBufferAllocTableGrow() size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries; - ContextBufferAllocTable.entries = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ContextBufferAllocTable.entries, size); - memset((void*) &ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2], 0, size / 2); + ContextBufferAllocTable.entries = realloc(ContextBufferAllocTable.entries, size); + ZeroMemory((void*) &ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2], size / 2); } void sspi_ContextBufferAllocTableFree() @@ -273,17 +277,23 @@ void sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, char* user, char* d { identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - identity->UserLength = strlen(user) * 2; - identity->User = (UINT16*) malloc(identity->UserLength); - MultiByteToWideChar(CP_ACP, 0, user, strlen(user), - (LPWSTR) identity->User, identity->UserLength / 2); + if (user) + { + identity->UserLength = MultiByteToWideChar(CP_UTF8, 0, user, strlen(user), NULL, 0); + identity->User = (UINT16*) malloc(identity->UserLength * sizeof(WCHAR)); + MultiByteToWideChar(CP_UTF8, 0, user, identity->UserLength, (LPWSTR) identity->User, identity->UserLength * sizeof(WCHAR)); + } + else + { + identity->User = (UINT16*) NULL; + identity->UserLength = 0; + } if (domain) { - identity->DomainLength = strlen(domain) * 2; - identity->Domain = (UINT16*) malloc(identity->DomainLength); - MultiByteToWideChar(CP_ACP, 0, domain, strlen(domain), - (LPWSTR) identity->Domain, identity->DomainLength / 2); + identity->DomainLength = MultiByteToWideChar(CP_UTF8, 0, domain, strlen(domain), NULL, 0); + identity->Domain = (UINT16*) malloc(identity->DomainLength * sizeof(WCHAR)); + MultiByteToWideChar(CP_UTF8, 0, domain, identity->DomainLength, (LPWSTR) identity->Domain, identity->DomainLength * sizeof(WCHAR)); } else { @@ -293,10 +303,9 @@ void sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, char* user, char* d if (password != NULL) { - identity->PasswordLength = strlen(password) * 2; - identity->Password = (UINT16*) malloc(identity->PasswordLength); - MultiByteToWideChar(CP_ACP, 0, password, strlen(password), - (LPWSTR) identity->Password, identity->PasswordLength / 2); + identity->PasswordLength = MultiByteToWideChar(CP_UTF8, 0, password, strlen(password), NULL, 0); + identity->Password = (UINT16*) malloc(identity->PasswordLength * sizeof(WCHAR)); + MultiByteToWideChar(CP_UTF8, 0, password, identity->PasswordLength, (LPWSTR) identity->Password, identity->PasswordLength * sizeof(WCHAR)); } else { @@ -320,16 +329,16 @@ void sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDE identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; identity->UserLength = srcIdentity->UserLength; - identity->User = malloc(identity->UserLength); - CopyMemory(identity->User, srcIdentity->User, identity->UserLength); + identity->User = (UINT16*) malloc(identity->UserLength * sizeof(WCHAR)); + CopyMemory(identity->User, srcIdentity->User, identity->UserLength * sizeof(WCHAR)); identity->DomainLength = srcIdentity->DomainLength; - identity->Domain = malloc(identity->DomainLength); - CopyMemory(identity->Domain, srcIdentity->Domain, identity->DomainLength); + identity->Domain = (UINT16*) malloc(identity->DomainLength * sizeof(WCHAR)); + CopyMemory(identity->Domain, srcIdentity->Domain, identity->DomainLength * sizeof(WCHAR)); identity->PasswordLength = srcIdentity->PasswordLength; - identity->Password = malloc(identity->PasswordLength); - CopyMemory(identity->Password, srcIdentity->Password, identity->PasswordLength); + identity->Password = (UINT16*) malloc(identity->PasswordLength * sizeof(WCHAR)); + CopyMemory(identity->Password, srcIdentity->Password, identity->PasswordLength * sizeof(WCHAR)); } void sspi_GlobalInit() @@ -342,7 +351,7 @@ void sspi_GlobalFinish() sspi_ContextBufferAllocTableFree(); } -#ifndef NATIVE_SSPI +#ifndef WITH_NATIVE_SSPI SecurityFunctionTableA* sspi_GetSecurityFunctionTableByNameA(const SEC_CHAR* Name) { @@ -371,7 +380,7 @@ SecurityFunctionTableW* sspi_GetSecurityFunctionTableByNameW(const SEC_WCHAR* Na for (index = 0; index < (int) cPackages; index++) { - if (wcscmp(Name, SecurityFunctionTableW_NAME_LIST[index].Name) == 0) + if (lstrcmpW(Name, SecurityFunctionTableW_NAME_LIST[index].Name) == 0) { return (SecurityFunctionTableW*) SecurityFunctionTableW_NAME_LIST[index].SecurityFunctionTable; } @@ -513,7 +522,7 @@ SECURITY_STATUS SEC_ENTRY QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName, P for (index = 0; index < (int) cPackages; index++) { - if (wcscmp(pszPackageName, SecPkgInfoW_LIST[index]->Name) == 0) + if (lstrcmpW(pszPackageName, SecPkgInfoW_LIST[index]->Name) == 0) { size = sizeof(SecPkgInfoW); pPackageInfo = (SecPkgInfoW*) sspi_ContextBufferAlloc(QuerySecurityPackageInfoIndex, size); diff --git a/winpr/synch/CMakeLists.txt b/winpr/synch/CMakeLists.txt new file mode 100644 index 000000000..ddbca8c96 --- /dev/null +++ b/winpr/synch/CMakeLists.txt @@ -0,0 +1,36 @@ +# WinPR: Windows Portable Runtime +# libwinpr-synch 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_SYNCH_SRCS + critical.c + event.c + mutex.c + semaphore.c + sleep.c) + +add_library(winpr-synch ${WINPR_SYNCH_SRCS}) + +set_target_properties(winpr-synch PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") + +if(NOT WIN32) + target_link_libraries(winpr-synch winpr-handle) +endif() + +install(TARGETS winpr-synch DESTINATION ${CMAKE_INSTALL_LIBDIR}) + diff --git a/winpr/synch/critical.c b/winpr/synch/critical.c new file mode 100644 index 000000000..b929ef678 --- /dev/null +++ b/winpr/synch/critical.c @@ -0,0 +1,23 @@ +/** + * WinPR: Windows Portable Runtime + * Synchronization Functions + * + * 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 + + + diff --git a/winpr/synch/event.c b/winpr/synch/event.c new file mode 100644 index 000000000..b929ef678 --- /dev/null +++ b/winpr/synch/event.c @@ -0,0 +1,23 @@ +/** + * WinPR: Windows Portable Runtime + * Synchronization Functions + * + * 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 + + + diff --git a/winpr/synch/mutex.c b/winpr/synch/mutex.c new file mode 100644 index 000000000..b929ef678 --- /dev/null +++ b/winpr/synch/mutex.c @@ -0,0 +1,23 @@ +/** + * WinPR: Windows Portable Runtime + * Synchronization Functions + * + * 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 + + + diff --git a/winpr/synch/semaphore.c b/winpr/synch/semaphore.c new file mode 100644 index 000000000..93175148a --- /dev/null +++ b/winpr/synch/semaphore.c @@ -0,0 +1,104 @@ +/** + * WinPR: Windows Portable Runtime + * Synchronization Functions + * + * 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 + +#ifndef _WIN32 + +#if defined __APPLE__ +#include +#include +#include +#include +#include +#define winpr_sem_t semaphore_td +#else +#include +#include +#define winpr_sem_t sem_t +#endif + +HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCSTR lpName) +{ + winpr_sem_t* hSemaphore; + + hSemaphore = malloc(sizeof(winpr_sem_t)); + +#if defined __APPLE__ + semaphore_create(mach_task_self(), hSemaphore, SYNC_POLICY_FIFO, lMaximumCount); +#else + sem_init(hSemaphore, 0, lMaximumCount); +#endif + + return (HANDLE) hSemaphore; +} + +HANDLE CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName) +{ + winpr_sem_t* hSemaphore; + + hSemaphore = malloc(sizeof(winpr_sem_t)); + +#if defined __APPLE__ + semaphore_create(mach_task_self(), hSemaphore, SYNC_POLICY_FIFO, lMaximumCount); +#else + sem_init(hSemaphore, 0, lMaximumCount); +#endif + + return (HANDLE) hSemaphore; +} + +HANDLE OpenSemaphoreA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName) +{ + return NULL; +} + +HANDLE OpenSemaphoreW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName) +{ + return NULL; +} + +BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount) +{ +#if defined __APPLE__ + semaphore_signal(*((winpr_sem_t*) hSemaphore)); +#else + sem_post((winpr_sem_t*) hSemaphore); +#endif + + return 1; +} + +DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) +{ +#if defined __APPLE__ + semaphore_wait(*((winpr_sem_t*) hHandle)); +#else + sem_wait((winpr_sem_t*) hHandle); +#endif + + return WAIT_OBJECT_0; +} + +DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles, BOOL bWaitAll, DWORD dwMilliseconds) +{ + return 0; +} + +#endif diff --git a/winpr/synch/sleep.c b/winpr/synch/sleep.c new file mode 100644 index 000000000..b929ef678 --- /dev/null +++ b/winpr/synch/sleep.c @@ -0,0 +1,23 @@ +/** + * WinPR: Windows Portable Runtime + * Synchronization Functions + * + * 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 + + + diff --git a/winpr/tools/CMakeLists.txt b/winpr/tools/CMakeLists.txt new file mode 100644 index 000000000..d04fbc019 --- /dev/null +++ b/winpr/tools/CMakeLists.txt @@ -0,0 +1,22 @@ +# WinPR: Windows Portable Runtime +# winpr 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. + +add_subdirectory(reg) +add_subdirectory(hash) + diff --git a/winpr/tools/hash/CMakeLists.txt b/winpr/tools/hash/CMakeLists.txt new file mode 100644 index 000000000..b8a1fc46c --- /dev/null +++ b/winpr/tools/hash/CMakeLists.txt @@ -0,0 +1,24 @@ +# WinPR: Windows Portable Runtime +# winpr-hash 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. + +add_executable(winpr-hash + hash.c) + +target_link_libraries(winpr-hash winpr-utils) + diff --git a/winpr/tools/hash/hash.c b/winpr/tools/hash/hash.c new file mode 100644 index 000000000..e42cbd1a9 --- /dev/null +++ b/winpr/tools/hash/hash.c @@ -0,0 +1,146 @@ +/** + * WinPR: Windows Portable Runtime + * NTLM Hashing Tool + * + * 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 + +/** + * Define NTOWFv1(Password, User, Domain) as + * MD4(UNICODE(Password)) + * EndDefine + * + * Define LMOWFv1(Password, User, Domain) as + * ConcatenationOf(DES(UpperCase(Password)[0..6], "KGS!@#$%"), + * DES(UpperCase(Password)[7..13], "KGS!@#$%")) + * EndDefine + * + * Define NTOWFv2(Password, User, Domain) as + * HMAC_MD5(MD4(UNICODE(Password)), + * UNICODE(ConcatenationOf(UpperCase(User), Domain))) + * EndDefine + * + * Define LMOWFv2(Password, User, Domain) as + * NTOWFv2(Password, User, Domain) + * EndDefine + * + */ + +int main(int argc, char* argv[]) +{ + int index = 1; + BYTE NtHash[16]; + BOOL sam_entry = 0; + char* User = NULL; + UINT32 UserLength; + char* Domain = NULL; + UINT32 DomainLength; + char* Password = NULL; + UINT32 PasswordLength; + + while (index < argc) + { + if (strcmp("-d", argv[index]) == 0) + { + index++; + + if (index == argc) + { + printf("missing domain\n"); + exit(1); + } + + Domain = argv[index]; + } + else if (strcmp("-u", argv[index]) == 0) + { + index++; + + if (index == argc) + { + printf("missing username\n"); + exit(1); + } + + User = argv[index]; + } + else if (strcmp("-p", argv[index]) == 0) + { + index++; + + if (index == argc) + { + printf("missing password\n"); + exit(1); + } + + Password = argv[index]; + } + else if (strcmp("-h", argv[index]) == 0) + { + printf("winpr-hash: NTLM hashing tool\n"); + printf("Usage: winpr-hash -u -p [-d ]\n"); + exit(1); + } + else if (strcmp("-s", argv[index]) == 0) + { + sam_entry = 1; + } + + index++; + } + + if ((!User) || (!Password)) + { + printf("missing username or password\n"); + exit(1); + } + + UserLength = strlen(User); + PasswordLength = strlen(Password); + DomainLength = (Domain) ? strlen(Domain) : 0; + + NTOWFv2A(Password, PasswordLength, User, UserLength, Domain, DomainLength, NtHash); + + if (sam_entry) + { + printf("%s:", User); + + if (DomainLength > 0) + printf("%s:", Domain); + else + printf(":"); + + printf(":"); + + for (index = 0; index < 16; index++) + printf("%02x", NtHash[index]); + printf("\n"); + } + else + { + for (index = 0; index < 16; index++) + printf("%02x", NtHash[index]); + printf("\n"); + } + + return 0; +} diff --git a/winpr/tools/reg/CMakeLists.txt b/winpr/tools/reg/CMakeLists.txt new file mode 100644 index 000000000..fd121a00e --- /dev/null +++ b/winpr/tools/reg/CMakeLists.txt @@ -0,0 +1,27 @@ +# WinPR: Windows Portable Runtime +# winpr-reg 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. + +add_executable(winpr-reg + reg.c) + +target_link_libraries(winpr-reg winpr-utils) + +if(NOT WIN32) + target_link_libraries(winpr-reg winpr-registry) +endif() diff --git a/winpr/tools/reg/reg.c b/winpr/tools/reg/reg.c new file mode 100644 index 000000000..5333a7a9f --- /dev/null +++ b/winpr/tools/reg/reg.c @@ -0,0 +1,86 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Registry API Tool + * + * 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 + +#include +#include + +int main(int argc, char* argv[]) +{ + HKEY hKey; + LONG status; + DWORD dwType; + DWORD dwSize; + DWORD dwValue; + DWORD RemoteFX; + char* ComputerName; + + status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\FreeRDP"), 0, KEY_READ, &hKey); + + if (status != ERROR_SUCCESS) + { + _tprintf(_T("RegOpenKeyEx error: 0x%08lX\n"), status); + return 0; + } + + dwValue = 0; + status = RegQueryValueEx(hKey, _T("RemoteFX"), NULL, &dwType, (BYTE*) &dwValue, &dwSize); + + if (status != ERROR_SUCCESS) + { + _tprintf(_T("RegQueryValueEx error: 0x%08lX\n"), status); + return 0; + } + + RemoteFX = dwValue; + + status = RegQueryValueEx(hKey, _T("ComputerName"), NULL, &dwType, NULL, &dwSize); + + if (status != ERROR_SUCCESS) + { + _tprintf(_T("RegQueryValueEx error: 0x%08lX\n"), status); + return 0; + } + + ComputerName = (char*) malloc(dwSize + 1); + + status = RegQueryValueEx(hKey, _T("ComputerName"), NULL, &dwType, (BYTE*) ComputerName, &dwSize); + + if (status != ERROR_SUCCESS) + { + _tprintf(_T("RegQueryValueEx error: 0x%08lX\n"), status); + return 0; + } + + printf("RemoteFX: %08lX\n", RemoteFX); + printf("ComputerName: %s\n", ComputerName); + + RegCloseKey(hKey); + + free(ComputerName); + + return 0; +} + diff --git a/winpr/utils/CMakeLists.txt b/winpr/utils/CMakeLists.txt index 33b1c427c..12d24a0b7 100644 --- a/winpr/utils/CMakeLists.txt +++ b/winpr/utils/CMakeLists.txt @@ -18,16 +18,24 @@ # limitations under the License. set(WINPR_UTILS_SRCS + ntlm.c print.c + sam.c stream.c) add_library(winpr-utils ${WINPR_UTILS_SRCS}) +include_directories(${ZLIB_INCLUDE_DIRS}) +include_directories(${OPENSSL_INCLUDE_DIR}) + set_target_properties(winpr-utils PROPERTIES VERSION ${FREERDP_VERSION_FULL} SOVERSION ${FREERDP_VERSION} PREFIX "lib") if (NOT WIN32) target_link_libraries(winpr-utils winpr-crt) endif() +target_link_libraries(winpr-utils ${ZLIB_LIBRARIES}) +target_link_libraries(winpr-utils ${OPENSSL_LIBRARIES}) + install(TARGETS winpr-utils DESTINATION ${CMAKE_INSTALL_LIBDIR}) diff --git a/winpr/utils/ntlm.c b/winpr/utils/ntlm.c new file mode 100644 index 000000000..be2851705 --- /dev/null +++ b/winpr/utils/ntlm.c @@ -0,0 +1,131 @@ +/** + * WinPR: Windows Portable Runtime + * NTLM Utils + * + * 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 +#include +#include +#include +#include +#include +#include + +/** + * Define NTOWFv1(Password, User, Domain) as + * MD4(UNICODE(Password)) + * EndDefine + */ + +BYTE* NTOWFv1W(LPWSTR Password, UINT32 PasswordLength, BYTE* NtHash) +{ + MD4_CTX md4_ctx; + + if (!Password) + return NULL; + + if (!NtHash) + NtHash = malloc(16); + + MD4_Init(&md4_ctx); + MD4_Update(&md4_ctx, Password, PasswordLength); + MD4_Final((void*) NtHash, &md4_ctx); + + return NtHash; +} + +BYTE* NTOWFv1A(LPSTR Password, UINT32 PasswordLength, BYTE* NtHash) +{ + LPWSTR PasswordW = NULL; + + PasswordW = (LPWSTR) malloc(PasswordLength * 2); + MultiByteToWideChar(CP_ACP, 0, Password, PasswordLength, PasswordW, PasswordLength); + + NtHash = NTOWFv1W(PasswordW, PasswordLength, NtHash); + + free(PasswordW); + + return NtHash; +} + +/** + * Define NTOWFv2(Password, User, Domain) as + * HMAC_MD5(MD4(UNICODE(Password)), + * UNICODE(ConcatenationOf(UpperCase(User), Domain))) + * EndDefine + */ + +BYTE* NTOWFv2W(LPWSTR Password, UINT32 PasswordLength, LPWSTR User, + UINT32 UserLength, LPWSTR Domain, UINT32 DomainLength, BYTE* NtHash) +{ + BYTE* buffer; + BYTE NtHashV1[16]; + + if ((!User) || (!Password)) + return NULL; + + if (!NtHash) + NtHash = (BYTE*) malloc(16); + + NTOWFv1W(Password, PasswordLength, NtHashV1); + + buffer = (BYTE*) malloc(UserLength + DomainLength); + + /* Concatenate(UpperCase(User), Domain) */ + + CopyMemory(buffer, User, UserLength); + CharUpperBuffW((LPWSTR) buffer, UserLength / 2); + CopyMemory(&buffer[UserLength], Domain, DomainLength); + + /* Compute the HMAC-MD5 hash of the above value using the NTLMv1 hash as the key, the result is the NTLMv2 hash */ + HMAC(EVP_md5(), (void*) NtHashV1, 16, buffer, UserLength + DomainLength, (void*) NtHash, NULL); + + free(buffer); + + return NtHash; +} + +BYTE* NTOWFv2A(LPSTR Password, UINT32 PasswordLength, LPSTR User, + UINT32 UserLength, LPSTR Domain, UINT32 DomainLength, BYTE* NtHash) +{ + LPWSTR UserW = NULL; + LPWSTR DomainW = NULL; + LPWSTR PasswordW = NULL; + + UserW = (LPWSTR) malloc(UserLength * 2); + DomainW = (LPWSTR) malloc(DomainLength * 2); + PasswordW = (LPWSTR) malloc(PasswordLength * 2); + + MultiByteToWideChar(CP_ACP, 0, User, UserLength, UserW, UserLength); + MultiByteToWideChar(CP_ACP, 0, Domain, DomainLength, DomainW, DomainLength); + MultiByteToWideChar(CP_ACP, 0, Password, PasswordLength, PasswordW, PasswordLength); + + NtHash = NTOWFv2W(PasswordW, PasswordLength * 2, UserW, UserLength * 2, DomainW, DomainLength * 2, NtHash); + + free(UserW); + free(DomainW); + free(PasswordW); + + return NtHash; +} + diff --git a/winpr/utils/sam.c b/winpr/utils/sam.c new file mode 100644 index 000000000..684d38283 --- /dev/null +++ b/winpr/utils/sam.c @@ -0,0 +1,272 @@ +/** + * WinPR: Windows Portable Runtime + * Security Accounts Manager (SAM) + * + * 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 +#include + +#define WINPR_SAM_FILE "/etc/winpr/SAM" + +WINPR_SAM* SamOpen(BOOL read_only) +{ + WINPR_SAM* sam; + + sam = (WINPR_SAM*) malloc(sizeof(WINPR_SAM)); + + if (sam != NULL) + { + sam->read_only = read_only; + + if (sam->read_only) + { + sam->fp = fopen(WINPR_SAM_FILE, "r"); + } + else + { + sam->fp = fopen(WINPR_SAM_FILE, "r+"); + + if (!sam->fp) + sam->fp = fopen(WINPR_SAM_FILE, "w+"); + } + } + + return sam; +} + +void SamLookupStart(WINPR_SAM* sam) +{ + long int file_size; + + fseek(sam->fp, 0, SEEK_END); + file_size = ftell(sam->fp); + fseek(sam->fp, 0, SEEK_SET); + + if (file_size < 1) + return; + + sam->buffer = (char*) malloc(file_size + 2); + + if (fread(sam->buffer, file_size, 1, sam->fp) != 1) + { + free(sam->buffer); + return; + } + + sam->buffer[file_size] = '\n'; + sam->buffer[file_size + 1] = '\0'; + + sam->line = strtok(sam->buffer, "\n"); +} + +void SamLookupFinish(WINPR_SAM* sam) +{ + free(sam->buffer); + + sam->buffer = NULL; + sam->line = NULL; +} + +void HexStrToBin(char* str, BYTE* bin, int length) +{ + int i; + + CharUpperBuffA(str, length * 2); + + for (i = 0; i < length; i++) + { + bin[i] = 0; + + if ((str[i * 2] >= '0') && (str[i * 2] <= '9')) + bin[i] |= (str[i * 2] - '0') << 4; + + if ((str[i * 2] >= 'A') && (str[i * 2] <= 'F')) + bin[i] |= (str[i * 2] - 'A' + 10) << 4; + + if ((str[i * 2 + 1] >= '0') && (str[i * 2 + 1] <= '9')) + bin[i] |= (str[i * 2 + 1] - '0'); + + if ((str[i * 2 + 1] >= 'A') && (str[i * 2 + 1] <= 'F')) + bin[i] |= (str[i * 2 + 1] - 'A' + 10); + } +} + +WINPR_SAM_ENTRY* SamReadEntry(WINPR_SAM* sam, WINPR_SAM_ENTRY* entry) +{ + char* p[5]; + int LmHashLength; + int NtHashLength; + + p[0] = sam->line; + p[1] = strchr(p[0], ':') + 1; + p[2] = strchr(p[1], ':') + 1; + p[3] = strchr(p[2], ':') + 1; + p[4] = p[0] + strlen(p[0]); + + entry->UserLength = p[1] - p[0] - 1; + entry->DomainLength = p[2] - p[1] - 1; + + LmHashLength = p[3] - p[2] - 1; + NtHashLength = p[4] - p[3]; + + entry->User = (LPSTR) malloc(entry->UserLength + 1); + memcpy(entry->User, p[0], entry->UserLength); + entry->User[entry->UserLength] = '\0'; + + if (entry->DomainLength > 0) + { + entry->Domain = (LPSTR) malloc(entry->DomainLength + 1); + memcpy(entry->Domain, p[1], entry->DomainLength); + entry->Domain[entry->DomainLength] = '\0'; + } + + if (LmHashLength == 32) + { + HexStrToBin(p[2], (BYTE*) entry->LmHash, 16); + } + + if (NtHashLength == 32) + { + HexStrToBin(p[3], (BYTE*) entry->NtHash, 16); + } + + printf("SamReadEntry: %s\n", entry->User); + + return entry; +} + +void SamFreeEntry(WINPR_SAM* sam, WINPR_SAM_ENTRY* entry) +{ + if (entry) + { + if (entry->UserLength > 0) + free(entry->User); + + if (entry->DomainLength > 0) + free(entry->Domain); + + free(entry); + } +} + +WINPR_SAM_ENTRY* SamLookupUserA(WINPR_SAM* sam, LPSTR User, UINT32 UserLength, LPSTR Domain, UINT32 DomainLength) +{ + int length; + BOOL found = 0; + WINPR_SAM_ENTRY* entry; + + entry = (WINPR_SAM_ENTRY*) malloc(sizeof(WINPR_SAM_ENTRY)); + + SamLookupStart(sam); + + while (sam->line != NULL) + { + length = strlen(sam->line); + + if (length > 1) + { + if (sam->line[0] != '#') + { + SamReadEntry(sam, entry); + + if (strcmp(User, entry->User) == 0) + { + found = 1; + break; + } + } + } + + sam->line = strtok(NULL, "\n"); + } + + SamLookupFinish(sam); + + if (!found) + { + free(entry); + return NULL; + } + + return entry; +} + +WINPR_SAM_ENTRY* SamLookupUserW(WINPR_SAM* sam, LPWSTR User, UINT32 UserLength, LPWSTR Domain, UINT32 DomainLength) +{ + int length; + BOOL found = 0; + LPWSTR EntryUser; + UINT32 EntryUserLength; + WINPR_SAM_ENTRY* entry; + + entry = (WINPR_SAM_ENTRY*) malloc(sizeof(WINPR_SAM_ENTRY)); + + SamLookupStart(sam); + + while (sam->line != NULL) + { + length = strlen(sam->line); + + if (length > 1) + { + if (sam->line[0] != '#') + { + entry = SamReadEntry(sam, entry); + + EntryUserLength = strlen(entry->User) * 2; + EntryUser = (LPWSTR) malloc(EntryUserLength + 2); + MultiByteToWideChar(CP_ACP, 0, entry->User, EntryUserLength / 2, + (LPWSTR) EntryUser, EntryUserLength / 2); + + if (UserLength == EntryUserLength) + { + if (memcmp(User, EntryUser, UserLength) == 0) + { + found = 1; + break; + } + } + } + } + + sam->line = strtok(NULL, "\n"); + } + + SamLookupFinish(sam); + + if (!found) + { + free(entry); + return NULL; + } + + return entry; +} + +void SamClose(WINPR_SAM* sam) +{ + if (sam != NULL) + { + fclose(sam->fp); + free(sam); + } +}