2 * Copyright (c) 2004, 2005, 2006, 2007, 2008 Secure Endpoints Inc.
3 * Copyright (c) 2003 SkyRope, LLC
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * - Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * - Neither the name of Skyrope, LLC nor the names of its contributors may be
15 * used to endorse or promote products derived from this software without
16 * specific prior written permission from Skyrope, LLC.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Portions of this code are derived from portions of the MIT
31 * Leash Ticket Manager and LoadFuncs utilities. For these portions the
32 * following copyright applies.
34 * Copyright (c) 2003,2004 by the Massachusetts Institute of Technology.
35 * All rights reserved.
37 * Export of this software from the United States of America may
38 * require a specific license from the United States Government.
39 * It is the responsibility of any person or organization contemplating
40 * export to obtain such a license before exporting.
42 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
43 * distribute this software and its documentation for any purpose and
44 * without fee is hereby granted, provided that the above copyright
45 * notice appear in all copies and that both that copyright notice and
46 * this permission notice appear in supporting documentation, and that
47 * the name of M.I.T. not be used in advertising or publicity pertaining
48 * to distribution of the software without specific, written prior
49 * permission. Furthermore if you modify this software you must label
50 * your software as modified software and not distribute it in such a
51 * fashion that it might be confused with the original M.I.T. software.
52 * M.I.T. makes no representations about the suitability of
53 * this software for any purpose. It is provided "as is" without express
54 * or implied warranty.
66 #include <afsconfig.h>
67 #include <afs/param.h>
71 #include <afs/ptserver.h>
72 #include <afs/ptuser.h>
74 #include <WINNT\afsreg.h>
78 #include "afskfw-int.h"
86 * TIMING _____________________________________________________________________
90 #define cminREMIND_TEST 1 // test every minute for expired creds
91 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
92 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
93 #define cminMINLIFE 30 // minimum life of Kerberos creds
95 #define c100ns1SECOND (LONGLONG)10000000
96 #define cmsec1SECOND 1000
97 #define cmsec1MINUTE 60000
98 #define csec1MINUTE 60
100 /* Function Pointer Declarations for Delayed Loading */
102 DECL_FUNC_PTR(cc_initialize);
103 DECL_FUNC_PTR(cc_shutdown);
104 DECL_FUNC_PTR(cc_get_NC_info);
105 DECL_FUNC_PTR(cc_free_NC_info);
109 DECL_FUNC_PTR(Leash_get_default_lifetime);
110 DECL_FUNC_PTR(Leash_get_default_forwardable);
111 DECL_FUNC_PTR(Leash_get_default_renew_till);
112 DECL_FUNC_PTR(Leash_get_default_noaddresses);
113 DECL_FUNC_PTR(Leash_get_default_proxiable);
114 DECL_FUNC_PTR(Leash_get_default_publicip);
115 DECL_FUNC_PTR(Leash_get_default_use_krb4);
116 DECL_FUNC_PTR(Leash_get_default_life_min);
117 DECL_FUNC_PTR(Leash_get_default_life_max);
118 DECL_FUNC_PTR(Leash_get_default_renew_min);
119 DECL_FUNC_PTR(Leash_get_default_renew_max);
120 DECL_FUNC_PTR(Leash_get_default_renewable);
121 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
125 DECL_FUNC_PTR(krb5_change_password);
126 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
127 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
128 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
129 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
130 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
131 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
132 DECL_FUNC_PTR(krb5_get_init_creds_password);
133 DECL_FUNC_PTR(krb5_build_principal_ext);
134 DECL_FUNC_PTR(krb5_cc_get_name);
135 DECL_FUNC_PTR(krb5_cc_resolve);
136 DECL_FUNC_PTR(krb5_cc_default);
137 DECL_FUNC_PTR(krb5_cc_default_name);
138 DECL_FUNC_PTR(krb5_cc_set_default_name);
139 DECL_FUNC_PTR(krb5_cc_initialize);
140 DECL_FUNC_PTR(krb5_cc_destroy);
141 DECL_FUNC_PTR(krb5_cc_close);
142 DECL_FUNC_PTR(krb5_cc_store_cred);
143 DECL_FUNC_PTR(krb5_cc_copy_creds);
144 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
145 DECL_FUNC_PTR(krb5_cc_get_principal);
146 DECL_FUNC_PTR(krb5_cc_start_seq_get);
147 DECL_FUNC_PTR(krb5_cc_next_cred);
148 DECL_FUNC_PTR(krb5_cc_end_seq_get);
149 DECL_FUNC_PTR(krb5_cc_remove_cred);
150 DECL_FUNC_PTR(krb5_cc_set_flags);
151 DECL_FUNC_PTR(krb5_cc_get_type);
152 DECL_FUNC_PTR(krb5_free_context);
153 DECL_FUNC_PTR(krb5_free_cred_contents);
154 DECL_FUNC_PTR(krb5_free_principal);
155 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
156 DECL_FUNC_PTR(krb5_init_context);
157 DECL_FUNC_PTR(krb5_parse_name);
158 DECL_FUNC_PTR(krb5_timeofday);
159 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
160 DECL_FUNC_PTR(krb5_unparse_name);
161 DECL_FUNC_PTR(krb5_get_credentials);
162 DECL_FUNC_PTR(krb5_mk_req);
163 DECL_FUNC_PTR(krb5_sname_to_principal);
164 DECL_FUNC_PTR(krb5_get_credentials_renew);
165 DECL_FUNC_PTR(krb5_free_data);
166 DECL_FUNC_PTR(krb5_free_data_contents);
167 DECL_FUNC_PTR(krb5_free_unparsed_name);
168 DECL_FUNC_PTR(krb5_os_localaddr);
169 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
170 DECL_FUNC_PTR(krb5_copy_data);
171 DECL_FUNC_PTR(krb5_free_creds);
172 DECL_FUNC_PTR(krb5_build_principal);
173 DECL_FUNC_PTR(krb5_get_renewed_creds);
174 DECL_FUNC_PTR(krb5_get_default_config_files);
175 DECL_FUNC_PTR(krb5_free_config_files);
176 DECL_FUNC_PTR(krb5_get_default_realm);
177 DECL_FUNC_PTR(krb5_free_default_realm);
178 DECL_FUNC_PTR(krb5_free_ticket);
179 DECL_FUNC_PTR(krb5_decode_ticket);
180 DECL_FUNC_PTR(krb5_get_host_realm);
181 DECL_FUNC_PTR(krb5_free_host_realm);
182 DECL_FUNC_PTR(krb5_free_addresses);
183 DECL_FUNC_PTR(krb5_c_random_make_octets);
185 // Krb5 KFW 3.2 functions
186 DECL_FUNC_PTR(krb5_get_error_message);
187 DECL_FUNC_PTR(krb5_free_error_message);
191 DECL_FUNC_PTR(krb524_init_ets);
192 DECL_FUNC_PTR(krb524_convert_creds_kdc);
197 DECL_FUNC_PTR(krb_get_cred);
198 DECL_FUNC_PTR(tkt_string);
199 DECL_FUNC_PTR(krb_get_tf_realm);
200 DECL_FUNC_PTR(krb_mk_req);
204 DECL_FUNC_PTR(com_err);
205 DECL_FUNC_PTR(error_message);
208 DECL_FUNC_PTR(profile_init);
209 DECL_FUNC_PTR(profile_release);
210 DECL_FUNC_PTR(profile_get_subsection_names);
211 DECL_FUNC_PTR(profile_free_list);
212 DECL_FUNC_PTR(profile_get_string);
213 DECL_FUNC_PTR(profile_release_string);
216 DECL_FUNC_PTR(OpenSCManagerA);
217 DECL_FUNC_PTR(OpenServiceA);
218 DECL_FUNC_PTR(QueryServiceStatus);
219 DECL_FUNC_PTR(CloseServiceHandle);
221 DECL_FUNC_PTR(LsaNtStatusToWinError);
222 #endif /* USE_MS2MIT */
226 DECL_FUNC_PTR(LsaConnectUntrusted);
227 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
228 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
229 DECL_FUNC_PTR(LsaFreeReturnBuffer);
230 DECL_FUNC_PTR(LsaGetLogonSessionData);
231 #endif /* USE_MS2MIT */
234 FUNC_INFO ccapi_fi[] = {
235 MAKE_FUNC_INFO(cc_initialize),
236 MAKE_FUNC_INFO(cc_shutdown),
237 MAKE_FUNC_INFO(cc_get_NC_info),
238 MAKE_FUNC_INFO(cc_free_NC_info),
243 FUNC_INFO leash_fi[] = {
244 MAKE_FUNC_INFO(Leash_get_default_lifetime),
245 MAKE_FUNC_INFO(Leash_get_default_renew_till),
246 MAKE_FUNC_INFO(Leash_get_default_forwardable),
247 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
248 MAKE_FUNC_INFO(Leash_get_default_proxiable),
249 MAKE_FUNC_INFO(Leash_get_default_publicip),
250 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
251 MAKE_FUNC_INFO(Leash_get_default_life_min),
252 MAKE_FUNC_INFO(Leash_get_default_life_max),
253 MAKE_FUNC_INFO(Leash_get_default_renew_min),
254 MAKE_FUNC_INFO(Leash_get_default_renew_max),
255 MAKE_FUNC_INFO(Leash_get_default_renewable),
259 FUNC_INFO leash_opt_fi[] = {
260 MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
265 FUNC_INFO k5_fi[] = {
266 MAKE_FUNC_INFO(krb5_change_password),
267 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
268 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
269 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
270 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
271 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
272 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
273 MAKE_FUNC_INFO(krb5_get_init_creds_password),
274 MAKE_FUNC_INFO(krb5_build_principal_ext),
275 MAKE_FUNC_INFO(krb5_cc_get_name),
276 MAKE_FUNC_INFO(krb5_cc_resolve),
277 MAKE_FUNC_INFO(krb5_cc_default),
278 MAKE_FUNC_INFO(krb5_cc_default_name),
279 MAKE_FUNC_INFO(krb5_cc_set_default_name),
280 MAKE_FUNC_INFO(krb5_cc_initialize),
281 MAKE_FUNC_INFO(krb5_cc_destroy),
282 MAKE_FUNC_INFO(krb5_cc_close),
283 MAKE_FUNC_INFO(krb5_cc_copy_creds),
284 MAKE_FUNC_INFO(krb5_cc_store_cred),
285 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
286 MAKE_FUNC_INFO(krb5_cc_get_principal),
287 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
288 MAKE_FUNC_INFO(krb5_cc_next_cred),
289 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
290 MAKE_FUNC_INFO(krb5_cc_remove_cred),
291 MAKE_FUNC_INFO(krb5_cc_set_flags),
292 MAKE_FUNC_INFO(krb5_cc_get_type),
293 MAKE_FUNC_INFO(krb5_free_context),
294 MAKE_FUNC_INFO(krb5_free_cred_contents),
295 MAKE_FUNC_INFO(krb5_free_principal),
296 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
297 MAKE_FUNC_INFO(krb5_init_context),
298 MAKE_FUNC_INFO(krb5_parse_name),
299 MAKE_FUNC_INFO(krb5_timeofday),
300 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
301 MAKE_FUNC_INFO(krb5_unparse_name),
302 MAKE_FUNC_INFO(krb5_get_credentials),
303 MAKE_FUNC_INFO(krb5_mk_req),
304 MAKE_FUNC_INFO(krb5_sname_to_principal),
305 MAKE_FUNC_INFO(krb5_get_credentials_renew),
306 MAKE_FUNC_INFO(krb5_free_data),
307 MAKE_FUNC_INFO(krb5_free_data_contents),
308 MAKE_FUNC_INFO(krb5_free_unparsed_name),
309 MAKE_FUNC_INFO(krb5_os_localaddr),
310 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
311 MAKE_FUNC_INFO(krb5_copy_data),
312 MAKE_FUNC_INFO(krb5_free_creds),
313 MAKE_FUNC_INFO(krb5_build_principal),
314 MAKE_FUNC_INFO(krb5_get_renewed_creds),
315 MAKE_FUNC_INFO(krb5_free_addresses),
316 MAKE_FUNC_INFO(krb5_get_default_config_files),
317 MAKE_FUNC_INFO(krb5_free_config_files),
318 MAKE_FUNC_INFO(krb5_get_default_realm),
319 MAKE_FUNC_INFO(krb5_free_default_realm),
320 MAKE_FUNC_INFO(krb5_free_ticket),
321 MAKE_FUNC_INFO(krb5_decode_ticket),
322 MAKE_FUNC_INFO(krb5_get_host_realm),
323 MAKE_FUNC_INFO(krb5_free_host_realm),
324 MAKE_FUNC_INFO(krb5_free_addresses),
325 MAKE_FUNC_INFO(krb5_c_random_make_octets),
329 FUNC_INFO k5_kfw_32_fi[] = {
330 MAKE_FUNC_INFO(krb5_get_error_message),
331 MAKE_FUNC_INFO(krb5_free_error_message),
336 FUNC_INFO k4_fi[] = {
337 MAKE_FUNC_INFO(krb_get_cred),
338 MAKE_FUNC_INFO(krb_get_tf_realm),
339 MAKE_FUNC_INFO(krb_mk_req),
340 MAKE_FUNC_INFO(tkt_string),
346 FUNC_INFO k524_fi[] = {
347 MAKE_FUNC_INFO(krb524_init_ets),
348 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
353 FUNC_INFO profile_fi[] = {
354 MAKE_FUNC_INFO(profile_init),
355 MAKE_FUNC_INFO(profile_release),
356 MAKE_FUNC_INFO(profile_get_subsection_names),
357 MAKE_FUNC_INFO(profile_free_list),
358 MAKE_FUNC_INFO(profile_get_string),
359 MAKE_FUNC_INFO(profile_release_string),
363 FUNC_INFO ce_fi[] = {
364 MAKE_FUNC_INFO(com_err),
365 MAKE_FUNC_INFO(error_message),
369 FUNC_INFO service_fi[] = {
370 MAKE_FUNC_INFO(OpenSCManagerA),
371 MAKE_FUNC_INFO(OpenServiceA),
372 MAKE_FUNC_INFO(QueryServiceStatus),
373 MAKE_FUNC_INFO(CloseServiceHandle),
375 MAKE_FUNC_INFO(LsaNtStatusToWinError),
376 #endif /* USE_MS2MIT */
381 FUNC_INFO lsa_fi[] = {
382 MAKE_FUNC_INFO(LsaConnectUntrusted),
383 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
384 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
385 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
386 MAKE_FUNC_INFO(LsaGetLogonSessionData),
389 #endif /* USE_MS2MIT */
391 /* Static Prototypes */
392 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
393 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *, unsigned short);
394 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
395 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
396 void *data, const char *name, const char *banner, int num_prompts,
397 krb5_prompt prompts[]);
400 /* Static Declarations */
401 static int inited = 0;
402 static int mid_cnt = 0;
403 static struct textField * mid_tb = NULL;
404 static HINSTANCE hKrb5 = 0;
405 static HINSTANCE hKrb5_kfw_32 = 0;
407 static HINSTANCE hKrb4 = 0;
408 #endif /* USE_KRB4 */
410 static HINSTANCE hKrb524 = 0;
413 static HINSTANCE hSecur32 = 0;
414 #endif /* USE_MS2MIT */
415 static HINSTANCE hAdvApi32 = 0;
416 static HINSTANCE hComErr = 0;
417 static HINSTANCE hService = 0;
418 static HINSTANCE hProfile = 0;
420 static HINSTANCE hLeash = 0;
421 static HINSTANCE hLeashOpt = 0;
423 static HINSTANCE hCCAPI = 0;
424 static struct principal_ccache_data * princ_cc_data = NULL;
425 static struct cell_principal_map * cell_princ_map = NULL;
430 static int inited = 0;
433 char mutexName[MAX_PATH];
434 HANDLE hMutex = NULL;
436 StringCbPrintf( mutexName, sizeof(mutexName), "AFS KFW Init pid=%d", getpid());
438 hMutex = CreateMutex( NULL, TRUE, mutexName );
439 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
440 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
446 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
447 LoadFuncs(KRB5_DLL, k5_kfw_32_fi, &hKrb5_kfw_32, 0, 1, 0, 0);
448 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
449 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
451 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
452 #endif /* USE_KRB4 */
453 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
455 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
456 #endif /* USE_MS2MIT */
458 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
461 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
462 LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
464 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
466 if ( KFW_is_available() ) {
467 char rootcell[CELL_MAXNAMELEN+1];
469 KFW_import_windows_lsa();
470 #endif /* USE_MS2MIT */
471 KFW_import_ccache_data();
472 KFW_AFS_renew_expiring_tokens();
474 /* WIN32 NOTE: no way to get max chars */
475 if (!cm_GetRootCellName(rootcell))
476 KFW_AFS_renew_token_for_cell(rootcell);
479 ReleaseMutex(hMutex);
489 FreeLibrary(hLeashOpt);
495 FreeLibrary(hKrb524);
501 FreeLibrary(hSecur32);
502 #endif /* USE_MS2MIT */
504 FreeLibrary(hService);
506 FreeLibrary(hComErr);
508 FreeLibrary(hProfile);
512 #endif /* USE_KRB4 */
516 FreeLibrary(hKrb5_kfw_32);
519 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
522 static int init = TRUE;
523 static int bIsWow64 = FALSE;
527 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
529 hModule = GetModuleHandle(TEXT("kernel32"));
531 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
533 if (NULL != fnIsWow64Process)
535 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
537 // on error, assume FALSE.
538 // in other words, do nothing.
541 FreeLibrary(hModule);
549 KFW_accept_dotted_usernames(void)
555 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
556 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
557 if (code == ERROR_SUCCESS) {
559 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
560 (BYTE *) &value, &len);
561 RegCloseKey(parmKey);
563 if (code != ERROR_SUCCESS) {
564 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
565 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
566 if (code == ERROR_SUCCESS) {
568 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
569 (BYTE *) &value, &len);
570 RegCloseKey (parmKey);
584 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
585 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
586 if (code == ERROR_SUCCESS) {
587 len = sizeof(use524);
588 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
589 (BYTE *) &use524, &len);
590 RegCloseKey(parmKey);
592 if (code != ERROR_SUCCESS) {
593 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
594 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
595 if (code == ERROR_SUCCESS) {
596 len = sizeof(use524);
597 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
598 (BYTE *) &use524, &len);
599 RegCloseKey (parmKey);
606 KFW_is_available(void)
612 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
613 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
614 if (code == ERROR_SUCCESS) {
615 len = sizeof(enableKFW);
616 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
617 (BYTE *) &enableKFW, &len);
618 RegCloseKey (parmKey);
621 if (code != ERROR_SUCCESS) {
622 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
623 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
624 if (code == ERROR_SUCCESS) {
625 len = sizeof(enableKFW);
626 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
627 (BYTE *) &enableKFW, &len);
628 RegCloseKey (parmKey);
636 if ( hKrb5 && hComErr && hService &&
639 #endif /* USE_MS2MIT */
652 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
653 int FreeContextFlag, krb5_context * ctx,
658 int krb5Error = ((int)(rc & 255));
670 if (pkrb5_get_error_message)
671 errText = pkrb5_get_error_message(ctx, rc);
673 errText = perror_message(rc);
674 StringCbPrintf(message, sizeof(message),
675 "%s\n(Kerberos error %ld)\n\n%s failed",
679 if (pkrb5_free_error_message)
680 pkrb5_free_error_message(ctx, (char *)errText);
682 if ( IsDebuggerPresent() )
683 OutputDebugString(message);
685 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
688 if (FreeContextFlag == 1)
690 if (ctx && *ctx != NULL)
692 if (cache && *cache != NULL) {
693 pkrb5_cc_close(*ctx, *cache);
697 pkrb5_free_context(*ctx);
706 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
708 struct principal_ccache_data * next = princ_cc_data;
709 krb5_principal principal = 0;
711 const char * ccname = NULL;
712 const char * cctype = NULL;
713 char * ccfullname = NULL;
714 krb5_error_code code = 0;
715 krb5_error_code cc_code = 0;
721 if (ctx == 0 || cc == 0)
724 code = pkrb5_cc_get_principal(ctx, cc, &principal);
727 code = pkrb5_unparse_name(ctx, principal, &pname);
728 if ( code ) goto cleanup;
730 ccname = pkrb5_cc_get_name(ctx, cc);
731 if (!ccname) goto cleanup;
733 cctype = pkrb5_cc_get_type(ctx, cc);
734 if (!cctype) goto cleanup;
736 ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
737 if (!ccfullname) goto cleanup;
739 StringCbPrintf(ccfullname, sizeof(ccfullname), "%s:%s", cctype, ccname);
741 // Search the existing list to see if we have a match
743 for ( ; next ; next = next->next ) {
744 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
749 // If not, match add a new node to the beginning of the list and assign init it
751 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
752 next->next = princ_cc_data;
753 princ_cc_data = next;
754 next->principal = _strdup(pname);
755 next->ccache_name = ccfullname;
757 next->from_lsa = lsa;
759 next->expiration_time = 0;
763 flags = 0; // turn off OPENCLOSE mode
764 code = pkrb5_cc_set_flags(ctx, cc, flags);
765 if ( code ) goto cleanup;
767 code = pkrb5_timeofday(ctx, &now);
769 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
771 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
772 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
774 // we found the ticket we are looking for
775 // check validity of timestamp
776 // We add a 5 minutes fudge factor to compensate for potential
777 // clock skew errors between the KDC and client OS
779 valid = ((creds.times.starttime > 0) &&
780 now >= (creds.times.starttime - 300) &&
781 now < (creds.times.endtime + 300) &&
782 !(creds.ticket_flags & TKT_FLG_INVALID));
784 if ( next->from_lsa) {
786 next->expiration_time = creds.times.endtime;
788 } else if ( valid ) {
790 next->expiration_time = creds.times.endtime;
791 next->renew = (creds.times.renew_till > creds.times.endtime) &&
792 (creds.ticket_flags & TKT_FLG_RENEWABLE);
795 next->expiration_time = 0;
799 pkrb5_free_cred_contents(ctx, &creds);
800 cc_code = KRB5_CC_END;
803 pkrb5_free_cred_contents(ctx, &creds);
806 if (cc_code == KRB5_CC_END) {
807 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
808 if (code) goto cleanup;
812 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
813 code = pkrb5_cc_set_flags(ctx, cc, flags);
818 pkrb5_free_unparsed_name(ctx,pname);
820 pkrb5_free_principal(ctx,principal);
824 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
826 struct principal_ccache_data * next = princ_cc_data;
827 char * response = NULL;
829 if ( !principal || !ccache )
833 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
835 // we always want to prefer the MS Kerberos LSA cache or
836 // the cache afscreds created specifically for the principal
837 // if the current entry is either one, drop the previous find
838 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
841 response = _strdup(next->ccache_name);
842 // MS Kerberos LSA is our best option so use it and quit
843 if ( next->from_lsa )
857 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
859 struct principal_ccache_data ** next = &princ_cc_data;
861 if ( !pname && !ccname )
865 if ( !strcmp((*next)->principal,pname) ||
866 !strcmp((*next)->ccache_name,ccname) ) {
868 free((*next)->principal);
869 free((*next)->ccache_name);
871 (*next) = (*next)->next;
878 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
880 struct cell_principal_map * next = cell_princ_map;
882 // Search the existing list to see if we have a match
884 for ( ; next ; next = next->next ) {
885 if ( !strcmp(next->cell, cell) ) {
886 if ( !strcmp(next->principal,pname) ) {
887 next->active = active;
890 // OpenAFS currently has a restriction of one active token per cell
891 // Therefore, whenever we update the table with a new active cell we
892 // must mark all of the other principal to cell entries as inactive.
900 // If not, match add a new node to the beginning of the list and assign init it
902 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
903 next->next = cell_princ_map;
904 cell_princ_map = next;
905 next->principal = _strdup(pname);
906 next->cell = _strdup(cell);
907 next->active = active;
912 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
914 struct cell_principal_map ** next = &cell_princ_map;
916 if ( !pname && !cell )
920 if ( !strcmp((*next)->principal,pname) ||
921 !strcmp((*next)->cell,cell) ) {
923 free((*next)->principal);
926 (*next) = (*next)->next;
932 // Returns (if possible) a principal which has been known in
933 // the past to have been used to obtain tokens for the specified
935 // TODO: Attempt to return one which has not yet expired by checking
936 // the principal/ccache data
938 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
940 struct cell_principal_map * next_map = cell_princ_map;
941 const char * princ = NULL;
948 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
951 next_map = next_map->next;
954 if ( !principals || !count )
957 *principals = (char **) malloc(sizeof(char *) * count);
958 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
960 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
961 (*principals)[i++] = _strdup(next_map->principal);
968 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
971 struct cell_principal_map * next_map = cell_princ_map;
972 const char * princ = NULL;
978 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
981 next_map = next_map->next;
987 *cells = (char **) malloc(sizeof(char *) * count);
988 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
990 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
991 (*cells)[i++] = _strdup(next_map->cell);
997 /* Given a principal return an existing ccache or create one and return */
999 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
1001 krb5_context ctx = NULL;
1002 char * pname = NULL;
1003 char * ccname = NULL;
1004 krb5_error_code code;
1006 if (!pkrb5_init_context)
1012 code = pkrb5_init_context(&ctx);
1013 if (code) goto cleanup;
1017 code = pkrb5_unparse_name(ctx, principal, &pname);
1018 if (code) goto cleanup;
1020 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
1021 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
1022 size_t len = strlen(pname) + 5;
1023 ccname = (char *)malloc(len);
1024 StringCbPrintf(ccname, len, "API:%s", pname);
1026 code = pkrb5_cc_resolve(ctx, ccname, cc);
1028 code = pkrb5_cc_default(ctx, cc);
1029 if (code) goto cleanup;
1036 pkrb5_free_unparsed_name(ctx,pname);
1037 if (ctx && (ctx != alt_ctx))
1038 pkrb5_free_context(ctx);
1043 // Import Microsoft Credentials into a new MIT ccache
1045 KFW_import_windows_lsa(void)
1047 krb5_context ctx = NULL;
1048 krb5_ccache cc = NULL;
1049 krb5_principal princ = NULL;
1050 char * pname = NULL;
1051 krb5_data * princ_realm;
1052 krb5_error_code code;
1053 char cell[128]="", realm[128]="", *def_realm = 0;
1055 DWORD dwMsLsaImport;
1057 if (!pkrb5_init_context)
1060 code = pkrb5_init_context(&ctx);
1061 if (code) goto cleanup;
1063 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
1064 if (code) goto cleanup;
1066 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
1068 code = pkrb5_cc_get_principal(ctx, cc, &princ);
1069 if ( code ) goto cleanup;
1071 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
1072 switch ( dwMsLsaImport ) {
1073 case 0: /* do not import */
1075 case 1: /* always import */
1077 case 2: { /* matching realm */
1078 char ms_realm[128] = "", *r;
1081 for ( r=ms_realm, j=0; j<krb5_princ_realm(ctx, princ)->length; r++, j++ ) {
1082 *r = krb5_princ_realm(ctx, princ)->data[j];
1086 if (code = pkrb5_get_default_realm(ctx, &def_realm))
1089 if (strcmp(def_realm, ms_realm))
1097 code = pkrb5_unparse_name(ctx,princ,&pname);
1098 if ( code ) goto cleanup;
1100 princ_realm = krb5_princ_realm(ctx, princ);
1101 for ( i=0; i<princ_realm->length; i++ ) {
1102 realm[i] = princ_realm->data[i];
1103 cell[i] = tolower(princ_realm->data[i]);
1108 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
1109 if ( IsDebuggerPresent() ) {
1111 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1112 OutputDebugString(message);
1114 if ( code ) goto cleanup;
1116 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1120 pkrb5_free_unparsed_name(ctx,pname);
1122 pkrb5_free_principal(ctx,princ);
1124 pkrb5_free_default_realm(ctx, def_realm);
1126 pkrb5_cc_close(ctx,cc);
1128 pkrb5_free_context(ctx);
1130 #endif /* USE_MS2MIT */
1132 // If there are existing MIT credentials, copy them to a new
1133 // ccache named after the principal
1135 // Enumerate all existing MIT ccaches and construct entries
1136 // in the principal_ccache table
1138 // Enumerate all existing AFS Tokens and construct entries
1139 // in the cell_principal table
1141 KFW_import_ccache_data(void)
1143 krb5_context ctx = NULL;
1144 krb5_ccache cc = NULL;
1145 krb5_principal principal = NULL;
1147 krb5_error_code code;
1148 krb5_error_code cc_code;
1150 apiCB * cc_ctx = NULL;
1151 struct _infoNC ** pNCi = NULL;
1154 if ( !pcc_initialize )
1157 if ( IsDebuggerPresent() )
1158 OutputDebugString("KFW_import_ccache_data()\n");
1160 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1161 if (code) goto cleanup;
1163 code = pcc_get_NC_info(cc_ctx, &pNCi);
1164 if (code) goto cleanup;
1166 code = pkrb5_init_context(&ctx);
1167 if (code) goto cleanup;
1169 for ( i=0; pNCi[i]; i++ ) {
1170 if ( pNCi[i]->vers != CC_CRED_V5 )
1172 if ( IsDebuggerPresent() ) {
1173 OutputDebugString("Principal: ");
1174 OutputDebugString(pNCi[i]->principal);
1175 OutputDebugString(" in ccache ");
1176 OutputDebugString(pNCi[i]->name);
1177 OutputDebugString("\n");
1179 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1180 && strcmp(pNCi[i]->name,LSA_CCNAME)
1183 for ( j=0; pNCi[j]; j++ ) {
1184 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1190 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1191 if (code) goto loop_cleanup;
1194 krb5_ccache oldcc = 0;
1196 if ( IsDebuggerPresent() )
1197 OutputDebugString("copying ccache data to new ccache\n");
1199 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1200 if (code) goto loop_cleanup;
1201 code = pkrb5_cc_initialize(ctx, cc, principal);
1202 if (code) goto loop_cleanup;
1204 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1205 if (code) goto loop_cleanup;
1206 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1208 code = pkrb5_cc_close(ctx,cc);
1210 code = pkrb5_cc_close(ctx,oldcc);
1212 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1215 code = pkrb5_cc_close(ctx,oldcc);
1218 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1219 if (code) goto loop_cleanup;
1222 flags = 0; // turn off OPENCLOSE mode
1223 code = pkrb5_cc_set_flags(ctx, cc, flags);
1224 if ( code ) goto cleanup;
1226 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1228 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1230 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1231 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1232 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1233 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1234 if ( sname && cell && !strcmp("afs",sname->data) ) {
1235 struct ktc_principal aserver;
1236 struct ktc_principal aclient;
1237 struct ktc_token atoken;
1240 if ( IsDebuggerPresent() ) {
1241 OutputDebugString("Found AFS ticket: ");
1242 OutputDebugString(sname->data);
1244 OutputDebugString("/");
1245 OutputDebugString(cell->data);
1247 OutputDebugString("@");
1248 OutputDebugString(realm->data);
1249 OutputDebugString("\n");
1252 memset(&aserver, '\0', sizeof(aserver));
1253 StringCbCopyN( aserver.name, sizeof(aserver.name),
1254 sname->data, sizeof(aserver.name) - 1);
1255 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
1256 cell->data, sizeof(aserver.cell) - 1);
1258 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1260 // Found a token in AFS Client Server which matches
1261 char pname[128], *p, *q;
1262 for ( p=pname, q=aclient.name; *q; p++, q++)
1264 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1268 if ( IsDebuggerPresent() ) {
1269 OutputDebugString("Found AFS token: ");
1270 OutputDebugString(pname);
1271 OutputDebugString("\n");
1274 if ( strcmp(pname,pNCi[i]->principal) )
1276 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1278 // Attempt to import it
1279 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1281 if ( IsDebuggerPresent() ) {
1282 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1285 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data,
1289 pLeash_get_default_lifetime(),
1290 #endif /* USE_LEASH */
1292 if ( IsDebuggerPresent() ) {
1294 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1295 OutputDebugString(message);
1298 } else if ( IsDebuggerPresent() ) {
1299 OutputDebugString("Found ticket: ");
1300 OutputDebugString(sname->data);
1301 if ( cell && cell->data ) {
1302 OutputDebugString("/");
1303 OutputDebugString(cell->data);
1305 OutputDebugString("@");
1306 OutputDebugString(realm->data);
1307 OutputDebugString("\n");
1309 pkrb5_free_cred_contents(ctx, &creds);
1312 if (cc_code == KRB5_CC_END) {
1313 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1314 if (cc_code) goto loop_cleanup;
1318 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1319 code = pkrb5_cc_set_flags(ctx, cc, flags);
1321 pkrb5_cc_close(ctx,cc);
1325 pkrb5_free_principal(ctx,principal);
1332 pkrb5_free_context(ctx);
1334 pcc_free_NC_info(cc_ctx, &pNCi);
1336 pcc_shutdown(&cc_ctx);
1341 KFW_AFS_get_cred( char * username,
1348 static char reason[1024]="";
1349 krb5_context ctx = NULL;
1350 krb5_ccache cc = NULL;
1351 char * realm = NULL, * userrealm = NULL;
1352 krb5_principal principal = NULL;
1353 char * pname = NULL;
1354 krb5_error_code code;
1355 char local_cell[CELL_MAXNAMELEN+1];
1356 char **cells = NULL;
1358 struct afsconf_cell cellconfig;
1361 if (!pkrb5_init_context)
1364 if ( IsDebuggerPresent() ) {
1365 OutputDebugString("KFW_AFS_get_cred for token ");
1366 OutputDebugString(username);
1367 OutputDebugString(" in cell ");
1368 OutputDebugString(cell);
1369 OutputDebugString("\n");
1372 memset(&cellconfig, 0, sizeof(cellconfig));
1374 code = pkrb5_init_context(&ctx);
1375 if ( code ) goto cleanup;
1377 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1378 if ( code ) goto cleanup;
1380 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1382 userrealm = strchr(username,'@');
1384 pname = strdup(username);
1385 if (!KFW_accept_dotted_usernames()) {
1386 userrealm = strchr(pname, '@');
1389 /* handle kerberos iv notation */
1390 while ( dot = strchr(pname,'.') ) {
1396 size_t len = strlen(username) + strlen(realm) + 2;
1397 pname = malloc(len);
1398 if (pname == NULL) {
1399 code = KRB5KRB_ERR_GENERIC;
1402 StringCbCopy(pname, len, username);
1404 if (!KFW_accept_dotted_usernames()) {
1405 /* handle kerberos iv notation */
1406 while ( dot = strchr(pname,'.') ) {
1410 StringCbCat( pname, len, "@");
1411 StringCbCat( pname, len, realm);
1413 if ( IsDebuggerPresent() ) {
1414 OutputDebugString("Realm: ");
1415 OutputDebugString(realm);
1416 OutputDebugString("\n");
1419 code = pkrb5_parse_name(ctx, pname, &principal);
1420 if ( code ) goto cleanup;
1422 code = KFW_get_ccache(ctx, principal, &cc);
1423 if ( code ) goto cleanup;
1425 if ( lifetime == 0 )
1429 lifetime = pLeash_get_default_lifetime();
1432 if ( password && password[0] ) {
1433 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1438 1, /* forwardable */
1439 0, /* not proxiable */
1441 1, /* noaddresses */
1442 0 /* no public ip */
1444 pLeash_get_default_forwardable(),
1445 pLeash_get_default_proxiable(),
1446 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1447 pLeash_get_default_noaddresses(),
1448 pLeash_get_default_publicip()
1449 #endif /* USE_LEASH */
1452 if ( IsDebuggerPresent() ) {
1454 StringCbPrintf(message, sizeof(message), "KFW_kinit() returns: %d\n", code);
1455 OutputDebugString(message);
1457 if ( code ) goto cleanup;
1459 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1462 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1463 if ( IsDebuggerPresent() ) {
1465 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1466 OutputDebugString(message);
1468 if ( code ) goto cleanup;
1470 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1472 // Attempt to obtain new tokens for other cells supported by the same
1474 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1475 if ( cell_count > 1 ) {
1476 while ( cell_count-- ) {
1477 if ( strcmp(cells[cell_count],cell) ) {
1478 if ( IsDebuggerPresent() ) {
1480 StringCbPrintf(message, sizeof(message),
1481 "found another cell for the same principal: %s\n", cell);
1482 OutputDebugString(message);
1485 if (cellconfig.linkedCell) {
1486 free(cellconfig.linkedCell);
1487 cellconfig.linkedCell = NULL;
1489 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1490 if ( code ) continue;
1492 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1493 if ( IsDebuggerPresent() ) {
1494 OutputDebugString("Realm: ");
1495 OutputDebugString(realm);
1496 OutputDebugString("\n");
1499 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1500 if ( IsDebuggerPresent() ) {
1502 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1503 OutputDebugString(message);
1506 free(cells[cell_count]);
1509 } else if ( cell_count == 1 ) {
1518 pkrb5_cc_close(ctx, cc);
1519 if ( cellconfig.linkedCell )
1520 free(cellconfig.linkedCell);
1522 if ( code && reasonP ) {
1523 if (pkrb5_get_error_message) {
1524 char *msg = pkrb5_get_error_message(ctx, code);
1525 StringCbCopyN( reason, sizeof(reason),
1526 msg, sizeof(reason) - 1);
1528 pkrb5_free_error_message(ctx, msg);
1530 *reasonP = perror_message(code);
1537 KFW_AFS_destroy_tickets_for_cell(char * cell)
1539 krb5_context ctx = NULL;
1540 krb5_error_code code;
1542 char ** principals = NULL;
1544 if (!pkrb5_init_context)
1547 if ( IsDebuggerPresent() ) {
1548 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1549 OutputDebugString(cell);
1550 OutputDebugString("\n");
1553 code = pkrb5_init_context(&ctx);
1556 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1558 krb5_principal princ = 0;
1562 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1563 if ( cell_count > 1 ) {
1564 // TODO - What we really should do here is verify whether or not any of the
1565 // other cells which use this principal to obtain its credentials actually
1566 // have valid tokens or not. If they are currently using these credentials
1567 // we will skip them. For the time being we assume that if there is an active
1568 // map in the table that they are actively being used.
1572 code = pkrb5_parse_name(ctx, principals[count], &princ);
1573 if (code) goto loop_cleanup;
1575 code = KFW_get_ccache(ctx, princ, &cc);
1576 if (code) goto loop_cleanup;
1578 code = pkrb5_cc_destroy(ctx, cc);
1583 pkrb5_cc_close(ctx, cc);
1587 pkrb5_free_principal(ctx, princ);
1591 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1592 free(principals[count]);
1597 pkrb5_free_context(ctx);
1602 KFW_AFS_destroy_tickets_for_principal(char * user)
1604 krb5_context ctx = NULL;
1605 krb5_error_code code;
1607 char ** cells = NULL;
1608 krb5_principal princ = NULL;
1609 krb5_ccache cc = NULL;
1611 if (!pkrb5_init_context)
1614 if ( IsDebuggerPresent() ) {
1615 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1616 OutputDebugString(user);
1617 OutputDebugString("\n");
1620 code = pkrb5_init_context(&ctx);
1623 code = pkrb5_parse_name(ctx, user, &princ);
1624 if (code) goto loop_cleanup;
1626 code = KFW_get_ccache(ctx, princ, &cc);
1627 if (code) goto loop_cleanup;
1629 code = pkrb5_cc_destroy(ctx, cc);
1634 pkrb5_cc_close(ctx, cc);
1638 pkrb5_free_principal(ctx, princ);
1642 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1645 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1652 pkrb5_free_context(ctx);
1657 KFW_AFS_renew_expiring_tokens(void)
1659 krb5_error_code code = 0;
1660 krb5_context ctx = NULL;
1661 krb5_ccache cc = NULL;
1663 struct principal_ccache_data * pcc_next = princ_cc_data;
1666 const char * realm = NULL;
1667 char local_cell[CELL_MAXNAMELEN+1]="";
1668 struct afsconf_cell cellconfig;
1670 if (!pkrb5_init_context)
1673 if ( pcc_next == NULL ) // nothing to do
1676 if ( IsDebuggerPresent() ) {
1677 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1680 memset(&cellconfig, 0, sizeof(cellconfig));
1682 code = pkrb5_init_context(&ctx);
1683 if (code) goto cleanup;
1685 code = pkrb5_timeofday(ctx, &now);
1686 if (code) goto cleanup;
1688 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1689 if ( pcc_next->expired )
1692 if ( now >= (pcc_next->expiration_time) ) {
1693 if ( !pcc_next->from_lsa ) {
1694 pcc_next->expired = 1;
1699 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1700 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1703 code = KFW_renew(ctx,cc);
1705 if ( code && pcc_next->from_lsa)
1707 #endif /* USE_MS2MIT */
1710 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1711 if (code) goto loop_cleanup;
1713 // Attempt to obtain new tokens for other cells supported by the same
1715 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1716 if ( cell_count > 0 ) {
1717 while ( cell_count-- ) {
1718 if ( IsDebuggerPresent() ) {
1719 OutputDebugString("Cell: ");
1720 OutputDebugString(cells[cell_count]);
1721 OutputDebugString("\n");
1723 if (cellconfig.linkedCell) {
1724 free(cellconfig.linkedCell);
1725 cellconfig.linkedCell = NULL;
1727 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1728 if ( code ) continue;
1729 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1730 if ( IsDebuggerPresent() ) {
1731 OutputDebugString("Realm: ");
1732 OutputDebugString(realm);
1733 OutputDebugString("\n");
1735 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1736 if ( IsDebuggerPresent() ) {
1738 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1739 OutputDebugString(message);
1741 free(cells[cell_count]);
1749 pkrb5_cc_close(ctx,cc);
1756 pkrb5_cc_close(ctx,cc);
1758 pkrb5_free_context(ctx);
1759 if (cellconfig.linkedCell)
1760 free(cellconfig.linkedCell);
1767 KFW_AFS_renew_token_for_cell(char * cell)
1769 krb5_error_code code = 0;
1770 krb5_context ctx = NULL;
1772 char ** principals = NULL;
1774 if (!pkrb5_init_context)
1777 if ( IsDebuggerPresent() ) {
1778 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1779 OutputDebugString(cell);
1780 OutputDebugString("\n");
1783 code = pkrb5_init_context(&ctx);
1784 if (code) goto cleanup;
1786 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1788 // We know we must have a credential somewhere since we are
1789 // trying to renew a token
1791 KFW_import_ccache_data();
1792 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1795 krb5_principal princ = 0;
1796 krb5_principal service = 0;
1798 krb5_creds mcreds, creds;
1799 #endif /* COMMENT */
1801 const char * realm = NULL;
1802 struct afsconf_cell cellconfig;
1803 char local_cell[CELL_MAXNAMELEN+1];
1805 memset(&cellconfig, 0, sizeof(cellconfig));
1808 code = pkrb5_parse_name(ctx, principals[count], &princ);
1809 if (code) goto loop_cleanup;
1811 code = KFW_get_ccache(ctx, princ, &cc);
1812 if (code) goto loop_cleanup;
1814 if (cellconfig.linkedCell) {
1815 free(cellconfig.linkedCell);
1816 cellconfig.linkedCell = NULL;
1818 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1819 if ( code ) goto loop_cleanup;
1821 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1822 if ( IsDebuggerPresent() ) {
1823 OutputDebugString("Realm: ");
1824 OutputDebugString(realm);
1825 OutputDebugString("\n");
1829 /* krb5_cc_remove_cred() is not implemented
1832 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1833 realm, "afs", cell, NULL);
1835 memset(&mcreds, 0, sizeof(krb5_creds));
1836 mcreds.client = princ;
1837 mcreds.server = service;
1839 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1841 if ( IsDebuggerPresent() ) {
1842 char * cname, *sname;
1843 pkrb5_unparse_name(ctx, creds.client, &cname);
1844 pkrb5_unparse_name(ctx, creds.server, &sname);
1845 OutputDebugString("Removing credential for client \"");
1846 OutputDebugString(cname);
1847 OutputDebugString("\" and service \"");
1848 OutputDebugString(sname);
1849 OutputDebugString("\"\n");
1850 pkrb5_free_unparsed_name(ctx,cname);
1851 pkrb5_free_unparsed_name(ctx,sname);
1854 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1855 pkrb5_free_principal(ctx, creds.client);
1856 pkrb5_free_principal(ctx, creds.server);
1859 #endif /* COMMENT */
1861 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1862 if ( IsDebuggerPresent() ) {
1864 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1865 OutputDebugString(message);
1870 pkrb5_cc_close(ctx, cc);
1874 pkrb5_free_principal(ctx, princ);
1878 pkrb5_free_principal(ctx, service);
1881 if (cellconfig.linkedCell) {
1882 free(cellconfig.linkedCell);
1883 cellconfig.linkedCell = NULL;
1886 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1887 free(principals[count]);
1891 code = -1; // we did not renew the tokens
1895 pkrb5_free_context(ctx);
1896 return (code ? FALSE : TRUE);
1901 KFW_AFS_renew_tokens_for_all_cells(void)
1903 struct cell_principal_map * next = cell_princ_map;
1905 if ( IsDebuggerPresent() )
1906 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1911 for ( ; next ; next = next->next ) {
1913 KFW_AFS_renew_token_for_cell(next->cell);
1919 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1921 krb5_error_code code = 0;
1922 krb5_context ctx = NULL;
1923 krb5_ccache cc = NULL;
1924 krb5_principal me = NULL;
1925 krb5_principal server = NULL;
1926 krb5_creds my_creds;
1927 krb5_data *realm = NULL;
1929 if (!pkrb5_init_context)
1932 memset(&my_creds, 0, sizeof(krb5_creds));
1937 code = pkrb5_init_context(&ctx);
1938 if (code) goto cleanup;
1944 code = pkrb5_cc_default(ctx, &cc);
1945 if (code) goto cleanup;
1948 code = pkrb5_cc_get_principal(ctx, cc, &me);
1949 if (code) goto cleanup;
1951 realm = krb5_princ_realm(ctx, me);
1953 code = pkrb5_build_principal_ext(ctx, &server,
1954 realm->length,realm->data,
1955 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1956 realm->length,realm->data,
1961 if ( IsDebuggerPresent() ) {
1962 char * cname, *sname;
1963 pkrb5_unparse_name(ctx, me, &cname);
1964 pkrb5_unparse_name(ctx, server, &sname);
1965 OutputDebugString("Renewing credential for client \"");
1966 OutputDebugString(cname);
1967 OutputDebugString("\" and service \"");
1968 OutputDebugString(sname);
1969 OutputDebugString("\"\n");
1970 pkrb5_free_unparsed_name(ctx,cname);
1971 pkrb5_free_unparsed_name(ctx,sname);
1974 my_creds.client = me;
1975 my_creds.server = server;
1977 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1979 if ( IsDebuggerPresent() ) {
1981 StringCbPrintf(message, sizeof(message), "krb5_get_renewed_creds() failed: %d\n", code);
1982 OutputDebugString(message);
1987 code = pkrb5_cc_initialize(ctx, cc, me);
1989 if ( IsDebuggerPresent() ) {
1991 StringCbPrintf(message, sizeof(message), "krb5_cc_initialize() failed: %d\n", code);
1992 OutputDebugString(message);
1997 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1999 if ( IsDebuggerPresent() ) {
2001 StringCbPrintf(message, sizeof(message), "krb5_cc_store_cred() failed: %d\n", code);
2002 OutputDebugString(message);
2008 if (my_creds.client == me)
2009 my_creds.client = 0;
2010 if (my_creds.server == server)
2011 my_creds.server = 0;
2012 pkrb5_free_cred_contents(ctx, &my_creds);
2014 pkrb5_free_principal(ctx, me);
2016 pkrb5_free_principal(ctx, server);
2017 if (cc && (cc != alt_cc))
2018 pkrb5_cc_close(ctx, cc);
2019 if (ctx && (ctx != alt_ctx))
2020 pkrb5_free_context(ctx);
2025 KFW_kinit( krb5_context alt_ctx,
2028 char *principal_name,
2030 krb5_deltat lifetime,
2033 krb5_deltat renew_life,
2038 krb5_error_code code = 0;
2039 krb5_context ctx = NULL;
2040 krb5_ccache cc = NULL;
2041 krb5_principal me = NULL;
2043 krb5_creds my_creds;
2044 krb5_get_init_creds_opt options;
2045 krb5_address ** addrs = NULL;
2046 int i = 0, addr_count = 0;
2048 if (!pkrb5_init_context)
2051 pkrb5_get_init_creds_opt_init(&options);
2052 memset(&my_creds, 0, sizeof(my_creds));
2060 code = pkrb5_init_context(&ctx);
2061 if (code) goto cleanup;
2067 code = pkrb5_cc_default(ctx, &cc);
2068 if (code) goto cleanup;
2071 code = pkrb5_parse_name(ctx, principal_name, &me);
2075 code = pkrb5_unparse_name(ctx, me, &name);
2083 lifetime = pLeash_get_default_lifetime();
2084 #endif /* USE_LEASH */
2091 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2092 pkrb5_get_init_creds_opt_set_forwardable(&options,
2093 forwardable ? 1 : 0);
2094 pkrb5_get_init_creds_opt_set_proxiable(&options,
2096 pkrb5_get_init_creds_opt_set_renew_life(&options,
2099 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2103 // we are going to add the public IP address specified by the user
2104 // to the list provided by the operating system
2105 krb5_address ** local_addrs=NULL;
2108 pkrb5_os_localaddr(ctx, &local_addrs);
2109 while ( local_addrs[i++] );
2112 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2114 pkrb5_free_addresses(ctx, local_addrs);
2117 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2119 while ( local_addrs[i] ) {
2120 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2121 if (addrs[i] == NULL) {
2122 pkrb5_free_addresses(ctx, local_addrs);
2126 addrs[i]->magic = local_addrs[i]->magic;
2127 addrs[i]->addrtype = local_addrs[i]->addrtype;
2128 addrs[i]->length = local_addrs[i]->length;
2129 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2130 if (!addrs[i]->contents) {
2131 pkrb5_free_addresses(ctx, local_addrs);
2135 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2136 local_addrs[i]->length); /* safe */
2139 pkrb5_free_addresses(ctx, local_addrs);
2141 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2142 if (addrs[i] == NULL)
2145 addrs[i]->magic = KV5M_ADDRESS;
2146 addrs[i]->addrtype = AF_INET;
2147 addrs[i]->length = 4;
2148 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2149 if (!addrs[i]->contents)
2152 netIPAddr = htonl(publicIP);
2153 memcpy(addrs[i]->contents,&netIPAddr,4);
2155 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2160 code = pkrb5_get_init_creds_password(ctx,
2163 password, // password
2164 KRB5_prompter, // prompter
2165 hParent, // prompter data
2172 code = pkrb5_cc_initialize(ctx, cc, me);
2176 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2182 for ( i=0;i<addr_count;i++ ) {
2184 if ( addrs[i]->contents )
2185 free(addrs[i]->contents);
2190 if (my_creds.client == me)
2191 my_creds.client = 0;
2192 pkrb5_free_cred_contents(ctx, &my_creds);
2194 pkrb5_free_unparsed_name(ctx, name);
2196 pkrb5_free_principal(ctx, me);
2197 if (cc && (cc != alt_cc))
2198 pkrb5_cc_close(ctx, cc);
2199 if (ctx && (ctx != alt_ctx))
2200 pkrb5_free_context(ctx);
2206 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2208 krb5_context ctx = NULL;
2209 krb5_ccache cc = NULL;
2210 krb5_error_code code;
2212 if (!pkrb5_init_context)
2221 code = pkrb5_init_context(&ctx);
2222 if (code) goto cleanup;
2228 code = pkrb5_cc_default(ctx, &cc);
2229 if (code) goto cleanup;
2232 code = pkrb5_cc_destroy(ctx, cc);
2233 if ( !code ) cc = 0;
2236 if (cc && (cc != alt_cc))
2237 pkrb5_cc_close(ctx, cc);
2238 if (ctx && (ctx != alt_ctx))
2239 pkrb5_free_context(ctx);
2247 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2249 NTSTATUS Status = 0;
2251 TOKEN_STATISTICS Stats;
2257 *ppSessionData = NULL;
2259 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2263 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2264 CloseHandle( TokenHandle );
2268 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2269 if ( FAILED(Status) || !ppSessionData )
2276 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2277 // cache. It validates whether or not it is reasonable to assume that if we
2278 // attempted to retrieve valid tickets we could do so. Microsoft does not
2279 // automatically renew expired tickets. Therefore, the cache could contain
2280 // expired or invalid tickets. Microsoft also caches the user's password
2281 // and will use it to retrieve new TGTs if the cache is empty and tickets
2285 MSLSA_IsKerberosLogon(VOID)
2287 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2288 BOOL Success = FALSE;
2290 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2291 if ( pSessionData->AuthenticationPackage.Buffer ) {
2297 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2298 usLength = (pSessionData->AuthenticationPackage).Length;
2301 StringCbCopyNW( buffer, sizeof(buffer)/sizeof(WCHAR),
2302 usBuffer, usLength);
2303 if ( !lstrcmpW(L"Kerberos",buffer) )
2307 pLsaFreeReturnBuffer(pSessionData);
2311 #endif /* USE_MS2MIT */
2313 static BOOL CALLBACK
2314 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2318 switch ( message ) {
2320 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2322 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2325 for ( i=0; i < mid_cnt ; i++ ) {
2326 if (mid_tb[i].echo == 0)
2327 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2328 else if (mid_tb[i].echo == 2)
2329 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2334 switch ( LOWORD(wParam) ) {
2336 for ( i=0; i < mid_cnt ; i++ ) {
2337 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2338 *mid_tb[i].buf = '\0';
2342 EndDialog(hDialog, LOWORD(wParam));
2350 lpwAlign( LPWORD lpIn )
2354 ul = (ULONG_PTR) lpIn;
2358 return (LPWORD) ul;;
2362 * dialog widths are measured in 1/4 character widths
2363 * dialog height are measured in 1/8 character heights
2367 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2368 char * ptext[], int numlines, int width,
2369 int tb_cnt, struct textField * tb)
2373 LPDLGITEMTEMPLATE lpdit;
2379 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2386 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2388 // Define a dialog box.
2390 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2391 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2392 | DS_SETFOREGROUND | DS_3DLOOK
2393 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2394 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2397 lpdt->cx = 20 + width * 4;
2398 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2400 lpw = (LPWORD) (lpdt + 1);
2401 *lpw++ = 0; // no menu
2402 *lpw++ = 0; // predefined dialog box class (by default)
2404 lpwsz = (LPWSTR) lpw;
2405 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2407 *lpw++ = 8; // font size (points)
2408 lpwsz = (LPWSTR) lpw;
2409 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2413 //-----------------------
2414 // Define an OK button.
2415 //-----------------------
2416 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2417 lpdit = (LPDLGITEMTEMPLATE) lpw;
2418 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2419 lpdit->dwExtendedStyle = 0;
2420 lpdit->x = (lpdt->cx - 14)/4 - 20;
2421 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2424 lpdit->id = IDOK; // OK button identifier
2426 lpw = (LPWORD) (lpdit + 1);
2428 *lpw++ = 0x0080; // button class
2430 lpwsz = (LPWSTR) lpw;
2431 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2433 *lpw++ = 0; // no creation data
2435 //-----------------------
2436 // Define an Cancel button.
2437 //-----------------------
2438 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2439 lpdit = (LPDLGITEMTEMPLATE) lpw;
2440 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2441 lpdit->dwExtendedStyle = 0;
2442 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2443 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2446 lpdit->id = IDCANCEL; // CANCEL button identifier
2448 lpw = (LPWORD) (lpdit + 1);
2450 *lpw++ = 0x0080; // button class
2452 lpwsz = (LPWSTR) lpw;
2453 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2455 *lpw++ = 0; // no creation data
2457 /* Add controls for preface data */
2458 for ( i=0; i<numlines; i++) {
2459 /*-----------------------
2460 * Define a static text control.
2461 *-----------------------*/
2462 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2463 lpdit = (LPDLGITEMTEMPLATE) lpw;
2464 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2465 lpdit->dwExtendedStyle = 0;
2467 lpdit->y = 10 + i * 14;
2468 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2470 lpdit->id = ID_TEXT + i; // text identifier
2472 lpw = (LPWORD) (lpdit + 1);
2474 *lpw++ = 0x0082; // static class
2476 lpwsz = (LPWSTR) lpw;
2477 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2478 -1, lpwsz, 2*width);
2480 *lpw++ = 0; // no creation data
2483 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2484 int len = (int)strlen(tb[i].label);
2489 for ( i=0; i<tb_cnt; i++) {
2491 /*-----------------------
2492 * Define a static text control.
2493 *-----------------------*/
2494 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2495 lpdit = (LPDLGITEMTEMPLATE) lpw;
2496 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2497 lpdit->dwExtendedStyle = 0;
2499 lpdit->y = 10 + (numlines + i + 1) * 14;
2500 lpdit->cx = pwid * 4;
2502 lpdit->id = ID_TEXT + numlines + i; // text identifier
2504 lpw = (LPWORD) (lpdit + 1);
2506 *lpw++ = 0x0082; // static class
2508 lpwsz = (LPWSTR) lpw;
2509 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2512 *lpw++ = 0; // no creation data
2514 /*-----------------------
2515 * Define an edit control.
2516 *-----------------------*/
2517 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2518 lpdit = (LPDLGITEMTEMPLATE) lpw;
2519 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2520 lpdit->dwExtendedStyle = 0;
2521 lpdit->x = 10 + (pwid + 1) * 4;
2522 lpdit->y = 10 + (numlines + i + 1) * 14;
2523 lpdit->cx = (width - (pwid + 1)) * 4;
2525 lpdit->id = ID_MID_TEXT + i; // identifier
2527 lpw = (LPWORD) (lpdit + 1);
2529 *lpw++ = 0x0081; // edit class
2531 lpwsz = (LPWSTR) lpw;
2532 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2535 *lpw++ = 0; // no creation data
2539 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2540 hwndOwner, (DLGPROC) MultiInputDialogProc);
2544 case 0: /* Timeout */
2552 StringCbPrintf(buf, sizeof(buf), "DialogBoxIndirect() failed: %d", GetLastError());
2553 MessageBox(hwndOwner,
2556 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2563 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2565 HINSTANCE hInst = 0;
2569 char * plines[16], *p = preface ? preface : "";
2572 for ( i=0; i<16; i++ )
2575 while (*p && numlines < 16) {
2576 plines[numlines++] = p;
2577 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2578 if ( *p == '\r' && *(p+1) == '\n' ) {
2581 } else if ( *p == '\n' ) {
2584 if ( strlen(plines[numlines-1]) > maxwidth )
2585 maxwidth = (int)strlen(plines[numlines-1]);
2588 for ( i=0;i<n;i++ ) {
2589 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2590 if ( maxwidth < len )
2594 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2597 static krb5_error_code KRB5_CALLCONV
2598 KRB5_prompter( krb5_context context,
2603 krb5_prompt prompts[])
2605 krb5_error_code errcode = 0;
2607 struct textField * tb = NULL;
2608 int len = 0, blen=0, nlen=0;
2609 HWND hParent = (HWND)data;
2612 nlen = (int)strlen(name)+2;
2615 blen = (int)strlen(banner)+2;
2617 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2620 memset(tb,0,sizeof(struct textField) * num_prompts);
2621 for ( i=0; i < num_prompts; i++ ) {
2622 tb[i].buf = prompts[i].reply->data;
2623 tb[i].len = prompts[i].reply->length;
2624 tb[i].label = prompts[i].prompt;
2626 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2629 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2631 for ( i=0; i < num_prompts; i++ )
2632 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2640 for (i = 0; i < num_prompts; i++) {
2641 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2648 KFW_AFS_wait_for_service_start(void)
2653 CurrentState = SERVICE_START_PENDING;
2654 memset(HostName, '\0', sizeof(HostName));
2655 gethostname(HostName, sizeof(HostName));
2657 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2659 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2661 if ( IsDebuggerPresent() ) {
2662 switch ( CurrentState ) {
2663 case SERVICE_STOPPED:
2664 OutputDebugString("SERVICE_STOPPED\n");
2666 case SERVICE_START_PENDING:
2667 OutputDebugString("SERVICE_START_PENDING\n");
2669 case SERVICE_STOP_PENDING:
2670 OutputDebugString("SERVICE_STOP_PENDING\n");
2672 case SERVICE_RUNNING:
2673 OutputDebugString("SERVICE_RUNNING\n");
2675 case SERVICE_CONTINUE_PENDING:
2676 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2678 case SERVICE_PAUSE_PENDING:
2679 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2681 case SERVICE_PAUSED:
2682 OutputDebugString("SERVICE_PAUSED\n");
2685 OutputDebugString("UNKNOWN Service State\n");
2688 if (CurrentState == SERVICE_STOPPED)
2690 if (CurrentState == SERVICE_RUNNING)
2706 memset(HostName, '\0', sizeof(HostName));
2707 gethostname(HostName, sizeof(HostName));
2708 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2710 if (CurrentState != SERVICE_RUNNING)
2713 rc = ktc_ForgetAllTokens();
2719 #define ALLOW_REGISTER 1
2721 ViceIDToUsername(char *username,
2722 char *realm_of_user,
2723 char *realm_of_cell,
2725 struct ktc_principal *aclient,
2726 struct ktc_principal *aserver,
2727 struct ktc_token *atoken)
2729 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2730 static char confdir[512] = { 0 };
2731 #ifdef AFS_ID_TO_NAME
2732 char username_copy[BUFSIZ];
2733 #endif /* AFS_ID_TO_NAME */
2734 long viceId = ANONYMOUSID; /* AFS uid of user */
2736 #ifdef ALLOW_REGISTER
2738 #endif /* ALLOW_REGISTER */
2740 if (confdir[0] == '\0')
2741 cm_GetConfigDir(confdir, sizeof(confdir));
2743 StringCbCopyN( lastcell, sizeof(lastcell),
2744 aserver->cell, sizeof(lastcell) - 1);
2746 if (!pr_Initialize (0, confdir, aserver->cell)) {
2747 char sname[PR_MAXNAMELEN];
2748 StringCbCopyN( sname, sizeof(sname),
2749 username, sizeof(sname) - 1);
2750 status = pr_SNameToId (sname, &viceId);
2755 * This is a crock, but it is Transarc's crock, so
2756 * we have to play along in order to get the
2757 * functionality. The way the afs id is stored is
2758 * as a string in the username field of the token.
2759 * Contrary to what you may think by looking at
2760 * the code for tokens, this hack (AFS ID %d) will
2761 * not work if you change %d to something else.
2765 * This code is taken from cklog -- it lets people
2766 * automatically register with the ptserver in foreign cells
2769 #ifdef ALLOW_REGISTER
2771 if (viceId != ANONYMOUSID) {
2772 #else /* ALLOW_REGISTER */
2773 if ((status == 0) && (viceId != ANONYMOUSID))
2774 #endif /* ALLOW_REGISTER */
2776 #ifdef AFS_ID_TO_NAME
2777 StringCbCopyN( username_copy, sizeof(username_copy),
2778 username, sizeof(username_copy) - 1);
2779 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2780 #endif /* AFS_ID_TO_NAME */
2782 #ifdef ALLOW_REGISTER
2783 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2785 StringCbCopyN( aclient->name, sizeof(aclient->name),
2786 username, sizeof(aclient->name) - 1);
2787 aclient->instance[0] = '\0';
2788 StringCbCopyN( aclient->cell, sizeof(aclient->cell),
2789 realm_of_user, sizeof(aclient->cell) - 1);
2790 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2792 if (status = pr_Initialize(1L, confdir, aserver->cell))
2794 status = pr_CreateUser(username, &id);
2798 #ifdef AFS_ID_TO_NAME
2799 StringCbCopyN( username_copy, sizeof(username_copy),
2800 username, sizeof(username_copy) - 1);
2801 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2802 #endif /* AFS_ID_TO_NAME */
2805 #endif /* ALLOW_REGISTER */
2811 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2812 krb5_error_code code;
2813 krb5_ticket *ticket;
2816 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2818 len = krb5_princ_realm(context, ticket->server)->length;
2819 if (len > destlen - 1)
2822 StringCbCopyN(dest, destlen, krb5_princ_realm(context, ticket->server)->data, len);
2824 pkrb5_free_ticket(context, ticket);
2830 krb5_context alt_ctx,
2835 int lifetime, /* unused parameter */
2843 #endif /* USE_KRB4 */
2844 struct ktc_principal aserver;
2845 struct ktc_principal aclient;
2846 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2847 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2848 char local_cell[CELL_MAXNAMELEN+1];
2849 char Dmycell[CELL_MAXNAMELEN+1];
2850 struct ktc_token atoken;
2851 struct ktc_token btoken;
2852 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2853 char RealmName[128];
2855 char ServiceName[128];
2859 krb5_context ctx = NULL;
2860 krb5_ccache cc = NULL;
2862 krb5_creds * k5creds = NULL;
2863 krb5_error_code code;
2864 krb5_principal client_principal = NULL;
2865 krb5_data * k5data = NULL;
2866 unsigned int i, retry = 0;
2869 memset(HostName, '\0', sizeof(HostName));
2870 gethostname(HostName, sizeof(HostName));
2871 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2872 if ( IsDebuggerPresent() )
2873 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2876 if (CurrentState != SERVICE_RUNNING) {
2877 if ( IsDebuggerPresent() )
2878 OutputDebugString("AFSD Service NOT RUNNING\n");
2882 if (!pkrb5_init_context)
2885 memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
2886 memset(RealmName, '\0', sizeof(RealmName));
2887 memset(CellName, '\0', sizeof(CellName));
2888 memset(ServiceName, '\0', sizeof(ServiceName));
2889 memset(realm_of_user, '\0', sizeof(realm_of_user));
2890 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2891 if (cell && cell[0])
2892 StringCbCopyN( Dmycell, sizeof(Dmycell),
2893 cell, sizeof(Dmycell) - 1);
2895 memset(Dmycell, '\0', sizeof(Dmycell));
2897 // NULL or empty cell returns information on local cell
2898 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2900 // KFW_AFS_error(rc, "get_cellconfig()");
2907 code = pkrb5_init_context(&ctx);
2908 if (code) goto cleanup;
2914 code = pkrb5_cc_default(ctx, &cc);
2915 if (code) goto skip_krb5_init;
2918 memset(&increds, 0, sizeof(increds));
2920 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2922 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2924 OutputDebugString("Principal Not Found for ccache\n");
2926 goto skip_krb5_init;
2929 if (!KFW_accept_dotted_usernames()) {
2930 /* look for client principals which cannot be distinguished
2931 * from Kerberos 4 multi-component principal names
2933 k5data = krb5_princ_component(ctx,client_principal,0);
2934 for ( i=0; i<k5data->length; i++ ) {
2935 if ( k5data->data[i] == '.' )
2938 if (i != k5data->length)
2940 OutputDebugString("Illegal Principal name contains dot in first component\n");
2941 rc = KRB5KRB_ERR_GENERIC;
2946 i = krb5_princ_realm(ctx, client_principal)->length;
2949 StringCbCopyN( realm_of_user, sizeof(realm_of_user),
2950 krb5_princ_realm(ctx, client_principal)->data, i);
2955 if ( !try_krb5 || !realm_of_user[0] ) {
2956 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2965 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
2966 afs_realm_of_cell(ctx, &ak_cellconfig),
2967 sizeof(realm_of_cell) - 1);
2969 if (strlen(service) == 0)
2970 StringCbCopy( ServiceName, sizeof(ServiceName), "afs");
2972 StringCbCopyN( ServiceName, sizeof(ServiceName),
2973 service, sizeof(ServiceName) - 1);
2975 if (strlen(cell) == 0)
2976 StringCbCopyN( CellName, sizeof(CellName),
2977 local_cell, sizeof(CellName) - 1);
2979 StringCbCopyN( CellName, sizeof(CellName),
2980 cell, sizeof(CellName) - 1);
2982 /* This is for Kerberos v4 only */
2983 if (strlen(realm) == 0)
2984 StringCbCopyN( RealmName, sizeof(RealmName),
2985 realm_of_cell, sizeof(RealmName) - 1);
2987 StringCbCopyN( RealmName, sizeof(RealmName),
2988 realm, sizeof(RealmName) - 1);
2990 memset(&creds, '\0', sizeof(creds));
2994 code = KRB5KRB_ERR_GENERIC;
2997 increds.client = client_principal;
2998 increds.times.endtime = 0;
2999 /* Ask for DES since that is what V4 understands */
3000 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
3002 /* If there was a specific realm we are supposed to try
3005 if (strlen(realm) != 0) {
3006 /* service/cell@REALM */
3008 code = pkrb5_build_principal(ctx, &increds.server,
3014 if ( IsDebuggerPresent() ) {
3015 char * cname, *sname;
3016 pkrb5_unparse_name(ctx, increds.client, &cname);
3017 pkrb5_unparse_name(ctx, increds.server, &sname);
3018 OutputDebugString("Getting tickets for \"");
3019 OutputDebugString(cname);
3020 OutputDebugString("\" and service \"");
3021 OutputDebugString(sname);
3022 OutputDebugString("\"\n");
3023 pkrb5_free_unparsed_name(ctx,cname);
3024 pkrb5_free_unparsed_name(ctx,sname);
3028 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3030 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3031 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3032 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3033 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3034 /* Or service@REALM */
3035 pkrb5_free_principal(ctx,increds.server);
3037 code = pkrb5_build_principal(ctx, &increds.server,
3043 if ( IsDebuggerPresent() ) {
3044 char * cname, *sname;
3045 pkrb5_unparse_name(ctx, increds.client, &cname);
3046 pkrb5_unparse_name(ctx, increds.server, &sname);
3047 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3048 OutputDebugString("Trying again: getting tickets for \"");
3049 OutputDebugString(cname);
3050 OutputDebugString("\" and service \"");
3051 OutputDebugString(sname);
3052 OutputDebugString("\"\n");
3053 pkrb5_free_unparsed_name(ctx,cname);
3054 pkrb5_free_unparsed_name(ctx,sname);
3058 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3062 /* we have a local realm for the cell */
3063 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3064 realm, sizeof(realm_of_cell) - 1);
3067 /* Otherwise, first try service/cell@CLIENT_REALM */
3068 if (code = pkrb5_build_principal(ctx, &increds.server,
3069 (int)strlen(realm_of_user),
3078 if ( IsDebuggerPresent() ) {
3079 char * cname, *sname;
3080 pkrb5_unparse_name(ctx, increds.client, &cname);
3081 pkrb5_unparse_name(ctx, increds.server, &sname);
3082 OutputDebugString("Getting tickets for \"");
3083 OutputDebugString(cname);
3084 OutputDebugString("\" and service \"");
3085 OutputDebugString(sname);
3086 OutputDebugString("\"\n");
3087 pkrb5_free_unparsed_name(ctx,cname);
3088 pkrb5_free_unparsed_name(ctx,sname);
3091 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3093 /* The client's realm is a local realm for the cell.
3094 * Save it so that later the pts registration will not
3097 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3098 realm_of_user, sizeof(realm_of_cell) - 1);
3101 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3102 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3103 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3104 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
3105 strcmp(realm_of_user, realm_of_cell)) {
3106 /* Then service/cell@CELL_REALM */
3107 pkrb5_free_principal(ctx,increds.server);
3109 code = pkrb5_build_principal(ctx, &increds.server,
3110 (int)strlen(realm_of_cell),
3115 if ( IsDebuggerPresent() ) {
3116 char * cname, *sname;
3117 pkrb5_unparse_name(ctx, increds.client, &cname);
3118 pkrb5_unparse_name(ctx, increds.server, &sname);
3119 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3120 OutputDebugString("Trying again: getting tickets for \"");
3121 OutputDebugString(cname);
3122 OutputDebugString("\" and service \"");
3123 OutputDebugString(sname);
3124 OutputDebugString("\"\n");
3125 pkrb5_free_unparsed_name(ctx,cname);
3126 pkrb5_free_unparsed_name(ctx,sname);
3130 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3132 if (!code && !strlen(realm_of_cell))
3133 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3136 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3137 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3138 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3139 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3140 /* Finally service@CELL_REALM */
3141 pkrb5_free_principal(ctx,increds.server);
3143 code = pkrb5_build_principal(ctx, &increds.server,
3144 (int)strlen(realm_of_cell),
3149 if ( IsDebuggerPresent() ) {
3150 char * cname, *sname;
3151 pkrb5_unparse_name(ctx, increds.client, &cname);
3152 pkrb5_unparse_name(ctx, increds.server, &sname);
3153 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3154 OutputDebugString("Trying again: getting tickets for \"");
3155 OutputDebugString(cname);
3156 OutputDebugString("\" and service \"");
3157 OutputDebugString(sname);
3158 OutputDebugString("\"\n");
3159 pkrb5_free_unparsed_name(ctx,cname);
3160 pkrb5_free_unparsed_name(ctx,sname);
3164 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3165 if (!code && !strlen(realm_of_cell))
3166 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3171 if ( IsDebuggerPresent() ) {
3173 StringCbPrintf(message, sizeof(message), "krb5_get_credentials returns: %d\n", code);
3174 OutputDebugString(message);
3180 /* This code inserts the entire K5 ticket into the token
3181 * No need to perform a krb524 translation which is
3182 * commented out in the code below
3184 if (KFW_use_krb524() ||
3185 k5creds->ticket.length > MAXKTCTICKETLEN)
3188 memset(&aserver, '\0', sizeof(aserver));
3189 StringCbCopyN( aserver.name, sizeof(aserver.name),
3190 ServiceName, sizeof(aserver.name) - 1);
3191 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
3192 CellName, sizeof(aserver.cell) - 1);
3194 memset(&atoken, '\0', sizeof(atoken));
3195 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3196 atoken.startTime = k5creds->times.starttime;
3197 atoken.endTime = k5creds->times.endtime;
3198 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3199 atoken.ticketLen = k5creds->ticket.length;
3200 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3203 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3204 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3205 if ( rc == KTC_NOCM && retry < 20 ) {
3208 goto retry_gettoken5;
3213 if (atoken.kvno == btoken.kvno &&
3214 atoken.ticketLen == btoken.ticketLen &&
3215 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3216 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3218 /* Success - Nothing to do */
3222 // * Reset the "aclient" structure before we call ktc_SetToken.
3223 // * This structure was first set by the ktc_GetToken call when
3224 // * we were comparing whether identical tokens already existed.
3226 len = min(k5creds->client->data[0].length, sizeof(aclient.name) - 1);
3227 StringCbCopyN( aclient.name, sizeof(aclient.name),
3228 k5creds->client->data[0].data, len);
3230 if ( k5creds->client->length > 1 ) {
3231 StringCbCat( aclient.name, sizeof(aclient.name), ".");
3232 len = min(k5creds->client->data[1].length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3233 StringCbCatN( aclient.name, sizeof(aclient.name),
3234 k5creds->client->data[1].data, len);
3236 aclient.instance[0] = '\0';
3238 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3239 realm_of_cell, sizeof(aclient.cell) - 1);
3241 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3242 /* For Khimaira, always append the realm name */
3243 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3244 StringCbCat( aclient.name, sizeof(aclient.name), "@");
3245 len = min(k5creds->client->realm.length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3246 StringCbCatN( aclient.name, sizeof(aclient.name), k5creds->client->realm.data, len);
3249 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3250 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3251 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3252 &aclient, &aserver, &atoken);
3255 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3256 smbname, sizeof(aclient.smbname) - 1);
3258 aclient.smbname[0] = '\0';
3261 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3263 goto cleanup; /* We have successfully inserted the token */
3269 /* Otherwise, the ticket could have been too large so try to
3270 * convert using the krb524d running with the KDC
3272 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3273 pkrb5_free_creds(ctx, k5creds);
3275 if ( IsDebuggerPresent() ) {
3277 StringCbPrintf(message, sizeof(message), "krb524_convert_creds_kdc returns: %d\n", code);
3278 OutputDebugString(message);
3283 #endif /* USE_KRB524 */
3287 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3288 if (code == NO_TKT_FIL) {
3289 // if the problem is that we have no krb4 tickets
3290 // do not attempt to continue
3293 if (code != KSUCCESS)
3294 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3296 if (code != KSUCCESS)
3298 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3300 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3305 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3307 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3322 memset(&aserver, '\0', sizeof(aserver));
3323 StringCbCopyN( aserver.name, sizeof(aserver.name), ServiceName, sizeof(aserver.name) - 1);
3324 StringCbCopyN( aserver.cell, sizeof(aserver.cell), CellName, sizeof(aserver.cell) - 1);
3326 memset(&atoken, '\0', sizeof(atoken));
3327 atoken.kvno = creds.kvno;
3328 atoken.startTime = creds.issue_date;
3329 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3330 memcpy(&atoken.sessionKey, creds.session, 8);
3331 atoken.ticketLen = creds.ticket_st.length;
3332 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3335 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3336 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3337 if ( rc == KTC_NOCM && retry < 20 ) {
3340 goto retry_gettoken;
3342 KFW_AFS_error(rc, "ktc_GetToken()");
3347 if (atoken.kvno == btoken.kvno &&
3348 atoken.ticketLen == btoken.ticketLen &&
3349 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3350 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3355 // * Reset the "aclient" structure before we call ktc_SetToken.
3356 // * This structure was first set by the ktc_GetToken call when
3357 // * we were comparing whether identical tokens already existed.
3359 StringCbCopyN( aclient.name, sizeof(aclient.name), creds.pname, sizeof(aclient.name) - 1);
3362 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3363 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3365 aclient.instance[0] = '\0';
3367 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3368 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3369 aclient.name[MAXKTCREALMLEN-1] = '\0';
3371 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3372 CellName, sizeof(aclient.cell) - 1);
3374 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3375 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3376 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3377 &aclient, &aserver, &atoken);
3380 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3381 smbname, sizeof(aclient.smbname) - 1);
3383 aclient.smbname[0] = '\0';
3386 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3388 KFW_AFS_error(rc, "ktc_SetToken()");
3394 if (client_principal)
3395 pkrb5_free_principal(ctx,client_principal);
3396 /* increds.client == client_principal */
3398 pkrb5_free_principal(ctx,increds.server);
3399 if (cc && (cc != alt_cc))
3400 pkrb5_cc_close(ctx, cc);
3401 if (ctx && (ctx != alt_ctx))
3402 pkrb5_free_context(ctx);
3403 if (ak_cellconfig.linkedCell)
3404 free(ak_cellconfig.linkedCell);
3406 return(rc? rc : code);
3409 /**************************************/
3410 /* afs_realm_of_cell(): */
3411 /**************************************/
3413 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3415 static char krbrlm[REALM_SZ+1]="";
3416 char ** realmlist=NULL;
3422 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3423 if ( !r && realmlist && realmlist[0] ) {
3424 StringCbCopyN( krbrlm, sizeof(krbrlm),
3425 realmlist[0], sizeof(krbrlm) - 1);
3426 pkrb5_free_host_realm(ctx, realmlist);
3432 char *t = cellconfig->name;
3437 if (islower(c)) c=toupper(c);
3445 /**************************************/
3446 /* KFW_AFS_get_cellconfig(): */
3447 /**************************************/
3449 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3452 char newcell[CELL_MAXNAMELEN+1];
3453 char linkedcell[CELL_MAXNAMELEN+1]="";
3455 local_cell[0] = (char)0;
3456 memset(cellconfig, 0, sizeof(*cellconfig));
3458 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3459 if (rc = cm_GetRootCellName(local_cell))
3464 if (strlen(cell) == 0)
3465 strcpy(cell, local_cell);
3467 rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3468 if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
3469 rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3472 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3476 StringCbCopyN( cellconfig->name, sizeof(cellconfig->name),
3477 newcell, sizeof(cellconfig->name) - 1);
3479 cellconfig->linkedCell = strdup(linkedcell);
3484 /**************************************/
3485 /* get_cellconfig_callback(): */
3486 /**************************************/
3488 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
3490 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3492 cc->hostAddr[cc->numServers] = *addrp;
3493 StringCbCopyN( cc->hostName[cc->numServers], sizeof(cc->hostName[cc->numServers]),
3494 namep, sizeof(cc->hostName[cc->numServers]) - 1);
3500 /**************************************/
3501 /* KFW_AFS_error(): */
3502 /**************************************/
3504 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3507 const char *errText;
3509 // Using AFS defines as error messages for now, until Transarc
3510 // gets back to me with "string" translations of each of these
3512 if (rc == KTC_ERROR)
3513 errText = "KTC_ERROR";
3514 else if (rc == KTC_TOOBIG)
3515 errText = "KTC_TOOBIG";
3516 else if (rc == KTC_INVAL)
3517 errText = "KTC_INVAL";
3518 else if (rc == KTC_NOENT)
3519 errText = "KTC_NOENT";
3520 else if (rc == KTC_PIOCTLFAIL)
3521 errText = "KTC_PIOCTLFAIL";
3522 else if (rc == KTC_NOPIOCTL)
3523 errText = "KTC_NOPIOCTL";
3524 else if (rc == KTC_NOCELL)
3525 errText = "KTC_NOCELL";
3526 else if (rc == KTC_NOCM)
3527 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3529 errText = "Unknown error!";
3531 StringCbPrintf(message, sizeof(message), "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3533 if ( IsDebuggerPresent() ) {
3534 OutputDebugString(message);
3535 OutputDebugString("\n");
3537 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3543 LPSTR lpszMachineName,
3544 LPSTR lpszServiceName,
3545 DWORD *lpdwCurrentState)
3548 SC_HANDLE schSCManager = NULL;
3549 SC_HANDLE schService = NULL;
3550 DWORD fdwDesiredAccess = 0;
3551 SERVICE_STATUS ssServiceStatus = {0};
3554 *lpdwCurrentState = 0;
3556 fdwDesiredAccess = GENERIC_READ;
3558 schSCManager = OpenSCManager(lpszMachineName,
3562 if(schSCManager == NULL)
3564 hr = GetLastError();
3568 schService = OpenService(schSCManager,
3572 if(schService == NULL)
3574 hr = GetLastError();
3578 fRet = QueryServiceStatus(schService,
3583 hr = GetLastError();
3587 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3591 CloseServiceHandle(schService);
3592 CloseServiceHandle(schSCManager);
3605 for (n = 0; fi[n].func_ptr_var; n++)
3606 *(fi[n].func_ptr_var) = 0;
3607 if (h) FreeLibrary(h);
3612 const char* dll_name,
3614 HINSTANCE* ph, // [out, optional] - DLL handle
3615 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3616 int cleanup, // cleanup function pointers and unload on error
3617 int go_on, // continue loading even if some functions cannot be loaded
3618 int silent // do not pop-up a system dialog if DLL cannot be loaded
3627 if (pindex) *pindex = -1;
3629 for (n = 0; fi[n].func_ptr_var; n++)
3630 *(fi[n].func_ptr_var) = 0;
3633 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3634 h = LoadLibrary(dll_name);
3642 for (i = 0; (go_on || !error) && (i < n); i++)
3644 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3650 *(fi[i].func_ptr_var) = p;
3653 if (pindex) *pindex = last_i;
3654 if (error && cleanup && !go_on) {
3655 for (i = 0; i < n; i++) {
3656 *(fi[i].func_ptr_var) = 0;
3662 if (error) return 0;
3666 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3668 krb5_context ctx = NULL;
3669 krb5_ccache cc = NULL;
3670 krb5_error_code code;
3672 const char * realm = NULL;
3673 krb5_principal principal = NULL;
3674 char * pname = NULL;
3675 char password[PROBE_PASSWORD_LEN+1];
3676 BOOL serverReachable = 0;
3678 if (!pkrb5_init_context)
3681 code = pkrb5_init_context(&ctx);
3682 if (code) goto cleanup;
3685 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3687 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3688 realm, PROBE_USERNAME, NULL, NULL);
3689 if ( code ) goto cleanup;
3691 code = KFW_get_ccache(ctx, principal, &cc);
3692 if ( code ) goto cleanup;
3694 code = pkrb5_unparse_name(ctx, principal, &pname);
3695 if ( code ) goto cleanup;
3697 pwdata.data = password;
3698 pwdata.length = PROBE_PASSWORD_LEN;
3699 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3702 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3705 password[PROBE_PASSWORD_LEN] = '\0';
3707 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3717 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3718 case KRB5KDC_ERR_CLIENT_REVOKED:
3719 case KRB5KDC_ERR_CLIENT_NOTYET:
3720 case KRB5KDC_ERR_PREAUTH_FAILED:
3721 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3722 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3723 serverReachable = TRUE;
3726 serverReachable = FALSE;
3731 pkrb5_free_unparsed_name(ctx,pname);
3733 pkrb5_free_principal(ctx,principal);
3735 pkrb5_cc_close(ctx,cc);
3737 pkrb5_free_context(ctx);
3739 return serverReachable;
3743 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
3745 krb5_context ctx = NULL;
3746 krb5_error_code code;
3747 krb5_ccache mslsa_ccache=NULL;
3748 krb5_principal princ = NULL;
3749 char * pname = NULL;
3752 if (!KFW_is_available())
3755 if (code = pkrb5_init_context(&ctx))
3758 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3761 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3764 if (code = pkrb5_unparse_name(ctx, princ, &pname))
3767 if ( strlen(pname) < *dwSize ) {
3768 StringCbCopyN(szUser, *dwSize, pname, (*dwSize) - 1);
3771 *dwSize = (DWORD)strlen(pname);
3775 pkrb5_free_unparsed_name(ctx, pname);
3778 pkrb5_free_principal(ctx, princ);
3781 pkrb5_cc_close(ctx, mslsa_ccache);
3784 pkrb5_free_context(ctx);
3789 KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
3791 // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
3792 PSID pSystemSID = NULL;
3793 DWORD SystemSIDlength = 0, UserSIDlength = 0;
3794 PACL ccacheACL = NULL;
3795 DWORD ccacheACLlength = 0;
3796 PTOKEN_USER pTokenUser = NULL;
3805 /* Get System SID */
3806 if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
3812 SystemSIDlength = GetLengthSid(pSystemSID);
3813 ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
3814 + SystemSIDlength - sizeof(DWORD);
3817 if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
3819 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
3820 pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
3822 GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
3827 UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
3829 ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
3834 ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
3839 InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
3840 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3841 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3844 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3845 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3846 pTokenUser->User.Sid);
3847 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3848 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3853 gle = GetLastError();
3854 if (gle != ERROR_NO_TOKEN)
3857 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3858 OWNER_SECURITY_INFORMATION,
3859 pTokenUser->User.Sid,
3863 gle = GetLastError();
3864 if (gle != ERROR_NO_TOKEN)
3868 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3869 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3874 gle = GetLastError();
3875 if (gle != ERROR_NO_TOKEN)
3882 LocalFree(pSystemSID);
3884 LocalFree(pTokenUser);
3886 LocalFree(ccacheACL);
3891 KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
3894 DWORD dwSize = size-1; /* leave room for nul */
3897 if (!hUserToken || !newfilename || size <= 0)
3900 *newfilename = '\0';
3902 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
3903 if ( !dwLen || dwLen > dwSize )
3904 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
3905 if ( !dwLen || dwLen > dwSize )
3908 newfilename[dwSize] = '\0';
3913 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
3915 char filename[MAX_PATH] = "";
3917 char cachename[MAX_PATH + 8] = "FILE:";
3918 krb5_context ctx = NULL;
3919 krb5_error_code code;
3920 krb5_principal princ = NULL;
3921 krb5_ccache cc = NULL;
3922 krb5_ccache ncc = NULL;
3924 if (!pkrb5_init_context || !user || !szLogonId)
3927 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
3928 if ( count > sizeof(filename) || count == 0 ) {
3929 GetWindowsDirectory(filename, sizeof(filename));
3932 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
3935 StringCbCat( filename, sizeof(filename), "\\");
3936 StringCbCat( filename, sizeof(filename), szLogonId);
3938 StringCbCat( cachename, sizeof(cachename), filename);
3940 DeleteFile(filename);
3942 code = pkrb5_init_context(&ctx);
3943 if (code) goto cleanup;
3945 code = pkrb5_parse_name(ctx, user, &princ);
3946 if (code) goto cleanup;
3948 code = KFW_get_ccache(ctx, princ, &cc);
3949 if (code) goto cleanup;
3951 code = pkrb5_cc_resolve(ctx, cachename, &ncc);
3952 if (code) goto cleanup;
3954 code = pkrb5_cc_initialize(ctx, ncc, princ);
3955 if (code) goto cleanup;
3957 code = KFW_AFS_set_file_cache_dacl(filename, NULL);
3958 if (code) goto cleanup;
3960 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3964 pkrb5_cc_close(ctx, cc);
3968 pkrb5_cc_close(ctx, ncc);
3972 pkrb5_free_principal(ctx, princ);
3977 pkrb5_free_context(ctx);
3981 KFW_AFS_copy_file_cache_to_default_cache(char * filename)
3983 char cachename[MAX_PATH + 8] = "FILE:";
3984 krb5_context ctx = NULL;
3985 krb5_error_code code;
3986 krb5_principal princ = NULL;
3987 krb5_ccache cc = NULL;
3988 krb5_ccache ncc = NULL;
3991 if (!pkrb5_init_context || !filename)
3994 if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
3997 code = pkrb5_init_context(&ctx);
4000 StringCbCat( cachename, sizeof(cachename), filename);
4002 code = pkrb5_cc_resolve(ctx, cachename, &cc);
4003 if (code) goto cleanup;
4005 code = pkrb5_cc_get_principal(ctx, cc, &princ);
4007 code = pkrb5_cc_default(ctx, &ncc);
4009 code = pkrb5_cc_initialize(ctx, ncc, princ);
4012 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
4015 pkrb5_cc_close(ctx, ncc);
4019 retval=0; /* success */
4023 pkrb5_cc_close(ctx, cc);
4027 DeleteFile(filename);
4030 pkrb5_free_principal(ctx, princ);
4035 pkrb5_free_context(ctx);
4040 /* We are including this
4042 /* Ticket lifetime. This defines the table used to lookup lifetime for the
4043 fixed part of rande of the one byte lifetime field. Values less than 0x80
4044 are intrpreted as the number of 5 minute intervals. Values from 0x80 to
4045 0xBF should be looked up in this table. The value of 0x80 is the same using
4046 both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days.
4047 The intervening values of have a fixed ratio of roughly 1.06914. The value
4048 oxFF is defined to mean a ticket has no expiration time. This should be
4049 used advisedly since individual servers may impose defacto upperbounds on
4050 ticket lifetimes. */
4052 #define TKTLIFENUMFIXED 64
4053 #define TKTLIFEMINFIXED 0x80
4054 #define TKTLIFEMAXFIXED 0xBF
4055 #define TKTLIFENOEXPIRE 0xFF
4056 #define MAXTKTLIFETIME (30*24*3600) /* 30 days */
4058 static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
4059 38400, /* 10.67 hours, 0.44 days */
4060 41055, /* 11.40 hours, 0.48 days */
4061 43894, /* 12.19 hours, 0.51 days */
4062 46929, /* 13.04 hours, 0.54 days */
4063 50174, /* 13.94 hours, 0.58 days */
4064 53643, /* 14.90 hours, 0.62 days */
4065 57352, /* 15.93 hours, 0.66 days */
4066 61318, /* 17.03 hours, 0.71 days */
4067 65558, /* 18.21 hours, 0.76 days */
4068 70091, /* 19.47 hours, 0.81 days */
4069 74937, /* 20.82 hours, 0.87 days */
4070 80119, /* 22.26 hours, 0.93 days */
4071 85658, /* 23.79 hours, 0.99 days */
4072 91581, /* 25.44 hours, 1.06 days */
4073 97914, /* 27.20 hours, 1.13 days */
4074 104684, /* 29.08 hours, 1.21 days */
4075 111922, /* 31.09 hours, 1.30 days */
4076 119661, /* 33.24 hours, 1.38 days */
4077 127935, /* 35.54 hours, 1.48 days */
4078 136781, /* 37.99 hours, 1.58 days */
4079 146239, /* 40.62 hours, 1.69 days */
4080 156350, /* 43.43 hours, 1.81 days */
4081 167161, /* 46.43 hours, 1.93 days */
4082 178720, /* 49.64 hours, 2.07 days */
4083 191077, /* 53.08 hours, 2.21 days */
4084 204289, /* 56.75 hours, 2.36 days */
4085 218415, /* 60.67 hours, 2.53 days */
4086 233517, /* 64.87 hours, 2.70 days */
4087 249664, /* 69.35 hours, 2.89 days */
4088 266926, /* 74.15 hours, 3.09 days */
4089 285383, /* 79.27 hours, 3.30 days */
4090 305116, /* 84.75 hours, 3.53 days */
4091 326213, /* 90.61 hours, 3.78 days */
4092 348769, /* 96.88 hours, 4.04 days */
4093 372885, /* 103.58 hours, 4.32 days */
4094 398668, /* 110.74 hours, 4.61 days */
4095 426234, /* 118.40 hours, 4.93 days */
4096 455705, /* 126.58 hours, 5.27 days */
4097 487215, /* 135.34 hours, 5.64 days */
4098 520904, /* 144.70 hours, 6.03 days */
4099 556921, /* 154.70 hours, 6.45 days */
4100 595430, /* 165.40 hours, 6.89 days */
4101 636601, /* 176.83 hours, 7.37 days */
4102 680618, /* 189.06 hours, 7.88 days */
4103 727680, /* 202.13 hours, 8.42 days */
4104 777995, /* 216.11 hours, 9.00 days */
4105 831789, /* 231.05 hours, 9.63 days */
4106 889303, /* 247.03 hours, 10.29 days */
4107 950794, /* 264.11 hours, 11.00 days */
4108 1016537, /* 282.37 hours, 11.77 days */
4109 1086825, /* 301.90 hours, 12.58 days */
4110 1161973, /* 322.77 hours, 13.45 days */
4111 1242318, /* 345.09 hours, 14.38 days */
4112 1328218, /* 368.95 hours, 15.37 days */
4113 1420057, /* 394.46 hours, 16.44 days */
4114 1518247, /* 421.74 hours, 17.57 days */
4115 1623226, /* 450.90 hours, 18.79 days */
4116 1735464, /* 482.07 hours, 20.09 days */
4117 1855462, /* 515.41 hours, 21.48 days */
4118 1983758, /* 551.04 hours, 22.96 days */
4119 2120925, /* 589.15 hours, 24.55 days */
4120 2267576, /* 629.88 hours, 26.25 days */
4121 2424367, /* 673.44 hours, 28.06 days */
4123 }; /* 720.00 hours, 30.00 days */
4125 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
4126 * returns the corresponding end time. There are four simple cases to be
4127 * handled. The first is a life of 0xff, meaning no expiration, and results in
4128 * an end time of 0xffffffff. The second is when life is less than the values
4129 * covered by the table. In this case, the end time is the start time plus the
4130 * number of 5 minute intervals specified by life. The third case returns
4131 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
4132 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
4133 * table to extract the lifetime in seconds, which is added to start to produce
4137 life_to_time(afs_uint32 start, unsigned char life)
4141 if (life == TKTLIFENOEXPIRE)
4143 if (life < TKTLIFEMINFIXED)
4144 return start + life * 5 * 60;
4145 if (life > TKTLIFEMAXFIXED)
4146 return start + MAXTKTLIFETIME;
4147 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
4148 return start + realLife;
4151 /* time_to_life - takes start and end times for the ticket and returns a
4152 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
4153 * lifetimes above 127*5minutes. First, the special case of (end ==
4154 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
4155 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
4156 * less than the first table entry are handled by rounding the requested
4157 * lifetime *up* to the next 5 minute interval. The final step is to search
4158 * the table for the smallest entry *greater than or equal* to the requested
4159 * entry. The actual code is prepared to handle the case where the table is
4160 * unordered but that it an unnecessary frill. */
4162 static unsigned char
4163 time_to_life(afs_uint32 start, afs_uint32 end)
4165 int lifetime = end - start;
4169 if (end == NEVERDATE)
4170 return TKTLIFENOEXPIRE;
4171 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
4173 if (lifetime < tkt_lifetimes[0])
4174 return (lifetime + 5 * 60 - 1) / (5 * 60);
4176 best = MAXKTCTICKETLIFETIME;
4177 for (i = 0; i < TKTLIFENUMFIXED; i++)
4178 if (tkt_lifetimes[i] >= lifetime) {
4179 int diff = tkt_lifetimes[i] - lifetime;
4187 return best_i + TKTLIFEMINFIXED;