From 3d6591dd63c23bcc0ae68e94a960c85fd53daad0 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Mon, 5 Jun 2006 04:30:35 +0000 Subject: more updates git-svn-id: svn://anonsvn.mit.edu/krb5/branches/ccapi@18082 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/ccapi/windows/server.c | 638 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 638 insertions(+) create mode 100644 src/lib/ccapi/windows/server.c (limited to 'src/lib/ccapi/windows/server.c') diff --git a/src/lib/ccapi/windows/server.c b/src/lib/ccapi/windows/server.c new file mode 100644 index 000000000..5ce8e6ebe --- /dev/null +++ b/src/lib/ccapi/windows/server.c @@ -0,0 +1,638 @@ + + +#include +#include "msg.h" +#include "marshall.h" +#include "serv_ops.h" +#include "datastore.h" +#include +#include +#include +#include +#include +#include "ntccrpc.h" +#include + +#define SVCNAME "MIT_CCAPI_NT_Service" + +SERVICE_STATUS_HANDLE h_service_status = NULL; +SERVICE_STATUS service_status; +FILE * logfile = NULL; + +/* Log File */ +void begin_log(void) { + char temppath[512]; + + temppath[0] = L'\0'; + + GetTempPathA(sizeof(temppath), temppath); + StringCbCatA(temppath, sizeof(temppath), "mit_nt_ccapi.log"); + logfile = fopen(temppath, "w"); +} + +void end_log(void) { + if (logfile) { + fclose(logfile); + logfile = NULL; + } +} + +BOOL report_status(DWORD state, + DWORD exit_code, + DWORD wait_hint) { + static DWORD checkpoint = 1; + BOOL rv = TRUE; + + if (state == SERVICE_START_PENDING) + service_status.dwControlsAccepted = 0; + else + service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP; + + service_status.dwCurrentState = state; + service_status.dwWin32ExitCode = exit_code; + service_status.dwWaitHint = wait_hint; + + if (state == SERVICE_RUNNING || + state == SERVICE_STOPPED) + service_status.dwCheckPoint = 0; + else + service_status.dwCheckPoint = checkpoint++; + + rv = SetServiceStatus(h_service_status, &service_status); + + return rv; +} + +void service_start(DWORD argc, LPTSTR * argv) { + RPC_STATUS status; + RPC_BINDING_VECTOR * bv; + + status = RpcServerUseProtseq("ncalrpc", + RPC_C_PROTSEQ_MAX_REQS_DEFAULT, + NULL); + + if (status != RPC_S_OK) { + return; + } + + report_status(SERVICE_START_PENDING, NO_ERROR, 3000); + + status = RpcServerRegisterIf(portable_ccapi_v1_0_s_ifspec, + 0, 0); + + if (status != RPC_S_OK) + return; + + report_status(SERVICE_START_PENDING, NO_ERROR, 3000); + + status = RpcServerInqBindings(&bv); + + if (status != RPC_S_OK) + return; + + status = RpcEpRegister(portable_ccapi_v1_0_s_ifspec, + bv, 0, 0); + + if (status != RPC_S_OK) + return; + + report_status(SERVICE_START_PENDING, NO_ERROR, 3000); + + status = RpcServerRegisterAuthInfo(NULL, + RPC_C_AUTHN_WINNT, + 0, 0); + + if (status != RPC_S_OK) + return; + + report_status(SERVICE_START_PENDING, NO_ERROR, 3000); + + status = RpcServerListen(1, + RPC_C_LISTEN_MAX_CALLS_DEFAULT, + TRUE); + + if (status != RPC_S_OK) + return; + + report_status(SERVICE_RUNNING, NO_ERROR, 0); + + begin_log(); + + status = RpcMgmtWaitServerListen(); + + end_log(); + + RpcEpUnregister(portable_ccapi_v1_0_s_ifspec, bv, 0); + + RpcBindingVectorFree(&bv); +} + +void service_stop(void) { + RpcMgmtStopServerListening(0); +} + +void * __RPC_USER MIDL_user_allocate(size_t s) { + return malloc(s); +} + +void __RPC_USER MIDL_user_free(void * p) { + free(p); +} + +typedef struct tag_client_info { + char client_name[512]; + LUID luid; +} client_info_t; + +int obtain_auth_info(client_info_t * client_info, cc_auth_info_t ** pauth_info) +{ + *pauth_info = (cc_auth_info_t *)malloc(sizeof(cc_auth_info_t)); + if ( !*pauth_info ) + return ccErrNoMem; + + (*pauth_info)->len = strlen(client_info->client_name) + 1; + (*pauth_info)->info = malloc((*pauth_info)->len); + if ( !(*pauth_info)->info ) { + free(*pauth_info); + return ccErrNoMem; + } + + memcpy((*pauth_info)->info, client_info->client_name, (*pauth_info)->len); + + return 0; +} + +void destroy_auth_info(cc_auth_info_t *auth_info) +{ + free(auth_info->info); + free(auth_info); +} + +int obtain_session_info(client_info_t * client_info, cc_session_info_t ** psession_info) +{ + *psession_info = (cc_session_info_t *)malloc(sizeof(cc_session_info_t)); + if ( !*psession_info ) + return ccErrNoMem; + + (*psession_info)->len = sizeof(LUID); + (*psession_info)->info = malloc((*psession_info)->len); + if ( !(*psession_info)->info ) { + free(*psession_info); + return ccErrNoMem; + } + + memcpy((*psession_info)->info, &client_info->luid, (*psession_info)->len); + + return 0; +} + +void destroy_session_info(cc_session_info_t *session_info) +{ + free(session_info->info); + free(session_info); +} + +RPC_STATUS check_auth(handle_t h, client_info_t * client_info) { + RPC_BINDING_HANDLE bh = (RPC_BINDING_HANDLE) h; + RPC_STATUS status; + HANDLE htoken = NULL; + char name[256]; + char domain[256]; + DWORD name_len; + DWORD domain_len; + SID_NAME_USE snu = 0; + + struct { + TOKEN_ORIGIN origin; + char pad[512]; + } torigin; + + struct { + TOKEN_OWNER owner; + char pad[4096]; + } towner; + + DWORD len; + + status = RpcImpersonateClient(bh); + + if (status != RPC_S_OK) + return status; + + if (!OpenThreadToken(GetCurrentThread(), + TOKEN_READ | TOKEN_QUERY_SOURCE, + FALSE, + &htoken)) { + status = GetLastError(); + goto _cleanup; + } + + len = 0; + + if (!GetTokenInformation(htoken, + TokenOrigin, + &torigin.origin, + sizeof(torigin), + &len)) { + status = GetLastError(); + goto _cleanup; + } + + if (!GetTokenInformation(htoken, + TokenOwner, + &towner.owner, + sizeof(towner), + &len)) { + status = GetLastError(); + goto _cleanup; + } + + + name_len = sizeof(name)/sizeof(name[0]); + domain_len = sizeof(domain)/sizeof(domain[0]); + + if (!LookupAccountSidA(NULL, + towner.owner.Owner, + name, + &name_len, + domain, + &domain_len, + &snu)) { + status = GetLastError(); + goto _cleanup; + } + + client_info->luid = torigin.origin.OriginatingLogonSession; + StringCbPrintfA(client_info->client_name, + sizeof(client_info->client_name), + "%s\\%s", domain, name); + + status = 0; + + _cleanup: + + RpcRevertToSelf(); + + return status; +} + +__int32 ccapi_Message( + /* [in] */ handle_t h, + /* [string][in] */ unsigned char *client_name, + /* [in] */ struct __LUID luid, + /* [size_is][length_is][in] */ unsigned char in_buf[], + /* [in] */ __int32 in_len, + /* [size_is][length_is][out] */ unsigned char out_buf[], + /* [out] */ __int32 *out_len) +{ + client_info_t client_info; + cc_msg_t * msg; + cc_msg_t * resp; + cc_auth_info_t * auth_info; + cc_session_info_t * session_info; + cc_int32 code; + + if ( ccs_serv_initialize() != ccNoError ) { + code = ccErrServerUnavailable; + goto done; + } + + code = check_auth(h, &client_info); + if (code == 0) { + if (!strcmp("SYSTEM",client_info.client_name) && + client_info.luid.HighPart == 0 && + client_info.luid.LowPart == 0 && + client_name != NULL && + client_name[0] != '\0') { + StringCbPrintfA(client_info.client_name, + sizeof(client_info.client_name), + "%s", client_name); + client_info.luid.HighPart = luid.HighPart; + client_info.luid.LowPart = luid.LowPart; + } + } else { + code = ccErrServerCantBecomeUID; + goto done; + } + + /* allocate message */ + msg = (cc_msg_t *)malloc(sizeof(cc_msg_t)); + if (!msg) { + code = ccErrNoMem; + goto done; + } + + /* unflatten message */ + code = cci_msg_unflatten(in_buf, in_len, &msg); + if (code) + goto cleanup; + + /* obtain auth info */ + code = obtain_auth_info(&client_info, &auth_info); + if (code) + goto cleanup; + + /* obtain session info */ + code = obtain_session_info(&client_info, &session_info); + if (code) + goto cleanup; + + /* process message */ + code = ccs_serv_process_msg(msg, auth_info, session_info, &resp); + if (code) + goto cleanup; + + /* flatten response */ + code = cci_msg_flatten(resp, NULL); + if (code) + goto cleanup; + + /* send response */ + if (resp->flat_len > MAXMSGLEN) { + code = ccErrBadInternalMessage; + goto cleanup; + } + memcpy(out_buf, resp->flat, resp->flat_len); + *out_len = resp->flat_len; + code = ccNoError; + + cleanup: + if (auth_info) + destroy_auth_info(auth_info); + + if (session_info) + destroy_session_info(session_info); + + /* free message */ + if (msg) + cci_msg_destroy(msg); + + /* free response */ + if (resp) + cci_msg_destroy(resp); + + done: + return code ? -1 : 0; +} + +void WINAPI service_control(DWORD ctrl_code) { + switch(ctrl_code) { + case SERVICE_CONTROL_STOP: + report_status(SERVICE_STOP_PENDING, NO_ERROR, 0); + service_stop(); + return; + + /* everything else falls through */ + } + + report_status(service_status.dwCurrentState, NO_ERROR, 0); +} + +void WINAPI service_main(DWORD argc, LPTSTR * argv) { + + h_service_status = RegisterServiceCtrlHandler( _T(SVCNAME), service_control); + + if (!h_service_status) + goto cleanup; + + ZeroMemory(&service_status, sizeof(service_status)); + + service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + service_status.dwServiceSpecificExitCode = 0; + + if (!report_status(SERVICE_START_PENDING, + NO_ERROR, + 3000)) + goto cleanup; + + service_start(argc, argv); + + cleanup: + + if (h_service_status) { + report_status(SERVICE_STOPPED, NO_ERROR, 0); + } +} + + +BOOL +IsInstalled() +{ + BOOL bResult = FALSE; + SC_HANDLE hSCM; + SC_HANDLE hService; + + // Open the Service Control Manager + hSCM = OpenSCManager( NULL, // local machine + NULL, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access + if (hSCM) { + + // Try to open the service + hService = OpenService( hSCM, + SVCNAME, + SERVICE_QUERY_CONFIG); + if (hService) { + bResult = TRUE; + CloseServiceHandle(hService); + } + + CloseServiceHandle(hSCM); + } + + return bResult; +} + +BOOL +Install() +{ + char szFilePath[_MAX_PATH]; + SC_HANDLE hSCM; + SC_HANDLE hService; + TCHAR szKey[256]; + HKEY hKey = NULL; + DWORD dwData; + + // Open the Service Control Manager + hSCM = OpenSCManager( NULL, // local machine + NULL, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access + if (!hSCM) + return FALSE; + + // Get the executable file path + GetModuleFileName(NULL, szFilePath, sizeof(szFilePath)); + + // Create the service + hService = CreateService( hSCM, + SVCNAME, + SVCNAME, + SERVICE_ALL_ACCESS, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, // start condition + SERVICE_ERROR_NORMAL, + szFilePath, + NULL, + NULL, + NULL, + NULL, + NULL); + if (!hService) { + CloseServiceHandle(hSCM); + return FALSE; + } + + // make registry entries to support logging messages + // Add the source name as a subkey under the Application + // key in the EventLog service portion of the registry. + StringCbCopyA(szKey, 256, "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\IKSD"); + if (RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &hKey) != ERROR_SUCCESS) { + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + return FALSE; + } + + // Add the Event ID message-file name to the 'EventMessageFile' subkey. + RegSetValueEx( hKey, + "EventMessageFile", + 0, + REG_EXPAND_SZ, + (CONST BYTE*)szFilePath, + strlen(szFilePath) + 1); + + // Set the supported types flags. + dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE; + RegSetValueEx( hKey, + "TypesSupported", + 0, + REG_DWORD, + (CONST BYTE*)&dwData, + sizeof(DWORD)); + RegCloseKey(hKey); + + // LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_INSTALLED, SVCNAME); + + // tidy up + CloseServiceHandle(hService); + CloseServiceHandle(hSCM); + return TRUE; +} + +BOOL +Uninstall() +{ + BOOL bResult = FALSE; + SC_HANDLE hService; + SC_HANDLE hSCM; + + // Open the Service Control Manager + hSCM = OpenSCManager( NULL, // local machine + NULL, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access + if (!hSCM) + return FALSE; + + hService = OpenService( hSCM, + _T(SVCNAME), + DELETE); + if (hService) { + if (DeleteService(hService)) { + // LogEvent(EVENTLOG_INFORMATION_TYPE, EVMSG_REMOVED, SVCNAME); + bResult = TRUE; + } else { + // LogEvent(EVENTLOG_ERROR_TYPE, EVMSG_NOTREMOVED, SVCNAME); + } + CloseServiceHandle(hService); + } + + CloseServiceHandle(hSCM); + return bResult; +} + + +// Returns TRUE if it found an arg it recognised, FALSE if not +// Note: processing some arguments causes output to stdout to be generated. +BOOL +ParseStandardArgs(int argc, char* argv[]) +{ + char szFilePath[_MAX_PATH]="not a file name"; + + // See if we have any command line args we recognize + if (argc <= 1) + return FALSE; + + if ( _stricmp(argv[1], "-h") == 0 || + _stricmp(argv[1], "-?") == 0 || + _stricmp(argv[1], "/h") == 0 || + _stricmp(argv[1], "/?") == 0) { + + // + GetModuleFileNameA(NULL, szFilePath, sizeof(szFilePath)); + fprintf(stderr, "usage: %s [-v | -i | -u | -h]\r\n",szFilePath); + return TRUE; + } else if (_stricmp(argv[1], "-v") == 0 || + _stricmp(argv[1], "/v") == 0 ) { + + // Spit out version info + fprintf(stderr, "%s Version 0.1\n",_T(SVCNAME)); + fprintf(stderr, "The service is %s installed\n", + IsInstalled() ? "currently" : "not"); + return TRUE; // say we processed the argument + + } else if (_stricmp(argv[1], "-i") == 0 || + _stricmp(argv[1], "/i") == 0) { + + // Request to install. + if (IsInstalled()) { + fprintf(stderr, "%s is already installed\n", _T(SVCNAME)); + } else { + // Try and install the copy that's running + if (Install()) { + fprintf(stderr, "%s installed\n", _T(SVCNAME)); + } else { + fprintf(stderr, "%s failed to install. Error %d\n", _T(SVCNAME), GetLastError()); + } + } + return TRUE; // say we processed the argument + + } else if (_stricmp(argv[1], "-u") == 0 || + _stricmp(argv[1], "/u") == 0) { + + // Request to uninstall. + if (!IsInstalled()) { + fprintf(stderr, "%s is not installed\n", _T(SVCNAME)); + } else { + // Try and remove the copy that's installed + if (Uninstall()) { + // Get the executable file path + GetModuleFileNameA(NULL, szFilePath, sizeof(szFilePath)); + fprintf(stderr, "%s removed. (You must delete the file (%s) yourself.)\n", + _T(SVCNAME), szFilePath); + } else { + fprintf(stderr, "Could not remove %s. Error %d\n", _T(SVCNAME), GetLastError()); + } + } + return TRUE; // say we processed the argument + + } + + // Don't recognise the args + return FALSE; +} + +int main(int argc, char ** argv) { + + SERVICE_TABLE_ENTRY dispatch_table[] = { + { _T(SVCNAME), (LPSERVICE_MAIN_FUNCTION) service_main }, + { NULL, NULL } + }; + + if ( ParseStandardArgs(argc, argv) ) + return 0; + + if (!StartServiceCtrlDispatcher(dispatch_table)) { + fprintf(stderr, "Can't start service control dispatcher\n"); + } + + return 0; +} -- cgit From f42fa33b985c230736ad5d9080055916de33be8c Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Mon, 5 Jun 2006 17:49:34 +0000 Subject: improved error handling git-svn-id: svn://anonsvn.mit.edu/krb5/branches/ccapi@18083 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/ccapi/windows/server.c | 77 ++++++++++++++++++++++++++++++++---------- 1 file changed, 59 insertions(+), 18 deletions(-) (limited to 'src/lib/ccapi/windows/server.c') diff --git a/src/lib/ccapi/windows/server.c b/src/lib/ccapi/windows/server.c index 5ce8e6ebe..34d329902 100644 --- a/src/lib/ccapi/windows/server.c +++ b/src/lib/ccapi/windows/server.c @@ -1,5 +1,4 @@ - #include #include "msg.h" #include "marshall.h" @@ -15,6 +14,9 @@ #define SVCNAME "MIT_CCAPI_NT_Service" +HANDLE hMainThread = 0; +HANDLE WaitToTerminate = 0; + SERVICE_STATUS_HANDLE h_service_status = NULL; SERVICE_STATUS service_status; FILE * logfile = NULL; @@ -72,7 +74,8 @@ void service_start(DWORD argc, LPTSTR * argv) { NULL); if (status != RPC_S_OK) { - return; + if (logfile) fprintf(logfile, "service_start RpcServerUseProtseq = 0x%x\n", status); + goto cleanup; } report_status(SERVICE_START_PENDING, NO_ERROR, 3000); @@ -80,21 +83,27 @@ void service_start(DWORD argc, LPTSTR * argv) { status = RpcServerRegisterIf(portable_ccapi_v1_0_s_ifspec, 0, 0); - if (status != RPC_S_OK) - return; + if (status != RPC_S_OK) { + if (logfile) fprintf(logfile, "service_start RpcServerRegisterIf = 0x%x\n", status); + goto cleanup; + } report_status(SERVICE_START_PENDING, NO_ERROR, 3000); status = RpcServerInqBindings(&bv); - if (status != RPC_S_OK) - return; + if (status != RPC_S_OK) { + if (logfile) fprintf(logfile, "service_start RpcServerInqBindings = 0x%x\n", status); + goto cleanup; + } status = RpcEpRegister(portable_ccapi_v1_0_s_ifspec, bv, 0, 0); - if (status != RPC_S_OK) - return; + if (status != RPC_S_OK) { + if (logfile) fprintf(logfile, "service_start RpcEpRegister = 0x%x\n", status); + goto cleanup; + } report_status(SERVICE_START_PENDING, NO_ERROR, 3000); @@ -102,32 +111,37 @@ void service_start(DWORD argc, LPTSTR * argv) { RPC_C_AUTHN_WINNT, 0, 0); - if (status != RPC_S_OK) - return; + if (status != RPC_S_OK) { + if (logfile) fprintf(logfile, "service_start RpcServerRegisterAuthInfo = 0x%x\n", status); + goto cleanup; + } report_status(SERVICE_START_PENDING, NO_ERROR, 3000); - status = RpcServerListen(1, + status = RpcServerListen(2, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE); - if (status != RPC_S_OK) - return; + if (status != RPC_S_OK) { + if (logfile) fprintf(logfile, "service_start RpcServerListen = 0x%x\n", status); + goto cleanup; + } report_status(SERVICE_RUNNING, NO_ERROR, 0); - begin_log(); + if (logfile) fprintf(logfile, "service_start calling RpcMgmtWaitServerListen\n"); status = RpcMgmtWaitServerListen(); + if (logfile) fprintf(logfile, "service_start RpcMgmtWaitServerListen = 0x%x\n", status); - end_log(); - + cleanup: RpcEpUnregister(portable_ccapi_v1_0_s_ifspec, bv, 0); RpcBindingVectorFree(&bv); } void service_stop(void) { + if (logfile) fprintf(logfile, "service_stop\n"); RpcMgmtStopServerListening(0); } @@ -292,6 +306,8 @@ __int32 ccapi_Message( cc_session_info_t * session_info; cc_int32 code; + if (logfile) fprintf(logfile, "ccapi_Message\n"); + if ( ccs_serv_initialize() != ccNoError ) { code = ccErrServerUnavailable; goto done; @@ -390,6 +406,8 @@ void WINAPI service_control(DWORD ctrl_code) { void WINAPI service_main(DWORD argc, LPTSTR * argv) { + begin_log(); + h_service_status = RegisterServiceCtrlHandler( _T(SVCNAME), service_control); if (!h_service_status) @@ -412,6 +430,8 @@ void WINAPI service_main(DWORD argc, LPTSTR * argv) { if (h_service_status) { report_status(SERVICE_STOPPED, NO_ERROR, 0); } + + end_log(); } @@ -620,8 +640,16 @@ ParseStandardArgs(int argc, char* argv[]) return FALSE; } -int main(int argc, char ** argv) { +DWORD __stdcall Main_thread(void* notUsed) +{ + char * argv[2] = {SVCNAME, NULL}; + begin_log(); + service_start(1, (LPTSTR*)argv); + end_log(); + return(0); +} +int main(int argc, char ** argv) { SERVICE_TABLE_ENTRY dispatch_table[] = { { _T(SVCNAME), (LPSERVICE_MAIN_FUNCTION) service_main }, { NULL, NULL } @@ -631,8 +659,21 @@ int main(int argc, char ** argv) { return 0; if (!StartServiceCtrlDispatcher(dispatch_table)) { - fprintf(stderr, "Can't start service control dispatcher\n"); + LONG status = GetLastError(); + if (status == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) + { + DWORD tid; + hMainThread = CreateThread(NULL, 0, Main_thread, 0, 0, &tid); + + printf("Hit to terminate MIT CCAPI Server\n"); + getchar(); + service_stop(); + } } + if ( hMainThread ) { + WaitForSingleObject( hMainThread, INFINITE ); + CloseHandle( hMainThread ); + } return 0; } -- cgit From 2e2e04bf3cbf340637fa6ccd3dbdd20b09e57f19 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 9 Jun 2006 14:42:04 +0000 Subject: * corrections to windows rpc layer * corrections to network byte order conversions git-svn-id: svn://anonsvn.mit.edu/krb5/branches/ccapi@18094 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/ccapi/windows/server.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/lib/ccapi/windows/server.c') diff --git a/src/lib/ccapi/windows/server.c b/src/lib/ccapi/windows/server.c index 34d329902..ac4ab70ab 100644 --- a/src/lib/ccapi/windows/server.c +++ b/src/lib/ccapi/windows/server.c @@ -300,10 +300,10 @@ __int32 ccapi_Message( /* [out] */ __int32 *out_len) { client_info_t client_info; - cc_msg_t * msg; - cc_msg_t * resp; - cc_auth_info_t * auth_info; - cc_session_info_t * session_info; + cc_msg_t * msg = NULL; + cc_msg_t * resp = NULL; + cc_auth_info_t * auth_info = NULL; + cc_session_info_t * session_info = NULL; cc_int32 code; if (logfile) fprintf(logfile, "ccapi_Message\n"); -- cgit