From 7bfff83859f4bfb254c659dc0caa529735fd2507 Mon Sep 17 00:00:00 2001 From: Kevin Koch Date: Tue, 22 Jan 2008 19:14:04 +0000 Subject: [PATCH] Windows CCAPI snapshot. Should build & pass ping test TargetVersion: 1.7 Component: krb5-libs Ticket: 5594 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@20203 dc483132-0cff-0310-8789-dd5450dbe970 --- src/ccapi/common/win/OldCC/autolock.hxx | 53 ++ src/ccapi/common/win/OldCC/ccutil.cxx | 187 +++++ src/ccapi/common/win/OldCC/ccutil.def | 5 + src/ccapi/common/win/OldCC/ccutils.c | 136 ++++ src/ccapi/common/win/OldCC/ccutils.h | 49 ++ src/ccapi/common/win/OldCC/init.cxx | 187 +++++ src/ccapi/common/win/OldCC/init.hxx | 102 +++ src/ccapi/common/win/OldCC/name.h | 38 + src/ccapi/common/win/OldCC/opts.cxx | 188 +++++ src/ccapi/common/win/OldCC/opts.hxx | 56 ++ src/ccapi/common/win/OldCC/secure.cxx | 161 ++++ src/ccapi/common/win/OldCC/secure.hxx | 60 ++ src/ccapi/common/win/OldCC/util.cxx | 519 +++++++++++++ src/ccapi/common/win/OldCC/util.h | 89 +++ src/ccapi/common/win/cci_os_debugging.c | 39 + src/ccapi/common/win/cci_os_identifier.c | 58 ++ src/ccapi/common/win/ccs_reply.Acf | 31 + src/ccapi/common/win/ccs_reply.Idl | 60 ++ src/ccapi/common/win/ccs_request.Acf | 31 + src/ccapi/common/win/ccs_request.idl | 58 ++ src/ccapi/common/win/tls.c | 71 ++ src/ccapi/common/win/tls.h | 70 ++ src/ccapi/common/win/win-utils.c | 66 ++ src/ccapi/common/win/win-utils.h | 55 ++ src/ccapi/lib/win/Makefile | 116 +++ src/ccapi/lib/win/OldCC/ccapi.h | 284 +++++++ src/ccapi/lib/win/OldCC/client.cxx | 389 ++++++++++ src/ccapi/lib/win/OldCC/client.h | 61 ++ src/ccapi/lib/win/OldCC/rpc.cxx | 79 ++ src/ccapi/lib/win/WINCCAPI.sln | 20 + src/ccapi/lib/win/WINCCAPI.vcproj | 111 +++ src/ccapi/lib/win/ccapi.def | 39 + src/ccapi/lib/win/ccapi_os_ipc.cxx | 373 +++++++++ src/ccapi/lib/win/ccs_reply_proc.c | 98 +++ src/ccapi/lib/win/dllmain.cxx | 279 +++++++ src/ccapi/lib/win/dllmain.h | 45 ++ src/ccapi/server/win/Makefile | 105 +++ src/ccapi/server/win/Server.sln | 20 + src/ccapi/server/win/Server.vcproj | 227 ++++++ src/ccapi/server/win/WorkItem.cpp | 126 +++ src/ccapi/server/win/WorkQueue.cpp | 61 ++ src/ccapi/server/win/WorkQueue.h | 46 ++ src/ccapi/server/win/ccs_os_pipe.c | 64 ++ src/ccapi/server/win/ccs_os_server.cpp | 950 +++++++++++++++++++++++ src/ccapi/server/win/ccs_request_proc.c | 116 +++ src/ccapi/server/win/ccs_win_pipe.c | 163 ++++ src/ccapi/server/win/ccs_win_pipe.h | 69 ++ src/ccapi/server/win/workitem.h | 48 ++ src/ccapi/test/Makefile.w32 | 64 ++ src/ccapi/test/pingtest.c | 108 +++ src/ccapi/test/simple_lock_test.c | 153 ++-- 51 files changed, 6514 insertions(+), 69 deletions(-) create mode 100644 src/ccapi/common/win/OldCC/autolock.hxx create mode 100644 src/ccapi/common/win/OldCC/ccutil.cxx create mode 100644 src/ccapi/common/win/OldCC/ccutil.def create mode 100644 src/ccapi/common/win/OldCC/ccutils.c create mode 100644 src/ccapi/common/win/OldCC/ccutils.h create mode 100644 src/ccapi/common/win/OldCC/init.cxx create mode 100644 src/ccapi/common/win/OldCC/init.hxx create mode 100644 src/ccapi/common/win/OldCC/name.h create mode 100644 src/ccapi/common/win/OldCC/opts.cxx create mode 100644 src/ccapi/common/win/OldCC/opts.hxx create mode 100644 src/ccapi/common/win/OldCC/secure.cxx create mode 100644 src/ccapi/common/win/OldCC/secure.hxx create mode 100644 src/ccapi/common/win/OldCC/util.cxx create mode 100644 src/ccapi/common/win/OldCC/util.h create mode 100644 src/ccapi/common/win/cci_os_debugging.c create mode 100644 src/ccapi/common/win/cci_os_identifier.c create mode 100644 src/ccapi/common/win/ccs_reply.Acf create mode 100644 src/ccapi/common/win/ccs_reply.Idl create mode 100644 src/ccapi/common/win/ccs_request.Acf create mode 100644 src/ccapi/common/win/ccs_request.idl create mode 100644 src/ccapi/common/win/tls.c create mode 100644 src/ccapi/common/win/tls.h create mode 100644 src/ccapi/common/win/win-utils.c create mode 100644 src/ccapi/common/win/win-utils.h create mode 100644 src/ccapi/lib/win/Makefile create mode 100644 src/ccapi/lib/win/OldCC/ccapi.h create mode 100644 src/ccapi/lib/win/OldCC/client.cxx create mode 100644 src/ccapi/lib/win/OldCC/client.h create mode 100644 src/ccapi/lib/win/OldCC/rpc.cxx create mode 100644 src/ccapi/lib/win/WINCCAPI.sln create mode 100644 src/ccapi/lib/win/WINCCAPI.vcproj create mode 100644 src/ccapi/lib/win/ccapi.def create mode 100644 src/ccapi/lib/win/ccapi_os_ipc.cxx create mode 100644 src/ccapi/lib/win/ccs_reply_proc.c create mode 100644 src/ccapi/lib/win/dllmain.cxx create mode 100644 src/ccapi/lib/win/dllmain.h create mode 100644 src/ccapi/server/win/Makefile create mode 100644 src/ccapi/server/win/Server.sln create mode 100644 src/ccapi/server/win/Server.vcproj create mode 100644 src/ccapi/server/win/WorkItem.cpp create mode 100644 src/ccapi/server/win/WorkQueue.cpp create mode 100644 src/ccapi/server/win/WorkQueue.h create mode 100644 src/ccapi/server/win/ccs_os_pipe.c create mode 100644 src/ccapi/server/win/ccs_os_server.cpp create mode 100644 src/ccapi/server/win/ccs_request_proc.c create mode 100644 src/ccapi/server/win/ccs_win_pipe.c create mode 100644 src/ccapi/server/win/ccs_win_pipe.h create mode 100644 src/ccapi/server/win/workitem.h create mode 100644 src/ccapi/test/Makefile.w32 create mode 100644 src/ccapi/test/pingtest.c diff --git a/src/ccapi/common/win/OldCC/autolock.hxx b/src/ccapi/common/win/OldCC/autolock.hxx new file mode 100644 index 000000000..9fc759514 --- /dev/null +++ b/src/ccapi/common/win/OldCC/autolock.hxx @@ -0,0 +1,53 @@ +/* + + Copyright (C) 1998 Danilo Almeida. All rights reserved. + + automatic stack-based locking object + + This file is part of FIFS (Framework for Implementing File Systems). + + This software is distributed with NO WARRANTY OF ANY KIND. No + author or distributor accepts any responsibility for the + consequences of using it, or for whether it serves any particular + purpose or works at all, unless he or she says so in writing. + Refer to the included modified Alladin Free Public License (the + "License") for full details. + + Every copy of this software must include a copy of the License, in + a plain ASCII text file named COPYING. The License grants you the + right to copy, modify and redistribute this software, but only + under certain conditions described in the License. Among other + things, the License requires that the copyright notice and this + notice be preserved on all copies. + +*/ + +#ifndef __AUTOLOCK_HXX__ +#define __AUTOLOCK_HXX__ + +#include + +class CcOsLock { + CRITICAL_SECTION cs; + bool valid; +public: + CcOsLock() {InitializeCriticalSection(&cs); valid = true; } + ~CcOsLock() {DeleteCriticalSection(&cs); valid = false;} + void lock() {if (valid) EnterCriticalSection(&cs);} + void unlock() {if (valid) LeaveCriticalSection(&cs);} +#if 0 + bool trylock() {return valid ? (TryEnterCriticalSection(&cs) ? true : false) + : false; } +#endif +}; + +class CcAutoLock { + CcOsLock& m_lock; +public: + static void Start(CcAutoLock*& a, CcOsLock& lock) { a = new CcAutoLock(lock); }; + static void Stop (CcAutoLock*& a) { delete a; a = 0; }; + CcAutoLock(CcOsLock& lock):m_lock(lock) { m_lock.lock(); } + ~CcAutoLock() { m_lock.unlock(); } +}; + +#endif /* __AUTOLOCK_HXX */ diff --git a/src/ccapi/common/win/OldCC/ccutil.cxx b/src/ccapi/common/win/OldCC/ccutil.cxx new file mode 100644 index 000000000..e5e5baef5 --- /dev/null +++ b/src/ccapi/common/win/OldCC/ccutil.cxx @@ -0,0 +1,187 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include "init.hxx" +#include "secure.hxx" + +extern "C" { +#include "cci_debugging.h" + } + + +CcOsLock Init::s_lock; +DWORD Init::s_refcount = 0; +DWORD Init::s_error = ERROR_INVALID_HANDLE; +bool Init::s_init = false; +Init::InitInfo Init::s_info = { 0 }; +HINSTANCE Init::s_hRpcDll = 0; + +#define INIT "INIT: " + +static +void +ShowInfo( + Init::InitInfo& info + ); + +DWORD +Init::Info( + InitInfo& info + ) +{ + // This funciton will not do automatic initialization. + CcAutoLock AL(s_lock); + if (!s_init) { + memset(&info, 0, sizeof(info)); + return s_error ? s_error : ERROR_INVALID_HANDLE; + } else { + info = s_info; + return 0; + } +} + +DWORD +Init::Initialize() { + CcAutoLock AL(s_lock); + cci_debug_printf("%s s_init:%d", __FUNCTION__, s_init); + if (s_init) { + s_refcount++; + return 0; + } + SecureClient s; + DWORD status = 0; + OSVERSIONINFO osvi; + BOOL isSupportedVersion = FALSE; + memset(&s_info, 0, sizeof(s_info)); + memset(&osvi, 0, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK. + + if (!status) { + switch(osvi.dwPlatformId) { + case VER_PLATFORM_WIN32_WINDOWS: + s_info.isNT = FALSE; + isSupportedVersion = TRUE; + break; + case VER_PLATFORM_WIN32_NT: + s_info.isNT = TRUE; + isSupportedVersion = TRUE; + break; + case VER_PLATFORM_WIN32s: + default: + s_info.isNT = FALSE; + break; + } + + if (!isSupportedVersion) { + cci_debug_printf("%s Trying to run on an unsupported version of Windows", __FUNCTION__); + status = 1; + } + } + + if (!status) {status = !s_info.isNT;} + + if (!status) {status = !(s_hRpcDll = LoadLibrary(TEXT("rpcrt4.dll")));} + + if (!status) { + s_info.fRpcBindingSetAuthInfoEx = (FP_RpcBindingSetAuthInfoEx) + GetProcAddress(s_hRpcDll, TEXT(FN_RpcBindingSetAuthInfoEx)); + if (!s_info.fRpcBindingSetAuthInfoEx) { + cci_debug_printf(" Running on NT but could not find RpcBindinSetAuthInfoEx"); + status = 1; + } + } + + if (!status) { + s_info.fRpcServerRegisterIfEx = (FP_RpcServerRegisterIfEx) + GetProcAddress(s_hRpcDll, TEXT(FN_RpcServerRegisterIfEx)); + if (!s_info.fRpcServerRegisterIfEx) { + cci_debug_printf(" Running on NT but could not find RpcServerRegisterIfEx"); + status = 1; + } + } + + if (!status) { + status = SecureClient::Attach(); + if (status) { + cci_debug_printf(" SecureClient::Attach() failed (%u)", status); + } + } + + if (status) { + memset(&s_info, 0, sizeof(s_info)); + if (s_hRpcDll) { + FreeLibrary(s_hRpcDll); + s_hRpcDll = 0; + } + cci_debug_printf(" Init::Attach() failed (%u)", status); + } else { + s_refcount++; + s_init = true; + ShowInfo(s_info); + } + s_error = status; + return status; +} + +DWORD +Init::Cleanup( + ) +{ + CcAutoLock AL(s_lock); + s_refcount--; + if (s_refcount) return 0; + if (!s_init) return 0; + DWORD error = 0; + if (s_hRpcDll) { + FreeLibrary(s_hRpcDll); + s_hRpcDll = 0; + } + error = SecureClient::Detach(); + memset(&s_info, 0, sizeof(s_info)); + s_init = false; + s_error = 0; + if (error) { + cci_debug_printf(" Init::Detach() had an error (%u)", error); + } + return error; +} + +static +void +ShowInfo( + Init::InitInfo& info + ) +{ + if (info.isNT) { + cci_debug_printf(" Running on Windows NT using secure mode"); + } else { + cci_debug_printf(" Running insecurely on non-NT Windows"); + } + return; +} diff --git a/src/ccapi/common/win/OldCC/ccutil.def b/src/ccapi/common/win/OldCC/ccutil.def new file mode 100644 index 000000000..a187c805d --- /dev/null +++ b/src/ccapi/common/win/OldCC/ccutil.def @@ -0,0 +1,5 @@ +;LIBRARY COMERR32 +HEAPSIZE 8192 + +EXPORTS + \ No newline at end of file diff --git a/src/ccapi/common/win/OldCC/ccutils.c b/src/ccapi/common/win/OldCC/ccutils.c new file mode 100644 index 000000000..1db00b480 --- /dev/null +++ b/src/ccapi/common/win/OldCC/ccutils.c @@ -0,0 +1,136 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include + +#include "cci_debugging.h" +#include "util.h" + +BOOL isNT() { + OSVERSIONINFO osvi; + DWORD status = 0; + BOOL bSupportedVersion = FALSE; + BOOL bIsNT = FALSE; + + memset(&osvi, 0, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK. + + if (!status) { + switch(osvi.dwPlatformId) { + case VER_PLATFORM_WIN32_WINDOWS: + bIsNT = FALSE; + bSupportedVersion = TRUE; + break; + case VER_PLATFORM_WIN32_NT: + bIsNT = TRUE; + bSupportedVersion = TRUE; + break; + case VER_PLATFORM_WIN32s: + default: + bIsNT = FALSE; + break; + } + + if (!bSupportedVersion) { + cci_debug_printf("%s Running on an unsupported version of Windows", __FUNCTION__); + status = 1; + } + } + + return (!status && bIsNT && bSupportedVersion); + } + +char* allocEventName(char* uuid_string, char* suffix) { + LPSTR event_name = NULL; + cc_int32 err = ccNoError; + + event_name = malloc(strlen(uuid_string) + strlen(suffix) + 3); + if (!event_name) err = cci_check_error(ccErrNoMem); + + if (!err) { + strcpy(event_name, uuid_string); + strcat(event_name, "_"); + strcat(event_name, suffix); + } + + return event_name; + } + +HANDLE createThreadEvent(char* uuid, char* suffix) { + LPSTR event_name = NULL; + HANDLE hEvent = NULL; + PSECURITY_ATTRIBUTES psa = 0; // Everything having to do with + SECURITY_ATTRIBUTES sa = { 0 }; // sa, psa, security is copied + DWORD status = 0; // from the previous implementation. + + psa = isNT() ? &sa : 0; + + if (isNT()) { + sa.nLength = sizeof(sa); + status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor); + cci_check_error(status); + } + + if (!status) { + event_name = allocEventName(uuid, suffix); + if (!event_name) status = cci_check_error(ccErrNoMem); + } + cci_debug_printf("%s event_name:%s", __FUNCTION__, event_name); + + if (!status) { + hEvent = CreateEvent(psa, FALSE, FALSE, event_name); + if (!hEvent) status = cci_check_error(GetLastError()); + } + + if (!status) ResetEvent(hEvent); + + + if (event_name) free(event_name); + if (isNT()) free(sa.lpSecurityDescriptor); + + return hEvent; + } + +HANDLE openThreadEvent(char* uuid, char* suffix) { + LPSTR event_name = NULL; + HANDLE hEvent = NULL; + DWORD status = 0; + + event_name = allocEventName(uuid, suffix); + if (!event_name) status = cci_check_error(ccErrNoMem); + cci_debug_printf("%s event_name:%s", __FUNCTION__, event_name); + + if (!status) { + hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name); + if (!hEvent) status = cci_check_error(GetLastError()); + } + + if (event_name) free(event_name); + + return hEvent; + } \ No newline at end of file diff --git a/src/ccapi/common/win/OldCC/ccutils.h b/src/ccapi/common/win/OldCC/ccutils.h new file mode 100644 index 000000000..77cafb11e --- /dev/null +++ b/src/ccapi/common/win/OldCC/ccutils.h @@ -0,0 +1,49 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __CCUTILS_H__ +#define __CCUTILS_H__ + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +#define REPLY_SUFFIX (char*)"reply" +#define LISTEN_SUFFIX (char*)"listen" + +BOOL isNT(); +char* allocEventName (char* uuid, char* suffix); +HANDLE createThreadEvent(char* uuid, char* suffix); +HANDLE openThreadEvent (char* uuid, char* suffix); + +#ifdef __cplusplus +} +#endif + +#endif /* __CCUTILS_H__ */ diff --git a/src/ccapi/common/win/OldCC/init.cxx b/src/ccapi/common/win/OldCC/init.cxx new file mode 100644 index 000000000..af93722fe --- /dev/null +++ b/src/ccapi/common/win/OldCC/init.cxx @@ -0,0 +1,187 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include "init.hxx" +#include "secure.hxx" + +extern "C" { +#include "cci_debugging.h" + } + + +CcOsLock Init::s_lock; +DWORD Init::s_refcount = 0; +DWORD Init::s_error = ERROR_INVALID_HANDLE; +bool Init::s_init = false; +Init::InitInfo Init::s_info = { 0 }; +HINSTANCE Init::s_hRpcDll = 0; + +#define INIT "INIT: " + +static +void +ShowInfo( + Init::InitInfo& info + ); + +DWORD +Init::Info( + InitInfo& info + ) +{ + // This funciton will not do automatic initialization. + CcAutoLock AL(s_lock); + if (!s_init) { + memset(&info, 0, sizeof(info)); + return s_error ? s_error : ERROR_INVALID_HANDLE; + } else { + info = s_info; + return 0; + } +} + +DWORD +Init::Initialize() { + CcAutoLock AL(s_lock); +// cci_debug_printf("%s s_init:%d", __FUNCTION__, s_init); + if (s_init) { + s_refcount++; + return 0; + } + SecureClient s; + DWORD status = 0; + OSVERSIONINFO osvi; + BOOL isSupportedVersion = FALSE; + memset(&s_info, 0, sizeof(s_info)); + memset(&osvi, 0, sizeof(osvi)); + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + + status = !GetVersionEx(&osvi); // Returns a boolean. Invert to 0 is OK. + + if (!status) { + switch(osvi.dwPlatformId) { + case VER_PLATFORM_WIN32_WINDOWS: + s_info.isNT = FALSE; + isSupportedVersion = TRUE; + break; + case VER_PLATFORM_WIN32_NT: + s_info.isNT = TRUE; + isSupportedVersion = TRUE; + break; + case VER_PLATFORM_WIN32s: + default: + s_info.isNT = FALSE; + break; + } + + if (!isSupportedVersion) { + cci_debug_printf("%s Trying to run on an unsupported version of Windows", __FUNCTION__); + status = 1; + } + } + + if (!status) {status = !s_info.isNT;} + + if (!status) {status = !(s_hRpcDll = LoadLibrary(TEXT("rpcrt4.dll")));} + + if (!status) { + s_info.fRpcBindingSetAuthInfoEx = (FP_RpcBindingSetAuthInfoEx) + GetProcAddress(s_hRpcDll, TEXT(FN_RpcBindingSetAuthInfoEx)); + if (!s_info.fRpcBindingSetAuthInfoEx) { + cci_debug_printf(" Running on NT but could not find RpcBindinSetAuthInfoEx"); + status = 1; + } + } + + if (!status) { + s_info.fRpcServerRegisterIfEx = (FP_RpcServerRegisterIfEx) + GetProcAddress(s_hRpcDll, TEXT(FN_RpcServerRegisterIfEx)); + if (!s_info.fRpcServerRegisterIfEx) { + cci_debug_printf(" Running on NT but could not find RpcServerRegisterIfEx"); + status = 1; + } + } + + if (!status) { + status = SecureClient::Attach(); + if (status) { + cci_debug_printf(" SecureClient::Attach() failed (%u)", status); + } + } + + if (status) { + memset(&s_info, 0, sizeof(s_info)); + if (s_hRpcDll) { + FreeLibrary(s_hRpcDll); + s_hRpcDll = 0; + } + cci_debug_printf(" Init::Attach() failed (%u)", status); + } else { + s_refcount++; + s_init = true; + ShowInfo(s_info); + } + s_error = status; + return status; +} + +DWORD +Init::Cleanup( + ) +{ + CcAutoLock AL(s_lock); + s_refcount--; + if (s_refcount) return 0; + if (!s_init) return 0; + DWORD error = 0; + if (s_hRpcDll) { + FreeLibrary(s_hRpcDll); + s_hRpcDll = 0; + } + error = SecureClient::Detach(); + memset(&s_info, 0, sizeof(s_info)); + s_init = false; + s_error = 0; + if (error) { + cci_debug_printf(" Init::Detach() had an error (%u)", error); + } + return error; +} + +static +void +ShowInfo( + Init::InitInfo& info + ) +{ + if (info.isNT) { + cci_debug_printf(" Running on Windows NT using secure mode"); + } else { + cci_debug_printf(" Running insecurely on non-NT Windows"); + } + return; +} diff --git a/src/ccapi/common/win/OldCC/init.hxx b/src/ccapi/common/win/OldCC/init.hxx new file mode 100644 index 000000000..f50db776a --- /dev/null +++ b/src/ccapi/common/win/OldCC/init.hxx @@ -0,0 +1,102 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#pragma once +#include "autolock.hxx" +#include + +typedef RPC_STATUS (RPC_ENTRY *FP_RpcBindingSetAuthInfoExA)( + IN RPC_BINDING_HANDLE Binding, + IN unsigned char __RPC_FAR * ServerPrincName, + IN unsigned long AuthnLevel, + IN unsigned long AuthnSvc, + IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL + IN unsigned long AuthzSvc, + IN RPC_SECURITY_QOS *SecurityQos OPTIONAL + ); + +typedef RPC_STATUS (RPC_ENTRY *FP_RpcBindingSetAuthInfoExW)( + IN RPC_BINDING_HANDLE Binding, + IN unsigned short __RPC_FAR * ServerPrincName, + IN unsigned long AuthnLevel, + IN unsigned long AuthnSvc, + IN RPC_AUTH_IDENTITY_HANDLE AuthIdentity, OPTIONAL + IN unsigned long AuthzSvc, OPTIONAL + IN RPC_SECURITY_QOS *SecurityQOS + ); + +typedef RPC_STATUS (RPC_ENTRY *FP_RpcServerRegisterIfEx)( + IN RPC_IF_HANDLE IfSpec, + IN UUID __RPC_FAR * MgrTypeUuid, + IN RPC_MGR_EPV __RPC_FAR * MgrEpv, + IN unsigned int Flags, + IN unsigned int MaxCalls, + IN RPC_IF_CALLBACK_FN __RPC_FAR *IfCallback + ); + +#ifdef UNICODE +#define FP_RpcBindingSetAuthInfoEx FP_RpcBindingSetAuthInfoExW +#define FN_RpcBindingSetAuthInfoEx "RpcBindingSetAuthInfoExW" +#else +#define FP_RpcBindingSetAuthInfoEx FP_RpcBindingSetAuthInfoExA +#define FN_RpcBindingSetAuthInfoEx "RpcBindingSetAuthInfoExA" +#endif + +#define FN_RpcServerRegisterIfEx "RpcServerRegisterIfEx" + +class Init +{ +public: + struct InitInfo { + BOOL isNT; + FP_RpcBindingSetAuthInfoEx fRpcBindingSetAuthInfoEx; + FP_RpcServerRegisterIfEx fRpcServerRegisterIfEx; + }; + + static DWORD Initialize(); + static DWORD Cleanup(); + static DWORD Info(InitInfo& info); + + static bool Initialized() { return s_init; } + +private: + static CcOsLock s_lock; + static DWORD s_refcount; + static DWORD s_error; + static bool s_init; + static InitInfo s_info; + static HINSTANCE s_hRpcDll; +}; + +#define INIT_INIT_EX(trap, error) \ +do \ +{ \ + if (!Init::Initialized()) \ + { \ + DWORD rc = Init::Initialize(); \ + if (rc) return (trap) ? (error) : rc; \ + } \ +} while(0) diff --git a/src/ccapi/common/win/OldCC/name.h b/src/ccapi/common/win/OldCC/name.h new file mode 100644 index 000000000..e0172d673 --- /dev/null +++ b/src/ccapi/common/win/OldCC/name.h @@ -0,0 +1,38 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#pragma once + +#ifdef _WIN64 +#define CCAPI_MODULE "krbcc64" +#else +#define CCAPI_MODULE "krbcc32" +#endif +#define CCAPI_DLL CCAPI_MODULE ".dll" +#define CCAPI_EXE CCAPI_MODULE "s.exe" + +#define CCAPI_DLL "ccapi.dll" +#define CCAPI_EXE "ccapiserver.exe" \ No newline at end of file diff --git a/src/ccapi/common/win/OldCC/opts.cxx b/src/ccapi/common/win/OldCC/opts.cxx new file mode 100644 index 000000000..c6a40d64d --- /dev/null +++ b/src/ccapi/common/win/OldCC/opts.cxx @@ -0,0 +1,188 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include +#include + +#if 0 +const struct Opts* +GetOpts( + ) +{ + bool done = false; + struct Opts* o; + if (!(o = new Opts)) + goto cleanup; + if (!(o->pszString = new char[lstrlenA(opts.pszString) + 1])) + goto cleanup; + if (!(o->pszEndpoint = new char[lstrlenA(opts.pszEndpoint) + 1])) + goto cleanup; + strcpy(o->pszString, opts.pszString); + strcpy(o->pszEndpoint, opts.pszEndpoint); + done = true; + cleanup: + if (!done) { + FreeOpts(o); + o = 0; + } + return o; +} + +void +FreeOpts( + struct Opts* o + ) +{ + if (o) { + if (o->pszString) + delete [] o->pszString; + if (o->pszEndpoint) + delete [] o->pszEndpoint; + delete o; + } +} +#endif + +bool +ParseOpts::IsValidOpt( + char ch + ) +{ + return (m_ValidOpts[ch % 256] != 0); +} + +void +ParseOpts::PrintOpt( + char ch, + char* text + ) +{ + if (IsValidOpt(ch)) + fprintf(stderr, " -%c %s\n", ch, text); +} + +void +ParseOpts::UsageOpts( + char * program, + int code + ) +{ + fprintf(stderr, "Usage: %s [options]\n", program); + PrintOpt('k', "stop server"); +#ifdef CCAPI_TEST_OPTIONS + PrintOpt('s', "string"); + PrintOpt('e', "endpoint"); + PrintOpt('m', "maxcalls"); + PrintOpt('n', "mincalls"); + PrintOpt('f', "flag_wait_op"); + PrintOpt('u', "unprotected"); + PrintOpt('b', "use security callback"); +#endif + PrintOpt('c', "output debug info to console"); + exit(code); +} + +void +ParseOpts::SetValidOpts( + char* valid_opts + ) +{ + memset(m_ValidOpts, 0, sizeof(m_ValidOpts)); + char *p = valid_opts; + for (p = valid_opts; *p; p++) { + m_ValidOpts[*p % sizeof(m_ValidOpts)] = 1; + } +} + +void +ParseOpts::Parse( + Opts& opts, + int argc, + char **argv + ) +{ + int i; + for (i = 1; i < argc; i++) { + if ((*argv[i] == '-') || (*argv[i] == '/')) { + char ch = tolower(*(argv[i]+1)); + if (!IsValidOpt(ch)) + UsageOpts(argv[0]); + switch (ch) { + case 'k': + opts.bShutdown = TRUE; + break; +#ifdef CCAPI_TEST_OPTIONS + case 's': + opts.pszString = argv[++i]; + break; + case 'e': + opts.pszEndpoint = argv[++i]; + break; + case 'm': + opts.cMaxCalls = (unsigned int) atoi(argv[++i]); + break; + case 'n': + opts.cMinCalls = (unsigned int) atoi(argv[++i]); + break; + case 'f': + opts.fDontWait = (unsigned int) atoi(argv[++i]); + break; + case 'u': + opts.bDontProtect = TRUE; + break; + case 'b': + opts.bSecCallback = TRUE; + break; +#endif + case 'c': + opts.bConsole = TRUE; + break; + case 'h': + case '?': + default: + UsageOpts(argv[0]); + } + } + else + UsageOpts(argv[0]); + } + +} + +ParseOpts::ParseOpts(char* valid_opts) +{ + SetValidOpts(valid_opts); +} + +ParseOpts::ParseOpts() +{ +} + +ParseOpts::~ParseOpts() +{ +} diff --git a/src/ccapi/common/win/OldCC/opts.hxx b/src/ccapi/common/win/OldCC/opts.hxx new file mode 100644 index 000000000..1732ceb25 --- /dev/null +++ b/src/ccapi/common/win/OldCC/opts.hxx @@ -0,0 +1,56 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#pragma once + +class ParseOpts +{ +public: + struct Opts { + char* pszString; + char* pszEndpoint; + unsigned int cMinCalls; + unsigned int cMaxCalls; + unsigned int fDontWait; + bool bDontProtect; + bool bShutdown; + bool bSecCallback; + bool bConsole; + }; + + ParseOpts(char* valid_opts); + ParseOpts(); + ~ParseOpts(); + void SetValidOpts(char* valid_opts); + void Parse(Opts& opts, int argc, char **argv); + +private: + bool IsValidOpt(char ch); + void PrintOpt(char ch, char* text); + void UsageOpts(char* program, int code = 0); + + char m_ValidOpts[256]; +}; diff --git a/src/ccapi/common/win/OldCC/secure.cxx b/src/ccapi/common/win/OldCC/secure.cxx new file mode 100644 index 000000000..a32235fd6 --- /dev/null +++ b/src/ccapi/common/win/OldCC/secure.cxx @@ -0,0 +1,161 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include "secure.hxx" + +extern "C" { +#include "cci_debugging.h" + } + +CcOsLock SecureClient::s_lock; +DWORD SecureClient::s_refcount = 0; +DWORD SecureClient::s_error = 0; +HANDLE SecureClient::s_hToken = 0; + +#include "util.h" + +#define SC "SecureClient::" + +DWORD +SecureClient::Attach( + ) +{ + CcAutoLock AL(s_lock); + if (s_hToken) { + s_refcount++; + return 0; + } + if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, + &s_hToken)) { + s_refcount++; + s_error = 0; + } else { + s_hToken = 0; + s_error = GetLastError(); + } + return s_error; +} + +DWORD +SecureClient::Detach( + ) +{ + CcAutoLock AL(s_lock); + s_refcount--; + if (s_refcount) return 0; + if (!s_hToken) return 0; + DWORD error = 0; + if (!CloseHandle(s_hToken)) + error = GetLastError(); + s_hToken = 0; + s_error = 0; + return error; +} + +DWORD SecureClient::Token(HANDLE& hToken) { + // This function will not do automatic initialization. + CcAutoLock AL(s_lock); + hToken = 0; + if (!s_hToken) { + cci_debug_printf("%s no process token initialized (%u)", __FUNCTION__, s_error); + return s_error ? s_error : ERROR_INVALID_HANDLE; + } + else { + DWORD status = 0; + if (!DuplicateHandle(GetCurrentProcess(), s_hToken, + GetCurrentProcess(), &hToken, 0, FALSE, + DUPLICATE_SAME_ACCESS)) { + status = GetLastError(); + cci_debug_printf(" Could not duplicate handle (%u)", status); + } + return status; + } + } + +void +SecureClient::Start(SecureClient*& s) { + s = new SecureClient; +} + +void +SecureClient::Stop(SecureClient*& s) { + delete s; + s = 0; +} + +/////////////////////////////////////////////////////////////////////////////// + +/* This constructor turns off impersonation. + * It is OK for OpenThreadToken to return an error -- that just means impersonation + * is off. + */ +SecureClient::SecureClient(): + m_Error(0), + m_hToken(0), + m_NeedRestore(false) { + + HANDLE hThread = GetCurrentThread(); + HANDLE hThDuplicate; + + int status = DuplicateHandle( GetCurrentProcess(), + hThread, + GetCurrentProcess(), + &hThDuplicate, + TOKEN_ALL_ACCESS, + FALSE, + 0); + if (!status) return; + + if (!OpenThreadToken(hThDuplicate, TOKEN_ALL_ACCESS, FALSE, &m_hToken)) { + m_Error = GetLastError(); + return; + } + if (SetThreadToken(&hThDuplicate, NULL)) { + m_NeedRestore = true; + } else { + m_Error = GetLastError(); + } + CloseHandle(hThDuplicate); + } + +SecureClient::~SecureClient() { + if (m_NeedRestore) { + HANDLE hThread = GetCurrentThread(); + if (!SetThreadToken(&hThread, m_hToken)) { + m_Error = cci_check_error(GetLastError()); + } + } + if (m_hToken) { + if (!CloseHandle(m_hToken)) { + m_Error = cci_check_error(GetLastError()); + } + } + } + +DWORD SecureClient::Error() { + return m_Error; + } \ No newline at end of file diff --git a/src/ccapi/common/win/OldCC/secure.hxx b/src/ccapi/common/win/OldCC/secure.hxx new file mode 100644 index 000000000..009e36c74 --- /dev/null +++ b/src/ccapi/common/win/OldCC/secure.hxx @@ -0,0 +1,60 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#pragma once + +#include +#include "autolock.hxx" + +class SecureClient +{ +public: + static DWORD Attach(); + static DWORD Detach(); + static DWORD Token(HANDLE& hToken); + static void Start(SecureClient*& s); + static void Stop(SecureClient*& s); + +#if 0 + static DWORD CheckImpersonation(); + static bool IsImp(); + static DWORD DuplicateImpAsPrimary(HANDLE& hPrimary); +#endif + + SecureClient(); + ~SecureClient(); + DWORD Error(); + +private: + static CcOsLock s_lock; + static DWORD s_refcount; + static DWORD s_error; + static HANDLE s_hToken; + + DWORD m_Error; + HANDLE m_hToken; + bool m_NeedRestore; +}; diff --git a/src/ccapi/common/win/OldCC/util.cxx b/src/ccapi/common/win/OldCC/util.cxx new file mode 100644 index 000000000..62b204b92 --- /dev/null +++ b/src/ccapi/common/win/OldCC/util.cxx @@ -0,0 +1,519 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include // for _snprintf + +#include "util.h" +#include "secure.hxx" + +extern "C" { +#include "cci_debugging.h" +#include "ccutils.h" + } + + + +void* malloc_alloc_p(size_t size) { + return malloc(size); + } + +void free_alloc_p(void *pptr) { + void **real_pptr = (void**)pptr; + if (*real_pptr) { + free(*real_pptr); + *real_pptr = 0; + } + } + +extern "C" DWORD alloc_textual_sid( + PSID pSid, // binary Sid + LPSTR *pTextualSid // buffer for Textual representaion of Sid + ) { + PSID_IDENTIFIER_AUTHORITY psia; + DWORD dwSubAuthorities; + DWORD dwSidRev = SID_REVISION; + DWORD dwCounter; + DWORD dwSidSize; + + *pTextualSid = 0; + + // + // test if Sid passed in is valid + // + if(!IsValidSid(pSid)) return ERROR_INVALID_PARAMETER; + + // obtain SidIdentifierAuthority + psia = GetSidIdentifierAuthority(pSid); + + // obtain sidsubauthority count + dwSubAuthorities =* GetSidSubAuthorityCount(pSid); + + // + // compute buffer length + // S-SID_REVISION- + identifierauthority- + subauthorities- + NULL + // + dwSidSize = (15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR); + *pTextualSid = (LPSTR)malloc_alloc_p(dwSidSize); + if (!*pTextualSid) + return GetLastError(); + + LPSTR TextualSid = *pTextualSid; + + // + // prepare S-SID_REVISION- + // + wsprintf(TextualSid, TEXT("S-%lu-"), dwSidRev ); + + // + // prepare SidIdentifierAuthority + // + if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) + { + wsprintf(TextualSid + lstrlen(TextualSid), + TEXT("0x%02hx%02hx%02hx%02hx%02hx%02hx"), + (USHORT)psia->Value[0], + (USHORT)psia->Value[1], + (USHORT)psia->Value[2], + (USHORT)psia->Value[3], + (USHORT)psia->Value[4], + (USHORT)psia->Value[5]); + } + else + { + wsprintf(TextualSid + lstrlen(TextualSid), TEXT("%lu"), + (ULONG)(psia->Value[5] ) + + (ULONG)(psia->Value[4] << 8) + + (ULONG)(psia->Value[3] << 16) + + (ULONG)(psia->Value[2] << 24) ); + } + + // + // loop through SidSubAuthorities + // + for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++) + { + wsprintf(TextualSid + lstrlen(TextualSid), TEXT("-%lu"), + *GetSidSubAuthority(pSid, dwCounter) ); + } + return 0; +} + +DWORD alloc_token_user(HANDLE hToken, PTOKEN_USER *pptu) { + DWORD status = 0; + DWORD size = 0; + *pptu = 0; + + GetTokenInformation(hToken, TokenUser, *pptu, 0, &size); + if (size == 0) status = GetLastError(); + + if (!status) { + if (!(*pptu = (PTOKEN_USER)malloc_alloc_p(size))) + status = GetLastError(); + } + + if (!status) { + if (!GetTokenInformation(hToken, TokenUser, *pptu, size, &size)) + status = GetLastError(); + } + + if (status && *pptu) { + free_alloc_p(pptu); + } + return status; + } + +DWORD +alloc_username( + PSID Sid, + LPSTR* pname, + LPSTR* pdomain = 0 + ) +{ + DWORD status = 0; + DWORD name_len = 0; + DWORD domain_len = 0; + SID_NAME_USE snu; + LPSTR name = 0; + LPSTR domain = 0; + + *pname = 0; + if (pdomain) *pdomain = 0; + + LookupAccountSidA(NULL, Sid, 0, &name_len, 0, &domain_len, &snu); + if ((name_len == 0) || (domain_len == 0)) status = GetLastError(); + + if (!status) { + if (!(name = (LPSTR)malloc_alloc_p(name_len))) status = GetLastError(); + } + + if (!status) { + if (!(domain = (LPSTR)malloc_alloc_p(domain_len))) status = GetLastError(); + } + + if (!status) { + if (!LookupAccountSidA(NULL, Sid, name, &name_len, domain, &domain_len, &snu)) status = GetLastError(); + } + + if (status) { + if (name) free_alloc_p(&name); + if (domain) free_alloc_p(&domain); + } + else { + if (pdomain) { + *pname = name; + *pdomain = domain; + } + else { + DWORD size = name_len + domain_len + 1; + *pname = (LPSTR)malloc_alloc_p(size); + if (!*pname) status = GetLastError(); + else _snprintf(*pname, size, "%s\\%s", name, domain); + } + } + return status; + } + +DWORD get_authentication_id(HANDLE hToken, LUID* pAuthId) { + TOKEN_STATISTICS ts; + DWORD len; + + if (!GetTokenInformation(hToken, TokenStatistics, &ts, sizeof(ts), &len)) + return GetLastError(); + *pAuthId = ts.AuthenticationId; + return 0; + } + +DWORD +alloc_name_9x( + LPSTR* pname, + LPSTR postfix + ) +{ + char prefix[] = "krbcc"; + DWORD len = (sizeof(prefix) - 1) + 1 + strlen(postfix) + 1; + + *pname = (LPSTR)malloc_alloc_p(len); + if (!*pname) return GetLastError(); + _snprintf(*pname, len, "%s.%s", prefix, postfix); + return 0; +} + +DWORD alloc_name_NT(LPSTR* pname, LPSTR postfix) { + DWORD status = 0; + HANDLE hToken = 0; + LUID auth_id; +#ifdef _DEBUG + PTOKEN_USER ptu = 0; + LPSTR name = 0; + LPSTR domain = 0; + LPSTR sid = 0; +#endif + char prefix[] = "krbcc"; + // Play it safe and say 3 characters are needed per 8 bits (byte). + // Note that 20 characters are needed for a 64-bit number in + // decimal (plus one for the string termination. + // and include room for sessionId. + char lid[3*sizeof(LUID)+1+5]; + DWORD sessionId; + DWORD len = 0; + + *pname = 0; + + status = SecureClient::Token(hToken); + + if (!status) { + status = get_authentication_id(hToken, &auth_id); + } + + if (!status) { + if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId)) + sessionId = 0; + } + +#ifdef _DEBUG + if (!status) {status = alloc_token_user(hToken, &ptu);} + if (!status) {status = alloc_username(ptu->User.Sid, &name, &domain);} + if (!status) {status = alloc_textual_sid(ptu->User.Sid, &sid);} +#endif + + if (!status) { + _snprintf(lid, sizeof(lid), "%I64u.%u", auth_id, sessionId); + lid[sizeof(lid)-1] = 0; // be safe + + len = (sizeof(prefix) - 1) + 1 + strlen(lid) + 1 + strlen(postfix) + 1; + *pname = (LPSTR)malloc_alloc_p(len); + if (!*pname) status = GetLastError(); + } + + // + // We used to allocate a name of the form: + // "prefix.domain.name.sid.lid.postfix" (usually under 80 + // characters, depending on username). However, XP thought this + // was "invalid" (too long?) for some reason. + // + // Therefore, we now use "prefix.lid.postfix" + // and for Terminal server we use "prefix.lid.sessionId.postfix" + // + + if (!status) { + _snprintf(*pname, len, "%s.%s.%s", prefix, lid, postfix); + } + +#ifdef _DEBUG + if (sid) + free_alloc_p(&sid); + if (name) + free_alloc_p(&name); + if (domain) + free_alloc_p(&domain); + if (ptu) + free_alloc_p(&ptu); +#endif + if (hToken && hToken != INVALID_HANDLE_VALUE) + CloseHandle(hToken); + if (status && *pname) + free_alloc_p(pname); + return status; +} + +extern "C" DWORD alloc_name(LPSTR* pname, LPSTR postfix, BOOL isNT) { + return isNT ? alloc_name_NT(pname, postfix) : + alloc_name_9x(pname, postfix); + } + +extern "C" DWORD alloc_own_security_descriptor_NT(PSECURITY_DESCRIPTOR* ppsd) { + DWORD status = 0; + HANDLE hToken = 0; + PTOKEN_USER ptu = 0; + PSID pSid = 0; + PACL pAcl = 0; + DWORD size = 0; + SECURITY_DESCRIPTOR sd; + + *ppsd = 0; + + if (!status) {status = SecureClient::Token(hToken);} + + // Get SID: + if (!status) {status = alloc_token_user(hToken, &ptu);} + + if (!status) { + size = GetLengthSid(ptu->User.Sid); + pSid = (PSID) malloc_alloc_p(size); + if (!pSid) status = GetLastError(); + } + if (!status) { + if (!CopySid(size, pSid, ptu->User.Sid)) status = GetLastError(); + } + + if (!status) { + // Prepare ACL: + size = sizeof(ACL); + // Add an ACE: + size += sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) + GetLengthSid(pSid); + pAcl = (PACL) malloc_alloc_p(size); + if (!pAcl) status = GetLastError(); + } + + if (!status) { + if (!InitializeAcl(pAcl, size, ACL_REVISION)) status = GetLastError(); + } + + if (!status) { + if (!AddAccessAllowedAce(pAcl, ACL_REVISION, GENERIC_ALL, pSid)) status = GetLastError(); + } + + if (!status) { + // Prepare SD itself: + if (!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) status = GetLastError(); + } + + if (!status) { + if (!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) status = GetLastError(); + } + + if (!status) { + if (!SetSecurityDescriptorOwner(&sd, pSid, FALSE)) status = GetLastError(); + } + + if (!status) { + if (!IsValidSecurityDescriptor(&sd)) status = ERROR_INVALID_PARAMETER; + } + + if (!status) { + // We now have a SD. Let's copy it. + { + // This should not succeed. Instead it should give us the size. + BOOL ok = MakeSelfRelativeSD(&sd, 0, &size); + } + if (size == 0) status = GetLastError(); + } + + if (!status) { + *ppsd = (PSECURITY_DESCRIPTOR) malloc_alloc_p(size); + if (!*ppsd) status = GetLastError(); + } + + if (!status) { + if (!MakeSelfRelativeSD(&sd, *ppsd, &size)) status = GetLastError(); + } + + if (ptu) free_alloc_p(&ptu); + if (pSid) free_alloc_p(&pSid); + if (pAcl) free_alloc_p(&pAcl); + if (hToken && hToken != INVALID_HANDLE_VALUE) CloseHandle(hToken); + if (status && *ppsd) free_alloc_p(ppsd); + return status; +} + +DWORD +alloc_module_file_name( + char* module, + char** pname + ) +{ + const DWORD max = 8192; + DWORD status = 0; + DWORD got = 0; + DWORD size = 512; // use low number to test... + HMODULE h = 0; + BOOL ok = FALSE; + char* name = 0; + + if (!pname) + return ERROR_INVALID_PARAMETER; + *pname = 0; + + h = GetModuleHandle(module); + + if (!h) return GetLastError(); + + // We assume size < max and size > 0 + while (!status && !ok) { + if (size > max) { + // XXX - Assert? + status = ERROR_INVALID_DATA; + continue; + } + if (name) free_alloc_p(&name); + name = (char*)malloc_alloc_p(size + 1); + if (!name) { + status = ERROR_NOT_ENOUGH_MEMORY; + continue; + } + name[size] = 0; + got = GetModuleFileName(h, name, size); + if (!got) { + status = GetLastError(); + // sanity check: + if (!status) { + // XXX - print nasty message...assert? + status = ERROR_INVALID_DATA; + } + continue; + } + // To know we're ok, we need to verify that what we got + // was bigger than GetModuleSize thought it got. + ok = got && (got < size) && !name[got]; + size *= 2; + } + if (status && name) + free_alloc_p(&name); + else + *pname = name; + return status; +} + +DWORD +alloc_module_dir_name( + char* module, + char** pname + ) +{ + DWORD status = alloc_module_file_name(module, pname); + if (!status) { + char* name = *pname; + char* p = name + strlen(name); + while ((p >= name) && (*p != '\\') && (*p != '/')) p--; + if (p < name) { + free_alloc_p(pname); + status = ERROR_INVALID_DATA; + } else { + *p = 0; + } + } + return status; +} + +DWORD +alloc_module_dir_name_with_file( + char* module, + char* file, + char** pname + ) +{ + DWORD status = alloc_module_dir_name(module, pname); + if (!status) { + char* name = *pname; + size_t name_size = strlen(name); + size_t size = name_size + 1 + strlen(file) + 1; + char* result = (char*)malloc_alloc_p(size); + if (!result) { + status = ERROR_NOT_ENOUGH_MEMORY; + free_alloc_p(pname); + } else { + strcpy(result, name); + result[name_size] = '\\'; + strcpy(result + name_size + 1, file); + free_alloc_p(pname); + *pname = result; + } + } + return status; +} + +DWORD alloc_cmdline_2_args(char* prog, + char* arg1, + char* arg2, + char** pname) { + DWORD status = 0; + size_t size = strlen(prog) + strlen(arg1) + strlen(arg2) + 4; + char* result = (char*)malloc_alloc_p(size); + if (!result) { + status = ERROR_NOT_ENOUGH_MEMORY; + } + else { + strcpy(result, prog); + strcat(result, " "); + strcat(result, arg1); + strcat(result, " "); + strcat(result, arg2); + *pname = result; + } + cci_debug_printf("%s made <%s>", __FUNCTION__, result); + return status; + } diff --git a/src/ccapi/common/win/OldCC/util.h b/src/ccapi/common/win/OldCC/util.h new file mode 100644 index 000000000..a51858cd2 --- /dev/null +++ b/src/ccapi/common/win/OldCC/util.h @@ -0,0 +1,89 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __UTIL_H__ +#define __UTIL_H__ + +#ifdef __cplusplus +extern "C" { +#endif +#if 0 +} +#endif + +BOOL isNT(); + +void* +user_allocate( + size_t size + ); + +void +user_free( + void* ptr + ); + +void +free_alloc_p( + void* pptr + ); + +DWORD +alloc_name( + LPSTR* pname, + LPSTR postfix, + BOOL isNT + ); + +DWORD +alloc_own_security_descriptor_NT( + PSECURITY_DESCRIPTOR* ppsd + ); + +DWORD +alloc_module_dir_name( + char* module, + char** pname + ); + +DWORD +alloc_module_dir_name_with_file( + char* module, + char* file, + char** pname + ); + +DWORD alloc_cmdline_2_args( + char* prog, + char* arg1, + char* arg2, + char** pname); + +#ifdef __cplusplus +} +#endif + +#endif /* __UTIL_H__ */ diff --git a/src/ccapi/common/win/cci_os_debugging.c b/src/ccapi/common/win/cci_os_debugging.c new file mode 100644 index 000000000..f1fbb2816 --- /dev/null +++ b/src/ccapi/common/win/cci_os_debugging.c @@ -0,0 +1,39 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include + +#include "cci_os_debugging.h" +#include "win-utils.h" + +/* ------------------------------------------------------------------------ */ + +void cci_os_debug_vprintf (const char *in_format, va_list in_args) { + printf ( "%s %ld ", timestamp(), GetCurrentThreadId() ); + vprintf ( in_format, in_args ); + printf ( "\n" ); + } diff --git a/src/ccapi/common/win/cci_os_identifier.c b/src/ccapi/common/win/cci_os_identifier.c new file mode 100644 index 000000000..7b44fe3e9 --- /dev/null +++ b/src/ccapi/common/win/cci_os_identifier.c @@ -0,0 +1,58 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "cci_common.h" +#include "cci_os_identifier.h" + +#include + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_os_identifier_new_uuid (cci_uuid_string_t *out_uuid_string) { + cc_int32 err = ccNoError; + UUID uuid; + char* uuidStringTemp; + + err = UuidCreate(&uuid); + + if (!err) { + err = UuidToString(&uuid, &uuidStringTemp); + } + + if (!err) { + *out_uuid_string = malloc(1+strlen(uuidStringTemp)); + + if (*out_uuid_string) { + strcpy(*out_uuid_string, uuidStringTemp); + } + + RpcStringFree(&uuidStringTemp); + } + + cci_debug_printf("cci_os_identifier_new_uuid returning %s", *out_uuid_string); + + return cci_check_error (err); + } \ No newline at end of file diff --git a/src/ccapi/common/win/ccs_reply.Acf b/src/ccapi/common/win/ccs_reply.Acf new file mode 100644 index 000000000..89e8abe7a --- /dev/null +++ b/src/ccapi/common/win/ccs_reply.Acf @@ -0,0 +1,31 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +[implicit_handle(handle_t ccs_reply_IfHandle)] + +interface ccs_reply { + [async] ccapi_listen(); + } diff --git a/src/ccapi/common/win/ccs_reply.Idl b/src/ccapi/common/win/ccs_reply.Idl new file mode 100644 index 000000000..4c6f6f304 --- /dev/null +++ b/src/ccapi/common/win/ccs_reply.Idl @@ -0,0 +1,60 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +[ uuid (6E3B5060-CA46-1067-B31A-00DD010662DA), + version(1.0), + pointer_default(unique) +] + +/* This interface sends a cci_stream via rpc. + */ + +interface ccs_reply { + const long HSIZE = sizeof(void*); + +/* The reply from the server to a request from the client: */ +void ccs_rpc_request_reply( + [in] const long rpcmsg, /* Message type */ + [in, size_is(HSIZE)] const char tsphandle[], + [in, string] const char* uuid, + [in] const long srvStartTime, /* Server Start Time */ + [in] const long cbIn, /* Length of buffer */ + [in, size_is(cbIn)] const unsigned char chIn[], /* Data buffer */ + [out] long* status ); /* Return code */ + +void ccs_rpc_connect_reply( + [in] const long rpcmsg, /* Message type */ + [in, size_is(HSIZE)] const char tsphandle[], + [in, string] const char* uuid, + [in] const long srvStartTime, /* Server Start Time */ + [out] long* status ); /* Return code */ + +void ccapi_listen( + handle_t hBinding, + [in] const long rpcmsg, /* Message type */ + [out] long* status ); /* Return code */ + + } diff --git a/src/ccapi/common/win/ccs_request.Acf b/src/ccapi/common/win/ccs_request.Acf new file mode 100644 index 000000000..853a15252 --- /dev/null +++ b/src/ccapi/common/win/ccs_request.Acf @@ -0,0 +1,31 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +[implicit_handle(handle_t ccs_request_IfHandle)] +interface ccs_request +{ + +} diff --git a/src/ccapi/common/win/ccs_request.idl b/src/ccapi/common/win/ccs_request.idl new file mode 100644 index 000000000..bd693142c --- /dev/null +++ b/src/ccapi/common/win/ccs_request.idl @@ -0,0 +1,58 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +[ uuid (906B0CE0-C70B-1067-B317-00DD010662DA), + version(1.0), + pointer_default(unique) +] + +interface ccs_request { + +typedef char CC_CHAR; +typedef unsigned char CC_UCHAR; +typedef int CC_INT32; +typedef unsigned int CC_UINT32; + +const long HSIZE = sizeof(void*); + +void ccs_rpc_request( + [in] const long rpcmsg, /* Message type */ + [in, size_is(HSIZE)] const char tsphandle[], + [in, string] const char* pszUUID, /* Requestor's UUID */ + [in] const long lenRequest, /* Length of buffer */ + [in, size_is(lenRequest)] const char* pszRequest, /* Data buffer */ + [in] const long serverStartTime,/* Which server session we're talking to */ + [out] long* status ); /* Return code */ + +void ccs_rpc_connect( + [in] const long rpcmsg, /* Message type */ + [in, size_is(HSIZE)] const char tsphandle[], + [in, string] const char* pszUUID, /* Requestor's UUID */ + [out] long* status ); /* Return code */ + +CC_UINT32 ccs_authenticate( + [in, string] const CC_CHAR* name ); +} diff --git a/src/ccapi/common/win/tls.c b/src/ccapi/common/win/tls.c new file mode 100644 index 000000000..411d709aa --- /dev/null +++ b/src/ccapi/common/win/tls.c @@ -0,0 +1,71 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "string.h" + +#include "tls.h" + +struct tspdata* new_tspdata(char* uuid, time_t sst) { + struct tspdata* p = (struct tspdata*)malloc(sizeof(struct tspdata)); + if (p) { + memset(p, 0, sizeof(struct tspdata)); + p->_sst = sst; + if (uuid) {strncpy(p->_uuid, uuid, UUID_SIZE-1);} + } + return p; + } + +void delete_tspdata(struct tspdata* p) { + if (p) free(p); + } + +void tspdata_setUUID(struct tspdata* p, unsigned char __RPC_FAR* uuidString) { + strncpy(p->_uuid, uuidString, UUID_SIZE-1); + }; + +void tspdata_setConnected (struct tspdata* p, BOOL b) {p->_CCAPI_Connected = b;} + +void tspdata_setReplyEvent(struct tspdata* p, HANDLE h) {p->_replyEvent = h;} + +void tspdata_setRpcAState (struct tspdata* p, RPC_ASYNC_STATE* rpcState) { + p->_rpcState = rpcState;} + +void tspdata_setSST (struct tspdata* p, time_t t) {p->_sst = t;} + +void tspdata_setStream (struct tspdata* p, cci_stream_t s) {p->_stream = s;} + + +BOOL tspdata_getConnected (struct tspdata* p) {return p->_CCAPI_Connected;} + +HANDLE tspdata_getReplyEvent(struct tspdata* p) {return p->_replyEvent;} + +time_t tspdata_getSST (const struct tspdata* p) {return p->_sst;} + +cci_stream_t tspdata_getStream (const struct tspdata* p) {return p->_stream;} + +char* tspdata_getUUID (const struct tspdata* p) {return p->_uuid;} + +RPC_ASYNC_STATE* tspdata_getRpcAState (const struct tspdata* p) {return p->_rpcState;} diff --git a/src/ccapi/common/win/tls.h b/src/ccapi/common/win/tls.h new file mode 100644 index 000000000..b18705e84 --- /dev/null +++ b/src/ccapi/common/win/tls.h @@ -0,0 +1,70 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +/* Thread local storage for client threads. */ + +#ifndef _tls_h +#define _tls_h + +#include "windows.h" +#include "time.h" + +#include "cci_stream.h" + +#define UUID_SIZE 128 + +/* The client code can be run in any client thread. The thread-specific data + is defined here. + */ + +struct tspdata { + BOOL _CCAPI_Connected; + RPC_ASYNC_STATE* _rpcState; + HANDLE _replyEvent; + time_t _sst; + cci_stream_t _stream; + char _uuid[UUID_SIZE]; + }; + +struct tspdata* new_tspdata (char* uuid, time_t sst); +void delete_tspdata (struct tspdata* p); + +void tspdata_setConnected (struct tspdata* p, BOOL b); +void tspdata_setReplyEvent(struct tspdata* p, HANDLE h); +void tspdata_setRpcAState (struct tspdata* p, RPC_ASYNC_STATE* rpcState); +void tspdata_setSST (struct tspdata* p, time_t t); +void tspdata_setStream (struct tspdata* p, cci_stream_t s); +void tspdata_setUUID (struct tspdata* p, unsigned char __RPC_FAR* uuidString); +HANDLE tspdata_getReplyEvent(const struct tspdata* p); + +BOOL tspdata_getConnected(const struct tspdata* p); +RPC_ASYNC_STATE* tspdata_getRpcAState(const struct tspdata* p); +time_t tspdata_getSST (const struct tspdata* p); +cci_stream_t tspdata_getStream (const struct tspdata* p); +char* tspdata_getUUID (const struct tspdata* p); + + +#endif _tls_h diff --git a/src/ccapi/common/win/win-utils.c b/src/ccapi/common/win/win-utils.c new file mode 100644 index 000000000..c082142b0 --- /dev/null +++ b/src/ccapi/common/win/win-utils.c @@ -0,0 +1,66 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include +#include "windows.h" + +#include "win-utils.h" +#include "cci_debugging.h" + +#pragma warning (disable : 4996) + +#define UUID_SIZE 128 + +char* clientPrefix = "CCAPI_CLIENT_"; +char* serverPrefix = "CCS_LISTEN_"; +unsigned char* pszProtocolSequence = "ncalrpc"; + +#define MAX_TIMESTAMP 40 +char _ts[MAX_TIMESTAMP]; + +char* clientEndpoint(const char* UUID) { + char* _clientEndpoint = (char*)malloc(strlen(UUID) + strlen(clientPrefix) + 2); + strcpy(_clientEndpoint, clientPrefix); + strncat(_clientEndpoint, UUID, UUID_SIZE); +// cci_debug_printf("%s returning %s", __FUNCTION__, _clientEndpoint); + return _clientEndpoint; + } + +char* serverEndpoint(const char* user) { + char* _serverEndpoint = (char*)malloc(strlen(user) + strlen(serverPrefix) + 2); + strcpy(_serverEndpoint, serverPrefix); + strncat(_serverEndpoint, user, UUID_SIZE); + return _serverEndpoint; + } + +char* timestamp() { + SYSTEMTIME _stime; + GetSystemTime(&_stime); + GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &_stime, "HH:mm:ss", _ts, sizeof(_ts)-1); + return _ts; + } \ No newline at end of file diff --git a/src/ccapi/common/win/win-utils.h b/src/ccapi/common/win/win-utils.h new file mode 100644 index 000000000..97226e90b --- /dev/null +++ b/src/ccapi/common/win/win-utils.h @@ -0,0 +1,55 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef _win_utils_h +#define _win_utils_h + +#ifndef TRUE +#define TRUE (1==1) +#endif + +#ifndef FALSE +#define FALSE (1==0) +#endif + +static enum ccapiMsgType { + CCMSG_INVALID = 0, + CCMSG_CONNECT, + CCMSG_REQUEST, + CCMSG_CONNECT_REPLY, + CCMSG_REQUEST_REPLY, + CCMSG_DISCONNECT, + CCMSG_LISTEN, + CCMSG_PING + }; + +char* clientEndpoint(const char* UUID); +char* serverEndpoint(const char* UUID); +extern unsigned char* pszProtocolSequence; + +char* timestamp(); + +#endif // _win_utils_h \ No newline at end of file diff --git a/src/ccapi/lib/win/Makefile b/src/ccapi/lib/win/Makefile new file mode 100644 index 000000000..4bdd98df7 --- /dev/null +++ b/src/ccapi/lib/win/Makefile @@ -0,0 +1,116 @@ +!include + +# . is ...\pismere\athena\auth\krb5\src\ccapi\lib\win +CCAPI = ..\.. +CO = $(CCAPI)\common +COWIN = $(CCAPI)\common\win +CCUTIL = $(CCAPI)\common\win\OldCC +LIBDIR = $(CCAPI)\lib +LIBWIN = $(LIBDIR)\win +K5SRC = $(CCAPI)\.. +POSIX = $(K5SRC)\lib\krb5\posix +OLDCC = $(LIBWIN)\OldCC + +INC = -I.. -I$(CO) -I$(COWIN) -I$(K5SRC)\include -I..\..\..\util\et -I$(OLDCC) \ + -I$(LIBWIN) -I$(CCUTIL) +MIDLI = /I $(K5SRC)\include /I. /I$(COWIN) /I$(CO) + +!if "$(CPU)" == "i386" +cflags = $(cflags) /EHsc /MDd -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 \ +$(INC) -D_CRT_SECURE_NO_WARNINGS +!else +cflags = $(cflags) /W3 -D_CRTAPI1= -D_CRTAPI2= $(INC) +!endif + +!if "$(PREPROCESS)" == "P" +cflags = $(cflags) -P +!endif + +all : ccapi.dll + +common = cci_array_internal.obj cci_cred_union.obj cci_debugging.obj cci_identifier.obj \ + cci_message.obj cci_stream.obj + +commonwin = cci_os_debugging.obj \ + cci_os_identifier.obj \ + tls.obj \ + win-utils.obj + +dll = ccapi_ccache.obj \ + ccapi_ccache_iterator.obj \ + ccapi_context.obj \ + ccapi_context_change_time.obj \ + ccapi_credentials.obj \ + ccapi_credentials_iterator.obj \ + ccapi_ipc.obj \ + ccapi_string.obj + +dllwin = ccs_reply_s.obj \ + ccs_reply_proc.obj \ + ccs_request_c.obj + +dllwincxx = ccapi_os_ipc.obj \ + dllmain.obj + +oldcc = client.obj \ + rpc.obj + +utils = ccutils.obj + +utilscxx = init.obj \ + secure.obj \ + util.obj + + +linkobjs = $(common) $(commonwin) $(dll) $(dllwin) $(dllwincxx) $(oldcc) $(utils) $(utilscxx) + +#includes = + +# Main program: +ccapi.dll : $(linkobjs) ccapi.def + $(link) $(linkdebug) $(conflags) -out:ccapi.dll /DEF:ccapi.def /implib:ccapi.lib $(dlllflags) \ + $(linkobjs) rpcrt4.lib kernel32.lib user32.lib $(conlibsdll) + + +ccs_request.h ccs_request_c.c ccs_request_s.c : $(COWIN)\ccs_request.idl $(COWIN)\ccs_request.acf + midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(cc) -cpp_opt "-E" \ + $(COWIN)\ccs_request.idl + +ccs_reply.h ccs_reply_c.c ccs_reply_s.c : $(COWIN)\ccs_reply.idl $(COWIN)\ccs_reply.acf + midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(cc) -cpp_opt "-E" -I. -I$(COWIN) \ + $(COWIN)\ccs_reply.idl + +$(common) : $(CO)\$*.c + $(cc) $(cdebug) $(cflags) $(cvarsdll) $(CO)\$*.c + +$(commonwin) : $(COWIN)\$*.c + $(cc) $(cdebug) $(cflags) $(cvarsdll) $(COWIN)\$*.c + +$(dll) : $(LIBDIR)\$*.c + $(cc) $(cdebug) $(cflags) $(cvarsdll) $(LIBDIR)\$*.c + +$(dllwin) : $*.c ccs_reply.h ccs_request.h + $(cc) $(cdebug) $(cflags) $(cvarsdll) $(LIBWIN)\$*.c + +$(dllwincxx) : $*.cxx ccs_reply.h ccs_request.h + $(cc) $(cdebug) $(cflags) $(cvarsdll) $(LIBWIN)\$*.cxx + +$(oldcc) : $(OLDCC)\$*.cxx + $(cc) $(cdebug) $(cflags) $(cvarsdll) $(OLDCC)\$*.cxx + +$(utils) : $(CCUTIL)\$*.c + $(cc) $(cdebug) $(cflags) $(cvarsdll) $(CCUTIL)\$*.c + +$(utilscxx) : $(CCUTIL)\$*.cxx + $(cc) $(cdebug) $(cflags) $(cvarsdll) $(CCUTIL)\$*.cxx + + + +# Clean up everything +cleanall : clean + -del *.dll + +# Clean up everything but the .EXEs +clean : + -del *.obj + -del *.map diff --git a/src/ccapi/lib/win/OldCC/ccapi.h b/src/ccapi/lib/win/OldCC/ccapi.h new file mode 100644 index 000000000..65a72edb4 --- /dev/null +++ b/src/ccapi/lib/win/OldCC/ccapi.h @@ -0,0 +1,284 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 6.00.0366 */ +/* at Fri Nov 30 10:06:16 2007 + */ +/* Compiler settings for ccapi.idl: + Oic, W1, Zp8, env=Win32 (32b run) + protocol : dce , ms_ext, c_ext, oldnames + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +//@@MIDL_FILE_HEADING( ) + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 440 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __ccapi_h__ +#define __ccapi_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifdef __cplusplus +extern "C"{ +#endif + +void * __RPC_USER MIDL_user_allocate(size_t); +void __RPC_USER MIDL_user_free( void * ); + +#ifndef __ccapi_INTERFACE_DEFINED__ +#define __ccapi_INTERFACE_DEFINED__ + +/* interface ccapi */ +/* [implicit_handle][unique][version][uuid] */ + +typedef /* [context_handle] */ struct opaque_handle_CTX *HCTX; + +typedef /* [context_handle] */ struct opaque_handle_CACHE *HCACHE; + +typedef /* [context_handle] */ struct opaque_handle_CACHE_ITER *HCACHE_ITER; + +typedef /* [context_handle] */ struct opaque_handle_CRED_ITER *HCRED_ITER; + +typedef unsigned char CC_CHAR; + +typedef unsigned char CC_UCHAR; + +typedef int CC_INT32; + +typedef unsigned int CC_UINT32; + +typedef CC_INT32 CC_TIME_T; + + +enum __MIDL_ccapi_0001 + { STK_AFS = 0, + STK_DES = 1 + } ; + +enum __MIDL_ccapi_0002 + { CC_API_VER_1 = 1, + CC_API_VER_2 = 2 + } ; + +enum __MIDL_ccapi_0003 + { KRB_NAME_SZ = 40, + KRB_INSTANCE_SZ = 40, + KRB_REALM_SZ = 40, + MAX_V4_CRED_LEN = 1250 + } ; +typedef struct _NC_INFO + { + /* [string] */ CC_CHAR *name; + /* [string] */ CC_CHAR *principal; + CC_INT32 vers; + } NC_INFO; + +typedef struct _NC_INFO_LIST + { + CC_UINT32 length; + /* [size_is] */ NC_INFO *info; + } NC_INFO_LIST; + +typedef struct _V4_CRED + { + CC_UCHAR kversion; + CC_CHAR principal[ 41 ]; + CC_CHAR principal_instance[ 41 ]; + CC_CHAR service[ 41 ]; + CC_CHAR service_instance[ 41 ]; + CC_CHAR realm[ 41 ]; + CC_UCHAR session_key[ 8 ]; + CC_INT32 kvno; + CC_INT32 str_to_key; + CC_INT32 issue_date; + CC_INT32 lifetime; + CC_UINT32 address; + CC_INT32 ticket_sz; + CC_UCHAR ticket[ 1250 ]; + } V4_CRED; + +typedef struct _CC_DATA + { + CC_UINT32 type; + CC_UINT32 length; + /* [size_is] */ CC_UCHAR *data; + } CC_DATA; + +typedef struct _CC_DATA_LIST + { + CC_UINT32 count; + /* [size_is] */ CC_DATA *data; + } CC_DATA_LIST; + +typedef struct _V5_CRED + { + /* [string] */ CC_CHAR *client; + /* [string] */ CC_CHAR *server; + CC_DATA keyblock; + CC_TIME_T authtime; + CC_TIME_T starttime; + CC_TIME_T endtime; + CC_TIME_T renew_till; + CC_UINT32 is_skey; + CC_UINT32 ticket_flags; + CC_DATA_LIST addresses; + CC_DATA ticket; + CC_DATA second_ticket; + CC_DATA_LIST authdata; + } V5_CRED; + +typedef /* [switch_type] */ union _CRED_PTR_UNION + { + /* [case()] */ V4_CRED *pV4Cred; + /* [case()] */ V5_CRED *pV5Cred; + } CRED_PTR_UNION; + +typedef struct _CRED_UNION + { + CC_INT32 cred_type; + /* [switch_is] */ CRED_PTR_UNION cred; + } CRED_UNION; + +CC_INT32 rcc_initialize( + /* [out] */ HCTX *pctx); + +CC_INT32 rcc_shutdown( + /* [out][in] */ HCTX *pctx); + +CC_INT32 rcc_get_change_time( + /* [in] */ HCTX ctx, + /* [out] */ CC_TIME_T *time); + +CC_INT32 rcc_create( + /* [in] */ HCTX ctx, + /* [string][in] */ const CC_CHAR *name, + /* [string][in] */ const CC_CHAR *principal, + /* [in] */ CC_INT32 vers, + /* [in] */ CC_UINT32 flags, + /* [out] */ HCACHE *pcache); + +CC_INT32 rcc_open( + /* [in] */ HCTX ctx, + /* [string][in] */ const CC_CHAR *name, + /* [in] */ CC_INT32 vers, + /* [in] */ CC_UINT32 flags, + /* [out] */ HCACHE *pcache); + +CC_INT32 rcc_close( + /* [out][in] */ HCACHE *pcache); + +CC_INT32 rcc_destroy( + /* [out][in] */ HCACHE *pcache); + +CC_INT32 rcc_seq_fetch_NCs_begin( + /* [in] */ HCTX ctx, + /* [out] */ HCACHE_ITER *piter); + +CC_INT32 rcc_seq_fetch_NCs_end( + /* [out][in] */ HCACHE_ITER *piter); + +CC_INT32 rcc_seq_fetch_NCs_next( + /* [in] */ HCACHE_ITER iter, + /* [out] */ HCACHE *pcache); + +CC_INT32 rcc_seq_fetch_NCs( + /* [in] */ HCTX ctx, + /* [out][in] */ HCACHE_ITER *piter, + /* [out] */ HCACHE *pcache); + +CC_INT32 rcc_get_NC_info( + /* [in] */ HCTX ctx, + /* [out] */ NC_INFO_LIST **info_list); + +CC_INT32 rcc_get_name( + /* [in] */ HCACHE cache, + /* [string][out] */ CC_CHAR **name); + +CC_INT32 rcc_set_principal( + /* [in] */ HCACHE cache, + /* [in] */ CC_INT32 vers, + /* [string][in] */ const CC_CHAR *principal); + +CC_INT32 rcc_get_principal( + /* [in] */ HCACHE cache, + /* [string][out] */ CC_CHAR **principal); + +CC_INT32 rcc_get_cred_version( + /* [in] */ HCACHE cache, + /* [out] */ CC_INT32 *vers); + +CC_INT32 rcc_lock_request( + /* [in] */ HCACHE cache, + /* [in] */ CC_INT32 lock_type); + +CC_INT32 rcc_store( + /* [in] */ HCACHE cache, + /* [in] */ CRED_UNION cred); + +CC_INT32 rcc_remove_cred( + /* [in] */ HCACHE cache, + /* [in] */ CRED_UNION cred); + +CC_INT32 rcc_seq_fetch_creds( + /* [in] */ HCACHE cache, + /* [out][in] */ HCRED_ITER *piter, + /* [out] */ CRED_UNION **cred); + +CC_INT32 rcc_seq_fetch_creds_begin( + /* [in] */ HCACHE cache, + /* [out] */ HCRED_ITER *piter); + +CC_INT32 rcc_seq_fetch_creds_end( + /* [out][in] */ HCRED_ITER *piter); + +CC_INT32 rcc_seq_fetch_creds_next( + /* [in] */ HCRED_ITER iter, + /* [out] */ CRED_UNION **cred); + +CC_UINT32 Connect( + /* [string][in] */ CC_CHAR *name); + +void Shutdown( void); + + +extern handle_t ccapi_IfHandle; + + +extern RPC_IF_HANDLE ccapi_ClientIfHandle; +extern RPC_IF_HANDLE ccapi_ServerIfHandle; +#endif /* __ccapi_INTERFACE_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +void __RPC_USER HCTX_rundown( HCTX ); +void __RPC_USER HCACHE_rundown( HCACHE ); +void __RPC_USER HCACHE_ITER_rundown( HCACHE_ITER ); +void __RPC_USER HCRED_ITER_rundown( HCRED_ITER ); + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/src/ccapi/lib/win/OldCC/client.cxx b/src/ccapi/lib/win/OldCC/client.cxx new file mode 100644 index 000000000..1f9051093 --- /dev/null +++ b/src/ccapi/lib/win/OldCC/client.cxx @@ -0,0 +1,389 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "stdio.h" // KPKDBG + +#include "ccs_request.h" + +#include "ccapi.h" +#include "util.h" + +extern "C" { +#include "cci_debugging.h" +#include "tls.h" // KPKDBG + } + +#include "client.h" +#include "init.hxx" +#include "name.h" +#include "secure.hxx" + +#define SECONDS_TO_WAIT 10 + +#define STARTUP "CLIENT STARTUP: " +#define DISCONNECT "CLIENT DISCONNECT: " + +bool Client::s_init = false; +CcOsLock Client::sLock; + +static DWORD bind_client(char* ep OPTIONAL, Init::InitInfo& info, LPSTR* endpoint) { + DWORD status = 0; + unsigned char * pszStringBinding = NULL; + + if (!ep) { + status = alloc_name(endpoint, "ep", isNT()); + } + else { + *endpoint = ep; + } + + if (!status) { + /* Use a convenience function to concatenate the elements of */ + /* the string binding into the proper sequence. */ + status = RpcStringBindingCompose(0, // uuid + (unsigned char*)"ncalrpc", // protseq + 0, // address + (unsigned char*)(*endpoint), // endpoint + 0, // options + &pszStringBinding); + cci_check_error(status); + } + + if (!status) { + /* Set the binding handle that will be used to bind to the server. */ + status = RpcBindingFromStringBinding(pszStringBinding, &ccs_request_IfHandle); + cci_check_error(status); + } + + if (!status) { + // Win9x might call RpcBindingSetAuthInfo (not Ex), but it does not + // quite work on Win9x... + if (isNT()) { + RPC_SECURITY_QOS qos; + qos.Version = RPC_C_SECURITY_QOS_VERSION; + qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT; + qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC; + qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY; + + status = info.fRpcBindingSetAuthInfoEx(ccs_request_IfHandle, + 0, // principal + RPC_C_AUTHN_LEVEL_CONNECT, + RPC_C_AUTHN_WINNT, + 0, // current address space + RPC_C_AUTHZ_NAME, + &qos); + cci_check_error(status); + } + } + + if (pszStringBinding) { + DWORD status = RpcStringFree(&pszStringBinding); + cci_check_error(status); + } + return cci_check_error(status); + } + +DWORD find_server(Init::InitInfo& info, LPSTR endpoint) { + DWORD status = 0; + LPSTR event_name = 0; + HANDLE hEvent = 0; + SECURITY_ATTRIBUTES sa = { 0 }; + PSECURITY_ATTRIBUTES psa = 0; + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + char* szExe = 0; + char* szDir = 0; + BOOL bRes = FALSE; + char* cmdline = NULL; +#if 0 + HANDLE hToken = 0; +#endif + + psa = isNT() ? &sa : 0; + +// cci_debug_printf("%s Looking for server; ccs_request_IfHandle:0x%X", __FUNCTION__, ccs_request_IfHandle); + status = cci_check_error(RpcMgmtIsServerListening(ccs_request_IfHandle)); + if (status == RPC_S_NOT_LISTENING) { +// cci_debug_printf(" Server *NOT* found!"); + si.cb = sizeof(si); + + status = alloc_module_dir_name(CCAPI_DLL, &szDir); + + if (!status) { + status = alloc_module_dir_name_with_file(CCAPI_DLL, CCAPI_EXE, &szExe); + } + + if (!status) { + status = alloc_name(&event_name, "startup", isNT()); + cci_check_error(status); + } + + if (!status) { + if (isNT()) { + sa.nLength = sizeof(sa); + status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor); + cci_check_error(status); + } + } + + if (!status) { + hEvent = CreateEvent(psa, FALSE, FALSE, event_name); + cci_debug_printf(" CreateEvent(... %s) returned hEvent 0x%X", event_name, hEvent); + if (!hEvent) status = GetLastError(); + } + + if (!status) { + +#if 0 + if (SecureClient::IsImp()) { + cci_debug_printf(STARTUP "Token is impersonation token")); + SecureClient::DuplicateImpAsPrimary(hToken); + } + else { + cci_debug_printf(STARTUP "Token is NOT impersonation token")); + } +#endif + +#if 0 + if (hToken) + bRes = CreateProcessAsUser(hToken, + szExe, // app name + NULL, // cmd line + psa, // SA + psa, // SA + FALSE, + CREATE_NEW_PROCESS_GROUP | + //CREATE_NEW_CONSOLE | + NORMAL_PRIORITY_CLASS | + // CREATE_NO_WINDOW | + DETACHED_PROCESS | + 0 + , + NULL, // environment + szDir, // current dir + &si, + &pi); + else +#endif + alloc_cmdline_2_args(szExe, endpoint, "-D", &cmdline); + bRes = CreateProcess( szExe, // app name + NULL, //cmdline, // cmd line is + psa, // SA + psa, // SA + FALSE, + CREATE_NEW_PROCESS_GROUP | + CREATE_NEW_CONSOLE | + NORMAL_PRIORITY_CLASS | + // CREATE_NO_WINDOW | + // DETACHED_PROCESS | /* KPK TODO: was set - restore */ + 0 + , + NULL, // environment + szDir, // current dir + &si, + &pi); + if (!bRes) { + status = GetLastError(); + cci_debug_printf(" CreateProcess returned %d; LastError: %d", bRes, status); + } + cci_debug_printf(" Waiting..."); + } + cci_check_error(status); + + if (!status) { + status = WaitForSingleObject(hEvent, (SECONDS_TO_WAIT)*1000); + status = RpcMgmtIsServerListening(ccs_request_IfHandle); + } + } + else if (status) { + cci_debug_printf(" unexpected error while looking for server: 0D%d / 0U%u / 0X%X", status, status, status); + } + +#if 0 + if (hToken) + CloseHandle(hToken); +#endif + if (szDir) free_alloc_p(&szDir); + if (szExe) free_alloc_p(&szExe); + if (hEvent) CloseHandle(hEvent); + if (pi.hThread) CloseHandle(pi.hThread); + if (pi.hProcess) CloseHandle(pi.hProcess); + if (sa.lpSecurityDescriptor) free_alloc_p(&sa.lpSecurityDescriptor); + return cci_check_error(status); + +} + +static +DWORD +authenticate_server(Init::InitInfo& info) { + DWORD challenge = 17; // XXX - maybe use random number + DWORD desired_response= challenge + 1; + HANDLE hMap = 0; + LPSTR mem_name = 0; + PDWORD pvalue = 0; + CC_UINT32 response = 0; + SECURITY_ATTRIBUTES sa = { 0 }; + DWORD status = 0; + + cci_debug_printf("%s entry", __FUNCTION__); + + status = alloc_name(&mem_name, "auth", isNT()); + cci_check_error(status); + + if (!status) { + if (isNT()) { + sa.nLength = sizeof(sa); + status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor); + } + } + cci_check_error(status); + + if (!status) { + hMap = CreateFileMapping(INVALID_HANDLE_VALUE, isNT() ? &sa : 0, + PAGE_READWRITE, 0, sizeof(DWORD), mem_name); + if (!hMap) + status = GetLastError(); + } + cci_check_error(status); + + if (!status) { + pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0); + if (!pvalue) status = GetLastError(); + } + cci_check_error(status); + + if (!status) { + *pvalue = challenge; + + RpcTryExcept { + response = ccs_authenticate( (CC_CHAR*)mem_name ); + } + RpcExcept(1) { + status = RpcExceptionCode(); + cci_check_error(status); + } + RpcEndExcept; + } + cci_check_error(status); + + if (!status) { + // Check response + if ((response != desired_response) && (*pvalue != desired_response)) { + cci_debug_printf(" Could not authenticate server."); + status = ERROR_ACCESS_DENIED; // XXX - CO_E_NOMATCHINGSIDFOUND? + } + else { + cci_debug_printf(" Server authenticated!"); + } + cci_check_error(status); + } + + free_alloc_p(&mem_name); + free_alloc_p(&sa.lpSecurityDescriptor); + if (pvalue) { + BOOL ok = UnmapViewOfFile(pvalue); +// DEBUG_ASSERT(ok); + } + if (hMap) CloseHandle(hMap); + return status; +} + +DWORD +Client::Disconnect() { + DWORD status = 0; + if (ccs_request_IfHandle) { + /* The calls to the remote procedures are complete. */ + /* Free the binding handle */ + status = RpcBindingFree(&ccs_request_IfHandle); + } + s_init = false; + return status; + } + +DWORD +Client::Connect(char* ep OPTIONAL) { + LPSTR endpoint = 0; + DWORD status = 0; + + if (!ccs_request_IfHandle) { + Init::InitInfo info; + + status = Init::Info(info); + cci_check_error(status); + + if (!status) { + status = bind_client(ep, info, &endpoint); + cci_check_error(status); + } + + if (!status) { + status = find_server(info, endpoint); + cci_check_error(status); + } + + if (!status) { + status = authenticate_server(info); + cci_check_error(status); + } + } + + + if (endpoint && (endpoint != ep)) free_alloc_p(&endpoint); + + if (status) Client::Disconnect(); + return status; + } + +DWORD Client::Initialize(char* ep OPTIONAL) { + CcAutoLock AL(Client::sLock); + SecureClient s; + ccs_request_IfHandle = NULL; + if (s_init) return 0; + DWORD status = Client::Connect(ep); + if (!status) s_init = true; + return status; + } + +DWORD Client::Cleanup() { + CcAutoLock AL(Client::sLock); + SecureClient s; + return Client::Disconnect(); + } + +DWORD Client::Reconnect(char* ep OPTIONAL) { + CcAutoLock AL(Client::sLock); + SecureClient s; + DWORD status = 0; + + if (Initialized()) { + DWORD status = Client::Cleanup(); + } + if ( (!status) ) { + status = Client::Initialize(ep); + } + + return status; + } diff --git a/src/ccapi/lib/win/OldCC/client.h b/src/ccapi/lib/win/OldCC/client.h new file mode 100644 index 000000000..f263ce1c0 --- /dev/null +++ b/src/ccapi/lib/win/OldCC/client.h @@ -0,0 +1,61 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef __DLL_CLIENT_H__ +#define __DLL_CLIENT_H__ + +#include "autolock.hxx" +#include "init.hxx" + +class Client { +public: + static DWORD Initialize(char* ep OPTIONAL); + static DWORD Cleanup(); + static DWORD Reconnect(char* ep OPTIONAL); + + static bool Initialized() { return s_init; } + + static CcOsLock sLock; + +private: + static bool s_init; + + static DWORD Disconnect(); + static DWORD Connect(char* ep OPTIONAL); + }; + +#define CLIENT_INIT_EX(trap, error) \ +do \ +{ \ + INIT_INIT_EX(trap, error); \ + if (!Client::Initialized()) \ + { \ + DWORD status = Client::Initialize(0); \ + if (status) return (trap) ? (error) : status; \ + } \ +} while(0) + +#endif diff --git a/src/ccapi/lib/win/OldCC/rpc.cxx b/src/ccapi/lib/win/OldCC/rpc.cxx new file mode 100644 index 000000000..332f1c503 --- /dev/null +++ b/src/ccapi/lib/win/OldCC/rpc.cxx @@ -0,0 +1,79 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include + +extern "C" { +#include "CredentialsCache.h" +#include "secure.hxx" +#include "client.h" +#include "autolock.hxx" +#include "cci_debugging.h" + } + +extern HANDLE hCCAPIv2Mutex; + +#define MAKE_RPC_CALL(rc, x) \ +do { \ + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); \ + SecureClient* s = 0; \ + SecureClient::Start(s); \ + CcAutoLock* a = 0; \ + CcAutoLock::Start(a, Client::sLock); \ + RpcTryExcept { \ + cci_debug_printf("RpcTry: #x"); \ + x; \ + } \ + RpcExcept(1) { \ + rc = handle_exception(RpcExceptionCode()); \ + } \ + RpcEndExcept; \ + CcAutoLock::Stop(a); \ + SecureClient::Stop(s); \ + ReleaseMutex( hCCAPIv2Mutex ); \ +} while (0) + +static +DWORD +handle_exception(DWORD code) { + cci_debug_printf("Runtime reported exception %u", code); + if (code == RPC_S_SERVER_UNAVAILABLE) { + Client::Reconnect(0); + } + return 4; + } + +////////////////////////////////////////////////////////////////////////////// + +cc_int32 cc_initialize() { + + CLIENT_INIT_EX(true, 4); + cc_int32 rc = ccNoError; + + MAKE_RPC_CALL(rc, rc = 5); + return rc; + } \ No newline at end of file diff --git a/src/ccapi/lib/win/WINCCAPI.sln b/src/ccapi/lib/win/WINCCAPI.sln new file mode 100644 index 000000000..985f4c610 --- /dev/null +++ b/src/ccapi/lib/win/WINCCAPI.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WINCCAPI", "WINCCAPI.vcproj", "{1137FC16-E53E-48C1-8293-085B4BE68C32}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1137FC16-E53E-48C1-8293-085B4BE68C32}.Debug|Win32.ActiveCfg = Debug|Win32 + {1137FC16-E53E-48C1-8293-085B4BE68C32}.Debug|Win32.Build.0 = Debug|Win32 + {1137FC16-E53E-48C1-8293-085B4BE68C32}.Release|Win32.ActiveCfg = Release|Win32 + {1137FC16-E53E-48C1-8293-085B4BE68C32}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/ccapi/lib/win/WINCCAPI.vcproj b/src/ccapi/lib/win/WINCCAPI.vcproj new file mode 100644 index 000000000..69b7722e8 --- /dev/null +++ b/src/ccapi/lib/win/WINCCAPI.vcproj @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ccapi/lib/win/ccapi.def b/src/ccapi/lib/win/ccapi.def new file mode 100644 index 000000000..0450331ec --- /dev/null +++ b/src/ccapi/lib/win/ccapi.def @@ -0,0 +1,39 @@ +;LIBRARY COMERR32 +HEAPSIZE 8192 + +EXPORTS + cci_debug_printf + + cc_initialize + + cci_string_new + cci_string_d_initializer + ccapi_string_release + + cci_credentials_iterator_new + cci_credentials_iterator_write + + cci_ccache_iterator_new + cci_ccache_iterator_write + + ccapi_ccache_iterator_release + ccapi_ccache_iterator_next + ccapi_ccache_iterator_clone + + ccapi_credentials_iterator_release + ccapi_credentials_iterator_next + ccapi_credentials_iterator_clone + +;debugging: + _cci_check_error + cci_os_ipc + cci_os_ipc_msg + cci_os_ipc_thread_init + cci_stream_data + cci_stream_write + cci_stream_new + + ccs_authenticate + + + \ No newline at end of file diff --git a/src/ccapi/lib/win/ccapi_os_ipc.cxx b/src/ccapi/lib/win/ccapi_os_ipc.cxx new file mode 100644 index 000000000..7ee917627 --- /dev/null +++ b/src/ccapi/lib/win/ccapi_os_ipc.cxx @@ -0,0 +1,373 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +extern "C" { +#include "k5-thread.h" +#include "ccapi_os_ipc.h" +#include "tls.h" +#include "dllmain.h" +#include "ccs_reply.h" +#include "ccs_request.h" +#include "win-utils.h" +#include "ccutils.h" +#include "util.h" + } + +#include "CredentialsCache.h" +#include "secure.hxx" +#include "opts.hxx" +#include "client.h" +#include "autolock.hxx" +#include "cci_debugging.h" + +#define SECONDS_TO_WAIT 10 +#define CLIENT_REQUEST_RPC_HANDLE ccs_request_IfHandle + +extern HANDLE hCCAPIv2Mutex; +ParseOpts::Opts opts = { 0 }; +PSECURITY_ATTRIBUTES psa = 0; +SECURITY_ATTRIBUTES sa = { 0 }; + +/* The layout of the rest of this module: + + The entrypoints defined in ccs_os_ipc.h: + cci_os_ipc_thread_init + cci_os_ipc + + Other routines needed by those four. + cci_os_connect + handle_exception + */ + +cc_int32 ccapi_connect(const struct tspdata* tsp); +static DWORD handle_exception(DWORD code); + +extern "C" { +cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, + cci_stream_t in_request_stream, + cc_int32 in_msg, + cci_stream_t* out_reply_stream); + } + +/* ------------------------------------------------------------------------ */ + +extern "C" cc_int32 cci_os_ipc_thread_init (void) { + cc_int32 err = ccNoError; + struct tspdata* ptspdata; + HANDLE replyEvent; + UUID __RPC_FAR uuid; + unsigned char __RPC_FAR* uuidString = NULL; + + if (!GetTspData(&ptspdata)) return ccErrNoMem; + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + + err = cci_check_error(UuidCreate(&uuid)); // Get a UUID + if (err == RPC_S_OK) { // Convert to string + err = UuidToString(&uuid, &uuidString); + } + if (!err) { // Save in thread local storage + tspdata_setUUID(ptspdata, uuidString); + } + cci_debug_printf("%s UUID:<%s>", __FUNCTION__, tspdata_getUUID(ptspdata)); + + // Initialize old CCAPI if necessary: + if (!err) if (!Init:: Initialized()) err = Init:: Initialize( ); + if (!err) if (!Client::Initialized()) err = Client::Initialize(0); + + if (!err) { + /* Whenever a reply to an RPC request is received, the RPC caller needs to + know when the reply has been received. It does that by waiting for a + client-specific event to be set. Define the event name to be _reply: */ + replyEvent = createThreadEvent((char*)uuidString, REPLY_SUFFIX); + } + + if (replyEvent) tspdata_setReplyEvent(ptspdata, replyEvent); + else err = cci_check_error(GetLastError()); + + if (uuidString) RpcStringFree(&uuidString); + + return cci_check_error(err); + } + + +/* ------------------------------------------------------------------------ */ + +cc_int32 cci_os_ipc (cc_int32 in_launch_server, + cci_stream_t in_request_stream, + cci_stream_t* out_reply_stream) { + return cci_os_ipc_msg( in_launch_server, + in_request_stream, + CCMSG_REQUEST, + out_reply_stream); + } + +extern "C" cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, + cci_stream_t in_request_stream, + cc_int32 in_msg, + cci_stream_t* out_reply_stream) { + + cc_int32 err = ccNoError; + cc_int32 done = FALSE; + cc_int32 try_count = 0; + cc_int32 server_died = FALSE; + TCHAR* pszStringBinding= NULL; + struct tspdata* ptspdata = NULL; + char* uuid = NULL; + int lenUUID = 0; + unsigned int trycount = 0; + time_t sst = 0; + STARTUPINFO si = { 0 }; + PROCESS_INFORMATION pi = { 0 }; + HANDLE replyEvent = 0; + BOOL bCCAPI_Connected= FALSE; + + if (!in_request_stream) { err = cci_check_error (ccErrBadParam); } + if (!out_reply_stream ) { err = cci_check_error (ccErrBadParam); } + + if (!GetTspData(&ptspdata)) {return ccErrBadParam;} + bCCAPI_Connected = tspdata_getConnected (ptspdata); + replyEvent = tspdata_getReplyEvent (ptspdata); + sst = tspdata_getSST (ptspdata); + uuid = tspdata_getUUID(ptspdata); + + // The lazy connection to the server has been put off as long as possible! + // ccapi_connect starts listening for replies as an RPC server and then + // calls ccs_rpc_connect. + if (!bCCAPI_Connected) { + err = cci_check_error(ccapi_connect(ptspdata)); + bCCAPI_Connected = !err; + tspdata_setConnected(ptspdata, bCCAPI_Connected); + } + + // Clear replyEvent so we can detect when a reply to our request has been received: + ResetEvent(replyEvent); + + //++ Use the old CCAPI implementation to try to talk to the server: + // It has all the code to use the RPC in a thread-safe way, make the endpoint, + // (re)connect and (re)start the server. + // Note: the old implementation wrapped the thread-safety stuff in a macro. + // Here it is expanded and thus duplicated for each RPC call. The new code has + // a very limited number of RPC calls, unlike the older code. + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); + SecureClient* s = 0; + SecureClient::Start(s); + CcAutoLock* a = 0; + CcAutoLock::Start(a, Client::sLock); + + // Initialize old CCAPI if necessary: + if (!err) if (!Init:: Initialized()) err = cci_check_error(Init:: Initialize( )); + if (!err) if (!Client::Initialized()) err = cci_check_error(Client::Initialize(0)); + + // New code using new RPC procedures for sending the data and receiving a reply: + if (!err) { + RpcTryExcept { + if (!GetTspData(&ptspdata)) {return ccErrBadParam;} + uuid = tspdata_getUUID(ptspdata); + lenUUID = 1 + strlen(uuid); /* 1+ includes terminating \0. */ + cci_debug_printf("%s calling remote ccs_rpc_request tsp*:0x%X", __FUNCTION__, ptspdata); + cci_debug_printf(" rpcmsg:%d; UUID[%d]:<%s> SST:%ld", in_msg, lenUUID, uuid, sst); + + ccs_rpc_request( /* make call with user message: */ + in_msg, /* Message type */ + (unsigned char*)&ptspdata, /* Our tspdata* will be sent back to the reply proc. */ + (unsigned char*)uuid, + cci_stream_size(in_request_stream), + (unsigned char*)cci_stream_data(in_request_stream), /* Data buffer */ + sst, /* session start time */ + (long*)(&err) ); /* Return code */ + } + RpcExcept(1) { + handle_exception(RpcExceptionCode()); + } + RpcEndExcept; + } + + cci_check_error(err); + CcAutoLock::Stop(a); + SecureClient::Stop(s); + ReleaseMutex(hCCAPIv2Mutex); + //-- Use the old CCAPI implementation to try to talk to the server. + + // Wait for reply handler to set event: + if (!err) { + cci_debug_printf(" Waiting for request reply."); + err = cci_check_error(WaitForSingleObject(replyEvent, INFINITE));//(SECONDS_TO_WAIT)*1000)); + cci_debug_printf(" Request reply received!"); + } + + if (!err) { + err = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE)); + } + + if (!err && server_died) { + err = cci_check_error (ccErrServerUnavailable); + } +#if 0 + if (err == BOOTSTRAP_UNKNOWN_SERVICE && !in_launch_server) { + err = ccNoError; /* If the server is not running just return an empty stream. */ + } +#endif + + if (!err) { + *out_reply_stream = tspdata_getStream(ptspdata); + } + + cci_debug_printf(" payload:<%s>", cci_stream_data(*out_reply_stream)); + + return cci_check_error (err); + } + + + +static DWORD handle_exception(DWORD code) { + cci_debug_printf("%s code %u; ccs_request_IfHandle:0x%X", __FUNCTION__, code, ccs_request_IfHandle); + if ( (code == RPC_S_SERVER_UNAVAILABLE) || (code == RPC_S_INVALID_BINDING) ) { + Client::Reconnect(0); + } + return 4; + } + + +/* Establish a CCAPI connection with the server. + * The connect logic here is identical to the logic in the send request code. + * TODO: merge this connect code with that request code. + */ +cc_int32 ccapi_connect(const struct tspdata* tsp) { + BOOL bListen = TRUE; + char* endpoint = NULL; + HANDLE replyEvent = 0; + RPC_STATUS status = FALSE; + char* uuid = NULL; + + /* Start listening to our uuid before establishing the connection, + * so that when the server tries to call ccapi_listen, we will be ready. + */ + + /* Build complete RPC uuid using previous CCAPI implementation: */ + replyEvent = tspdata_getReplyEvent(tsp); + uuid = tspdata_getUUID(tsp); + endpoint = clientEndpoint(uuid); + cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint); + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + + if (!status) { + status = RpcServerUseProtseqEp((RPC_CSTR)"ncalrpc", + opts.cMaxCalls, + (RPC_CSTR)endpoint, + sa.lpSecurityDescriptor); // SD + cci_check_error(status); + } + + if (!status) { + status = RpcServerRegisterAuthInfo(0, // server principal + RPC_C_AUTHN_WINNT, + 0, + 0 ); + cci_check_error(status); + } + + cci_debug_printf("%s is listening ...", __FUNCTION__); + + if (!status) { + if (!isNT()) { + status = RpcServerRegisterIf(ccs_reply_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL); // MgrEpv; null means use default + } + else { + status = RpcServerRegisterIfEx(ccs_reply_ServerIfHandle,// interface + NULL, // MgrTypeUuid + NULL, // MgrEpv; 0 means default + RPC_IF_ALLOW_SECURE_ONLY, + opts.cMaxCalls, + NULL); // No security callback. + } + + cci_check_error(status); + + if (!status) { + status = RpcServerListen(opts.cMinCalls, + opts.cMaxCalls, + TRUE); + cci_check_error(status); + } + } + + // Clear replyEvent so we can detect when a reply to our connect request has been received: + ResetEvent(replyEvent); + + // We use the old CCAPI implementation to try to talk to the server. + // It has all the code to make the uuid, (re)connect and (re)start the server. + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); + SecureClient* s = 0; + SecureClient::Start(s); + CcAutoLock* a = 0; + CcAutoLock::Start(a, Client::sLock); + + // Initialize old CCAPI if necessary: + if (!status) if (!Init:: Initialized()) status = Init:: Initialize( ); + if (!status) if (!Client::Initialized()) status = Client::Initialize(0); + + // New code using new RPC procedures for sending the data and receiving a reply: + if (!status) { + RpcTryExcept { + ccs_rpc_connect( /* make call with user message: */ + CCMSG_CONNECT, /* Message type */ + (unsigned char*)&tsp, /* Our tspdata* will be sent back to the reply proc. */ + (unsigned char*)uuid, + (long*)(&status) ); /* Return code */ + } + RpcExcept(1) { + cci_check_error(RpcExceptionCode()); + status = ccErrBadInternalMessage; + } + RpcEndExcept; + } + + CcAutoLock::Stop(a); + SecureClient::Stop(s); + ReleaseMutex(hCCAPIv2Mutex); + + if (!status) { + cci_debug_printf("%s Waiting for replyEvent.", __FUNCTION__); + status = WaitForSingleObject(replyEvent, INFINITE);//(SECONDS_TO_WAIT)*1000); + status = cci_check_error(RpcMgmtIsServerListening(CLIENT_REQUEST_RPC_HANDLE)); + cci_debug_printf(" Server %sFOUND!", (status) ? "NOT " : ""); + } + if (status) { + cci_debug_printf(" unexpected error while looking for server... (%u)", status); + } + + cci_debug_printf("%s TODO: check connect reply result.", __FUNCTION__); + cci_debug_printf("%s TODO: merge this connect code with that request code.", __FUNCTION__); + return status; + } \ No newline at end of file diff --git a/src/ccapi/lib/win/ccs_reply_proc.c b/src/ccapi/lib/win/ccs_reply_proc.c new file mode 100644 index 000000000..ebac6e3cf --- /dev/null +++ b/src/ccapi/lib/win/ccs_reply_proc.c @@ -0,0 +1,98 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include +#include + +#include "cci_debugging.h" +#include "ccs_reply.h" /* generated by MIDL compiler */ +#include "ccutils.h" +#include "tls.h" +#include "win-utils.h" + + +void ccs_rpc_request_reply( + const long rpcmsg, /* Message type */ + const char tspHandle[], /* Client's tspdata* */ + const char* uuid, /* uuid for making thread-specific event name */ + const long srvStartTime, /* Server Start Time */ + const long cbIn, /* Length of buffer */ + const char* chIn, /* Data buffer */ + long* ret_status ) { /* Return code */ + + HANDLE hEvent = openThreadEvent(uuid, REPLY_SUFFIX); + DWORD* p = (DWORD*)(tspHandle); + struct tspdata* tsp = (struct tspdata*)*p; + cci_stream_t stream; + long status = 0; + + cci_debug_printf("%s! msg#:%d SST:%ld uuid:%s", __FUNCTION__, rpcmsg, srvStartTime, uuid); + cci_debug_printf(" payload:<%s>", chIn); + cci_debug_printf(" uuid from handle:<%s>", tspdata_getUUID(tsp)); + + if (!status) { + status = cci_stream_new (&stream); /* Create a stream for the request data */ + } + + if (!status) { /* Put the data into the stream */ + status = cci_stream_write (stream, chIn, cbIn); + } + + if (!status) { /* Put the data into the stream */ + tspdata_setStream(tsp, stream); + } + + SetEvent(hEvent); + CloseHandle(hEvent); + *ret_status = status; + } + +void ccs_rpc_connect_reply( + const long rpcmsg, /* Message type */ + const char tspHandle[], /* Client's tspdata* */ + const char* uuid, /* uuid for making thread-specific event name */ + const long srvStartTime, /* Server Start Time */ + long* status ) { /* Return code */ + + HANDLE hEvent = openThreadEvent(uuid, REPLY_SUFFIX); + DWORD* p = (DWORD*)(tspHandle); + + cci_debug_printf("%s! msg#:%d SST:%ld uuid:%s", __FUNCTION__, rpcmsg, srvStartTime, uuid); + + SetEvent(hEvent); + CloseHandle(hEvent); + } + +void ccapi_listen( + RPC_ASYNC_STATE* rpcState, + handle_t hBinding, + const long rpcmsg, /* Message type */ + long* status ) { /* Return code */ + + cci_debug_printf("%s %s!", __FUNCTION__, rpcState->UserInfo); + *status = 0; + } diff --git a/src/ccapi/lib/win/dllmain.cxx b/src/ccapi/lib/win/dllmain.cxx new file mode 100644 index 000000000..7000e1418 --- /dev/null +++ b/src/ccapi/lib/win/dllmain.cxx @@ -0,0 +1,279 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include + +extern "C" { +#include "dllmain.h" +#include "tls.h" +#include "cci_debugging.h" +#include "ccapi_context.h" +#include "client.h" + +//void cci_thread_init__auxinit(); + } + +#define CCAPI_V2_MUTEX_NAME TEXT("MIT_CCAPI_V4_MUTEX") + +// Process-specific data: +static DWORD dwTlsIndex; +static char _user[UNLEN+1]; // Username is used as part of the server and client endpoints. +static HANDLE sessionToken; +static char* ep_prefices[] = {"CCS", "CCAPI"}; +HANDLE hCCAPIv2Mutex = NULL; +DWORD firstThreadID = 0; + +// These data structures are used by the old CCAPI implementation +// to keep track of the state of the RPC connection. All data is static. +static Init init; +static Client client; + +// DllMain() is the entry-point function for this DLL. +BOOL WINAPI DllMain(HINSTANCE hinstDLL, // DLL module handle + DWORD fdwReason, // reason called + LPVOID lpvReserved) { // reserved + + struct tspdata* ptspdata; + BOOL fIgnore; + BOOL bStatus; + DWORD status = 0; // 0 is success. + DWORD maxUN = sizeof(_user); + unsigned int i = 0; + unsigned int j = 0; + + switch (fdwReason) { + // The DLL is loading due to process initialization or a call to LoadLibrary: + case DLL_PROCESS_ATTACH: + cci_debug_printf("%s DLL_PROCESS_ATTACH", __FUNCTION__); + // Process-wide mutex used to allow only one thread at a time into the RPC code: + hCCAPIv2Mutex = CreateMutex(NULL, FALSE, CCAPI_V2_MUTEX_NAME); + + // Figure out our username; it's process-wide: + bStatus = GetUserName(_user, &maxUN); + if (!bStatus) return bStatus; + + // Remove any characters that aren't valid endpoint characters: + while (_user[j] != 0) { + if (isalnum(_user[j])) _user[i++] = _user[j]; + j++; + } + _user[i] = '\0'; + + // Our logon session is determined in client.cxx, old CCAPI code carried + // over to this implementation. + + // Allocate a TLS index: + if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES) return FALSE; + + // Initialize CCAPI once per DLL load: + firstThreadID = GetCurrentThreadId(); + + // Don't break; fallthrough: Initialize the TLS index for first thread. + + // The attached process creates a new thread: + case DLL_THREAD_ATTACH: + // Initialize the TLS index for this thread: + ptspdata = (struct tspdata*) LocalAlloc(LPTR, sizeof(struct tspdata)); + cci_debug_printf("%s DLL_THREAD_ATTACH; tsp*:0x%X", __FUNCTION__, ptspdata); + if (ptspdata == NULL) return FALSE; + fIgnore = TlsSetValue(dwTlsIndex, ptspdata); + + memset(ptspdata, 0, sizeof(struct tspdata)); + + // Initialize CCAPI once per DLL load: + if (GetCurrentThreadId() == firstThreadID) cci_thread_init__auxinit(); + + break; + + // The thread of the attached process terminates: + case DLL_THREAD_DETACH: + cci_debug_printf("%s DLL_THREAD_DETACH", __FUNCTION__); + // Release the allocated memory for this thread: + ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (ptspdata != NULL) { + LocalFree((HLOCAL) ptspdata); + TlsSetValue(dwTlsIndex, NULL); + } + break; + + // DLL unload due to process termination or FreeLibrary: + case DLL_PROCESS_DETACH: + cci_debug_printf("%s DLL_PROCESS_DETACH", __FUNCTION__); + //++ Copied from previous implementation: + // Process Teardown "Problem" + // + // There are two problems that occur during process teardown: + // + // 1) Windows (NT/9x/2000) does not keep track of load/unload + // ordering dependencies for use in process teardown. + // + // 2) The RPC exception handling in the RPC calls do not work + // during process shutdown in Win9x. + // + // When a process is being torn down in Windows, the krbcc DLL + // may get a DLL_PROCESS_DETACH before other DLLs are done + // with it. Thus, it may disconnect from the RPC server + // before the last shutdown RPC call. + // + // On NT/2000, this is ok because the RPC call will fail and just + // return an error. + // + // On Win9x/Me, the RPC exception will not be caught. + // However, Win9x ignores exceptions during process shutdown, + // so the exception will never be seen unless a debugger is + // attached to the proccess. + // + // A good potential woraround would be to have a global + // variable that denotes whether the DLL is attached to the + // process. If it is not, all entrypoints into the DLL should + // return failure. + // + // A not as good workaround is below but ifdefed out. + // + // However, we can safely ignore this problem since it can + // only affects people running debuggers under 9x/Me who are + // using multiple DLLs that use this DLL. + // + WaitForSingleObject( hCCAPIv2Mutex, INFINITE ); +#if 0 + bool process_teardown_workaround = false; + if (lpvReserved) { + Init::InitInfo info; + status = Init::Info(info); + if (status) break; + if (!info.isNT) process_teardown_workaround = true; + } + if (process_teardown_workaround) + break; +#endif + // return value is ignored, so we set status for debugging purposes + status = Client::Cleanup(); + status = Init::Cleanup(); + ReleaseMutex( hCCAPIv2Mutex ); + CloseHandle( hCCAPIv2Mutex ); + //-- Copied from previous implementation. + + // Release the allocated memory for this thread: + ptspdata = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (ptspdata != NULL) LocalFree((HLOCAL) ptspdata); + TlsFree(dwTlsIndex); // Release the TLS index. + break; + + default: break; + } + + UNREFERENCED_PARAMETER(hinstDLL); // no whining! + UNREFERENCED_PARAMETER(lpvReserved); + return status ? FALSE : TRUE; +} + + +#ifdef __cplusplus // If used by C++ code, +extern "C" { // we need to export the C interface +#endif + +__declspec(dllexport) +BOOL WINAPI PutTspData(struct tspdata* dw) { + LPVOID lpvData; + struct tspdata** pData; // The stored memory pointer + + // Retrieve a data pointer for the current thread: + lpvData = TlsGetValue(dwTlsIndex); + + // If NULL, allocate memory for the TLS slot for this thread: + if (lpvData == NULL) { + lpvData = (LPVOID) LocalAlloc(LPTR, sizeof(struct tspdata)); + if (lpvData == NULL) return FALSE; + if (!TlsSetValue(dwTlsIndex, lpvData)) return FALSE; + } + + pData = (struct tspdata**) lpvData; // Cast to my data type. + // In this example, it is only a pointer to a DWORD + // but it can be a structure pointer to contain more complicated data. + + (*pData) = dw; + return TRUE; + } + +__declspec(dllexport) +BOOL WINAPI GetTspData(struct tspdata** pdw) { + struct tspdata* pData; // The stored memory pointer + + pData = (struct tspdata*)TlsGetValue(dwTlsIndex); + if (pData == NULL) return FALSE; + (*pdw) = pData; + return TRUE; + } + +#if 0 // replaced by clientEndpoint / serverEndpoint. +__declspec(dllexport) +char* WINAPI getEndpoint(enum EndpointType ep) { + // The server endpoint is of the form CCS_ + // The client endpoint is of the form CCAPI_ + // Each client thread can have its own connection. + // + // NB: Caller must free the data the returned char* points to. + struct tspdata* pData; + char* s; + char* uuid; + unsigned int len; + + switch (ep) { + case EPT_SERVER: + s = (char*)malloc(32); // Length of CCS_ + sprintf(s, "%s_%ld", ep_prefices[EPT_SERVER], sessionToken); + break; + case EPT_CLIENT: + GetTspData(&pData); + uuid = tspdata_getUUID(pData); + len = 4 + strlen(ep_prefices[ep]) + strlen(_user) + strlen(uuid); + s = (char*)malloc(len); + sprintf(s, "%s_%s_%s", ep_prefices[EPT_CLIENT], _user, uuid); + break; + default:; + } + cci_debug_printf("%s(%d) returning %s", __FUNCTION__, ep, s); + + return s; + } +#endif + +#ifdef __cplusplus +} +#endif + +/*********************************************************************/ +/* MIDL allocate and free */ +/*********************************************************************/ + +void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { + return(malloc(len)); + } + +void __RPC_USER midl_user_free(void __RPC_FAR * ptr) { + free(ptr); + } diff --git a/src/ccapi/lib/win/dllmain.h b/src/ccapi/lib/win/dllmain.h new file mode 100644 index 000000000..3ce2ac230 --- /dev/null +++ b/src/ccapi/lib/win/dllmain.h @@ -0,0 +1,45 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef _dll_h +#define _dll_h + +#include "windows.h" + +enum EndpointType {EPT_SERVER=0, EPT_CLIENT}; + +#ifdef __cplusplus // If used by C++ code, +extern "C" { // we need to export the C interface +#endif +__declspec(dllexport) BOOL WINAPI PutTspData(struct tspdata* p); +__declspec(dllexport) BOOL WINAPI GetTspData(struct tspdata** p); + +//__declspec(dllexport) char* WINAPI getEndpoint(enum EndpointType); +#ifdef __cplusplus +} +#endif + +#endif _dll_h \ No newline at end of file diff --git a/src/ccapi/server/win/Makefile b/src/ccapi/server/win/Makefile new file mode 100644 index 000000000..deaebb2e0 --- /dev/null +++ b/src/ccapi/server/win/Makefile @@ -0,0 +1,105 @@ +!include + +# . is ...\pismere\athena\auth\krb5\src\ccapi\server\win +CCAPI = ..\.. +CO = $(CCAPI)\common +COWIN = $(CCAPI)\common\win +CCUTIL = $(CCAPI)\common\win\OldCC +LIBDIR = $(CCAPI)\lib +LIBWIN = $(CCAPI)\lib\win +K5SRC = $(CCAPI)\.. +POSIX = $(K5SRC)\lib\krb5\posix + +INC = -I. -I.. -I$(CO) -I$(COWIN) -I$(K5SRC)\include -I..\..\..\util\et -I$(CCUTIL) + +!if "$(CPU)" == "i386" +cflags = $(cflags) /EHsc -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 \ +$(INC) -MTd +!else +cflags = $(cflags) /W3 -D_CRTAPI1= -D_CRTAPI2= $(INC) +!endif + +all : server + +server : server.exe + +common = cci_array_internal.obj cci_cred_union.obj cci_debugging.obj cci_identifier.obj \ + cci_message.obj cci_stream.obj + +commonwin = cci_os_debugging.obj \ + cci_os_identifier.obj \ + tls.obj \ + win-utils.obj + +ccutils = ccutils.obj + +ccutilscxx = opts.obj util.obj secure.obj init.obj + +dll = ccapi_string.obj + +srv = ccs_array.obj ccs_cache_collection.obj ccs_callback.obj ccs_ccache.obj \ + ccs_ccache_iterator.obj ccs_client.obj \ + ccs_credentials.obj ccs_credentials_iterator.obj ccs_list.obj ccs_list_internal.obj \ + ccs_lock.obj ccs_lock_state.obj ccs_pipe.obj ccs_server.obj + +srvwin = ccs_os_pipe.obj ccs_reply_c.obj \ + ccs_request_proc.obj ccs_win_pipe.obj + +srvwincpp = ccs_os_server.obj ccs_request_s.obj WorkItem.obj WorkQueue.obj + +linkobjs = $(common) $(commonwin) $(ccutils) $(ccutilscxx) \ + $(srv) $(srvwin) $(srvwincpp) + +includes = ccs_reply.h ccs_request.h + +# Main program: +server.exe : $(linkobjs) +# $(link) $(linkdebug) $(conflags) -MTd -out:ccapiserver.exe $(linkobjs) \ + $(link) $(linkdebug) $(conflags) -out:ccapiserver.exe $(linkobjs) \ + rpcrt4.lib advapi32.lib ws2_32.lib user32.lib + + +ccs_request.h ccs_request_s.cpp : $(COWIN)\ccs_request.idl $(COWIN)\ccs_request.acf + midl $(MIDL_OPTIMIZATION) -oldnames -cpp_cmd $(cc) -cpp_opt "-E" -I. -I$(COWIN) -sstub \ + ccs_request_s.cpp $(COWIN)\ccs_request.idl + +ccs_reply.h ccs_reply_c.c : $(COWIN)\ccs_reply.idl $(COWIN)\ccs_reply.acf + midl $(MIDL_OPTIMIZATION) -oldnames -cpp_cmd $(cc) -cpp_opt "-E" -I. -I$(COWIN) \ + $(COWIN)\ccs_reply.idl + +$(common) : $(CO)\$*.c + $(cc) $(cdebug) $(cflags) $(CO)\$*.c + +$(commonwin) : $(COWIN)\$*.c + $(cc) $(cdebug) $(cflags) $(COWIN)\$*.c + +$(ccutils) : $(CCUTIL)\$*.c + $(cc) $(cdebug) $(cflags) $(CCUTIL)\$*.c + +$(ccutilscxx) : $(CCUTIL)\$*.cxx + $(cc) $(cdebug) $(cflags) $(CCUTIL)\$*.cxx + +$(srv) : ..\$*.c + $(cc) $(cdebug) $(cflags) ..\$*.c + +$(srvwin) : $*.c $(includes) + $(cc) $(cdebug) $(cflags) $*.c + +$(srvwincpp) : $*.cpp + $(cc) $(cdebug) $(cflags) $*.cpp + + +# Clean up everything +cleanall : clean + -del *.exe + +# Clean up everything but the .EXEs +clean : + -del *.obj + -del *.map + -del ccs_request_s.c + -del ccs_request_c.c + -del ccs_request.h + -del ccs_reply_s.c + -del ccs_reply_c.c + -del ccs_reply.h diff --git a/src/ccapi/server/win/Server.sln b/src/ccapi/server/win/Server.sln new file mode 100644 index 000000000..64cc7f08c --- /dev/null +++ b/src/ccapi/server/win/Server.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "Server.vcproj", "{114DCD80-6D13-4AAA-9510-B51CE6D94C1C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Debug|Win32.ActiveCfg = Debug|Win32 + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Debug|Win32.Build.0 = Debug|Win32 + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Release|Win32.ActiveCfg = Release|Win32 + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/ccapi/server/win/Server.vcproj b/src/ccapi/server/win/Server.vcproj new file mode 100644 index 000000000..39db361d8 --- /dev/null +++ b/src/ccapi/server/win/Server.vcproj @@ -0,0 +1,227 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/ccapi/server/win/WorkItem.cpp b/src/ccapi/server/win/WorkItem.cpp new file mode 100644 index 000000000..7e6aeb1cb --- /dev/null +++ b/src/ccapi/server/win/WorkItem.cpp @@ -0,0 +1,126 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include "assert.h" + +#pragma warning (disable : 4996) + +#include "win-utils.h" +#include "WorkItem.h" + +extern "C" { +#include "cci_debugging.h" + } + +// CountedBuffer makes a copy of the data. Each CountedBuffer must be deleted. + +void deleteBuffer(char** buf) { + if (*buf) { + delete [](*buf); + *buf = NULL; + } + } + +// WorkItem contains a CountedBuffer which must be deleted, +// so each WorkItem must be deleted. +WorkItem::WorkItem(cci_stream_t buf, WIN_PIPE* pipe, const long type, const long sst) +: _buf(buf), _rpcmsg(type), _pipe(pipe), _sst(sst) { } + +WorkItem::WorkItem(const WorkItem& item) : _buf(NULL), _rpcmsg(0), _pipe(NULL), _sst(0) { + + cci_stream_t _buf = NULL; + cci_stream_new(&_buf); + cci_stream_write(_buf, + cci_stream_data(item.payload()), + cci_stream_size(item.payload()) ); + WorkItem(_buf, item._pipe, item._rpcmsg, item._sst); + } + +WorkItem::WorkItem() : _buf(NULL), _rpcmsg(CCMSG_INVALID), _pipe(NULL), _sst(0) { } + +WorkItem::~WorkItem() { + if (_buf) cci_stream_release(_buf); + if (_pipe) ccs_win_pipe_release(_pipe); + } + +const cci_stream_t WorkItem::take_payload() { + cci_stream_t temp = payload(); + _buf = NULL; + return temp; + } + +WIN_PIPE* WorkItem::take_pipe() { + WIN_PIPE* temp = pipe(); + _pipe = NULL; + return temp; + } + +WorkList::WorkList() { + assert(InitializeCriticalSectionAndSpinCount(&cs, 0x80000400)); + } + +WorkList::~WorkList() { + // Delete any WorkItems in the queue: + WorkItem* item; + cci_debug_printf("%s", __FUNCTION__); + char buf[2048]; + char* pbuf = (char*)buf; + while (remove(&item)) { + cci_debug_printf("WorkList::~WorkList() deleting %s", item->print(pbuf)); + delete item; + } + + DeleteCriticalSection(&cs); + } + +char* WorkItem::print(char* buf) { + sprintf(buf, "WorkItem msg#:%d sst:%ld pipe:<%s>/0x%X", _rpcmsg, _sst, + ccs_win_pipe_getUuid(_pipe), ccs_win_pipe_getHandle(_pipe)); + return buf; + } + +int WorkList::add(WorkItem* item) { + EnterCriticalSection(&cs); + wl.push_front(item); + LeaveCriticalSection(&cs); + return 1; + } + +int WorkList::remove(WorkItem** item) { + bool bEmpty; + + bEmpty = wl.empty() & 1; + + if (!bEmpty) { + EnterCriticalSection(&cs); + *item = wl.back(); + wl.pop_back(); + LeaveCriticalSection(&cs); + } + + return !bEmpty; + } \ No newline at end of file diff --git a/src/ccapi/server/win/WorkQueue.cpp b/src/ccapi/server/win/WorkQueue.cpp new file mode 100644 index 000000000..711ecc173 --- /dev/null +++ b/src/ccapi/server/win/WorkQueue.cpp @@ -0,0 +1,61 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +extern "C" { + #include "cci_debugging.h" + } + +#include "WorkItem.h" + +WorkList worklist; + +/* C interfaces: */ +EXTERN_C bool worklist_isEmpty() { + return worklist.isEmpty(); + } + +EXTERN_C int worklist_add( const long rpcmsg, + const ccs_pipe_t pipe, + const cci_stream_t stream, + const time_t serverStartTime) { + return worklist.add(new WorkItem(stream, pipe, rpcmsg, serverStartTime) ); + } + +EXTERN_C int worklist_remove(long* rpcmsg, + ccs_pipe_t* pipe, + cci_stream_t* stream, + time_t* sst) { + WorkItem* item = NULL; + cc_int32 err = worklist.remove(&item); + + *rpcmsg = item->type(); + *pipe = item->take_pipe(); + *stream = item->take_payload(); + *sst = item->sst(); + delete item; + return err; + } + diff --git a/src/ccapi/server/win/WorkQueue.h b/src/ccapi/server/win/WorkQueue.h new file mode 100644 index 000000000..106f9acb9 --- /dev/null +++ b/src/ccapi/server/win/WorkQueue.h @@ -0,0 +1,46 @@ +/* + * $Header$ + * + * Copyright 2007 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef _work_queue_h +#define _work_queue_h + +#include "windows.h" +#include "cci_stream.h" +#include "ccs_pipe.h" + +EXTERN_C BOOL worklist_isEmpty(); + +EXTERN_C void worklist_add( const long rpcmsg, + const ccs_pipe_t pipe, + const cci_stream_t stream, + const time_t serverStartTime); + +EXTERN_C int worklist_remove(long* rpcmsg, + ccs_pipe_t* pipe, + cci_stream_t* stream, + time_t* serverStartTime); + +#endif // _work_queue_h \ No newline at end of file diff --git a/src/ccapi/server/win/ccs_os_pipe.c b/src/ccapi/server/win/ccs_os_pipe.c new file mode 100644 index 000000000..69dcec474 --- /dev/null +++ b/src/ccapi/server/win/ccs_os_pipe.c @@ -0,0 +1,64 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "ccs_common.h" +#include "ccs_os_pipe.h" +#include "ccs_win_pipe.h" + +/* ------------------------------------------------------------------------ */ + +/* On Windows, a pipe is a struct. See ccs_win_pipe.h for details. */ + + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_valid (ccs_pipe_t in_pipe) { + return ccs_win_pipe_valid(in_pipe); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_copy (ccs_pipe_t* out_pipe, ccs_pipe_t in_pipe) { + return ccs_win_pipe_copy( + out_pipe, + in_pipe); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_release (ccs_pipe_t io_pipe) { + return ccs_win_pipe_release(io_pipe); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_pipe_compare (ccs_pipe_t pipe_1, + ccs_pipe_t pipe_2, + cc_uint32 *out_equal) { + + return ccs_win_pipe_compare(pipe_1, pipe_2, out_equal); + } + diff --git a/src/ccapi/server/win/ccs_os_server.cpp b/src/ccapi/server/win/ccs_os_server.cpp new file mode 100644 index 000000000..0c3f7660e --- /dev/null +++ b/src/ccapi/server/win/ccs_os_server.cpp @@ -0,0 +1,950 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "process.h" +#include "windows.h" + +extern "C" { +#include "ccs_common.h" +#include "ccs_os_server.h" +#include +#include "ccs_reply.h" +#include "ccs_request.h" +#include "win-utils.h" +#include "ccutils.h" +#include "cci_stream.h" + } + +#include "WorkQueue.h" +#include "util.h" +#include "opts.hxx" +#include "init.hxx" + +#pragma warning (disable : 4996) + +BOOL bListen = TRUE; /* Why aren't bool and true defined? */ +const char* sessID = NULL; /* The logon session we are running on behalf of. */ +time_t _sst = 0; +unsigned char* pszNetworkAddress = NULL; +unsigned char* pszStringBinding = NULL; +BOOL bRpcHandleInited = FALSE; +_RPC_ASYNC_STATE* rpcState = NULL; + +/* Thread procedures can take only one void* argument. We put all the args we want + to pass into this struct and then pass a pointer to the struct: */ +struct RpcRcvArgs { + char* networkAddress; + unsigned char* protocolSequence; + unsigned char* sessID; /* Used for this server's endpoint */ + unsigned char* uuid; /* Used for client's UUID */ + ParseOpts::Opts* opts; + RPC_STATUS status; + } rpcargs = { NULL, /* pszNetworkAddress */ + (unsigned char*)"ncalrpc", /* pszProtocolSequence */ + NULL, /* sessID placeholder */ + NULL, /* uuid placeholder */ + NULL }; /* Opts placeholder */ + +/* Command line format: + argv[0] Program name + argv[1] session ID to use + argv[2] "D" Debug: go into infinite loop in ccs_os_server_initialize so process + can be attached in debugger. + Any other value: continue + */ +#define N_FIXED_ARGS 3 +#define SERVER_REPLY_RPC_HANDLE ccs_reply_IfHandle + +/* Forward declarations: */ +void receiveLoop(void* rpcargs); +void connectionListener(void* rpcargs); +void Usage(const char* argv0); +void printError(TCHAR* msg); +void setMySST() {_sst = time(&_sst);} +time_t getMySST() {return _sst;} +RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe); +void RPC_ENTRY clientListener( _RPC_ASYNC_STATE*, + void* Context, + RPC_ASYNC_EVENT Event); +RPC_STATUS RPC_ENTRY sec_callback( IN RPC_IF_ID *Interface, + IN void *Context); +RPC_STATUS send_init(char* clientUUID); +//DWORD alloc_name(LPSTR* pname, LPSTR postfix); + + +/* The layout of the rest of this module: + + The four entrypoints defined in ccs_os_server.h: + ccs_os_server_initialize + cc_int32 ccs_os_server_cleanup + cc_int32 ccs_os_server_listen_loop + cc_int32 ccs_os_server_send_reply + + Other routines needed by those four. + */ + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_initialize (int argc, const char *argv[]) { + cc_int32 err = 0; + ParseOpts::Opts opts = { 0 }; + ParseOpts PO; + BOOL bAdjustedShutdown = FALSE; + HMODULE hKernel32 = GetModuleHandle("kernel32"); + + if (!err) { + sessID = argv[1]; + setMySST(); + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + +#ifdef CCAPI_TEST_OPTIONS + PO.SetValidOpts("kemnfubc"); +#else + PO.SetValidOpts("kc"); +#endif + + PO.Parse(opts, argc, (char**)argv); + +// while(*argv[2] == 'D') {} /* Hang here to attach process with debugger. */ + + if (hKernel32) { + typedef BOOL (WINAPI *FP_SetProcessShutdownParameters)(DWORD, DWORD); + FP_SetProcessShutdownParameters pSetProcessShutdownParameters = + (FP_SetProcessShutdownParameters) + GetProcAddress(hKernel32, "SetProcessShutdownParameters"); + if (pSetProcessShutdownParameters) { + bAdjustedShutdown = pSetProcessShutdownParameters(100, 0); + } + } + cci_debug_printf("%s Shutdown Parameters", + bAdjustedShutdown ? "Adjusted" : "Did not adjust"); + + err = Init::Initialize(); + } + +// if (!err) { +// if (opts.bShutdown) { +// status = shutdown_server(opts.pszEndpoint); +// } +// } +// else { +// status = startup_server(opts); +// } + + if (err) { + Init::Cleanup(); + fprintf( stderr, "An error occured while %s the server (%u)\n", + opts.bShutdown ? "shutting down" : "starting/running", + err); + exit(cci_check_error (err)); + } + + return cci_check_error (err); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_cleanup (int argc, const char *argv[]) { + cc_int32 err = 0; + + cci_debug_printf("%s for user <%s> shutting down.", argv[0], argv[1]); + + return cci_check_error (err); + } + +/* ------------------------------------------------------------------------ */ + +/* This function takes work items off the work queue and executes them. + * This is the one and only place where the multi-threaded Windows code + * calls into the single-threaded common code. + * + * The actual 'listening' for requests from clients happens after receiveloop + * establishes the RPC endpoint the clients will connect to and the RPC procedures + * put the work items into the work queue. + */ +cc_int32 ccs_os_server_listen_loop (int argc, const char *argv[]) { + cc_int32 err = 0; + uintptr_t threadStatus; + unsigned int loopCounter = 0; + + ParseOpts::Opts opts = { 0 }; + ParseOpts PO; + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + +#ifdef CCAPI_TEST_OPTIONS + PO.SetValidOpts("kemnfubc"); +#else + PO.SetValidOpts("kc"); +#endif + PO.Parse(opts, argc, (char**)argv); + + + //++ debug stuff + #define INFO_BUFFER_SIZE 32767 + TCHAR infoBuf[INFO_BUFFER_SIZE]; + DWORD bufCharCount = INFO_BUFFER_SIZE; + // Get and display the user name. + bufCharCount = INFO_BUFFER_SIZE; + if( !GetUserName( infoBuf, &bufCharCount ) ) printError( TEXT("GetUserName") ); + //-- + + /* Sending the reply from within the request RPC handler doesn't seem to work. + So we listen for requests in a separate thread and put the requests in a + queue. */ + rpcargs.sessID = (unsigned char*)sessID; + rpcargs.opts = &opts; + threadStatus = _beginthread(receiveLoop, 0, (void*)&rpcargs); + + /* We handle the queue entries here. Work loop: */ + while (TRUE) { + loopCounter++; + if (worklist_isEmpty() & 1) { + SleepEx(1000, TRUE); + } + else if (TRUE) { // Take next WorkItem from the queue: + cci_stream_t buf = NULL; + long rpcmsg = CCMSG_INVALID; + time_t serverStartTime = 0xDEADDEAD; + RPC_STATUS status = 0; + char* uuid = NULL; + cci_stream_t stream = NULL; + ccs_pipe_t pipe = NULL; + ccs_pipe_t pipe2 = NULL; + + if (worklist_remove(&rpcmsg, &pipe, &buf, &serverStartTime)) { + uuid = ccs_win_pipe_getUuid(pipe); + cci_debug_printf("%s: processing WorkItem msg:%ld pipeUUID:<%s> pipeHandle:0x%X SST:%ld", + __FUNCTION__, rpcmsg, uuid, ccs_win_pipe_getHandle(pipe), serverStartTime); + + if (serverStartTime <= getMySST()) { + switch (rpcmsg) { + case CCMSG_CONNECT: { + cci_debug_printf(" Processing CONNECT"); + rpcargs.uuid = (unsigned char*)uuid; + + // Even if a disconnect message is received before this code finishes, + // it won't be dequeued and processed until after this code finishes. + // So we can add the client after starting the connection listener. + connectionListener((void*)&rpcargs); + status = rpcargs.status; + + if (!status) { + status = ccs_server_add_client(pipe); + } + if (!status) {status = send_connection_reply(pipe);} + break; + } + case CCMSG_DISCONNECT: { + cci_debug_printf(" Processing DISCONNECT"); + if (!status) { + status = ccs_server_remove_client(pipe); + } + break; + } + case CCMSG_REQUEST: + cci_debug_printf(" Processing REQUEST"); + ccs_pipe_copy(&pipe2, pipe); + // Dispatch message here, setting both pipes to the client UUID: + err = ccs_server_handle_request (pipe, pipe2, buf); + break; + case CCMSG_PING: + cci_debug_printf(" Processing PING"); + err = cci_stream_new (&stream); + err = cci_stream_write(stream, "This is a test of the emergency broadcasting system", 52); + err = ccs_os_server_send_reply(pipe, stream); + break; + default: + cci_debug_printf("Huh? Received invalid message type %ld from UUID:<%s>", + rpcmsg, uuid); + break; + } + if (buf) cci_stream_release(buf); + /* Don't free uuid, which was allocated here. A pointer to it is in the + rpcargs struct which was passed to connectionListener which will be + received by ccapi_listen when the client exits. ccapi_listen needs + the uuid to know which client to disconnect. + */ + } + // Server's start time is different from what the client thinks. + // That means the server has rebooted since the client connected. + else { + cci_debug_printf("Whoops! Server has rebooted since client established connection."); + } + } + else {cci_debug_printf("Huh? Queue not empty but no item to remove.");} + } + } + + return cci_check_error (err); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_send_reply (ccs_pipe_t in_pipe, + cci_stream_t in_reply_stream) { + + /* ccs_pipe_t in_reply_pipe is a char* reply endpoint. + cci_stream_t in_reply_stream is the data to be sent. + */ + + cc_int32 err = 0; + char* uuid = ccs_win_pipe_getUuid(in_pipe); + HANDLE h = ccs_win_pipe_getHandle(in_pipe); + + if (!err) { + err = send_init(uuid); // Sets RPC handle to be used. + } + + if (!err) { + RpcTryExcept { + long status; + ccs_rpc_request_reply( // make call with user message + CCMSG_REQUEST_REPLY, /* Message type */ + (unsigned char*)&h, /* client's tspdata* */ + (unsigned char*)uuid, + getMySST(), + cci_stream_size(in_reply_stream), /* Length of buffer */ + (const unsigned char*)cci_stream_data(in_reply_stream), /* Data buffer */ + &status ); /* Return code */ + } + RpcExcept(1) { + cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + } + + /* The calls to the remote procedures are complete. */ + /* Free whatever we allocated: */ + err = RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); + + return cci_check_error (err); + } + + +/* Windows-specific routines: */ + +void Usage(const char* argv0) { + printf("Usage:\n"); + printf("%s [m maxcalls] [n mincalls] [f dontwait] [h|?]]\n", argv0); + printf(" CCAPI server process.\n"); + printf(" h|? whow usage message. <\n"); + } + +/* ------------------------------------------------------------------------ */ +/* The receive thread repeatedly issues RpcServerListen. + When a message arrives, it is handled in the RPC procedure. + */ +void receiveLoop(void* rpcargs) { + + struct RpcRcvArgs* rcvargs = (struct RpcRcvArgs*)rpcargs; + RPC_STATUS status = FALSE; + unsigned char* pszSecurity = NULL; + LPSTR endpoint = NULL; + LPSTR event_name = NULL; + PSECURITY_DESCRIPTOR psd = NULL; + HANDLE hEvent = 0; + Init::InitInfo info; + + cci_debug_printf("THREAD BEGIN: %s", __FUNCTION__); + + status = Init::Info(info); + + /* Build complete RPC endpoint using previous CCAPI implementation: */ + if (!status) { + if (!rcvargs->opts->pszEndpoint) { + if (!status) { + status = alloc_name(&endpoint, "ep", isNT()); + } + + if (!status) { + status = alloc_name(&event_name, "startup", isNT()); + } + + if (!status) { + hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name); + // We ignore any error opening the event because we do not know who started us. + // [Comment paraphrased from previous implementation, whence it was copied.] + } + } + else { + endpoint = rcvargs->opts->pszEndpoint; + } + } + + cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint); + + if (!status && isNT()) { + status = alloc_own_security_descriptor_NT(&psd); + } + + if (!status) { + status = RpcServerUseProtseqEp(rcvargs->protocolSequence, + rcvargs->opts->cMaxCalls, + (RPC_CSTR)endpoint, + rcvargs->opts->bDontProtect ? 0 : psd); // SD + } + + if (!status) { + status = RpcServerRegisterAuthInfo(0, // server principal + RPC_C_AUTHN_WINNT, + 0, + 0); + } + + while (bListen && !status) { + cci_debug_printf("%s is listening ...", __FUNCTION__); + + if (!info.isNT) { + status = RpcServerRegisterIf(ccs_request_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL); // MgrEpv; null means use default + } + else { + status = info.fRpcServerRegisterIfEx(ccs_request_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL, // MgrEpv; 0 means default + RPC_IF_ALLOW_SECURE_ONLY, + rcvargs->opts->cMaxCalls, + rcvargs->opts->bSecCallback ? + (RPC_IF_CALLBACK_FN*)sec_callback : 0 ); + } + + if (!status) { + status = RpcServerListen(rcvargs->opts->cMinCalls, + rcvargs->opts->cMaxCalls, + rcvargs->opts->fDontWait); + } + + if (!status) { + if (rcvargs->opts->fDontWait) { + if (hEvent) SetEvent(hEvent); // Ignore any error -- SetEvent is an optimization. + status = RpcMgmtWaitServerListen(); + } + } + } + + if (status) { // Cleanup in case of errors: + if (hEvent) CloseHandle(hEvent); + free_alloc_p(&event_name); + free_alloc_p(&psd); + if (endpoint && (endpoint != rcvargs->opts->pszEndpoint)) + free_alloc_p(&endpoint); + } + + _endthread(); + } // End receiveLoop + + +#if 0 + + return status; +} +#endif + + + +/* ------------------------------------------------------------------------ */ +/* The connection listener thread waits forever for a call to the CCAPI_CLIENT_ + endpoint, ccapi_listen function to complete. If the call completes or gets an + RPC exception, it means the client has disappeared. + + A separate connectionListener is started for each client that has connected to the server. + */ + +void connectionListener(void* rpcargs) { + + struct RpcRcvArgs* rcvargs = (struct RpcRcvArgs*)rpcargs; + RPC_STATUS status = FALSE; + char* endpoint; + unsigned char* pszOptions = NULL; + unsigned char * pszUuid = NULL; + + endpoint = clientEndpoint((char*)rcvargs->uuid); + rpcState = (RPC_ASYNC_STATE*)malloc(sizeof(RPC_ASYNC_STATE)); + status = RpcAsyncInitializeHandle(rpcState, sizeof(RPC_ASYNC_STATE)); + cci_debug_printf(""); + cci_debug_printf("%s About to LISTEN to <%s>", __FUNCTION__, endpoint); + + rpcState->UserInfo = rcvargs->uuid; + rpcState->NotificationType = RpcNotificationTypeApc; + rpcState->u.APC.NotificationRoutine = clientListener; + rpcState->u.APC.hThread = 0; + + /* [If in use] Free previous binding: */ + if (bRpcHandleInited) { + // Free previous binding (could have been used to call ccapi_listen + // in a different client thread). + // Don't check result or update status. + RpcStringFree(&pszStringBinding); + RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); + bRpcHandleInited = FALSE; + } + + /* Set up binding to the client's endpoint: */ + if (!status) { + status = RpcStringBindingCompose( + pszUuid, + pszProtocolSequence, + pszNetworkAddress, + (RPC_CSTR)endpoint, + pszOptions, + &pszStringBinding); + } + + /* Set the binding handle that will be used to bind to the server. */ + if (!status) { + status = RpcBindingFromStringBinding(pszStringBinding, &SERVER_REPLY_RPC_HANDLE); + } + if (!status) {bRpcHandleInited = TRUE;} + + RpcTryExcept { + cci_debug_printf(" Calling remote procedure ccapi_listen"); + ccapi_listen(rpcState, SERVER_REPLY_RPC_HANDLE, CCMSG_LISTEN, &status); + /* Asynchronous call will return immediately. */ + } + RpcExcept(1) { + status = cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + + rcvargs->status = status; + } // End connectionListener + + +void RPC_ENTRY clientListener( + _RPC_ASYNC_STATE* pAsync, + void* Context, + RPC_ASYNC_EVENT Event + ) { + + ccs_pipe_t pipe = ccs_win_pipe_new((char*)pAsync->UserInfo, NULL); + + cci_debug_printf("%s(0x%X, ...) async routine for <0x%X:%s>!", + __FUNCTION__, pAsync, pAsync->UserInfo, pAsync->UserInfo); + + worklist_add( CCMSG_DISCONNECT, + pipe, + NULL, /* No payload with connect request */ + (const time_t)0 ); /* No server session number with connect request */ + } + + +void printError( TCHAR* msg ) { + DWORD eNum; + TCHAR sysMsg[256]; + TCHAR* p; + + eNum = GetLastError( ); + FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, eNum, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + sysMsg, 256, NULL ); + + // Trim the end of the line and terminate it with a null + p = sysMsg; + while( ( *p > 31 ) || ( *p == 9 ) ) + ++p; + do { *p-- = 0; } while( ( p >= sysMsg ) && + ( ( *p == '.' ) || ( *p < 33 ) ) ); + + // Display the message + cci_debug_printf("%s failed with error %d (%s)", msg, eNum, sysMsg); + } + + +RPC_STATUS send_init(char* clientUUID) { + RPC_STATUS status; + unsigned char * pszUuid = NULL; + unsigned char * pszOptions = NULL; + + /* Use a convenience function to concatenate the elements of */ + /* the string binding into the proper sequence. */ + status = RpcStringBindingCompose(pszUuid, + pszProtocolSequence, + pszNetworkAddress, + (unsigned char*)clientEndpoint(clientUUID), + pszOptions, + &pszStringBinding); + if (status) {return (status);} + + /* Set the binding handle that will be used to bind to the RPC server [the 'client']. */ + status = RpcBindingFromStringBinding(pszStringBinding, &SERVER_REPLY_RPC_HANDLE); + return (status); + } + +RPC_STATUS send_finish() { + RPC_STATUS status; + /* Can't shut down client -- it runs listen function which */ + /* server uses to detect the client going away. */ + + /* The calls to the remote procedures are complete. */ + /* Free the string and the binding handle */ + status = RpcStringFree(&pszStringBinding); // remote calls done; unbind + if (status) {return (status);} + + status = RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); // remote calls done; unbind + + return (status); + } + +RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe) { + char* uuid = ccs_win_pipe_getUuid (in_pipe); + HANDLE h = ccs_win_pipe_getHandle(in_pipe); + RPC_STATUS status = send_init(uuid); + + RpcTryExcept { + ccs_rpc_connect_reply( // make call with user message + CCMSG_CONNECT_REPLY, /* Message type */ + (unsigned char*)&h, /* client's tspdata* */ + (unsigned char*)uuid, + getMySST(), /* Server's session number = it's start time */ + &status ); /* Return code */ + } + RpcExcept(1) { + cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + + status = send_finish(); + return (status); + } + +#if 0 +DWORD alloc_name(LPSTR* pname, LPSTR postfix) { + DWORD len = strlen(sessID) + 1 + strlen(postfix) + 1; + + *pname = (LPSTR)malloc(len); + if (!*pname) return GetLastError(); + _snprintf(*pname, len, "%s.%s", sessID, postfix); + return 0; + } +#endif + +RPC_STATUS GetPeerName( RPC_BINDING_HANDLE hClient, + LPTSTR pszClientName, + int iMaxLen) { + RPC_STATUS Status = RPC_S_OK; + RPC_BINDING_HANDLE hServer = NULL; + PTBYTE pszStringBinding = NULL; + PTBYTE pszClientNetAddr = NULL; + PTBYTE pszProtSequence = NULL; + + memset(pszClientName, 0, iMaxLen * sizeof(TCHAR)); + + __try { + // Create a partially bound server handle from the client handle. + Status = RpcBindingServerFromClient (hClient, &hServer); + if (Status != RPC_S_OK) __leave; + + // Get the partially bound server string binding and parse it. + Status = RpcBindingToStringBinding (hServer, + &pszStringBinding); + if (Status != RPC_S_OK) __leave; + + // String binding only contains protocol sequence and client + // address, and is not currently implemented for named pipes. + Status = RpcStringBindingParse (pszStringBinding, NULL, + &pszProtSequence, &pszClientNetAddr, + NULL, NULL); + if (Status != RPC_S_OK) + __leave; + int iLen = lstrlen(pszClientName) + 1; + if (iMaxLen < iLen) + Status = RPC_S_BUFFER_TOO_SMALL; + lstrcpyn(pszClientName, (LPCTSTR)pszClientNetAddr, iMaxLen); + } + __finally { + if (pszProtSequence) + RpcStringFree (&pszProtSequence); + + if (pszClientNetAddr) + RpcStringFree (&pszClientNetAddr); + + if (pszStringBinding) + RpcStringFree (&pszStringBinding); + + if (hServer) + RpcBindingFree (&hServer); + } + return Status; +} + +struct client_auth_info { + RPC_AUTHZ_HANDLE authz_handle; + unsigned char* server_principal; // need to RpcFreeString this + ULONG authn_level; + ULONG authn_svc; + ULONG authz_svc; +}; + +RPC_STATUS +GetClientId( + RPC_BINDING_HANDLE hClient, + char* client_id, + int max_len, + client_auth_info* info + ) +{ + RPC_AUTHZ_HANDLE authz_handle = 0; + unsigned char* server_principal = 0; + ULONG authn_level = 0; + ULONG authn_svc = 0; + ULONG authz_svc = 0; + RPC_STATUS status = 0; + + memset(client_id, 0, max_len); + + if (info) { + memset(info, 0, sizeof(client_auth_info)); + } + + status = RpcBindingInqAuthClient(hClient, &authz_handle, + info ? &server_principal : 0, + &authn_level, &authn_svc, &authz_svc); + if (status == RPC_S_OK) + { + if (info) { + info->server_principal = server_principal; + info->authz_handle = authz_handle; + info->authn_level = authn_level; + info->authn_svc = authn_svc; + info->authz_svc = authz_svc; + } + + if (authn_svc == RPC_C_AUTHN_WINNT) { + WCHAR* username = (WCHAR*)authz_handle; + int len = lstrlenW(username) + 1; + if (max_len < len) + status = RPC_S_BUFFER_TOO_SMALL; + _snprintf(client_id, max_len, "%S", username); + } else { + status = RPC_S_UNKNOWN_AUTHN_SERVICE; + } + } + return status; +} + +char* +rpc_error_to_string( + RPC_STATUS status + ) +{ + switch(status) { + case RPC_S_OK: + return "OK"; + case RPC_S_INVALID_BINDING: + return "Invalid binding"; + case RPC_S_WRONG_KIND_OF_BINDING: + return "Wrong binding"; + case RPC_S_BINDING_HAS_NO_AUTH: + RpcRaiseException(RPC_S_BINDING_HAS_NO_AUTH); + return "Binding has no auth"; + default: + return "BUG: I am confused"; + } +} + +void +print_client_info( + RPC_STATUS peer_status, + const char* peer_name, + RPC_STATUS client_status, + const char* client_id, + client_auth_info* info + ) +{ + if (peer_status == RPC_S_OK || peer_status == RPC_S_BUFFER_TOO_SMALL) { + cci_debug_printf("%s Peer Name is \"%s\"", __FUNCTION__, peer_name); + } else { + cci_debug_printf("%s Error %u getting Peer Name (%s)", + __FUNCTION__, peer_status, rpc_error_to_string(peer_status)); + } + + if (client_status == RPC_S_OK || client_status == RPC_S_BUFFER_TOO_SMALL) { + if (info) { + cci_debug_printf("%s Client Auth Info" + "\tServer Principal: %s\n" + "\tAuthentication Level: %d\n" + "\tAuthentication Service: %d\n" + "\tAuthorization Service: %d\n", + __FUNCTION__, + info->server_principal, + info->authn_level, + info->authn_svc, + info->authz_svc); + } + cci_debug_printf("%s Client ID is \"%s\"", __FUNCTION__, client_id); + } else { + cci_debug_printf("%s Error getting Client Info (%u = %s)", + __FUNCTION__, client_status, rpc_error_to_string(client_status)); + } +} + +DWORD sid_check() { + DWORD status = 0; + HANDLE hToken_c = 0; + HANDLE hToken_s = 0; + PTOKEN_USER ptu_c = 0; + PTOKEN_USER ptu_s = 0; + DWORD len = 0; + BOOL bImpersonate = FALSE; + + // Note GetUserName will fail while impersonating at identify + // level. The workaround is to impersonate, OpenThreadToken, + // revert, call GetTokenInformation, and finally, call + // LookupAccountSid. + + // XXX - Note: This workaround does not appear to work. + // OpenThreadToken fails with error 1346: "Either a requid + // impersonation level was not provided or the provided + // impersonation level is invalid". + + status = RpcImpersonateClient(0); + + if (!status) { + bImpersonate = TRUE; + if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken_c)) + status = GetLastError(); + } + + if (!status) { + status = RpcRevertToSelf(); + } + + if (!status) { + bImpersonate = FALSE; + + len = 0; + GetTokenInformation(hToken_c, TokenUser, ptu_c, 0, &len); + if (len == 0) status = 1; + } + + if (!status) { + if (!(ptu_c = (PTOKEN_USER)LocalAlloc(0, len))) + status = GetLastError(); + } + + if (!status) { + if (!GetTokenInformation(hToken_c, TokenUser, ptu_c, len, &len)) + status = GetLastError(); + } + + if (!status) { + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken_s)) + status = GetLastError(); + } + + if (!status) { + len = 0; + GetTokenInformation(hToken_s, TokenUser, ptu_s, 0, &len); + if (len == 0) status = GetLastError(); + } + + if (!status) { + if (!(ptu_s = (PTOKEN_USER)LocalAlloc(0, len))) + status = GetLastError(); + } + + if (!status) { + if (!GetTokenInformation(hToken_s, TokenUser, ptu_s, len, &len)) + status = GetLastError(); + } + + if (!EqualSid(ptu_s->User.Sid, ptu_c->User.Sid)) + status = RPC_S_ACCESS_DENIED; + +/* Cleanup: */ + if (!hToken_c && !bImpersonate) + cci_debug_printf("%s Cannot impersonate (%u)", __FUNCTION__, status); + else if (!hToken_c) + cci_debug_printf("%s Failed to open client token (%u)", __FUNCTION__, status); + else if (bImpersonate) + cci_debug_printf("%s Failed to revert (%u)", __FUNCTION__, status); + else if (!ptu_c) + cci_debug_printf("%s Failed to get client token user info (%u)", + __FUNCTION__, status); + else if (!hToken_s) + cci_debug_printf("%s Failed to open server token (%u)", __FUNCTION__, status); + else if (!ptu_s) + cci_debug_printf("%s Failed to get server token user info (%u)", + __FUNCTION__, status); + else if (status == RPC_S_ACCESS_DENIED) + cci_debug_printf("%s SID **does not** match!", __FUNCTION__); + else if (status == RPC_S_OK) + cci_debug_printf("%s SID matches!", __FUNCTION__); + else + if (status) { + cci_debug_printf("%s unrecognized error %u", __FUNCTION__, status); + abort(); + } + + if (bImpersonate) RpcRevertToSelf(); + if (hToken_c && hToken_c != INVALID_HANDLE_VALUE) + CloseHandle(hToken_c); + if (ptu_c) LocalFree(ptu_c); + if (hToken_s && hToken_s != INVALID_HANDLE_VALUE) + CloseHandle(hToken_s); + if (ptu_s) LocalFree(ptu_s); + if (status) cci_debug_printf("%s returning %u", __FUNCTION__, status); + return status; + } + +RPC_STATUS RPC_ENTRY sec_callback( IN RPC_IF_ID *Interface, + IN void *Context) { + char peer_name[1024]; + char client_name[1024]; + RPC_STATUS peer_status; + RPC_STATUS client_status; + + cci_debug_printf("%s", __FUNCTION__); + peer_status = GetPeerName(Context, peer_name, sizeof(peer_name)); + client_status = GetClientId(Context, client_name, sizeof(client_name), 0); + print_client_info(peer_status, peer_name, client_status, client_name, 0); + DWORD sid_status = sid_check(); + cci_debug_printf("%s returning (%u)", __FUNCTION__, sid_status); + return sid_status; + } + + + +/*********************************************************************/ +/* MIDL allocate and free */ +/*********************************************************************/ + +void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { + return(malloc(len)); + } + +void __RPC_USER midl_user_free(void __RPC_FAR * ptr) { + free(ptr); + } diff --git a/src/ccapi/server/win/ccs_request_proc.c b/src/ccapi/server/win/ccs_request_proc.c new file mode 100644 index 000000000..40713fb50 --- /dev/null +++ b/src/ccapi/server/win/ccs_request_proc.c @@ -0,0 +1,116 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include +#include + +#include "ccs_request.h" // header file generated by MIDL compiler +#include "cci_debugging.h" +#include "WorkQueue.h" +#include "win-utils.h" +#include "ccs_win_pipe.h" + +void ccs_rpc_request( + const long rpcmsg, /* Message type */ + const char tspHandle[], /* Client's tspdata* */ + const char* pszUUID, /* Where client will listen for the reply */ + const long lenRequest, /* Length of buffer */ + const char pbRequest[], /* Data buffer */ + const long serverStartTime, /* Which server session we're talking to */ + long* return_status ) { /* Return code */ + + cc_int32 status = 0; + cci_stream_t stream; + DWORD* p = (DWORD*)(tspHandle); + WIN_PIPE* pipe = NULL; + + cci_debug_printf("%s rpcmsg:%d; UUID:<%s> SST:<%s>", + __FUNCTION__, rpcmsg, pszUUID, serverStartTime); + + status = (rpcmsg != CCMSG_REQUEST) && (rpcmsg != CCMSG_PING); + + if (!status) { + status = cci_stream_new (&stream); /* Create a stream for the request data */ + } + + if (!status) { /* Put the data into the stream */ + status = cci_stream_write (stream, pbRequest, lenRequest); + } + + pipe = ccs_win_pipe_new(pszUUID, *p); + worklist_add(rpcmsg, pipe, stream, serverStartTime); + *return_status = status; + } + + +void ccs_rpc_connect( + const long rpcmsg, /* Message type */ + const char tspHandle[], /* Client's tspdata* */ + const char* pszUUID, /* Data buffer */ + long* return_status ) { /* Return code */ + + DWORD* p = (DWORD*)(tspHandle); + WIN_PIPE* pipe = ccs_win_pipe_new(pszUUID, *p); + + cci_debug_printf("%s; rpcmsg:%d; UUID: <%s>", __FUNCTION__, rpcmsg, pszUUID); + + worklist_add( rpcmsg, + pipe, + NULL, /* No payload with connect request */ + (const time_t)0 ); /* No server session number with connect request */ + } + + +// 'Authentication' is client setting a value in a file and the server +// returning that value plus one. +CC_UINT32 ccs_authenticate(const CC_CHAR* name) { + HANDLE hMap = 0; + PDWORD pvalue = 0; + CC_UINT32 result = 0; + DWORD status = 0; + + cci_debug_printf("%s ( %s )", __FUNCTION__, name); + + hMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, (LPSTR)name); + status = !hMap; + + if (!status) { + pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0); + status = !pvalue; + } + + if (!status) { + *pvalue += 1; + result = *pvalue; + } + + if (pvalue) { + UnmapViewOfFile(pvalue); + } + + if (hMap) CloseHandle(hMap); + return result; + } \ No newline at end of file diff --git a/src/ccapi/server/win/ccs_win_pipe.c b/src/ccapi/server/win/ccs_win_pipe.c new file mode 100644 index 000000000..4d121aaea --- /dev/null +++ b/src/ccapi/server/win/ccs_win_pipe.c @@ -0,0 +1,163 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "assert.h" + +#include "ccs_win_pipe.h" +#include "cci_debugging.h" + +/* Ref: +struct ccs_win_pipe_t { + char* uuid; + HANDLE clientHandle; + } + */ + +/* ------------------------------------------------------------------------ */ + +struct ccs_win_pipe_t* ccs_win_pipe_new (const char* uuid, const HANDLE h) { + + cc_int32 err = ccNoError; + struct ccs_win_pipe_t* out_pipe = NULL; + char* uuidCopy = NULL; + + if (!err) { + if (!uuid) {err = cci_check_error(ccErrBadParam);} + } + + if (!err) { + uuidCopy = (char*)malloc(1+strlen(uuid)); + if (!uuidCopy) {err = cci_check_error(ccErrBadParam);} + strcpy(uuidCopy, uuid); + } + + if (!err) { + out_pipe = (struct ccs_win_pipe_t*)malloc(sizeof(struct ccs_win_pipe_t)); + if (!out_pipe) {err = cci_check_error(ccErrBadParam);} + out_pipe->uuid = uuidCopy; + out_pipe->clientHandle = h; + } + + cci_debug_printf("0x%X = %s(%s, 0x%X)", out_pipe, __FUNCTION__, uuid, h); + + return out_pipe; + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_win_pipe_copy (WIN_PIPE** out_pipe, + const WIN_PIPE* in_pipe) { + + *out_pipe = + ccs_win_pipe_new( + ccs_win_pipe_getUuid (in_pipe), + ccs_win_pipe_getHandle(in_pipe) ); + + return (*out_pipe) ? ccNoError : ccErrBadParam; + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_win_pipe_release(const WIN_PIPE* in_pipe) { + + cc_int32 err = ccNoError; + + if (!ccs_win_pipe_valid(in_pipe)) {err = cci_check_error(ccErrBadParam);} + + if (!err) { + if (!in_pipe->uuid) free(in_pipe->uuid); + if (!in_pipe) free(in_pipe); + } + + return err; + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_win_pipe_valid (const WIN_PIPE* in_pipe) { + + if (!in_pipe) { + cci_check_error(ccErrBadParam); + return FALSE; + } + + if (!in_pipe->uuid) { + cci_check_error(ccErrBadParam); + return FALSE; + } + + return TRUE; + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_win_pipe_compare (const WIN_PIPE* in_pipe_1, + const WIN_PIPE* in_pipe_2, + cc_uint32 *out_equal) { + + cc_int32 err = ccNoError; + int seq = 0; + *out_equal = FALSE; + + if (!ccs_win_pipe_valid(in_pipe_1)) {err = cci_check_error(ccErrBadParam);} + if (!ccs_win_pipe_valid(in_pipe_2)) {err = cci_check_error(ccErrBadParam);} + if (!out_equal) {err = cci_check_error(ccErrBadParam);} + + /* A disconnect doesn't have a tls* with it -- only the uuid. SO only + compare the uuids. + */ + if (!err) { + seq = strcmp( ccs_win_pipe_getUuid(in_pipe_1), + ccs_win_pipe_getUuid(in_pipe_2) ); + *out_equal = (seq == 0); + } + + return err; + } + +/* ------------------------------------------------------------------------ */ + +char* ccs_win_pipe_getUuid (const WIN_PIPE* in_pipe) { + + char* result = NULL; + + if (!ccs_win_pipe_valid(in_pipe)) {cci_check_error(ccErrBadParam);} + else {result = in_pipe->uuid;} + + return result; + } + +/* ------------------------------------------------------------------------ */ + +HANDLE ccs_win_pipe_getHandle (const WIN_PIPE* in_pipe) { + + HANDLE result = NULL; + + if (!ccs_win_pipe_valid(in_pipe)) {cci_check_error(ccErrBadParam);} + else {result = in_pipe->clientHandle;} + + return result; + } diff --git a/src/ccapi/server/win/ccs_win_pipe.h b/src/ccapi/server/win/ccs_win_pipe.h new file mode 100644 index 000000000..afabe12fe --- /dev/null +++ b/src/ccapi/server/win/ccs_win_pipe.h @@ -0,0 +1,69 @@ +/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#ifndef _ccs_win_pipe_h_ +#define _ccs_win_pipe_h_ + +#include "windows.h" + +#include "CredentialsCache.h" + +/* ------------------------------------------------------------------------ */ + +/* On Windows, a pipe is a struct containing a UUID and a handle. Both the + UUID and handle are supplied by the client. + + The UUID is used to build the client's reply endpoint. + + The handle is to the requesting client thread's thread local storage struct, + so that the client's one and only reply handler can put reply data where + the requesting thread will be able to see it. + */ + +struct ccs_win_pipe_t { + char* uuid; + HANDLE clientHandle; + }; + +typedef struct ccs_win_pipe_t WIN_PIPE; + +struct ccs_win_pipe_t* ccs_win_pipe_new(const char* uuid, const HANDLE h); + +cc_int32 ccs_win_pipe_release (const WIN_PIPE* io_pipe); + +cc_int32 ccs_win_pipe_compare (const WIN_PIPE* win_pipe_1, + const WIN_PIPE* win_pipe_2, + cc_uint32 *out_equal); + +cc_int32 ccs_win_pipe_copy (WIN_PIPE** out_pipe, + const WIN_PIPE* in_pipe); + +cc_int32 ccs_win_pipe_valid (const WIN_PIPE* in_pipe); + +char* ccs_win_pipe_getUuid (const WIN_PIPE* in_pipe); +HANDLE ccs_win_pipe_getHandle (const WIN_PIPE* in_pipe); + +#endif // _ccs_win_pipe_h_ \ No newline at end of file diff --git a/src/ccapi/server/win/workitem.h b/src/ccapi/server/win/workitem.h new file mode 100644 index 000000000..a9d1c0e29 --- /dev/null +++ b/src/ccapi/server/win/workitem.h @@ -0,0 +1,48 @@ +#ifndef __WorkItem +#define __WorkItem + +#include +#include "windows.h" + +extern "C" { + #include "cci_stream.h" + #include "ccs_pipe.h" + } + +class WorkItem { +private: + cci_stream_t _buf; + WIN_PIPE* _pipe; + const long _rpcmsg; + const long _sst; +public: + WorkItem( cci_stream_t buf, + WIN_PIPE* pipe, + const long type, + const long serverStartTime); + WorkItem( const WorkItem&); + WorkItem(); + ~WorkItem(); + + const cci_stream_t payload() const {return _buf;} + const cci_stream_t take_payload(); + WIN_PIPE* take_pipe(); + WIN_PIPE* pipe() const {return _pipe;} + const long type() const {return _rpcmsg;} + const long sst() const {return _sst;} + char* print(char* buf); + }; + +class WorkList { +private: + std::list wl; + CRITICAL_SECTION cs; +public: + WorkList(); + ~WorkList(); + int add(WorkItem*); + int remove(WorkItem**); + bool isEmpty() {return wl.empty();} + }; + +#endif // __WorkItem \ No newline at end of file diff --git a/src/ccapi/test/Makefile.w32 b/src/ccapi/test/Makefile.w32 new file mode 100644 index 000000000..077c20b06 --- /dev/null +++ b/src/ccapi/test/Makefile.w32 @@ -0,0 +1,64 @@ +# . is ccapi/test. +CO = ..\common +COWIN = $(CO)\win +LIBDIR = ..\lib +LIBWIN = $(LIBDIR)\win + +!include + +INC = -I..\..\include -I..\..\util\et -I$(CO) -I$(COWIN) -I$(LIBDIR) -I$(LIBWIN) + +!if "$(CPU)" == "i386" +cflags = $(cflags) /EHsc /MTd -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 -D_WIN32_WINNT=0x0501 \ +$(INC) +!else +cflags = $(cflags) /W3 -D_CRTAPI1= -D_CRTAPI2= $(INC) +!endif +LIBS = $(LIBWIN)\ccapi.lib + +DSTROOT = . +SRC = $(DSTROOT) +#OBJDIR = $(DSTROOT)\obj +OBJDIR = . +OBJEXT = obj +TESTDIR = $(DSTROOT)\tests +TESTEXT = exe +DSTDIR = $(DSTROOT)\ccapi_tests +PINGOBJS = pingtest.obj ccs_request_c.obj +SIMPLEOBJS = simple_lock_test.obj + +OBJS = cci_debugging.$(OBJEXT) \ + ccs_request_c.obj \ + cci_os_debugging.$(OBJEXT) \ + win-utils.obj \ + ccapi_os_ipc.obj \ + cci_stream.obj + +#all: build-base simple_lock_test pingtest +all: build-base pingtest + +# compile base files used by all tests +build-base: $(OBJS) + @echo "Base objects built." + +# rule to compile src files +.c.obj: + $(cc) $(cdebug) $(cflags) /Fo$(OBJDIR)\$(*B).$(OBJEXT) $(SRC)\$(*B).c + +simple_lock_test: simple_lock_test.obj $(OBJS) + @echo R3+ Build $(*B) in $(TESTDIR) + $(cc) $(cdebug) $(cflags) $(*B).c + $(link) $(linkdebug) $(conflags) -out:$(TESTDIR)\$(*B).exe $(*B).obj \ + $(LIBS) rpcrt4.lib + @echo R3- Built $(*B) in $(TESTDIR) + +pingtest: pingtest.obj + @echo R4+ Build $(*B) in $(TESTDIR) + $(cc) $(cdebug) $(cflags) $(*B).c +# $(link) $(linkdebug) $(conflags) -out:$(*B).exe $(*B).obj \ + $(link) $(linkdebug) $(conflags) -out:$(*B).exe $(PINGOBJS) \ + $(LIBS) rpcrt4.lib + @echo R4- Built $(*B) in $(TESTDIR) + +clean: + DEL *.$(OBJEXT) \ No newline at end of file diff --git a/src/ccapi/test/pingtest.c b/src/ccapi/test/pingtest.c new file mode 100644 index 000000000..992772586 --- /dev/null +++ b/src/ccapi/test/pingtest.c @@ -0,0 +1,108 @@ +// pingtest.c +// +// Test RPC to server, with PING message, which exists for no other purpose than this test. + +#include +#include + +#include "cci_debugging.h" +#include "CredentialsCache.h" +#include "cci_stream.h" +#include "win-utils.h" + +#include "ccs_request.h" +#define CLIENT_REQUEST_RPC_HANDLE ccs_request_IfHandle + + +extern cc_int32 cci_os_ipc_thread_init (void); +extern cc_int32 cci_os_ipc_msg( cc_int32 in_launch_server, + cci_stream_t in_request_stream, + cc_int32 in_msg, + cci_stream_t* out_reply_stream); + +RPC_STATUS send_test(char* endpoint) { + unsigned char* pszNetworkAddress = NULL; + unsigned char* pszOptions = NULL; + unsigned char* pszStringBinding = NULL; + unsigned char* pszUuid = NULL; + RPC_STATUS status; + + status = RpcStringBindingCompose(pszUuid, + (RPC_CSTR)"ncalrpc", + pszNetworkAddress, + (unsigned char*)endpoint, + pszOptions, + &pszStringBinding); + cci_debug_printf("%s pszStringBinding = %s", __FUNCTION__, pszStringBinding); + if (status) {return cci_check_error(status);} + + /* Set the binding handle that will be used to bind to the RPC server [the 'client']. */ + status = RpcBindingFromStringBinding(pszStringBinding, &CLIENT_REQUEST_RPC_HANDLE); + if (status) {return cci_check_error(status);} + + status = RpcStringFree(&pszStringBinding); // Temp var no longer needed. + + if (!status) { + RpcTryExcept { + cci_debug_printf("%s calling remote procedure 'ccs_authenticate'", __FUNCTION__); + status = ccs_authenticate((CC_CHAR*)"DLLMAIN TEST!"); + cci_debug_printf(" ccs_authenticate returned %d", status); + } + RpcExcept(1) { + status = cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + } + + cci_check_error(RpcBindingFree(&CLIENT_REQUEST_RPC_HANDLE)); + + return (status); + } + +int main( int argc, char *argv[]) { + cc_int32 err = 0; + cc_context_t context = NULL; + cci_stream_t send_stream = NULL; + cci_stream_t reply_stream = NULL; + char* message = "Hello, RPC!"; + + +// send_test("krbcc.229026.0.ep"); + +#if 0 + err = cc_initialize(&context, ccapi_version_7, NULL, NULL); +#endif + + if (!err) { + err = cci_os_ipc_thread_init(); + } + if (!err) { + err = cci_stream_new (&send_stream); + err = cci_stream_write(send_stream, message, 1+strlen(message)); + } + + if (!err) { + err = cci_os_ipc_msg(TRUE, send_stream, CCMSG_PING, &reply_stream); + } + Sleep(10*1000); + cci_debug_printf("Try finishing async call."); + + Sleep(INFINITE); + cci_debug_printf("main: return. err == %d", err); + + return 0; + } + + + +/*********************************************************************/ +/* MIDL allocate and free */ +/*********************************************************************/ + +void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { + return(malloc(len)); + } + +void __RPC_USER midl_user_free(void __RPC_FAR * ptr) { + free(ptr); + } diff --git a/src/ccapi/test/simple_lock_test.c b/src/ccapi/test/simple_lock_test.c index 6674a1ef6..254663c3a 100644 --- a/src/ccapi/test/simple_lock_test.c +++ b/src/ccapi/test/simple_lock_test.c @@ -1,69 +1,84 @@ -/* - simple_lock_test.c - - Initializes two contexts in two different threads and tries to get read locks on both at the same time. - Hangs at line 24. -*/ -#include -#include -#include -#include -#include - -void * other_thread () -{ - cc_int32 err; - cc_context_t context = NULL; - - err = cc_initialize(&context, ccapi_version_7, NULL, NULL); - - fprintf(stderr, "thread: attempting lock. may hang. err == %d\n", err); - - if (!err) { - // hangs with cc_lock_read which should succeed immediately, but does not hang with write, upgrade, and downgrade, which fail immediately - err = cc_context_lock(context, cc_lock_read, cc_lock_noblock); - } - - if (context) { - cc_context_unlock(context); - cc_context_release(context); - context = NULL; - } - fprintf(stderr, "thread: return. err == %d\n", err); -} - - -int main (int argc, char *argv[]) -{ - cc_int32 err; - int status; - pthread_t thread_id; - cc_context_t context = NULL; - - err = cc_initialize(&context, ccapi_version_7, NULL, NULL); - if (!err) { - err = cc_context_lock(context, cc_lock_read, cc_lock_noblock); - } - - fprintf(stderr, "main: initialized and read locked context. err == %d\n", err); - - status = pthread_create (&thread_id, NULL, (void *) other_thread, NULL); - if (status != 0) { - fprintf(stderr,"Create error!\n"); - exit(-1); - } - - pthread_join(thread_id, NULL); - - fprintf(stderr, "main: unlocking and releasing context. err == %d\n", err); - - if (context) { - cc_context_unlock(context); - cc_context_release(context); - context = NULL; - } - - fprintf(stderr, "main: return. err == %d\n", err); - - return 0; -} \ No newline at end of file +/* + simple_lock_test.c + + Initializes two contexts in two different threads and tries to get read locks on both at the same time. + Hangs at line 24. +*/ +#include +#include + +#include "cci_debugging.h" + +#ifdef TARGET_OS_MAC +#include +#include +#else +#include "CredentialsCache.h" +#endif + + +void * other_thread () { + cc_int32 err; + cc_context_t context = NULL; + + err = cc_initialize(&context, ccapi_version_7, NULL, NULL); + + cci_debug_printf("thread: attempting lock. may hang. err == %d", err); + + if (!err) { + // hangs with cc_lock_read which should succeed immediately, but does not hang with write, upgrade, and downgrade, which fail immediately + err = cc_context_lock(context, cc_lock_read, cc_lock_noblock); + } + + if (context) { + cc_context_unlock(context); + cc_context_release(context); + context = NULL; + } + cci_debug_printf("thread: return. err == %d", err); + } + + +int main (int argc, char *argv[]) { + cc_int32 err; + int status; + cc_context_t context = NULL; + +#ifdef TARGET_OS_MAC + pthread_t thread_id; +#endif + + err = cc_initialize(&context, ccapi_version_7, NULL, NULL); + if (!err) { + err = cc_context_lock(context, cc_lock_read, cc_lock_noblock); + } + + cci_debug_printf("main: initialized and read locked context. err == %d", err); + +#ifdef TARGET_OS_MAC + status = pthread_create (&thread_id, NULL, (void *) other_thread, NULL); + if (status != 0) { + cci_debug_printf("Create error!"); + exit(-1); + } + + pthread_join(thread_id, NULL); +#else + +#endif + + cci_debug_printf("main: unlocking and releasing context. err == %d", err); + + if (context) { + cci_debug_printf("main: calling cc_context_unlock"); + cc_context_unlock(context); + cci_debug_printf("main: calling cc_context_release"); + cc_context_release(context); + context = NULL; + } + + cci_debug_printf("main: return. err == %d", err); + + UNREFERENCED_PARAMETER(status); // no whining! + return 0; + } \ No newline at end of file -- 2.26.2