extern "C" {
#include "k5-thread.h"
#include "ccapi_os_ipc.h"
#include "cci_debugging.h"
#include "ccs_reply.h"
#include "ccs_request.h"
#include "ccutils.h"
#include "tls.h"
#include "util.h"
#include "win-utils.h"
}
#include "autolock.hxx"
#include "CredentialsCache.h"
#include "secure.hxx"
#include "opts.hxx"
#include "client.h"
extern "C" DWORD GetTlsIndex();
#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 };
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,
k5_ipc_stream in_request_stream,
cc_int32 in_msg,
k5_ipc_stream* 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(GetTlsIndex(), &ptspdata)) return ccErrNoMem;
opts.cMinCalls = 1;
opts.cMaxCalls = 20;
opts.fDontWait = TRUE;
err = cci_check_error(UuidCreate(&uuid)); if (err == RPC_S_OK) { err = UuidToString(&uuid, &uuidString);
}
if (!err) { tspdata_setUUID(ptspdata, uuidString);
}
#if 0
cci_debug_printf("%s UUID:<%s>", __FUNCTION__, tspdata_getUUID(ptspdata));
#endif
if (!err) if (!Init:: Initialized()) err = Init:: Initialize( );
if (!err) if (!Client::Initialized()) err = Client::Initialize(0);
if (!err) {
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);
}
void cci_os_ipc_thread_fini (void)
{
}
cc_int32 cci_os_ipc (cc_int32 in_launch_server,
k5_ipc_stream in_request_stream,
k5_ipc_stream* 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,
k5_ipc_stream in_request_stream,
cc_int32 in_msg,
k5_ipc_stream* 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(GetTlsIndex(), &ptspdata)) {return ccErrBadParam;}
bCCAPI_Connected = tspdata_getConnected (ptspdata);
replyEvent = tspdata_getReplyEvent (ptspdata);
sst = tspdata_getSST (ptspdata);
uuid = tspdata_getUUID(ptspdata);
if (!bCCAPI_Connected) {
err = cci_check_error(ccapi_connect(ptspdata));
bCCAPI_Connected = !err;
tspdata_setConnected(ptspdata, bCCAPI_Connected);
}
ResetEvent(replyEvent);
WaitForSingleObject( hCCAPIv2Mutex, INFINITE );
SecureClient* s = 0;
SecureClient::Start(s);
CcAutoLock* a = 0;
CcAutoLock::Start(a, Client::sLock);
if (!err) if (!Init:: Initialized()) err = cci_check_error(Init:: Initialize( ));
if (!err) if (!Client::Initialized()) err = cci_check_error(Client::Initialize(0));
if (!err) {
RpcTryExcept {
if (!GetTspData(GetTlsIndex(), &ptspdata)) {return ccErrBadParam;}
uuid = tspdata_getUUID(ptspdata);
lenUUID = 1 + strlen(uuid);
#if 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);
#endif
ccs_rpc_request(
in_msg,
(unsigned char*)&ptspdata,
(unsigned char*)uuid,
k5_ipc_stream_size(in_request_stream),
(unsigned char*)k5_ipc_stream_data(in_request_stream),
sst,
(long*)(&err) );
}
RpcExcept(1) {
handle_exception(RpcExceptionCode());
}
RpcEndExcept;
}
cci_check_error(err);
CcAutoLock::Stop(a);
SecureClient::Stop(s);
ReleaseMutex(hCCAPIv2Mutex);
if (!err) {
err = cci_check_error(WaitForSingleObject(replyEvent, INFINITE)); }
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;
}
#endif
if (!err) {
*out_reply_stream = tspdata_getStream(ptspdata);
}
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;
}
cc_int32 ccapi_connect(const struct tspdata* tsp) {
BOOL bListen = TRUE;
char* endpoint = NULL;
HANDLE replyEvent = 0;
RPC_STATUS status = FALSE;
char* uuid = NULL;
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); cci_check_error(status);
}
if (!status) {
status = RpcServerRegisterAuthInfo(0, 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, NULL, NULL); }
else {
status = RpcServerRegisterIfEx(ccs_reply_ServerIfHandle, NULL, NULL, RPC_IF_ALLOW_SECURE_ONLY,
opts.cMaxCalls,
NULL); }
cci_check_error(status);
if (!status) {
status = RpcServerListen(opts.cMinCalls,
opts.cMaxCalls,
TRUE);
cci_check_error(status);
}
}
ResetEvent(replyEvent);
WaitForSingleObject( hCCAPIv2Mutex, INFINITE );
SecureClient* s = 0;
SecureClient::Start(s);
CcAutoLock* a = 0;
CcAutoLock::Start(a, Client::sLock);
if (!status) if (!Init:: Initialized()) status = Init:: Initialize( );
if (!status) if (!Client::Initialized()) status = Client::Initialize(0);
if (!status) {
RpcTryExcept {
ccs_rpc_connect(
CCMSG_CONNECT,
(unsigned char*)&tsp,
(unsigned char*)uuid,
(long*)(&status) );
}
RpcExcept(1) {
cci_check_error(RpcExceptionCode());
status = ccErrBadInternalMessage;
}
RpcEndExcept;
}
CcAutoLock::Stop(a);
SecureClient::Stop(s);
ReleaseMutex(hCCAPIv2Mutex);
if (!status) {
#if 0
cci_debug_printf("%s Waiting for replyEvent.", __FUNCTION__);
#endif
status = WaitForSingleObject(replyEvent, INFINITE); 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);
}
return status;
}