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 /* Prevent inclusion of des.h to avoid conflicts with des types */
67 #define NO_DES_H_INCLUDE
70 #include <afs/ptserver.h>
71 #include <afs/ptuser.h>
73 #include <WINNT\afsreg.h>
77 #include "afskfw-int.h"
85 * TIMING _____________________________________________________________________
89 #define cminREMIND_TEST 1 // test every minute for expired creds
90 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
91 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
92 #define cminMINLIFE 30 // minimum life of Kerberos creds
94 #define c100ns1SECOND (LONGLONG)10000000
95 #define cmsec1SECOND 1000
96 #define cmsec1MINUTE 60000
97 #define csec1MINUTE 60
99 /* Function Pointer Declarations for Delayed Loading */
101 DECL_FUNC_PTR(cc_initialize);
102 DECL_FUNC_PTR(cc_shutdown);
103 DECL_FUNC_PTR(cc_get_NC_info);
104 DECL_FUNC_PTR(cc_free_NC_info);
108 DECL_FUNC_PTR(Leash_get_default_lifetime);
109 DECL_FUNC_PTR(Leash_get_default_forwardable);
110 DECL_FUNC_PTR(Leash_get_default_renew_till);
111 DECL_FUNC_PTR(Leash_get_default_noaddresses);
112 DECL_FUNC_PTR(Leash_get_default_proxiable);
113 DECL_FUNC_PTR(Leash_get_default_publicip);
114 DECL_FUNC_PTR(Leash_get_default_use_krb4);
115 DECL_FUNC_PTR(Leash_get_default_life_min);
116 DECL_FUNC_PTR(Leash_get_default_life_max);
117 DECL_FUNC_PTR(Leash_get_default_renew_min);
118 DECL_FUNC_PTR(Leash_get_default_renew_max);
119 DECL_FUNC_PTR(Leash_get_default_renewable);
120 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
124 DECL_FUNC_PTR(krb5_change_password);
125 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
126 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
127 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
128 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
129 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
130 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
131 DECL_FUNC_PTR(krb5_get_init_creds_password);
132 DECL_FUNC_PTR(krb5_build_principal_ext);
133 DECL_FUNC_PTR(krb5_cc_get_name);
134 DECL_FUNC_PTR(krb5_cc_resolve);
135 DECL_FUNC_PTR(krb5_cc_default);
136 DECL_FUNC_PTR(krb5_cc_default_name);
137 DECL_FUNC_PTR(krb5_cc_set_default_name);
138 DECL_FUNC_PTR(krb5_cc_initialize);
139 DECL_FUNC_PTR(krb5_cc_destroy);
140 DECL_FUNC_PTR(krb5_cc_close);
141 DECL_FUNC_PTR(krb5_cc_store_cred);
142 DECL_FUNC_PTR(krb5_cc_copy_creds);
143 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
144 DECL_FUNC_PTR(krb5_cc_get_principal);
145 DECL_FUNC_PTR(krb5_cc_start_seq_get);
146 DECL_FUNC_PTR(krb5_cc_next_cred);
147 DECL_FUNC_PTR(krb5_cc_end_seq_get);
148 DECL_FUNC_PTR(krb5_cc_remove_cred);
149 DECL_FUNC_PTR(krb5_cc_set_flags);
150 DECL_FUNC_PTR(krb5_cc_get_type);
151 DECL_FUNC_PTR(krb5_free_context);
152 DECL_FUNC_PTR(krb5_free_cred_contents);
153 DECL_FUNC_PTR(krb5_free_principal);
154 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
155 DECL_FUNC_PTR(krb5_init_context);
156 DECL_FUNC_PTR(krb5_parse_name);
157 DECL_FUNC_PTR(krb5_timeofday);
158 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
159 DECL_FUNC_PTR(krb5_unparse_name);
160 DECL_FUNC_PTR(krb5_get_credentials);
161 DECL_FUNC_PTR(krb5_mk_req);
162 DECL_FUNC_PTR(krb5_sname_to_principal);
163 DECL_FUNC_PTR(krb5_get_credentials_renew);
164 DECL_FUNC_PTR(krb5_free_data);
165 DECL_FUNC_PTR(krb5_free_data_contents);
166 DECL_FUNC_PTR(krb5_free_unparsed_name);
167 DECL_FUNC_PTR(krb5_os_localaddr);
168 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
169 DECL_FUNC_PTR(krb5_copy_data);
170 DECL_FUNC_PTR(krb5_free_creds);
171 DECL_FUNC_PTR(krb5_build_principal);
172 DECL_FUNC_PTR(krb5_get_renewed_creds);
173 DECL_FUNC_PTR(krb5_get_default_config_files);
174 DECL_FUNC_PTR(krb5_free_config_files);
175 DECL_FUNC_PTR(krb5_get_default_realm);
176 DECL_FUNC_PTR(krb5_free_default_realm);
177 DECL_FUNC_PTR(krb5_free_ticket);
178 DECL_FUNC_PTR(krb5_decode_ticket);
179 DECL_FUNC_PTR(krb5_get_host_realm);
180 DECL_FUNC_PTR(krb5_free_host_realm);
181 DECL_FUNC_PTR(krb5_free_addresses);
182 DECL_FUNC_PTR(krb5_c_random_make_octets);
184 // Krb5 KFW 3.2 functions
185 DECL_FUNC_PTR(krb5_get_error_message);
186 DECL_FUNC_PTR(krb5_free_error_message);
190 DECL_FUNC_PTR(krb524_init_ets);
191 DECL_FUNC_PTR(krb524_convert_creds_kdc);
196 DECL_FUNC_PTR(krb_get_cred);
197 DECL_FUNC_PTR(tkt_string);
198 DECL_FUNC_PTR(krb_get_tf_realm);
199 DECL_FUNC_PTR(krb_mk_req);
203 DECL_FUNC_PTR(com_err);
204 DECL_FUNC_PTR(error_message);
207 DECL_FUNC_PTR(profile_init);
208 DECL_FUNC_PTR(profile_release);
209 DECL_FUNC_PTR(profile_get_subsection_names);
210 DECL_FUNC_PTR(profile_free_list);
211 DECL_FUNC_PTR(profile_get_string);
212 DECL_FUNC_PTR(profile_release_string);
215 DECL_FUNC_PTR(OpenSCManagerA);
216 DECL_FUNC_PTR(OpenServiceA);
217 DECL_FUNC_PTR(QueryServiceStatus);
218 DECL_FUNC_PTR(CloseServiceHandle);
220 DECL_FUNC_PTR(LsaNtStatusToWinError);
221 #endif /* USE_MS2MIT */
225 DECL_FUNC_PTR(LsaConnectUntrusted);
226 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
227 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
228 DECL_FUNC_PTR(LsaFreeReturnBuffer);
229 DECL_FUNC_PTR(LsaGetLogonSessionData);
230 #endif /* USE_MS2MIT */
233 FUNC_INFO ccapi_fi[] = {
234 MAKE_FUNC_INFO(cc_initialize),
235 MAKE_FUNC_INFO(cc_shutdown),
236 MAKE_FUNC_INFO(cc_get_NC_info),
237 MAKE_FUNC_INFO(cc_free_NC_info),
242 FUNC_INFO leash_fi[] = {
243 MAKE_FUNC_INFO(Leash_get_default_lifetime),
244 MAKE_FUNC_INFO(Leash_get_default_renew_till),
245 MAKE_FUNC_INFO(Leash_get_default_forwardable),
246 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
247 MAKE_FUNC_INFO(Leash_get_default_proxiable),
248 MAKE_FUNC_INFO(Leash_get_default_publicip),
249 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
250 MAKE_FUNC_INFO(Leash_get_default_life_min),
251 MAKE_FUNC_INFO(Leash_get_default_life_max),
252 MAKE_FUNC_INFO(Leash_get_default_renew_min),
253 MAKE_FUNC_INFO(Leash_get_default_renew_max),
254 MAKE_FUNC_INFO(Leash_get_default_renewable),
258 FUNC_INFO leash_opt_fi[] = {
259 MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
264 FUNC_INFO k5_fi[] = {
265 MAKE_FUNC_INFO(krb5_change_password),
266 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
267 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
268 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
269 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
270 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
271 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
272 MAKE_FUNC_INFO(krb5_get_init_creds_password),
273 MAKE_FUNC_INFO(krb5_build_principal_ext),
274 MAKE_FUNC_INFO(krb5_cc_get_name),
275 MAKE_FUNC_INFO(krb5_cc_resolve),
276 MAKE_FUNC_INFO(krb5_cc_default),
277 MAKE_FUNC_INFO(krb5_cc_default_name),
278 MAKE_FUNC_INFO(krb5_cc_set_default_name),
279 MAKE_FUNC_INFO(krb5_cc_initialize),
280 MAKE_FUNC_INFO(krb5_cc_destroy),
281 MAKE_FUNC_INFO(krb5_cc_close),
282 MAKE_FUNC_INFO(krb5_cc_copy_creds),
283 MAKE_FUNC_INFO(krb5_cc_store_cred),
284 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
285 MAKE_FUNC_INFO(krb5_cc_get_principal),
286 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
287 MAKE_FUNC_INFO(krb5_cc_next_cred),
288 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
289 MAKE_FUNC_INFO(krb5_cc_remove_cred),
290 MAKE_FUNC_INFO(krb5_cc_set_flags),
291 MAKE_FUNC_INFO(krb5_cc_get_type),
292 MAKE_FUNC_INFO(krb5_free_context),
293 MAKE_FUNC_INFO(krb5_free_cred_contents),
294 MAKE_FUNC_INFO(krb5_free_principal),
295 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
296 MAKE_FUNC_INFO(krb5_init_context),
297 MAKE_FUNC_INFO(krb5_parse_name),
298 MAKE_FUNC_INFO(krb5_timeofday),
299 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
300 MAKE_FUNC_INFO(krb5_unparse_name),
301 MAKE_FUNC_INFO(krb5_get_credentials),
302 MAKE_FUNC_INFO(krb5_mk_req),
303 MAKE_FUNC_INFO(krb5_sname_to_principal),
304 MAKE_FUNC_INFO(krb5_get_credentials_renew),
305 MAKE_FUNC_INFO(krb5_free_data),
306 MAKE_FUNC_INFO(krb5_free_data_contents),
307 MAKE_FUNC_INFO(krb5_free_unparsed_name),
308 MAKE_FUNC_INFO(krb5_os_localaddr),
309 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
310 MAKE_FUNC_INFO(krb5_copy_data),
311 MAKE_FUNC_INFO(krb5_free_creds),
312 MAKE_FUNC_INFO(krb5_build_principal),
313 MAKE_FUNC_INFO(krb5_get_renewed_creds),
314 MAKE_FUNC_INFO(krb5_free_addresses),
315 MAKE_FUNC_INFO(krb5_get_default_config_files),
316 MAKE_FUNC_INFO(krb5_free_config_files),
317 MAKE_FUNC_INFO(krb5_get_default_realm),
318 MAKE_FUNC_INFO(krb5_free_default_realm),
319 MAKE_FUNC_INFO(krb5_free_ticket),
320 MAKE_FUNC_INFO(krb5_decode_ticket),
321 MAKE_FUNC_INFO(krb5_get_host_realm),
322 MAKE_FUNC_INFO(krb5_free_host_realm),
323 MAKE_FUNC_INFO(krb5_free_addresses),
324 MAKE_FUNC_INFO(krb5_c_random_make_octets),
328 FUNC_INFO k5_kfw_32_fi[] = {
329 MAKE_FUNC_INFO(krb5_get_error_message),
330 MAKE_FUNC_INFO(krb5_free_error_message),
335 FUNC_INFO k4_fi[] = {
336 MAKE_FUNC_INFO(krb_get_cred),
337 MAKE_FUNC_INFO(krb_get_tf_realm),
338 MAKE_FUNC_INFO(krb_mk_req),
339 MAKE_FUNC_INFO(tkt_string),
345 FUNC_INFO k524_fi[] = {
346 MAKE_FUNC_INFO(krb524_init_ets),
347 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
352 FUNC_INFO profile_fi[] = {
353 MAKE_FUNC_INFO(profile_init),
354 MAKE_FUNC_INFO(profile_release),
355 MAKE_FUNC_INFO(profile_get_subsection_names),
356 MAKE_FUNC_INFO(profile_free_list),
357 MAKE_FUNC_INFO(profile_get_string),
358 MAKE_FUNC_INFO(profile_release_string),
362 FUNC_INFO ce_fi[] = {
363 MAKE_FUNC_INFO(com_err),
364 MAKE_FUNC_INFO(error_message),
368 FUNC_INFO service_fi[] = {
369 MAKE_FUNC_INFO(OpenSCManagerA),
370 MAKE_FUNC_INFO(OpenServiceA),
371 MAKE_FUNC_INFO(QueryServiceStatus),
372 MAKE_FUNC_INFO(CloseServiceHandle),
374 MAKE_FUNC_INFO(LsaNtStatusToWinError),
375 #endif /* USE_MS2MIT */
380 FUNC_INFO lsa_fi[] = {
381 MAKE_FUNC_INFO(LsaConnectUntrusted),
382 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
383 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
384 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
385 MAKE_FUNC_INFO(LsaGetLogonSessionData),
388 #endif /* USE_MS2MIT */
390 /* Static Prototypes */
391 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
392 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *, unsigned short);
393 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
394 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
395 void *data, const char *name, const char *banner, int num_prompts,
396 krb5_prompt prompts[]);
399 /* Static Declarations */
400 static int inited = 0;
401 static int mid_cnt = 0;
402 static struct textField * mid_tb = NULL;
403 static HINSTANCE hKrb5 = 0;
404 static HINSTANCE hKrb5_kfw_32 = 0;
406 static HINSTANCE hKrb4 = 0;
407 #endif /* USE_KRB4 */
409 static HINSTANCE hKrb524 = 0;
412 static HINSTANCE hSecur32 = 0;
413 #endif /* USE_MS2MIT */
414 static HINSTANCE hAdvApi32 = 0;
415 static HINSTANCE hComErr = 0;
416 static HINSTANCE hService = 0;
417 static HINSTANCE hProfile = 0;
419 static HINSTANCE hLeash = 0;
420 static HINSTANCE hLeashOpt = 0;
422 static HINSTANCE hCCAPI = 0;
423 static struct principal_ccache_data * princ_cc_data = NULL;
424 static struct cell_principal_map * cell_princ_map = NULL;
429 static int inited = 0;
432 char mutexName[MAX_PATH];
433 HANDLE hMutex = NULL;
435 StringCbPrintf( mutexName, sizeof(mutexName), "AFS KFW Init pid=%d", getpid());
437 hMutex = CreateMutex( NULL, TRUE, mutexName );
438 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
439 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
445 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
446 LoadFuncs(KRB5_DLL, k5_kfw_32_fi, &hKrb5_kfw_32, 0, 1, 0, 0);
447 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
448 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
450 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
451 #endif /* USE_KRB4 */
452 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
454 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
455 #endif /* USE_MS2MIT */
457 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
460 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
461 LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
463 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
465 if ( KFW_is_available() ) {
466 char rootcell[CELL_MAXNAMELEN+1];
468 KFW_import_windows_lsa();
469 #endif /* USE_MS2MIT */
470 KFW_import_ccache_data();
471 KFW_AFS_renew_expiring_tokens();
473 /* WIN32 NOTE: no way to get max chars */
474 if (!cm_GetRootCellName(rootcell))
475 KFW_AFS_renew_token_for_cell(rootcell);
478 ReleaseMutex(hMutex);
488 FreeLibrary(hLeashOpt);
494 FreeLibrary(hKrb524);
500 FreeLibrary(hSecur32);
501 #endif /* USE_MS2MIT */
503 FreeLibrary(hService);
505 FreeLibrary(hComErr);
507 FreeLibrary(hProfile);
511 #endif /* USE_KRB4 */
515 FreeLibrary(hKrb5_kfw_32);
518 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
521 static int init = TRUE;
522 static int bIsWow64 = FALSE;
526 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
528 hModule = GetModuleHandle(TEXT("kernel32"));
530 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
532 if (NULL != fnIsWow64Process)
534 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
536 // on error, assume FALSE.
537 // in other words, do nothing.
540 FreeLibrary(hModule);
548 KFW_accept_dotted_usernames(void)
554 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
555 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
556 if (code == ERROR_SUCCESS) {
558 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
559 (BYTE *) &value, &len);
560 RegCloseKey(parmKey);
562 if (code != ERROR_SUCCESS) {
563 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
564 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
565 if (code == ERROR_SUCCESS) {
567 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
568 (BYTE *) &value, &len);
569 RegCloseKey (parmKey);
583 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
584 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
585 if (code == ERROR_SUCCESS) {
586 len = sizeof(use524);
587 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
588 (BYTE *) &use524, &len);
589 RegCloseKey(parmKey);
591 if (code != ERROR_SUCCESS) {
592 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
593 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
594 if (code == ERROR_SUCCESS) {
595 len = sizeof(use524);
596 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
597 (BYTE *) &use524, &len);
598 RegCloseKey (parmKey);
605 KFW_is_available(void)
611 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
612 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
613 if (code == ERROR_SUCCESS) {
614 len = sizeof(enableKFW);
615 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
616 (BYTE *) &enableKFW, &len);
617 RegCloseKey (parmKey);
620 if (code != ERROR_SUCCESS) {
621 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
622 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
623 if (code == ERROR_SUCCESS) {
624 len = sizeof(enableKFW);
625 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
626 (BYTE *) &enableKFW, &len);
627 RegCloseKey (parmKey);
635 if ( hKrb5 && hComErr && hService &&
638 #endif /* USE_MS2MIT */
651 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
652 int FreeContextFlag, krb5_context * ctx,
657 int krb5Error = ((int)(rc & 255));
669 if (pkrb5_get_error_message)
670 errText = pkrb5_get_error_message(ctx, rc);
672 errText = perror_message(rc);
673 StringCbPrintf(message, sizeof(message),
674 "%s\n(Kerberos error %ld)\n\n%s failed",
678 if (pkrb5_free_error_message)
679 pkrb5_free_error_message(ctx, (char *)errText);
681 if ( IsDebuggerPresent() )
682 OutputDebugString(message);
684 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
687 if (FreeContextFlag == 1)
689 if (ctx && *ctx != NULL)
691 if (cache && *cache != NULL) {
692 pkrb5_cc_close(*ctx, *cache);
696 pkrb5_free_context(*ctx);
705 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
707 struct principal_ccache_data * next = princ_cc_data;
708 krb5_principal principal = 0;
710 const char * ccname = NULL;
711 const char * cctype = NULL;
712 char * ccfullname = NULL;
713 krb5_error_code code = 0;
714 krb5_error_code cc_code = 0;
720 if (ctx == 0 || cc == 0)
723 code = pkrb5_cc_get_principal(ctx, cc, &principal);
726 code = pkrb5_unparse_name(ctx, principal, &pname);
727 if ( code ) goto cleanup;
729 ccname = pkrb5_cc_get_name(ctx, cc);
730 if (!ccname) goto cleanup;
732 cctype = pkrb5_cc_get_type(ctx, cc);
733 if (!cctype) goto cleanup;
735 ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
736 if (!ccfullname) goto cleanup;
738 StringCbPrintf(ccfullname, sizeof(ccfullname), "%s:%s", cctype, ccname);
740 // Search the existing list to see if we have a match
742 for ( ; next ; next = next->next ) {
743 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
748 // If not, match add a new node to the beginning of the list and assign init it
750 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
751 next->next = princ_cc_data;
752 princ_cc_data = next;
753 next->principal = _strdup(pname);
754 next->ccache_name = ccfullname;
756 next->from_lsa = lsa;
758 next->expiration_time = 0;
762 flags = 0; // turn off OPENCLOSE mode
763 code = pkrb5_cc_set_flags(ctx, cc, flags);
764 if ( code ) goto cleanup;
766 code = pkrb5_timeofday(ctx, &now);
768 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
770 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
771 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
773 // we found the ticket we are looking for
774 // check validity of timestamp
775 // We add a 5 minutes fudge factor to compensate for potential
776 // clock skew errors between the KDC and client OS
778 valid = ((creds.times.starttime > 0) &&
779 now >= (creds.times.starttime - 300) &&
780 now < (creds.times.endtime + 300) &&
781 !(creds.ticket_flags & TKT_FLG_INVALID));
783 if ( next->from_lsa) {
785 next->expiration_time = creds.times.endtime;
787 } else if ( valid ) {
789 next->expiration_time = creds.times.endtime;
790 next->renew = (creds.times.renew_till > creds.times.endtime) &&
791 (creds.ticket_flags & TKT_FLG_RENEWABLE);
794 next->expiration_time = 0;
798 pkrb5_free_cred_contents(ctx, &creds);
799 cc_code = KRB5_CC_END;
802 pkrb5_free_cred_contents(ctx, &creds);
805 if (cc_code == KRB5_CC_END) {
806 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
807 if (code) goto cleanup;
811 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
812 code = pkrb5_cc_set_flags(ctx, cc, flags);
817 pkrb5_free_unparsed_name(ctx,pname);
819 pkrb5_free_principal(ctx,principal);
823 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
825 struct principal_ccache_data * next = princ_cc_data;
826 char * response = NULL;
828 if ( !principal || !ccache )
832 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
834 // we always want to prefer the MS Kerberos LSA cache or
835 // the cache afscreds created specifically for the principal
836 // if the current entry is either one, drop the previous find
837 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
840 response = _strdup(next->ccache_name);
841 // MS Kerberos LSA is our best option so use it and quit
842 if ( next->from_lsa )
856 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
858 struct principal_ccache_data ** next = &princ_cc_data;
860 if ( !pname && !ccname )
864 if ( !strcmp((*next)->principal,pname) ||
865 !strcmp((*next)->ccache_name,ccname) ) {
867 free((*next)->principal);
868 free((*next)->ccache_name);
870 (*next) = (*next)->next;
877 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
879 struct cell_principal_map * next = cell_princ_map;
881 // Search the existing list to see if we have a match
883 for ( ; next ; next = next->next ) {
884 if ( !strcmp(next->cell, cell) ) {
885 if ( !strcmp(next->principal,pname) ) {
886 next->active = active;
889 // OpenAFS currently has a restriction of one active token per cell
890 // Therefore, whenever we update the table with a new active cell we
891 // must mark all of the other principal to cell entries as inactive.
899 // If not, match add a new node to the beginning of the list and assign init it
901 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
902 next->next = cell_princ_map;
903 cell_princ_map = next;
904 next->principal = _strdup(pname);
905 next->cell = _strdup(cell);
906 next->active = active;
911 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
913 struct cell_principal_map ** next = &cell_princ_map;
915 if ( !pname && !cell )
919 if ( !strcmp((*next)->principal,pname) ||
920 !strcmp((*next)->cell,cell) ) {
922 free((*next)->principal);
925 (*next) = (*next)->next;
931 // Returns (if possible) a principal which has been known in
932 // the past to have been used to obtain tokens for the specified
934 // TODO: Attempt to return one which has not yet expired by checking
935 // the principal/ccache data
937 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
939 struct cell_principal_map * next_map = cell_princ_map;
940 const char * princ = NULL;
947 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
950 next_map = next_map->next;
953 if ( !principals || !count )
956 *principals = (char **) malloc(sizeof(char *) * count);
957 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
959 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
960 (*principals)[i++] = _strdup(next_map->principal);
967 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
970 struct cell_principal_map * next_map = cell_princ_map;
971 const char * princ = NULL;
977 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
980 next_map = next_map->next;
986 *cells = (char **) malloc(sizeof(char *) * count);
987 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
989 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
990 (*cells)[i++] = _strdup(next_map->cell);
996 /* Given a principal return an existing ccache or create one and return */
998 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
1000 krb5_context ctx = NULL;
1001 char * pname = NULL;
1002 char * ccname = NULL;
1003 krb5_error_code code;
1005 if (!pkrb5_init_context)
1011 code = pkrb5_init_context(&ctx);
1012 if (code) goto cleanup;
1016 code = pkrb5_unparse_name(ctx, principal, &pname);
1017 if (code) goto cleanup;
1019 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
1020 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
1021 size_t len = strlen(pname) + 5;
1022 ccname = (char *)malloc(len);
1023 StringCbPrintf(ccname, len, "API:%s", pname);
1025 code = pkrb5_cc_resolve(ctx, ccname, cc);
1027 code = pkrb5_cc_default(ctx, cc);
1028 if (code) goto cleanup;
1035 pkrb5_free_unparsed_name(ctx,pname);
1036 if (ctx && (ctx != alt_ctx))
1037 pkrb5_free_context(ctx);
1042 // Import Microsoft Credentials into a new MIT ccache
1044 KFW_import_windows_lsa(void)
1046 krb5_context ctx = NULL;
1047 krb5_ccache cc = NULL;
1048 krb5_principal princ = NULL;
1049 char * pname = NULL;
1050 krb5_data * princ_realm;
1051 krb5_error_code code;
1052 char cell[128]="", realm[128]="", *def_realm = 0;
1054 DWORD dwMsLsaImport;
1056 if (!pkrb5_init_context)
1059 code = pkrb5_init_context(&ctx);
1060 if (code) goto cleanup;
1062 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
1063 if (code) goto cleanup;
1065 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
1067 code = pkrb5_cc_get_principal(ctx, cc, &princ);
1068 if ( code ) goto cleanup;
1070 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
1071 switch ( dwMsLsaImport ) {
1072 case 0: /* do not import */
1074 case 1: /* always import */
1076 case 2: { /* matching realm */
1077 char ms_realm[128] = "", *r;
1080 for ( r=ms_realm, j=0; j<krb5_princ_realm(ctx, princ)->length; r++, j++ ) {
1081 *r = krb5_princ_realm(ctx, princ)->data[j];
1085 if (code = pkrb5_get_default_realm(ctx, &def_realm))
1088 if (strcmp(def_realm, ms_realm))
1096 code = pkrb5_unparse_name(ctx,princ,&pname);
1097 if ( code ) goto cleanup;
1099 princ_realm = krb5_princ_realm(ctx, princ);
1100 for ( i=0; i<princ_realm->length; i++ ) {
1101 realm[i] = princ_realm->data[i];
1102 cell[i] = tolower(princ_realm->data[i]);
1107 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
1108 if ( IsDebuggerPresent() ) {
1110 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1111 OutputDebugString(message);
1113 if ( code ) goto cleanup;
1115 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1119 pkrb5_free_unparsed_name(ctx,pname);
1121 pkrb5_free_principal(ctx,princ);
1123 pkrb5_free_default_realm(ctx, def_realm);
1125 pkrb5_cc_close(ctx,cc);
1127 pkrb5_free_context(ctx);
1129 #endif /* USE_MS2MIT */
1131 // If there are existing MIT credentials, copy them to a new
1132 // ccache named after the principal
1134 // Enumerate all existing MIT ccaches and construct entries
1135 // in the principal_ccache table
1137 // Enumerate all existing AFS Tokens and construct entries
1138 // in the cell_principal table
1140 KFW_import_ccache_data(void)
1142 krb5_context ctx = NULL;
1143 krb5_ccache cc = NULL;
1144 krb5_principal principal = NULL;
1146 krb5_error_code code;
1147 krb5_error_code cc_code;
1149 apiCB * cc_ctx = NULL;
1150 struct _infoNC ** pNCi = NULL;
1153 if ( !pcc_initialize )
1156 if ( IsDebuggerPresent() )
1157 OutputDebugString("KFW_import_ccache_data()\n");
1159 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1160 if (code) goto cleanup;
1162 code = pcc_get_NC_info(cc_ctx, &pNCi);
1163 if (code) goto cleanup;
1165 code = pkrb5_init_context(&ctx);
1166 if (code) goto cleanup;
1168 for ( i=0; pNCi[i]; i++ ) {
1169 if ( pNCi[i]->vers != CC_CRED_V5 )
1171 if ( IsDebuggerPresent() ) {
1172 OutputDebugString("Principal: ");
1173 OutputDebugString(pNCi[i]->principal);
1174 OutputDebugString(" in ccache ");
1175 OutputDebugString(pNCi[i]->name);
1176 OutputDebugString("\n");
1178 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1179 && strcmp(pNCi[i]->name,LSA_CCNAME)
1182 for ( j=0; pNCi[j]; j++ ) {
1183 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1189 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1190 if (code) goto loop_cleanup;
1193 krb5_ccache oldcc = 0;
1195 if ( IsDebuggerPresent() )
1196 OutputDebugString("copying ccache data to new ccache\n");
1198 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1199 if (code) goto loop_cleanup;
1200 code = pkrb5_cc_initialize(ctx, cc, principal);
1201 if (code) goto loop_cleanup;
1203 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1204 if (code) goto loop_cleanup;
1205 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1207 code = pkrb5_cc_close(ctx,cc);
1209 code = pkrb5_cc_close(ctx,oldcc);
1211 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1214 code = pkrb5_cc_close(ctx,oldcc);
1217 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1218 if (code) goto loop_cleanup;
1221 flags = 0; // turn off OPENCLOSE mode
1222 code = pkrb5_cc_set_flags(ctx, cc, flags);
1223 if ( code ) goto cleanup;
1225 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1227 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1229 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1230 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1231 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1232 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1233 if ( sname && cell && !strcmp("afs",sname->data) ) {
1234 struct ktc_principal aserver;
1235 struct ktc_principal aclient;
1236 struct ktc_token atoken;
1239 if ( IsDebuggerPresent() ) {
1240 OutputDebugString("Found AFS ticket: ");
1241 OutputDebugString(sname->data);
1243 OutputDebugString("/");
1244 OutputDebugString(cell->data);
1246 OutputDebugString("@");
1247 OutputDebugString(realm->data);
1248 OutputDebugString("\n");
1251 memset(&aserver, '\0', sizeof(aserver));
1252 StringCbCopyN( aserver.name, sizeof(aserver.name),
1253 sname->data, sizeof(aserver.name) - 1);
1254 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
1255 cell->data, sizeof(aserver.cell) - 1);
1257 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1259 // Found a token in AFS Client Server which matches
1260 char pname[128], *p, *q;
1261 for ( p=pname, q=aclient.name; *q; p++, q++)
1263 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1267 if ( IsDebuggerPresent() ) {
1268 OutputDebugString("Found AFS token: ");
1269 OutputDebugString(pname);
1270 OutputDebugString("\n");
1273 if ( strcmp(pname,pNCi[i]->principal) )
1275 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1277 // Attempt to import it
1278 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1280 if ( IsDebuggerPresent() ) {
1281 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1284 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data,
1288 pLeash_get_default_lifetime(),
1289 #endif /* USE_LEASH */
1291 if ( IsDebuggerPresent() ) {
1293 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1294 OutputDebugString(message);
1297 } else if ( IsDebuggerPresent() ) {
1298 OutputDebugString("Found ticket: ");
1299 OutputDebugString(sname->data);
1300 if ( cell && cell->data ) {
1301 OutputDebugString("/");
1302 OutputDebugString(cell->data);
1304 OutputDebugString("@");
1305 OutputDebugString(realm->data);
1306 OutputDebugString("\n");
1308 pkrb5_free_cred_contents(ctx, &creds);
1311 if (cc_code == KRB5_CC_END) {
1312 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1313 if (cc_code) goto loop_cleanup;
1317 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1318 code = pkrb5_cc_set_flags(ctx, cc, flags);
1320 pkrb5_cc_close(ctx,cc);
1324 pkrb5_free_principal(ctx,principal);
1331 pkrb5_free_context(ctx);
1333 pcc_free_NC_info(cc_ctx, &pNCi);
1335 pcc_shutdown(&cc_ctx);
1340 KFW_AFS_get_cred( char * username,
1347 static char reason[1024]="";
1348 krb5_context ctx = NULL;
1349 krb5_ccache cc = NULL;
1350 char * realm = NULL, * userrealm = NULL;
1351 krb5_principal principal = NULL;
1352 char * pname = NULL;
1353 krb5_error_code code;
1354 char local_cell[CELL_MAXNAMELEN+1];
1355 char **cells = NULL;
1357 struct afsconf_cell cellconfig;
1360 if (!pkrb5_init_context)
1363 if ( IsDebuggerPresent() ) {
1364 OutputDebugString("KFW_AFS_get_cred for token ");
1365 OutputDebugString(username);
1366 OutputDebugString(" in cell ");
1367 OutputDebugString(cell);
1368 OutputDebugString("\n");
1371 memset(&cellconfig, 0, sizeof(cellconfig));
1373 code = pkrb5_init_context(&ctx);
1374 if ( code ) goto cleanup;
1376 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1377 if ( code ) goto cleanup;
1379 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1381 userrealm = strchr(username,'@');
1383 pname = strdup(username);
1384 if (!KFW_accept_dotted_usernames()) {
1385 userrealm = strchr(pname, '@');
1388 /* handle kerberos iv notation */
1389 while ( dot = strchr(pname,'.') ) {
1395 size_t len = strlen(username) + strlen(realm) + 2;
1396 pname = malloc(len);
1397 if (pname == NULL) {
1398 code = KRB5KRB_ERR_GENERIC;
1401 StringCbCopy(pname, len, username);
1403 if (!KFW_accept_dotted_usernames()) {
1404 /* handle kerberos iv notation */
1405 while ( dot = strchr(pname,'.') ) {
1409 StringCbCat( pname, len, "@");
1410 StringCbCat( pname, len, realm);
1412 if ( IsDebuggerPresent() ) {
1413 OutputDebugString("Realm: ");
1414 OutputDebugString(realm);
1415 OutputDebugString("\n");
1418 code = pkrb5_parse_name(ctx, pname, &principal);
1419 if ( code ) goto cleanup;
1421 code = KFW_get_ccache(ctx, principal, &cc);
1422 if ( code ) goto cleanup;
1424 if ( lifetime == 0 )
1428 lifetime = pLeash_get_default_lifetime();
1431 if ( password && password[0] ) {
1432 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1437 1, /* forwardable */
1438 0, /* not proxiable */
1440 1, /* noaddresses */
1441 0 /* no public ip */
1443 pLeash_get_default_forwardable(),
1444 pLeash_get_default_proxiable(),
1445 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1446 pLeash_get_default_noaddresses(),
1447 pLeash_get_default_publicip()
1448 #endif /* USE_LEASH */
1451 if ( IsDebuggerPresent() ) {
1453 StringCbPrintf(message, sizeof(message), "KFW_kinit() returns: %d\n", code);
1454 OutputDebugString(message);
1456 if ( code ) goto cleanup;
1458 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1461 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1462 if ( IsDebuggerPresent() ) {
1464 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1465 OutputDebugString(message);
1467 if ( code ) goto cleanup;
1469 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1471 // Attempt to obtain new tokens for other cells supported by the same
1473 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1474 if ( cell_count > 1 ) {
1475 while ( cell_count-- ) {
1476 if ( strcmp(cells[cell_count],cell) ) {
1477 if ( IsDebuggerPresent() ) {
1479 StringCbPrintf(message, sizeof(message),
1480 "found another cell for the same principal: %s\n", cell);
1481 OutputDebugString(message);
1484 if (cellconfig.linkedCell) {
1485 free(cellconfig.linkedCell);
1486 cellconfig.linkedCell = NULL;
1488 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1489 if ( code ) continue;
1491 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1492 if ( IsDebuggerPresent() ) {
1493 OutputDebugString("Realm: ");
1494 OutputDebugString(realm);
1495 OutputDebugString("\n");
1498 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1499 if ( IsDebuggerPresent() ) {
1501 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1502 OutputDebugString(message);
1505 free(cells[cell_count]);
1508 } else if ( cell_count == 1 ) {
1517 pkrb5_cc_close(ctx, cc);
1518 if ( cellconfig.linkedCell )
1519 free(cellconfig.linkedCell);
1521 if ( code && reasonP ) {
1522 if (pkrb5_get_error_message) {
1523 char *msg = pkrb5_get_error_message(ctx, code);
1524 StringCbCopyN( reason, sizeof(reason),
1525 msg, sizeof(reason) - 1);
1527 pkrb5_free_error_message(ctx, msg);
1529 *reasonP = perror_message(code);
1536 KFW_AFS_destroy_tickets_for_cell(char * cell)
1538 krb5_context ctx = NULL;
1539 krb5_error_code code;
1541 char ** principals = NULL;
1543 if (!pkrb5_init_context)
1546 if ( IsDebuggerPresent() ) {
1547 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1548 OutputDebugString(cell);
1549 OutputDebugString("\n");
1552 code = pkrb5_init_context(&ctx);
1555 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1557 krb5_principal princ = 0;
1561 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1562 if ( cell_count > 1 ) {
1563 // TODO - What we really should do here is verify whether or not any of the
1564 // other cells which use this principal to obtain its credentials actually
1565 // have valid tokens or not. If they are currently using these credentials
1566 // we will skip them. For the time being we assume that if there is an active
1567 // map in the table that they are actively being used.
1571 code = pkrb5_parse_name(ctx, principals[count], &princ);
1572 if (code) goto loop_cleanup;
1574 code = KFW_get_ccache(ctx, princ, &cc);
1575 if (code) goto loop_cleanup;
1577 code = pkrb5_cc_destroy(ctx, cc);
1582 pkrb5_cc_close(ctx, cc);
1586 pkrb5_free_principal(ctx, princ);
1590 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1591 free(principals[count]);
1596 pkrb5_free_context(ctx);
1601 KFW_AFS_destroy_tickets_for_principal(char * user)
1603 krb5_context ctx = NULL;
1604 krb5_error_code code;
1606 char ** cells = NULL;
1607 krb5_principal princ = NULL;
1608 krb5_ccache cc = NULL;
1610 if (!pkrb5_init_context)
1613 if ( IsDebuggerPresent() ) {
1614 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1615 OutputDebugString(user);
1616 OutputDebugString("\n");
1619 code = pkrb5_init_context(&ctx);
1622 code = pkrb5_parse_name(ctx, user, &princ);
1623 if (code) goto loop_cleanup;
1625 code = KFW_get_ccache(ctx, princ, &cc);
1626 if (code) goto loop_cleanup;
1628 code = pkrb5_cc_destroy(ctx, cc);
1633 pkrb5_cc_close(ctx, cc);
1637 pkrb5_free_principal(ctx, princ);
1641 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1644 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1651 pkrb5_free_context(ctx);
1656 KFW_AFS_renew_expiring_tokens(void)
1658 krb5_error_code code = 0;
1659 krb5_context ctx = NULL;
1660 krb5_ccache cc = NULL;
1662 struct principal_ccache_data * pcc_next = princ_cc_data;
1665 const char * realm = NULL;
1666 char local_cell[CELL_MAXNAMELEN+1]="";
1667 struct afsconf_cell cellconfig;
1669 if (!pkrb5_init_context)
1672 if ( pcc_next == NULL ) // nothing to do
1675 if ( IsDebuggerPresent() ) {
1676 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1679 memset(&cellconfig, 0, sizeof(cellconfig));
1681 code = pkrb5_init_context(&ctx);
1682 if (code) goto cleanup;
1684 code = pkrb5_timeofday(ctx, &now);
1685 if (code) goto cleanup;
1687 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1688 if ( pcc_next->expired )
1691 if ( now >= (pcc_next->expiration_time) ) {
1692 if ( !pcc_next->from_lsa ) {
1693 pcc_next->expired = 1;
1698 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1699 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1702 code = KFW_renew(ctx,cc);
1704 if ( code && pcc_next->from_lsa)
1706 #endif /* USE_MS2MIT */
1709 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1710 if (code) goto loop_cleanup;
1712 // Attempt to obtain new tokens for other cells supported by the same
1714 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1715 if ( cell_count > 0 ) {
1716 while ( cell_count-- ) {
1717 if ( IsDebuggerPresent() ) {
1718 OutputDebugString("Cell: ");
1719 OutputDebugString(cells[cell_count]);
1720 OutputDebugString("\n");
1722 if (cellconfig.linkedCell) {
1723 free(cellconfig.linkedCell);
1724 cellconfig.linkedCell = NULL;
1726 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1727 if ( code ) continue;
1728 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1729 if ( IsDebuggerPresent() ) {
1730 OutputDebugString("Realm: ");
1731 OutputDebugString(realm);
1732 OutputDebugString("\n");
1734 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1735 if ( IsDebuggerPresent() ) {
1737 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1738 OutputDebugString(message);
1740 free(cells[cell_count]);
1748 pkrb5_cc_close(ctx,cc);
1755 pkrb5_cc_close(ctx,cc);
1757 pkrb5_free_context(ctx);
1758 if (cellconfig.linkedCell)
1759 free(cellconfig.linkedCell);
1766 KFW_AFS_renew_token_for_cell(char * cell)
1768 krb5_error_code code = 0;
1769 krb5_context ctx = NULL;
1771 char ** principals = NULL;
1773 if (!pkrb5_init_context)
1776 if ( IsDebuggerPresent() ) {
1777 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1778 OutputDebugString(cell);
1779 OutputDebugString("\n");
1782 code = pkrb5_init_context(&ctx);
1783 if (code) goto cleanup;
1785 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1787 // We know we must have a credential somewhere since we are
1788 // trying to renew a token
1790 KFW_import_ccache_data();
1791 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1794 krb5_principal princ = 0;
1795 krb5_principal service = 0;
1797 krb5_creds mcreds, creds;
1798 #endif /* COMMENT */
1800 const char * realm = NULL;
1801 struct afsconf_cell cellconfig;
1802 char local_cell[CELL_MAXNAMELEN+1];
1804 memset(&cellconfig, 0, sizeof(cellconfig));
1807 code = pkrb5_parse_name(ctx, principals[count], &princ);
1808 if (code) goto loop_cleanup;
1810 code = KFW_get_ccache(ctx, princ, &cc);
1811 if (code) goto loop_cleanup;
1813 if (cellconfig.linkedCell) {
1814 free(cellconfig.linkedCell);
1815 cellconfig.linkedCell = NULL;
1817 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1818 if ( code ) goto loop_cleanup;
1820 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1821 if ( IsDebuggerPresent() ) {
1822 OutputDebugString("Realm: ");
1823 OutputDebugString(realm);
1824 OutputDebugString("\n");
1828 /* krb5_cc_remove_cred() is not implemented
1831 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1832 realm, "afs", cell, NULL);
1834 memset(&mcreds, 0, sizeof(krb5_creds));
1835 mcreds.client = princ;
1836 mcreds.server = service;
1838 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1840 if ( IsDebuggerPresent() ) {
1841 char * cname, *sname;
1842 pkrb5_unparse_name(ctx, creds.client, &cname);
1843 pkrb5_unparse_name(ctx, creds.server, &sname);
1844 OutputDebugString("Removing credential for client \"");
1845 OutputDebugString(cname);
1846 OutputDebugString("\" and service \"");
1847 OutputDebugString(sname);
1848 OutputDebugString("\"\n");
1849 pkrb5_free_unparsed_name(ctx,cname);
1850 pkrb5_free_unparsed_name(ctx,sname);
1853 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1854 pkrb5_free_principal(ctx, creds.client);
1855 pkrb5_free_principal(ctx, creds.server);
1858 #endif /* COMMENT */
1860 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1861 if ( IsDebuggerPresent() ) {
1863 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1864 OutputDebugString(message);
1869 pkrb5_cc_close(ctx, cc);
1873 pkrb5_free_principal(ctx, princ);
1877 pkrb5_free_principal(ctx, service);
1880 if (cellconfig.linkedCell) {
1881 free(cellconfig.linkedCell);
1882 cellconfig.linkedCell = NULL;
1885 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1886 free(principals[count]);
1890 code = -1; // we did not renew the tokens
1894 pkrb5_free_context(ctx);
1895 return (code ? FALSE : TRUE);
1900 KFW_AFS_renew_tokens_for_all_cells(void)
1902 struct cell_principal_map * next = cell_princ_map;
1904 if ( IsDebuggerPresent() )
1905 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1910 for ( ; next ; next = next->next ) {
1912 KFW_AFS_renew_token_for_cell(next->cell);
1918 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1920 krb5_error_code code = 0;
1921 krb5_context ctx = NULL;
1922 krb5_ccache cc = NULL;
1923 krb5_principal me = NULL;
1924 krb5_principal server = NULL;
1925 krb5_creds my_creds;
1926 krb5_data *realm = NULL;
1928 if (!pkrb5_init_context)
1931 memset(&my_creds, 0, sizeof(krb5_creds));
1936 code = pkrb5_init_context(&ctx);
1937 if (code) goto cleanup;
1943 code = pkrb5_cc_default(ctx, &cc);
1944 if (code) goto cleanup;
1947 code = pkrb5_cc_get_principal(ctx, cc, &me);
1948 if (code) goto cleanup;
1950 realm = krb5_princ_realm(ctx, me);
1952 code = pkrb5_build_principal_ext(ctx, &server,
1953 realm->length,realm->data,
1954 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1955 realm->length,realm->data,
1960 if ( IsDebuggerPresent() ) {
1961 char * cname, *sname;
1962 pkrb5_unparse_name(ctx, me, &cname);
1963 pkrb5_unparse_name(ctx, server, &sname);
1964 OutputDebugString("Renewing credential for client \"");
1965 OutputDebugString(cname);
1966 OutputDebugString("\" and service \"");
1967 OutputDebugString(sname);
1968 OutputDebugString("\"\n");
1969 pkrb5_free_unparsed_name(ctx,cname);
1970 pkrb5_free_unparsed_name(ctx,sname);
1973 my_creds.client = me;
1974 my_creds.server = server;
1976 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1978 if ( IsDebuggerPresent() ) {
1980 StringCbPrintf(message, sizeof(message), "krb5_get_renewed_creds() failed: %d\n", code);
1981 OutputDebugString(message);
1986 code = pkrb5_cc_initialize(ctx, cc, me);
1988 if ( IsDebuggerPresent() ) {
1990 StringCbPrintf(message, sizeof(message), "krb5_cc_initialize() failed: %d\n", code);
1991 OutputDebugString(message);
1996 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1998 if ( IsDebuggerPresent() ) {
2000 StringCbPrintf(message, sizeof(message), "krb5_cc_store_cred() failed: %d\n", code);
2001 OutputDebugString(message);
2007 if (my_creds.client == me)
2008 my_creds.client = 0;
2009 if (my_creds.server == server)
2010 my_creds.server = 0;
2011 pkrb5_free_cred_contents(ctx, &my_creds);
2013 pkrb5_free_principal(ctx, me);
2015 pkrb5_free_principal(ctx, server);
2016 if (cc && (cc != alt_cc))
2017 pkrb5_cc_close(ctx, cc);
2018 if (ctx && (ctx != alt_ctx))
2019 pkrb5_free_context(ctx);
2024 KFW_kinit( krb5_context alt_ctx,
2027 char *principal_name,
2029 krb5_deltat lifetime,
2032 krb5_deltat renew_life,
2037 krb5_error_code code = 0;
2038 krb5_context ctx = NULL;
2039 krb5_ccache cc = NULL;
2040 krb5_principal me = NULL;
2042 krb5_creds my_creds;
2043 krb5_get_init_creds_opt options;
2044 krb5_address ** addrs = NULL;
2045 int i = 0, addr_count = 0;
2047 if (!pkrb5_init_context)
2050 pkrb5_get_init_creds_opt_init(&options);
2051 memset(&my_creds, 0, sizeof(my_creds));
2059 code = pkrb5_init_context(&ctx);
2060 if (code) goto cleanup;
2066 code = pkrb5_cc_default(ctx, &cc);
2067 if (code) goto cleanup;
2070 code = pkrb5_parse_name(ctx, principal_name, &me);
2074 code = pkrb5_unparse_name(ctx, me, &name);
2082 lifetime = pLeash_get_default_lifetime();
2083 #endif /* USE_LEASH */
2090 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2091 pkrb5_get_init_creds_opt_set_forwardable(&options,
2092 forwardable ? 1 : 0);
2093 pkrb5_get_init_creds_opt_set_proxiable(&options,
2095 pkrb5_get_init_creds_opt_set_renew_life(&options,
2098 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2102 // we are going to add the public IP address specified by the user
2103 // to the list provided by the operating system
2104 krb5_address ** local_addrs=NULL;
2107 pkrb5_os_localaddr(ctx, &local_addrs);
2108 while ( local_addrs[i++] );
2111 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2113 pkrb5_free_addresses(ctx, local_addrs);
2116 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2118 while ( local_addrs[i] ) {
2119 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2120 if (addrs[i] == NULL) {
2121 pkrb5_free_addresses(ctx, local_addrs);
2125 addrs[i]->magic = local_addrs[i]->magic;
2126 addrs[i]->addrtype = local_addrs[i]->addrtype;
2127 addrs[i]->length = local_addrs[i]->length;
2128 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2129 if (!addrs[i]->contents) {
2130 pkrb5_free_addresses(ctx, local_addrs);
2134 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2135 local_addrs[i]->length); /* safe */
2138 pkrb5_free_addresses(ctx, local_addrs);
2140 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2141 if (addrs[i] == NULL)
2144 addrs[i]->magic = KV5M_ADDRESS;
2145 addrs[i]->addrtype = AF_INET;
2146 addrs[i]->length = 4;
2147 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2148 if (!addrs[i]->contents)
2151 netIPAddr = htonl(publicIP);
2152 memcpy(addrs[i]->contents,&netIPAddr,4);
2154 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2159 code = pkrb5_get_init_creds_password(ctx,
2162 password, // password
2163 KRB5_prompter, // prompter
2164 hParent, // prompter data
2171 code = pkrb5_cc_initialize(ctx, cc, me);
2175 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2181 for ( i=0;i<addr_count;i++ ) {
2183 if ( addrs[i]->contents )
2184 free(addrs[i]->contents);
2189 if (my_creds.client == me)
2190 my_creds.client = 0;
2191 pkrb5_free_cred_contents(ctx, &my_creds);
2193 pkrb5_free_unparsed_name(ctx, name);
2195 pkrb5_free_principal(ctx, me);
2196 if (cc && (cc != alt_cc))
2197 pkrb5_cc_close(ctx, cc);
2198 if (ctx && (ctx != alt_ctx))
2199 pkrb5_free_context(ctx);
2205 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2207 krb5_context ctx = NULL;
2208 krb5_ccache cc = NULL;
2209 krb5_error_code code;
2211 if (!pkrb5_init_context)
2220 code = pkrb5_init_context(&ctx);
2221 if (code) goto cleanup;
2227 code = pkrb5_cc_default(ctx, &cc);
2228 if (code) goto cleanup;
2231 code = pkrb5_cc_destroy(ctx, cc);
2232 if ( !code ) cc = 0;
2235 if (cc && (cc != alt_cc))
2236 pkrb5_cc_close(ctx, cc);
2237 if (ctx && (ctx != alt_ctx))
2238 pkrb5_free_context(ctx);
2246 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2248 NTSTATUS Status = 0;
2250 TOKEN_STATISTICS Stats;
2256 *ppSessionData = NULL;
2258 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2262 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2263 CloseHandle( TokenHandle );
2267 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2268 if ( FAILED(Status) || !ppSessionData )
2275 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2276 // cache. It validates whether or not it is reasonable to assume that if we
2277 // attempted to retrieve valid tickets we could do so. Microsoft does not
2278 // automatically renew expired tickets. Therefore, the cache could contain
2279 // expired or invalid tickets. Microsoft also caches the user's password
2280 // and will use it to retrieve new TGTs if the cache is empty and tickets
2284 MSLSA_IsKerberosLogon(VOID)
2286 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2287 BOOL Success = FALSE;
2289 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2290 if ( pSessionData->AuthenticationPackage.Buffer ) {
2296 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2297 usLength = (pSessionData->AuthenticationPackage).Length;
2300 StringCbCopyNW( buffer, sizeof(buffer)/sizeof(WCHAR),
2301 usBuffer, usLength);
2302 if ( !lstrcmpW(L"Kerberos",buffer) )
2306 pLsaFreeReturnBuffer(pSessionData);
2310 #endif /* USE_MS2MIT */
2312 static BOOL CALLBACK
2313 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2317 switch ( message ) {
2319 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2321 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2324 for ( i=0; i < mid_cnt ; i++ ) {
2325 if (mid_tb[i].echo == 0)
2326 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2327 else if (mid_tb[i].echo == 2)
2328 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2333 switch ( LOWORD(wParam) ) {
2335 for ( i=0; i < mid_cnt ; i++ ) {
2336 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2337 *mid_tb[i].buf = '\0';
2341 EndDialog(hDialog, LOWORD(wParam));
2349 lpwAlign( LPWORD lpIn )
2353 ul = (ULONG_PTR) lpIn;
2357 return (LPWORD) ul;;
2361 * dialog widths are measured in 1/4 character widths
2362 * dialog height are measured in 1/8 character heights
2366 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2367 char * ptext[], int numlines, int width,
2368 int tb_cnt, struct textField * tb)
2372 LPDLGITEMTEMPLATE lpdit;
2378 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2385 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2387 // Define a dialog box.
2389 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2390 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2391 | DS_SETFOREGROUND | DS_3DLOOK
2392 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2393 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2396 lpdt->cx = 20 + width * 4;
2397 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2399 lpw = (LPWORD) (lpdt + 1);
2400 *lpw++ = 0; // no menu
2401 *lpw++ = 0; // predefined dialog box class (by default)
2403 lpwsz = (LPWSTR) lpw;
2404 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2406 *lpw++ = 8; // font size (points)
2407 lpwsz = (LPWSTR) lpw;
2408 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2412 //-----------------------
2413 // Define an OK button.
2414 //-----------------------
2415 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2416 lpdit = (LPDLGITEMTEMPLATE) lpw;
2417 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2418 lpdit->dwExtendedStyle = 0;
2419 lpdit->x = (lpdt->cx - 14)/4 - 20;
2420 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2423 lpdit->id = IDOK; // OK button identifier
2425 lpw = (LPWORD) (lpdit + 1);
2427 *lpw++ = 0x0080; // button class
2429 lpwsz = (LPWSTR) lpw;
2430 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2432 *lpw++ = 0; // no creation data
2434 //-----------------------
2435 // Define an Cancel button.
2436 //-----------------------
2437 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2438 lpdit = (LPDLGITEMTEMPLATE) lpw;
2439 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2440 lpdit->dwExtendedStyle = 0;
2441 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2442 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2445 lpdit->id = IDCANCEL; // CANCEL button identifier
2447 lpw = (LPWORD) (lpdit + 1);
2449 *lpw++ = 0x0080; // button class
2451 lpwsz = (LPWSTR) lpw;
2452 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2454 *lpw++ = 0; // no creation data
2456 /* Add controls for preface data */
2457 for ( i=0; i<numlines; i++) {
2458 /*-----------------------
2459 * Define a static text control.
2460 *-----------------------*/
2461 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2462 lpdit = (LPDLGITEMTEMPLATE) lpw;
2463 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2464 lpdit->dwExtendedStyle = 0;
2466 lpdit->y = 10 + i * 14;
2467 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2469 lpdit->id = ID_TEXT + i; // text identifier
2471 lpw = (LPWORD) (lpdit + 1);
2473 *lpw++ = 0x0082; // static class
2475 lpwsz = (LPWSTR) lpw;
2476 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2477 -1, lpwsz, 2*width);
2479 *lpw++ = 0; // no creation data
2482 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2483 int len = (int)strlen(tb[i].label);
2488 for ( i=0; i<tb_cnt; i++) {
2490 /*-----------------------
2491 * Define a static text control.
2492 *-----------------------*/
2493 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2494 lpdit = (LPDLGITEMTEMPLATE) lpw;
2495 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2496 lpdit->dwExtendedStyle = 0;
2498 lpdit->y = 10 + (numlines + i + 1) * 14;
2499 lpdit->cx = pwid * 4;
2501 lpdit->id = ID_TEXT + numlines + i; // text identifier
2503 lpw = (LPWORD) (lpdit + 1);
2505 *lpw++ = 0x0082; // static class
2507 lpwsz = (LPWSTR) lpw;
2508 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2511 *lpw++ = 0; // no creation data
2513 /*-----------------------
2514 * Define an edit control.
2515 *-----------------------*/
2516 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2517 lpdit = (LPDLGITEMTEMPLATE) lpw;
2518 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2519 lpdit->dwExtendedStyle = 0;
2520 lpdit->x = 10 + (pwid + 1) * 4;
2521 lpdit->y = 10 + (numlines + i + 1) * 14;
2522 lpdit->cx = (width - (pwid + 1)) * 4;
2524 lpdit->id = ID_MID_TEXT + i; // identifier
2526 lpw = (LPWORD) (lpdit + 1);
2528 *lpw++ = 0x0081; // edit class
2530 lpwsz = (LPWSTR) lpw;
2531 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2534 *lpw++ = 0; // no creation data
2538 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2539 hwndOwner, (DLGPROC) MultiInputDialogProc);
2543 case 0: /* Timeout */
2551 StringCbPrintf(buf, sizeof(buf), "DialogBoxIndirect() failed: %d", GetLastError());
2552 MessageBox(hwndOwner,
2555 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2562 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2564 HINSTANCE hInst = 0;
2568 char * plines[16], *p = preface ? preface : "";
2571 for ( i=0; i<16; i++ )
2574 while (*p && numlines < 16) {
2575 plines[numlines++] = p;
2576 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2577 if ( *p == '\r' && *(p+1) == '\n' ) {
2580 } else if ( *p == '\n' ) {
2583 if ( strlen(plines[numlines-1]) > maxwidth )
2584 maxwidth = (int)strlen(plines[numlines-1]);
2587 for ( i=0;i<n;i++ ) {
2588 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2589 if ( maxwidth < len )
2593 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2596 static krb5_error_code KRB5_CALLCONV
2597 KRB5_prompter( krb5_context context,
2602 krb5_prompt prompts[])
2604 krb5_error_code errcode = 0;
2606 struct textField * tb = NULL;
2607 int len = 0, blen=0, nlen=0;
2608 HWND hParent = (HWND)data;
2611 nlen = (int)strlen(name)+2;
2614 blen = (int)strlen(banner)+2;
2616 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2619 memset(tb,0,sizeof(struct textField) * num_prompts);
2620 for ( i=0; i < num_prompts; i++ ) {
2621 tb[i].buf = prompts[i].reply->data;
2622 tb[i].len = prompts[i].reply->length;
2623 tb[i].label = prompts[i].prompt;
2625 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2628 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2630 for ( i=0; i < num_prompts; i++ )
2631 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2639 for (i = 0; i < num_prompts; i++) {
2640 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2647 KFW_AFS_wait_for_service_start(void)
2652 CurrentState = SERVICE_START_PENDING;
2653 memset(HostName, '\0', sizeof(HostName));
2654 gethostname(HostName, sizeof(HostName));
2656 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2658 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2660 if ( IsDebuggerPresent() ) {
2661 switch ( CurrentState ) {
2662 case SERVICE_STOPPED:
2663 OutputDebugString("SERVICE_STOPPED\n");
2665 case SERVICE_START_PENDING:
2666 OutputDebugString("SERVICE_START_PENDING\n");
2668 case SERVICE_STOP_PENDING:
2669 OutputDebugString("SERVICE_STOP_PENDING\n");
2671 case SERVICE_RUNNING:
2672 OutputDebugString("SERVICE_RUNNING\n");
2674 case SERVICE_CONTINUE_PENDING:
2675 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2677 case SERVICE_PAUSE_PENDING:
2678 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2680 case SERVICE_PAUSED:
2681 OutputDebugString("SERVICE_PAUSED\n");
2684 OutputDebugString("UNKNOWN Service State\n");
2687 if (CurrentState == SERVICE_STOPPED)
2689 if (CurrentState == SERVICE_RUNNING)
2705 memset(HostName, '\0', sizeof(HostName));
2706 gethostname(HostName, sizeof(HostName));
2707 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2709 if (CurrentState != SERVICE_RUNNING)
2712 rc = ktc_ForgetAllTokens();
2718 #define ALLOW_REGISTER 1
2720 ViceIDToUsername(char *username,
2721 char *realm_of_user,
2722 char *realm_of_cell,
2724 struct ktc_principal *aclient,
2725 struct ktc_principal *aserver,
2726 struct ktc_token *atoken)
2728 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2729 static char confdir[512] = { 0 };
2730 #ifdef AFS_ID_TO_NAME
2731 char username_copy[BUFSIZ];
2732 #endif /* AFS_ID_TO_NAME */
2733 long viceId = ANONYMOUSID; /* AFS uid of user */
2735 #ifdef ALLOW_REGISTER
2737 #endif /* ALLOW_REGISTER */
2739 if (confdir[0] == '\0')
2740 cm_GetConfigDir(confdir, sizeof(confdir));
2742 StringCbCopyN( lastcell, sizeof(lastcell),
2743 aserver->cell, sizeof(lastcell) - 1);
2745 if (!pr_Initialize (0, confdir, aserver->cell)) {
2746 char sname[PR_MAXNAMELEN];
2747 StringCbCopyN( sname, sizeof(sname),
2748 username, sizeof(sname) - 1);
2749 status = pr_SNameToId (sname, &viceId);
2754 * This is a crock, but it is Transarc's crock, so
2755 * we have to play along in order to get the
2756 * functionality. The way the afs id is stored is
2757 * as a string in the username field of the token.
2758 * Contrary to what you may think by looking at
2759 * the code for tokens, this hack (AFS ID %d) will
2760 * not work if you change %d to something else.
2764 * This code is taken from cklog -- it lets people
2765 * automatically register with the ptserver in foreign cells
2768 #ifdef ALLOW_REGISTER
2770 if (viceId != ANONYMOUSID) {
2771 #else /* ALLOW_REGISTER */
2772 if ((status == 0) && (viceId != ANONYMOUSID))
2773 #endif /* ALLOW_REGISTER */
2775 #ifdef AFS_ID_TO_NAME
2776 StringCbCopyN( username_copy, sizeof(username_copy),
2777 username, sizeof(username_copy) - 1);
2778 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2779 #endif /* AFS_ID_TO_NAME */
2781 #ifdef ALLOW_REGISTER
2782 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2784 StringCbCopyN( aclient->name, sizeof(aclient->name),
2785 username, sizeof(aclient->name) - 1);
2786 aclient->instance[0] = '\0';
2787 StringCbCopyN( aclient->cell, sizeof(aclient->cell),
2788 realm_of_user, sizeof(aclient->cell) - 1);
2789 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2791 if (status = pr_Initialize(1L, confdir, aserver->cell))
2793 status = pr_CreateUser(username, &id);
2797 #ifdef AFS_ID_TO_NAME
2798 StringCbCopyN( username_copy, sizeof(username_copy),
2799 username, sizeof(username_copy) - 1);
2800 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2801 #endif /* AFS_ID_TO_NAME */
2804 #endif /* ALLOW_REGISTER */
2810 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2811 krb5_error_code code;
2812 krb5_ticket *ticket;
2815 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2817 len = krb5_princ_realm(context, ticket->server)->length;
2818 if (len > destlen - 1)
2821 StringCbCopyN(dest, destlen, krb5_princ_realm(context, ticket->server)->data, len);
2823 pkrb5_free_ticket(context, ticket);
2829 krb5_context alt_ctx,
2834 int lifetime, /* unused parameter */
2842 #endif /* USE_KRB4 */
2843 struct ktc_principal aserver;
2844 struct ktc_principal aclient;
2845 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2846 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2847 char local_cell[CELL_MAXNAMELEN+1];
2848 char Dmycell[CELL_MAXNAMELEN+1];
2849 struct ktc_token atoken;
2850 struct ktc_token btoken;
2851 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2852 char RealmName[128];
2854 char ServiceName[128];
2858 krb5_context ctx = NULL;
2859 krb5_ccache cc = NULL;
2861 krb5_creds * k5creds = NULL;
2862 krb5_error_code code;
2863 krb5_principal client_principal = NULL;
2864 krb5_data * k5data = NULL;
2865 unsigned int i, retry = 0;
2868 memset(HostName, '\0', sizeof(HostName));
2869 gethostname(HostName, sizeof(HostName));
2870 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2871 if ( IsDebuggerPresent() )
2872 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2875 if (CurrentState != SERVICE_RUNNING) {
2876 if ( IsDebuggerPresent() )
2877 OutputDebugString("AFSD Service NOT RUNNING\n");
2881 if (!pkrb5_init_context)
2884 memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
2885 memset(RealmName, '\0', sizeof(RealmName));
2886 memset(CellName, '\0', sizeof(CellName));
2887 memset(ServiceName, '\0', sizeof(ServiceName));
2888 memset(realm_of_user, '\0', sizeof(realm_of_user));
2889 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2890 if (cell && cell[0])
2891 StringCbCopyN( Dmycell, sizeof(Dmycell),
2892 cell, sizeof(Dmycell) - 1);
2894 memset(Dmycell, '\0', sizeof(Dmycell));
2896 // NULL or empty cell returns information on local cell
2897 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2899 // KFW_AFS_error(rc, "get_cellconfig()");
2906 code = pkrb5_init_context(&ctx);
2907 if (code) goto cleanup;
2913 code = pkrb5_cc_default(ctx, &cc);
2914 if (code) goto skip_krb5_init;
2917 memset(&increds, 0, sizeof(increds));
2919 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2921 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2923 OutputDebugString("Principal Not Found for ccache\n");
2925 goto skip_krb5_init;
2928 if (!KFW_accept_dotted_usernames()) {
2929 /* look for client principals which cannot be distinguished
2930 * from Kerberos 4 multi-component principal names
2932 k5data = krb5_princ_component(ctx,client_principal,0);
2933 for ( i=0; i<k5data->length; i++ ) {
2934 if ( k5data->data[i] == '.' )
2937 if (i != k5data->length)
2939 OutputDebugString("Illegal Principal name contains dot in first component\n");
2940 rc = KRB5KRB_ERR_GENERIC;
2945 i = krb5_princ_realm(ctx, client_principal)->length;
2948 StringCbCopyN( realm_of_user, sizeof(realm_of_user),
2949 krb5_princ_realm(ctx, client_principal)->data, i);
2954 if ( !try_krb5 || !realm_of_user[0] ) {
2955 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2964 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
2965 afs_realm_of_cell(ctx, &ak_cellconfig),
2966 sizeof(realm_of_cell) - 1);
2968 if (strlen(service) == 0)
2969 StringCbCopy( ServiceName, sizeof(ServiceName), "afs");
2971 StringCbCopyN( ServiceName, sizeof(ServiceName),
2972 service, sizeof(ServiceName) - 1);
2974 if (strlen(cell) == 0)
2975 StringCbCopyN( CellName, sizeof(CellName),
2976 local_cell, sizeof(CellName) - 1);
2978 StringCbCopyN( CellName, sizeof(CellName),
2979 cell, sizeof(CellName) - 1);
2981 /* This is for Kerberos v4 only */
2982 if (strlen(realm) == 0)
2983 StringCbCopyN( RealmName, sizeof(RealmName),
2984 realm_of_cell, sizeof(RealmName) - 1);
2986 StringCbCopyN( RealmName, sizeof(RealmName),
2987 realm, sizeof(RealmName) - 1);
2989 memset(&creds, '\0', sizeof(creds));
2993 code = KRB5KRB_ERR_GENERIC;
2996 increds.client = client_principal;
2997 increds.times.endtime = 0;
2998 /* Ask for DES since that is what V4 understands */
2999 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
3001 /* If there was a specific realm we are supposed to try
3004 if (strlen(realm) != 0) {
3005 /* service/cell@REALM */
3007 code = pkrb5_build_principal(ctx, &increds.server,
3013 if ( IsDebuggerPresent() ) {
3014 char * cname, *sname;
3015 pkrb5_unparse_name(ctx, increds.client, &cname);
3016 pkrb5_unparse_name(ctx, increds.server, &sname);
3017 OutputDebugString("Getting tickets for \"");
3018 OutputDebugString(cname);
3019 OutputDebugString("\" and service \"");
3020 OutputDebugString(sname);
3021 OutputDebugString("\"\n");
3022 pkrb5_free_unparsed_name(ctx,cname);
3023 pkrb5_free_unparsed_name(ctx,sname);
3027 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3029 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3030 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3031 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3032 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3033 /* Or service@REALM */
3034 pkrb5_free_principal(ctx,increds.server);
3036 code = pkrb5_build_principal(ctx, &increds.server,
3042 if ( IsDebuggerPresent() ) {
3043 char * cname, *sname;
3044 pkrb5_unparse_name(ctx, increds.client, &cname);
3045 pkrb5_unparse_name(ctx, increds.server, &sname);
3046 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3047 OutputDebugString("Trying again: getting tickets for \"");
3048 OutputDebugString(cname);
3049 OutputDebugString("\" and service \"");
3050 OutputDebugString(sname);
3051 OutputDebugString("\"\n");
3052 pkrb5_free_unparsed_name(ctx,cname);
3053 pkrb5_free_unparsed_name(ctx,sname);
3057 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3061 /* we have a local realm for the cell */
3062 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3063 realm, sizeof(realm_of_cell) - 1);
3066 /* Otherwise, first try service/cell@CLIENT_REALM */
3067 if (code = pkrb5_build_principal(ctx, &increds.server,
3068 (int)strlen(realm_of_user),
3077 if ( IsDebuggerPresent() ) {
3078 char * cname, *sname;
3079 pkrb5_unparse_name(ctx, increds.client, &cname);
3080 pkrb5_unparse_name(ctx, increds.server, &sname);
3081 OutputDebugString("Getting tickets for \"");
3082 OutputDebugString(cname);
3083 OutputDebugString("\" and service \"");
3084 OutputDebugString(sname);
3085 OutputDebugString("\"\n");
3086 pkrb5_free_unparsed_name(ctx,cname);
3087 pkrb5_free_unparsed_name(ctx,sname);
3090 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3092 /* The client's realm is a local realm for the cell.
3093 * Save it so that later the pts registration will not
3096 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3097 realm_of_user, sizeof(realm_of_cell) - 1);
3100 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3101 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3102 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3103 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
3104 strcmp(realm_of_user, realm_of_cell)) {
3105 /* Then service/cell@CELL_REALM */
3106 pkrb5_free_principal(ctx,increds.server);
3108 code = pkrb5_build_principal(ctx, &increds.server,
3109 (int)strlen(realm_of_cell),
3114 if ( IsDebuggerPresent() ) {
3115 char * cname, *sname;
3116 pkrb5_unparse_name(ctx, increds.client, &cname);
3117 pkrb5_unparse_name(ctx, increds.server, &sname);
3118 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3119 OutputDebugString("Trying again: getting tickets for \"");
3120 OutputDebugString(cname);
3121 OutputDebugString("\" and service \"");
3122 OutputDebugString(sname);
3123 OutputDebugString("\"\n");
3124 pkrb5_free_unparsed_name(ctx,cname);
3125 pkrb5_free_unparsed_name(ctx,sname);
3129 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3131 if (!code && !strlen(realm_of_cell))
3132 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3135 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3136 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3137 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3138 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3139 /* Finally service@CELL_REALM */
3140 pkrb5_free_principal(ctx,increds.server);
3142 code = pkrb5_build_principal(ctx, &increds.server,
3143 (int)strlen(realm_of_cell),
3148 if ( IsDebuggerPresent() ) {
3149 char * cname, *sname;
3150 pkrb5_unparse_name(ctx, increds.client, &cname);
3151 pkrb5_unparse_name(ctx, increds.server, &sname);
3152 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3153 OutputDebugString("Trying again: getting tickets for \"");
3154 OutputDebugString(cname);
3155 OutputDebugString("\" and service \"");
3156 OutputDebugString(sname);
3157 OutputDebugString("\"\n");
3158 pkrb5_free_unparsed_name(ctx,cname);
3159 pkrb5_free_unparsed_name(ctx,sname);
3163 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3164 if (!code && !strlen(realm_of_cell))
3165 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3170 if ( IsDebuggerPresent() ) {
3172 StringCbPrintf(message, sizeof(message), "krb5_get_credentials returns: %d\n", code);
3173 OutputDebugString(message);
3179 /* This code inserts the entire K5 ticket into the token
3180 * No need to perform a krb524 translation which is
3181 * commented out in the code below
3183 if (KFW_use_krb524() ||
3184 k5creds->ticket.length > MAXKTCTICKETLEN)
3187 memset(&aserver, '\0', sizeof(aserver));
3188 StringCbCopyN( aserver.name, sizeof(aserver.name),
3189 ServiceName, sizeof(aserver.name) - 1);
3190 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
3191 CellName, sizeof(aserver.cell) - 1);
3193 memset(&atoken, '\0', sizeof(atoken));
3194 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3195 atoken.startTime = k5creds->times.starttime;
3196 atoken.endTime = k5creds->times.endtime;
3197 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3198 atoken.ticketLen = k5creds->ticket.length;
3199 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3202 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3203 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3204 if ( rc == KTC_NOCM && retry < 20 ) {
3207 goto retry_gettoken5;
3212 if (atoken.kvno == btoken.kvno &&
3213 atoken.ticketLen == btoken.ticketLen &&
3214 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3215 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3217 /* Success - Nothing to do */
3221 // * Reset the "aclient" structure before we call ktc_SetToken.
3222 // * This structure was first set by the ktc_GetToken call when
3223 // * we were comparing whether identical tokens already existed.
3225 len = min(k5creds->client->data[0].length, sizeof(aclient.name) - 1);
3226 StringCbCopyN( aclient.name, sizeof(aclient.name),
3227 k5creds->client->data[0].data, len);
3229 if ( k5creds->client->length > 1 ) {
3230 StringCbCat( aclient.name, sizeof(aclient.name), ".");
3231 len = min(k5creds->client->data[1].length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3232 StringCbCatN( aclient.name, sizeof(aclient.name),
3233 k5creds->client->data[1].data, len);
3235 aclient.instance[0] = '\0';
3237 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3238 realm_of_cell, sizeof(aclient.cell) - 1);
3240 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3241 /* For Khimaira, always append the realm name */
3242 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3243 StringCbCat( aclient.name, sizeof(aclient.name), "@");
3244 len = min(k5creds->client->realm.length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3245 StringCbCatN( aclient.name, sizeof(aclient.name), k5creds->client->realm.data, len);
3248 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3249 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3250 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3251 &aclient, &aserver, &atoken);
3254 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3255 smbname, sizeof(aclient.smbname) - 1);
3257 aclient.smbname[0] = '\0';
3260 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3262 goto cleanup; /* We have successfully inserted the token */
3268 /* Otherwise, the ticket could have been too large so try to
3269 * convert using the krb524d running with the KDC
3271 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3272 pkrb5_free_creds(ctx, k5creds);
3274 if ( IsDebuggerPresent() ) {
3276 StringCbPrintf(message, sizeof(message), "krb524_convert_creds_kdc returns: %d\n", code);
3277 OutputDebugString(message);
3282 #endif /* USE_KRB524 */
3286 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3287 if (code == NO_TKT_FIL) {
3288 // if the problem is that we have no krb4 tickets
3289 // do not attempt to continue
3292 if (code != KSUCCESS)
3293 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3295 if (code != KSUCCESS)
3297 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3299 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3304 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3306 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3321 memset(&aserver, '\0', sizeof(aserver));
3322 StringCbCopyN( aserver.name, sizeof(aserver.name), ServiceName, sizeof(aserver.name) - 1);
3323 StringCbCopyN( aserver.cell, sizeof(aserver.cell), CellName, sizeof(aserver.cell) - 1);
3325 memset(&atoken, '\0', sizeof(atoken));
3326 atoken.kvno = creds.kvno;
3327 atoken.startTime = creds.issue_date;
3328 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3329 memcpy(&atoken.sessionKey, creds.session, 8);
3330 atoken.ticketLen = creds.ticket_st.length;
3331 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3334 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3335 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3336 if ( rc == KTC_NOCM && retry < 20 ) {
3339 goto retry_gettoken;
3341 KFW_AFS_error(rc, "ktc_GetToken()");
3346 if (atoken.kvno == btoken.kvno &&
3347 atoken.ticketLen == btoken.ticketLen &&
3348 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3349 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3354 // * Reset the "aclient" structure before we call ktc_SetToken.
3355 // * This structure was first set by the ktc_GetToken call when
3356 // * we were comparing whether identical tokens already existed.
3358 StringCbCopyN( aclient.name, sizeof(aclient.name), creds.pname, sizeof(aclient.name) - 1);
3361 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3362 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3364 aclient.instance[0] = '\0';
3366 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3367 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3368 aclient.name[MAXKTCREALMLEN-1] = '\0';
3370 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3371 CellName, sizeof(aclient.cell) - 1);
3373 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3374 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3375 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3376 &aclient, &aserver, &atoken);
3379 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3380 smbname, sizeof(aclient.smbname) - 1);
3382 aclient.smbname[0] = '\0';
3385 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3387 KFW_AFS_error(rc, "ktc_SetToken()");
3393 if (client_principal)
3394 pkrb5_free_principal(ctx,client_principal);
3395 /* increds.client == client_principal */
3397 pkrb5_free_principal(ctx,increds.server);
3398 if (cc && (cc != alt_cc))
3399 pkrb5_cc_close(ctx, cc);
3400 if (ctx && (ctx != alt_ctx))
3401 pkrb5_free_context(ctx);
3402 if (ak_cellconfig.linkedCell)
3403 free(ak_cellconfig.linkedCell);
3405 return(rc? rc : code);
3408 /**************************************/
3409 /* afs_realm_of_cell(): */
3410 /**************************************/
3412 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3414 static char krbrlm[REALM_SZ+1]="";
3415 char ** realmlist=NULL;
3421 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3422 if ( !r && realmlist && realmlist[0] ) {
3423 StringCbCopyN( krbrlm, sizeof(krbrlm),
3424 realmlist[0], sizeof(krbrlm) - 1);
3425 pkrb5_free_host_realm(ctx, realmlist);
3431 char *t = cellconfig->name;
3436 if (islower(c)) c=toupper(c);
3444 /**************************************/
3445 /* KFW_AFS_get_cellconfig(): */
3446 /**************************************/
3448 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3451 char newcell[CELL_MAXNAMELEN+1];
3452 char linkedcell[CELL_MAXNAMELEN+1]="";
3454 local_cell[0] = (char)0;
3455 memset(cellconfig, 0, sizeof(*cellconfig));
3457 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3458 if (rc = cm_GetRootCellName(local_cell))
3463 if (strlen(cell) == 0)
3464 strcpy(cell, local_cell);
3466 rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3467 if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
3468 rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3471 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3475 StringCbCopyN( cellconfig->name, sizeof(cellconfig->name),
3476 newcell, sizeof(cellconfig->name) - 1);
3478 cellconfig->linkedCell = strdup(linkedcell);
3483 /**************************************/
3484 /* get_cellconfig_callback(): */
3485 /**************************************/
3487 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
3489 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3491 cc->hostAddr[cc->numServers] = *addrp;
3492 StringCbCopyN( cc->hostName[cc->numServers], sizeof(cc->hostName[cc->numServers]),
3493 namep, sizeof(cc->hostName[cc->numServers]) - 1);
3499 /**************************************/
3500 /* KFW_AFS_error(): */
3501 /**************************************/
3503 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3506 const char *errText;
3508 // Using AFS defines as error messages for now, until Transarc
3509 // gets back to me with "string" translations of each of these
3511 if (rc == KTC_ERROR)
3512 errText = "KTC_ERROR";
3513 else if (rc == KTC_TOOBIG)
3514 errText = "KTC_TOOBIG";
3515 else if (rc == KTC_INVAL)
3516 errText = "KTC_INVAL";
3517 else if (rc == KTC_NOENT)
3518 errText = "KTC_NOENT";
3519 else if (rc == KTC_PIOCTLFAIL)
3520 errText = "KTC_PIOCTLFAIL";
3521 else if (rc == KTC_NOPIOCTL)
3522 errText = "KTC_NOPIOCTL";
3523 else if (rc == KTC_NOCELL)
3524 errText = "KTC_NOCELL";
3525 else if (rc == KTC_NOCM)
3526 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3528 errText = "Unknown error!";
3530 StringCbPrintf(message, sizeof(message), "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3532 if ( IsDebuggerPresent() ) {
3533 OutputDebugString(message);
3534 OutputDebugString("\n");
3536 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3542 LPSTR lpszMachineName,
3543 LPSTR lpszServiceName,
3544 DWORD *lpdwCurrentState)
3547 SC_HANDLE schSCManager = NULL;
3548 SC_HANDLE schService = NULL;
3549 DWORD fdwDesiredAccess = 0;
3550 SERVICE_STATUS ssServiceStatus = {0};
3553 *lpdwCurrentState = 0;
3555 fdwDesiredAccess = GENERIC_READ;
3557 schSCManager = OpenSCManager(lpszMachineName,
3561 if(schSCManager == NULL)
3563 hr = GetLastError();
3567 schService = OpenService(schSCManager,
3571 if(schService == NULL)
3573 hr = GetLastError();
3577 fRet = QueryServiceStatus(schService,
3582 hr = GetLastError();
3586 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3590 CloseServiceHandle(schService);
3591 CloseServiceHandle(schSCManager);
3604 for (n = 0; fi[n].func_ptr_var; n++)
3605 *(fi[n].func_ptr_var) = 0;
3606 if (h) FreeLibrary(h);
3611 const char* dll_name,
3613 HINSTANCE* ph, // [out, optional] - DLL handle
3614 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3615 int cleanup, // cleanup function pointers and unload on error
3616 int go_on, // continue loading even if some functions cannot be loaded
3617 int silent // do not pop-up a system dialog if DLL cannot be loaded
3626 if (pindex) *pindex = -1;
3628 for (n = 0; fi[n].func_ptr_var; n++)
3629 *(fi[n].func_ptr_var) = 0;
3632 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3633 h = LoadLibrary(dll_name);
3641 for (i = 0; (go_on || !error) && (i < n); i++)
3643 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3649 *(fi[i].func_ptr_var) = p;
3652 if (pindex) *pindex = last_i;
3653 if (error && cleanup && !go_on) {
3654 for (i = 0; i < n; i++) {
3655 *(fi[i].func_ptr_var) = 0;
3661 if (error) return 0;
3665 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3667 krb5_context ctx = NULL;
3668 krb5_ccache cc = NULL;
3669 krb5_error_code code;
3671 const char * realm = NULL;
3672 krb5_principal principal = NULL;
3673 char * pname = NULL;
3674 char password[PROBE_PASSWORD_LEN+1];
3675 BOOL serverReachable = 0;
3677 if (!pkrb5_init_context)
3680 code = pkrb5_init_context(&ctx);
3681 if (code) goto cleanup;
3684 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3686 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3687 realm, PROBE_USERNAME, NULL, NULL);
3688 if ( code ) goto cleanup;
3690 code = KFW_get_ccache(ctx, principal, &cc);
3691 if ( code ) goto cleanup;
3693 code = pkrb5_unparse_name(ctx, principal, &pname);
3694 if ( code ) goto cleanup;
3696 pwdata.data = password;
3697 pwdata.length = PROBE_PASSWORD_LEN;
3698 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3701 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3704 password[PROBE_PASSWORD_LEN] = '\0';
3706 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3716 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3717 case KRB5KDC_ERR_CLIENT_REVOKED:
3718 case KRB5KDC_ERR_CLIENT_NOTYET:
3719 case KRB5KDC_ERR_PREAUTH_FAILED:
3720 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3721 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3722 serverReachable = TRUE;
3725 serverReachable = FALSE;
3730 pkrb5_free_unparsed_name(ctx,pname);
3732 pkrb5_free_principal(ctx,principal);
3734 pkrb5_cc_close(ctx,cc);
3736 pkrb5_free_context(ctx);
3738 return serverReachable;
3742 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
3744 krb5_context ctx = NULL;
3745 krb5_error_code code;
3746 krb5_ccache mslsa_ccache=NULL;
3747 krb5_principal princ = NULL;
3748 char * pname = NULL;
3751 if (!KFW_is_available())
3754 if (code = pkrb5_init_context(&ctx))
3757 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3760 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3763 if (code = pkrb5_unparse_name(ctx, princ, &pname))
3766 if ( strlen(pname) < *dwSize ) {
3767 StringCbCopyN(szUser, *dwSize, pname, (*dwSize) - 1);
3770 *dwSize = (DWORD)strlen(pname);
3774 pkrb5_free_unparsed_name(ctx, pname);
3777 pkrb5_free_principal(ctx, princ);
3780 pkrb5_cc_close(ctx, mslsa_ccache);
3783 pkrb5_free_context(ctx);
3788 KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
3790 // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
3791 PSID pSystemSID = NULL;
3792 DWORD SystemSIDlength = 0, UserSIDlength = 0;
3793 PACL ccacheACL = NULL;
3794 DWORD ccacheACLlength = 0;
3795 PTOKEN_USER pTokenUser = NULL;
3804 /* Get System SID */
3805 if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
3811 SystemSIDlength = GetLengthSid(pSystemSID);
3812 ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
3813 + SystemSIDlength - sizeof(DWORD);
3816 if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
3818 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
3819 pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
3821 GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
3826 UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
3828 ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
3833 ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
3838 InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
3839 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3840 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3843 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3844 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3845 pTokenUser->User.Sid);
3846 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3847 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3852 gle = GetLastError();
3853 if (gle != ERROR_NO_TOKEN)
3856 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3857 OWNER_SECURITY_INFORMATION,
3858 pTokenUser->User.Sid,
3862 gle = GetLastError();
3863 if (gle != ERROR_NO_TOKEN)
3867 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3868 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3873 gle = GetLastError();
3874 if (gle != ERROR_NO_TOKEN)
3881 LocalFree(pSystemSID);
3883 LocalFree(pTokenUser);
3885 LocalFree(ccacheACL);
3890 KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
3893 DWORD dwSize = size-1; /* leave room for nul */
3896 if (!hUserToken || !newfilename || size <= 0)
3899 *newfilename = '\0';
3901 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
3902 if ( !dwLen || dwLen > dwSize )
3903 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
3904 if ( !dwLen || dwLen > dwSize )
3907 newfilename[dwSize] = '\0';
3912 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
3914 char filename[MAX_PATH] = "";
3916 char cachename[MAX_PATH + 8] = "FILE:";
3917 krb5_context ctx = NULL;
3918 krb5_error_code code;
3919 krb5_principal princ = NULL;
3920 krb5_ccache cc = NULL;
3921 krb5_ccache ncc = NULL;
3923 if (!pkrb5_init_context || !user || !szLogonId)
3926 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
3927 if ( count > sizeof(filename) || count == 0 ) {
3928 GetWindowsDirectory(filename, sizeof(filename));
3931 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
3934 StringCbCat( filename, sizeof(filename), "\\");
3935 StringCbCat( filename, sizeof(filename), szLogonId);
3937 StringCbCat( cachename, sizeof(cachename), filename);
3939 DeleteFile(filename);
3941 code = pkrb5_init_context(&ctx);
3942 if (code) goto cleanup;
3944 code = pkrb5_parse_name(ctx, user, &princ);
3945 if (code) goto cleanup;
3947 code = KFW_get_ccache(ctx, princ, &cc);
3948 if (code) goto cleanup;
3950 code = pkrb5_cc_resolve(ctx, cachename, &ncc);
3951 if (code) goto cleanup;
3953 code = pkrb5_cc_initialize(ctx, ncc, princ);
3954 if (code) goto cleanup;
3956 code = KFW_AFS_set_file_cache_dacl(filename, NULL);
3957 if (code) goto cleanup;
3959 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3963 pkrb5_cc_close(ctx, cc);
3967 pkrb5_cc_close(ctx, ncc);
3971 pkrb5_free_principal(ctx, princ);
3976 pkrb5_free_context(ctx);
3980 KFW_AFS_copy_file_cache_to_default_cache(char * filename)
3982 char cachename[MAX_PATH + 8] = "FILE:";
3983 krb5_context ctx = NULL;
3984 krb5_error_code code;
3985 krb5_principal princ = NULL;
3986 krb5_ccache cc = NULL;
3987 krb5_ccache ncc = NULL;
3990 if (!pkrb5_init_context || !filename)
3993 if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
3996 code = pkrb5_init_context(&ctx);
3999 StringCbCat( cachename, sizeof(cachename), filename);
4001 code = pkrb5_cc_resolve(ctx, cachename, &cc);
4002 if (code) goto cleanup;
4004 code = pkrb5_cc_get_principal(ctx, cc, &princ);
4006 code = pkrb5_cc_default(ctx, &ncc);
4008 code = pkrb5_cc_initialize(ctx, ncc, princ);
4011 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
4014 pkrb5_cc_close(ctx, ncc);
4018 retval=0; /* success */
4022 pkrb5_cc_close(ctx, cc);
4026 DeleteFile(filename);
4029 pkrb5_free_principal(ctx, princ);
4034 pkrb5_free_context(ctx);
4039 /* We are including this
4041 /* Ticket lifetime. This defines the table used to lookup lifetime for the
4042 fixed part of rande of the one byte lifetime field. Values less than 0x80
4043 are intrpreted as the number of 5 minute intervals. Values from 0x80 to
4044 0xBF should be looked up in this table. The value of 0x80 is the same using
4045 both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days.
4046 The intervening values of have a fixed ratio of roughly 1.06914. The value
4047 oxFF is defined to mean a ticket has no expiration time. This should be
4048 used advisedly since individual servers may impose defacto upperbounds on
4049 ticket lifetimes. */
4051 #define TKTLIFENUMFIXED 64
4052 #define TKTLIFEMINFIXED 0x80
4053 #define TKTLIFEMAXFIXED 0xBF
4054 #define TKTLIFENOEXPIRE 0xFF
4055 #define MAXTKTLIFETIME (30*24*3600) /* 30 days */
4057 static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
4058 38400, /* 10.67 hours, 0.44 days */
4059 41055, /* 11.40 hours, 0.48 days */
4060 43894, /* 12.19 hours, 0.51 days */
4061 46929, /* 13.04 hours, 0.54 days */
4062 50174, /* 13.94 hours, 0.58 days */
4063 53643, /* 14.90 hours, 0.62 days */
4064 57352, /* 15.93 hours, 0.66 days */
4065 61318, /* 17.03 hours, 0.71 days */
4066 65558, /* 18.21 hours, 0.76 days */
4067 70091, /* 19.47 hours, 0.81 days */
4068 74937, /* 20.82 hours, 0.87 days */
4069 80119, /* 22.26 hours, 0.93 days */
4070 85658, /* 23.79 hours, 0.99 days */
4071 91581, /* 25.44 hours, 1.06 days */
4072 97914, /* 27.20 hours, 1.13 days */
4073 104684, /* 29.08 hours, 1.21 days */
4074 111922, /* 31.09 hours, 1.30 days */
4075 119661, /* 33.24 hours, 1.38 days */
4076 127935, /* 35.54 hours, 1.48 days */
4077 136781, /* 37.99 hours, 1.58 days */
4078 146239, /* 40.62 hours, 1.69 days */
4079 156350, /* 43.43 hours, 1.81 days */
4080 167161, /* 46.43 hours, 1.93 days */
4081 178720, /* 49.64 hours, 2.07 days */
4082 191077, /* 53.08 hours, 2.21 days */
4083 204289, /* 56.75 hours, 2.36 days */
4084 218415, /* 60.67 hours, 2.53 days */
4085 233517, /* 64.87 hours, 2.70 days */
4086 249664, /* 69.35 hours, 2.89 days */
4087 266926, /* 74.15 hours, 3.09 days */
4088 285383, /* 79.27 hours, 3.30 days */
4089 305116, /* 84.75 hours, 3.53 days */
4090 326213, /* 90.61 hours, 3.78 days */
4091 348769, /* 96.88 hours, 4.04 days */
4092 372885, /* 103.58 hours, 4.32 days */
4093 398668, /* 110.74 hours, 4.61 days */
4094 426234, /* 118.40 hours, 4.93 days */
4095 455705, /* 126.58 hours, 5.27 days */
4096 487215, /* 135.34 hours, 5.64 days */
4097 520904, /* 144.70 hours, 6.03 days */
4098 556921, /* 154.70 hours, 6.45 days */
4099 595430, /* 165.40 hours, 6.89 days */
4100 636601, /* 176.83 hours, 7.37 days */
4101 680618, /* 189.06 hours, 7.88 days */
4102 727680, /* 202.13 hours, 8.42 days */
4103 777995, /* 216.11 hours, 9.00 days */
4104 831789, /* 231.05 hours, 9.63 days */
4105 889303, /* 247.03 hours, 10.29 days */
4106 950794, /* 264.11 hours, 11.00 days */
4107 1016537, /* 282.37 hours, 11.77 days */
4108 1086825, /* 301.90 hours, 12.58 days */
4109 1161973, /* 322.77 hours, 13.45 days */
4110 1242318, /* 345.09 hours, 14.38 days */
4111 1328218, /* 368.95 hours, 15.37 days */
4112 1420057, /* 394.46 hours, 16.44 days */
4113 1518247, /* 421.74 hours, 17.57 days */
4114 1623226, /* 450.90 hours, 18.79 days */
4115 1735464, /* 482.07 hours, 20.09 days */
4116 1855462, /* 515.41 hours, 21.48 days */
4117 1983758, /* 551.04 hours, 22.96 days */
4118 2120925, /* 589.15 hours, 24.55 days */
4119 2267576, /* 629.88 hours, 26.25 days */
4120 2424367, /* 673.44 hours, 28.06 days */
4122 }; /* 720.00 hours, 30.00 days */
4124 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
4125 * returns the corresponding end time. There are four simple cases to be
4126 * handled. The first is a life of 0xff, meaning no expiration, and results in
4127 * an end time of 0xffffffff. The second is when life is less than the values
4128 * covered by the table. In this case, the end time is the start time plus the
4129 * number of 5 minute intervals specified by life. The third case returns
4130 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
4131 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
4132 * table to extract the lifetime in seconds, which is added to start to produce
4136 life_to_time(afs_uint32 start, unsigned char life)
4140 if (life == TKTLIFENOEXPIRE)
4142 if (life < TKTLIFEMINFIXED)
4143 return start + life * 5 * 60;
4144 if (life > TKTLIFEMAXFIXED)
4145 return start + MAXTKTLIFETIME;
4146 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
4147 return start + realLife;
4150 /* time_to_life - takes start and end times for the ticket and returns a
4151 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
4152 * lifetimes above 127*5minutes. First, the special case of (end ==
4153 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
4154 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
4155 * less than the first table entry are handled by rounding the requested
4156 * lifetime *up* to the next 5 minute interval. The final step is to search
4157 * the table for the smallest entry *greater than or equal* to the requested
4158 * entry. The actual code is prepared to handle the case where the table is
4159 * unordered but that it an unnecessary frill. */
4161 static unsigned char
4162 time_to_life(afs_uint32 start, afs_uint32 end)
4164 int lifetime = end - start;
4168 if (end == NEVERDATE)
4169 return TKTLIFENOEXPIRE;
4170 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
4172 if (lifetime < tkt_lifetimes[0])
4173 return (lifetime + 5 * 60 - 1) / (5 * 60);
4175 best = MAXKTCTICKETLIFETIME;
4176 for (i = 0; i < TKTLIFENUMFIXED; i++)
4177 if (tkt_lifetimes[i] >= lifetime) {
4178 int diff = tkt_lifetimes[i] - lifetime;
4186 return best_i + TKTLIFEMINFIXED;