xref: /freebsd/crypto/krb5/src/ccapi/lib/win/OldCC/client.cxx (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /*
2*7f2fe78bSCy Schubert  * $Header$
3*7f2fe78bSCy Schubert  *
4*7f2fe78bSCy Schubert  * Copyright 2008 Massachusetts Institute of Technology.
5*7f2fe78bSCy Schubert  * All Rights Reserved.
6*7f2fe78bSCy Schubert  *
7*7f2fe78bSCy Schubert  * Export of this software from the United States of America may
8*7f2fe78bSCy Schubert  * require a specific license from the United States Government.
9*7f2fe78bSCy Schubert  * It is the responsibility of any person or organization contemplating
10*7f2fe78bSCy Schubert  * export to obtain such a license before exporting.
11*7f2fe78bSCy Schubert  *
12*7f2fe78bSCy Schubert  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13*7f2fe78bSCy Schubert  * distribute this software and its documentation for any purpose and
14*7f2fe78bSCy Schubert  * without fee is hereby granted, provided that the above copyright
15*7f2fe78bSCy Schubert  * notice appear in all copies and that both that copyright notice and
16*7f2fe78bSCy Schubert  * this permission notice appear in supporting documentation, and that
17*7f2fe78bSCy Schubert  * the name of M.I.T. not be used in advertising or publicity pertaining
18*7f2fe78bSCy Schubert  * to distribution of the software without specific, written prior
19*7f2fe78bSCy Schubert  * permission.  Furthermore if you modify this software you must label
20*7f2fe78bSCy Schubert  * your software as modified software and not distribute it in such a
21*7f2fe78bSCy Schubert  * fashion that it might be confused with the original M.I.T. software.
22*7f2fe78bSCy Schubert  * M.I.T. makes no representations about the suitability of
23*7f2fe78bSCy Schubert  * this software for any purpose.  It is provided "as is" without express
24*7f2fe78bSCy Schubert  * or implied warranty.
25*7f2fe78bSCy Schubert  */
26*7f2fe78bSCy Schubert 
27*7f2fe78bSCy Schubert #include "stdio.h"    // KPKDBG
28*7f2fe78bSCy Schubert 
29*7f2fe78bSCy Schubert #include "ccs_request.h"
30*7f2fe78bSCy Schubert 
31*7f2fe78bSCy Schubert #include "ccapi.h"
32*7f2fe78bSCy Schubert #include "util.h"
33*7f2fe78bSCy Schubert 
34*7f2fe78bSCy Schubert extern "C" {
35*7f2fe78bSCy Schubert #include "cci_debugging.h"
36*7f2fe78bSCy Schubert #include "tls.h"    // KPKDBG
37*7f2fe78bSCy Schubert     }
38*7f2fe78bSCy Schubert 
39*7f2fe78bSCy Schubert #include "client.h"
40*7f2fe78bSCy Schubert #include "init.hxx"
41*7f2fe78bSCy Schubert #include "name.h"
42*7f2fe78bSCy Schubert #include "secure.hxx"
43*7f2fe78bSCy Schubert 
44*7f2fe78bSCy Schubert #define SECONDS_TO_WAIT 10
45*7f2fe78bSCy Schubert 
46*7f2fe78bSCy Schubert #define STARTUP "CLIENT STARTUP: "
47*7f2fe78bSCy Schubert #define DISCONNECT "CLIENT DISCONNECT: "
48*7f2fe78bSCy Schubert 
49*7f2fe78bSCy Schubert bool Client::s_init = false;
50*7f2fe78bSCy Schubert CcOsLock Client::sLock;
51*7f2fe78bSCy Schubert 
bind_client(char * ep OPTIONAL,Init::InitInfo & info,LPSTR * endpoint)52*7f2fe78bSCy Schubert static DWORD bind_client(char* ep OPTIONAL, Init::InitInfo& info, LPSTR* endpoint) {
53*7f2fe78bSCy Schubert     DWORD status = 0;
54*7f2fe78bSCy Schubert     unsigned char * pszStringBinding = NULL;
55*7f2fe78bSCy Schubert 
56*7f2fe78bSCy Schubert     if (!ep) {
57*7f2fe78bSCy Schubert         status = alloc_name(endpoint, "ep", isNT());
58*7f2fe78bSCy Schubert         }
59*7f2fe78bSCy Schubert     else {
60*7f2fe78bSCy Schubert         *endpoint = ep;
61*7f2fe78bSCy Schubert         }
62*7f2fe78bSCy Schubert 
63*7f2fe78bSCy Schubert     if (!status) {
64*7f2fe78bSCy Schubert         /* Use a convenience function to concatenate the elements of */
65*7f2fe78bSCy Schubert         /* the string binding into the proper sequence.              */
66*7f2fe78bSCy Schubert         status = RpcStringBindingCompose(0,            // uuid
67*7f2fe78bSCy Schubert                                          (unsigned char*)"ncalrpc",    // protseq
68*7f2fe78bSCy Schubert                                          0,            // address
69*7f2fe78bSCy Schubert                                          (unsigned char*)(*endpoint),  // endpoint
70*7f2fe78bSCy Schubert                                          0,            // options
71*7f2fe78bSCy Schubert                                          &pszStringBinding);
72*7f2fe78bSCy Schubert         cci_check_error(status);
73*7f2fe78bSCy Schubert         }
74*7f2fe78bSCy Schubert 
75*7f2fe78bSCy Schubert     if (!status) {
76*7f2fe78bSCy Schubert         /* Set the binding handle that will be used to bind to the server. */
77*7f2fe78bSCy Schubert         status = RpcBindingFromStringBinding(pszStringBinding, &ccs_request_IfHandle);
78*7f2fe78bSCy Schubert         cci_check_error(status);
79*7f2fe78bSCy Schubert         }
80*7f2fe78bSCy Schubert 
81*7f2fe78bSCy Schubert     if (!status) {
82*7f2fe78bSCy Schubert         // Win9x might call RpcBindingSetAuthInfo (not Ex), but it does not
83*7f2fe78bSCy Schubert         // quite work on Win9x...
84*7f2fe78bSCy Schubert         if (isNT()) {
85*7f2fe78bSCy Schubert             RPC_SECURITY_QOS qos;
86*7f2fe78bSCy Schubert             qos.Version = RPC_C_SECURITY_QOS_VERSION;
87*7f2fe78bSCy Schubert             qos.Capabilities = RPC_C_QOS_CAPABILITIES_DEFAULT;
88*7f2fe78bSCy Schubert             qos.IdentityTracking = RPC_C_QOS_IDENTITY_STATIC;
89*7f2fe78bSCy Schubert             qos.ImpersonationType = RPC_C_IMP_LEVEL_IDENTIFY;
90*7f2fe78bSCy Schubert 
91*7f2fe78bSCy Schubert             status = info.fRpcBindingSetAuthInfoEx(ccs_request_IfHandle,
92*7f2fe78bSCy Schubert                                                    0, // principal
93*7f2fe78bSCy Schubert                                                    RPC_C_AUTHN_LEVEL_CONNECT,
94*7f2fe78bSCy Schubert                                                    RPC_C_AUTHN_WINNT,
95*7f2fe78bSCy Schubert                                                    0, // current address space
96*7f2fe78bSCy Schubert                                                    RPC_C_AUTHZ_NAME,
97*7f2fe78bSCy Schubert                                                    &qos);
98*7f2fe78bSCy Schubert             cci_check_error(status);
99*7f2fe78bSCy Schubert             }
100*7f2fe78bSCy Schubert         }
101*7f2fe78bSCy Schubert 
102*7f2fe78bSCy Schubert     if (pszStringBinding) {
103*7f2fe78bSCy Schubert         DWORD status = RpcStringFree(&pszStringBinding);
104*7f2fe78bSCy Schubert         cci_check_error(status);
105*7f2fe78bSCy Schubert         }
106*7f2fe78bSCy Schubert     return cci_check_error(status);
107*7f2fe78bSCy Schubert     }
108*7f2fe78bSCy Schubert 
find_server(Init::InitInfo & info,LPSTR endpoint)109*7f2fe78bSCy Schubert DWORD find_server(Init::InitInfo& info, LPSTR endpoint) {
110*7f2fe78bSCy Schubert     DWORD               status      = 0;
111*7f2fe78bSCy Schubert     LPSTR               event_name  = 0;
112*7f2fe78bSCy Schubert     HANDLE              hEvent      = 0;
113*7f2fe78bSCy Schubert     SECURITY_ATTRIBUTES sa          = { 0 };
114*7f2fe78bSCy Schubert     PSECURITY_ATTRIBUTES psa        = 0;
115*7f2fe78bSCy Schubert     STARTUPINFO         si          = { 0 };
116*7f2fe78bSCy Schubert     PROCESS_INFORMATION pi          = { 0 };
117*7f2fe78bSCy Schubert     char*               szExe       = 0;
118*7f2fe78bSCy Schubert     char*               szDir       = 0;
119*7f2fe78bSCy Schubert     BOOL                bRes        = FALSE;
120*7f2fe78bSCy Schubert     char*               cmdline     = NULL;
121*7f2fe78bSCy Schubert 
122*7f2fe78bSCy Schubert     psa = isNT() ? &sa : 0;
123*7f2fe78bSCy Schubert 
124*7f2fe78bSCy Schubert     cci_debug_printf("%s Looking for server; ccs_request_IfHandle:0x%X", __FUNCTION__, ccs_request_IfHandle);
125*7f2fe78bSCy Schubert     status = cci_check_error(RpcMgmtIsServerListening(ccs_request_IfHandle));
126*7f2fe78bSCy Schubert     if (status == RPC_S_NOT_LISTENING) {
127*7f2fe78bSCy Schubert         cci_debug_printf("  Server *NOT* found!");
128*7f2fe78bSCy Schubert         si.cb = sizeof(si);
129*7f2fe78bSCy Schubert 
130*7f2fe78bSCy Schubert         status = alloc_module_dir_name(CCAPI_DLL, &szDir);
131*7f2fe78bSCy Schubert 
132*7f2fe78bSCy Schubert         if (!status) {
133*7f2fe78bSCy Schubert             status = alloc_module_dir_name_with_file(CCAPI_DLL, CCAPI_EXE, &szExe);
134*7f2fe78bSCy Schubert             }
135*7f2fe78bSCy Schubert 
136*7f2fe78bSCy Schubert         if (!status) {
137*7f2fe78bSCy Schubert             status = alloc_name(&event_name, "startup", isNT());
138*7f2fe78bSCy Schubert             cci_check_error(status);
139*7f2fe78bSCy Schubert             }
140*7f2fe78bSCy Schubert 
141*7f2fe78bSCy Schubert         if (!status) {
142*7f2fe78bSCy Schubert             if (isNT()) {
143*7f2fe78bSCy Schubert                 sa.nLength = sizeof(sa);
144*7f2fe78bSCy Schubert                 status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor);
145*7f2fe78bSCy Schubert                 cci_check_error(status);
146*7f2fe78bSCy Schubert                 }
147*7f2fe78bSCy Schubert             }
148*7f2fe78bSCy Schubert 
149*7f2fe78bSCy Schubert         if (!status) {
150*7f2fe78bSCy Schubert             hEvent = CreateEvent(psa, FALSE, FALSE, event_name);
151*7f2fe78bSCy Schubert             cci_debug_printf("  CreateEvent(... %s) returned hEvent 0x%X", event_name, hEvent);
152*7f2fe78bSCy Schubert             if (!hEvent) status = GetLastError();
153*7f2fe78bSCy Schubert             }
154*7f2fe78bSCy Schubert 
155*7f2fe78bSCy Schubert         if (!status) {
156*7f2fe78bSCy Schubert                 alloc_cmdline_2_args(szExe, endpoint, "-D", &cmdline);
157*7f2fe78bSCy Schubert                 bRes = CreateProcess(  szExe,       // app name
158*7f2fe78bSCy Schubert                                        NULL, //cmdline,     // cmd line is <server endpoint -[DC]>
159*7f2fe78bSCy Schubert                                        psa,         // SA
160*7f2fe78bSCy Schubert                                        psa,         // SA
161*7f2fe78bSCy Schubert                                        FALSE,
162*7f2fe78bSCy Schubert                                        CREATE_NEW_PROCESS_GROUP |
163*7f2fe78bSCy Schubert                                        NORMAL_PRIORITY_CLASS |
164*7f2fe78bSCy Schubert #ifdef CCAPI_LAUNCH_SERVER_WITH_CONSOLE
165*7f2fe78bSCy Schubert                                        CREATE_NEW_CONSOLE |
166*7f2fe78bSCy Schubert #else
167*7f2fe78bSCy Schubert                                        DETACHED_PROCESS |
168*7f2fe78bSCy Schubert #endif
169*7f2fe78bSCy Schubert                                        0,
170*7f2fe78bSCy Schubert                                        NULL,        // environment
171*7f2fe78bSCy Schubert                                        szDir,       // current dir
172*7f2fe78bSCy Schubert                                        &si,
173*7f2fe78bSCy Schubert                                        &pi);
174*7f2fe78bSCy Schubert             if (!bRes) {
175*7f2fe78bSCy Schubert                 status = GetLastError();
176*7f2fe78bSCy Schubert                 cci_debug_printf("  CreateProcess returned %d; LastError: %d", bRes, status);
177*7f2fe78bSCy Schubert                 }
178*7f2fe78bSCy Schubert             cci_debug_printf("  Waiting...");
179*7f2fe78bSCy Schubert             }
180*7f2fe78bSCy Schubert         cci_check_error(status);
181*7f2fe78bSCy Schubert 
182*7f2fe78bSCy Schubert         if (!status) {
183*7f2fe78bSCy Schubert             status = WaitForSingleObject(hEvent, (SECONDS_TO_WAIT)*1000);
184*7f2fe78bSCy Schubert             status = RpcMgmtIsServerListening(ccs_request_IfHandle);
185*7f2fe78bSCy Schubert             }
186*7f2fe78bSCy Schubert         }
187*7f2fe78bSCy Schubert     else if (status) {
188*7f2fe78bSCy Schubert             cci_debug_printf("  unexpected error while looking for server: 0D%d / 0U%u / 0X%X", status, status, status);
189*7f2fe78bSCy Schubert             }
190*7f2fe78bSCy Schubert 
191*7f2fe78bSCy Schubert     if (szDir)                      free_alloc_p(&szDir);
192*7f2fe78bSCy Schubert     if (szExe)                      free_alloc_p(&szExe);
193*7f2fe78bSCy Schubert     if (hEvent)                     CloseHandle(hEvent);
194*7f2fe78bSCy Schubert     if (pi.hThread)                 CloseHandle(pi.hThread);
195*7f2fe78bSCy Schubert     if (pi.hProcess)                CloseHandle(pi.hProcess);
196*7f2fe78bSCy Schubert     if (sa.lpSecurityDescriptor)    free_alloc_p(&sa.lpSecurityDescriptor);
197*7f2fe78bSCy Schubert     return cci_check_error(status);
198*7f2fe78bSCy Schubert 
199*7f2fe78bSCy Schubert }
200*7f2fe78bSCy Schubert 
201*7f2fe78bSCy Schubert static
202*7f2fe78bSCy Schubert DWORD
make_random_challenge(DWORD * challenge_out)203*7f2fe78bSCy Schubert make_random_challenge(DWORD *challenge_out) {
204*7f2fe78bSCy Schubert     HCRYPTPROV provider;
205*7f2fe78bSCy Schubert     DWORD status = 0;
206*7f2fe78bSCy Schubert     *challenge_out = 0;
207*7f2fe78bSCy Schubert     if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL,
208*7f2fe78bSCy Schubert                              CRYPT_VERIFYCONTEXT)) {
209*7f2fe78bSCy Schubert         status = GetLastError();
210*7f2fe78bSCy Schubert         cci_check_error(status);
211*7f2fe78bSCy Schubert         return status;
212*7f2fe78bSCy Schubert         }
213*7f2fe78bSCy Schubert     if (!CryptGenRandom(provider, sizeof(*challenge_out),
214*7f2fe78bSCy Schubert                         (BYTE *)challenge_out)) {
215*7f2fe78bSCy Schubert         status = GetLastError();
216*7f2fe78bSCy Schubert         cci_check_error(status);
217*7f2fe78bSCy Schubert         return status;
218*7f2fe78bSCy Schubert         }
219*7f2fe78bSCy Schubert     if (!CryptReleaseContext(provider, 0)) {
220*7f2fe78bSCy Schubert         /*
221*7f2fe78bSCy Schubert          * Note: even though CryptReleaseContext() failed, we don't really
222*7f2fe78bSCy Schubert          * care since a) we've already successfully obtained our challenge
223*7f2fe78bSCy Schubert          * anyway and b) at least one of the potential errors, "ERROR_BUSY"
224*7f2fe78bSCy Schubert          * does not really seem to be an error at all.  So GetLastError() is
225*7f2fe78bSCy Schubert          * logged for informational purposes only and should not be returned.
226*7f2fe78bSCy Schubert          */
227*7f2fe78bSCy Schubert         cci_check_error(GetLastError());
228*7f2fe78bSCy Schubert         }
229*7f2fe78bSCy Schubert     return status;
230*7f2fe78bSCy Schubert }
231*7f2fe78bSCy Schubert 
232*7f2fe78bSCy Schubert static
233*7f2fe78bSCy Schubert DWORD
authenticate_server(Init::InitInfo & info)234*7f2fe78bSCy Schubert authenticate_server(Init::InitInfo& info) {
235*7f2fe78bSCy Schubert     DWORD               challenge, desired_response;
236*7f2fe78bSCy Schubert     HANDLE              hMap            = 0;
237*7f2fe78bSCy Schubert     LPSTR               mem_name        = 0;
238*7f2fe78bSCy Schubert     PDWORD              pvalue          = 0;
239*7f2fe78bSCy Schubert     CC_UINT32           response        = 0;
240*7f2fe78bSCy Schubert     SECURITY_ATTRIBUTES sa              = { 0 };
241*7f2fe78bSCy Schubert     DWORD               status          = 0;
242*7f2fe78bSCy Schubert 
243*7f2fe78bSCy Schubert     cci_debug_printf("%s entry", __FUNCTION__);
244*7f2fe78bSCy Schubert 
245*7f2fe78bSCy Schubert     status = alloc_name(&mem_name, "auth", isNT());
246*7f2fe78bSCy Schubert     cci_check_error(status);
247*7f2fe78bSCy Schubert 
248*7f2fe78bSCy Schubert     if (!status) {
249*7f2fe78bSCy Schubert         status = make_random_challenge(&challenge);
250*7f2fe78bSCy Schubert         desired_response = challenge + 1;
251*7f2fe78bSCy Schubert         cci_check_error(status);
252*7f2fe78bSCy Schubert         }
253*7f2fe78bSCy Schubert 
254*7f2fe78bSCy Schubert     if (!status) {
255*7f2fe78bSCy Schubert         if (isNT()) {
256*7f2fe78bSCy Schubert             sa.nLength = sizeof(sa);
257*7f2fe78bSCy Schubert             status = alloc_own_security_descriptor_NT(&sa.lpSecurityDescriptor);
258*7f2fe78bSCy Schubert             }
259*7f2fe78bSCy Schubert         }
260*7f2fe78bSCy Schubert     cci_check_error(status);
261*7f2fe78bSCy Schubert 
262*7f2fe78bSCy Schubert     if (!status) {
263*7f2fe78bSCy Schubert         hMap = CreateFileMapping(INVALID_HANDLE_VALUE, isNT() ? &sa : 0,
264*7f2fe78bSCy Schubert                                  PAGE_READWRITE, 0, sizeof(DWORD), mem_name);
265*7f2fe78bSCy Schubert         if (!hMap)
266*7f2fe78bSCy Schubert         status = GetLastError();
267*7f2fe78bSCy Schubert         }
268*7f2fe78bSCy Schubert     cci_check_error(status);
269*7f2fe78bSCy Schubert 
270*7f2fe78bSCy Schubert     if (!status) {
271*7f2fe78bSCy Schubert         pvalue = (PDWORD)MapViewOfFile(hMap, FILE_MAP_ALL_ACCESS, 0, 0, 0);
272*7f2fe78bSCy Schubert         if (!pvalue) status = GetLastError();
273*7f2fe78bSCy Schubert         }
274*7f2fe78bSCy Schubert     cci_check_error(status);
275*7f2fe78bSCy Schubert 
276*7f2fe78bSCy Schubert     if (!status) {
277*7f2fe78bSCy Schubert         *pvalue = challenge;
278*7f2fe78bSCy Schubert 
279*7f2fe78bSCy Schubert         RpcTryExcept {
280*7f2fe78bSCy Schubert             response = ccs_authenticate( (CC_CHAR*)mem_name );
281*7f2fe78bSCy Schubert             }
282*7f2fe78bSCy Schubert         RpcExcept(1) {
283*7f2fe78bSCy Schubert             status = RpcExceptionCode();
284*7f2fe78bSCy Schubert             cci_check_error(status);
285*7f2fe78bSCy Schubert             }
286*7f2fe78bSCy Schubert         RpcEndExcept;
287*7f2fe78bSCy Schubert         }
288*7f2fe78bSCy Schubert     cci_check_error(status);
289*7f2fe78bSCy Schubert 
290*7f2fe78bSCy Schubert     if (!status) {
291*7f2fe78bSCy Schubert         // Check response
292*7f2fe78bSCy Schubert         if ((response != desired_response) && (*pvalue != desired_response)) {
293*7f2fe78bSCy Schubert             cci_debug_printf("  Could not authenticate server.");
294*7f2fe78bSCy Schubert             status = ERROR_ACCESS_DENIED; // XXX - CO_E_NOMATCHINGSIDFOUND?
295*7f2fe78bSCy Schubert             }
296*7f2fe78bSCy Schubert         else {
297*7f2fe78bSCy Schubert             cci_debug_printf("  Server authenticated!");
298*7f2fe78bSCy Schubert             }
299*7f2fe78bSCy Schubert         cci_check_error(status);
300*7f2fe78bSCy Schubert         }
301*7f2fe78bSCy Schubert 
302*7f2fe78bSCy Schubert     free_alloc_p(&mem_name);
303*7f2fe78bSCy Schubert     free_alloc_p(&sa.lpSecurityDescriptor);
304*7f2fe78bSCy Schubert     if (pvalue) {
305*7f2fe78bSCy Schubert         BOOL ok = UnmapViewOfFile(pvalue);
306*7f2fe78bSCy Schubert //        DEBUG_ASSERT(ok);
307*7f2fe78bSCy Schubert         }
308*7f2fe78bSCy Schubert     if (hMap) CloseHandle(hMap);
309*7f2fe78bSCy Schubert     return status;
310*7f2fe78bSCy Schubert }
311*7f2fe78bSCy Schubert 
312*7f2fe78bSCy Schubert DWORD
Disconnect()313*7f2fe78bSCy Schubert Client::Disconnect() {
314*7f2fe78bSCy Schubert     DWORD status = 0;
315*7f2fe78bSCy Schubert     if (ccs_request_IfHandle) {
316*7f2fe78bSCy Schubert         /*  The calls to the remote procedures are complete. */
317*7f2fe78bSCy Schubert         /*  Free the binding handle           */
318*7f2fe78bSCy Schubert         status = RpcBindingFree(&ccs_request_IfHandle);
319*7f2fe78bSCy Schubert         }
320*7f2fe78bSCy Schubert     s_init  = false;
321*7f2fe78bSCy Schubert     return status;
322*7f2fe78bSCy Schubert     }
323*7f2fe78bSCy Schubert 
324*7f2fe78bSCy Schubert DWORD
Connect(char * ep OPTIONAL)325*7f2fe78bSCy Schubert Client::Connect(char* ep OPTIONAL) {
326*7f2fe78bSCy Schubert     LPSTR   endpoint    = 0;
327*7f2fe78bSCy Schubert     DWORD   status      = 0;
328*7f2fe78bSCy Schubert 
329*7f2fe78bSCy Schubert     if (!ccs_request_IfHandle) {
330*7f2fe78bSCy Schubert         Init::InitInfo info;
331*7f2fe78bSCy Schubert 
332*7f2fe78bSCy Schubert         status = Init::Info(info);
333*7f2fe78bSCy Schubert         cci_check_error(status);
334*7f2fe78bSCy Schubert 
335*7f2fe78bSCy Schubert         if (!status) {
336*7f2fe78bSCy Schubert             status = bind_client(ep, info, &endpoint);
337*7f2fe78bSCy Schubert             cci_check_error(status);
338*7f2fe78bSCy Schubert             }
339*7f2fe78bSCy Schubert 
340*7f2fe78bSCy Schubert         if (!status) {
341*7f2fe78bSCy Schubert             status = find_server(info, endpoint);
342*7f2fe78bSCy Schubert             cci_check_error(status);
343*7f2fe78bSCy Schubert             }
344*7f2fe78bSCy Schubert 
345*7f2fe78bSCy Schubert         if (!status) {
346*7f2fe78bSCy Schubert             status = authenticate_server(info);
347*7f2fe78bSCy Schubert             cci_check_error(status);
348*7f2fe78bSCy Schubert             }
349*7f2fe78bSCy Schubert         }
350*7f2fe78bSCy Schubert 
351*7f2fe78bSCy Schubert 
352*7f2fe78bSCy Schubert     if (endpoint && (endpoint != ep)) free_alloc_p(&endpoint);
353*7f2fe78bSCy Schubert 
354*7f2fe78bSCy Schubert     if (status) Client::Disconnect();
355*7f2fe78bSCy Schubert     return status;
356*7f2fe78bSCy Schubert     }
357*7f2fe78bSCy Schubert 
Initialize(char * ep OPTIONAL)358*7f2fe78bSCy Schubert DWORD Client::Initialize(char* ep OPTIONAL) {
359*7f2fe78bSCy Schubert     CcAutoTryLock AL(Client::sLock);
360*7f2fe78bSCy Schubert     if (!AL.IsLocked() || s_init)
361*7f2fe78bSCy Schubert         return 0;
362*7f2fe78bSCy Schubert     SecureClient s;
363*7f2fe78bSCy Schubert     ccs_request_IfHandle  = NULL;
364*7f2fe78bSCy Schubert     DWORD status = Client::Connect(ep);
365*7f2fe78bSCy Schubert     if (!status) s_init = true;
366*7f2fe78bSCy Schubert     return status;
367*7f2fe78bSCy Schubert     }
368*7f2fe78bSCy Schubert 
Cleanup()369*7f2fe78bSCy Schubert DWORD Client::Cleanup() {
370*7f2fe78bSCy Schubert     CcAutoLock AL(Client::sLock);
371*7f2fe78bSCy Schubert     SecureClient s;
372*7f2fe78bSCy Schubert     return Client::Disconnect();
373*7f2fe78bSCy Schubert     }
374*7f2fe78bSCy Schubert 
Reconnect(char * ep OPTIONAL)375*7f2fe78bSCy Schubert DWORD Client::Reconnect(char* ep OPTIONAL) {
376*7f2fe78bSCy Schubert     CcAutoLock AL(Client::sLock);
377*7f2fe78bSCy Schubert     SecureClient s;
378*7f2fe78bSCy Schubert     DWORD status = 0;
379*7f2fe78bSCy Schubert 
380*7f2fe78bSCy Schubert     if (Initialized()) {
381*7f2fe78bSCy Schubert         DWORD status = Client::Cleanup();
382*7f2fe78bSCy Schubert         }
383*7f2fe78bSCy Schubert     if ( (!status) ) {
384*7f2fe78bSCy Schubert         status = Client::Initialize(ep);
385*7f2fe78bSCy Schubert         }
386*7f2fe78bSCy Schubert 
387*7f2fe78bSCy Schubert     return status;
388*7f2fe78bSCy Schubert     }
389