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>
66 #include <afs/ptuser.h>
69 * TIMING _____________________________________________________________________
73 #define cminREMIND_TEST 1 // test every minute for expired creds
74 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
75 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
76 #define cminMINLIFE 30 // minimum life of Kerberos creds
78 #define c100ns1SECOND (LONGLONG)10000000
79 #define cmsec1SECOND 1000
80 #define cmsec1MINUTE 60000
81 #define csec1MINUTE 60
83 /* Function Pointer Declarations for Delayed Loading */
85 DECL_FUNC_PTR(cc_initialize);
86 DECL_FUNC_PTR(cc_shutdown);
87 DECL_FUNC_PTR(cc_get_NC_info);
88 DECL_FUNC_PTR(cc_free_NC_info);
91 DECL_FUNC_PTR(Leash_get_default_lifetime);
92 DECL_FUNC_PTR(Leash_get_default_forwardable);
93 DECL_FUNC_PTR(Leash_get_default_renew_till);
94 DECL_FUNC_PTR(Leash_get_default_noaddresses);
95 DECL_FUNC_PTR(Leash_get_default_proxiable);
96 DECL_FUNC_PTR(Leash_get_default_publicip);
97 DECL_FUNC_PTR(Leash_get_default_use_krb4);
98 DECL_FUNC_PTR(Leash_get_default_life_min);
99 DECL_FUNC_PTR(Leash_get_default_life_max);
100 DECL_FUNC_PTR(Leash_get_default_renew_min);
101 DECL_FUNC_PTR(Leash_get_default_renew_max);
102 DECL_FUNC_PTR(Leash_get_default_renewable);
103 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
106 DECL_FUNC_PTR(krb5_change_password);
107 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
108 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
109 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
110 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
111 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
112 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
113 DECL_FUNC_PTR(krb5_get_init_creds_password);
114 DECL_FUNC_PTR(krb5_build_principal_ext);
115 DECL_FUNC_PTR(krb5_cc_get_name);
116 DECL_FUNC_PTR(krb5_cc_resolve);
117 DECL_FUNC_PTR(krb5_cc_default);
118 DECL_FUNC_PTR(krb5_cc_default_name);
119 DECL_FUNC_PTR(krb5_cc_set_default_name);
120 DECL_FUNC_PTR(krb5_cc_initialize);
121 DECL_FUNC_PTR(krb5_cc_destroy);
122 DECL_FUNC_PTR(krb5_cc_close);
123 DECL_FUNC_PTR(krb5_cc_store_cred);
124 DECL_FUNC_PTR(krb5_cc_copy_creds);
125 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
126 DECL_FUNC_PTR(krb5_cc_get_principal);
127 DECL_FUNC_PTR(krb5_cc_start_seq_get);
128 DECL_FUNC_PTR(krb5_cc_next_cred);
129 DECL_FUNC_PTR(krb5_cc_end_seq_get);
130 DECL_FUNC_PTR(krb5_cc_remove_cred);
131 DECL_FUNC_PTR(krb5_cc_set_flags);
132 DECL_FUNC_PTR(krb5_cc_get_type);
133 DECL_FUNC_PTR(krb5_free_context);
134 DECL_FUNC_PTR(krb5_free_cred_contents);
135 DECL_FUNC_PTR(krb5_free_principal);
136 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
137 DECL_FUNC_PTR(krb5_init_context);
138 DECL_FUNC_PTR(krb5_parse_name);
139 DECL_FUNC_PTR(krb5_timeofday);
140 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
141 DECL_FUNC_PTR(krb5_unparse_name);
142 DECL_FUNC_PTR(krb5_get_credentials);
143 DECL_FUNC_PTR(krb5_mk_req);
144 DECL_FUNC_PTR(krb5_sname_to_principal);
145 DECL_FUNC_PTR(krb5_get_credentials_renew);
146 DECL_FUNC_PTR(krb5_free_data);
147 DECL_FUNC_PTR(krb5_free_data_contents);
148 DECL_FUNC_PTR(krb5_free_unparsed_name);
149 DECL_FUNC_PTR(krb5_os_localaddr);
150 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
151 DECL_FUNC_PTR(krb5_copy_data);
152 DECL_FUNC_PTR(krb5_free_creds);
153 DECL_FUNC_PTR(krb5_build_principal);
154 DECL_FUNC_PTR(krb5_get_renewed_creds);
155 DECL_FUNC_PTR(krb5_get_default_config_files);
156 DECL_FUNC_PTR(krb5_free_config_files);
157 DECL_FUNC_PTR(krb5_get_default_realm);
158 DECL_FUNC_PTR(krb5_free_default_realm);
159 DECL_FUNC_PTR(krb5_free_ticket);
160 DECL_FUNC_PTR(krb5_decode_ticket);
161 DECL_FUNC_PTR(krb5_get_host_realm);
162 DECL_FUNC_PTR(krb5_free_host_realm);
163 DECL_FUNC_PTR(krb5_free_addresses);
164 DECL_FUNC_PTR(krb5_c_random_make_octets);
167 DECL_FUNC_PTR(krb524_init_ets);
168 DECL_FUNC_PTR(krb524_convert_creds_kdc);
171 DECL_FUNC_PTR(krb_get_cred);
172 DECL_FUNC_PTR(tkt_string);
173 DECL_FUNC_PTR(krb_get_tf_realm);
174 DECL_FUNC_PTR(krb_mk_req);
177 DECL_FUNC_PTR(com_err);
178 DECL_FUNC_PTR(error_message);
181 DECL_FUNC_PTR(profile_init);
182 DECL_FUNC_PTR(profile_release);
183 DECL_FUNC_PTR(profile_get_subsection_names);
184 DECL_FUNC_PTR(profile_free_list);
185 DECL_FUNC_PTR(profile_get_string);
186 DECL_FUNC_PTR(profile_release_string);
189 DECL_FUNC_PTR(OpenSCManagerA);
190 DECL_FUNC_PTR(OpenServiceA);
191 DECL_FUNC_PTR(QueryServiceStatus);
192 DECL_FUNC_PTR(CloseServiceHandle);
194 DECL_FUNC_PTR(LsaNtStatusToWinError);
195 #endif /* USE_MS2MIT */
199 DECL_FUNC_PTR(LsaConnectUntrusted);
200 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
201 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
202 DECL_FUNC_PTR(LsaFreeReturnBuffer);
203 DECL_FUNC_PTR(LsaGetLogonSessionData);
204 #endif /* USE_MS2MIT */
207 FUNC_INFO ccapi_fi[] = {
208 MAKE_FUNC_INFO(cc_initialize),
209 MAKE_FUNC_INFO(cc_shutdown),
210 MAKE_FUNC_INFO(cc_get_NC_info),
211 MAKE_FUNC_INFO(cc_free_NC_info),
215 FUNC_INFO leash_fi[] = {
216 MAKE_FUNC_INFO(Leash_get_default_lifetime),
217 MAKE_FUNC_INFO(Leash_get_default_renew_till),
218 MAKE_FUNC_INFO(Leash_get_default_forwardable),
219 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
220 MAKE_FUNC_INFO(Leash_get_default_proxiable),
221 MAKE_FUNC_INFO(Leash_get_default_publicip),
222 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
223 MAKE_FUNC_INFO(Leash_get_default_life_min),
224 MAKE_FUNC_INFO(Leash_get_default_life_max),
225 MAKE_FUNC_INFO(Leash_get_default_renew_min),
226 MAKE_FUNC_INFO(Leash_get_default_renew_max),
227 MAKE_FUNC_INFO(Leash_get_default_renewable),
231 FUNC_INFO k5_fi[] = {
232 MAKE_FUNC_INFO(krb5_change_password),
233 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
234 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
235 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
236 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
237 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
238 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
239 MAKE_FUNC_INFO(krb5_get_init_creds_password),
240 MAKE_FUNC_INFO(krb5_build_principal_ext),
241 MAKE_FUNC_INFO(krb5_cc_get_name),
242 MAKE_FUNC_INFO(krb5_cc_resolve),
243 MAKE_FUNC_INFO(krb5_cc_default),
244 MAKE_FUNC_INFO(krb5_cc_default_name),
245 MAKE_FUNC_INFO(krb5_cc_set_default_name),
246 MAKE_FUNC_INFO(krb5_cc_initialize),
247 MAKE_FUNC_INFO(krb5_cc_destroy),
248 MAKE_FUNC_INFO(krb5_cc_close),
249 MAKE_FUNC_INFO(krb5_cc_copy_creds),
250 MAKE_FUNC_INFO(krb5_cc_store_cred),
251 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
252 MAKE_FUNC_INFO(krb5_cc_get_principal),
253 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
254 MAKE_FUNC_INFO(krb5_cc_next_cred),
255 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
256 MAKE_FUNC_INFO(krb5_cc_remove_cred),
257 MAKE_FUNC_INFO(krb5_cc_set_flags),
258 MAKE_FUNC_INFO(krb5_cc_get_type),
259 MAKE_FUNC_INFO(krb5_free_context),
260 MAKE_FUNC_INFO(krb5_free_cred_contents),
261 MAKE_FUNC_INFO(krb5_free_principal),
262 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
263 MAKE_FUNC_INFO(krb5_init_context),
264 MAKE_FUNC_INFO(krb5_parse_name),
265 MAKE_FUNC_INFO(krb5_timeofday),
266 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
267 MAKE_FUNC_INFO(krb5_unparse_name),
268 MAKE_FUNC_INFO(krb5_get_credentials),
269 MAKE_FUNC_INFO(krb5_mk_req),
270 MAKE_FUNC_INFO(krb5_sname_to_principal),
271 MAKE_FUNC_INFO(krb5_get_credentials_renew),
272 MAKE_FUNC_INFO(krb5_free_data),
273 MAKE_FUNC_INFO(krb5_free_data_contents),
274 MAKE_FUNC_INFO(krb5_free_unparsed_name),
275 MAKE_FUNC_INFO(krb5_os_localaddr),
276 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
277 MAKE_FUNC_INFO(krb5_copy_data),
278 MAKE_FUNC_INFO(krb5_free_creds),
279 MAKE_FUNC_INFO(krb5_build_principal),
280 MAKE_FUNC_INFO(krb5_get_renewed_creds),
281 MAKE_FUNC_INFO(krb5_free_addresses),
282 MAKE_FUNC_INFO(krb5_get_default_config_files),
283 MAKE_FUNC_INFO(krb5_free_config_files),
284 MAKE_FUNC_INFO(krb5_get_default_realm),
285 MAKE_FUNC_INFO(krb5_free_ticket),
286 MAKE_FUNC_INFO(krb5_decode_ticket),
287 MAKE_FUNC_INFO(krb5_get_host_realm),
288 MAKE_FUNC_INFO(krb5_free_host_realm),
289 MAKE_FUNC_INFO(krb5_free_addresses),
290 MAKE_FUNC_INFO(krb5_c_random_make_octets),
295 FUNC_INFO k4_fi[] = {
296 MAKE_FUNC_INFO(krb_get_cred),
297 MAKE_FUNC_INFO(krb_get_tf_realm),
298 MAKE_FUNC_INFO(krb_mk_req),
299 MAKE_FUNC_INFO(tkt_string),
304 FUNC_INFO k524_fi[] = {
305 MAKE_FUNC_INFO(krb524_init_ets),
306 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
310 FUNC_INFO profile_fi[] = {
311 MAKE_FUNC_INFO(profile_init),
312 MAKE_FUNC_INFO(profile_release),
313 MAKE_FUNC_INFO(profile_get_subsection_names),
314 MAKE_FUNC_INFO(profile_free_list),
315 MAKE_FUNC_INFO(profile_get_string),
316 MAKE_FUNC_INFO(profile_release_string),
320 FUNC_INFO ce_fi[] = {
321 MAKE_FUNC_INFO(com_err),
322 MAKE_FUNC_INFO(error_message),
326 FUNC_INFO service_fi[] = {
327 MAKE_FUNC_INFO(OpenSCManagerA),
328 MAKE_FUNC_INFO(OpenServiceA),
329 MAKE_FUNC_INFO(QueryServiceStatus),
330 MAKE_FUNC_INFO(CloseServiceHandle),
332 MAKE_FUNC_INFO(LsaNtStatusToWinError),
333 #endif /* USE_MS2MIT */
338 FUNC_INFO lsa_fi[] = {
339 MAKE_FUNC_INFO(LsaConnectUntrusted),
340 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
341 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
342 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
343 MAKE_FUNC_INFO(LsaGetLogonSessionData),
346 #endif /* USE_MS2MIT */
348 /* Static Prototypes */
349 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
350 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
351 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
352 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
353 void *data, const char *name, const char *banner, int num_prompts,
354 krb5_prompt prompts[]);
357 /* Static Declarations */
358 static int inited = 0;
359 static int mid_cnt = 0;
360 static struct textField * mid_tb = NULL;
361 static HINSTANCE hKrb5 = 0;
363 static HINSTANCE hKrb4 = 0;
364 #endif /* USE_KRB4 */
365 static HINSTANCE hKrb524 = 0;
367 static HINSTANCE hSecur32 = 0;
368 #endif /* USE_MS2MIT */
369 static HINSTANCE hAdvApi32 = 0;
370 static HINSTANCE hComErr = 0;
371 static HINSTANCE hService = 0;
372 static HINSTANCE hProfile = 0;
373 static HINSTANCE hLeash = 0;
374 static HINSTANCE hCCAPI = 0;
375 static struct principal_ccache_data * princ_cc_data = NULL;
376 static struct cell_principal_map * cell_princ_map = NULL;
381 static int inited = 0;
384 char mutexName[MAX_PATH];
385 HANDLE hMutex = NULL;
387 sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
389 hMutex = CreateMutex( NULL, TRUE, mutexName );
390 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
391 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
397 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
399 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
400 #endif /* USE_KRB4 */
401 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
402 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
404 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
405 #endif /* USE_MS2MIT */
406 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
407 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
408 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
409 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
411 if ( KFW_is_available() ) {
412 char rootcell[MAXCELLCHARS+1];
414 KFW_import_windows_lsa();
415 #endif /* USE_MS2MIT */
416 KFW_import_ccache_data();
417 KFW_AFS_renew_expiring_tokens();
419 /* WIN32 NOTE: no way to get max chars */
420 if (!cm_GetRootCellName(rootcell))
421 KFW_AFS_renew_token_for_cell(rootcell);
424 ReleaseMutex(hMutex);
437 #endif /* USE_KRB4 */
439 FreeLibrary(hProfile);
441 FreeLibrary(hComErr);
443 FreeLibrary(hService);
446 FreeLibrary(hSecur32);
447 #endif /* USE_MS2MIT */
449 FreeLibrary(hKrb524);
456 static char OpenAFSConfigKeyName[] = "SOFTWARE\\OpenAFS\\Client";
465 code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
466 0, KEY_QUERY_VALUE, &parmKey);
467 if (code == ERROR_SUCCESS) {
468 len = sizeof(use524);
469 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
470 (BYTE *) &use524, &len);
471 RegCloseKey(parmKey);
473 if (code != ERROR_SUCCESS) {
474 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
475 0, KEY_QUERY_VALUE, &parmKey);
476 if (code == ERROR_SUCCESS) {
477 len = sizeof(use524);
478 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
479 (BYTE *) &use524, &len);
480 RegCloseKey (parmKey);
487 KFW_is_available(void)
493 code = RegOpenKeyEx(HKEY_CURRENT_USER, OpenAFSConfigKeyName,
494 0, KEY_QUERY_VALUE, &parmKey);
495 if (code == ERROR_SUCCESS) {
496 len = sizeof(enableKFW);
497 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
498 (BYTE *) &enableKFW, &len);
499 RegCloseKey (parmKey);
502 if (code != ERROR_SUCCESS) {
503 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, OpenAFSConfigKeyName,
504 0, KEY_QUERY_VALUE, &parmKey);
505 if (code == ERROR_SUCCESS) {
506 len = sizeof(enableKFW);
507 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
508 (BYTE *) &enableKFW, &len);
509 RegCloseKey (parmKey);
517 if ( hKrb5 && hComErr && hService &&
520 #endif /* USE_MS2MIT */
522 hProfile && hLeash && hCCAPI )
528 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
529 int FreeContextFlag, krb5_context * ctx,
534 int krb5Error = ((int)(rc & 255));
546 errText = perror_message(rc);
547 _snprintf(message, sizeof(message),
548 "%s\n(Kerberos error %ld)\n\n%s failed",
553 if ( IsDebuggerPresent() )
554 OutputDebugString(message);
556 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
559 if (FreeContextFlag == 1)
561 if (ctx && *ctx != NULL)
563 if (cache && *cache != NULL) {
564 pkrb5_cc_close(*ctx, *cache);
568 pkrb5_free_context(*ctx);
577 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
579 struct principal_ccache_data * next = princ_cc_data;
580 krb5_principal principal = 0;
582 const char * ccname = NULL;
583 krb5_error_code code = 0;
584 krb5_error_code cc_code = 0;
590 if (ctx == 0 || cc == 0)
593 code = pkrb5_cc_get_principal(ctx, cc, &principal);
596 code = pkrb5_unparse_name(ctx, principal, &pname);
597 if ( code ) goto cleanup;
599 ccname = pkrb5_cc_get_name(ctx, cc);
600 if (!ccname) goto cleanup;
602 // Search the existing list to see if we have a match
604 for ( ; next ; next = next->next ) {
605 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccname) )
610 // If not, match add a new node to the beginning of the list and assign init it
612 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
613 next->next = princ_cc_data;
614 princ_cc_data = next;
615 next->principal = _strdup(pname);
616 next->ccache_name = _strdup(ccname);
617 next->from_lsa = lsa;
619 next->expiration_time = 0;
623 flags = 0; // turn off OPENCLOSE mode
624 code = pkrb5_cc_set_flags(ctx, cc, flags);
625 if ( code ) goto cleanup;
627 code = pkrb5_timeofday(ctx, &now);
629 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
631 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
632 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
634 // we found the ticket we are looking for
635 // check validity of timestamp
636 // We add a 5 minutes fudge factor to compensate for potential
637 // clock skew errors between the KDC and client OS
639 valid = ((creds.times.starttime > 0) &&
640 now >= (creds.times.starttime - 300) &&
641 now < (creds.times.endtime + 300) &&
642 !(creds.ticket_flags & TKT_FLG_INVALID));
644 if ( next->from_lsa) {
646 next->expiration_time = creds.times.endtime;
648 } else if ( valid ) {
650 next->expiration_time = creds.times.endtime;
651 next->renew = (creds.times.renew_till > creds.times.endtime) &&
652 (creds.ticket_flags & TKT_FLG_RENEWABLE);
655 next->expiration_time = 0;
659 pkrb5_free_cred_contents(ctx, &creds);
660 cc_code = KRB5_CC_END;
663 pkrb5_free_cred_contents(ctx, &creds);
666 if (cc_code == KRB5_CC_END) {
667 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
668 if (code) goto cleanup;
672 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
673 code = pkrb5_cc_set_flags(ctx, cc, flags);
676 pkrb5_free_unparsed_name(ctx,pname);
678 pkrb5_free_principal(ctx,principal);
682 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
684 struct principal_ccache_data * next = princ_cc_data;
685 char * response = NULL;
687 if ( !principal || !ccache )
691 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
693 // we always want to prefer the MS Kerberos LSA cache or
694 // the cache afscreds created specifically for the principal
695 // if the current entry is either one, drop the previous find
696 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
699 response = _strdup(next->ccache_name);
700 // MS Kerberos LSA is our best option so use it and quit
701 if ( next->from_lsa )
715 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
717 struct principal_ccache_data ** next = &princ_cc_data;
719 if ( !pname && !ccname )
723 if ( !strcmp((*next)->principal,pname) ||
724 !strcmp((*next)->ccache_name,ccname) ) {
726 free((*next)->principal);
727 free((*next)->ccache_name);
729 (*next) = (*next)->next;
736 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
738 struct cell_principal_map * next = cell_princ_map;
740 // Search the existing list to see if we have a match
742 for ( ; next ; next = next->next ) {
743 if ( !strcmp(next->cell, cell) ) {
744 if ( !strcmp(next->principal,pname) ) {
745 next->active = active;
748 // OpenAFS currently has a restriction of one active token per cell
749 // Therefore, whenever we update the table with a new active cell we
750 // must mark all of the other principal to cell entries as inactive.
758 // If not, match add a new node to the beginning of the list and assign init it
760 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
761 next->next = cell_princ_map;
762 cell_princ_map = next;
763 next->principal = _strdup(pname);
764 next->cell = _strdup(cell);
765 next->active = active;
770 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
772 struct cell_principal_map ** next = &cell_princ_map;
774 if ( !pname && !cell )
778 if ( !strcmp((*next)->principal,pname) ||
779 !strcmp((*next)->cell,cell) ) {
781 free((*next)->principal);
784 (*next) = (*next)->next;
790 // Returns (if possible) a principal which has been known in
791 // the past to have been used to obtain tokens for the specified
793 // TODO: Attempt to return one which has not yet expired by checking
794 // the principal/ccache data
796 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
798 struct cell_principal_map * next_map = cell_princ_map;
799 const char * princ = NULL;
806 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
809 next_map = next_map->next;
812 if ( !principals || !count )
815 *principals = (char **) malloc(sizeof(char *) * count);
816 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
818 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
819 (*principals)[i++] = _strdup(next_map->principal);
826 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
829 struct cell_principal_map * next_map = cell_princ_map;
830 const char * princ = NULL;
836 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
839 next_map = next_map->next;
845 *cells = (char **) malloc(sizeof(char *) * count);
846 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
848 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
849 (*cells)[i++] = _strdup(next_map->cell);
855 /* Given a principal return an existing ccache or create one and return */
857 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
862 krb5_error_code code;
864 if (!pkrb5_init_context)
870 code = pkrb5_init_context(&ctx);
871 if (code) goto cleanup;
875 code = pkrb5_unparse_name(ctx, principal, &pname);
876 if (code) goto cleanup;
878 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
879 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
880 ccname = (char *)malloc(strlen(pname) + 5);
881 sprintf(ccname,"API:%s",pname);
883 code = pkrb5_cc_resolve(ctx, ccname, cc);
885 code = pkrb5_cc_default(ctx, cc);
886 if (code) goto cleanup;
893 pkrb5_free_unparsed_name(ctx,pname);
894 if (ctx && (ctx != alt_ctx))
895 pkrb5_free_context(ctx);
900 // Import Microsoft Credentials into a new MIT ccache
902 KFW_import_windows_lsa(void)
904 krb5_context ctx = 0;
906 krb5_principal princ = 0;
908 krb5_data * princ_realm;
909 krb5_error_code code;
910 char cell[128]="", realm[128]="", *def_realm = 0;
914 if (!pkrb5_init_context)
918 if ( !MSLSA_IsKerberosLogon() )
922 code = pkrb5_init_context(&ctx);
923 if (code) goto cleanup;
925 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
926 if (code) goto cleanup;
928 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
930 code = pkrb5_cc_get_principal(ctx, cc, &princ);
931 if ( code ) goto cleanup;
933 dwMsLsaImport = pLeash_get_default_mslsa_import();
934 switch ( dwMsLsaImport ) {
935 case 0: /* do not import */
937 case 1: /* always import */
939 case 2: { /* matching realm */
940 char ms_realm[128] = "", *r;
943 for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) {
944 *r = krb5_princ_realm(ctx, princ)->data[i];
948 if (code = pkrb5_get_default_realm(ctx, &def_realm))
951 if (strcmp(def_realm, ms_realm))
959 code = pkrb5_unparse_name(ctx,princ,&pname);
960 if ( code ) goto cleanup;
962 princ_realm = krb5_princ_realm(ctx, princ);
963 for ( i=0; i<princ_realm->length; i++ ) {
964 realm[i] = princ_realm->data[i];
965 cell[i] = tolower(princ_realm->data[i]);
970 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
971 if ( IsDebuggerPresent() ) {
973 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
974 OutputDebugString(message);
976 if ( code ) goto cleanup;
978 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
982 pkrb5_free_unparsed_name(ctx,pname);
984 pkrb5_free_principal(ctx,princ);
986 pkrb5_free_default_realm(ctx, def_realm);
988 pkrb5_cc_close(ctx,cc);
990 pkrb5_free_context(ctx);
992 #endif /* USE_MS2MIT */
994 // If there are existing MIT credentials, copy them to a new
995 // ccache named after the principal
997 // Enumerate all existing MIT ccaches and construct entries
998 // in the principal_ccache table
1000 // Enumerate all existing AFS Tokens and construct entries
1001 // in the cell_principal table
1003 KFW_import_ccache_data(void)
1005 krb5_context ctx = 0;
1007 krb5_principal principal = 0;
1009 krb5_error_code code;
1010 krb5_error_code cc_code;
1013 struct _infoNC ** pNCi = NULL;
1016 if ( !pcc_initialize )
1019 if ( IsDebuggerPresent() )
1020 OutputDebugString("KFW_import_ccache_data()\n");
1022 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1023 if (code) goto cleanup;
1025 code = pcc_get_NC_info(cc_ctx, &pNCi);
1026 if (code) goto cleanup;
1028 code = pkrb5_init_context(&ctx);
1029 if (code) goto cleanup;
1031 for ( i=0; pNCi[i]; i++ ) {
1032 if ( pNCi[i]->vers != CC_CRED_V5 )
1034 if ( IsDebuggerPresent() ) {
1035 OutputDebugString("Principal: ");
1036 OutputDebugString(pNCi[i]->principal);
1037 OutputDebugString(" in ccache ");
1038 OutputDebugString(pNCi[i]->name);
1039 OutputDebugString("\n");
1041 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1042 && strcmp(pNCi[i]->name,LSA_CCNAME)
1045 for ( j=0; pNCi[j]; j++ ) {
1046 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1052 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1053 if (code) goto loop_cleanup;
1056 krb5_ccache oldcc = 0;
1058 if ( IsDebuggerPresent() )
1059 OutputDebugString("copying ccache data to new ccache\n");
1061 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1062 if (code) goto loop_cleanup;
1063 code = pkrb5_cc_initialize(ctx, cc, principal);
1064 if (code) goto loop_cleanup;
1066 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1067 if (code) goto loop_cleanup;
1068 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1070 code = pkrb5_cc_close(ctx,cc);
1072 code = pkrb5_cc_close(ctx,oldcc);
1074 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1077 code = pkrb5_cc_close(ctx,oldcc);
1080 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1081 if (code) goto loop_cleanup;
1084 flags = 0; // turn off OPENCLOSE mode
1085 code = pkrb5_cc_set_flags(ctx, cc, flags);
1086 if ( code ) goto cleanup;
1088 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1090 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1092 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1093 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1094 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1095 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1096 if ( sname && cell && !strcmp("afs",sname->data) ) {
1097 struct ktc_principal aserver;
1098 struct ktc_principal aclient;
1099 struct ktc_token atoken;
1102 if ( IsDebuggerPresent() ) {
1103 OutputDebugString("Found AFS ticket: ");
1104 OutputDebugString(sname->data);
1106 OutputDebugString("/");
1107 OutputDebugString(cell->data);
1109 OutputDebugString("@");
1110 OutputDebugString(realm->data);
1111 OutputDebugString("\n");
1114 memset(&aserver, '\0', sizeof(aserver));
1115 strcpy(aserver.name, sname->data);
1116 strcpy(aserver.cell, cell->data);
1118 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1120 // Found a token in AFS Client Server which matches
1121 char pname[128], *p, *q;
1122 for ( p=pname, q=aclient.name; *q; p++, q++)
1124 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1128 if ( IsDebuggerPresent() ) {
1129 OutputDebugString("Found AFS token: ");
1130 OutputDebugString(pname);
1131 OutputDebugString("\n");
1134 if ( strcmp(pname,pNCi[i]->principal) )
1136 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1138 // Attempt to import it
1139 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1141 if ( IsDebuggerPresent() ) {
1142 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1145 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data, pLeash_get_default_lifetime(),NULL);
1146 if ( IsDebuggerPresent() ) {
1148 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1149 OutputDebugString(message);
1152 } else if ( IsDebuggerPresent() ) {
1153 OutputDebugString("Found ticket: ");
1154 OutputDebugString(sname->data);
1155 if ( cell && cell->data ) {
1156 OutputDebugString("/");
1157 OutputDebugString(cell->data);
1159 OutputDebugString("@");
1160 OutputDebugString(realm->data);
1161 OutputDebugString("\n");
1163 pkrb5_free_cred_contents(ctx, &creds);
1166 if (cc_code == KRB5_CC_END) {
1167 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1168 if (cc_code) goto loop_cleanup;
1172 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1173 code = pkrb5_cc_set_flags(ctx, cc, flags);
1175 pkrb5_cc_close(ctx,cc);
1179 pkrb5_free_principal(ctx,principal);
1186 pkrb5_free_context(ctx);
1188 pcc_free_NC_info(cc_ctx, &pNCi);
1190 pcc_shutdown(&cc_ctx);
1195 KFW_AFS_get_cred( char * username,
1202 krb5_context ctx = 0;
1204 char * realm = 0, * userrealm = 0;
1205 krb5_principal principal = 0;
1207 krb5_error_code code;
1208 char local_cell[MAXCELLCHARS+1];
1209 char **cells = NULL;
1211 struct afsconf_cell cellconfig;
1215 if (!pkrb5_init_context)
1218 if ( IsDebuggerPresent() ) {
1219 OutputDebugString("KFW_AFS_get_cred for token ");
1220 OutputDebugString(username);
1221 OutputDebugString(" in cell ");
1222 OutputDebugString(cell);
1223 OutputDebugString("\n");
1226 code = pkrb5_init_context(&ctx);
1227 if ( code ) goto cleanup;
1229 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1230 if ( code ) goto cleanup;
1232 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1233 userrealm = strchr(username,'@');
1235 pname = strdup(username);
1236 userrealm = strchr(pname, '@');
1239 /* handle kerberos iv notation */
1240 while ( dot = strchr(pname,'.') ) {
1245 pname = malloc(strlen(username) + strlen(realm) + 2);
1247 strcpy(pname, username);
1249 /* handle kerberos iv notation */
1250 while ( dot = strchr(pname,'.') ) {
1255 strcat(pname,realm);
1258 if ( IsDebuggerPresent() ) {
1259 OutputDebugString("Realm: ");
1260 OutputDebugString(realm);
1261 OutputDebugString("\n");
1264 code = pkrb5_parse_name(ctx, pname, &principal);
1265 if ( code ) goto cleanup;
1267 code = KFW_get_ccache(ctx, principal, &cc);
1268 if ( code ) goto cleanup;
1270 if ( lifetime == 0 )
1271 lifetime = pLeash_get_default_lifetime();
1273 if ( password && password[0] ) {
1274 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1278 pLeash_get_default_forwardable(),
1279 pLeash_get_default_proxiable(),
1280 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1281 pLeash_get_default_noaddresses(),
1282 pLeash_get_default_publicip());
1283 if ( IsDebuggerPresent() ) {
1285 sprintf(message,"KFW_kinit() returns: %d\n",code);
1286 OutputDebugString(message);
1288 if ( code ) goto cleanup;
1290 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1293 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime,smbname);
1294 if ( IsDebuggerPresent() ) {
1296 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1297 OutputDebugString(message);
1299 if ( code ) goto cleanup;
1301 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1303 // Attempt to obtain new tokens for other cells supported by the same
1305 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1306 if ( cell_count > 1 ) {
1307 while ( cell_count-- ) {
1308 if ( strcmp(cells[cell_count],cell) ) {
1309 if ( IsDebuggerPresent() ) {
1311 sprintf(message,"found another cell for the same principal: %s\n",cell);
1312 OutputDebugString(message);
1314 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1315 if ( code ) continue;
1317 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1318 if ( IsDebuggerPresent() ) {
1319 OutputDebugString("Realm: ");
1320 OutputDebugString(realm);
1321 OutputDebugString("\n");
1324 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime,smbname);
1325 if ( IsDebuggerPresent() ) {
1327 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1328 OutputDebugString(message);
1331 free(cells[cell_count]);
1334 } else if ( cell_count == 1 ) {
1343 pkrb5_cc_close(ctx, cc);
1345 if ( code && reasonP ) {
1346 *reasonP = (char *)perror_message(code);
1352 KFW_AFS_destroy_tickets_for_cell(char * cell)
1354 krb5_context ctx = 0;
1355 krb5_error_code code;
1357 char ** principals = NULL;
1359 if (!pkrb5_init_context)
1362 if ( IsDebuggerPresent() ) {
1363 OutputDebugString("KFW_AFS_destroy_ticets_for_cell: ");
1364 OutputDebugString(cell);
1365 OutputDebugString("\n");
1368 code = pkrb5_init_context(&ctx);
1371 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1373 krb5_principal princ = 0;
1377 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1378 if ( cell_count > 1 ) {
1379 // TODO - What we really should do here is verify whether or not any of the
1380 // other cells which use this principal to obtain its credentials actually
1381 // have valid tokens or not. If they are currently using these credentials
1382 // we will skip them. For the time being we assume that if there is an active
1383 // map in the table that they are actively being used.
1387 code = pkrb5_parse_name(ctx, principals[count], &princ);
1388 if (code) goto loop_cleanup;
1390 code = KFW_get_ccache(ctx, princ, &cc);
1391 if (code) goto loop_cleanup;
1393 code = pkrb5_cc_destroy(ctx, cc);
1398 pkrb5_cc_close(ctx, cc);
1402 pkrb5_free_principal(ctx, princ);
1406 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1407 free(principals[count]);
1411 pkrb5_free_context(ctx);
1416 KFW_AFS_renew_expiring_tokens(void)
1418 krb5_error_code code = 0;
1419 krb5_context ctx = 0;
1422 struct principal_ccache_data * pcc_next = princ_cc_data;
1425 const char * realm = NULL;
1426 char local_cell[MAXCELLCHARS+1]="";
1427 struct afsconf_cell cellconfig;
1429 if (!pkrb5_init_context)
1432 if ( pcc_next == NULL ) // nothing to do
1435 if ( IsDebuggerPresent() ) {
1436 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1439 code = pkrb5_init_context(&ctx);
1440 if (code) goto cleanup;
1442 code = pkrb5_timeofday(ctx, &now);
1443 if (code) goto cleanup;
1445 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1446 if ( pcc_next->expired )
1449 if ( now >= (pcc_next->expiration_time) ) {
1450 if ( !pcc_next->from_lsa ) {
1451 pcc_next->expired = 1;
1456 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1457 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1460 code = KFW_renew(ctx,cc);
1462 if ( code && pcc_next->from_lsa)
1464 #endif /* USE_MS2MIT */
1467 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1468 if (code) goto loop_cleanup;
1470 // Attempt to obtain new tokens for other cells supported by the same
1472 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1473 if ( cell_count > 0 ) {
1474 while ( cell_count-- ) {
1475 if ( IsDebuggerPresent() ) {
1476 OutputDebugString("Cell: ");
1477 OutputDebugString(cells[cell_count]);
1478 OutputDebugString("\n");
1480 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1481 if ( code ) continue;
1482 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1483 if ( IsDebuggerPresent() ) {
1484 OutputDebugString("Realm: ");
1485 OutputDebugString(realm);
1486 OutputDebugString("\n");
1488 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, pLeash_get_default_lifetime(),NULL);
1489 if ( IsDebuggerPresent() ) {
1491 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1492 OutputDebugString(message);
1494 free(cells[cell_count]);
1502 pkrb5_cc_close(ctx,cc);
1509 pkrb5_cc_close(ctx,cc);
1511 pkrb5_free_context(ctx);
1518 KFW_AFS_renew_token_for_cell(char * cell)
1520 krb5_error_code code = 0;
1521 krb5_context ctx = 0;
1523 char ** principals = NULL;
1525 if (!pkrb5_init_context)
1528 if ( IsDebuggerPresent() ) {
1529 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1530 OutputDebugString(cell);
1531 OutputDebugString("\n");
1534 code = pkrb5_init_context(&ctx);
1535 if (code) goto cleanup;
1537 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1539 // We know we must have a credential somewhere since we are
1540 // trying to renew a token
1542 KFW_import_ccache_data();
1543 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1546 krb5_principal princ = 0;
1547 krb5_principal service = 0;
1549 krb5_creds mcreds, creds;
1550 #endif /* COMMENT */
1552 const char * realm = NULL;
1553 struct afsconf_cell cellconfig;
1554 char local_cell[MAXCELLCHARS+1];
1557 code = pkrb5_parse_name(ctx, principals[count], &princ);
1558 if (code) goto loop_cleanup;
1560 code = KFW_get_ccache(ctx, princ, &cc);
1561 if (code) goto loop_cleanup;
1563 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1564 if ( code ) goto loop_cleanup;
1566 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1567 if ( IsDebuggerPresent() ) {
1568 OutputDebugString("Realm: ");
1569 OutputDebugString(realm);
1570 OutputDebugString("\n");
1574 /* krb5_cc_remove_cred() is not implemented
1577 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1578 realm, "afs", cell, NULL);
1580 memset(&mcreds, 0, sizeof(krb5_creds));
1581 mcreds.client = princ;
1582 mcreds.server = service;
1584 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1586 if ( IsDebuggerPresent() ) {
1587 char * cname, *sname;
1588 pkrb5_unparse_name(ctx, creds.client, &cname);
1589 pkrb5_unparse_name(ctx, creds.server, &sname);
1590 OutputDebugString("Removing credential for client \"");
1591 OutputDebugString(cname);
1592 OutputDebugString("\" and service \"");
1593 OutputDebugString(sname);
1594 OutputDebugString("\"\n");
1595 pkrb5_free_unparsed_name(ctx,cname);
1596 pkrb5_free_unparsed_name(ctx,sname);
1599 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1600 pkrb5_free_principal(ctx, creds.client);
1601 pkrb5_free_principal(ctx, creds.server);
1604 #endif /* COMMENT */
1606 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, pLeash_get_default_lifetime(),NULL);
1607 if ( IsDebuggerPresent() ) {
1609 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1610 OutputDebugString(message);
1615 pkrb5_cc_close(ctx, cc);
1619 pkrb5_free_principal(ctx, princ);
1623 pkrb5_free_principal(ctx, service);
1627 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1628 free(principals[count]);
1632 code = -1; // we did not renew the tokens
1635 pkrb5_free_context(ctx);
1636 return (code ? FALSE : TRUE);
1641 KFW_AFS_renew_tokens_for_all_cells(void)
1643 struct cell_principal_map * next = cell_princ_map;
1645 if ( IsDebuggerPresent() )
1646 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1651 for ( ; next ; next = next->next ) {
1653 KFW_AFS_renew_token_for_cell(next->cell);
1659 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1661 krb5_error_code code = 0;
1662 krb5_context ctx = 0;
1664 krb5_principal me = 0;
1665 krb5_principal server = 0;
1666 krb5_creds my_creds;
1667 krb5_data *realm = 0;
1669 if (!pkrb5_init_context)
1672 memset(&my_creds, 0, sizeof(krb5_creds));
1677 code = pkrb5_init_context(&ctx);
1678 if (code) goto cleanup;
1684 code = pkrb5_cc_default(ctx, &cc);
1685 if (code) goto cleanup;
1688 code = pkrb5_cc_get_principal(ctx, cc, &me);
1689 if (code) goto cleanup;
1691 realm = krb5_princ_realm(ctx, me);
1693 code = pkrb5_build_principal_ext(ctx, &server,
1694 realm->length,realm->data,
1695 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1696 realm->length,realm->data,
1701 if ( IsDebuggerPresent() ) {
1702 char * cname, *sname;
1703 pkrb5_unparse_name(ctx, me, &cname);
1704 pkrb5_unparse_name(ctx, server, &sname);
1705 OutputDebugString("Renewing credential for client \"");
1706 OutputDebugString(cname);
1707 OutputDebugString("\" and service \"");
1708 OutputDebugString(sname);
1709 OutputDebugString("\"\n");
1710 pkrb5_free_unparsed_name(ctx,cname);
1711 pkrb5_free_unparsed_name(ctx,sname);
1714 my_creds.client = me;
1715 my_creds.server = server;
1717 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1719 if ( IsDebuggerPresent() ) {
1721 sprintf(message,"krb5_get_renewed_creds() failed: %d\n",code);
1722 OutputDebugString(message);
1727 code = pkrb5_cc_initialize(ctx, cc, me);
1729 if ( IsDebuggerPresent() ) {
1731 sprintf(message,"krb5_cc_initialize() failed: %d\n",code);
1732 OutputDebugString(message);
1737 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1739 if ( IsDebuggerPresent() ) {
1741 sprintf(message,"krb5_cc_store_cred() failed: %d\n",code);
1742 OutputDebugString(message);
1748 if (my_creds.client == me)
1749 my_creds.client = 0;
1750 if (my_creds.server == server)
1751 my_creds.server = 0;
1752 pkrb5_free_cred_contents(ctx, &my_creds);
1754 pkrb5_free_principal(ctx, me);
1756 pkrb5_free_principal(ctx, server);
1757 if (cc && (cc != alt_cc))
1758 pkrb5_cc_close(ctx, cc);
1759 if (ctx && (ctx != alt_ctx))
1760 pkrb5_free_context(ctx);
1765 KFW_kinit( krb5_context alt_ctx,
1768 char *principal_name,
1770 krb5_deltat lifetime,
1773 krb5_deltat renew_life,
1778 krb5_error_code code = 0;
1779 krb5_context ctx = 0;
1781 krb5_principal me = 0;
1783 krb5_creds my_creds;
1784 krb5_get_init_creds_opt options;
1785 krb5_address ** addrs = NULL;
1786 int i = 0, addr_count = 0;
1788 if (!pkrb5_init_context)
1791 pkrb5_get_init_creds_opt_init(&options);
1792 memset(&my_creds, 0, sizeof(my_creds));
1800 code = pkrb5_init_context(&ctx);
1801 if (code) goto cleanup;
1807 code = pkrb5_cc_default(ctx, &cc);
1808 if (code) goto cleanup;
1811 code = pkrb5_parse_name(ctx, principal_name, &me);
1815 code = pkrb5_unparse_name(ctx, me, &name);
1820 lifetime = pLeash_get_default_lifetime();
1828 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
1829 pkrb5_get_init_creds_opt_set_forwardable(&options,
1830 forwardable ? 1 : 0);
1831 pkrb5_get_init_creds_opt_set_proxiable(&options,
1833 pkrb5_get_init_creds_opt_set_renew_life(&options,
1836 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
1840 // we are going to add the public IP address specified by the user
1841 // to the list provided by the operating system
1842 krb5_address ** local_addrs=NULL;
1845 pkrb5_os_localaddr(ctx, &local_addrs);
1846 while ( local_addrs[i++] );
1849 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
1851 pkrb5_free_addresses(ctx, local_addrs);
1854 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
1856 while ( local_addrs[i] ) {
1857 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
1858 if (addrs[i] == NULL) {
1859 pkrb5_free_addresses(ctx, local_addrs);
1863 addrs[i]->magic = local_addrs[i]->magic;
1864 addrs[i]->addrtype = local_addrs[i]->addrtype;
1865 addrs[i]->length = local_addrs[i]->length;
1866 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
1867 if (!addrs[i]->contents) {
1868 pkrb5_free_addresses(ctx, local_addrs);
1872 memcpy(addrs[i]->contents,local_addrs[i]->contents,
1873 local_addrs[i]->length); /* safe */
1876 pkrb5_free_addresses(ctx, local_addrs);
1878 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
1879 if (addrs[i] == NULL)
1882 addrs[i]->magic = KV5M_ADDRESS;
1883 addrs[i]->addrtype = AF_INET;
1884 addrs[i]->length = 4;
1885 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
1886 if (!addrs[i]->contents)
1889 netIPAddr = htonl(publicIP);
1890 memcpy(addrs[i]->contents,&netIPAddr,4);
1892 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
1897 code = pkrb5_get_init_creds_password(ctx,
1900 password, // password
1901 KRB5_prompter, // prompter
1902 hParent, // prompter data
1909 code = pkrb5_cc_initialize(ctx, cc, me);
1913 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1919 for ( i=0;i<addr_count;i++ ) {
1921 if ( addrs[i]->contents )
1922 free(addrs[i]->contents);
1927 if (my_creds.client == me)
1928 my_creds.client = 0;
1929 pkrb5_free_cred_contents(ctx, &my_creds);
1931 pkrb5_free_unparsed_name(ctx, name);
1933 pkrb5_free_principal(ctx, me);
1934 if (cc && (cc != alt_cc))
1935 pkrb5_cc_close(ctx, cc);
1936 if (ctx && (ctx != alt_ctx))
1937 pkrb5_free_context(ctx);
1943 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
1947 krb5_error_code code;
1949 if (!pkrb5_init_context)
1958 code = pkrb5_init_context(&ctx);
1959 if (code) goto cleanup;
1965 code = pkrb5_cc_default(ctx, &cc);
1966 if (code) goto cleanup;
1969 code = pkrb5_cc_destroy(ctx, cc);
1970 if ( !code ) cc = 0;
1973 if (cc && (cc != alt_cc))
1974 pkrb5_cc_close(ctx, cc);
1975 if (ctx && (ctx != alt_ctx))
1976 pkrb5_free_context(ctx);
1984 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
1986 NTSTATUS Status = 0;
1988 TOKEN_STATISTICS Stats;
1994 *ppSessionData = NULL;
1996 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2000 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2001 CloseHandle( TokenHandle );
2005 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2006 if ( FAILED(Status) || !ppSessionData )
2013 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2014 // cache. It validates whether or not it is reasonable to assume that if we
2015 // attempted to retrieve valid tickets we could do so. Microsoft does not
2016 // automatically renew expired tickets. Therefore, the cache could contain
2017 // expired or invalid tickets. Microsoft also caches the user's password
2018 // and will use it to retrieve new TGTs if the cache is empty and tickets
2022 MSLSA_IsKerberosLogon(VOID)
2024 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2025 BOOL Success = FALSE;
2027 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2028 if ( pSessionData->AuthenticationPackage.Buffer ) {
2034 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2035 usLength = (pSessionData->AuthenticationPackage).Length;
2038 lstrcpynW (buffer, usBuffer, usLength);
2039 lstrcatW (buffer,L"");
2040 if ( !lstrcmpW(L"Kerberos",buffer) )
2044 pLsaFreeReturnBuffer(pSessionData);
2048 #endif /* USE_MS2MIT */
2050 static BOOL CALLBACK
2051 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2055 switch ( message ) {
2057 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2059 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2062 for ( i=0; i < mid_cnt ; i++ ) {
2063 if (mid_tb[i].echo == 0)
2064 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2065 else if (mid_tb[i].echo == 2)
2066 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2071 switch ( LOWORD(wParam) ) {
2073 for ( i=0; i < mid_cnt ; i++ ) {
2074 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2075 *mid_tb[i].buf = '\0';
2079 EndDialog(hDialog, LOWORD(wParam));
2087 lpwAlign( LPWORD lpIn )
2095 return (LPWORD) ul;;
2099 * dialog widths are measured in 1/4 character widths
2100 * dialog height are measured in 1/8 character heights
2104 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2105 char * ptext[], int numlines, int width,
2106 int tb_cnt, struct textField * tb)
2110 LPDLGITEMTEMPLATE lpdit;
2116 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2123 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2125 // Define a dialog box.
2127 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2128 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2129 | DS_SETFOREGROUND | DS_3DLOOK
2130 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2131 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2134 lpdt->cx = 20 + width * 4;
2135 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2137 lpw = (LPWORD) (lpdt + 1);
2138 *lpw++ = 0; // no menu
2139 *lpw++ = 0; // predefined dialog box class (by default)
2141 lpwsz = (LPWSTR) lpw;
2142 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2144 *lpw++ = 8; // font size (points)
2145 lpwsz = (LPWSTR) lpw;
2146 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2150 //-----------------------
2151 // Define an OK button.
2152 //-----------------------
2153 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2154 lpdit = (LPDLGITEMTEMPLATE) lpw;
2155 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2156 lpdit->dwExtendedStyle = 0;
2157 lpdit->x = (lpdt->cx - 14)/4 - 20;
2158 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2161 lpdit->id = IDOK; // OK button identifier
2163 lpw = (LPWORD) (lpdit + 1);
2165 *lpw++ = 0x0080; // button class
2167 lpwsz = (LPWSTR) lpw;
2168 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2170 *lpw++ = 0; // no creation data
2172 //-----------------------
2173 // Define an Cancel button.
2174 //-----------------------
2175 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2176 lpdit = (LPDLGITEMTEMPLATE) lpw;
2177 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2178 lpdit->dwExtendedStyle = 0;
2179 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2180 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2183 lpdit->id = IDCANCEL; // CANCEL button identifier
2185 lpw = (LPWORD) (lpdit + 1);
2187 *lpw++ = 0x0080; // button class
2189 lpwsz = (LPWSTR) lpw;
2190 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2192 *lpw++ = 0; // no creation data
2194 /* Add controls for preface data */
2195 for ( i=0; i<numlines; i++) {
2196 /*-----------------------
2197 * Define a static text control.
2198 *-----------------------*/
2199 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2200 lpdit = (LPDLGITEMTEMPLATE) lpw;
2201 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2202 lpdit->dwExtendedStyle = 0;
2204 lpdit->y = 10 + i * 14;
2205 lpdit->cx = strlen(ptext[i]) * 4 + 10;
2207 lpdit->id = ID_TEXT + i; // text identifier
2209 lpw = (LPWORD) (lpdit + 1);
2211 *lpw++ = 0x0082; // static class
2213 lpwsz = (LPWSTR) lpw;
2214 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2215 -1, lpwsz, 2*width);
2217 *lpw++ = 0; // no creation data
2220 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2221 if ( pwid < strlen(tb[i].label) )
2222 pwid = strlen(tb[i].label);
2225 for ( i=0; i<tb_cnt; i++) {
2227 /*-----------------------
2228 * Define a static text control.
2229 *-----------------------*/
2230 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2231 lpdit = (LPDLGITEMTEMPLATE) lpw;
2232 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2233 lpdit->dwExtendedStyle = 0;
2235 lpdit->y = 10 + (numlines + i + 1) * 14;
2236 lpdit->cx = pwid * 4;
2238 lpdit->id = ID_TEXT + numlines + i; // text identifier
2240 lpw = (LPWORD) (lpdit + 1);
2242 *lpw++ = 0x0082; // static class
2244 lpwsz = (LPWSTR) lpw;
2245 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2248 *lpw++ = 0; // no creation data
2250 /*-----------------------
2251 * Define an edit control.
2252 *-----------------------*/
2253 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2254 lpdit = (LPDLGITEMTEMPLATE) lpw;
2255 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2256 lpdit->dwExtendedStyle = 0;
2257 lpdit->x = 10 + (pwid + 1) * 4;
2258 lpdit->y = 10 + (numlines + i + 1) * 14;
2259 lpdit->cx = (width - (pwid + 1)) * 4;
2261 lpdit->id = ID_MID_TEXT + i; // identifier
2263 lpw = (LPWORD) (lpdit + 1);
2265 *lpw++ = 0x0081; // edit class
2267 lpwsz = (LPWSTR) lpw;
2268 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2271 *lpw++ = 0; // no creation data
2275 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2276 hwndOwner, (DLGPROC) MultiInputDialogProc);
2280 case 0: /* Timeout */
2288 sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
2289 MessageBox(hwndOwner,
2292 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2299 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2301 HINSTANCE hInst = 0;
2305 char * plines[16], *p = preface ? preface : "";
2308 for ( i=0; i<16; i++ )
2311 while (*p && numlines < 16) {
2312 plines[numlines++] = p;
2313 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2314 if ( *p == '\r' && *(p+1) == '\n' ) {
2317 } else if ( *p == '\n' ) {
2320 if ( strlen(plines[numlines-1]) > maxwidth )
2321 maxwidth = strlen(plines[numlines-1]);
2324 for ( i=0;i<n;i++ ) {
2325 len = strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2326 if ( maxwidth < len )
2330 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb));
2333 static krb5_error_code KRB5_CALLCONV
2334 KRB5_prompter( krb5_context context,
2339 krb5_prompt prompts[])
2341 krb5_error_code errcode = 0;
2343 struct textField * tb = NULL;
2344 int len = 0, blen=0, nlen=0;
2345 HWND hParent = (HWND)data;
2348 nlen = strlen(name)+2;
2351 blen = strlen(banner)+2;
2353 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2356 memset(tb,0,sizeof(struct textField) * num_prompts);
2357 for ( i=0; i < num_prompts; i++ ) {
2358 tb[i].buf = prompts[i].reply->data;
2359 tb[i].len = prompts[i].reply->length;
2360 tb[i].label = prompts[i].prompt;
2362 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2365 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2367 for ( i=0; i < num_prompts; i++ )
2368 prompts[i].reply->length = strlen(prompts[i].reply->data);
2376 for (i = 0; i < num_prompts; i++) {
2377 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2384 KFW_AFS_wait_for_service_start(void)
2389 CurrentState = SERVICE_START_PENDING;
2390 memset(HostName, '\0', sizeof(HostName));
2391 gethostname(HostName, sizeof(HostName));
2393 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2395 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2397 if ( IsDebuggerPresent() ) {
2398 switch ( CurrentState ) {
2399 case SERVICE_STOPPED:
2400 OutputDebugString("SERVICE_STOPPED\n");
2402 case SERVICE_START_PENDING:
2403 OutputDebugString("SERVICE_START_PENDING\n");
2405 case SERVICE_STOP_PENDING:
2406 OutputDebugString("SERVICE_STOP_PENDING\n");
2408 case SERVICE_RUNNING:
2409 OutputDebugString("SERVICE_RUNNING\n");
2411 case SERVICE_CONTINUE_PENDING:
2412 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2414 case SERVICE_PAUSE_PENDING:
2415 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2417 case SERVICE_PAUSED:
2418 OutputDebugString("SERVICE_PAUSED\n");
2421 OutputDebugString("UNKNOWN Service State\n");
2424 if (CurrentState == SERVICE_STOPPED)
2426 if (CurrentState == SERVICE_RUNNING)
2442 memset(HostName, '\0', sizeof(HostName));
2443 gethostname(HostName, sizeof(HostName));
2444 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2446 if (CurrentState != SERVICE_RUNNING)
2449 rc = ktc_ForgetAllTokens();
2455 #define ALLOW_REGISTER 1
2457 ViceIDToUsername(char *username,
2458 char *realm_of_user,
2459 char *realm_of_cell,
2461 struct ktc_principal *aclient,
2462 struct ktc_principal *aserver,
2463 struct ktc_token *atoken)
2465 static char lastcell[MAXCELLCHARS+1] = { 0 };
2466 static char confname[512] = { 0 };
2467 #ifdef AFS_ID_TO_NAME
2468 char username_copy[BUFSIZ];
2469 #endif /* AFS_ID_TO_NAME */
2470 long viceId; /* AFS uid of user */
2472 #ifdef ALLOW_REGISTER
2474 #endif /* ALLOW_REGISTER */
2476 if (confname[0] == '\0') {
2477 strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname));
2478 confname[sizeof(confname) - 2] = '\0';
2482 * Talk about DUMB! It turns out that there is a bug in
2483 * pr_Initialize -- even if you give a different cell name
2484 * to it, it still uses a connection to a previous AFS server
2485 * if one exists. The way to fix this is to change the
2486 * _filename_ argument to pr_Initialize - that forces it to
2487 * re-initialize the connection. We do this by adding and
2488 * removing a "/" on the end of the configuration directory name.
2491 if (lastcell[0] != '\0' && (strcmp(lastcell, aserver->cell) != 0)) {
2492 int i = strlen(confname);
2493 if (confname[i - 1] == '/') {
2494 confname[i - 1] = '\0';
2497 confname[i + 1] = '\0';
2501 strcpy(lastcell, aserver->cell);
2503 if (!pr_Initialize (0, confname, aserver->cell))
2504 status = pr_SNameToId (username, &viceId);
2507 * This is a crock, but it is Transarc's crock, so
2508 * we have to play along in order to get the
2509 * functionality. The way the afs id is stored is
2510 * as a string in the username field of the token.
2511 * Contrary to what you may think by looking at
2512 * the code for tokens, this hack (AFS ID %d) will
2513 * not work if you change %d to something else.
2517 * This code is taken from cklog -- it lets people
2518 * automatically register with the ptserver in foreign cells
2521 #ifdef ALLOW_REGISTER
2523 if (viceId != ANONYMOUSID) {
2524 #else /* ALLOW_REGISTER */
2525 if ((status == 0) && (viceId != ANONYMOUSID))
2526 #endif /* ALLOW_REGISTER */
2528 #ifdef AFS_ID_TO_NAME
2529 strncpy(username_copy, username, BUFSIZ);
2530 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2531 #endif /* AFS_ID_TO_NAME */
2533 #ifdef ALLOW_REGISTER
2534 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2536 strncpy(aclient->name, username, MAXKTCNAMELEN - 1);
2537 strcpy(aclient->instance, "");
2538 strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
2539 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2543 * In case you're wondering, we don't need to change the
2544 * filename here because we're still connecting to the
2545 * same cell -- we're just using a different authentication
2549 if (status = pr_Initialize(1L, confname, aserver->cell))
2551 if (status = pr_CreateUser(username, &id))
2553 #ifdef AFS_ID_TO_NAME
2554 strncpy(username_copy, username, BUFSIZ);
2555 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2556 #endif /* AFS_ID_TO_NAME */
2559 #endif /* ALLOW_REGISTER */
2566 krb5_context alt_ctx,
2579 #endif /* USE_KRB4 */
2580 struct ktc_principal aserver;
2581 struct ktc_principal aclient;
2582 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2583 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2584 char local_cell[MAXCELLCHARS+1];
2585 char Dmycell[MAXCELLCHARS+1];
2586 struct ktc_token atoken;
2587 struct ktc_token btoken;
2588 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2589 char RealmName[128];
2591 char ServiceName[128];
2595 krb5_context ctx = 0;
2598 krb5_creds * k5creds = 0;
2599 krb5_error_code code;
2600 krb5_principal client_principal = 0;
2605 memset(HostName, '\0', sizeof(HostName));
2606 gethostname(HostName, sizeof(HostName));
2607 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2608 if ( IsDebuggerPresent() )
2609 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2612 if (CurrentState != SERVICE_RUNNING) {
2613 if ( IsDebuggerPresent() )
2614 OutputDebugString("AFSD Service NOT RUNNING\n");
2618 if (!pkrb5_init_context)
2621 memset(RealmName, '\0', sizeof(RealmName));
2622 memset(CellName, '\0', sizeof(CellName));
2623 memset(ServiceName, '\0', sizeof(ServiceName));
2624 memset(realm_of_user, '\0', sizeof(realm_of_user));
2625 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2626 if (cell && cell[0])
2627 strcpy(Dmycell, cell);
2629 memset(Dmycell, '\0', sizeof(Dmycell));
2631 // NULL or empty cell returns information on local cell
2632 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2634 // KFW_AFS_error(rc, "get_cellconfig()");
2641 code = pkrb5_init_context(&ctx);
2642 if (code) goto cleanup;
2648 code = pkrb5_cc_default(ctx, &cc);
2649 if (code) goto skip_krb5_init;
2652 memset((char *)&increds, 0, sizeof(increds));
2654 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2656 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2658 OutputDebugString("Principal Not Found for ccache\n");
2660 goto skip_krb5_init;
2663 /* lookfor client principals which cannot be distinguished
2664 * from Kerberos 4 multi-component principal names
2666 k5data = krb5_princ_component(ctx,client_principal,0);
2667 for ( i=0; i<k5data->length; i++ ) {
2668 if ( k5data->data[i] == '.' )
2671 if (i != k5data->length)
2673 OutputDebugString("Illegal Principal name contains dot in first component\n");
2674 rc = KRB5KRB_ERR_GENERIC;
2678 i = krb5_princ_realm(ctx, client_principal)->length;
2681 strncpy(realm_of_user,krb5_princ_realm(ctx, client_principal)->data,i);
2682 realm_of_user[i] = 0;
2687 if ( !try_krb5 || !realm_of_user[0] ) {
2688 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2697 strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig));
2699 if (strlen(service) == 0)
2700 strcpy(ServiceName, "afs");
2702 strcpy(ServiceName, service);
2704 if (strlen(cell) == 0)
2705 strcpy(CellName, local_cell);
2707 strcpy(CellName, cell);
2709 if (strlen(realm) == 0)
2710 strcpy(RealmName, realm_of_cell);
2712 strcpy(RealmName, realm);
2714 memset(&creds, '\0', sizeof(creds));
2719 /* First try service/cell@REALM */
2720 if (code = pkrb5_build_principal(ctx, &increds.server,
2730 increds.client = client_principal;
2731 increds.times.endtime = 0;
2732 /* Ask for DES since that is what V4 understands */
2733 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
2736 if ( IsDebuggerPresent() ) {
2737 char * cname, *sname;
2738 pkrb5_unparse_name(ctx, increds.client, &cname);
2739 pkrb5_unparse_name(ctx, increds.server, &sname);
2740 OutputDebugString("Getting tickets for \"");
2741 OutputDebugString(cname);
2742 OutputDebugString("\" and service \"");
2743 OutputDebugString(sname);
2744 OutputDebugString("\"\n");
2745 pkrb5_free_unparsed_name(ctx,cname);
2746 pkrb5_free_unparsed_name(ctx,sname);
2749 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2750 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2751 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2752 code == KRB5KRB_AP_ERR_MSG_TYPE) {
2753 /* Or service@REALM */
2754 pkrb5_free_principal(ctx,increds.server);
2756 code = pkrb5_build_principal(ctx, &increds.server,
2762 if ( IsDebuggerPresent() ) {
2763 char * cname, *sname;
2764 pkrb5_unparse_name(ctx, increds.client, &cname);
2765 pkrb5_unparse_name(ctx, increds.server, &sname);
2766 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2767 OutputDebugString("Trying again: getting tickets for \"");
2768 OutputDebugString(cname);
2769 OutputDebugString("\" and service \"");
2770 OutputDebugString(sname);
2771 OutputDebugString("\"\n");
2772 pkrb5_free_unparsed_name(ctx,cname);
2773 pkrb5_free_unparsed_name(ctx,sname);
2777 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2780 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2781 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2782 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
2783 strcmp(RealmName, realm_of_cell)) {
2784 /* Or service/cell@REALM_OF_CELL */
2785 strcpy(RealmName, realm_of_cell);
2786 pkrb5_free_principal(ctx,increds.server);
2788 code = pkrb5_build_principal(ctx, &increds.server,
2795 if ( IsDebuggerPresent() ) {
2796 char * cname, *sname;
2797 pkrb5_unparse_name(ctx, increds.client, &cname);
2798 pkrb5_unparse_name(ctx, increds.server, &sname);
2799 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2800 OutputDebugString("Trying again: getting tickets for \"");
2801 OutputDebugString(cname);
2802 OutputDebugString("\" and service \"");
2803 OutputDebugString(sname);
2804 OutputDebugString("\"\n");
2805 pkrb5_free_unparsed_name(ctx,cname);
2806 pkrb5_free_unparsed_name(ctx,sname);
2810 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2813 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2814 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2815 code == KRB5KRB_AP_ERR_MSG_TYPE) {
2816 /* Or service@REALM_OF_CELL */
2817 pkrb5_free_principal(ctx,increds.server);
2819 code = pkrb5_build_principal(ctx, &increds.server,
2825 if ( IsDebuggerPresent() ) {
2826 char * cname, *sname;
2827 pkrb5_unparse_name(ctx, increds.client, &cname);
2828 pkrb5_unparse_name(ctx, increds.server, &sname);
2829 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2830 OutputDebugString("Trying again: getting tickets for \"");
2831 OutputDebugString(cname);
2832 OutputDebugString("\" and service \"");
2833 OutputDebugString(sname);
2834 OutputDebugString("\"\n");
2835 pkrb5_free_unparsed_name(ctx,cname);
2836 pkrb5_free_unparsed_name(ctx,sname);
2840 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2845 if ( IsDebuggerPresent() ) {
2847 sprintf(message,"krb5_get_credentials returns: %d\n",code);
2848 OutputDebugString(message);
2854 /* This code inserts the entire K5 ticket into the token
2855 * No need to perform a krb524 translation which is
2856 * commented out in the code below
2858 if (KFW_use_krb524() ||
2859 k5creds->ticket.length > MAXKTCTICKETLEN)
2862 memset(&aserver, '\0', sizeof(aserver));
2863 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
2864 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
2866 memset(&atoken, '\0', sizeof(atoken));
2867 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
2868 atoken.startTime = k5creds->times.starttime;
2869 atoken.endTime = k5creds->times.endtime;
2870 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
2871 atoken.ticketLen = k5creds->ticket.length;
2872 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
2875 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
2876 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
2877 if ( rc == KTC_NOCM && retry < 20 ) {
2880 goto retry_gettoken5;
2885 if (atoken.kvno == btoken.kvno &&
2886 atoken.ticketLen == btoken.ticketLen &&
2887 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
2888 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
2890 /* Success - Nothing to do */
2894 // * Reset the "aclient" structure before we call ktc_SetToken.
2895 // * This structure was first set by the ktc_GetToken call when
2896 // * we were comparing whether identical tokens already existed.
2898 len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
2899 strncpy(aclient.name, k5creds->client->data[0].data, len);
2900 aclient.name[len] = '\0';
2902 if ( k5creds->client->length > 1 ) {
2904 strcat(aclient.name, ".");
2905 p = aclient.name + strlen(aclient.name);
2906 len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
2907 strncpy(p, k5creds->client->data[1].data, len);
2910 aclient.instance[0] = '\0';
2912 strcpy(aclient.cell, realm_of_cell);
2914 len = min(k5creds->client->realm.length,strlen(realm_of_cell));
2915 if ( strncmp(realm_of_cell, k5creds->client->realm.data, len) ) {
2917 strcat(aclient.name, "@");
2918 p = aclient.name + strlen(aclient.name);
2919 len = min(k5creds->client->realm.length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
2920 strncpy(p, k5creds->client->realm.data, len);
2924 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
2925 &aclient, &aserver, &atoken);
2928 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
2929 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
2931 aclient.smbname[0] = '\0';
2934 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
2936 goto cleanup; /* We have successfully inserted the token */
2939 /* Otherwise, the ticket could have been too large so try to
2940 * convert using the krb524d running with the KDC
2942 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
2943 pkrb5_free_creds(ctx, k5creds);
2945 if ( IsDebuggerPresent() ) {
2947 sprintf(message,"krb524_convert_creds_kdc returns: %d\n",code);
2948 OutputDebugString(message);
2956 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
2957 if (code == NO_TKT_FIL) {
2958 // if the problem is that we have no krb4 tickets
2959 // do not attempt to continue
2962 if (code != KSUCCESS)
2963 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
2965 if (code != KSUCCESS)
2967 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
2969 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
2974 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
2976 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
2991 memset(&aserver, '\0', sizeof(aserver));
2992 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
2993 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
2995 memset(&atoken, '\0', sizeof(atoken));
2996 atoken.kvno = creds.kvno;
2997 atoken.startTime = creds.issue_date;
2998 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
2999 memcpy(&atoken.sessionKey, creds.session, 8);
3000 atoken.ticketLen = creds.ticket_st.length;
3001 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3004 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3005 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3006 if ( rc == KTC_NOCM && retry < 20 ) {
3009 goto retry_gettoken;
3011 KFW_AFS_error(rc, "ktc_GetToken()");
3016 if (atoken.kvno == btoken.kvno &&
3017 atoken.ticketLen == btoken.ticketLen &&
3018 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3019 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3024 // * Reset the "aclient" structure before we call ktc_SetToken.
3025 // * This structure was first set by the ktc_GetToken call when
3026 // * we were comparing whether identical tokens already existed.
3028 strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
3031 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3032 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3034 strcpy(aclient.instance, "");
3036 if ( strcmp(realm_of_cell, creds.realm) )
3038 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3039 strncpy(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3041 aclient.name[MAXKTCREALMLEN-1] = '\0';
3043 strcpy(aclient.cell, CellName);
3045 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3046 &aclient, &aserver, &atoken);
3049 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
3050 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
3052 aclient.smbname[0] = '\0';
3055 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3057 KFW_AFS_error(rc, "ktc_SetToken()");
3063 if (client_principal)
3064 pkrb5_free_principal(ctx,client_principal);
3065 /* increds.client == client_principal */
3067 pkrb5_free_principal(ctx,increds.server);
3068 if (cc && (cc != alt_cc))
3069 pkrb5_cc_close(ctx, cc);
3070 if (ctx && (ctx != alt_ctx))
3071 pkrb5_free_context(ctx);
3073 return(rc? rc : code);
3076 /**************************************/
3077 /* afs_realm_of_cell(): */
3078 /**************************************/
3080 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3082 static char krbrlm[REALM_SZ+1]="";
3083 char ** realmlist=NULL;
3089 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3090 if ( !r && realmlist && realmlist[0] ) {
3091 strcpy(krbrlm, realmlist[0]);
3092 pkrb5_free_host_realm(ctx, realmlist);
3098 char *t = cellconfig->name;
3103 if (islower(c)) c=toupper(c);
3111 /**************************************/
3112 /* KFW_AFS_get_cellconfig(): */
3113 /**************************************/
3115 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3118 char newcell[MAXCELLCHARS+1];
3120 local_cell[0] = (char)0;
3121 memset(cellconfig, 0, sizeof(*cellconfig));
3123 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3124 if (rc = cm_GetRootCellName(local_cell))
3129 if (strlen(cell) == 0)
3130 strcpy(cell, local_cell);
3132 /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
3133 strcpy(cellconfig->name, cell);
3135 rc = cm_SearchCellFile(cell, newcell, get_cellconfig_callback, (void*)cellconfig);
3136 #ifdef AFS_AFSDB_ENV
3139 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3145 /**************************************/
3146 /* get_cellconfig_callback(): */
3147 /**************************************/
3149 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep)
3151 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3153 cc->hostAddr[cc->numServers] = *addrp;
3154 strcpy(cc->hostName[cc->numServers], namep);
3160 /**************************************/
3161 /* KFW_AFS_error(): */
3162 /**************************************/
3164 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3167 const char *errText;
3169 // Using AFS defines as error messages for now, until Transarc
3170 // gets back to me with "string" translations of each of these
3172 if (rc == KTC_ERROR)
3173 errText = "KTC_ERROR";
3174 else if (rc == KTC_TOOBIG)
3175 errText = "KTC_TOOBIG";
3176 else if (rc == KTC_INVAL)
3177 errText = "KTC_INVAL";
3178 else if (rc == KTC_NOENT)
3179 errText = "KTC_NOENT";
3180 else if (rc == KTC_PIOCTLFAIL)
3181 errText = "KTC_PIOCTLFAIL";
3182 else if (rc == KTC_NOPIOCTL)
3183 errText = "KTC_NOPIOCTL";
3184 else if (rc == KTC_NOCELL)
3185 errText = "KTC_NOCELL";
3186 else if (rc == KTC_NOCM)
3187 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3189 errText = "Unknown error!";
3191 sprintf(message, "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3193 if ( IsDebuggerPresent() ) {
3194 OutputDebugString(message);
3195 OutputDebugString("\n");
3197 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3203 LPSTR lpszMachineName,
3204 LPSTR lpszServiceName,
3205 DWORD *lpdwCurrentState)
3208 SC_HANDLE schSCManager = NULL;
3209 SC_HANDLE schService = NULL;
3210 DWORD fdwDesiredAccess = 0;
3211 SERVICE_STATUS ssServiceStatus = {0};
3214 *lpdwCurrentState = 0;
3216 fdwDesiredAccess = GENERIC_READ;
3218 schSCManager = OpenSCManager(lpszMachineName,
3222 if(schSCManager == NULL)
3224 hr = GetLastError();
3228 schService = OpenService(schSCManager,
3232 if(schService == NULL)
3234 hr = GetLastError();
3238 fRet = QueryServiceStatus(schService,
3243 hr = GetLastError();
3247 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3251 CloseServiceHandle(schService);
3252 CloseServiceHandle(schSCManager);
3265 for (n = 0; fi[n].func_ptr_var; n++)
3266 *(fi[n].func_ptr_var) = 0;
3267 if (h) FreeLibrary(h);
3272 const char* dll_name,
3274 HINSTANCE* ph, // [out, optional] - DLL handle
3275 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3276 int cleanup, // cleanup function pointers and unload on error
3277 int go_on, // continue loading even if some functions cannot be loaded
3278 int silent // do not pop-up a system dialog if DLL cannot be loaded
3287 if (pindex) *pindex = -1;
3289 for (n = 0; fi[n].func_ptr_var; n++)
3290 *(fi[n].func_ptr_var) = 0;
3293 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3294 h = LoadLibrary(dll_name);
3302 for (i = 0; (go_on || !error) && (i < n); i++)
3304 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3310 *(fi[i].func_ptr_var) = p;
3313 if (pindex) *pindex = last_i;
3314 if (error && cleanup && !go_on) {
3315 for (i = 0; i < n; i++) {
3316 *(fi[i].func_ptr_var) = 0;
3322 if (error) return 0;
3326 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3328 krb5_context ctx = 0;
3330 krb5_error_code code;
3332 const char * realm = 0;
3333 krb5_principal principal = 0;
3335 char password[PROBE_PASSWORD_LEN+1];
3336 BOOL serverReachable = 0;
3338 if (!pkrb5_init_context)
3341 code = pkrb5_init_context(&ctx);
3342 if (code) goto cleanup;
3345 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3347 code = pkrb5_build_principal(ctx, &principal, strlen(realm),
3348 realm, PROBE_USERNAME, NULL, NULL);
3349 if ( code ) goto cleanup;
3351 code = KFW_get_ccache(ctx, principal, &cc);
3352 if ( code ) goto cleanup;
3354 code = pkrb5_unparse_name(ctx, principal, &pname);
3355 if ( code ) goto cleanup;
3357 pwdata.data = password;
3358 pwdata.length = PROBE_PASSWORD_LEN;
3359 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3362 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3365 password[PROBE_PASSWORD_LEN] = '\0';
3367 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3377 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3378 case KRB5KDC_ERR_CLIENT_REVOKED:
3379 case KRB5KDC_ERR_CLIENT_NOTYET:
3380 case KRB5KDC_ERR_PREAUTH_FAILED:
3381 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3382 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3383 serverReachable = TRUE;
3386 serverReachable = FALSE;
3391 pkrb5_free_unparsed_name(ctx,pname);
3393 pkrb5_free_principal(ctx,principal);
3395 pkrb5_cc_close(ctx,cc);
3397 pkrb5_free_context(ctx);
3399 return serverReachable;