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.
64 #include <afsconfig.h>
65 #include <afs/param.h>
69 #include <afs/ptserver.h>
70 #include <afs/ptuser.h>
72 #include <afs/com_err.h>
74 #include <WINNT\afsreg.h>
78 #include "afskfw-int.h"
86 * TIMING _____________________________________________________________________
90 #define cminREMIND_TEST 1 // test every minute for expired creds
91 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
92 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
93 #define cminMINLIFE 30 // minimum life of Kerberos creds
95 #define c100ns1SECOND (LONGLONG)10000000
96 #define cmsec1SECOND 1000
97 #define cmsec1MINUTE 60000
98 #define csec1MINUTE 60
100 /* Function Pointer Declarations for Delayed Loading */
102 DECL_FUNC_PTR(cc_initialize);
103 DECL_FUNC_PTR(cc_shutdown);
104 DECL_FUNC_PTR(cc_get_NC_info);
105 DECL_FUNC_PTR(cc_free_NC_info);
109 DECL_FUNC_PTR(Leash_get_default_lifetime);
110 DECL_FUNC_PTR(Leash_get_default_forwardable);
111 DECL_FUNC_PTR(Leash_get_default_renew_till);
112 DECL_FUNC_PTR(Leash_get_default_noaddresses);
113 DECL_FUNC_PTR(Leash_get_default_proxiable);
114 DECL_FUNC_PTR(Leash_get_default_publicip);
115 DECL_FUNC_PTR(Leash_get_default_use_krb4);
116 DECL_FUNC_PTR(Leash_get_default_life_min);
117 DECL_FUNC_PTR(Leash_get_default_life_max);
118 DECL_FUNC_PTR(Leash_get_default_renew_min);
119 DECL_FUNC_PTR(Leash_get_default_renew_max);
120 DECL_FUNC_PTR(Leash_get_default_renewable);
121 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
125 DECL_FUNC_PTR(krb5_change_password);
126 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
127 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
128 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
129 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
130 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
131 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
132 DECL_FUNC_PTR(krb5_get_init_creds_password);
133 DECL_FUNC_PTR(krb5_build_principal_ext);
134 DECL_FUNC_PTR(krb5_cc_get_name);
135 DECL_FUNC_PTR(krb5_cc_resolve);
136 DECL_FUNC_PTR(krb5_cc_default);
137 DECL_FUNC_PTR(krb5_cc_default_name);
138 DECL_FUNC_PTR(krb5_cc_set_default_name);
139 DECL_FUNC_PTR(krb5_cc_initialize);
140 DECL_FUNC_PTR(krb5_cc_destroy);
141 DECL_FUNC_PTR(krb5_cc_close);
142 DECL_FUNC_PTR(krb5_cc_store_cred);
143 DECL_FUNC_PTR(krb5_cc_copy_creds);
144 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
145 DECL_FUNC_PTR(krb5_cc_get_principal);
146 DECL_FUNC_PTR(krb5_cc_start_seq_get);
147 DECL_FUNC_PTR(krb5_cc_next_cred);
148 DECL_FUNC_PTR(krb5_cc_end_seq_get);
149 DECL_FUNC_PTR(krb5_cc_remove_cred);
150 DECL_FUNC_PTR(krb5_cc_set_flags);
151 DECL_FUNC_PTR(krb5_cc_get_type);
152 DECL_FUNC_PTR(krb5_free_context);
153 DECL_FUNC_PTR(krb5_free_cred_contents);
154 DECL_FUNC_PTR(krb5_free_principal);
155 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
156 DECL_FUNC_PTR(krb5_init_context);
157 DECL_FUNC_PTR(krb5_parse_name);
158 DECL_FUNC_PTR(krb5_timeofday);
159 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
160 DECL_FUNC_PTR(krb5_unparse_name);
161 DECL_FUNC_PTR(krb5_get_credentials);
162 DECL_FUNC_PTR(krb5_mk_req);
163 DECL_FUNC_PTR(krb5_sname_to_principal);
164 DECL_FUNC_PTR(krb5_get_credentials_renew);
165 DECL_FUNC_PTR(krb5_free_data);
166 DECL_FUNC_PTR(krb5_free_data_contents);
167 DECL_FUNC_PTR(krb5_free_unparsed_name);
168 DECL_FUNC_PTR(krb5_os_localaddr);
169 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
170 DECL_FUNC_PTR(krb5_copy_data);
171 DECL_FUNC_PTR(krb5_free_creds);
172 DECL_FUNC_PTR(krb5_build_principal);
173 DECL_FUNC_PTR(krb5_get_renewed_creds);
174 DECL_FUNC_PTR(krb5_get_default_config_files);
175 DECL_FUNC_PTR(krb5_free_config_files);
176 DECL_FUNC_PTR(krb5_get_default_realm);
177 DECL_FUNC_PTR(krb5_free_default_realm);
178 DECL_FUNC_PTR(krb5_free_ticket);
179 DECL_FUNC_PTR(krb5_decode_ticket);
180 DECL_FUNC_PTR(krb5_get_host_realm);
181 DECL_FUNC_PTR(krb5_free_host_realm);
182 DECL_FUNC_PTR(krb5_free_addresses);
183 DECL_FUNC_PTR(krb5_c_random_make_octets);
185 // Krb5 KFW 3.2 functions
186 DECL_FUNC_PTR(krb5_get_error_message);
187 DECL_FUNC_PTR(krb5_free_error_message);
191 DECL_FUNC_PTR(krb524_init_ets);
192 DECL_FUNC_PTR(krb524_convert_creds_kdc);
197 DECL_FUNC_PTR(krb_get_cred);
198 DECL_FUNC_PTR(tkt_string);
199 DECL_FUNC_PTR(krb_get_tf_realm);
200 DECL_FUNC_PTR(krb_mk_req);
204 DECL_FUNC_PTR(com_err);
205 DECL_FUNC_PTR(error_message);
208 DECL_FUNC_PTR(profile_init);
209 DECL_FUNC_PTR(profile_release);
210 DECL_FUNC_PTR(profile_get_subsection_names);
211 DECL_FUNC_PTR(profile_free_list);
212 DECL_FUNC_PTR(profile_get_string);
213 DECL_FUNC_PTR(profile_release_string);
216 DECL_FUNC_PTR(OpenSCManagerA);
217 DECL_FUNC_PTR(OpenServiceA);
218 DECL_FUNC_PTR(QueryServiceStatus);
219 DECL_FUNC_PTR(CloseServiceHandle);
221 DECL_FUNC_PTR(LsaNtStatusToWinError);
222 #endif /* USE_MS2MIT */
226 DECL_FUNC_PTR(LsaConnectUntrusted);
227 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
228 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
229 DECL_FUNC_PTR(LsaFreeReturnBuffer);
230 DECL_FUNC_PTR(LsaGetLogonSessionData);
231 #endif /* USE_MS2MIT */
234 FUNC_INFO ccapi_fi[] = {
235 MAKE_FUNC_INFO(cc_initialize),
236 MAKE_FUNC_INFO(cc_shutdown),
237 MAKE_FUNC_INFO(cc_get_NC_info),
238 MAKE_FUNC_INFO(cc_free_NC_info),
243 FUNC_INFO leash_fi[] = {
244 MAKE_FUNC_INFO(Leash_get_default_lifetime),
245 MAKE_FUNC_INFO(Leash_get_default_renew_till),
246 MAKE_FUNC_INFO(Leash_get_default_forwardable),
247 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
248 MAKE_FUNC_INFO(Leash_get_default_proxiable),
249 MAKE_FUNC_INFO(Leash_get_default_publicip),
250 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
251 MAKE_FUNC_INFO(Leash_get_default_life_min),
252 MAKE_FUNC_INFO(Leash_get_default_life_max),
253 MAKE_FUNC_INFO(Leash_get_default_renew_min),
254 MAKE_FUNC_INFO(Leash_get_default_renew_max),
255 MAKE_FUNC_INFO(Leash_get_default_renewable),
259 FUNC_INFO leash_opt_fi[] = {
260 MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
265 FUNC_INFO k5_fi[] = {
266 MAKE_FUNC_INFO(krb5_change_password),
267 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
268 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
269 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
270 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
271 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
272 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
273 MAKE_FUNC_INFO(krb5_get_init_creds_password),
274 MAKE_FUNC_INFO(krb5_build_principal_ext),
275 MAKE_FUNC_INFO(krb5_cc_get_name),
276 MAKE_FUNC_INFO(krb5_cc_resolve),
277 MAKE_FUNC_INFO(krb5_cc_default),
278 MAKE_FUNC_INFO(krb5_cc_default_name),
279 MAKE_FUNC_INFO(krb5_cc_set_default_name),
280 MAKE_FUNC_INFO(krb5_cc_initialize),
281 MAKE_FUNC_INFO(krb5_cc_destroy),
282 MAKE_FUNC_INFO(krb5_cc_close),
283 MAKE_FUNC_INFO(krb5_cc_copy_creds),
284 MAKE_FUNC_INFO(krb5_cc_store_cred),
285 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
286 MAKE_FUNC_INFO(krb5_cc_get_principal),
287 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
288 MAKE_FUNC_INFO(krb5_cc_next_cred),
289 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
290 MAKE_FUNC_INFO(krb5_cc_remove_cred),
291 MAKE_FUNC_INFO(krb5_cc_set_flags),
292 MAKE_FUNC_INFO(krb5_cc_get_type),
293 MAKE_FUNC_INFO(krb5_free_context),
294 MAKE_FUNC_INFO(krb5_free_cred_contents),
295 MAKE_FUNC_INFO(krb5_free_principal),
296 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
297 MAKE_FUNC_INFO(krb5_init_context),
298 MAKE_FUNC_INFO(krb5_parse_name),
299 MAKE_FUNC_INFO(krb5_timeofday),
300 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
301 MAKE_FUNC_INFO(krb5_unparse_name),
302 MAKE_FUNC_INFO(krb5_get_credentials),
303 MAKE_FUNC_INFO(krb5_mk_req),
304 MAKE_FUNC_INFO(krb5_sname_to_principal),
305 MAKE_FUNC_INFO(krb5_get_credentials_renew),
306 MAKE_FUNC_INFO(krb5_free_data),
307 MAKE_FUNC_INFO(krb5_free_data_contents),
308 MAKE_FUNC_INFO(krb5_free_unparsed_name),
309 MAKE_FUNC_INFO(krb5_os_localaddr),
310 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
311 MAKE_FUNC_INFO(krb5_copy_data),
312 MAKE_FUNC_INFO(krb5_free_creds),
313 MAKE_FUNC_INFO(krb5_build_principal),
314 MAKE_FUNC_INFO(krb5_get_renewed_creds),
315 MAKE_FUNC_INFO(krb5_free_addresses),
316 MAKE_FUNC_INFO(krb5_get_default_config_files),
317 MAKE_FUNC_INFO(krb5_free_config_files),
318 MAKE_FUNC_INFO(krb5_get_default_realm),
319 MAKE_FUNC_INFO(krb5_free_default_realm),
320 MAKE_FUNC_INFO(krb5_free_ticket),
321 MAKE_FUNC_INFO(krb5_decode_ticket),
322 MAKE_FUNC_INFO(krb5_get_host_realm),
323 MAKE_FUNC_INFO(krb5_free_host_realm),
324 MAKE_FUNC_INFO(krb5_free_addresses),
325 MAKE_FUNC_INFO(krb5_c_random_make_octets),
329 FUNC_INFO k5_kfw_32_fi[] = {
330 MAKE_FUNC_INFO(krb5_get_error_message),
331 MAKE_FUNC_INFO(krb5_free_error_message),
336 FUNC_INFO k4_fi[] = {
337 MAKE_FUNC_INFO(krb_get_cred),
338 MAKE_FUNC_INFO(krb_get_tf_realm),
339 MAKE_FUNC_INFO(krb_mk_req),
340 MAKE_FUNC_INFO(tkt_string),
346 FUNC_INFO k524_fi[] = {
347 MAKE_FUNC_INFO(krb524_init_ets),
348 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
353 FUNC_INFO profile_fi[] = {
354 MAKE_FUNC_INFO(profile_init),
355 MAKE_FUNC_INFO(profile_release),
356 MAKE_FUNC_INFO(profile_get_subsection_names),
357 MAKE_FUNC_INFO(profile_free_list),
358 MAKE_FUNC_INFO(profile_get_string),
359 MAKE_FUNC_INFO(profile_release_string),
363 FUNC_INFO ce_fi[] = {
364 MAKE_FUNC_INFO(com_err),
365 MAKE_FUNC_INFO(error_message),
369 FUNC_INFO service_fi[] = {
370 MAKE_FUNC_INFO(OpenSCManagerA),
371 MAKE_FUNC_INFO(OpenServiceA),
372 MAKE_FUNC_INFO(QueryServiceStatus),
373 MAKE_FUNC_INFO(CloseServiceHandle),
375 MAKE_FUNC_INFO(LsaNtStatusToWinError),
376 #endif /* USE_MS2MIT */
381 FUNC_INFO lsa_fi[] = {
382 MAKE_FUNC_INFO(LsaConnectUntrusted),
383 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
384 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
385 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
386 MAKE_FUNC_INFO(LsaGetLogonSessionData),
389 #endif /* USE_MS2MIT */
391 /* Static Prototypes */
392 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
393 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *, unsigned short);
394 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
395 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
396 void *data, const char *name, const char *banner, int num_prompts,
397 krb5_prompt prompts[]);
400 /* Static Declarations */
401 static int inited = 0;
402 static int mid_cnt = 0;
403 static struct textField * mid_tb = NULL;
404 static HINSTANCE hKrb5 = 0;
405 static HINSTANCE hKrb5_kfw_32 = 0;
407 static HINSTANCE hKrb4 = 0;
408 #endif /* USE_KRB4 */
410 static HINSTANCE hKrb524 = 0;
413 static HINSTANCE hSecur32 = 0;
414 #endif /* USE_MS2MIT */
415 static HINSTANCE hAdvApi32 = 0;
416 static HINSTANCE hComErr = 0;
417 static HINSTANCE hService = 0;
418 static HINSTANCE hProfile = 0;
420 static HINSTANCE hLeash = 0;
421 static HINSTANCE hLeashOpt = 0;
423 static HINSTANCE hCCAPI = 0;
424 static struct principal_ccache_data * princ_cc_data = NULL;
425 static struct cell_principal_map * cell_princ_map = NULL;
428 #define DEFAULT_LIFETIME pLeash_get_default_lifetime()
430 #define DEFAULT_LIFETIME (24 * 60)
436 static int inited = 0;
439 char mutexName[MAX_PATH];
440 HANDLE hMutex = NULL;
442 StringCbPrintf( mutexName, sizeof(mutexName), "AFS KFW Init pid=%d", getpid());
444 hMutex = CreateMutex( NULL, TRUE, mutexName );
445 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
446 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
452 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
453 LoadFuncs(KRB5_DLL, k5_kfw_32_fi, &hKrb5_kfw_32, 0, 1, 0, 0);
454 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
455 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
457 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
458 #endif /* USE_KRB4 */
459 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
461 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
462 #endif /* USE_MS2MIT */
464 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
467 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
468 LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
470 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
472 if ( KFW_is_available() ) {
473 char rootcell[CELL_MAXNAMELEN+1];
475 KFW_import_windows_lsa();
476 #endif /* USE_MS2MIT */
477 KFW_import_ccache_data();
478 KFW_AFS_renew_expiring_tokens();
480 /* WIN32 NOTE: no way to get max chars */
481 if (!cm_GetRootCellName(rootcell))
482 KFW_AFS_renew_token_for_cell(rootcell);
485 ReleaseMutex(hMutex);
488 initialize_KTC_error_table();
489 initialize_PT_error_table();
498 FreeLibrary(hLeashOpt);
504 FreeLibrary(hKrb524);
510 FreeLibrary(hSecur32);
511 #endif /* USE_MS2MIT */
513 FreeLibrary(hService);
515 FreeLibrary(hComErr);
517 FreeLibrary(hProfile);
521 #endif /* USE_KRB4 */
525 FreeLibrary(hKrb5_kfw_32);
528 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
531 static int init = TRUE;
532 static int bIsWow64 = FALSE;
536 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
538 hModule = GetModuleHandle(TEXT("kernel32"));
540 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
542 if (NULL != fnIsWow64Process)
544 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
546 // on error, assume FALSE.
547 // in other words, do nothing.
550 FreeLibrary(hModule);
558 KFW_accept_dotted_usernames(void)
564 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
565 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
566 if (code == ERROR_SUCCESS) {
568 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
569 (BYTE *) &value, &len);
570 RegCloseKey(parmKey);
572 if (code != ERROR_SUCCESS) {
573 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
574 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
575 if (code == ERROR_SUCCESS) {
577 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
578 (BYTE *) &value, &len);
579 RegCloseKey (parmKey);
593 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
594 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
595 if (code == ERROR_SUCCESS) {
596 len = sizeof(use524);
597 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
598 (BYTE *) &use524, &len);
599 RegCloseKey(parmKey);
601 if (code != ERROR_SUCCESS) {
602 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
603 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
604 if (code == ERROR_SUCCESS) {
605 len = sizeof(use524);
606 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
607 (BYTE *) &use524, &len);
608 RegCloseKey (parmKey);
615 KFW_is_available(void)
621 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_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);
630 if (code != ERROR_SUCCESS) {
631 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
632 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
633 if (code == ERROR_SUCCESS) {
634 len = sizeof(enableKFW);
635 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
636 (BYTE *) &enableKFW, &len);
637 RegCloseKey (parmKey);
645 if ( hKrb5 && hComErr && hService &&
648 #endif /* USE_MS2MIT */
661 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
662 int FreeContextFlag, krb5_context * ctx,
667 int krb5Error = ((int)(rc & 255));
679 if (pkrb5_get_error_message)
680 errText = pkrb5_get_error_message(ctx, rc);
682 errText = perror_message(rc);
683 StringCbPrintf(message, sizeof(message),
684 "%s\n(Kerberos error %ld)\n\n%s failed",
688 if (pkrb5_free_error_message)
689 pkrb5_free_error_message(ctx, (char *)errText);
691 if ( IsDebuggerPresent() )
692 OutputDebugString(message);
694 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
697 if (FreeContextFlag == 1)
699 if (ctx && *ctx != NULL)
701 if (cache && *cache != NULL) {
702 pkrb5_cc_close(*ctx, *cache);
706 pkrb5_free_context(*ctx);
715 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
717 struct principal_ccache_data * next = princ_cc_data;
718 krb5_principal principal = 0;
720 const char * ccname = NULL;
721 const char * cctype = NULL;
722 char * ccfullname = NULL;
723 krb5_error_code code = 0;
724 krb5_error_code cc_code = 0;
730 if (ctx == 0 || cc == 0)
733 code = pkrb5_cc_get_principal(ctx, cc, &principal);
736 code = pkrb5_unparse_name(ctx, principal, &pname);
737 if ( code ) goto cleanup;
739 ccname = pkrb5_cc_get_name(ctx, cc);
740 if (!ccname) goto cleanup;
742 cctype = pkrb5_cc_get_type(ctx, cc);
743 if (!cctype) goto cleanup;
745 ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
746 if (!ccfullname) goto cleanup;
748 StringCbPrintf(ccfullname, sizeof(ccfullname), "%s:%s", cctype, ccname);
750 // Search the existing list to see if we have a match
752 for ( ; next ; next = next->next ) {
753 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
758 // If not, match add a new node to the beginning of the list and assign init it
760 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
761 next->next = princ_cc_data;
762 princ_cc_data = next;
763 next->principal = _strdup(pname);
764 next->ccache_name = ccfullname;
766 next->from_lsa = lsa;
768 next->expiration_time = 0;
772 flags = 0; // turn off OPENCLOSE mode
773 code = pkrb5_cc_set_flags(ctx, cc, flags);
774 if ( code ) goto cleanup;
776 code = pkrb5_timeofday(ctx, &now);
778 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
779 if (cc_code) goto cleanup;
781 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
782 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
784 // we found the ticket we are looking for
785 // check validity of timestamp
786 // We add a 5 minutes fudge factor to compensate for potential
787 // clock skew errors between the KDC and client OS
789 valid = ((creds.times.starttime > 0) &&
790 now >= (creds.times.starttime - 300) &&
791 now < (creds.times.endtime + 300) &&
792 !(creds.ticket_flags & TKT_FLG_INVALID));
794 if ( next->from_lsa) {
796 next->expiration_time = creds.times.endtime;
798 } else if ( valid ) {
800 next->expiration_time = creds.times.endtime;
801 next->renew = (creds.times.renew_till > creds.times.endtime) &&
802 (creds.ticket_flags & TKT_FLG_RENEWABLE);
805 next->expiration_time = 0;
809 pkrb5_free_cred_contents(ctx, &creds);
810 cc_code = KRB5_CC_END;
813 pkrb5_free_cred_contents(ctx, &creds);
816 if (cc_code == KRB5_CC_END) {
817 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
818 if (code) goto cleanup;
822 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
823 code = pkrb5_cc_set_flags(ctx, cc, flags);
828 pkrb5_free_unparsed_name(ctx,pname);
830 pkrb5_free_principal(ctx,principal);
834 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
836 struct principal_ccache_data * next = princ_cc_data;
837 char * response = NULL;
839 if ( !principal || !ccache )
843 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
845 // we always want to prefer the MS Kerberos LSA cache or
846 // the cache afscreds created specifically for the principal
847 // if the current entry is either one, drop the previous find
848 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
851 response = _strdup(next->ccache_name);
852 // MS Kerberos LSA is our best option so use it and quit
853 if ( next->from_lsa )
867 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
869 struct principal_ccache_data ** next = &princ_cc_data;
871 if ( !pname && !ccname )
875 if ( !strcmp((*next)->principal,pname) ||
876 !strcmp((*next)->ccache_name,ccname) ) {
878 free((*next)->principal);
879 free((*next)->ccache_name);
881 (*next) = (*next)->next;
888 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
890 struct cell_principal_map * next = cell_princ_map;
892 // Search the existing list to see if we have a match
894 for ( ; next ; next = next->next ) {
895 if ( !strcmp(next->cell, cell) ) {
896 if ( !strcmp(next->principal,pname) ) {
897 next->active = active;
900 // OpenAFS currently has a restriction of one active token per cell
901 // Therefore, whenever we update the table with a new active cell we
902 // must mark all of the other principal to cell entries as inactive.
910 // If not, match add a new node to the beginning of the list and assign init it
912 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
913 next->next = cell_princ_map;
914 cell_princ_map = next;
915 next->principal = _strdup(pname);
916 next->cell = _strdup(cell);
917 next->active = active;
922 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
924 struct cell_principal_map ** next = &cell_princ_map;
926 if ( !pname && !cell )
930 if ( !strcmp((*next)->principal,pname) ||
931 !strcmp((*next)->cell,cell) ) {
933 free((*next)->principal);
936 (*next) = (*next)->next;
942 // Returns (if possible) a principal which has been known in
943 // the past to have been used to obtain tokens for the specified
945 // TODO: Attempt to return one which has not yet expired by checking
946 // the principal/ccache data
948 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
950 struct cell_principal_map * next_map = cell_princ_map;
951 const char * princ = NULL;
958 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
961 next_map = next_map->next;
964 if ( !principals || !count )
967 *principals = (char **) malloc(sizeof(char *) * count);
968 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
970 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
971 (*principals)[i++] = _strdup(next_map->principal);
978 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
981 struct cell_principal_map * next_map = cell_princ_map;
982 const char * princ = NULL;
988 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
991 next_map = next_map->next;
997 *cells = (char **) malloc(sizeof(char *) * count);
998 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
1000 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
1001 (*cells)[i++] = _strdup(next_map->cell);
1007 /* Given a principal return an existing ccache or create one and return */
1009 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
1011 krb5_context ctx = NULL;
1012 char * pname = NULL;
1013 char * ccname = NULL;
1014 krb5_error_code code;
1016 if (!pkrb5_init_context)
1017 return KRB5_CONFIG_CANTOPEN;
1022 code = pkrb5_init_context(&ctx);
1023 if (code) goto cleanup;
1027 code = pkrb5_unparse_name(ctx, principal, &pname);
1028 if (code) goto cleanup;
1030 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
1031 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
1032 size_t len = strlen(pname) + 5;
1033 ccname = (char *)malloc(len);
1034 StringCbPrintf(ccname, len, "API:%s", pname);
1036 code = pkrb5_cc_resolve(ctx, ccname, cc);
1038 code = pkrb5_cc_default(ctx, cc);
1039 if (code) goto cleanup;
1046 pkrb5_free_unparsed_name(ctx,pname);
1047 if (ctx && (ctx != alt_ctx))
1048 pkrb5_free_context(ctx);
1053 // Import Microsoft Credentials into a new MIT ccache
1055 KFW_import_windows_lsa(void)
1057 krb5_context ctx = NULL;
1058 krb5_ccache cc = NULL;
1059 krb5_principal princ = NULL;
1060 char * pname = NULL;
1061 krb5_data * princ_realm;
1062 krb5_error_code code;
1063 char cell[128]="", realm[128]="", *def_realm = 0;
1065 DWORD dwMsLsaImport;
1067 if (!pkrb5_init_context)
1070 code = pkrb5_init_context(&ctx);
1071 if (code) goto cleanup;
1073 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
1074 if (code) goto cleanup;
1076 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
1078 code = pkrb5_cc_get_principal(ctx, cc, &princ);
1079 if ( code ) goto cleanup;
1082 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
1086 switch ( dwMsLsaImport ) {
1087 case 0: /* do not import */
1089 case 1: /* always import */
1091 case 2: { /* matching realm */
1092 char ms_realm[128] = "", *r;
1095 for ( r=ms_realm, j=0; j<krb5_princ_realm(ctx, princ)->length; r++, j++ ) {
1096 *r = krb5_princ_realm(ctx, princ)->data[j];
1100 if (code = pkrb5_get_default_realm(ctx, &def_realm))
1103 if (strcmp(def_realm, ms_realm))
1111 code = pkrb5_unparse_name(ctx,princ,&pname);
1112 if ( code ) goto cleanup;
1114 princ_realm = krb5_princ_realm(ctx, princ);
1115 for ( i=0; i<princ_realm->length; i++ ) {
1116 realm[i] = princ_realm->data[i];
1117 cell[i] = tolower(princ_realm->data[i]);
1122 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, DEFAULT_LIFETIME, NULL);
1123 if ( IsDebuggerPresent() ) {
1125 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1126 OutputDebugString(message);
1128 if ( code ) goto cleanup;
1130 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1134 pkrb5_free_unparsed_name(ctx,pname);
1136 pkrb5_free_principal(ctx,princ);
1138 pkrb5_free_default_realm(ctx, def_realm);
1140 pkrb5_cc_close(ctx,cc);
1142 pkrb5_free_context(ctx);
1144 #endif /* USE_MS2MIT */
1146 // If there are existing MIT credentials, copy them to a new
1147 // ccache named after the principal
1149 // Enumerate all existing MIT ccaches and construct entries
1150 // in the principal_ccache table
1152 // Enumerate all existing AFS Tokens and construct entries
1153 // in the cell_principal table
1155 KFW_import_ccache_data(void)
1157 krb5_context ctx = NULL;
1158 krb5_ccache cc = NULL;
1159 krb5_principal principal = NULL;
1161 krb5_error_code code;
1162 krb5_error_code cc_code;
1164 apiCB * cc_ctx = NULL;
1165 struct _infoNC ** pNCi = NULL;
1168 if ( !pcc_initialize )
1171 if ( IsDebuggerPresent() )
1172 OutputDebugString("KFW_import_ccache_data()\n");
1174 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1175 if (code) goto cleanup;
1177 code = pcc_get_NC_info(cc_ctx, &pNCi);
1178 if (code) goto cleanup;
1180 code = pkrb5_init_context(&ctx);
1181 if (code) goto cleanup;
1183 for ( i=0; pNCi[i]; i++ ) {
1184 if ( pNCi[i]->vers != CC_CRED_V5 )
1186 if ( IsDebuggerPresent() ) {
1187 OutputDebugString("Principal: ");
1188 OutputDebugString(pNCi[i]->principal);
1189 OutputDebugString(" in ccache ");
1190 OutputDebugString(pNCi[i]->name);
1191 OutputDebugString("\n");
1193 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1194 && strcmp(pNCi[i]->name,LSA_CCNAME)
1197 for ( j=0; pNCi[j]; j++ ) {
1198 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1204 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1205 if (code) goto loop_cleanup;
1208 krb5_ccache oldcc = 0;
1210 if ( IsDebuggerPresent() )
1211 OutputDebugString("copying ccache data to new ccache\n");
1213 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1214 if (code) goto loop_cleanup;
1215 code = pkrb5_cc_initialize(ctx, cc, principal);
1216 if (code) goto loop_cleanup;
1218 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1219 if (code) goto loop_cleanup;
1220 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1222 code = pkrb5_cc_close(ctx,cc);
1224 code = pkrb5_cc_close(ctx,oldcc);
1226 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1229 code = pkrb5_cc_close(ctx,oldcc);
1232 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1233 if (code) goto loop_cleanup;
1236 flags = 0; // turn off OPENCLOSE mode
1237 code = pkrb5_cc_set_flags(ctx, cc, flags);
1238 if ( code ) goto cleanup;
1240 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1242 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1243 if (cc_code) goto cleanup;
1245 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1246 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1247 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1248 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1249 if ( sname && cell && !strcmp("afs",sname->data) ) {
1250 struct ktc_principal aserver;
1251 struct ktc_principal aclient;
1252 struct ktc_token atoken;
1255 if ( IsDebuggerPresent() ) {
1256 OutputDebugString("Found AFS ticket: ");
1257 OutputDebugString(sname->data);
1259 OutputDebugString("/");
1260 OutputDebugString(cell->data);
1262 OutputDebugString("@");
1263 OutputDebugString(realm->data);
1264 OutputDebugString("\n");
1267 memset(&aserver, '\0', sizeof(aserver));
1268 StringCbCopyN( aserver.name, sizeof(aserver.name),
1269 sname->data, sizeof(aserver.name) - 1);
1270 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
1271 cell->data, sizeof(aserver.cell) - 1);
1273 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1275 // Found a token in AFS Client Server which matches
1276 char pname[128], *p, *q;
1277 for ( p=pname, q=aclient.name; *q; p++, q++)
1279 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1283 if ( IsDebuggerPresent() ) {
1284 OutputDebugString("Found AFS token: ");
1285 OutputDebugString(pname);
1286 OutputDebugString("\n");
1289 if ( strcmp(pname,pNCi[i]->principal) )
1291 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1293 // Attempt to import it
1294 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1296 if ( IsDebuggerPresent() ) {
1297 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1300 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data, DEFAULT_LIFETIME, NULL);
1301 if ( IsDebuggerPresent() ) {
1303 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1304 OutputDebugString(message);
1307 } else if ( IsDebuggerPresent() ) {
1308 OutputDebugString("Found ticket: ");
1309 OutputDebugString(sname->data);
1310 if ( cell && cell->data ) {
1311 OutputDebugString("/");
1312 OutputDebugString(cell->data);
1314 OutputDebugString("@");
1315 OutputDebugString(realm->data);
1316 OutputDebugString("\n");
1318 pkrb5_free_cred_contents(ctx, &creds);
1321 if (cc_code == KRB5_CC_END) {
1322 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1323 if (cc_code) goto loop_cleanup;
1327 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1328 code = pkrb5_cc_set_flags(ctx, cc, flags);
1330 pkrb5_cc_close(ctx,cc);
1334 pkrb5_free_principal(ctx,principal);
1341 pkrb5_free_context(ctx);
1343 pcc_free_NC_info(cc_ctx, &pNCi);
1345 pcc_shutdown(&cc_ctx);
1350 KFW_AFS_get_cred( char * username,
1357 static char reason[1024]="";
1358 krb5_context ctx = NULL;
1359 krb5_ccache cc = NULL;
1360 char * realm = NULL, * userrealm = NULL;
1361 krb5_principal principal = NULL;
1362 char * pname = NULL;
1363 krb5_error_code code;
1364 char local_cell[CELL_MAXNAMELEN+1];
1365 char **cells = NULL;
1367 struct afsconf_cell cellconfig;
1370 if (!pkrb5_init_context)
1371 return KRB5_CONFIG_CANTOPEN;
1373 if ( IsDebuggerPresent() ) {
1374 OutputDebugString("KFW_AFS_get_cred for token ");
1375 OutputDebugString(username);
1376 OutputDebugString(" in cell ");
1377 OutputDebugString(cell);
1378 OutputDebugString("\n");
1381 memset(&cellconfig, 0, sizeof(cellconfig));
1383 code = pkrb5_init_context(&ctx);
1384 if ( code ) goto cleanup;
1386 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1387 if ( code ) goto cleanup;
1389 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1391 userrealm = strchr(username,'@');
1393 pname = strdup(username);
1394 if (!KFW_accept_dotted_usernames()) {
1395 userrealm = strchr(pname, '@');
1398 /* handle kerberos iv notation */
1399 while ( dot = strchr(pname,'.') ) {
1405 size_t len = strlen(username) + strlen(realm) + 2;
1406 pname = malloc(len);
1407 if (pname == NULL) {
1408 code = KRB5KRB_ERR_GENERIC;
1411 StringCbCopy(pname, len, username);
1413 if (!KFW_accept_dotted_usernames()) {
1414 /* handle kerberos iv notation */
1415 while ( dot = strchr(pname,'.') ) {
1419 StringCbCat( pname, len, "@");
1420 StringCbCat( pname, len, realm);
1422 if ( IsDebuggerPresent() ) {
1423 OutputDebugString("Realm of Cell: ");
1424 OutputDebugString(realm);
1425 OutputDebugString("\n");
1426 OutputDebugString("Realm of User: ");
1427 OutputDebugString(userrealm);
1428 OutputDebugString("\n");
1431 code = pkrb5_parse_name(ctx, pname, &principal);
1432 if ( code ) goto cleanup;
1434 code = KFW_get_ccache(ctx, principal, &cc);
1435 if ( code ) goto cleanup;
1437 if ( lifetime == 0 )
1438 lifetime = DEFAULT_LIFETIME;
1440 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1441 if ( IsDebuggerPresent() ) {
1443 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1444 OutputDebugString(message);
1447 if (code && password && password[0] ) {
1448 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1453 0, /* forwardable */
1454 0, /* not proxiable */
1456 1, /* noaddresses */
1457 0 /* no public ip */
1459 pLeash_get_default_forwardable(),
1460 pLeash_get_default_proxiable(),
1461 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1462 pLeash_get_default_noaddresses(),
1463 pLeash_get_default_publicip()
1464 #endif /* USE_LEASH */
1467 if ( IsDebuggerPresent() ) {
1469 StringCbPrintf(message, sizeof(message), "KFW_kinit() returns: %d\n", code);
1470 OutputDebugString(message);
1472 if ( code ) goto cleanup;
1474 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1477 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1478 if ( IsDebuggerPresent() ) {
1480 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1481 OutputDebugString(message);
1483 if ( code ) goto cleanup;
1485 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1487 // Attempt to obtain new tokens for other cells supported by the same
1489 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1490 if ( cell_count > 1 ) {
1491 while ( cell_count-- ) {
1492 if ( strcmp(cells[cell_count],cell) ) {
1493 if ( IsDebuggerPresent() ) {
1495 StringCbPrintf(message, sizeof(message),
1496 "found another cell for the same principal: %s\n", cell);
1497 OutputDebugString(message);
1500 if (cellconfig.linkedCell) {
1501 free(cellconfig.linkedCell);
1502 cellconfig.linkedCell = NULL;
1504 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1505 if ( code ) continue;
1507 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1508 if ( IsDebuggerPresent() ) {
1509 OutputDebugString("Realm: ");
1510 OutputDebugString(realm);
1511 OutputDebugString("\n");
1514 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1515 if ( IsDebuggerPresent() ) {
1517 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1518 OutputDebugString(message);
1521 free(cells[cell_count]);
1524 } else if ( cell_count == 1 ) {
1533 pkrb5_cc_close(ctx, cc);
1534 if ( cellconfig.linkedCell )
1535 free(cellconfig.linkedCell);
1537 if ( code && reasonP ) {
1539 char *msg = (char *)afs_error_message(code);
1540 if (strncmp(msg, "unknown", strlen(msg)) == 0) {
1541 if (pkrb5_get_error_message) {
1542 msg = pkrb5_get_error_message(ctx, code);
1545 msg = (char *)perror_message(code);
1547 StringCbCopyN( reason, sizeof(reason),
1548 msg, sizeof(reason) - 1);
1551 pkrb5_free_error_message(ctx, msg);
1557 KFW_AFS_destroy_tickets_for_cell(char * cell)
1559 krb5_context ctx = NULL;
1560 krb5_error_code code;
1562 char ** principals = NULL;
1564 if (!pkrb5_init_context)
1565 return KRB5_CONFIG_CANTOPEN;
1567 if ( IsDebuggerPresent() ) {
1568 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1569 OutputDebugString(cell);
1570 OutputDebugString("\n");
1573 code = pkrb5_init_context(&ctx);
1576 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1578 krb5_principal princ = 0;
1582 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1583 if ( cell_count > 1 ) {
1584 // TODO - What we really should do here is verify whether or not any of the
1585 // other cells which use this principal to obtain its credentials actually
1586 // have valid tokens or not. If they are currently using these credentials
1587 // we will skip them. For the time being we assume that if there is an active
1588 // map in the table that they are actively being used.
1592 code = pkrb5_parse_name(ctx, principals[count], &princ);
1593 if (code) goto loop_cleanup;
1595 code = KFW_get_ccache(ctx, princ, &cc);
1596 if (code) goto loop_cleanup;
1598 code = pkrb5_cc_destroy(ctx, cc);
1603 pkrb5_cc_close(ctx, cc);
1607 pkrb5_free_principal(ctx, princ);
1611 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1612 free(principals[count]);
1617 pkrb5_free_context(ctx);
1622 KFW_AFS_destroy_tickets_for_principal(char * user)
1624 krb5_context ctx = NULL;
1625 krb5_error_code code;
1627 char ** cells = NULL;
1628 krb5_principal princ = NULL;
1629 krb5_ccache cc = NULL;
1631 if (!pkrb5_init_context)
1632 return KRB5_CONFIG_CANTOPEN;
1634 if ( IsDebuggerPresent() ) {
1635 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1636 OutputDebugString(user);
1637 OutputDebugString("\n");
1640 code = pkrb5_init_context(&ctx);
1643 code = pkrb5_parse_name(ctx, user, &princ);
1644 if (code) goto loop_cleanup;
1646 code = KFW_get_ccache(ctx, princ, &cc);
1647 if (code) goto loop_cleanup;
1649 code = pkrb5_cc_destroy(ctx, cc);
1654 pkrb5_cc_close(ctx, cc);
1658 pkrb5_free_principal(ctx, princ);
1662 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1665 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1672 pkrb5_free_context(ctx);
1677 KFW_AFS_renew_expiring_tokens(void)
1679 krb5_error_code code = 0;
1680 krb5_context ctx = NULL;
1681 krb5_ccache cc = NULL;
1683 struct principal_ccache_data * pcc_next = princ_cc_data;
1686 const char * realm = NULL;
1687 char local_cell[CELL_MAXNAMELEN+1]="";
1688 struct afsconf_cell cellconfig;
1690 if (!pkrb5_init_context)
1691 return KRB5_CONFIG_CANTOPEN;
1693 if ( pcc_next == NULL ) // nothing to do
1696 if ( IsDebuggerPresent() ) {
1697 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1700 memset(&cellconfig, 0, sizeof(cellconfig));
1702 code = pkrb5_init_context(&ctx);
1703 if (code) goto cleanup;
1705 code = pkrb5_timeofday(ctx, &now);
1706 if (code) goto cleanup;
1708 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1709 if ( pcc_next->expired )
1712 if ( now >= (pcc_next->expiration_time) ) {
1713 if ( !pcc_next->from_lsa ) {
1714 pcc_next->expired = 1;
1719 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1720 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1723 code = KFW_renew(ctx,cc);
1725 if ( code && pcc_next->from_lsa)
1727 #endif /* USE_MS2MIT */
1730 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1731 if (code) goto loop_cleanup;
1733 // Attempt to obtain new tokens for other cells supported by the same
1735 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1736 if ( cell_count > 0 ) {
1737 while ( cell_count-- ) {
1738 if ( IsDebuggerPresent() ) {
1739 OutputDebugString("Cell: ");
1740 OutputDebugString(cells[cell_count]);
1741 OutputDebugString("\n");
1743 if (cellconfig.linkedCell) {
1744 free(cellconfig.linkedCell);
1745 cellconfig.linkedCell = NULL;
1747 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1748 if ( code ) continue;
1749 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1750 if ( IsDebuggerPresent() ) {
1751 OutputDebugString("Realm: ");
1752 OutputDebugString(realm);
1753 OutputDebugString("\n");
1755 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1756 if ( IsDebuggerPresent() ) {
1758 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1759 OutputDebugString(message);
1761 free(cells[cell_count]);
1769 pkrb5_cc_close(ctx,cc);
1776 pkrb5_cc_close(ctx,cc);
1778 pkrb5_free_context(ctx);
1779 if (cellconfig.linkedCell)
1780 free(cellconfig.linkedCell);
1787 KFW_AFS_renew_token_for_cell(char * cell)
1789 krb5_error_code code = 0;
1790 krb5_context ctx = NULL;
1792 char ** principals = NULL;
1794 if (!pkrb5_init_context)
1795 return KRB5_CONFIG_CANTOPEN;
1797 if ( IsDebuggerPresent() ) {
1798 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1799 OutputDebugString(cell);
1800 OutputDebugString("\n");
1803 code = pkrb5_init_context(&ctx);
1804 if (code) goto cleanup;
1806 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1808 // We know we must have a credential somewhere since we are
1809 // trying to renew a token
1811 KFW_import_ccache_data();
1812 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1815 krb5_principal princ = 0;
1816 krb5_principal service = 0;
1818 krb5_creds mcreds, creds;
1819 #endif /* COMMENT */
1821 const char * realm = NULL;
1822 struct afsconf_cell cellconfig;
1823 char local_cell[CELL_MAXNAMELEN+1];
1825 memset(&cellconfig, 0, sizeof(cellconfig));
1828 code = pkrb5_parse_name(ctx, principals[count], &princ);
1829 if (code) goto loop_cleanup;
1831 code = KFW_get_ccache(ctx, princ, &cc);
1832 if (code) goto loop_cleanup;
1834 if (cellconfig.linkedCell) {
1835 free(cellconfig.linkedCell);
1836 cellconfig.linkedCell = NULL;
1838 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1839 if ( code ) goto loop_cleanup;
1841 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1842 if ( IsDebuggerPresent() ) {
1843 OutputDebugString("Realm: ");
1844 OutputDebugString(realm);
1845 OutputDebugString("\n");
1849 /* krb5_cc_remove_cred() is not implemented
1852 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1853 realm, "afs", cell, NULL);
1855 memset(&mcreds, 0, sizeof(krb5_creds));
1856 mcreds.client = princ;
1857 mcreds.server = service;
1859 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1861 if ( IsDebuggerPresent() ) {
1862 char * cname, *sname;
1863 pkrb5_unparse_name(ctx, creds.client, &cname);
1864 pkrb5_unparse_name(ctx, creds.server, &sname);
1865 OutputDebugString("Removing credential for client \"");
1866 OutputDebugString(cname);
1867 OutputDebugString("\" and service \"");
1868 OutputDebugString(sname);
1869 OutputDebugString("\"\n");
1870 pkrb5_free_unparsed_name(ctx,cname);
1871 pkrb5_free_unparsed_name(ctx,sname);
1874 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1875 pkrb5_free_principal(ctx, creds.client);
1876 pkrb5_free_principal(ctx, creds.server);
1879 #endif /* COMMENT */
1881 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1882 if ( IsDebuggerPresent() ) {
1884 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1885 OutputDebugString(message);
1890 pkrb5_cc_close(ctx, cc);
1894 pkrb5_free_principal(ctx, princ);
1898 pkrb5_free_principal(ctx, service);
1901 if (cellconfig.linkedCell) {
1902 free(cellconfig.linkedCell);
1903 cellconfig.linkedCell = NULL;
1906 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1907 free(principals[count]);
1911 code = -1; // we did not renew the tokens
1915 pkrb5_free_context(ctx);
1916 return (code ? FALSE : TRUE);
1921 KFW_AFS_renew_tokens_for_all_cells(void)
1923 struct cell_principal_map * next = cell_princ_map;
1925 if ( IsDebuggerPresent() )
1926 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1931 for ( ; next ; next = next->next ) {
1933 KFW_AFS_renew_token_for_cell(next->cell);
1939 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1941 krb5_error_code code = 0;
1942 krb5_context ctx = NULL;
1943 krb5_ccache cc = NULL;
1944 krb5_principal me = NULL;
1945 krb5_principal server = NULL;
1946 krb5_creds my_creds;
1947 krb5_data *realm = NULL;
1949 if (!pkrb5_init_context)
1950 return KRB5_CONFIG_CANTOPEN;
1952 memset(&my_creds, 0, sizeof(krb5_creds));
1957 code = pkrb5_init_context(&ctx);
1958 if (code) goto cleanup;
1964 code = pkrb5_cc_default(ctx, &cc);
1965 if (code) goto cleanup;
1968 code = pkrb5_cc_get_principal(ctx, cc, &me);
1969 if (code) goto cleanup;
1971 realm = krb5_princ_realm(ctx, me);
1973 code = pkrb5_build_principal_ext(ctx, &server,
1974 realm->length,realm->data,
1975 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1976 realm->length,realm->data,
1981 if ( IsDebuggerPresent() ) {
1982 char * cname, *sname;
1983 pkrb5_unparse_name(ctx, me, &cname);
1984 pkrb5_unparse_name(ctx, server, &sname);
1985 OutputDebugString("Renewing credential for client \"");
1986 OutputDebugString(cname);
1987 OutputDebugString("\" and service \"");
1988 OutputDebugString(sname);
1989 OutputDebugString("\"\n");
1990 pkrb5_free_unparsed_name(ctx,cname);
1991 pkrb5_free_unparsed_name(ctx,sname);
1994 my_creds.client = me;
1995 my_creds.server = server;
1997 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1999 if ( IsDebuggerPresent() ) {
2001 StringCbPrintf(message, sizeof(message), "krb5_get_renewed_creds() failed: %d\n", code);
2002 OutputDebugString(message);
2007 code = pkrb5_cc_initialize(ctx, cc, me);
2009 if ( IsDebuggerPresent() ) {
2011 StringCbPrintf(message, sizeof(message), "krb5_cc_initialize() failed: %d\n", code);
2012 OutputDebugString(message);
2017 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2019 if ( IsDebuggerPresent() ) {
2021 StringCbPrintf(message, sizeof(message), "krb5_cc_store_cred() failed: %d\n", code);
2022 OutputDebugString(message);
2028 if (my_creds.client == me)
2029 my_creds.client = 0;
2030 if (my_creds.server == server)
2031 my_creds.server = 0;
2032 pkrb5_free_cred_contents(ctx, &my_creds);
2034 pkrb5_free_principal(ctx, me);
2036 pkrb5_free_principal(ctx, server);
2037 if (cc && (cc != alt_cc))
2038 pkrb5_cc_close(ctx, cc);
2039 if (ctx && (ctx != alt_ctx))
2040 pkrb5_free_context(ctx);
2045 KFW_kinit( krb5_context alt_ctx,
2048 char *principal_name,
2050 krb5_deltat lifetime,
2053 krb5_deltat renew_life,
2058 krb5_error_code code = 0;
2059 krb5_context ctx = NULL;
2060 krb5_ccache cc = NULL;
2061 krb5_principal me = NULL;
2063 krb5_creds my_creds;
2064 krb5_get_init_creds_opt options;
2065 krb5_address ** addrs = NULL;
2066 int i = 0, addr_count = 0;
2068 if (!pkrb5_init_context)
2069 return KRB5_CONFIG_CANTOPEN;
2071 pkrb5_get_init_creds_opt_init(&options);
2072 memset(&my_creds, 0, sizeof(my_creds));
2080 code = pkrb5_init_context(&ctx);
2081 if (code) goto cleanup;
2087 code = pkrb5_cc_default(ctx, &cc);
2088 if (code) goto cleanup;
2091 code = pkrb5_parse_name(ctx, principal_name, &me);
2095 code = pkrb5_unparse_name(ctx, me, &name);
2100 lifetime = DEFAULT_LIFETIME;
2107 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2108 pkrb5_get_init_creds_opt_set_forwardable(&options,
2109 forwardable ? 1 : 0);
2110 pkrb5_get_init_creds_opt_set_proxiable(&options,
2112 pkrb5_get_init_creds_opt_set_renew_life(&options,
2115 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2119 // we are going to add the public IP address specified by the user
2120 // to the list provided by the operating system
2121 krb5_address ** local_addrs=NULL;
2124 pkrb5_os_localaddr(ctx, &local_addrs);
2125 while ( local_addrs[i++] );
2128 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2130 pkrb5_free_addresses(ctx, local_addrs);
2133 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2135 while ( local_addrs[i] ) {
2136 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2137 if (addrs[i] == NULL) {
2138 pkrb5_free_addresses(ctx, local_addrs);
2142 addrs[i]->magic = local_addrs[i]->magic;
2143 addrs[i]->addrtype = local_addrs[i]->addrtype;
2144 addrs[i]->length = local_addrs[i]->length;
2145 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2146 if (!addrs[i]->contents) {
2147 pkrb5_free_addresses(ctx, local_addrs);
2151 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2152 local_addrs[i]->length); /* safe */
2155 pkrb5_free_addresses(ctx, local_addrs);
2157 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2158 if (addrs[i] == NULL)
2161 addrs[i]->magic = KV5M_ADDRESS;
2162 addrs[i]->addrtype = AF_INET;
2163 addrs[i]->length = 4;
2164 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2165 if (!addrs[i]->contents)
2168 netIPAddr = htonl(publicIP);
2169 memcpy(addrs[i]->contents,&netIPAddr,4);
2171 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2176 code = pkrb5_get_init_creds_password(ctx,
2179 password, // password
2180 KRB5_prompter, // prompter
2181 hParent, // prompter data
2188 code = pkrb5_cc_initialize(ctx, cc, me);
2192 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2198 for ( i=0;i<addr_count;i++ ) {
2200 if ( addrs[i]->contents )
2201 free(addrs[i]->contents);
2206 if (my_creds.client == me)
2207 my_creds.client = 0;
2208 pkrb5_free_cred_contents(ctx, &my_creds);
2210 pkrb5_free_unparsed_name(ctx, name);
2212 pkrb5_free_principal(ctx, me);
2213 if (cc && (cc != alt_cc))
2214 pkrb5_cc_close(ctx, cc);
2215 if (ctx && (ctx != alt_ctx))
2216 pkrb5_free_context(ctx);
2222 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2224 krb5_context ctx = NULL;
2225 krb5_ccache cc = NULL;
2226 krb5_error_code code;
2228 if (!pkrb5_init_context)
2229 return KRB5_CONFIG_CANTOPEN;
2237 code = pkrb5_init_context(&ctx);
2238 if (code) goto cleanup;
2244 code = pkrb5_cc_default(ctx, &cc);
2245 if (code) goto cleanup;
2248 code = pkrb5_cc_destroy(ctx, cc);
2249 if ( !code ) cc = 0;
2252 if (cc && (cc != alt_cc))
2253 pkrb5_cc_close(ctx, cc);
2254 if (ctx && (ctx != alt_ctx))
2255 pkrb5_free_context(ctx);
2263 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2265 NTSTATUS Status = 0;
2267 TOKEN_STATISTICS Stats;
2273 *ppSessionData = NULL;
2275 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2279 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2280 CloseHandle( TokenHandle );
2284 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2285 if ( FAILED(Status) || !ppSessionData )
2292 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2293 // cache. It validates whether or not it is reasonable to assume that if we
2294 // attempted to retrieve valid tickets we could do so. Microsoft does not
2295 // automatically renew expired tickets. Therefore, the cache could contain
2296 // expired or invalid tickets. Microsoft also caches the user's password
2297 // and will use it to retrieve new TGTs if the cache is empty and tickets
2301 MSLSA_IsKerberosLogon(VOID)
2303 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2304 BOOL Success = FALSE;
2306 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2307 if ( pSessionData->AuthenticationPackage.Buffer ) {
2313 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2314 usLength = (pSessionData->AuthenticationPackage).Length;
2317 StringCbCopyNW( buffer, sizeof(buffer)/sizeof(WCHAR),
2318 usBuffer, usLength);
2319 if ( !lstrcmpW(L"Kerberos",buffer) )
2323 pLsaFreeReturnBuffer(pSessionData);
2327 #endif /* USE_MS2MIT */
2329 static BOOL CALLBACK
2330 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2334 switch ( message ) {
2336 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2338 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2341 for ( i=0; i < mid_cnt ; i++ ) {
2342 if (mid_tb[i].echo == 0)
2343 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2344 else if (mid_tb[i].echo == 2)
2345 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2350 switch ( LOWORD(wParam) ) {
2352 for ( i=0; i < mid_cnt ; i++ ) {
2353 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2354 *mid_tb[i].buf = '\0';
2358 EndDialog(hDialog, LOWORD(wParam));
2366 lpwAlign( LPWORD lpIn )
2370 ul = (ULONG_PTR) lpIn;
2374 return (LPWORD) ul;;
2378 * dialog widths are measured in 1/4 character widths
2379 * dialog height are measured in 1/8 character heights
2383 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2384 char * ptext[], int numlines, int width,
2385 int tb_cnt, struct textField * tb)
2389 LPDLGITEMTEMPLATE lpdit;
2395 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2402 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2404 // Define a dialog box.
2406 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2407 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2408 | DS_SETFOREGROUND | DS_3DLOOK
2409 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2410 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2413 lpdt->cx = 20 + width * 4;
2414 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2416 lpw = (LPWORD) (lpdt + 1);
2417 *lpw++ = 0; // no menu
2418 *lpw++ = 0; // predefined dialog box class (by default)
2420 lpwsz = (LPWSTR) lpw;
2421 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2423 *lpw++ = 8; // font size (points)
2424 lpwsz = (LPWSTR) lpw;
2425 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2429 //-----------------------
2430 // Define an OK button.
2431 //-----------------------
2432 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2433 lpdit = (LPDLGITEMTEMPLATE) lpw;
2434 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2435 lpdit->dwExtendedStyle = 0;
2436 lpdit->x = (lpdt->cx - 14)/4 - 20;
2437 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2440 lpdit->id = IDOK; // OK button identifier
2442 lpw = (LPWORD) (lpdit + 1);
2444 *lpw++ = 0x0080; // button class
2446 lpwsz = (LPWSTR) lpw;
2447 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2449 *lpw++ = 0; // no creation data
2451 //-----------------------
2452 // Define an Cancel button.
2453 //-----------------------
2454 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2455 lpdit = (LPDLGITEMTEMPLATE) lpw;
2456 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2457 lpdit->dwExtendedStyle = 0;
2458 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2459 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2462 lpdit->id = IDCANCEL; // CANCEL button identifier
2464 lpw = (LPWORD) (lpdit + 1);
2466 *lpw++ = 0x0080; // button class
2468 lpwsz = (LPWSTR) lpw;
2469 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2471 *lpw++ = 0; // no creation data
2473 /* Add controls for preface data */
2474 for ( i=0; i<numlines; i++) {
2475 /*-----------------------
2476 * Define a static text control.
2477 *-----------------------*/
2478 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2479 lpdit = (LPDLGITEMTEMPLATE) lpw;
2480 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2481 lpdit->dwExtendedStyle = 0;
2483 lpdit->y = 10 + i * 14;
2484 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2486 lpdit->id = ID_TEXT + i; // text identifier
2488 lpw = (LPWORD) (lpdit + 1);
2490 *lpw++ = 0x0082; // static class
2492 lpwsz = (LPWSTR) lpw;
2493 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2494 -1, lpwsz, 2*width);
2496 *lpw++ = 0; // no creation data
2499 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2500 int len = (int)strlen(tb[i].label);
2505 for ( i=0; i<tb_cnt; i++) {
2507 /*-----------------------
2508 * Define a static text control.
2509 *-----------------------*/
2510 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2511 lpdit = (LPDLGITEMTEMPLATE) lpw;
2512 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2513 lpdit->dwExtendedStyle = 0;
2515 lpdit->y = 10 + (numlines + i + 1) * 14;
2516 lpdit->cx = pwid * 4;
2518 lpdit->id = ID_TEXT + numlines + i; // text identifier
2520 lpw = (LPWORD) (lpdit + 1);
2522 *lpw++ = 0x0082; // static class
2524 lpwsz = (LPWSTR) lpw;
2525 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2528 *lpw++ = 0; // no creation data
2530 /*-----------------------
2531 * Define an edit control.
2532 *-----------------------*/
2533 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2534 lpdit = (LPDLGITEMTEMPLATE) lpw;
2535 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2536 lpdit->dwExtendedStyle = 0;
2537 lpdit->x = 10 + (pwid + 1) * 4;
2538 lpdit->y = 10 + (numlines + i + 1) * 14;
2539 lpdit->cx = (width - (pwid + 1)) * 4;
2541 lpdit->id = ID_MID_TEXT + i; // identifier
2543 lpw = (LPWORD) (lpdit + 1);
2545 *lpw++ = 0x0081; // edit class
2547 lpwsz = (LPWSTR) lpw;
2548 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2551 *lpw++ = 0; // no creation data
2555 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2556 hwndOwner, (DLGPROC) MultiInputDialogProc);
2560 case 0: /* Timeout */
2568 StringCbPrintf(buf, sizeof(buf), "DialogBoxIndirect() failed: %d", GetLastError());
2569 MessageBox(hwndOwner,
2572 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2579 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2581 HINSTANCE hInst = 0;
2585 char * plines[16], *p = preface ? preface : "";
2588 for ( i=0; i<16; i++ )
2591 while (*p && numlines < 16) {
2592 plines[numlines++] = p;
2593 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2594 if ( *p == '\r' && *(p+1) == '\n' ) {
2597 } else if ( *p == '\n' ) {
2600 if ( strlen(plines[numlines-1]) > maxwidth )
2601 maxwidth = (int)strlen(plines[numlines-1]);
2604 for ( i=0;i<n;i++ ) {
2605 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2606 if ( maxwidth < len )
2610 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2613 static krb5_error_code KRB5_CALLCONV
2614 KRB5_prompter( krb5_context context,
2619 krb5_prompt prompts[])
2621 krb5_error_code errcode = 0;
2623 struct textField * tb = NULL;
2624 int len = 0, blen=0, nlen=0;
2625 HWND hParent = (HWND)data;
2628 nlen = (int)strlen(name)+2;
2631 blen = (int)strlen(banner)+2;
2633 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2636 memset(tb,0,sizeof(struct textField) * num_prompts);
2637 for ( i=0; i < num_prompts; i++ ) {
2638 tb[i].buf = prompts[i].reply->data;
2639 tb[i].len = prompts[i].reply->length;
2640 tb[i].label = prompts[i].prompt;
2642 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2645 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2647 for ( i=0; i < num_prompts; i++ )
2648 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2656 for (i = 0; i < num_prompts; i++) {
2657 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2664 KFW_AFS_wait_for_service_start(void)
2669 CurrentState = SERVICE_START_PENDING;
2670 memset(HostName, '\0', sizeof(HostName));
2671 gethostname(HostName, sizeof(HostName));
2673 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2675 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2677 if ( IsDebuggerPresent() ) {
2678 switch ( CurrentState ) {
2679 case SERVICE_STOPPED:
2680 OutputDebugString("SERVICE_STOPPED\n");
2682 case SERVICE_START_PENDING:
2683 OutputDebugString("SERVICE_START_PENDING\n");
2685 case SERVICE_STOP_PENDING:
2686 OutputDebugString("SERVICE_STOP_PENDING\n");
2688 case SERVICE_RUNNING:
2689 OutputDebugString("SERVICE_RUNNING\n");
2691 case SERVICE_CONTINUE_PENDING:
2692 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2694 case SERVICE_PAUSE_PENDING:
2695 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2697 case SERVICE_PAUSED:
2698 OutputDebugString("SERVICE_PAUSED\n");
2701 OutputDebugString("UNKNOWN Service State\n");
2704 if (CurrentState == SERVICE_STOPPED)
2706 if (CurrentState == SERVICE_RUNNING)
2722 memset(HostName, '\0', sizeof(HostName));
2723 gethostname(HostName, sizeof(HostName));
2724 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2726 if (CurrentState != SERVICE_RUNNING)
2729 rc = ktc_ForgetAllTokens();
2735 #define ALLOW_REGISTER 1
2737 ViceIDToUsername(char *username,
2738 char *realm_of_user,
2739 char *realm_of_cell,
2741 struct ktc_principal *aclient,
2742 struct ktc_principal *aserver,
2743 struct ktc_token *atoken)
2745 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2746 static char confdir[512] = { 0 };
2747 #ifdef AFS_ID_TO_NAME
2748 char username_copy[BUFSIZ];
2749 #endif /* AFS_ID_TO_NAME */
2750 long viceId = ANONYMOUSID; /* AFS uid of user */
2752 #ifdef ALLOW_REGISTER
2754 #endif /* ALLOW_REGISTER */
2756 if (confdir[0] == '\0')
2757 cm_GetConfigDir(confdir, sizeof(confdir));
2759 StringCbCopyN( lastcell, sizeof(lastcell),
2760 aserver->cell, sizeof(lastcell) - 1);
2762 if (!pr_Initialize (0, confdir, aserver->cell)) {
2763 char sname[PR_MAXNAMELEN];
2764 StringCbCopyN( sname, sizeof(sname),
2765 username, sizeof(sname) - 1);
2766 status = pr_SNameToId (sname, &viceId);
2771 * This is a crock, but it is Transarc's crock, so
2772 * we have to play along in order to get the
2773 * functionality. The way the afs id is stored is
2774 * as a string in the username field of the token.
2775 * Contrary to what you may think by looking at
2776 * the code for tokens, this hack (AFS ID %d) will
2777 * not work if you change %d to something else.
2781 * This code is taken from cklog -- it lets people
2782 * automatically register with the ptserver in foreign cells
2785 #ifdef ALLOW_REGISTER
2787 if (viceId != ANONYMOUSID) {
2788 #else /* ALLOW_REGISTER */
2789 if ((status == 0) && (viceId != ANONYMOUSID))
2790 #endif /* ALLOW_REGISTER */
2792 #ifdef AFS_ID_TO_NAME
2793 StringCbCopyN( username_copy, sizeof(username_copy),
2794 username, sizeof(username_copy) - 1);
2795 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2796 #endif /* AFS_ID_TO_NAME */
2798 #ifdef ALLOW_REGISTER
2799 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2801 StringCbCopyN( aclient->name, sizeof(aclient->name),
2802 username, sizeof(aclient->name) - 1);
2803 aclient->instance[0] = '\0';
2804 StringCbCopyN( aclient->cell, sizeof(aclient->cell),
2805 realm_of_user, sizeof(aclient->cell) - 1);
2806 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2808 if (status = pr_Initialize(1L, confdir, aserver->cell))
2810 status = pr_CreateUser(username, &id);
2814 #ifdef AFS_ID_TO_NAME
2815 StringCbCopyN( username_copy, sizeof(username_copy),
2816 username, sizeof(username_copy) - 1);
2817 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2818 #endif /* AFS_ID_TO_NAME */
2821 #endif /* ALLOW_REGISTER */
2827 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2828 krb5_error_code code;
2829 krb5_ticket *ticket;
2832 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2834 len = krb5_princ_realm(context, ticket->server)->length;
2835 if (len > destlen - 1)
2838 StringCbCopyN(dest, destlen, krb5_princ_realm(context, ticket->server)->data, len);
2840 pkrb5_free_ticket(context, ticket);
2846 krb5_context alt_ctx,
2851 int lifetime, /* unused parameter */
2859 #endif /* USE_KRB4 */
2860 struct ktc_principal aserver;
2861 struct ktc_principal aclient;
2862 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2863 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2864 char local_cell[CELL_MAXNAMELEN+1];
2865 char Dmycell[CELL_MAXNAMELEN+1];
2866 struct ktc_token atoken;
2867 struct ktc_token btoken;
2868 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2869 char RealmName[128];
2871 char ServiceName[128];
2875 krb5_context ctx = NULL;
2876 krb5_ccache cc = NULL;
2878 krb5_creds * k5creds = NULL;
2879 krb5_error_code code;
2880 krb5_principal client_principal = NULL;
2881 krb5_data * k5data = NULL;
2882 unsigned int i, retry = 0;
2885 memset(HostName, '\0', sizeof(HostName));
2886 gethostname(HostName, sizeof(HostName));
2887 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2888 if ( IsDebuggerPresent() )
2889 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2892 if (CurrentState != SERVICE_RUNNING) {
2893 if ( IsDebuggerPresent() )
2894 OutputDebugString("AFSD Service NOT RUNNING\n");
2898 if (!pkrb5_init_context)
2899 return KRB5_CONFIG_CANTOPEN;
2901 memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
2902 memset(RealmName, '\0', sizeof(RealmName));
2903 memset(CellName, '\0', sizeof(CellName));
2904 memset(ServiceName, '\0', sizeof(ServiceName));
2905 memset(realm_of_user, '\0', sizeof(realm_of_user));
2906 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2907 if (cell && cell[0])
2908 StringCbCopyN( Dmycell, sizeof(Dmycell),
2909 cell, sizeof(Dmycell) - 1);
2911 memset(Dmycell, '\0', sizeof(Dmycell));
2913 // NULL or empty cell returns information on local cell
2914 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2916 // KFW_AFS_error(rc, "get_cellconfig()");
2923 code = pkrb5_init_context(&ctx);
2924 if (code) goto cleanup;
2930 code = pkrb5_cc_default(ctx, &cc);
2931 if (code) goto skip_krb5_init;
2934 memset(&increds, 0, sizeof(increds));
2936 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2938 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2940 OutputDebugString("Principal Not Found for ccache\n");
2942 goto skip_krb5_init;
2945 if (!KFW_accept_dotted_usernames()) {
2946 /* look for client principals which cannot be distinguished
2947 * from Kerberos 4 multi-component principal names
2949 k5data = krb5_princ_component(ctx,client_principal,0);
2950 for ( i=0; i<k5data->length; i++ ) {
2951 if ( k5data->data[i] == '.' )
2954 if (i != k5data->length)
2956 OutputDebugString("Illegal Principal name contains dot in first component\n");
2957 rc = KRB5KRB_ERR_GENERIC;
2962 i = krb5_princ_realm(ctx, client_principal)->length;
2965 StringCbCopyN( realm_of_user, sizeof(realm_of_user),
2966 krb5_princ_realm(ctx, client_principal)->data, i);
2971 if ( !try_krb5 || !realm_of_user[0] ) {
2972 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2981 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
2982 afs_realm_of_cell(ctx, &ak_cellconfig),
2983 sizeof(realm_of_cell) - 1);
2985 if (strlen(service) == 0)
2986 StringCbCopy( ServiceName, sizeof(ServiceName), "afs");
2988 StringCbCopyN( ServiceName, sizeof(ServiceName),
2989 service, sizeof(ServiceName) - 1);
2991 if (strlen(cell) == 0)
2992 StringCbCopyN( CellName, sizeof(CellName),
2993 local_cell, sizeof(CellName) - 1);
2995 StringCbCopyN( CellName, sizeof(CellName),
2996 cell, sizeof(CellName) - 1);
2998 /* This is for Kerberos v4 only */
2999 if (strlen(realm) == 0)
3000 StringCbCopyN( RealmName, sizeof(RealmName),
3001 realm_of_cell, sizeof(RealmName) - 1);
3003 StringCbCopyN( RealmName, sizeof(RealmName),
3004 realm, sizeof(RealmName) - 1);
3006 memset(&creds, '\0', sizeof(creds));
3010 code = KRB5KRB_ERR_GENERIC;
3013 increds.client = client_principal;
3014 increds.times.endtime = 0;
3015 /* Ask for DES since that is what V4 understands */
3016 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
3018 /* ALWAYS first try service/cell@CLIENT_REALM */
3019 if (code = pkrb5_build_principal(ctx, &increds.server,
3020 (int)strlen(realm_of_user),
3029 if ( IsDebuggerPresent() ) {
3030 char * cname, *sname;
3031 pkrb5_unparse_name(ctx, increds.client, &cname);
3032 pkrb5_unparse_name(ctx, increds.server, &sname);
3033 OutputDebugString("Getting tickets for \"");
3034 OutputDebugString(cname);
3035 OutputDebugString("\" and service \"");
3036 OutputDebugString(sname);
3037 OutputDebugString("\"\n");
3038 pkrb5_free_unparsed_name(ctx,cname);
3039 pkrb5_free_unparsed_name(ctx,sname);
3042 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3044 /* The client's realm is a local realm for the cell.
3045 * Save it so that later the pts registration will not
3048 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3049 realm_of_user, sizeof(realm_of_cell) - 1);
3053 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3054 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3055 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3056 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3057 /* If there was a specific realm we are supposed to try
3060 if (strlen(realm) != 0) {
3061 /* service/cell@REALM */
3063 code = pkrb5_build_principal(ctx, &increds.server,
3069 if ( IsDebuggerPresent() ) {
3070 char * cname, *sname;
3071 pkrb5_unparse_name(ctx, increds.client, &cname);
3072 pkrb5_unparse_name(ctx, increds.server, &sname);
3073 OutputDebugString("Getting tickets for \"");
3074 OutputDebugString(cname);
3075 OutputDebugString("\" and service \"");
3076 OutputDebugString(sname);
3077 OutputDebugString("\"\n");
3078 pkrb5_free_unparsed_name(ctx,cname);
3079 pkrb5_free_unparsed_name(ctx,sname);
3083 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3085 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3086 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3087 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3088 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3089 /* Or service@REALM */
3090 pkrb5_free_principal(ctx,increds.server);
3092 code = pkrb5_build_principal(ctx, &increds.server,
3098 if ( IsDebuggerPresent() ) {
3099 char * cname, *sname;
3100 pkrb5_unparse_name(ctx, increds.client, &cname);
3101 pkrb5_unparse_name(ctx, increds.server, &sname);
3102 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3103 OutputDebugString("Trying again: getting tickets for \"");
3104 OutputDebugString(cname);
3105 OutputDebugString("\" and service \"");
3106 OutputDebugString(sname);
3107 OutputDebugString("\"\n");
3108 pkrb5_free_unparsed_name(ctx,cname);
3109 pkrb5_free_unparsed_name(ctx,sname);
3113 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3117 /* we have a local realm for the cell */
3118 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3119 realm, sizeof(realm_of_cell) - 1);
3122 if (strcmp(realm_of_user, realm_of_cell)) {
3123 /* Then service/cell@CELL_REALM */
3124 pkrb5_free_principal(ctx,increds.server);
3126 code = pkrb5_build_principal(ctx, &increds.server,
3127 (int)strlen(realm_of_cell),
3132 if ( IsDebuggerPresent() ) {
3133 char * cname, *sname;
3134 pkrb5_unparse_name(ctx, increds.client, &cname);
3135 pkrb5_unparse_name(ctx, increds.server, &sname);
3136 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3137 OutputDebugString("Trying again: getting tickets for \"");
3138 OutputDebugString(cname);
3139 OutputDebugString("\" and service \"");
3140 OutputDebugString(sname);
3141 OutputDebugString("\"\n");
3142 pkrb5_free_unparsed_name(ctx,cname);
3143 pkrb5_free_unparsed_name(ctx,sname);
3147 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3149 if (!code && !strlen(realm_of_cell))
3150 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3153 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3154 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3155 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3156 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3157 /* Finally service@CELL_REALM */
3158 pkrb5_free_principal(ctx,increds.server);
3160 code = pkrb5_build_principal(ctx, &increds.server,
3161 (int)strlen(realm_of_cell),
3166 if ( IsDebuggerPresent() ) {
3167 char * cname, *sname;
3168 pkrb5_unparse_name(ctx, increds.client, &cname);
3169 pkrb5_unparse_name(ctx, increds.server, &sname);
3170 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3171 OutputDebugString("Trying again: getting tickets for \"");
3172 OutputDebugString(cname);
3173 OutputDebugString("\" and service \"");
3174 OutputDebugString(sname);
3175 OutputDebugString("\"\n");
3176 pkrb5_free_unparsed_name(ctx,cname);
3177 pkrb5_free_unparsed_name(ctx,sname);
3181 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3182 if (!code && !strlen(realm_of_cell))
3183 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3189 if ( IsDebuggerPresent() ) {
3191 StringCbPrintf(message, sizeof(message), "krb5_get_credentials returns: %d\n", code);
3192 OutputDebugString(message);
3198 /* This code inserts the entire K5 ticket into the token
3199 * No need to perform a krb524 translation which is
3200 * commented out in the code below
3202 if (KFW_use_krb524() ||
3203 k5creds->ticket.length > MAXKTCTICKETLEN)
3206 memset(&aserver, '\0', sizeof(aserver));
3207 StringCbCopyN(aserver.name, sizeof(aserver.name),
3208 ServiceName, sizeof(aserver.name) - 1);
3209 StringCbCopyN(aserver.cell, sizeof(aserver.cell),
3210 CellName, sizeof(aserver.cell) - 1);
3212 memset(&atoken, '\0', sizeof(atoken));
3213 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3214 atoken.startTime = k5creds->times.starttime;
3215 atoken.endTime = k5creds->times.endtime;
3216 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3217 atoken.ticketLen = k5creds->ticket.length;
3218 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3221 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3222 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3223 if ( rc == KTC_NOCM && retry < 20 ) {
3226 goto retry_gettoken5;
3231 if (atoken.kvno == btoken.kvno &&
3232 atoken.ticketLen == btoken.ticketLen &&
3233 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3234 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3236 /* Success - Nothing to do */
3240 // * Reset the "aclient" structure before we call ktc_SetToken.
3241 // * This structure was first set by the ktc_GetToken call when
3242 // * we were comparing whether identical tokens already existed.
3244 len = min(k5creds->client->data[0].length, sizeof(aclient.name) - 1);
3245 StringCbCopyN( aclient.name, sizeof(aclient.name),
3246 k5creds->client->data[0].data, len);
3248 if ( k5creds->client->length > 1 ) {
3249 StringCbCat( aclient.name, sizeof(aclient.name), ".");
3250 len = min(k5creds->client->data[1].length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3251 StringCbCatN( aclient.name, sizeof(aclient.name),
3252 k5creds->client->data[1].data, len);
3254 aclient.instance[0] = '\0';
3256 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3257 realm_of_cell, sizeof(aclient.cell) - 1);
3259 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3260 /* For Khimaira, always append the realm name */
3261 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3262 StringCbCat( aclient.name, sizeof(aclient.name), "@");
3263 len = min(k5creds->client->realm.length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3264 StringCbCatN( aclient.name, sizeof(aclient.name), k5creds->client->realm.data, len);
3267 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3268 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3269 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3270 &aclient, &aserver, &atoken);
3273 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3274 smbname, sizeof(aclient.smbname) - 1);
3276 aclient.smbname[0] = '\0';
3279 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3281 goto cleanup; /* We have successfully inserted the token */
3287 /* Otherwise, the ticket could have been too large so try to
3288 * convert using the krb524d running with the KDC
3290 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3291 pkrb5_free_creds(ctx, k5creds);
3293 if ( IsDebuggerPresent() ) {
3295 StringCbPrintf(message, sizeof(message), "krb524_convert_creds_kdc returns: %d\n", code);
3296 OutputDebugString(message);
3301 #endif /* USE_KRB524 */
3305 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3306 if (code == NO_TKT_FIL) {
3307 // if the problem is that we have no krb4 tickets
3308 // do not attempt to continue
3311 if (code != KSUCCESS)
3312 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3314 if (code != KSUCCESS)
3316 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3318 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3323 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3325 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3340 memset(&aserver, '\0', sizeof(aserver));
3341 StringCbCopyN( aserver.name, sizeof(aserver.name), ServiceName, sizeof(aserver.name) - 1);
3342 StringCbCopyN( aserver.cell, sizeof(aserver.cell), CellName, sizeof(aserver.cell) - 1);
3344 memset(&atoken, '\0', sizeof(atoken));
3345 atoken.kvno = creds.kvno;
3346 atoken.startTime = creds.issue_date;
3347 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3348 memcpy(&atoken.sessionKey, creds.session, 8);
3349 atoken.ticketLen = creds.ticket_st.length;
3350 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3353 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3354 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3355 if ( rc == KTC_NOCM && retry < 20 ) {
3358 goto retry_gettoken;
3360 KFW_AFS_error(rc, "ktc_GetToken()");
3365 if (atoken.kvno == btoken.kvno &&
3366 atoken.ticketLen == btoken.ticketLen &&
3367 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3368 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3373 // * Reset the "aclient" structure before we call ktc_SetToken.
3374 // * This structure was first set by the ktc_GetToken call when
3375 // * we were comparing whether identical tokens already existed.
3377 StringCbCopyN( aclient.name, sizeof(aclient.name), creds.pname, sizeof(aclient.name) - 1);
3380 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3381 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3383 aclient.instance[0] = '\0';
3385 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3386 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3387 aclient.name[MAXKTCREALMLEN-1] = '\0';
3389 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3390 CellName, sizeof(aclient.cell) - 1);
3392 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3393 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3394 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3395 &aclient, &aserver, &atoken);
3398 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3399 smbname, sizeof(aclient.smbname) - 1);
3401 aclient.smbname[0] = '\0';
3404 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3406 KFW_AFS_error(rc, "ktc_SetToken()");
3412 if (client_principal)
3413 pkrb5_free_principal(ctx,client_principal);
3414 /* increds.client == client_principal */
3416 pkrb5_free_principal(ctx,increds.server);
3417 if (cc && (cc != alt_cc))
3418 pkrb5_cc_close(ctx, cc);
3419 if (ctx && (ctx != alt_ctx))
3420 pkrb5_free_context(ctx);
3421 if (ak_cellconfig.linkedCell)
3422 free(ak_cellconfig.linkedCell);
3424 return(rc? rc : code);
3427 /**************************************/
3428 /* afs_realm_of_cell(): */
3429 /**************************************/
3431 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3433 static char krbrlm[REALM_SZ+1]="";
3434 char ** realmlist=NULL;
3440 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3441 if ( !r && realmlist && realmlist[0] ) {
3442 StringCbCopyN( krbrlm, sizeof(krbrlm),
3443 realmlist[0], sizeof(krbrlm) - 1);
3444 pkrb5_free_host_realm(ctx, realmlist);
3450 char *t = cellconfig->name;
3455 if (islower(c)) c=toupper(c);
3463 /**************************************/
3464 /* KFW_AFS_get_cellconfig(): */
3465 /**************************************/
3467 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3470 char newcell[CELL_MAXNAMELEN+1];
3471 char linkedcell[CELL_MAXNAMELEN+1]="";
3473 local_cell[0] = (char)0;
3474 memset(cellconfig, 0, sizeof(*cellconfig));
3476 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3477 if (rc = cm_GetRootCellName(local_cell))
3482 if (strlen(cell) == 0)
3483 strcpy(cell, local_cell);
3485 rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3486 if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
3487 rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3490 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3494 StringCbCopyN( cellconfig->name, sizeof(cellconfig->name),
3495 newcell, sizeof(cellconfig->name) - 1);
3497 cellconfig->linkedCell = strdup(linkedcell);
3502 /**************************************/
3503 /* get_cellconfig_callback(): */
3504 /**************************************/
3506 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
3508 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3510 cc->hostAddr[cc->numServers] = *addrp;
3511 StringCbCopyN( cc->hostName[cc->numServers], sizeof(cc->hostName[cc->numServers]),
3512 namep, sizeof(cc->hostName[cc->numServers]) - 1);
3518 /**************************************/
3519 /* KFW_AFS_error(): */
3520 /**************************************/
3522 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3525 const char *errText;
3527 // Using AFS defines as error messages for now, until Transarc
3528 // gets back to me with "string" translations of each of these
3530 if (rc == KTC_ERROR)
3531 errText = "KTC_ERROR";
3532 else if (rc == KTC_TOOBIG)
3533 errText = "KTC_TOOBIG";
3534 else if (rc == KTC_INVAL)
3535 errText = "KTC_INVAL";
3536 else if (rc == KTC_NOENT)
3537 errText = "KTC_NOENT";
3538 else if (rc == KTC_PIOCTLFAIL)
3539 errText = "KTC_PIOCTLFAIL";
3540 else if (rc == KTC_NOPIOCTL)
3541 errText = "KTC_NOPIOCTL";
3542 else if (rc == KTC_NOCELL)
3543 errText = "KTC_NOCELL";
3544 else if (rc == KTC_NOCM)
3545 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3547 errText = "Unknown error!";
3549 StringCbPrintf(message, sizeof(message), "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3551 if ( IsDebuggerPresent() ) {
3552 OutputDebugString(message);
3553 OutputDebugString("\n");
3555 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3561 LPSTR lpszMachineName,
3562 LPSTR lpszServiceName,
3563 DWORD *lpdwCurrentState)
3566 SC_HANDLE schSCManager = NULL;
3567 SC_HANDLE schService = NULL;
3568 DWORD fdwDesiredAccess = 0;
3569 SERVICE_STATUS ssServiceStatus = {0};
3572 *lpdwCurrentState = 0;
3574 fdwDesiredAccess = GENERIC_READ;
3576 schSCManager = OpenSCManager(lpszMachineName,
3580 if(schSCManager == NULL)
3582 hr = GetLastError();
3586 schService = OpenService(schSCManager,
3590 if(schService == NULL)
3592 hr = GetLastError();
3596 fRet = QueryServiceStatus(schService,
3601 hr = GetLastError();
3605 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3609 CloseServiceHandle(schService);
3610 CloseServiceHandle(schSCManager);
3623 for (n = 0; fi[n].func_ptr_var; n++)
3624 *(fi[n].func_ptr_var) = 0;
3625 if (h) FreeLibrary(h);
3630 const char* dll_name,
3632 HINSTANCE* ph, // [out, optional] - DLL handle
3633 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3634 int cleanup, // cleanup function pointers and unload on error
3635 int go_on, // continue loading even if some functions cannot be loaded
3636 int silent // do not pop-up a system dialog if DLL cannot be loaded
3645 if (pindex) *pindex = -1;
3647 for (n = 0; fi[n].func_ptr_var; n++)
3648 *(fi[n].func_ptr_var) = 0;
3651 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3652 h = LoadLibrary(dll_name);
3660 for (i = 0; (go_on || !error) && (i < n); i++)
3662 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3668 *(fi[i].func_ptr_var) = p;
3671 if (pindex) *pindex = last_i;
3672 if (error && cleanup && !go_on) {
3673 for (i = 0; i < n; i++) {
3674 *(fi[i].func_ptr_var) = 0;
3680 if (error) return 0;
3684 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3686 krb5_context ctx = NULL;
3687 krb5_ccache cc = NULL;
3688 krb5_error_code code;
3690 const char * realm = NULL;
3691 krb5_principal principal = NULL;
3692 char * pname = NULL;
3693 char password[PROBE_PASSWORD_LEN+1];
3694 BOOL serverReachable = 0;
3696 if (!pkrb5_init_context)
3697 return KRB5_CONFIG_CANTOPEN;
3699 code = pkrb5_init_context(&ctx);
3700 if (code) goto cleanup;
3703 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3705 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3706 realm, PROBE_USERNAME, NULL, NULL);
3707 if ( code ) goto cleanup;
3709 code = KFW_get_ccache(ctx, principal, &cc);
3710 if ( code ) goto cleanup;
3712 code = pkrb5_unparse_name(ctx, principal, &pname);
3713 if ( code ) goto cleanup;
3715 pwdata.data = password;
3716 pwdata.length = PROBE_PASSWORD_LEN;
3717 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3720 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3723 password[PROBE_PASSWORD_LEN] = '\0';
3725 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3735 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3736 case KRB5KDC_ERR_CLIENT_REVOKED:
3737 case KRB5KDC_ERR_CLIENT_NOTYET:
3738 case KRB5KDC_ERR_PREAUTH_FAILED:
3739 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3740 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3741 serverReachable = TRUE;
3744 serverReachable = FALSE;
3749 pkrb5_free_unparsed_name(ctx,pname);
3751 pkrb5_free_principal(ctx,principal);
3753 pkrb5_cc_close(ctx,cc);
3755 pkrb5_free_context(ctx);
3757 return serverReachable;
3761 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
3763 krb5_context ctx = NULL;
3764 krb5_error_code code;
3765 krb5_ccache mslsa_ccache=NULL;
3766 krb5_principal princ = NULL;
3767 char * pname = NULL;
3770 if (!KFW_is_available())
3773 if (code = pkrb5_init_context(&ctx))
3776 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3779 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3782 if (code = pkrb5_unparse_name(ctx, princ, &pname))
3785 if ( strlen(pname) < *dwSize ) {
3786 StringCbCopyN(szUser, *dwSize, pname, (*dwSize) - 1);
3789 *dwSize = (DWORD)strlen(pname);
3793 pkrb5_free_unparsed_name(ctx, pname);
3796 pkrb5_free_principal(ctx, princ);
3799 pkrb5_cc_close(ctx, mslsa_ccache);
3802 pkrb5_free_context(ctx);
3807 KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
3809 // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
3810 PSID pSystemSID = NULL;
3811 DWORD SystemSIDlength = 0, UserSIDlength = 0;
3812 PACL ccacheACL = NULL;
3813 DWORD ccacheACLlength = 0;
3814 PTOKEN_USER pTokenUser = NULL;
3823 /* Get System SID */
3824 if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
3830 SystemSIDlength = GetLengthSid(pSystemSID);
3831 ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
3832 + SystemSIDlength - sizeof(DWORD);
3835 if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
3837 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
3838 pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
3840 GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
3845 UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
3847 ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
3852 ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
3857 InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
3858 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3859 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3862 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3863 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3864 pTokenUser->User.Sid);
3865 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3866 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3871 gle = GetLastError();
3872 if (gle != ERROR_NO_TOKEN)
3875 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3876 OWNER_SECURITY_INFORMATION,
3877 pTokenUser->User.Sid,
3881 gle = GetLastError();
3882 if (gle != ERROR_NO_TOKEN)
3886 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3887 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3892 gle = GetLastError();
3893 if (gle != ERROR_NO_TOKEN)
3900 LocalFree(pSystemSID);
3902 LocalFree(pTokenUser);
3904 LocalFree(ccacheACL);
3909 KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
3912 DWORD dwSize = size-1; /* leave room for nul */
3915 if (!hUserToken || !newfilename || size <= 0)
3918 *newfilename = '\0';
3920 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
3921 if ( !dwLen || dwLen > dwSize )
3922 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
3923 if ( !dwLen || dwLen > dwSize )
3926 newfilename[dwSize] = '\0';
3931 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
3933 char filename[MAX_PATH] = "";
3935 char cachename[MAX_PATH + 8] = "FILE:";
3936 krb5_context ctx = NULL;
3937 krb5_error_code code;
3938 krb5_principal princ = NULL;
3939 krb5_ccache cc = NULL;
3940 krb5_ccache ncc = NULL;
3942 if (!pkrb5_init_context || !user || !szLogonId)
3945 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
3946 if ( count > sizeof(filename) || count == 0 ) {
3947 GetWindowsDirectory(filename, sizeof(filename));
3950 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
3953 StringCbCat( filename, sizeof(filename), "\\");
3954 StringCbCat( filename, sizeof(filename), szLogonId);
3956 StringCbCat( cachename, sizeof(cachename), filename);
3958 DeleteFile(filename);
3960 code = pkrb5_init_context(&ctx);
3961 if (code) goto cleanup;
3963 code = pkrb5_parse_name(ctx, user, &princ);
3964 if (code) goto cleanup;
3966 code = KFW_get_ccache(ctx, princ, &cc);
3967 if (code) goto cleanup;
3969 code = pkrb5_cc_resolve(ctx, cachename, &ncc);
3970 if (code) goto cleanup;
3972 code = pkrb5_cc_initialize(ctx, ncc, princ);
3973 if (code) goto cleanup;
3975 code = KFW_AFS_set_file_cache_dacl(filename, NULL);
3976 if (code) goto cleanup;
3978 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3982 pkrb5_cc_close(ctx, cc);
3986 pkrb5_cc_close(ctx, ncc);
3990 pkrb5_free_principal(ctx, princ);
3995 pkrb5_free_context(ctx);
3999 KFW_AFS_copy_file_cache_to_default_cache(char * filename)
4001 char cachename[MAX_PATH + 8] = "FILE:";
4002 krb5_context ctx = NULL;
4003 krb5_error_code code;
4004 krb5_principal princ = NULL;
4005 krb5_ccache cc = NULL;
4006 krb5_ccache ncc = NULL;
4009 if (!pkrb5_init_context || !filename)
4012 if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
4015 code = pkrb5_init_context(&ctx);
4018 StringCbCat( cachename, sizeof(cachename), filename);
4020 code = pkrb5_cc_resolve(ctx, cachename, &cc);
4021 if (code) goto cleanup;
4023 code = pkrb5_cc_get_principal(ctx, cc, &princ);
4025 code = pkrb5_cc_default(ctx, &ncc);
4027 code = pkrb5_cc_initialize(ctx, ncc, princ);
4030 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
4033 pkrb5_cc_close(ctx, ncc);
4037 retval=0; /* success */
4041 pkrb5_cc_close(ctx, cc);
4045 DeleteFile(filename);
4048 pkrb5_free_principal(ctx, princ);
4053 pkrb5_free_context(ctx);
4058 /* We are including this
4060 /* Ticket lifetime. This defines the table used to lookup lifetime for the
4061 fixed part of rande of the one byte lifetime field. Values less than 0x80
4062 are intrpreted as the number of 5 minute intervals. Values from 0x80 to
4063 0xBF should be looked up in this table. The value of 0x80 is the same using
4064 both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days.
4065 The intervening values of have a fixed ratio of roughly 1.06914. The value
4066 oxFF is defined to mean a ticket has no expiration time. This should be
4067 used advisedly since individual servers may impose defacto upperbounds on
4068 ticket lifetimes. */
4070 #define TKTLIFENUMFIXED 64
4071 #define TKTLIFEMINFIXED 0x80
4072 #define TKTLIFEMAXFIXED 0xBF
4073 #define TKTLIFENOEXPIRE 0xFF
4074 #define MAXTKTLIFETIME (30*24*3600) /* 30 days */
4076 static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
4077 38400, /* 10.67 hours, 0.44 days */
4078 41055, /* 11.40 hours, 0.48 days */
4079 43894, /* 12.19 hours, 0.51 days */
4080 46929, /* 13.04 hours, 0.54 days */
4081 50174, /* 13.94 hours, 0.58 days */
4082 53643, /* 14.90 hours, 0.62 days */
4083 57352, /* 15.93 hours, 0.66 days */
4084 61318, /* 17.03 hours, 0.71 days */
4085 65558, /* 18.21 hours, 0.76 days */
4086 70091, /* 19.47 hours, 0.81 days */
4087 74937, /* 20.82 hours, 0.87 days */
4088 80119, /* 22.26 hours, 0.93 days */
4089 85658, /* 23.79 hours, 0.99 days */
4090 91581, /* 25.44 hours, 1.06 days */
4091 97914, /* 27.20 hours, 1.13 days */
4092 104684, /* 29.08 hours, 1.21 days */
4093 111922, /* 31.09 hours, 1.30 days */
4094 119661, /* 33.24 hours, 1.38 days */
4095 127935, /* 35.54 hours, 1.48 days */
4096 136781, /* 37.99 hours, 1.58 days */
4097 146239, /* 40.62 hours, 1.69 days */
4098 156350, /* 43.43 hours, 1.81 days */
4099 167161, /* 46.43 hours, 1.93 days */
4100 178720, /* 49.64 hours, 2.07 days */
4101 191077, /* 53.08 hours, 2.21 days */
4102 204289, /* 56.75 hours, 2.36 days */
4103 218415, /* 60.67 hours, 2.53 days */
4104 233517, /* 64.87 hours, 2.70 days */
4105 249664, /* 69.35 hours, 2.89 days */
4106 266926, /* 74.15 hours, 3.09 days */
4107 285383, /* 79.27 hours, 3.30 days */
4108 305116, /* 84.75 hours, 3.53 days */
4109 326213, /* 90.61 hours, 3.78 days */
4110 348769, /* 96.88 hours, 4.04 days */
4111 372885, /* 103.58 hours, 4.32 days */
4112 398668, /* 110.74 hours, 4.61 days */
4113 426234, /* 118.40 hours, 4.93 days */
4114 455705, /* 126.58 hours, 5.27 days */
4115 487215, /* 135.34 hours, 5.64 days */
4116 520904, /* 144.70 hours, 6.03 days */
4117 556921, /* 154.70 hours, 6.45 days */
4118 595430, /* 165.40 hours, 6.89 days */
4119 636601, /* 176.83 hours, 7.37 days */
4120 680618, /* 189.06 hours, 7.88 days */
4121 727680, /* 202.13 hours, 8.42 days */
4122 777995, /* 216.11 hours, 9.00 days */
4123 831789, /* 231.05 hours, 9.63 days */
4124 889303, /* 247.03 hours, 10.29 days */
4125 950794, /* 264.11 hours, 11.00 days */
4126 1016537, /* 282.37 hours, 11.77 days */
4127 1086825, /* 301.90 hours, 12.58 days */
4128 1161973, /* 322.77 hours, 13.45 days */
4129 1242318, /* 345.09 hours, 14.38 days */
4130 1328218, /* 368.95 hours, 15.37 days */
4131 1420057, /* 394.46 hours, 16.44 days */
4132 1518247, /* 421.74 hours, 17.57 days */
4133 1623226, /* 450.90 hours, 18.79 days */
4134 1735464, /* 482.07 hours, 20.09 days */
4135 1855462, /* 515.41 hours, 21.48 days */
4136 1983758, /* 551.04 hours, 22.96 days */
4137 2120925, /* 589.15 hours, 24.55 days */
4138 2267576, /* 629.88 hours, 26.25 days */
4139 2424367, /* 673.44 hours, 28.06 days */
4141 }; /* 720.00 hours, 30.00 days */
4143 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
4144 * returns the corresponding end time. There are four simple cases to be
4145 * handled. The first is a life of 0xff, meaning no expiration, and results in
4146 * an end time of 0xffffffff. The second is when life is less than the values
4147 * covered by the table. In this case, the end time is the start time plus the
4148 * number of 5 minute intervals specified by life. The third case returns
4149 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
4150 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
4151 * table to extract the lifetime in seconds, which is added to start to produce
4155 life_to_time(afs_uint32 start, unsigned char life)
4159 if (life == TKTLIFENOEXPIRE)
4161 if (life < TKTLIFEMINFIXED)
4162 return start + life * 5 * 60;
4163 if (life > TKTLIFEMAXFIXED)
4164 return start + MAXTKTLIFETIME;
4165 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
4166 return start + realLife;
4169 /* time_to_life - takes start and end times for the ticket and returns a
4170 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
4171 * lifetimes above 127*5minutes. First, the special case of (end ==
4172 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
4173 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
4174 * less than the first table entry are handled by rounding the requested
4175 * lifetime *up* to the next 5 minute interval. The final step is to search
4176 * the table for the smallest entry *greater than or equal* to the requested
4177 * entry. The actual code is prepared to handle the case where the table is
4178 * unordered but that it an unnecessary frill. */
4180 static unsigned char
4181 time_to_life(afs_uint32 start, afs_uint32 end)
4183 int lifetime = end - start;
4187 if (end == NEVERDATE)
4188 return TKTLIFENOEXPIRE;
4189 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
4191 if (lifetime < tkt_lifetimes[0])
4192 return (lifetime + 5 * 60 - 1) / (5 * 60);
4194 best = MAXKTCTICKETLIFETIME;
4195 for (i = 0; i < TKTLIFENUMFIXED; i++)
4196 if (tkt_lifetimes[i] >= lifetime) {
4197 int diff = tkt_lifetimes[i] - lifetime;
4205 return best_i + TKTLIFEMINFIXED;