2 * Copyright (c) 2003 SkyRope, LLC
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * - Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * - Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * - Neither the name of Skyrope, LLC nor the names of its contributors may be
14 * used to endorse or promote products derived from this software without
15 * specific prior written permission from Skyrope, LLC.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * Portions of this code are derived from portions of the MIT
30 * Leash Ticket Manager and LoadFuncs utilities. For these portions the
31 * following copyright applies.
33 * Copyright (c) 2003,2004 by the Massachusetts Institute of Technology.
34 * All rights reserved.
36 * Export of this software from the United States of America may
37 * require a specific license from the United States Government.
38 * It is the responsibility of any person or organization contemplating
39 * export to obtain such a license before exporting.
41 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
42 * distribute this software and its documentation for any purpose and
43 * without fee is hereby granted, provided that the above copyright
44 * notice appear in all copies and that both that copyright notice and
45 * this permission notice appear in supporting documentation, and that
46 * the name of M.I.T. not be used in advertising or publicity pertaining
47 * to distribution of the software without specific, written prior
48 * permission. Furthermore if you modify this software you must label
49 * your software as modified software and not distribute it in such a
50 * fashion that it might be confused with the original M.I.T. software.
51 * M.I.T. makes no representations about the suitability of
52 * this software for any purpose. It is provided "as is" without express
53 * or implied warranty.
60 #include "afskfw-int.h"
64 #include <rxkad_prototypes.h> /* for life_to_time */
65 #include <afs/ptserver.h>
68 * TIMING _____________________________________________________________________
72 #define cminREMIND_TEST 1 // test every minute for expired creds
73 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
74 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
75 #define cminMINLIFE 30 // minimum life of Kerberos creds
77 #define c100ns1SECOND (LONGLONG)10000000
78 #define cmsec1SECOND 1000
79 #define cmsec1MINUTE 60000
80 #define csec1MINUTE 60
82 /* Function Pointer Declarations for Delayed Loading */
84 DECL_FUNC_PTR(cc_initialize);
85 DECL_FUNC_PTR(cc_shutdown);
86 DECL_FUNC_PTR(cc_get_NC_info);
87 DECL_FUNC_PTR(cc_free_NC_info);
90 DECL_FUNC_PTR(Leash_get_default_lifetime);
91 DECL_FUNC_PTR(Leash_get_default_forwardable);
92 DECL_FUNC_PTR(Leash_get_default_renew_till);
93 DECL_FUNC_PTR(Leash_get_default_noaddresses);
94 DECL_FUNC_PTR(Leash_get_default_proxiable);
95 DECL_FUNC_PTR(Leash_get_default_publicip);
96 DECL_FUNC_PTR(Leash_get_default_use_krb4);
97 DECL_FUNC_PTR(Leash_get_default_life_min);
98 DECL_FUNC_PTR(Leash_get_default_life_max);
99 DECL_FUNC_PTR(Leash_get_default_renew_min);
100 DECL_FUNC_PTR(Leash_get_default_renew_max);
101 DECL_FUNC_PTR(Leash_get_default_renewable);
104 DECL_FUNC_PTR(krb5_change_password);
105 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
106 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
107 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
108 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
109 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
110 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
111 DECL_FUNC_PTR(krb5_get_init_creds_password);
112 DECL_FUNC_PTR(krb5_build_principal_ext);
113 DECL_FUNC_PTR(krb5_cc_get_name);
114 DECL_FUNC_PTR(krb5_cc_resolve);
115 DECL_FUNC_PTR(krb5_cc_default);
116 DECL_FUNC_PTR(krb5_cc_default_name);
117 DECL_FUNC_PTR(krb5_cc_set_default_name);
118 DECL_FUNC_PTR(krb5_cc_initialize);
119 DECL_FUNC_PTR(krb5_cc_destroy);
120 DECL_FUNC_PTR(krb5_cc_close);
121 DECL_FUNC_PTR(krb5_cc_store_cred);
122 DECL_FUNC_PTR(krb5_cc_copy_creds);
123 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
124 DECL_FUNC_PTR(krb5_cc_get_principal);
125 DECL_FUNC_PTR(krb5_cc_start_seq_get);
126 DECL_FUNC_PTR(krb5_cc_next_cred);
127 DECL_FUNC_PTR(krb5_cc_end_seq_get);
128 DECL_FUNC_PTR(krb5_cc_remove_cred);
129 DECL_FUNC_PTR(krb5_cc_set_flags);
130 DECL_FUNC_PTR(krb5_cc_get_type);
131 DECL_FUNC_PTR(krb5_free_context);
132 DECL_FUNC_PTR(krb5_free_cred_contents);
133 DECL_FUNC_PTR(krb5_free_principal);
134 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
135 DECL_FUNC_PTR(krb5_init_context);
136 DECL_FUNC_PTR(krb5_parse_name);
137 DECL_FUNC_PTR(krb5_timeofday);
138 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
139 DECL_FUNC_PTR(krb5_unparse_name);
140 DECL_FUNC_PTR(krb5_get_credentials);
141 DECL_FUNC_PTR(krb5_mk_req);
142 DECL_FUNC_PTR(krb5_sname_to_principal);
143 DECL_FUNC_PTR(krb5_get_credentials_renew);
144 DECL_FUNC_PTR(krb5_free_data);
145 DECL_FUNC_PTR(krb5_free_data_contents);
146 DECL_FUNC_PTR(krb5_free_unparsed_name);
147 DECL_FUNC_PTR(krb5_os_localaddr);
148 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
149 DECL_FUNC_PTR(krb5_copy_data);
150 DECL_FUNC_PTR(krb5_free_creds);
151 DECL_FUNC_PTR(krb5_build_principal);
152 DECL_FUNC_PTR(krb5_get_renewed_creds);
153 DECL_FUNC_PTR(krb5_get_default_config_files);
154 DECL_FUNC_PTR(krb5_free_config_files);
155 DECL_FUNC_PTR(krb5_get_default_realm);
156 DECL_FUNC_PTR(krb5_free_ticket);
157 DECL_FUNC_PTR(krb5_decode_ticket);
158 DECL_FUNC_PTR(krb5_get_host_realm);
159 DECL_FUNC_PTR(krb5_free_host_realm);
160 DECL_FUNC_PTR(krb5_free_addresses);
161 DECL_FUNC_PTR(krb5_c_random_make_octets);
164 DECL_FUNC_PTR(krb524_init_ets);
165 DECL_FUNC_PTR(krb524_convert_creds_kdc);
168 DECL_FUNC_PTR(krb_get_cred);
169 DECL_FUNC_PTR(tkt_string);
170 DECL_FUNC_PTR(krb_get_tf_realm);
171 DECL_FUNC_PTR(krb_mk_req);
174 DECL_FUNC_PTR(com_err);
175 DECL_FUNC_PTR(error_message);
178 DECL_FUNC_PTR(profile_init);
179 DECL_FUNC_PTR(profile_release);
180 DECL_FUNC_PTR(profile_get_subsection_names);
181 DECL_FUNC_PTR(profile_free_list);
182 DECL_FUNC_PTR(profile_get_string);
183 DECL_FUNC_PTR(profile_release_string);
186 DECL_FUNC_PTR(OpenSCManagerA);
187 DECL_FUNC_PTR(OpenServiceA);
188 DECL_FUNC_PTR(QueryServiceStatus);
189 DECL_FUNC_PTR(CloseServiceHandle);
191 DECL_FUNC_PTR(LsaNtStatusToWinError);
192 #endif /* USE_MS2MIT */
196 DECL_FUNC_PTR(LsaConnectUntrusted);
197 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
198 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
199 DECL_FUNC_PTR(LsaFreeReturnBuffer);
200 DECL_FUNC_PTR(LsaGetLogonSessionData);
201 #endif /* USE_MS2MIT */
204 FUNC_INFO ccapi_fi[] = {
205 MAKE_FUNC_INFO(cc_initialize),
206 MAKE_FUNC_INFO(cc_shutdown),
207 MAKE_FUNC_INFO(cc_get_NC_info),
208 MAKE_FUNC_INFO(cc_free_NC_info),
212 FUNC_INFO leash_fi[] = {
213 MAKE_FUNC_INFO(Leash_get_default_lifetime),
214 MAKE_FUNC_INFO(Leash_get_default_renew_till),
215 MAKE_FUNC_INFO(Leash_get_default_forwardable),
216 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
217 MAKE_FUNC_INFO(Leash_get_default_proxiable),
218 MAKE_FUNC_INFO(Leash_get_default_publicip),
219 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
220 MAKE_FUNC_INFO(Leash_get_default_life_min),
221 MAKE_FUNC_INFO(Leash_get_default_life_max),
222 MAKE_FUNC_INFO(Leash_get_default_renew_min),
223 MAKE_FUNC_INFO(Leash_get_default_renew_max),
224 MAKE_FUNC_INFO(Leash_get_default_renewable),
228 FUNC_INFO k5_fi[] = {
229 MAKE_FUNC_INFO(krb5_change_password),
230 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
231 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
232 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
233 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
234 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
235 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
236 MAKE_FUNC_INFO(krb5_get_init_creds_password),
237 MAKE_FUNC_INFO(krb5_build_principal_ext),
238 MAKE_FUNC_INFO(krb5_cc_get_name),
239 MAKE_FUNC_INFO(krb5_cc_resolve),
240 MAKE_FUNC_INFO(krb5_cc_default),
241 MAKE_FUNC_INFO(krb5_cc_default_name),
242 MAKE_FUNC_INFO(krb5_cc_set_default_name),
243 MAKE_FUNC_INFO(krb5_cc_initialize),
244 MAKE_FUNC_INFO(krb5_cc_destroy),
245 MAKE_FUNC_INFO(krb5_cc_close),
246 MAKE_FUNC_INFO(krb5_cc_copy_creds),
247 MAKE_FUNC_INFO(krb5_cc_store_cred),
248 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
249 MAKE_FUNC_INFO(krb5_cc_get_principal),
250 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
251 MAKE_FUNC_INFO(krb5_cc_next_cred),
252 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
253 MAKE_FUNC_INFO(krb5_cc_remove_cred),
254 MAKE_FUNC_INFO(krb5_cc_set_flags),
255 MAKE_FUNC_INFO(krb5_cc_get_type),
256 MAKE_FUNC_INFO(krb5_free_context),
257 MAKE_FUNC_INFO(krb5_free_cred_contents),
258 MAKE_FUNC_INFO(krb5_free_principal),
259 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
260 MAKE_FUNC_INFO(krb5_init_context),
261 MAKE_FUNC_INFO(krb5_parse_name),
262 MAKE_FUNC_INFO(krb5_timeofday),
263 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
264 MAKE_FUNC_INFO(krb5_unparse_name),
265 MAKE_FUNC_INFO(krb5_get_credentials),
266 MAKE_FUNC_INFO(krb5_mk_req),
267 MAKE_FUNC_INFO(krb5_sname_to_principal),
268 MAKE_FUNC_INFO(krb5_get_credentials_renew),
269 MAKE_FUNC_INFO(krb5_free_data),
270 MAKE_FUNC_INFO(krb5_free_data_contents),
271 MAKE_FUNC_INFO(krb5_free_unparsed_name),
272 MAKE_FUNC_INFO(krb5_os_localaddr),
273 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
274 MAKE_FUNC_INFO(krb5_copy_data),
275 MAKE_FUNC_INFO(krb5_free_creds),
276 MAKE_FUNC_INFO(krb5_build_principal),
277 MAKE_FUNC_INFO(krb5_get_renewed_creds),
278 MAKE_FUNC_INFO(krb5_free_addresses),
279 MAKE_FUNC_INFO(krb5_get_default_config_files),
280 MAKE_FUNC_INFO(krb5_free_config_files),
281 MAKE_FUNC_INFO(krb5_get_default_realm),
282 MAKE_FUNC_INFO(krb5_free_ticket),
283 MAKE_FUNC_INFO(krb5_decode_ticket),
284 MAKE_FUNC_INFO(krb5_get_host_realm),
285 MAKE_FUNC_INFO(krb5_free_host_realm),
286 MAKE_FUNC_INFO(krb5_free_addresses),
287 MAKE_FUNC_INFO(krb5_c_random_make_octets),
292 FUNC_INFO k4_fi[] = {
293 MAKE_FUNC_INFO(krb_get_cred),
294 MAKE_FUNC_INFO(krb_get_tf_realm),
295 MAKE_FUNC_INFO(krb_mk_req),
296 MAKE_FUNC_INFO(tkt_string),
301 FUNC_INFO k524_fi[] = {
302 MAKE_FUNC_INFO(krb524_init_ets),
303 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
307 FUNC_INFO profile_fi[] = {
308 MAKE_FUNC_INFO(profile_init),
309 MAKE_FUNC_INFO(profile_release),
310 MAKE_FUNC_INFO(profile_get_subsection_names),
311 MAKE_FUNC_INFO(profile_free_list),
312 MAKE_FUNC_INFO(profile_get_string),
313 MAKE_FUNC_INFO(profile_release_string),
317 FUNC_INFO ce_fi[] = {
318 MAKE_FUNC_INFO(com_err),
319 MAKE_FUNC_INFO(error_message),
323 FUNC_INFO service_fi[] = {
324 MAKE_FUNC_INFO(OpenSCManagerA),
325 MAKE_FUNC_INFO(OpenServiceA),
326 MAKE_FUNC_INFO(QueryServiceStatus),
327 MAKE_FUNC_INFO(CloseServiceHandle),
329 MAKE_FUNC_INFO(LsaNtStatusToWinError),
330 #endif /* USE_MS2MIT */
335 FUNC_INFO lsa_fi[] = {
336 MAKE_FUNC_INFO(LsaConnectUntrusted),
337 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
338 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
339 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
340 MAKE_FUNC_INFO(LsaGetLogonSessionData),
343 #endif /* USE_MS2MIT */
345 /* Static Prototypes */
346 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
347 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
348 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
349 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
350 void *data, const char *name, const char *banner, int num_prompts,
351 krb5_prompt prompts[]);
354 /* Static Declarations */
355 static int inited = 0;
356 static int mid_cnt = 0;
357 static struct textField * mid_tb = NULL;
358 static HINSTANCE hKrb5 = 0;
359 static HINSTANCE hKrb4 = 0;
360 static HINSTANCE hKrb524 = 0;
362 static HINSTANCE hSecur32 = 0;
363 #endif /* USE_MS2MIT */
364 static HINSTANCE hAdvApi32 = 0;
365 static HINSTANCE hComErr = 0;
366 static HINSTANCE hService = 0;
367 static HINSTANCE hProfile = 0;
368 static HINSTANCE hLeash = 0;
369 static HINSTANCE hCCAPI = 0;
370 static struct principal_ccache_data * princ_cc_data = NULL;
371 static struct cell_principal_map * cell_princ_map = NULL;
376 static int inited = 0;
379 char mutexName[MAX_PATH];
380 HANDLE hMutex = NULL;
382 sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
384 hMutex = CreateMutex( NULL, TRUE, mutexName );
385 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
386 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
392 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
394 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
395 #endif /* USE_KRB4 */
396 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
397 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
399 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
400 #endif /* USE_MS2MIT */
401 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
402 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
403 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
404 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
406 if ( KFW_is_available() ) {
407 char rootcell[MAXCELLCHARS+1];
409 KFW_import_windows_lsa();
410 #endif /* USE_MS2MIT */
411 KFW_import_ccache_data();
412 KFW_AFS_renew_expiring_tokens();
414 /* WIN32 NOTE: no way to get max chars */
415 if (!cm_GetRootCellName(rootcell))
416 KFW_AFS_renew_token_for_cell(rootcell);
419 ReleaseMutex(hMutex);
432 FreeLibrary(hProfile);
434 FreeLibrary(hComErr);
436 FreeLibrary(hService);
439 FreeLibrary(hSecur32);
440 #endif /* USE_MS2MIT */
442 FreeLibrary(hKrb524);
449 static char OpenAFSConfigKeyName[] = "SOFTWARE\\OpenAFS\\Client";
458 code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
459 0, KEY_QUERY_VALUE, &parmKey);
460 if (code == ERROR_SUCCESS) {
461 len = sizeof(use524);
462 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
463 (BYTE *) &use524, &len);
464 RegCloseKey(parmKey);
466 if (code != ERROR_SUCCESS) {
467 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
468 0, KEY_QUERY_VALUE, &parmKey);
469 if (code == ERROR_SUCCESS) {
470 len = sizeof(use524);
471 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
472 (BYTE *) &use524, &len);
473 RegCloseKey (parmKey);
480 KFW_is_available(void)
486 code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
487 0, KEY_QUERY_VALUE, &parmKey);
488 if (code == ERROR_SUCCESS) {
489 len = sizeof(enableKFW);
490 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
491 (BYTE *) &enableKFW, &len);
492 RegCloseKey (parmKey);
495 if (code != ERROR_SUCCESS) {
496 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
497 0, KEY_QUERY_VALUE, &parmKey);
498 if (code == ERROR_SUCCESS) {
499 len = sizeof(enableKFW);
500 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
501 (BYTE *) &enableKFW, &len);
502 RegCloseKey (parmKey);
510 if ( hKrb5 && hComErr && hService &&
513 #endif /* USE_MS2MIT */
515 hProfile && hLeash && hCCAPI )
521 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
522 int FreeContextFlag, krb5_context * ctx,
527 int krb5Error = ((int)(rc & 255));
539 errText = perror_message(rc);
540 _snprintf(message, sizeof(message),
541 "%s\n(Kerberos error %ld)\n\n%s failed",
546 if ( IsDebuggerPresent() )
547 OutputDebugString(message);
549 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
552 if (FreeContextFlag == 1)
554 if (ctx && *ctx != NULL)
556 if (cache && *cache != NULL) {
557 pkrb5_cc_close(*ctx, *cache);
561 pkrb5_free_context(*ctx);
570 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
572 struct principal_ccache_data * next = princ_cc_data;
573 krb5_principal principal = 0;
575 const char * ccname = NULL;
576 krb5_error_code code = 0;
577 krb5_error_code cc_code = 0;
583 if (ctx == 0 || cc == 0)
586 code = pkrb5_cc_get_principal(ctx, cc, &principal);
589 code = pkrb5_unparse_name(ctx, principal, &pname);
590 if ( code ) goto cleanup;
592 ccname = pkrb5_cc_get_name(ctx, cc);
593 if (!ccname) goto cleanup;
595 // Search the existing list to see if we have a match
597 for ( ; next ; next = next->next ) {
598 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccname) )
603 // If not, match add a new node to the beginning of the list and assign init it
605 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
606 next->next = princ_cc_data;
607 princ_cc_data = next;
608 next->principal = _strdup(pname);
609 next->ccache_name = _strdup(ccname);
610 next->from_lsa = lsa;
612 next->expiration_time = 0;
616 flags = 0; // turn off OPENCLOSE mode
617 code = pkrb5_cc_set_flags(ctx, cc, flags);
618 if ( code ) goto cleanup;
620 code = pkrb5_timeofday(ctx, &now);
622 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
624 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
625 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
627 // we found the ticket we are looking for
628 // check validity of timestamp
629 // We add a 5 minutes fudge factor to compensate for potential
630 // clock skew errors between the KDC and client OS
632 valid = ((creds.times.starttime > 0) &&
633 now >= (creds.times.starttime - 300) &&
634 now < (creds.times.endtime + 300) &&
635 !(creds.ticket_flags & TKT_FLG_INVALID));
637 if ( next->from_lsa) {
639 next->expiration_time = creds.times.endtime;
641 } else if ( valid ) {
643 next->expiration_time = creds.times.endtime;
644 next->renew = (creds.times.renew_till > creds.times.endtime) &&
645 (creds.ticket_flags & TKT_FLG_RENEWABLE);
648 next->expiration_time = 0;
652 pkrb5_free_cred_contents(ctx, &creds);
653 cc_code = KRB5_CC_END;
656 pkrb5_free_cred_contents(ctx, &creds);
659 if (cc_code == KRB5_CC_END) {
660 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
661 if (code) goto cleanup;
665 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
666 code = pkrb5_cc_set_flags(ctx, cc, flags);
669 pkrb5_free_unparsed_name(ctx,pname);
671 pkrb5_free_principal(ctx,principal);
675 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
677 struct principal_ccache_data * next = princ_cc_data;
678 char * response = NULL;
680 if ( !principal || !ccache )
684 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
686 // we always want to prefer the MS Kerberos LSA cache or
687 // the cache afscreds created specifically for the principal
688 // if the current entry is either one, drop the previous find
689 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
692 response = _strdup(next->ccache_name);
693 // MS Kerberos LSA is our best option so use it and quit
694 if ( next->from_lsa )
708 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
710 struct principal_ccache_data ** next = &princ_cc_data;
712 if ( !pname && !ccname )
716 if ( !strcmp((*next)->principal,pname) ||
717 !strcmp((*next)->ccache_name,ccname) ) {
719 free((*next)->principal);
720 free((*next)->ccache_name);
722 (*next) = (*next)->next;
729 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
731 struct cell_principal_map * next = cell_princ_map;
733 // Search the existing list to see if we have a match
735 for ( ; next ; next = next->next ) {
736 if ( !strcmp(next->cell, cell) ) {
737 if ( !strcmp(next->principal,pname) ) {
738 next->active = active;
741 // OpenAFS currently has a restriction of one active token per cell
742 // Therefore, whenever we update the table with a new active cell we
743 // must mark all of the other principal to cell entries as inactive.
751 // If not, match add a new node to the beginning of the list and assign init it
753 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
754 next->next = cell_princ_map;
755 cell_princ_map = next;
756 next->principal = _strdup(pname);
757 next->cell = _strdup(cell);
758 next->active = active;
763 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
765 struct cell_principal_map ** next = &cell_princ_map;
767 if ( !pname && !cell )
771 if ( !strcmp((*next)->principal,pname) ||
772 !strcmp((*next)->cell,cell) ) {
774 free((*next)->principal);
777 (*next) = (*next)->next;
783 // Returns (if possible) a principal which has been known in
784 // the past to have been used to obtain tokens for the specified
786 // TODO: Attempt to return one which has not yet expired by checking
787 // the principal/ccache data
789 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
791 struct cell_principal_map * next_map = cell_princ_map;
792 const char * princ = NULL;
799 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
802 next_map = next_map->next;
805 if ( !principals || !count )
808 *principals = (char **) malloc(sizeof(char *) * count);
809 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
811 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
812 (*principals)[i++] = _strdup(next_map->principal);
819 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
822 struct cell_principal_map * next_map = cell_princ_map;
823 const char * princ = NULL;
829 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
832 next_map = next_map->next;
838 *cells = (char **) malloc(sizeof(char *) * count);
839 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
841 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
842 (*cells)[i++] = _strdup(next_map->cell);
848 /* Given a principal return an existing ccache or create one and return */
850 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
855 krb5_error_code code;
857 if (!pkrb5_init_context)
863 code = pkrb5_init_context(&ctx);
864 if (code) goto cleanup;
868 code = pkrb5_unparse_name(ctx, principal, &pname);
869 if (code) goto cleanup;
871 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
872 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
873 ccname = (char *)malloc(strlen(pname) + 5);
874 sprintf(ccname,"API:%s",pname);
876 code = pkrb5_cc_resolve(ctx, ccname, cc);
878 code = pkrb5_cc_default(ctx, cc);
879 if (code) goto cleanup;
886 pkrb5_free_unparsed_name(ctx,pname);
887 if (ctx && (ctx != alt_ctx))
888 pkrb5_free_context(ctx);
893 // Import Microsoft Credentials into a new MIT ccache
895 KFW_import_windows_lsa(void)
897 krb5_context ctx = 0;
899 krb5_principal princ = 0;
901 krb5_data * princ_realm;
902 krb5_error_code code;
903 char cell[128]="", realm[128]="";
906 if (!pkrb5_init_context)
910 if ( !MSLSA_IsKerberosLogon() )
914 code = pkrb5_init_context(&ctx);
915 if (code) goto cleanup;
917 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
918 if (code) goto cleanup;
920 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
922 code = pkrb5_cc_get_principal(ctx, cc, &princ);
923 if ( code ) goto cleanup;
925 code = pkrb5_unparse_name(ctx,princ,&pname);
926 if ( code ) goto cleanup;
928 princ_realm = krb5_princ_realm(ctx, princ);
929 for ( i=0; i<princ_realm->length; i++ ) {
930 realm[i] = princ_realm->data[i];
931 cell[i] = tolower(princ_realm->data[i]);
936 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
937 if ( IsDebuggerPresent() ) {
939 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
940 OutputDebugString(message);
942 if ( code ) goto cleanup;
944 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
948 pkrb5_free_unparsed_name(ctx,pname);
950 pkrb5_free_principal(ctx,princ);
952 pkrb5_cc_close(ctx,cc);
954 pkrb5_free_context(ctx);
956 #endif /* USE_MS2MIT */
958 // If there are existing MIT credentials, copy them to a new
959 // ccache named after the principal
961 // Enumerate all existing MIT ccaches and construct entries
962 // in the principal_ccache table
964 // Enumerate all existing AFS Tokens and construct entries
965 // in the cell_principal table
967 KFW_import_ccache_data(void)
969 krb5_context ctx = 0;
971 krb5_principal principal = 0;
973 krb5_error_code code;
974 krb5_error_code cc_code;
977 struct _infoNC ** pNCi = NULL;
980 if ( !pcc_initialize )
983 if ( IsDebuggerPresent() )
984 OutputDebugString("KFW_import_ccache_data()\n");
986 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
987 if (code) goto cleanup;
989 code = pcc_get_NC_info(cc_ctx, &pNCi);
990 if (code) goto cleanup;
992 code = pkrb5_init_context(&ctx);
993 if (code) goto cleanup;
995 for ( i=0; pNCi[i]; i++ ) {
996 if ( pNCi[i]->vers != CC_CRED_V5 )
998 if ( IsDebuggerPresent() ) {
999 OutputDebugString("Principal: ");
1000 OutputDebugString(pNCi[i]->principal);
1001 OutputDebugString(" in ccache ");
1002 OutputDebugString(pNCi[i]->name);
1003 OutputDebugString("\n");
1005 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1006 && strcmp(pNCi[i]->name,LSA_CCNAME)
1009 for ( j=0; pNCi[j]; j++ ) {
1010 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1016 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1017 if (code) goto loop_cleanup;
1020 krb5_ccache oldcc = 0;
1022 if ( IsDebuggerPresent() )
1023 OutputDebugString("copying ccache data to new ccache\n");
1025 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1026 if (code) goto loop_cleanup;
1027 code = pkrb5_cc_initialize(ctx, cc, principal);
1028 if (code) goto loop_cleanup;
1030 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1031 if (code) goto loop_cleanup;
1032 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1034 code = pkrb5_cc_close(ctx,cc);
1036 code = pkrb5_cc_close(ctx,oldcc);
1038 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1041 code = pkrb5_cc_close(ctx,oldcc);
1044 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1045 if (code) goto loop_cleanup;
1048 flags = 0; // turn off OPENCLOSE mode
1049 code = pkrb5_cc_set_flags(ctx, cc, flags);
1050 if ( code ) goto cleanup;
1052 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1054 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1056 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1057 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1058 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1059 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1060 if ( sname && cell && !strcmp("afs",sname->data) ) {
1061 struct ktc_principal aserver;
1062 struct ktc_principal aclient;
1063 struct ktc_token atoken;
1066 if ( IsDebuggerPresent() ) {
1067 OutputDebugString("Found AFS ticket: ");
1068 OutputDebugString(sname->data);
1070 OutputDebugString("/");
1071 OutputDebugString(cell->data);
1073 OutputDebugString("@");
1074 OutputDebugString(realm->data);
1075 OutputDebugString("\n");
1078 memset(&aserver, '\0', sizeof(aserver));
1079 strcpy(aserver.name, sname->data);
1080 strcpy(aserver.cell, cell->data);
1082 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1084 // Found a token in AFS Client Server which matches
1085 char pname[128], *p, *q;
1086 for ( p=pname, q=aclient.name; *q; p++, q++)
1088 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1092 if ( IsDebuggerPresent() ) {
1093 OutputDebugString("Found AFS token: ");
1094 OutputDebugString(pname);
1095 OutputDebugString("\n");
1098 if ( strcmp(pname,pNCi[i]->principal) )
1100 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1102 // Attempt to import it
1103 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1105 if ( IsDebuggerPresent() ) {
1106 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1109 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data, pLeash_get_default_lifetime(),NULL);
1110 if ( IsDebuggerPresent() ) {
1112 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1113 OutputDebugString(message);
1116 } else if ( IsDebuggerPresent() ) {
1117 OutputDebugString("Found ticket: ");
1118 OutputDebugString(sname->data);
1119 if ( cell && cell->data ) {
1120 OutputDebugString("/");
1121 OutputDebugString(cell->data);
1123 OutputDebugString("@");
1124 OutputDebugString(realm->data);
1125 OutputDebugString("\n");
1127 pkrb5_free_cred_contents(ctx, &creds);
1130 if (cc_code == KRB5_CC_END) {
1131 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1132 if (cc_code) goto loop_cleanup;
1136 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1137 code = pkrb5_cc_set_flags(ctx, cc, flags);
1139 pkrb5_cc_close(ctx,cc);
1143 pkrb5_free_principal(ctx,principal);
1150 pkrb5_free_context(ctx);
1152 pcc_free_NC_info(cc_ctx, &pNCi);
1154 pcc_shutdown(&cc_ctx);
1159 KFW_AFS_get_cred( char * username,
1166 krb5_context ctx = 0;
1169 char ** realmlist = 0;
1170 krb5_principal principal = 0;
1172 krb5_error_code code;
1173 char local_cell[MAXCELLCHARS+1];
1174 char **cells = NULL;
1176 struct afsconf_cell cellconfig;
1180 if (!pkrb5_init_context)
1183 if ( IsDebuggerPresent() ) {
1184 OutputDebugString("KFW_AFS_get_cred for token ");
1185 OutputDebugString(username);
1186 OutputDebugString(" in cell ");
1187 OutputDebugString(cell);
1188 OutputDebugString("\n");
1191 code = pkrb5_init_context(&ctx);
1192 if ( code ) goto cleanup;
1194 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1195 if ( code ) goto cleanup;
1197 realm = strchr(username,'@');
1199 pname = strdup(username);
1200 realm = strchr(pname, '@');
1203 /* handle kerberos iv notation */
1204 while ( dot = strchr(pname,'.') ) {
1209 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1210 pname = malloc(strlen(username) + strlen(realm) + 2);
1212 strcpy(pname, username);
1214 /* handle kerberos iv notation */
1215 while ( dot = strchr(pname,'.') ) {
1220 strcat(pname,realm);
1223 if ( IsDebuggerPresent() ) {
1224 OutputDebugString("Realm: ");
1225 OutputDebugString(realm);
1226 OutputDebugString("\n");
1229 code = pkrb5_parse_name(ctx, pname, &principal);
1230 if ( code ) goto cleanup;
1232 code = KFW_get_ccache(ctx, principal, &cc);
1233 if ( code ) goto cleanup;
1235 if ( lifetime == 0 )
1236 lifetime = pLeash_get_default_lifetime();
1238 if ( password && password[0] ) {
1239 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1243 pLeash_get_default_forwardable(),
1244 pLeash_get_default_proxiable(),
1245 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1246 pLeash_get_default_noaddresses(),
1247 pLeash_get_default_publicip());
1248 if ( IsDebuggerPresent() ) {
1250 sprintf(message,"KFW_kinit() returns: %d\n",code);
1251 OutputDebugString(message);
1253 if ( code ) goto cleanup;
1255 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1258 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime,smbname);
1259 if ( IsDebuggerPresent() ) {
1261 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1262 OutputDebugString(message);
1264 if ( code ) goto cleanup;
1266 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1268 // Attempt to obtain new tokens for other cells supported by the same
1270 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1271 if ( cell_count > 1 ) {
1272 while ( cell_count-- ) {
1273 if ( strcmp(cells[cell_count],cell) ) {
1274 if ( IsDebuggerPresent() ) {
1276 sprintf(message,"found another cell for the same principal: %s\n",cell);
1277 OutputDebugString(message);
1279 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1280 if ( code ) continue;
1282 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1283 if ( IsDebuggerPresent() ) {
1284 OutputDebugString("Realm: ");
1285 OutputDebugString(realm);
1286 OutputDebugString("\n");
1289 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime,smbname);
1290 if ( IsDebuggerPresent() ) {
1292 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1293 OutputDebugString(message);
1296 free(cells[cell_count]);
1299 } else if ( cell_count == 1 ) {
1308 pkrb5_cc_close(ctx, cc);
1310 if ( code && reasonP ) {
1311 *reasonP = (char *)perror_message(code);
1317 KFW_AFS_destroy_tickets_for_cell(char * cell)
1319 krb5_context ctx = 0;
1320 krb5_error_code code;
1322 char ** principals = NULL;
1324 if (!pkrb5_init_context)
1327 if ( IsDebuggerPresent() ) {
1328 OutputDebugString("KFW_AFS_destroy_ticets_for_cell: ");
1329 OutputDebugString(cell);
1330 OutputDebugString("\n");
1333 code = pkrb5_init_context(&ctx);
1336 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1338 krb5_principal princ = 0;
1342 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1343 if ( cell_count > 1 ) {
1344 // TODO - What we really should do here is verify whether or not any of the
1345 // other cells which use this principal to obtain its credentials actually
1346 // have valid tokens or not. If they are currently using these credentials
1347 // we will skip them. For the time being we assume that if there is an active
1348 // map in the table that they are actively being used.
1352 code = pkrb5_parse_name(ctx, principals[count], &princ);
1353 if (code) goto loop_cleanup;
1355 code = KFW_get_ccache(ctx, princ, &cc);
1356 if (code) goto loop_cleanup;
1358 code = pkrb5_cc_destroy(ctx, cc);
1363 pkrb5_cc_close(ctx, cc);
1367 pkrb5_free_principal(ctx, princ);
1371 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1372 free(principals[count]);
1376 pkrb5_free_context(ctx);
1381 KFW_AFS_renew_expiring_tokens(void)
1383 krb5_error_code code = 0;
1384 krb5_context ctx = 0;
1387 struct principal_ccache_data * pcc_next = princ_cc_data;
1390 const char * realm = NULL;
1391 char local_cell[MAXCELLCHARS+1]="";
1392 struct afsconf_cell cellconfig;
1394 if (!pkrb5_init_context)
1397 if ( pcc_next == NULL ) // nothing to do
1400 if ( IsDebuggerPresent() ) {
1401 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1404 code = pkrb5_init_context(&ctx);
1405 if (code) goto cleanup;
1407 code = pkrb5_timeofday(ctx, &now);
1408 if (code) goto cleanup;
1410 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1411 if ( pcc_next->expired )
1414 if ( now >= (pcc_next->expiration_time) ) {
1415 if ( !pcc_next->from_lsa ) {
1416 pcc_next->expired = 1;
1421 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1422 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1425 code = KFW_renew(ctx,cc);
1427 if ( code && pcc_next->from_lsa)
1429 #endif /* USE_MS2MIT */
1432 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1433 if (code) goto loop_cleanup;
1435 // Attempt to obtain new tokens for other cells supported by the same
1437 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1438 if ( cell_count > 0 ) {
1439 while ( cell_count-- ) {
1440 if ( IsDebuggerPresent() ) {
1441 OutputDebugString("Cell: ");
1442 OutputDebugString(cells[cell_count]);
1443 OutputDebugString("\n");
1445 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1446 if ( code ) continue;
1447 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1448 if ( IsDebuggerPresent() ) {
1449 OutputDebugString("Realm: ");
1450 OutputDebugString(realm);
1451 OutputDebugString("\n");
1453 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, pLeash_get_default_lifetime(),NULL);
1454 if ( IsDebuggerPresent() ) {
1456 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1457 OutputDebugString(message);
1459 free(cells[cell_count]);
1467 pkrb5_cc_close(ctx,cc);
1474 pkrb5_cc_close(ctx,cc);
1476 pkrb5_free_context(ctx);
1483 KFW_AFS_renew_token_for_cell(char * cell)
1485 krb5_error_code code = 0;
1486 krb5_context ctx = 0;
1488 char ** principals = NULL;
1490 if (!pkrb5_init_context)
1493 if ( IsDebuggerPresent() ) {
1494 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1495 OutputDebugString(cell);
1496 OutputDebugString("\n");
1499 code = pkrb5_init_context(&ctx);
1500 if (code) goto cleanup;
1502 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1504 // We know we must have a credential somewhere since we are
1505 // trying to renew a token
1507 KFW_import_ccache_data();
1508 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1511 krb5_principal princ = 0;
1512 krb5_principal service = 0;
1514 krb5_creds mcreds, creds;
1515 #endif /* COMMENT */
1517 const char * realm = NULL;
1518 struct afsconf_cell cellconfig;
1519 char local_cell[MAXCELLCHARS+1];
1522 code = pkrb5_parse_name(ctx, principals[count], &princ);
1523 if (code) goto loop_cleanup;
1525 code = KFW_get_ccache(ctx, princ, &cc);
1526 if (code) goto loop_cleanup;
1528 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1529 if ( code ) goto loop_cleanup;
1531 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1532 if ( IsDebuggerPresent() ) {
1533 OutputDebugString("Realm: ");
1534 OutputDebugString(realm);
1535 OutputDebugString("\n");
1539 /* krb5_cc_remove_cred() is not implemented
1542 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1543 realm, "afs", cell, NULL);
1545 memset(&mcreds, 0, sizeof(krb5_creds));
1546 mcreds.client = princ;
1547 mcreds.server = service;
1549 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1551 if ( IsDebuggerPresent() ) {
1552 char * cname, *sname;
1553 pkrb5_unparse_name(ctx, creds.client, &cname);
1554 pkrb5_unparse_name(ctx, creds.server, &sname);
1555 OutputDebugString("Removing credential for client \"");
1556 OutputDebugString(cname);
1557 OutputDebugString("\" and service \"");
1558 OutputDebugString(sname);
1559 OutputDebugString("\"\n");
1560 pkrb5_free_unparsed_name(ctx,cname);
1561 pkrb5_free_unparsed_name(ctx,sname);
1564 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1565 pkrb5_free_principal(ctx, creds.client);
1566 pkrb5_free_principal(ctx, creds.server);
1569 #endif /* COMMENT */
1571 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, pLeash_get_default_lifetime(),NULL);
1572 if ( IsDebuggerPresent() ) {
1574 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1575 OutputDebugString(message);
1580 pkrb5_cc_close(ctx, cc);
1584 pkrb5_free_principal(ctx, princ);
1588 pkrb5_free_principal(ctx, service);
1592 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1593 free(principals[count]);
1597 code = -1; // we did not renew the tokens
1600 pkrb5_free_context(ctx);
1601 return (code ? FALSE : TRUE);
1606 KFW_AFS_renew_tokens_for_all_cells(void)
1608 struct cell_principal_map * next = cell_princ_map;
1610 if ( IsDebuggerPresent() )
1611 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1616 for ( ; next ; next = next->next ) {
1618 KFW_AFS_renew_token_for_cell(next->cell);
1624 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1626 krb5_error_code code = 0;
1627 krb5_context ctx = 0;
1629 krb5_principal me = 0;
1630 krb5_principal server = 0;
1631 krb5_creds my_creds;
1632 krb5_data *realm = 0;
1634 if (!pkrb5_init_context)
1637 memset(&my_creds, 0, sizeof(krb5_creds));
1642 code = pkrb5_init_context(&ctx);
1643 if (code) goto cleanup;
1649 code = pkrb5_cc_default(ctx, &cc);
1650 if (code) goto cleanup;
1653 code = pkrb5_cc_get_principal(ctx, cc, &me);
1654 if (code) goto cleanup;
1656 realm = krb5_princ_realm(ctx, me);
1658 code = pkrb5_build_principal_ext(ctx, &server,
1659 realm->length,realm->data,
1660 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1661 realm->length,realm->data,
1666 if ( IsDebuggerPresent() ) {
1667 char * cname, *sname;
1668 pkrb5_unparse_name(ctx, me, &cname);
1669 pkrb5_unparse_name(ctx, server, &sname);
1670 OutputDebugString("Renewing credential for client \"");
1671 OutputDebugString(cname);
1672 OutputDebugString("\" and service \"");
1673 OutputDebugString(sname);
1674 OutputDebugString("\"\n");
1675 pkrb5_free_unparsed_name(ctx,cname);
1676 pkrb5_free_unparsed_name(ctx,sname);
1679 my_creds.client = me;
1680 my_creds.server = server;
1682 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1684 if ( IsDebuggerPresent() ) {
1686 sprintf(message,"krb5_get_renewed_creds() failed: %d\n",code);
1687 OutputDebugString(message);
1692 code = pkrb5_cc_initialize(ctx, cc, me);
1694 if ( IsDebuggerPresent() ) {
1696 sprintf(message,"krb5_cc_initialize() failed: %d\n",code);
1697 OutputDebugString(message);
1702 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1704 if ( IsDebuggerPresent() ) {
1706 sprintf(message,"krb5_cc_store_cred() failed: %d\n",code);
1707 OutputDebugString(message);
1713 if (my_creds.client == me)
1714 my_creds.client = 0;
1715 if (my_creds.server == server)
1716 my_creds.server = 0;
1717 pkrb5_free_cred_contents(ctx, &my_creds);
1719 pkrb5_free_principal(ctx, me);
1721 pkrb5_free_principal(ctx, server);
1722 if (cc && (cc != alt_cc))
1723 pkrb5_cc_close(ctx, cc);
1724 if (ctx && (ctx != alt_ctx))
1725 pkrb5_free_context(ctx);
1730 KFW_kinit( krb5_context alt_ctx,
1733 char *principal_name,
1735 krb5_deltat lifetime,
1738 krb5_deltat renew_life,
1743 krb5_error_code code = 0;
1744 krb5_context ctx = 0;
1746 krb5_principal me = 0;
1748 krb5_creds my_creds;
1749 krb5_get_init_creds_opt options;
1750 krb5_address ** addrs = NULL;
1751 int i = 0, addr_count = 0;
1753 if (!pkrb5_init_context)
1756 pkrb5_get_init_creds_opt_init(&options);
1757 memset(&my_creds, 0, sizeof(my_creds));
1765 code = pkrb5_init_context(&ctx);
1766 if (code) goto cleanup;
1772 code = pkrb5_cc_default(ctx, &cc);
1773 if (code) goto cleanup;
1776 code = pkrb5_parse_name(ctx, principal_name, &me);
1780 code = pkrb5_unparse_name(ctx, me, &name);
1785 lifetime = pLeash_get_default_lifetime();
1793 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
1794 pkrb5_get_init_creds_opt_set_forwardable(&options,
1795 forwardable ? 1 : 0);
1796 pkrb5_get_init_creds_opt_set_proxiable(&options,
1798 pkrb5_get_init_creds_opt_set_renew_life(&options,
1801 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
1805 // we are going to add the public IP address specified by the user
1806 // to the list provided by the operating system
1807 krb5_address ** local_addrs=NULL;
1810 pkrb5_os_localaddr(ctx, &local_addrs);
1811 while ( local_addrs[i++] );
1814 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
1816 pkrb5_free_addresses(ctx, local_addrs);
1819 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
1821 while ( local_addrs[i] ) {
1822 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
1823 if (addrs[i] == NULL) {
1824 pkrb5_free_addresses(ctx, local_addrs);
1828 addrs[i]->magic = local_addrs[i]->magic;
1829 addrs[i]->addrtype = local_addrs[i]->addrtype;
1830 addrs[i]->length = local_addrs[i]->length;
1831 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
1832 if (!addrs[i]->contents) {
1833 pkrb5_free_addresses(ctx, local_addrs);
1837 memcpy(addrs[i]->contents,local_addrs[i]->contents,
1838 local_addrs[i]->length); /* safe */
1841 pkrb5_free_addresses(ctx, local_addrs);
1843 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
1844 if (addrs[i] == NULL)
1847 addrs[i]->magic = KV5M_ADDRESS;
1848 addrs[i]->addrtype = AF_INET;
1849 addrs[i]->length = 4;
1850 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
1851 if (!addrs[i]->contents)
1854 netIPAddr = htonl(publicIP);
1855 memcpy(addrs[i]->contents,&netIPAddr,4);
1857 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
1862 code = pkrb5_get_init_creds_password(ctx,
1865 password, // password
1866 KRB5_prompter, // prompter
1867 hParent, // prompter data
1874 code = pkrb5_cc_initialize(ctx, cc, me);
1878 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1884 for ( i=0;i<addr_count;i++ ) {
1886 if ( addrs[i]->contents )
1887 free(addrs[i]->contents);
1892 if (my_creds.client == me)
1893 my_creds.client = 0;
1894 pkrb5_free_cred_contents(ctx, &my_creds);
1896 pkrb5_free_unparsed_name(ctx, name);
1898 pkrb5_free_principal(ctx, me);
1899 if (cc && (cc != alt_cc))
1900 pkrb5_cc_close(ctx, cc);
1901 if (ctx && (ctx != alt_ctx))
1902 pkrb5_free_context(ctx);
1908 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
1912 krb5_error_code code;
1914 if (!pkrb5_init_context)
1923 code = pkrb5_init_context(&ctx);
1924 if (code) goto cleanup;
1930 code = pkrb5_cc_default(ctx, &cc);
1931 if (code) goto cleanup;
1934 code = pkrb5_cc_destroy(ctx, cc);
1935 if ( !code ) cc = 0;
1938 if (cc && (cc != alt_cc))
1939 pkrb5_cc_close(ctx, cc);
1940 if (ctx && (ctx != alt_ctx))
1941 pkrb5_free_context(ctx);
1949 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
1951 NTSTATUS Status = 0;
1953 TOKEN_STATISTICS Stats;
1959 *ppSessionData = NULL;
1961 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
1965 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
1966 CloseHandle( TokenHandle );
1970 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
1971 if ( FAILED(Status) || !ppSessionData )
1978 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
1979 // cache. It validates whether or not it is reasonable to assume that if we
1980 // attempted to retrieve valid tickets we could do so. Microsoft does not
1981 // automatically renew expired tickets. Therefore, the cache could contain
1982 // expired or invalid tickets. Microsoft also caches the user's password
1983 // and will use it to retrieve new TGTs if the cache is empty and tickets
1987 MSLSA_IsKerberosLogon(VOID)
1989 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
1990 BOOL Success = FALSE;
1992 if ( GetSecurityLogonSessionData(&pSessionData) ) {
1993 if ( pSessionData->AuthenticationPackage.Buffer ) {
1999 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2000 usLength = (pSessionData->AuthenticationPackage).Length;
2003 lstrcpynW (buffer, usBuffer, usLength);
2004 lstrcatW (buffer,L"");
2005 if ( !lstrcmpW(L"Kerberos",buffer) )
2009 pLsaFreeReturnBuffer(pSessionData);
2013 #endif /* USE_MS2MIT */
2015 static BOOL CALLBACK
2016 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2020 switch ( message ) {
2022 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2024 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2027 for ( i=0; i < mid_cnt ; i++ ) {
2028 if (mid_tb[i].echo == 0)
2029 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2030 else if (mid_tb[i].echo == 2)
2031 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2036 switch ( LOWORD(wParam) ) {
2038 for ( i=0; i < mid_cnt ; i++ ) {
2039 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2040 *mid_tb[i].buf = '\0';
2044 EndDialog(hDialog, LOWORD(wParam));
2052 lpwAlign( LPWORD lpIn )
2060 return (LPWORD) ul;;
2064 * dialog widths are measured in 1/4 character widths
2065 * dialog height are measured in 1/8 character heights
2069 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2070 char * ptext[], int numlines, int width,
2071 int tb_cnt, struct textField * tb)
2075 LPDLGITEMTEMPLATE lpdit;
2081 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2088 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2090 // Define a dialog box.
2092 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2093 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2094 | DS_SETFOREGROUND | DS_3DLOOK
2095 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2096 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2099 lpdt->cx = 20 + width * 4;
2100 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2102 lpw = (LPWORD) (lpdt + 1);
2103 *lpw++ = 0; // no menu
2104 *lpw++ = 0; // predefined dialog box class (by default)
2106 lpwsz = (LPWSTR) lpw;
2107 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2109 *lpw++ = 8; // font size (points)
2110 lpwsz = (LPWSTR) lpw;
2111 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2115 //-----------------------
2116 // Define an OK button.
2117 //-----------------------
2118 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2119 lpdit = (LPDLGITEMTEMPLATE) lpw;
2120 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2121 lpdit->dwExtendedStyle = 0;
2122 lpdit->x = (lpdt->cx - 14)/4 - 20;
2123 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2126 lpdit->id = IDOK; // OK button identifier
2128 lpw = (LPWORD) (lpdit + 1);
2130 *lpw++ = 0x0080; // button class
2132 lpwsz = (LPWSTR) lpw;
2133 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2135 *lpw++ = 0; // no creation data
2137 //-----------------------
2138 // Define an Cancel button.
2139 //-----------------------
2140 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2141 lpdit = (LPDLGITEMTEMPLATE) lpw;
2142 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2143 lpdit->dwExtendedStyle = 0;
2144 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2145 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2148 lpdit->id = IDCANCEL; // CANCEL button identifier
2150 lpw = (LPWORD) (lpdit + 1);
2152 *lpw++ = 0x0080; // button class
2154 lpwsz = (LPWSTR) lpw;
2155 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2157 *lpw++ = 0; // no creation data
2159 /* Add controls for preface data */
2160 for ( i=0; i<numlines; i++) {
2161 /*-----------------------
2162 * Define a static text control.
2163 *-----------------------*/
2164 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2165 lpdit = (LPDLGITEMTEMPLATE) lpw;
2166 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2167 lpdit->dwExtendedStyle = 0;
2169 lpdit->y = 10 + i * 14;
2170 lpdit->cx = strlen(ptext[i]) * 4 + 10;
2172 lpdit->id = ID_TEXT + i; // text identifier
2174 lpw = (LPWORD) (lpdit + 1);
2176 *lpw++ = 0x0082; // static class
2178 lpwsz = (LPWSTR) lpw;
2179 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2180 -1, lpwsz, 2*width);
2182 *lpw++ = 0; // no creation data
2185 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2186 if ( pwid < strlen(tb[i].label) )
2187 pwid = strlen(tb[i].label);
2190 for ( i=0; i<tb_cnt; i++) {
2192 /*-----------------------
2193 * Define a static text control.
2194 *-----------------------*/
2195 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2196 lpdit = (LPDLGITEMTEMPLATE) lpw;
2197 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2198 lpdit->dwExtendedStyle = 0;
2200 lpdit->y = 10 + (numlines + i + 1) * 14;
2201 lpdit->cx = pwid * 4;
2203 lpdit->id = ID_TEXT + numlines + i; // text identifier
2205 lpw = (LPWORD) (lpdit + 1);
2207 *lpw++ = 0x0082; // static class
2209 lpwsz = (LPWSTR) lpw;
2210 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2213 *lpw++ = 0; // no creation data
2215 /*-----------------------
2216 * Define an edit control.
2217 *-----------------------*/
2218 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2219 lpdit = (LPDLGITEMTEMPLATE) lpw;
2220 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2221 lpdit->dwExtendedStyle = 0;
2222 lpdit->x = 10 + (pwid + 1) * 4;
2223 lpdit->y = 10 + (numlines + i + 1) * 14;
2224 lpdit->cx = (width - (pwid + 1)) * 4;
2226 lpdit->id = ID_MID_TEXT + i; // identifier
2228 lpw = (LPWORD) (lpdit + 1);
2230 *lpw++ = 0x0081; // edit class
2232 lpwsz = (LPWSTR) lpw;
2233 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2236 *lpw++ = 0; // no creation data
2240 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2241 hwndOwner, (DLGPROC) MultiInputDialogProc);
2245 case 0: /* Timeout */
2253 sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
2254 MessageBox(hwndOwner,
2257 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2264 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2266 HINSTANCE hInst = 0;
2270 char * plines[16], *p = preface ? preface : "";
2273 for ( i=0; i<16; i++ )
2276 while (*p && numlines < 16) {
2277 plines[numlines++] = p;
2278 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2279 if ( *p == '\r' && *(p+1) == '\n' ) {
2282 } else if ( *p == '\n' ) {
2285 if ( strlen(plines[numlines-1]) > maxwidth )
2286 maxwidth = strlen(plines[numlines-1]);
2289 for ( i=0;i<n;i++ ) {
2290 len = strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2291 if ( maxwidth < len )
2295 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb));
2298 static krb5_error_code KRB5_CALLCONV
2299 KRB5_prompter( krb5_context context,
2304 krb5_prompt prompts[])
2306 krb5_error_code errcode = 0;
2308 struct textField * tb = NULL;
2309 int len = 0, blen=0, nlen=0;
2310 HWND hParent = (HWND)data;
2313 nlen = strlen(name)+2;
2316 blen = strlen(banner)+2;
2318 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2321 memset(tb,0,sizeof(struct textField) * num_prompts);
2322 for ( i=0; i < num_prompts; i++ ) {
2323 tb[i].buf = prompts[i].reply->data;
2324 tb[i].len = prompts[i].reply->length;
2325 tb[i].label = prompts[i].prompt;
2327 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2330 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2332 for ( i=0; i < num_prompts; i++ )
2333 prompts[i].reply->length = strlen(prompts[i].reply->data);
2341 for (i = 0; i < num_prompts; i++) {
2342 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2349 KFW_AFS_wait_for_service_start(void)
2354 CurrentState = SERVICE_START_PENDING;
2355 memset(HostName, '\0', sizeof(HostName));
2356 gethostname(HostName, sizeof(HostName));
2358 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2360 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2362 if ( IsDebuggerPresent() ) {
2363 switch ( CurrentState ) {
2364 case SERVICE_STOPPED:
2365 OutputDebugString("SERVICE_STOPPED\n");
2367 case SERVICE_START_PENDING:
2368 OutputDebugString("SERVICE_START_PENDING\n");
2370 case SERVICE_STOP_PENDING:
2371 OutputDebugString("SERVICE_STOP_PENDING\n");
2373 case SERVICE_RUNNING:
2374 OutputDebugString("SERVICE_RUNNING\n");
2376 case SERVICE_CONTINUE_PENDING:
2377 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2379 case SERVICE_PAUSE_PENDING:
2380 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2382 case SERVICE_PAUSED:
2383 OutputDebugString("SERVICE_PAUSED\n");
2386 OutputDebugString("UNKNOWN Service State\n");
2389 if (CurrentState == SERVICE_STOPPED)
2391 if (CurrentState == SERVICE_RUNNING)
2407 memset(HostName, '\0', sizeof(HostName));
2408 gethostname(HostName, sizeof(HostName));
2409 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2411 if (CurrentState != SERVICE_RUNNING)
2414 rc = ktc_ForgetAllTokens();
2420 #define ALLOW_REGISTER 1
2422 ViceIDToUsername(char *username,
2423 char *realm_of_user,
2424 char *realm_of_cell,
2426 struct ktc_principal *aclient,
2427 struct ktc_principal *aserver,
2428 struct ktc_token *atoken)
2430 static char lastcell[MAXCELLCHARS+1] = { 0 };
2431 static char confname[512] = { 0 };
2432 char username_copy[BUFSIZ];
2433 long viceId; /* AFS uid of user */
2435 #ifdef ALLOW_REGISTER
2437 #endif /* ALLOW_REGISTER */
2439 if (confname[0] == '\0') {
2440 strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname));
2441 confname[sizeof(confname) - 2] = '\0';
2445 * Talk about DUMB! It turns out that there is a bug in
2446 * pr_Initialize -- even if you give a different cell name
2447 * to it, it still uses a connection to a previous AFS server
2448 * if one exists. The way to fix this is to change the
2449 * _filename_ argument to pr_Initialize - that forces it to
2450 * re-initialize the connection. We do this by adding and
2451 * removing a "/" on the end of the configuration directory name.
2454 if (lastcell[0] != '\0' && (strcmp(lastcell, aserver->cell) != 0)) {
2455 int i = strlen(confname);
2456 if (confname[i - 1] == '/') {
2457 confname[i - 1] = '\0';
2460 confname[i + 1] = '\0';
2464 strcpy(lastcell, aserver->cell);
2466 if (!pr_Initialize (0, confname, aserver->cell))
2467 status = pr_SNameToId (username, &viceId);
2470 * This is a crock, but it is Transarc's crock, so
2471 * we have to play along in order to get the
2472 * functionality. The way the afs id is stored is
2473 * as a string in the username field of the token.
2474 * Contrary to what you may think by looking at
2475 * the code for tokens, this hack (AFS ID %d) will
2476 * not work if you change %d to something else.
2480 * This code is taken from cklog -- it lets people
2481 * automatically register with the ptserver in foreign cells
2484 #ifdef ALLOW_REGISTER
2486 if (viceId != ANONYMOUSID) {
2487 #else /* ALLOW_REGISTER */
2488 if ((status == 0) && (viceId != ANONYMOUSID))
2489 #endif /* ALLOW_REGISTER */
2491 #ifdef AFS_ID_TO_NAME
2492 strncpy(username_copy, username, BUFSIZ);
2493 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2494 #endif /* AFS_ID_TO_NAME */
2496 #ifdef ALLOW_REGISTER
2497 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2499 strncpy(aclient->name, username, MAXKTCNAMELEN - 1);
2500 strcpy(aclient->instance, "");
2501 strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
2502 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2506 * In case you're wondering, we don't need to change the
2507 * filename here because we're still connecting to the
2508 * same cell -- we're just using a different authentication
2512 if (status = pr_Initialize(1L, confname, aserver->cell, 0))
2514 if (status = pr_CreateUser(username, &id))
2516 #ifdef AFS_ID_TO_NAME
2517 strncpy(username_copy, username, BUFSIZ);
2518 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2519 #endif /* AFS_ID_TO_NAME */
2522 #endif /* ALLOW_REGISTER */
2529 krb5_context alt_ctx,
2541 struct ktc_principal aserver;
2542 struct ktc_principal aclient;
2543 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2544 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2545 char local_cell[MAXCELLCHARS+1];
2546 char Dmycell[MAXCELLCHARS+1];
2547 struct ktc_token atoken;
2548 struct ktc_token btoken;
2549 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2550 char RealmName[128];
2552 char ServiceName[128];
2556 krb5_context ctx = 0;
2559 krb5_creds * k5creds = 0;
2560 krb5_error_code code;
2561 krb5_principal client_principal = 0;
2565 memset(HostName, '\0', sizeof(HostName));
2566 gethostname(HostName, sizeof(HostName));
2567 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2568 if ( IsDebuggerPresent() )
2569 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2572 if (CurrentState != SERVICE_RUNNING) {
2573 if ( IsDebuggerPresent() )
2574 OutputDebugString("AFSD Service NOT RUNNING\n");
2578 if (!pkrb5_init_context)
2581 memset(RealmName, '\0', sizeof(RealmName));
2582 memset(CellName, '\0', sizeof(CellName));
2583 memset(ServiceName, '\0', sizeof(ServiceName));
2584 memset(realm_of_user, '\0', sizeof(realm_of_user));
2585 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2586 if (cell && cell[0])
2587 strcpy(Dmycell, cell);
2589 memset(Dmycell, '\0', sizeof(Dmycell));
2591 // NULL or empty cell returns information on local cell
2592 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2594 // KFW_AFS_error(rc, "get_cellconfig()");
2601 code = pkrb5_init_context(&ctx);
2602 if (code) goto cleanup;
2608 code = pkrb5_cc_default(ctx, &cc);
2609 if (code) goto skip_krb5_init;
2612 memset((char *)&increds, 0, sizeof(increds));
2614 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2616 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2618 OutputDebugString("Principal Not Found for ccache\n");
2620 goto skip_krb5_init;
2623 if ( strchr(krb5_princ_component(ctx,client_principal,0),'.') != NULL )
2625 OutputDebugString("Illegal Principal name contains dot in first component\n");
2626 rc = KRB5KRB_ERR_GENERIC;
2630 i = krb5_princ_realm(ctx, client_principal)->length;
2633 strncpy(realm_of_user,krb5_princ_realm(ctx, client_principal)->data,i);
2634 realm_of_user[i] = 0;
2639 if ( !try_krb5 || !realm_of_user[0] ) {
2640 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2649 strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig));
2651 if (strlen(service) == 0)
2652 strcpy(ServiceName, "afs");
2654 strcpy(ServiceName, service);
2656 if (strlen(cell) == 0)
2657 strcpy(CellName, local_cell);
2659 strcpy(CellName, cell);
2661 if (strlen(realm) == 0)
2662 strcpy(RealmName, realm_of_cell);
2664 strcpy(RealmName, realm);
2666 memset(&creds, '\0', sizeof(creds));
2671 /* First try service/cell@REALM */
2672 if (code = pkrb5_build_principal(ctx, &increds.server,
2682 increds.client = client_principal;
2683 increds.times.endtime = 0;
2684 /* Ask for DES since that is what V4 understands */
2685 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
2688 if ( IsDebuggerPresent() ) {
2689 char * cname, *sname;
2690 pkrb5_unparse_name(ctx, increds.client, &cname);
2691 pkrb5_unparse_name(ctx, increds.server, &sname);
2692 OutputDebugString("Getting tickets for \"");
2693 OutputDebugString(cname);
2694 OutputDebugString("\" and service \"");
2695 OutputDebugString(sname);
2696 OutputDebugString("\"\n");
2697 pkrb5_free_unparsed_name(ctx,cname);
2698 pkrb5_free_unparsed_name(ctx,sname);
2701 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2702 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2703 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2704 code == KRB5KRB_AP_ERR_MSG_TYPE) {
2705 /* Or service@REALM */
2706 pkrb5_free_principal(ctx,increds.server);
2708 code = pkrb5_build_principal(ctx, &increds.server,
2714 if ( IsDebuggerPresent() ) {
2715 char * cname, *sname;
2716 pkrb5_unparse_name(ctx, increds.client, &cname);
2717 pkrb5_unparse_name(ctx, increds.server, &sname);
2718 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2719 OutputDebugString("Trying again: getting tickets for \"");
2720 OutputDebugString(cname);
2721 OutputDebugString("\" and service \"");
2722 OutputDebugString(sname);
2723 OutputDebugString("\"\n");
2724 pkrb5_free_unparsed_name(ctx,cname);
2725 pkrb5_free_unparsed_name(ctx,sname);
2729 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2732 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2733 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2734 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
2735 strcmp(RealmName, realm_of_cell)) {
2736 /* Or service/cell@REALM_OF_CELL */
2737 strcpy(RealmName, realm_of_cell);
2738 pkrb5_free_principal(ctx,increds.server);
2740 code = pkrb5_build_principal(ctx, &increds.server,
2747 if ( IsDebuggerPresent() ) {
2748 char * cname, *sname;
2749 pkrb5_unparse_name(ctx, increds.client, &cname);
2750 pkrb5_unparse_name(ctx, increds.server, &sname);
2751 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2752 OutputDebugString("Trying again: getting tickets for \"");
2753 OutputDebugString(cname);
2754 OutputDebugString("\" and service \"");
2755 OutputDebugString(sname);
2756 OutputDebugString("\"\n");
2757 pkrb5_free_unparsed_name(ctx,cname);
2758 pkrb5_free_unparsed_name(ctx,sname);
2762 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2765 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2766 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2767 code == KRB5KRB_AP_ERR_MSG_TYPE) {
2768 /* Or service@REALM_OF_CELL */
2769 pkrb5_free_principal(ctx,increds.server);
2771 code = pkrb5_build_principal(ctx, &increds.server,
2777 if ( IsDebuggerPresent() ) {
2778 char * cname, *sname;
2779 pkrb5_unparse_name(ctx, increds.client, &cname);
2780 pkrb5_unparse_name(ctx, increds.server, &sname);
2781 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2782 OutputDebugString("Trying again: getting tickets for \"");
2783 OutputDebugString(cname);
2784 OutputDebugString("\" and service \"");
2785 OutputDebugString(sname);
2786 OutputDebugString("\"\n");
2787 pkrb5_free_unparsed_name(ctx,cname);
2788 pkrb5_free_unparsed_name(ctx,sname);
2792 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2797 if ( IsDebuggerPresent() ) {
2799 sprintf(message,"krb5_get_credentials returns: %d\n",code);
2800 OutputDebugString(message);
2806 /* This code inserts the entire K5 ticket into the token
2807 * No need to perform a krb524 translation which is
2808 * commented out in the code below
2810 if (KFW_use_krb524() ||
2811 k5creds->ticket.length > MAXKTCTICKETLEN)
2814 memset(&aserver, '\0', sizeof(aserver));
2815 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
2816 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
2818 memset(&atoken, '\0', sizeof(atoken));
2819 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
2820 atoken.startTime = k5creds->times.starttime;
2821 atoken.endTime = k5creds->times.endtime;
2822 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
2823 atoken.ticketLen = k5creds->ticket.length;
2824 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
2827 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
2828 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
2829 if ( rc == KTC_NOCM && retry < 20 ) {
2832 goto retry_gettoken5;
2837 if (atoken.kvno == btoken.kvno &&
2838 atoken.ticketLen == btoken.ticketLen &&
2839 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
2840 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
2842 /* Success - Nothing to do */
2846 // * Reset the "aclient" structure before we call ktc_SetToken.
2847 // * This structure was first set by the ktc_GetToken call when
2848 // * we were comparing whether identical tokens already existed.
2850 len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
2851 strncpy(aclient.name, k5creds->client->data[0].data, len);
2852 aclient.name[len] = '\0';
2854 if ( k5creds->client->length > 1 ) {
2856 strcat(aclient.name, ".");
2857 p = aclient.name + strlen(aclient.name);
2858 len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
2859 strncpy(p, k5creds->client->data[1].data, len);
2862 aclient.instance[0] = '\0';
2864 strcpy(aclient.cell, realm_of_cell);
2866 len = min(k5creds->client->realm.length,strlen(realm_of_cell));
2867 if ( strncmp(realm_of_cell, k5creds->client->realm.data, len) ) {
2869 strcat(aclient.name, "@");
2870 p = aclient.name + strlen(aclient.name);
2871 len = min(k5creds->client->realm.length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
2872 strncpy(p, k5creds->client->realm.data, len);
2876 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
2877 &aclient, &aserver, &atoken);
2880 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
2881 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
2883 aclient.smbname[0] = '\0';
2886 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
2888 goto cleanup; /* We have successfully inserted the token */
2891 /* Otherwise, the ticket could have been too large so try to
2892 * convert using the krb524d running with the KDC
2894 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
2895 pkrb5_free_creds(ctx, k5creds);
2897 if ( IsDebuggerPresent() ) {
2899 sprintf(message,"krb524_convert_creds_kdc returns: %d\n",code);
2900 OutputDebugString(message);
2908 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
2909 if (code == NO_TKT_FIL) {
2910 // if the problem is that we have no krb4 tickets
2911 // do not attempt to continue
2914 if (code != KSUCCESS)
2915 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
2917 if (code != KSUCCESS)
2919 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
2921 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
2926 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
2928 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
2943 memset(&aserver, '\0', sizeof(aserver));
2944 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
2945 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
2947 memset(&atoken, '\0', sizeof(atoken));
2948 atoken.kvno = creds.kvno;
2949 atoken.startTime = creds.issue_date;
2950 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
2951 memcpy(&atoken.sessionKey, creds.session, 8);
2952 atoken.ticketLen = creds.ticket_st.length;
2953 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
2956 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
2957 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
2958 if ( rc == KTC_NOCM && retry < 20 ) {
2961 goto retry_gettoken;
2963 KFW_AFS_error(rc, "ktc_GetToken()");
2968 if (atoken.kvno == btoken.kvno &&
2969 atoken.ticketLen == btoken.ticketLen &&
2970 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
2971 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
2976 // * Reset the "aclient" structure before we call ktc_SetToken.
2977 // * This structure was first set by the ktc_GetToken call when
2978 // * we were comparing whether identical tokens already existed.
2980 strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
2983 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
2984 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
2986 strcpy(aclient.instance, "");
2988 if ( strcmp(realm_of_cell, creds.realm) )
2990 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
2991 strncpy(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
2993 aclient.name[MAXKTCREALMLEN-1] = '\0';
2995 strcpy(aclient.cell, CellName);
2997 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
2998 &aclient, &aserver, &atoken);
3001 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
3002 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
3004 aclient.smbname[0] = '\0';
3007 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3009 KFW_AFS_error(rc, "ktc_SetToken()");
3015 if (client_principal)
3016 pkrb5_free_principal(ctx,client_principal);
3017 /* increds.client == client_principal */
3019 pkrb5_free_principal(ctx,increds.server);
3020 if (cc && (cc != alt_cc))
3021 pkrb5_cc_close(ctx, cc);
3022 if (ctx && (ctx != alt_ctx))
3023 pkrb5_free_context(ctx);
3025 return(rc? rc : code);
3028 /**************************************/
3029 /* afs_realm_of_cell(): */
3030 /**************************************/
3032 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3034 static char krbrlm[REALM_SZ+1]="";
3035 char ** realmlist=NULL;
3041 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3042 if ( !r && realmlist && realmlist[0] ) {
3043 strcpy(krbrlm, realmlist[0]);
3044 pkrb5_free_host_realm(ctx, realmlist);
3050 char *t = cellconfig->name;
3055 if (islower(c)) c=toupper(c);
3063 /**************************************/
3064 /* KFW_AFS_get_cellconfig(): */
3065 /**************************************/
3067 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3070 char newcell[MAXCELLCHARS+1];
3072 local_cell[0] = (char)0;
3073 memset(cellconfig, 0, sizeof(*cellconfig));
3075 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3076 if (rc = cm_GetRootCellName(local_cell))
3081 if (strlen(cell) == 0)
3082 strcpy(cell, local_cell);
3084 /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
3085 strcpy(cellconfig->name, cell);
3087 rc = cm_SearchCellFile(cell, newcell, get_cellconfig_callback, (void*)cellconfig);
3088 #ifdef AFS_AFSDB_ENV
3091 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3097 /**************************************/
3098 /* get_cellconfig_callback(): */
3099 /**************************************/
3101 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep)
3103 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3105 cc->hostAddr[cc->numServers] = *addrp;
3106 strcpy(cc->hostName[cc->numServers], namep);
3112 /**************************************/
3113 /* KFW_AFS_error(): */
3114 /**************************************/
3116 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3119 const char *errText;
3121 // Using AFS defines as error messages for now, until Transarc
3122 // gets back to me with "string" translations of each of these
3124 if (rc == KTC_ERROR)
3125 errText = "KTC_ERROR";
3126 else if (rc == KTC_TOOBIG)
3127 errText = "KTC_TOOBIG";
3128 else if (rc == KTC_INVAL)
3129 errText = "KTC_INVAL";
3130 else if (rc == KTC_NOENT)
3131 errText = "KTC_NOENT";
3132 else if (rc == KTC_PIOCTLFAIL)
3133 errText = "KTC_PIOCTLFAIL";
3134 else if (rc == KTC_NOPIOCTL)
3135 errText = "KTC_NOPIOCTL";
3136 else if (rc == KTC_NOCELL)
3137 errText = "KTC_NOCELL";
3138 else if (rc == KTC_NOCM)
3139 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3141 errText = "Unknown error!";
3143 sprintf(message, "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3145 if ( IsDebuggerPresent() ) {
3146 OutputDebugString(message);
3147 OutputDebugString("\n");
3149 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3155 LPSTR lpszMachineName,
3156 LPSTR lpszServiceName,
3157 DWORD *lpdwCurrentState)
3160 SC_HANDLE schSCManager = NULL;
3161 SC_HANDLE schService = NULL;
3162 DWORD fdwDesiredAccess = 0;
3163 SERVICE_STATUS ssServiceStatus = {0};
3166 *lpdwCurrentState = 0;
3168 fdwDesiredAccess = GENERIC_READ;
3170 schSCManager = OpenSCManager(lpszMachineName,
3174 if(schSCManager == NULL)
3176 hr = GetLastError();
3180 schService = OpenService(schSCManager,
3184 if(schService == NULL)
3186 hr = GetLastError();
3190 fRet = QueryServiceStatus(schService,
3195 hr = GetLastError();
3199 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3203 CloseServiceHandle(schService);
3204 CloseServiceHandle(schSCManager);
3217 for (n = 0; fi[n].func_ptr_var; n++)
3218 *(fi[n].func_ptr_var) = 0;
3219 if (h) FreeLibrary(h);
3224 const char* dll_name,
3226 HINSTANCE* ph, // [out, optional] - DLL handle
3227 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3228 int cleanup, // cleanup function pointers and unload on error
3229 int go_on, // continue loading even if some functions cannot be loaded
3230 int silent // do not pop-up a system dialog if DLL cannot be loaded
3239 if (pindex) *pindex = -1;
3241 for (n = 0; fi[n].func_ptr_var; n++)
3242 *(fi[n].func_ptr_var) = 0;
3245 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3246 h = LoadLibrary(dll_name);
3254 for (i = 0; (go_on || !error) && (i < n); i++)
3256 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3262 *(fi[i].func_ptr_var) = p;
3265 if (pindex) *pindex = last_i;
3266 if (error && cleanup && !go_on) {
3267 for (i = 0; i < n; i++) {
3268 *(fi[i].func_ptr_var) = 0;
3274 if (error) return 0;
3278 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3280 krb5_context ctx = 0;
3282 krb5_error_code code;
3284 const char * realm = 0;
3285 krb5_principal principal = 0;
3287 char password[PROBE_PASSWORD_LEN+1];
3288 BOOL serverReachable = 0;
3290 if (!pkrb5_init_context)
3293 code = pkrb5_init_context(&ctx);
3294 if (code) goto cleanup;
3297 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3299 code = pkrb5_build_principal(ctx, &principal, strlen(realm),
3300 realm, PROBE_USERNAME, NULL, NULL);
3301 if ( code ) goto cleanup;
3303 code = KFW_get_ccache(ctx, principal, &cc);
3304 if ( code ) goto cleanup;
3306 code = pkrb5_unparse_name(ctx, principal, &pname);
3307 if ( code ) goto cleanup;
3309 pwdata.data = password;
3310 pwdata.length = PROBE_PASSWORD_LEN;
3311 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3314 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3317 password[PROBE_PASSWORD_LEN] = '\0';
3319 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3329 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3330 case KRB5KDC_ERR_CLIENT_REVOKED:
3331 case KRB5KDC_ERR_CLIENT_NOTYET:
3332 case KRB5KDC_ERR_PREAUTH_FAILED:
3333 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3334 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3335 serverReachable = TRUE;
3338 serverReachable = FALSE;
3343 pkrb5_free_unparsed_name(ctx,pname);
3345 pkrb5_free_principal(ctx,principal);
3347 pkrb5_cc_close(ctx,cc);
3349 pkrb5_free_context(ctx);
3351 return serverReachable;