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,'.') ) {
1406 size_t len = strlen(username) + strlen(realm) + 2;
1407 pname = malloc(len);
1408 if (pname == NULL) {
1409 code = KRB5KRB_ERR_GENERIC;
1412 StringCbCopy(pname, len, username);
1414 if (!KFW_accept_dotted_usernames()) {
1415 /* handle kerberos iv notation */
1416 while ( dot = strchr(pname,'.') ) {
1420 StringCbCat( pname, len, "@");
1421 StringCbCat( pname, len, realm);
1423 if ( IsDebuggerPresent() ) {
1424 OutputDebugString("Realm of Cell: ");
1425 OutputDebugString(realm);
1426 OutputDebugString("\n");
1427 OutputDebugString("Realm of User: ");
1428 OutputDebugString(userrealm?userrealm:"<NULL>");
1429 OutputDebugString("\n");
1432 code = pkrb5_parse_name(ctx, pname, &principal);
1433 if ( code ) goto cleanup;
1435 code = KFW_get_ccache(ctx, principal, &cc);
1436 if ( code ) goto cleanup;
1438 if ( lifetime == 0 )
1439 lifetime = DEFAULT_LIFETIME;
1441 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1442 if ( IsDebuggerPresent() ) {
1444 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1445 OutputDebugString(message);
1448 if (code && password && password[0] ) {
1449 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1454 0, /* forwardable */
1455 0, /* not proxiable */
1457 1, /* noaddresses */
1458 0 /* no public ip */
1460 pLeash_get_default_forwardable(),
1461 pLeash_get_default_proxiable(),
1462 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1463 pLeash_get_default_noaddresses(),
1464 pLeash_get_default_publicip()
1465 #endif /* USE_LEASH */
1468 if ( IsDebuggerPresent() ) {
1470 StringCbPrintf(message, sizeof(message), "KFW_kinit() returns: %d\n", code);
1471 OutputDebugString(message);
1473 if ( code ) goto cleanup;
1475 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1478 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1479 if ( IsDebuggerPresent() ) {
1481 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1482 OutputDebugString(message);
1484 if ( code ) goto cleanup;
1486 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1488 // Attempt to obtain new tokens for other cells supported by the same
1490 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1491 if ( cell_count > 1 ) {
1492 while ( cell_count-- ) {
1493 if ( strcmp(cells[cell_count],cell) ) {
1494 if ( IsDebuggerPresent() ) {
1496 StringCbPrintf(message, sizeof(message),
1497 "found another cell for the same principal: %s\n", cell);
1498 OutputDebugString(message);
1501 if (cellconfig.linkedCell) {
1502 free(cellconfig.linkedCell);
1503 cellconfig.linkedCell = NULL;
1505 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1506 if ( code ) continue;
1508 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1509 if ( IsDebuggerPresent() ) {
1510 OutputDebugString("Realm: ");
1511 OutputDebugString(realm);
1512 OutputDebugString("\n");
1515 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1516 if ( IsDebuggerPresent() ) {
1518 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1519 OutputDebugString(message);
1522 free(cells[cell_count]);
1525 } else if ( cell_count == 1 ) {
1534 pkrb5_cc_close(ctx, cc);
1535 if ( cellconfig.linkedCell )
1536 free(cellconfig.linkedCell);
1538 if ( code && reasonP ) {
1540 char *msg = (char *)afs_error_message(code);
1541 if (strncmp(msg, "unknown", strlen(msg)) == 0) {
1542 if (pkrb5_get_error_message) {
1543 msg = pkrb5_get_error_message(ctx, code);
1546 msg = (char *)perror_message(code);
1548 StringCbCopyN( reason, sizeof(reason),
1549 msg, sizeof(reason) - 1);
1552 pkrb5_free_error_message(ctx, msg);
1558 KFW_AFS_destroy_tickets_for_cell(char * cell)
1560 krb5_context ctx = NULL;
1561 krb5_error_code code;
1563 char ** principals = NULL;
1565 if (!pkrb5_init_context)
1566 return KRB5_CONFIG_CANTOPEN;
1568 if ( IsDebuggerPresent() ) {
1569 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1570 OutputDebugString(cell);
1571 OutputDebugString("\n");
1574 code = pkrb5_init_context(&ctx);
1577 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1579 krb5_principal princ = 0;
1583 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1584 if ( cell_count > 1 ) {
1585 // TODO - What we really should do here is verify whether or not any of the
1586 // other cells which use this principal to obtain its credentials actually
1587 // have valid tokens or not. If they are currently using these credentials
1588 // we will skip them. For the time being we assume that if there is an active
1589 // map in the table that they are actively being used.
1593 code = pkrb5_parse_name(ctx, principals[count], &princ);
1594 if (code) goto loop_cleanup;
1596 code = KFW_get_ccache(ctx, princ, &cc);
1597 if (code) goto loop_cleanup;
1599 code = pkrb5_cc_destroy(ctx, cc);
1604 pkrb5_cc_close(ctx, cc);
1608 pkrb5_free_principal(ctx, princ);
1612 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1613 free(principals[count]);
1618 pkrb5_free_context(ctx);
1623 KFW_AFS_destroy_tickets_for_principal(char * user)
1625 krb5_context ctx = NULL;
1626 krb5_error_code code;
1628 char ** cells = NULL;
1629 krb5_principal princ = NULL;
1630 krb5_ccache cc = NULL;
1632 if (!pkrb5_init_context)
1633 return KRB5_CONFIG_CANTOPEN;
1635 if ( IsDebuggerPresent() ) {
1636 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1637 OutputDebugString(user);
1638 OutputDebugString("\n");
1641 code = pkrb5_init_context(&ctx);
1644 code = pkrb5_parse_name(ctx, user, &princ);
1645 if (code) goto loop_cleanup;
1647 code = KFW_get_ccache(ctx, princ, &cc);
1648 if (code) goto loop_cleanup;
1650 code = pkrb5_cc_destroy(ctx, cc);
1655 pkrb5_cc_close(ctx, cc);
1659 pkrb5_free_principal(ctx, princ);
1663 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1666 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1673 pkrb5_free_context(ctx);
1678 KFW_AFS_renew_expiring_tokens(void)
1680 krb5_error_code code = 0;
1681 krb5_context ctx = NULL;
1682 krb5_ccache cc = NULL;
1684 struct principal_ccache_data * pcc_next = princ_cc_data;
1687 const char * realm = NULL;
1688 char local_cell[CELL_MAXNAMELEN+1]="";
1689 struct afsconf_cell cellconfig;
1691 if (!pkrb5_init_context)
1692 return KRB5_CONFIG_CANTOPEN;
1694 if ( pcc_next == NULL ) // nothing to do
1697 if ( IsDebuggerPresent() ) {
1698 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1701 memset(&cellconfig, 0, sizeof(cellconfig));
1703 code = pkrb5_init_context(&ctx);
1704 if (code) goto cleanup;
1706 code = pkrb5_timeofday(ctx, &now);
1707 if (code) goto cleanup;
1709 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1710 if ( pcc_next->expired )
1713 if ( now >= (pcc_next->expiration_time) ) {
1714 if ( !pcc_next->from_lsa ) {
1715 pcc_next->expired = 1;
1720 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1721 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1724 code = KFW_renew(ctx,cc);
1726 if ( code && pcc_next->from_lsa)
1728 #endif /* USE_MS2MIT */
1731 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1732 if (code) goto loop_cleanup;
1734 // Attempt to obtain new tokens for other cells supported by the same
1736 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1737 if ( cell_count > 0 ) {
1738 while ( cell_count-- ) {
1739 if ( IsDebuggerPresent() ) {
1740 OutputDebugString("Cell: ");
1741 OutputDebugString(cells[cell_count]);
1742 OutputDebugString("\n");
1744 if (cellconfig.linkedCell) {
1745 free(cellconfig.linkedCell);
1746 cellconfig.linkedCell = NULL;
1748 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1749 if ( code ) continue;
1750 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1751 if ( IsDebuggerPresent() ) {
1752 OutputDebugString("Realm: ");
1753 OutputDebugString(realm);
1754 OutputDebugString("\n");
1756 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1757 if ( IsDebuggerPresent() ) {
1759 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1760 OutputDebugString(message);
1762 free(cells[cell_count]);
1770 pkrb5_cc_close(ctx,cc);
1777 pkrb5_cc_close(ctx,cc);
1779 pkrb5_free_context(ctx);
1780 if (cellconfig.linkedCell)
1781 free(cellconfig.linkedCell);
1788 KFW_AFS_renew_token_for_cell(char * cell)
1790 krb5_error_code code = 0;
1791 krb5_context ctx = NULL;
1793 char ** principals = NULL;
1795 if (!pkrb5_init_context)
1796 return KRB5_CONFIG_CANTOPEN;
1798 if ( IsDebuggerPresent() ) {
1799 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1800 OutputDebugString(cell);
1801 OutputDebugString("\n");
1804 code = pkrb5_init_context(&ctx);
1805 if (code) goto cleanup;
1807 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1809 // We know we must have a credential somewhere since we are
1810 // trying to renew a token
1812 KFW_import_ccache_data();
1813 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1816 krb5_principal princ = 0;
1817 krb5_principal service = 0;
1819 krb5_creds mcreds, creds;
1820 #endif /* COMMENT */
1822 const char * realm = NULL;
1823 struct afsconf_cell cellconfig;
1824 char local_cell[CELL_MAXNAMELEN+1];
1826 memset(&cellconfig, 0, sizeof(cellconfig));
1829 code = pkrb5_parse_name(ctx, principals[count], &princ);
1830 if (code) goto loop_cleanup;
1832 code = KFW_get_ccache(ctx, princ, &cc);
1833 if (code) goto loop_cleanup;
1835 if (cellconfig.linkedCell) {
1836 free(cellconfig.linkedCell);
1837 cellconfig.linkedCell = NULL;
1839 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1840 if ( code ) goto loop_cleanup;
1842 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1843 if ( IsDebuggerPresent() ) {
1844 OutputDebugString("Realm: ");
1845 OutputDebugString(realm);
1846 OutputDebugString("\n");
1850 /* krb5_cc_remove_cred() is not implemented
1853 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1854 realm, "afs", cell, NULL);
1856 memset(&mcreds, 0, sizeof(krb5_creds));
1857 mcreds.client = princ;
1858 mcreds.server = service;
1860 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1862 if ( IsDebuggerPresent() ) {
1863 char * cname, *sname;
1864 pkrb5_unparse_name(ctx, creds.client, &cname);
1865 pkrb5_unparse_name(ctx, creds.server, &sname);
1866 OutputDebugString("Removing credential for client \"");
1867 OutputDebugString(cname);
1868 OutputDebugString("\" and service \"");
1869 OutputDebugString(sname);
1870 OutputDebugString("\"\n");
1871 pkrb5_free_unparsed_name(ctx,cname);
1872 pkrb5_free_unparsed_name(ctx,sname);
1875 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1876 pkrb5_free_principal(ctx, creds.client);
1877 pkrb5_free_principal(ctx, creds.server);
1880 #endif /* COMMENT */
1882 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1883 if ( IsDebuggerPresent() ) {
1885 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1886 OutputDebugString(message);
1891 pkrb5_cc_close(ctx, cc);
1895 pkrb5_free_principal(ctx, princ);
1899 pkrb5_free_principal(ctx, service);
1902 if (cellconfig.linkedCell) {
1903 free(cellconfig.linkedCell);
1904 cellconfig.linkedCell = NULL;
1907 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1908 free(principals[count]);
1912 code = -1; // we did not renew the tokens
1916 pkrb5_free_context(ctx);
1917 return (code ? FALSE : TRUE);
1922 KFW_AFS_renew_tokens_for_all_cells(void)
1924 struct cell_principal_map * next = cell_princ_map;
1926 if ( IsDebuggerPresent() )
1927 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1932 for ( ; next ; next = next->next ) {
1934 KFW_AFS_renew_token_for_cell(next->cell);
1940 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1942 krb5_error_code code = 0;
1943 krb5_context ctx = NULL;
1944 krb5_ccache cc = NULL;
1945 krb5_principal me = NULL;
1946 krb5_principal server = NULL;
1947 krb5_creds my_creds;
1948 krb5_data *realm = NULL;
1950 if (!pkrb5_init_context)
1951 return KRB5_CONFIG_CANTOPEN;
1953 memset(&my_creds, 0, sizeof(krb5_creds));
1958 code = pkrb5_init_context(&ctx);
1959 if (code) goto cleanup;
1965 code = pkrb5_cc_default(ctx, &cc);
1966 if (code) goto cleanup;
1969 code = pkrb5_cc_get_principal(ctx, cc, &me);
1970 if (code) goto cleanup;
1972 realm = krb5_princ_realm(ctx, me);
1974 code = pkrb5_build_principal_ext(ctx, &server,
1975 realm->length,realm->data,
1976 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1977 realm->length,realm->data,
1982 if ( IsDebuggerPresent() ) {
1983 char * cname, *sname;
1984 pkrb5_unparse_name(ctx, me, &cname);
1985 pkrb5_unparse_name(ctx, server, &sname);
1986 OutputDebugString("Renewing credential for client \"");
1987 OutputDebugString(cname);
1988 OutputDebugString("\" and service \"");
1989 OutputDebugString(sname);
1990 OutputDebugString("\"\n");
1991 pkrb5_free_unparsed_name(ctx,cname);
1992 pkrb5_free_unparsed_name(ctx,sname);
1995 my_creds.client = me;
1996 my_creds.server = server;
1998 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
2000 if ( IsDebuggerPresent() ) {
2002 StringCbPrintf(message, sizeof(message), "krb5_get_renewed_creds() failed: %d\n", code);
2003 OutputDebugString(message);
2008 code = pkrb5_cc_initialize(ctx, cc, me);
2010 if ( IsDebuggerPresent() ) {
2012 StringCbPrintf(message, sizeof(message), "krb5_cc_initialize() failed: %d\n", code);
2013 OutputDebugString(message);
2018 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2020 if ( IsDebuggerPresent() ) {
2022 StringCbPrintf(message, sizeof(message), "krb5_cc_store_cred() failed: %d\n", code);
2023 OutputDebugString(message);
2029 if (my_creds.client == me)
2030 my_creds.client = 0;
2031 if (my_creds.server == server)
2032 my_creds.server = 0;
2033 pkrb5_free_cred_contents(ctx, &my_creds);
2035 pkrb5_free_principal(ctx, me);
2037 pkrb5_free_principal(ctx, server);
2038 if (cc && (cc != alt_cc))
2039 pkrb5_cc_close(ctx, cc);
2040 if (ctx && (ctx != alt_ctx))
2041 pkrb5_free_context(ctx);
2046 KFW_kinit( krb5_context alt_ctx,
2049 char *principal_name,
2051 krb5_deltat lifetime,
2054 krb5_deltat renew_life,
2059 krb5_error_code code = 0;
2060 krb5_context ctx = NULL;
2061 krb5_ccache cc = NULL;
2062 krb5_principal me = NULL;
2064 krb5_creds my_creds;
2065 krb5_get_init_creds_opt options;
2066 krb5_address ** addrs = NULL;
2067 int i = 0, addr_count = 0;
2069 if (!pkrb5_init_context)
2070 return KRB5_CONFIG_CANTOPEN;
2072 pkrb5_get_init_creds_opt_init(&options);
2073 memset(&my_creds, 0, sizeof(my_creds));
2081 code = pkrb5_init_context(&ctx);
2082 if (code) goto cleanup;
2088 code = pkrb5_cc_default(ctx, &cc);
2089 if (code) goto cleanup;
2092 code = pkrb5_parse_name(ctx, principal_name, &me);
2096 code = pkrb5_unparse_name(ctx, me, &name);
2101 lifetime = DEFAULT_LIFETIME;
2108 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2109 pkrb5_get_init_creds_opt_set_forwardable(&options,
2110 forwardable ? 1 : 0);
2111 pkrb5_get_init_creds_opt_set_proxiable(&options,
2113 pkrb5_get_init_creds_opt_set_renew_life(&options,
2116 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2120 // we are going to add the public IP address specified by the user
2121 // to the list provided by the operating system
2122 krb5_address ** local_addrs=NULL;
2125 pkrb5_os_localaddr(ctx, &local_addrs);
2126 while ( local_addrs[i++] );
2129 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2131 pkrb5_free_addresses(ctx, local_addrs);
2134 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2136 while ( local_addrs[i] ) {
2137 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2138 if (addrs[i] == NULL) {
2139 pkrb5_free_addresses(ctx, local_addrs);
2143 addrs[i]->magic = local_addrs[i]->magic;
2144 addrs[i]->addrtype = local_addrs[i]->addrtype;
2145 addrs[i]->length = local_addrs[i]->length;
2146 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2147 if (!addrs[i]->contents) {
2148 pkrb5_free_addresses(ctx, local_addrs);
2152 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2153 local_addrs[i]->length); /* safe */
2156 pkrb5_free_addresses(ctx, local_addrs);
2158 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2159 if (addrs[i] == NULL)
2162 addrs[i]->magic = KV5M_ADDRESS;
2163 addrs[i]->addrtype = AF_INET;
2164 addrs[i]->length = 4;
2165 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2166 if (!addrs[i]->contents)
2169 netIPAddr = htonl(publicIP);
2170 memcpy(addrs[i]->contents,&netIPAddr,4);
2172 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2177 code = pkrb5_get_init_creds_password(ctx,
2180 password, // password
2181 KRB5_prompter, // prompter
2182 hParent, // prompter data
2189 code = pkrb5_cc_initialize(ctx, cc, me);
2193 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2199 for ( i=0;i<addr_count;i++ ) {
2201 if ( addrs[i]->contents )
2202 free(addrs[i]->contents);
2207 if (my_creds.client == me)
2208 my_creds.client = 0;
2209 pkrb5_free_cred_contents(ctx, &my_creds);
2211 pkrb5_free_unparsed_name(ctx, name);
2213 pkrb5_free_principal(ctx, me);
2214 if (cc && (cc != alt_cc))
2215 pkrb5_cc_close(ctx, cc);
2216 if (ctx && (ctx != alt_ctx))
2217 pkrb5_free_context(ctx);
2223 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2225 krb5_context ctx = NULL;
2226 krb5_ccache cc = NULL;
2227 krb5_error_code code;
2229 if (!pkrb5_init_context)
2230 return KRB5_CONFIG_CANTOPEN;
2238 code = pkrb5_init_context(&ctx);
2239 if (code) goto cleanup;
2245 code = pkrb5_cc_default(ctx, &cc);
2246 if (code) goto cleanup;
2249 code = pkrb5_cc_destroy(ctx, cc);
2250 if ( !code ) cc = 0;
2253 if (cc && (cc != alt_cc))
2254 pkrb5_cc_close(ctx, cc);
2255 if (ctx && (ctx != alt_ctx))
2256 pkrb5_free_context(ctx);
2264 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2266 NTSTATUS Status = 0;
2268 TOKEN_STATISTICS Stats;
2274 *ppSessionData = NULL;
2276 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2280 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2281 CloseHandle( TokenHandle );
2285 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2286 if ( FAILED(Status) || !ppSessionData )
2293 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2294 // cache. It validates whether or not it is reasonable to assume that if we
2295 // attempted to retrieve valid tickets we could do so. Microsoft does not
2296 // automatically renew expired tickets. Therefore, the cache could contain
2297 // expired or invalid tickets. Microsoft also caches the user's password
2298 // and will use it to retrieve new TGTs if the cache is empty and tickets
2302 MSLSA_IsKerberosLogon(VOID)
2304 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2305 BOOL Success = FALSE;
2307 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2308 if ( pSessionData->AuthenticationPackage.Buffer ) {
2314 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2315 usLength = (pSessionData->AuthenticationPackage).Length;
2318 StringCbCopyNW( buffer, sizeof(buffer)/sizeof(WCHAR),
2319 usBuffer, usLength);
2320 if ( !lstrcmpW(L"Kerberos",buffer) )
2324 pLsaFreeReturnBuffer(pSessionData);
2328 #endif /* USE_MS2MIT */
2330 static BOOL CALLBACK
2331 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2335 switch ( message ) {
2337 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2339 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2342 for ( i=0; i < mid_cnt ; i++ ) {
2343 if (mid_tb[i].echo == 0)
2344 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2345 else if (mid_tb[i].echo == 2)
2346 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2351 switch ( LOWORD(wParam) ) {
2353 for ( i=0; i < mid_cnt ; i++ ) {
2354 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2355 *mid_tb[i].buf = '\0';
2359 EndDialog(hDialog, LOWORD(wParam));
2367 lpwAlign( LPWORD lpIn )
2371 ul = (ULONG_PTR) lpIn;
2375 return (LPWORD) ul;;
2379 * dialog widths are measured in 1/4 character widths
2380 * dialog height are measured in 1/8 character heights
2384 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2385 char * ptext[], int numlines, int width,
2386 int tb_cnt, struct textField * tb)
2390 LPDLGITEMTEMPLATE lpdit;
2396 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2403 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2405 // Define a dialog box.
2407 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2408 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2409 | DS_SETFOREGROUND | DS_3DLOOK
2410 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2411 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2414 lpdt->cx = 20 + width * 4;
2415 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2417 lpw = (LPWORD) (lpdt + 1);
2418 *lpw++ = 0; // no menu
2419 *lpw++ = 0; // predefined dialog box class (by default)
2421 lpwsz = (LPWSTR) lpw;
2422 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2424 *lpw++ = 8; // font size (points)
2425 lpwsz = (LPWSTR) lpw;
2426 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2430 //-----------------------
2431 // Define an OK button.
2432 //-----------------------
2433 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2434 lpdit = (LPDLGITEMTEMPLATE) lpw;
2435 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2436 lpdit->dwExtendedStyle = 0;
2437 lpdit->x = (lpdt->cx - 14)/4 - 20;
2438 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2441 lpdit->id = IDOK; // OK button identifier
2443 lpw = (LPWORD) (lpdit + 1);
2445 *lpw++ = 0x0080; // button class
2447 lpwsz = (LPWSTR) lpw;
2448 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2450 *lpw++ = 0; // no creation data
2452 //-----------------------
2453 // Define an Cancel button.
2454 //-----------------------
2455 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2456 lpdit = (LPDLGITEMTEMPLATE) lpw;
2457 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2458 lpdit->dwExtendedStyle = 0;
2459 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2460 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2463 lpdit->id = IDCANCEL; // CANCEL button identifier
2465 lpw = (LPWORD) (lpdit + 1);
2467 *lpw++ = 0x0080; // button class
2469 lpwsz = (LPWSTR) lpw;
2470 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2472 *lpw++ = 0; // no creation data
2474 /* Add controls for preface data */
2475 for ( i=0; i<numlines; i++) {
2476 /*-----------------------
2477 * Define a static text control.
2478 *-----------------------*/
2479 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2480 lpdit = (LPDLGITEMTEMPLATE) lpw;
2481 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2482 lpdit->dwExtendedStyle = 0;
2484 lpdit->y = 10 + i * 14;
2485 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2487 lpdit->id = ID_TEXT + i; // text identifier
2489 lpw = (LPWORD) (lpdit + 1);
2491 *lpw++ = 0x0082; // static class
2493 lpwsz = (LPWSTR) lpw;
2494 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2495 -1, lpwsz, 2*width);
2497 *lpw++ = 0; // no creation data
2500 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2501 int len = (int)strlen(tb[i].label);
2506 for ( i=0; i<tb_cnt; i++) {
2508 /*-----------------------
2509 * Define a static text control.
2510 *-----------------------*/
2511 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2512 lpdit = (LPDLGITEMTEMPLATE) lpw;
2513 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2514 lpdit->dwExtendedStyle = 0;
2516 lpdit->y = 10 + (numlines + i + 1) * 14;
2517 lpdit->cx = pwid * 4;
2519 lpdit->id = ID_TEXT + numlines + i; // text identifier
2521 lpw = (LPWORD) (lpdit + 1);
2523 *lpw++ = 0x0082; // static class
2525 lpwsz = (LPWSTR) lpw;
2526 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2529 *lpw++ = 0; // no creation data
2531 /*-----------------------
2532 * Define an edit control.
2533 *-----------------------*/
2534 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2535 lpdit = (LPDLGITEMTEMPLATE) lpw;
2536 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2537 lpdit->dwExtendedStyle = 0;
2538 lpdit->x = 10 + (pwid + 1) * 4;
2539 lpdit->y = 10 + (numlines + i + 1) * 14;
2540 lpdit->cx = (width - (pwid + 1)) * 4;
2542 lpdit->id = ID_MID_TEXT + i; // identifier
2544 lpw = (LPWORD) (lpdit + 1);
2546 *lpw++ = 0x0081; // edit class
2548 lpwsz = (LPWSTR) lpw;
2549 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2552 *lpw++ = 0; // no creation data
2556 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2557 hwndOwner, (DLGPROC) MultiInputDialogProc);
2561 case 0: /* Timeout */
2569 StringCbPrintf(buf, sizeof(buf), "DialogBoxIndirect() failed: %d", GetLastError());
2570 MessageBox(hwndOwner,
2573 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2580 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2582 HINSTANCE hInst = 0;
2586 char * plines[16], *p = preface ? preface : "";
2589 for ( i=0; i<16; i++ )
2592 while (*p && numlines < 16) {
2593 plines[numlines++] = p;
2594 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2595 if ( *p == '\r' && *(p+1) == '\n' ) {
2598 } else if ( *p == '\n' ) {
2601 if ( strlen(plines[numlines-1]) > maxwidth )
2602 maxwidth = (int)strlen(plines[numlines-1]);
2605 for ( i=0;i<n;i++ ) {
2606 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2607 if ( maxwidth < len )
2611 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2614 static krb5_error_code KRB5_CALLCONV
2615 KRB5_prompter( krb5_context context,
2620 krb5_prompt prompts[])
2622 krb5_error_code errcode = 0;
2624 struct textField * tb = NULL;
2625 int len = 0, blen=0, nlen=0;
2626 HWND hParent = (HWND)data;
2629 nlen = (int)strlen(name)+2;
2632 blen = (int)strlen(banner)+2;
2634 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2637 memset(tb,0,sizeof(struct textField) * num_prompts);
2638 for ( i=0; i < num_prompts; i++ ) {
2639 tb[i].buf = prompts[i].reply->data;
2640 tb[i].len = prompts[i].reply->length;
2641 tb[i].label = prompts[i].prompt;
2643 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2646 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2648 for ( i=0; i < num_prompts; i++ )
2649 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2657 for (i = 0; i < num_prompts; i++) {
2658 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2665 KFW_AFS_wait_for_service_start(void)
2670 CurrentState = SERVICE_START_PENDING;
2671 memset(HostName, '\0', sizeof(HostName));
2672 gethostname(HostName, sizeof(HostName));
2674 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2676 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2678 if ( IsDebuggerPresent() ) {
2679 switch ( CurrentState ) {
2680 case SERVICE_STOPPED:
2681 OutputDebugString("SERVICE_STOPPED\n");
2683 case SERVICE_START_PENDING:
2684 OutputDebugString("SERVICE_START_PENDING\n");
2686 case SERVICE_STOP_PENDING:
2687 OutputDebugString("SERVICE_STOP_PENDING\n");
2689 case SERVICE_RUNNING:
2690 OutputDebugString("SERVICE_RUNNING\n");
2692 case SERVICE_CONTINUE_PENDING:
2693 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2695 case SERVICE_PAUSE_PENDING:
2696 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2698 case SERVICE_PAUSED:
2699 OutputDebugString("SERVICE_PAUSED\n");
2702 OutputDebugString("UNKNOWN Service State\n");
2705 if (CurrentState == SERVICE_STOPPED)
2707 if (CurrentState == SERVICE_RUNNING)
2723 memset(HostName, '\0', sizeof(HostName));
2724 gethostname(HostName, sizeof(HostName));
2725 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2727 if (CurrentState != SERVICE_RUNNING)
2730 rc = ktc_ForgetAllTokens();
2736 #define ALLOW_REGISTER 1
2738 ViceIDToUsername(char *username,
2739 char *realm_of_user,
2740 char *realm_of_cell,
2742 struct ktc_principal *aclient,
2743 struct ktc_principal *aserver,
2744 struct ktc_token *atoken)
2746 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2747 static char confdir[512] = { 0 };
2748 #ifdef AFS_ID_TO_NAME
2749 char username_copy[BUFSIZ];
2750 #endif /* AFS_ID_TO_NAME */
2751 long viceId = ANONYMOUSID; /* AFS uid of user */
2753 #ifdef ALLOW_REGISTER
2755 #endif /* ALLOW_REGISTER */
2757 if (confdir[0] == '\0')
2758 cm_GetConfigDir(confdir, sizeof(confdir));
2760 StringCbCopyN( lastcell, sizeof(lastcell),
2761 aserver->cell, sizeof(lastcell) - 1);
2763 if (!pr_Initialize (0, confdir, aserver->cell)) {
2764 char sname[PR_MAXNAMELEN];
2765 StringCbCopyN( sname, sizeof(sname),
2766 username, sizeof(sname) - 1);
2767 status = pr_SNameToId (sname, &viceId);
2772 * This is a crock, but it is Transarc's crock, so
2773 * we have to play along in order to get the
2774 * functionality. The way the afs id is stored is
2775 * as a string in the username field of the token.
2776 * Contrary to what you may think by looking at
2777 * the code for tokens, this hack (AFS ID %d) will
2778 * not work if you change %d to something else.
2782 * This code is taken from cklog -- it lets people
2783 * automatically register with the ptserver in foreign cells
2786 #ifdef ALLOW_REGISTER
2788 if (viceId != ANONYMOUSID) {
2789 #else /* ALLOW_REGISTER */
2790 if ((status == 0) && (viceId != ANONYMOUSID))
2791 #endif /* ALLOW_REGISTER */
2793 #ifdef AFS_ID_TO_NAME
2794 StringCbCopyN( username_copy, sizeof(username_copy),
2795 username, sizeof(username_copy) - 1);
2796 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2797 #endif /* AFS_ID_TO_NAME */
2799 #ifdef ALLOW_REGISTER
2800 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2802 StringCbCopyN( aclient->name, sizeof(aclient->name),
2803 username, sizeof(aclient->name) - 1);
2804 aclient->instance[0] = '\0';
2805 StringCbCopyN( aclient->cell, sizeof(aclient->cell),
2806 realm_of_user, sizeof(aclient->cell) - 1);
2807 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2809 if (status = pr_Initialize(1L, confdir, aserver->cell))
2811 status = pr_CreateUser(username, &id);
2815 #ifdef AFS_ID_TO_NAME
2816 StringCbCopyN( username_copy, sizeof(username_copy),
2817 username, sizeof(username_copy) - 1);
2818 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2819 #endif /* AFS_ID_TO_NAME */
2822 #endif /* ALLOW_REGISTER */
2828 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2829 krb5_error_code code;
2830 krb5_ticket *ticket;
2833 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2835 len = krb5_princ_realm(context, ticket->server)->length;
2836 if (len > destlen - 1)
2839 StringCbCopyN(dest, destlen, krb5_princ_realm(context, ticket->server)->data, len);
2841 pkrb5_free_ticket(context, ticket);
2847 krb5_context alt_ctx,
2852 int lifetime, /* unused parameter */
2860 #endif /* USE_KRB4 */
2861 struct ktc_principal aserver;
2862 struct ktc_principal aclient;
2863 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2864 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2865 char local_cell[CELL_MAXNAMELEN+1];
2866 char Dmycell[CELL_MAXNAMELEN+1];
2867 struct ktc_token atoken;
2868 struct ktc_token btoken;
2869 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2870 char RealmName[128];
2872 char ServiceName[128];
2876 krb5_context ctx = NULL;
2877 krb5_ccache cc = NULL;
2879 krb5_creds * k5creds = NULL;
2880 krb5_error_code code;
2881 krb5_principal client_principal = NULL;
2882 krb5_data * k5data = NULL;
2883 unsigned int i, retry = 0;
2886 memset(HostName, '\0', sizeof(HostName));
2887 gethostname(HostName, sizeof(HostName));
2888 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2889 if ( IsDebuggerPresent() )
2890 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2893 if (CurrentState != SERVICE_RUNNING) {
2894 if ( IsDebuggerPresent() )
2895 OutputDebugString("AFSD Service NOT RUNNING\n");
2899 if (!pkrb5_init_context)
2900 return KRB5_CONFIG_CANTOPEN;
2902 memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
2903 memset(RealmName, '\0', sizeof(RealmName));
2904 memset(CellName, '\0', sizeof(CellName));
2905 memset(ServiceName, '\0', sizeof(ServiceName));
2906 memset(realm_of_user, '\0', sizeof(realm_of_user));
2907 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2908 if (cell && cell[0])
2909 StringCbCopyN( Dmycell, sizeof(Dmycell),
2910 cell, sizeof(Dmycell) - 1);
2912 memset(Dmycell, '\0', sizeof(Dmycell));
2914 // NULL or empty cell returns information on local cell
2915 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2917 // KFW_AFS_error(rc, "get_cellconfig()");
2924 code = pkrb5_init_context(&ctx);
2925 if (code) goto cleanup;
2931 code = pkrb5_cc_default(ctx, &cc);
2932 if (code) goto skip_krb5_init;
2935 memset(&increds, 0, sizeof(increds));
2937 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2939 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2941 OutputDebugString("Principal Not Found for ccache\n");
2943 goto skip_krb5_init;
2946 if (!KFW_accept_dotted_usernames()) {
2947 /* look for client principals which cannot be distinguished
2948 * from Kerberos 4 multi-component principal names
2950 k5data = krb5_princ_component(ctx,client_principal,0);
2951 for ( i=0; i<k5data->length; i++ ) {
2952 if ( k5data->data[i] == '.' )
2955 if (i != k5data->length)
2957 OutputDebugString("Illegal Principal name contains dot in first component\n");
2958 rc = KRB5KRB_ERR_GENERIC;
2963 i = krb5_princ_realm(ctx, client_principal)->length;
2966 StringCbCopyN( realm_of_user, sizeof(realm_of_user),
2967 krb5_princ_realm(ctx, client_principal)->data, i);
2972 if ( !try_krb5 || !realm_of_user[0] ) {
2973 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2982 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
2983 afs_realm_of_cell(ctx, &ak_cellconfig),
2984 sizeof(realm_of_cell) - 1);
2986 if (strlen(service) == 0)
2987 StringCbCopy( ServiceName, sizeof(ServiceName), "afs");
2989 StringCbCopyN( ServiceName, sizeof(ServiceName),
2990 service, sizeof(ServiceName) - 1);
2992 if (strlen(cell) == 0)
2993 StringCbCopyN( CellName, sizeof(CellName),
2994 local_cell, sizeof(CellName) - 1);
2996 StringCbCopyN( CellName, sizeof(CellName),
2997 cell, sizeof(CellName) - 1);
2999 /* This is for Kerberos v4 only */
3000 if (strlen(realm) == 0)
3001 StringCbCopyN( RealmName, sizeof(RealmName),
3002 realm_of_cell, sizeof(RealmName) - 1);
3004 StringCbCopyN( RealmName, sizeof(RealmName),
3005 realm, sizeof(RealmName) - 1);
3007 memset(&creds, '\0', sizeof(creds));
3011 code = KRB5KRB_ERR_GENERIC;
3014 increds.client = client_principal;
3015 increds.times.endtime = 0;
3016 /* Ask for DES since that is what V4 understands */
3017 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
3019 /* ALWAYS first try service/cell@CLIENT_REALM */
3020 if (code = pkrb5_build_principal(ctx, &increds.server,
3021 (int)strlen(realm_of_user),
3030 if ( IsDebuggerPresent() ) {
3031 char * cname, *sname;
3032 pkrb5_unparse_name(ctx, increds.client, &cname);
3033 pkrb5_unparse_name(ctx, increds.server, &sname);
3034 OutputDebugString("Getting tickets for \"");
3035 OutputDebugString(cname);
3036 OutputDebugString("\" and service \"");
3037 OutputDebugString(sname);
3038 OutputDebugString("\"\n");
3039 pkrb5_free_unparsed_name(ctx,cname);
3040 pkrb5_free_unparsed_name(ctx,sname);
3043 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3045 /* The client's realm is a local realm for the cell.
3046 * Save it so that later the pts registration will not
3049 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3050 realm_of_user, sizeof(realm_of_cell) - 1);
3054 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3055 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3056 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3057 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3058 /* If there was a specific realm we are supposed to try
3061 if (strlen(realm) != 0) {
3062 /* service/cell@REALM */
3064 code = pkrb5_build_principal(ctx, &increds.server,
3070 if ( IsDebuggerPresent() ) {
3071 char * cname, *sname;
3072 pkrb5_unparse_name(ctx, increds.client, &cname);
3073 pkrb5_unparse_name(ctx, increds.server, &sname);
3074 OutputDebugString("Getting tickets for \"");
3075 OutputDebugString(cname);
3076 OutputDebugString("\" and service \"");
3077 OutputDebugString(sname);
3078 OutputDebugString("\"\n");
3079 pkrb5_free_unparsed_name(ctx,cname);
3080 pkrb5_free_unparsed_name(ctx,sname);
3084 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3086 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3087 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3088 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3089 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3090 /* Or service@REALM */
3091 pkrb5_free_principal(ctx,increds.server);
3093 code = pkrb5_build_principal(ctx, &increds.server,
3099 if ( IsDebuggerPresent() ) {
3100 char * cname, *sname;
3101 pkrb5_unparse_name(ctx, increds.client, &cname);
3102 pkrb5_unparse_name(ctx, increds.server, &sname);
3103 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3104 OutputDebugString("Trying again: getting tickets for \"");
3105 OutputDebugString(cname);
3106 OutputDebugString("\" and service \"");
3107 OutputDebugString(sname);
3108 OutputDebugString("\"\n");
3109 pkrb5_free_unparsed_name(ctx,cname);
3110 pkrb5_free_unparsed_name(ctx,sname);
3114 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3118 /* we have a local realm for the cell */
3119 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3120 realm, sizeof(realm_of_cell) - 1);
3123 if (strcmp(realm_of_user, realm_of_cell)) {
3124 /* Then service/cell@CELL_REALM */
3125 pkrb5_free_principal(ctx,increds.server);
3127 code = pkrb5_build_principal(ctx, &increds.server,
3128 (int)strlen(realm_of_cell),
3133 if ( IsDebuggerPresent() ) {
3134 char * cname, *sname;
3135 pkrb5_unparse_name(ctx, increds.client, &cname);
3136 pkrb5_unparse_name(ctx, increds.server, &sname);
3137 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3138 OutputDebugString("Trying again: getting tickets for \"");
3139 OutputDebugString(cname);
3140 OutputDebugString("\" and service \"");
3141 OutputDebugString(sname);
3142 OutputDebugString("\"\n");
3143 pkrb5_free_unparsed_name(ctx,cname);
3144 pkrb5_free_unparsed_name(ctx,sname);
3148 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3150 if (!code && !strlen(realm_of_cell))
3151 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3154 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3155 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3156 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3157 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3158 /* Finally service@CELL_REALM */
3159 pkrb5_free_principal(ctx,increds.server);
3161 code = pkrb5_build_principal(ctx, &increds.server,
3162 (int)strlen(realm_of_cell),
3167 if ( IsDebuggerPresent() ) {
3168 char * cname, *sname;
3169 pkrb5_unparse_name(ctx, increds.client, &cname);
3170 pkrb5_unparse_name(ctx, increds.server, &sname);
3171 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3172 OutputDebugString("Trying again: getting tickets for \"");
3173 OutputDebugString(cname);
3174 OutputDebugString("\" and service \"");
3175 OutputDebugString(sname);
3176 OutputDebugString("\"\n");
3177 pkrb5_free_unparsed_name(ctx,cname);
3178 pkrb5_free_unparsed_name(ctx,sname);
3182 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3183 if (!code && !strlen(realm_of_cell))
3184 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3190 if ( IsDebuggerPresent() ) {
3192 StringCbPrintf(message, sizeof(message), "krb5_get_credentials returns: %d\n", code);
3193 OutputDebugString(message);
3199 /* This code inserts the entire K5 ticket into the token
3200 * No need to perform a krb524 translation which is
3201 * commented out in the code below
3203 if (KFW_use_krb524() ||
3204 k5creds->ticket.length > MAXKTCTICKETLEN)
3207 memset(&aserver, '\0', sizeof(aserver));
3208 StringCbCopyN(aserver.name, sizeof(aserver.name),
3209 ServiceName, sizeof(aserver.name) - 1);
3210 StringCbCopyN(aserver.cell, sizeof(aserver.cell),
3211 CellName, sizeof(aserver.cell) - 1);
3213 memset(&atoken, '\0', sizeof(atoken));
3214 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3215 atoken.startTime = k5creds->times.starttime;
3216 atoken.endTime = k5creds->times.endtime;
3217 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3218 atoken.ticketLen = k5creds->ticket.length;
3219 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3222 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3223 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3224 if ( rc == KTC_NOCM && retry < 20 ) {
3227 goto retry_gettoken5;
3232 if (atoken.kvno == btoken.kvno &&
3233 atoken.ticketLen == btoken.ticketLen &&
3234 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3235 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3237 /* Success - Nothing to do */
3241 // * Reset the "aclient" structure before we call ktc_SetToken.
3242 // * This structure was first set by the ktc_GetToken call when
3243 // * we were comparing whether identical tokens already existed.
3245 len = min(k5creds->client->data[0].length, sizeof(aclient.name) - 1);
3246 StringCbCopyN( aclient.name, sizeof(aclient.name),
3247 k5creds->client->data[0].data, len);
3249 if ( k5creds->client->length > 1 ) {
3250 StringCbCat( aclient.name, sizeof(aclient.name), ".");
3251 len = min(k5creds->client->data[1].length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3252 StringCbCatN( aclient.name, sizeof(aclient.name),
3253 k5creds->client->data[1].data, len);
3255 aclient.instance[0] = '\0';
3257 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3258 realm_of_cell, sizeof(aclient.cell) - 1);
3260 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3261 /* For Khimaira, always append the realm name */
3262 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3263 StringCbCat( aclient.name, sizeof(aclient.name), "@");
3264 len = min(k5creds->client->realm.length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3265 StringCbCatN( aclient.name, sizeof(aclient.name), k5creds->client->realm.data, len);
3268 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3269 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3270 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3271 &aclient, &aserver, &atoken);
3274 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3275 smbname, sizeof(aclient.smbname) - 1);
3277 aclient.smbname[0] = '\0';
3280 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3282 goto cleanup; /* We have successfully inserted the token */
3288 /* Otherwise, the ticket could have been too large so try to
3289 * convert using the krb524d running with the KDC
3291 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3292 pkrb5_free_creds(ctx, k5creds);
3294 if ( IsDebuggerPresent() ) {
3296 StringCbPrintf(message, sizeof(message), "krb524_convert_creds_kdc returns: %d\n", code);
3297 OutputDebugString(message);
3302 #endif /* USE_KRB524 */
3306 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3307 if (code == NO_TKT_FIL) {
3308 // if the problem is that we have no krb4 tickets
3309 // do not attempt to continue
3312 if (code != KSUCCESS)
3313 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3315 if (code != KSUCCESS)
3317 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3319 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3324 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3326 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3341 memset(&aserver, '\0', sizeof(aserver));
3342 StringCbCopyN( aserver.name, sizeof(aserver.name), ServiceName, sizeof(aserver.name) - 1);
3343 StringCbCopyN( aserver.cell, sizeof(aserver.cell), CellName, sizeof(aserver.cell) - 1);
3345 memset(&atoken, '\0', sizeof(atoken));
3346 atoken.kvno = creds.kvno;
3347 atoken.startTime = creds.issue_date;
3348 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3349 memcpy(&atoken.sessionKey, creds.session, 8);
3350 atoken.ticketLen = creds.ticket_st.length;
3351 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3354 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3355 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3356 if ( rc == KTC_NOCM && retry < 20 ) {
3359 goto retry_gettoken;
3361 KFW_AFS_error(rc, "ktc_GetToken()");
3366 if (atoken.kvno == btoken.kvno &&
3367 atoken.ticketLen == btoken.ticketLen &&
3368 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3369 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3374 // * Reset the "aclient" structure before we call ktc_SetToken.
3375 // * This structure was first set by the ktc_GetToken call when
3376 // * we were comparing whether identical tokens already existed.
3378 StringCbCopyN( aclient.name, sizeof(aclient.name), creds.pname, sizeof(aclient.name) - 1);
3381 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3382 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3384 aclient.instance[0] = '\0';
3386 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3387 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3388 aclient.name[MAXKTCREALMLEN-1] = '\0';
3390 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3391 CellName, sizeof(aclient.cell) - 1);
3393 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3394 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3395 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3396 &aclient, &aserver, &atoken);
3399 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3400 smbname, sizeof(aclient.smbname) - 1);
3402 aclient.smbname[0] = '\0';
3405 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3407 KFW_AFS_error(rc, "ktc_SetToken()");
3413 if (client_principal)
3414 pkrb5_free_principal(ctx,client_principal);
3415 /* increds.client == client_principal */
3417 pkrb5_free_principal(ctx,increds.server);
3418 if (cc && (cc != alt_cc))
3419 pkrb5_cc_close(ctx, cc);
3420 if (ctx && (ctx != alt_ctx))
3421 pkrb5_free_context(ctx);
3422 if (ak_cellconfig.linkedCell)
3423 free(ak_cellconfig.linkedCell);
3425 return(rc? rc : code);
3428 /**************************************/
3429 /* afs_realm_of_cell(): */
3430 /**************************************/
3432 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3434 static char krbrlm[REALM_SZ+1]="";
3435 char ** realmlist=NULL;
3441 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3442 if ( !r && realmlist && realmlist[0] ) {
3443 StringCbCopyN( krbrlm, sizeof(krbrlm),
3444 realmlist[0], sizeof(krbrlm) - 1);
3445 pkrb5_free_host_realm(ctx, realmlist);
3451 char *t = cellconfig->name;
3456 if (islower(c)) c=toupper(c);
3464 /**************************************/
3465 /* KFW_AFS_get_cellconfig(): */
3466 /**************************************/
3468 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3471 char newcell[CELL_MAXNAMELEN+1];
3472 char linkedcell[CELL_MAXNAMELEN+1]="";
3474 local_cell[0] = (char)0;
3475 memset(cellconfig, 0, sizeof(*cellconfig));
3477 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3478 if (rc = cm_GetRootCellName(local_cell))
3483 if (strlen(cell) == 0)
3484 strcpy(cell, local_cell);
3486 rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3487 if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
3488 rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3491 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3495 StringCbCopyN( cellconfig->name, sizeof(cellconfig->name),
3496 newcell, sizeof(cellconfig->name) - 1);
3498 cellconfig->linkedCell = strdup(linkedcell);
3503 /**************************************/
3504 /* get_cellconfig_callback(): */
3505 /**************************************/
3507 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
3509 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3511 cc->hostAddr[cc->numServers] = *addrp;
3512 StringCbCopyN( cc->hostName[cc->numServers], sizeof(cc->hostName[cc->numServers]),
3513 namep, sizeof(cc->hostName[cc->numServers]) - 1);
3519 /**************************************/
3520 /* KFW_AFS_error(): */
3521 /**************************************/
3523 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3526 const char *errText;
3528 // Using AFS defines as error messages for now, until Transarc
3529 // gets back to me with "string" translations of each of these
3531 if (rc == KTC_ERROR)
3532 errText = "KTC_ERROR";
3533 else if (rc == KTC_TOOBIG)
3534 errText = "KTC_TOOBIG";
3535 else if (rc == KTC_INVAL)
3536 errText = "KTC_INVAL";
3537 else if (rc == KTC_NOENT)
3538 errText = "KTC_NOENT";
3539 else if (rc == KTC_PIOCTLFAIL)
3540 errText = "KTC_PIOCTLFAIL";
3541 else if (rc == KTC_NOPIOCTL)
3542 errText = "KTC_NOPIOCTL";
3543 else if (rc == KTC_NOCELL)
3544 errText = "KTC_NOCELL";
3545 else if (rc == KTC_NOCM)
3546 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3548 errText = "Unknown error!";
3550 StringCbPrintf(message, sizeof(message), "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3552 if ( IsDebuggerPresent() ) {
3553 OutputDebugString(message);
3554 OutputDebugString("\n");
3556 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3562 LPSTR lpszMachineName,
3563 LPSTR lpszServiceName,
3564 DWORD *lpdwCurrentState)
3567 SC_HANDLE schSCManager = NULL;
3568 SC_HANDLE schService = NULL;
3569 DWORD fdwDesiredAccess = 0;
3570 SERVICE_STATUS ssServiceStatus = {0};
3573 *lpdwCurrentState = 0;
3575 fdwDesiredAccess = GENERIC_READ;
3577 schSCManager = OpenSCManager(lpszMachineName,
3581 if(schSCManager == NULL)
3583 hr = GetLastError();
3587 schService = OpenService(schSCManager,
3591 if(schService == NULL)
3593 hr = GetLastError();
3597 fRet = QueryServiceStatus(schService,
3602 hr = GetLastError();
3606 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3610 CloseServiceHandle(schService);
3611 CloseServiceHandle(schSCManager);
3624 for (n = 0; fi[n].func_ptr_var; n++)
3625 *(fi[n].func_ptr_var) = 0;
3626 if (h) FreeLibrary(h);
3631 const char* dll_name,
3633 HINSTANCE* ph, // [out, optional] - DLL handle
3634 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3635 int cleanup, // cleanup function pointers and unload on error
3636 int go_on, // continue loading even if some functions cannot be loaded
3637 int silent // do not pop-up a system dialog if DLL cannot be loaded
3646 if (pindex) *pindex = -1;
3648 for (n = 0; fi[n].func_ptr_var; n++)
3649 *(fi[n].func_ptr_var) = 0;
3652 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3653 h = LoadLibrary(dll_name);
3661 for (i = 0; (go_on || !error) && (i < n); i++)
3663 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3669 *(fi[i].func_ptr_var) = p;
3672 if (pindex) *pindex = last_i;
3673 if (error && cleanup && !go_on) {
3674 for (i = 0; i < n; i++) {
3675 *(fi[i].func_ptr_var) = 0;
3681 if (error) return 0;
3685 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3687 krb5_context ctx = NULL;
3688 krb5_ccache cc = NULL;
3689 krb5_error_code code;
3691 const char * realm = NULL;
3692 krb5_principal principal = NULL;
3693 char * pname = NULL;
3694 char password[PROBE_PASSWORD_LEN+1];
3695 BOOL serverReachable = 0;
3697 if (!pkrb5_init_context)
3698 return KRB5_CONFIG_CANTOPEN;
3700 code = pkrb5_init_context(&ctx);
3701 if (code) goto cleanup;
3704 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3706 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3707 realm, PROBE_USERNAME, NULL, NULL);
3708 if ( code ) goto cleanup;
3710 code = KFW_get_ccache(ctx, principal, &cc);
3711 if ( code ) goto cleanup;
3713 code = pkrb5_unparse_name(ctx, principal, &pname);
3714 if ( code ) goto cleanup;
3716 pwdata.data = password;
3717 pwdata.length = PROBE_PASSWORD_LEN;
3718 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3721 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3724 password[PROBE_PASSWORD_LEN] = '\0';
3726 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3736 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3737 case KRB5KDC_ERR_CLIENT_REVOKED:
3738 case KRB5KDC_ERR_CLIENT_NOTYET:
3739 case KRB5KDC_ERR_PREAUTH_FAILED:
3740 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3741 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3742 serverReachable = TRUE;
3745 serverReachable = FALSE;
3750 pkrb5_free_unparsed_name(ctx,pname);
3752 pkrb5_free_principal(ctx,principal);
3754 pkrb5_cc_close(ctx,cc);
3756 pkrb5_free_context(ctx);
3758 return serverReachable;
3762 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
3764 krb5_context ctx = NULL;
3765 krb5_error_code code;
3766 krb5_ccache mslsa_ccache=NULL;
3767 krb5_principal princ = NULL;
3768 char * pname = NULL;
3771 if (!KFW_is_available())
3774 if (code = pkrb5_init_context(&ctx))
3777 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3780 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3783 if (code = pkrb5_unparse_name(ctx, princ, &pname))
3786 if ( strlen(pname) < *dwSize ) {
3787 StringCbCopyN(szUser, *dwSize, pname, (*dwSize) - 1);
3790 *dwSize = (DWORD)strlen(pname);
3794 pkrb5_free_unparsed_name(ctx, pname);
3797 pkrb5_free_principal(ctx, princ);
3800 pkrb5_cc_close(ctx, mslsa_ccache);
3803 pkrb5_free_context(ctx);
3808 KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
3810 // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
3811 PSID pSystemSID = NULL;
3812 DWORD SystemSIDlength = 0, UserSIDlength = 0;
3813 PACL ccacheACL = NULL;
3814 DWORD ccacheACLlength = 0;
3815 PTOKEN_USER pTokenUser = NULL;
3824 /* Get System SID */
3825 if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
3831 SystemSIDlength = GetLengthSid(pSystemSID);
3832 ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
3833 + SystemSIDlength - sizeof(DWORD);
3836 if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
3838 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
3839 pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
3841 GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
3846 UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
3848 ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
3853 ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
3858 InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
3859 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3860 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3863 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3864 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3865 pTokenUser->User.Sid);
3866 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3867 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3872 gle = GetLastError();
3873 if (gle != ERROR_NO_TOKEN)
3876 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3877 OWNER_SECURITY_INFORMATION,
3878 pTokenUser->User.Sid,
3882 gle = GetLastError();
3883 if (gle != ERROR_NO_TOKEN)
3887 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3888 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3893 gle = GetLastError();
3894 if (gle != ERROR_NO_TOKEN)
3901 LocalFree(pSystemSID);
3903 LocalFree(pTokenUser);
3905 LocalFree(ccacheACL);
3910 KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
3913 DWORD dwSize = size-1; /* leave room for nul */
3916 if (!hUserToken || !newfilename || size <= 0)
3919 *newfilename = '\0';
3921 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
3922 if ( !dwLen || dwLen > dwSize )
3923 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
3924 if ( !dwLen || dwLen > dwSize )
3927 newfilename[dwSize] = '\0';
3932 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
3934 char filename[MAX_PATH] = "";
3936 char cachename[MAX_PATH + 8] = "FILE:";
3937 krb5_context ctx = NULL;
3938 krb5_error_code code;
3939 krb5_principal princ = NULL;
3940 krb5_ccache cc = NULL;
3941 krb5_ccache ncc = NULL;
3943 if (!pkrb5_init_context || !user || !szLogonId)
3946 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
3947 if ( count > sizeof(filename) || count == 0 ) {
3948 GetWindowsDirectory(filename, sizeof(filename));
3951 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
3954 StringCbCat( filename, sizeof(filename), "\\");
3955 StringCbCat( filename, sizeof(filename), szLogonId);
3957 StringCbCat( cachename, sizeof(cachename), filename);
3959 DeleteFile(filename);
3961 code = pkrb5_init_context(&ctx);
3962 if (code) goto cleanup;
3964 code = pkrb5_parse_name(ctx, user, &princ);
3965 if (code) goto cleanup;
3967 code = KFW_get_ccache(ctx, princ, &cc);
3968 if (code) goto cleanup;
3970 code = pkrb5_cc_resolve(ctx, cachename, &ncc);
3971 if (code) goto cleanup;
3973 code = pkrb5_cc_initialize(ctx, ncc, princ);
3974 if (code) goto cleanup;
3976 code = KFW_AFS_set_file_cache_dacl(filename, NULL);
3977 if (code) goto cleanup;
3979 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3983 pkrb5_cc_close(ctx, cc);
3987 pkrb5_cc_close(ctx, ncc);
3991 pkrb5_free_principal(ctx, princ);
3996 pkrb5_free_context(ctx);
4000 KFW_AFS_copy_file_cache_to_default_cache(char * filename)
4002 char cachename[MAX_PATH + 8] = "FILE:";
4003 krb5_context ctx = NULL;
4004 krb5_error_code code;
4005 krb5_principal princ = NULL;
4006 krb5_ccache cc = NULL;
4007 krb5_ccache ncc = NULL;
4010 if (!pkrb5_init_context || !filename)
4013 if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
4016 code = pkrb5_init_context(&ctx);
4019 StringCbCat( cachename, sizeof(cachename), filename);
4021 code = pkrb5_cc_resolve(ctx, cachename, &cc);
4022 if (code) goto cleanup;
4024 code = pkrb5_cc_get_principal(ctx, cc, &princ);
4026 code = pkrb5_cc_default(ctx, &ncc);
4028 code = pkrb5_cc_initialize(ctx, ncc, princ);
4031 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
4034 pkrb5_cc_close(ctx, ncc);
4038 retval=0; /* success */
4042 pkrb5_cc_close(ctx, cc);
4046 DeleteFile(filename);
4049 pkrb5_free_principal(ctx, princ);
4054 pkrb5_free_context(ctx);
4059 /* We are including this
4061 /* Ticket lifetime. This defines the table used to lookup lifetime for the
4062 fixed part of rande of the one byte lifetime field. Values less than 0x80
4063 are intrpreted as the number of 5 minute intervals. Values from 0x80 to
4064 0xBF should be looked up in this table. The value of 0x80 is the same using
4065 both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days.
4066 The intervening values of have a fixed ratio of roughly 1.06914. The value
4067 oxFF is defined to mean a ticket has no expiration time. This should be
4068 used advisedly since individual servers may impose defacto upperbounds on
4069 ticket lifetimes. */
4071 #define TKTLIFENUMFIXED 64
4072 #define TKTLIFEMINFIXED 0x80
4073 #define TKTLIFEMAXFIXED 0xBF
4074 #define TKTLIFENOEXPIRE 0xFF
4075 #define MAXTKTLIFETIME (30*24*3600) /* 30 days */
4077 static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
4078 38400, /* 10.67 hours, 0.44 days */
4079 41055, /* 11.40 hours, 0.48 days */
4080 43894, /* 12.19 hours, 0.51 days */
4081 46929, /* 13.04 hours, 0.54 days */
4082 50174, /* 13.94 hours, 0.58 days */
4083 53643, /* 14.90 hours, 0.62 days */
4084 57352, /* 15.93 hours, 0.66 days */
4085 61318, /* 17.03 hours, 0.71 days */
4086 65558, /* 18.21 hours, 0.76 days */
4087 70091, /* 19.47 hours, 0.81 days */
4088 74937, /* 20.82 hours, 0.87 days */
4089 80119, /* 22.26 hours, 0.93 days */
4090 85658, /* 23.79 hours, 0.99 days */
4091 91581, /* 25.44 hours, 1.06 days */
4092 97914, /* 27.20 hours, 1.13 days */
4093 104684, /* 29.08 hours, 1.21 days */
4094 111922, /* 31.09 hours, 1.30 days */
4095 119661, /* 33.24 hours, 1.38 days */
4096 127935, /* 35.54 hours, 1.48 days */
4097 136781, /* 37.99 hours, 1.58 days */
4098 146239, /* 40.62 hours, 1.69 days */
4099 156350, /* 43.43 hours, 1.81 days */
4100 167161, /* 46.43 hours, 1.93 days */
4101 178720, /* 49.64 hours, 2.07 days */
4102 191077, /* 53.08 hours, 2.21 days */
4103 204289, /* 56.75 hours, 2.36 days */
4104 218415, /* 60.67 hours, 2.53 days */
4105 233517, /* 64.87 hours, 2.70 days */
4106 249664, /* 69.35 hours, 2.89 days */
4107 266926, /* 74.15 hours, 3.09 days */
4108 285383, /* 79.27 hours, 3.30 days */
4109 305116, /* 84.75 hours, 3.53 days */
4110 326213, /* 90.61 hours, 3.78 days */
4111 348769, /* 96.88 hours, 4.04 days */
4112 372885, /* 103.58 hours, 4.32 days */
4113 398668, /* 110.74 hours, 4.61 days */
4114 426234, /* 118.40 hours, 4.93 days */
4115 455705, /* 126.58 hours, 5.27 days */
4116 487215, /* 135.34 hours, 5.64 days */
4117 520904, /* 144.70 hours, 6.03 days */
4118 556921, /* 154.70 hours, 6.45 days */
4119 595430, /* 165.40 hours, 6.89 days */
4120 636601, /* 176.83 hours, 7.37 days */
4121 680618, /* 189.06 hours, 7.88 days */
4122 727680, /* 202.13 hours, 8.42 days */
4123 777995, /* 216.11 hours, 9.00 days */
4124 831789, /* 231.05 hours, 9.63 days */
4125 889303, /* 247.03 hours, 10.29 days */
4126 950794, /* 264.11 hours, 11.00 days */
4127 1016537, /* 282.37 hours, 11.77 days */
4128 1086825, /* 301.90 hours, 12.58 days */
4129 1161973, /* 322.77 hours, 13.45 days */
4130 1242318, /* 345.09 hours, 14.38 days */
4131 1328218, /* 368.95 hours, 15.37 days */
4132 1420057, /* 394.46 hours, 16.44 days */
4133 1518247, /* 421.74 hours, 17.57 days */
4134 1623226, /* 450.90 hours, 18.79 days */
4135 1735464, /* 482.07 hours, 20.09 days */
4136 1855462, /* 515.41 hours, 21.48 days */
4137 1983758, /* 551.04 hours, 22.96 days */
4138 2120925, /* 589.15 hours, 24.55 days */
4139 2267576, /* 629.88 hours, 26.25 days */
4140 2424367, /* 673.44 hours, 28.06 days */
4142 }; /* 720.00 hours, 30.00 days */
4144 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
4145 * returns the corresponding end time. There are four simple cases to be
4146 * handled. The first is a life of 0xff, meaning no expiration, and results in
4147 * an end time of 0xffffffff. The second is when life is less than the values
4148 * covered by the table. In this case, the end time is the start time plus the
4149 * number of 5 minute intervals specified by life. The third case returns
4150 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
4151 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
4152 * table to extract the lifetime in seconds, which is added to start to produce
4156 life_to_time(afs_uint32 start, unsigned char life)
4160 if (life == TKTLIFENOEXPIRE)
4162 if (life < TKTLIFEMINFIXED)
4163 return start + life * 5 * 60;
4164 if (life > TKTLIFEMAXFIXED)
4165 return start + MAXTKTLIFETIME;
4166 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
4167 return start + realLife;
4170 /* time_to_life - takes start and end times for the ticket and returns a
4171 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
4172 * lifetimes above 127*5minutes. First, the special case of (end ==
4173 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
4174 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
4175 * less than the first table entry are handled by rounding the requested
4176 * lifetime *up* to the next 5 minute interval. The final step is to search
4177 * the table for the smallest entry *greater than or equal* to the requested
4178 * entry. The actual code is prepared to handle the case where the table is
4179 * unordered but that it an unnecessary frill. */
4181 static unsigned char
4182 time_to_life(afs_uint32 start, afs_uint32 end)
4184 int lifetime = end - start;
4188 if (end == NEVERDATE)
4189 return TKTLIFENOEXPIRE;
4190 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
4192 if (lifetime < tkt_lifetimes[0])
4193 return (lifetime + 5 * 60 - 1) / (5 * 60);
4195 best = MAXKTCTICKETLIFETIME;
4196 for (i = 0; i < TKTLIFENUMFIXED; i++)
4197 if (tkt_lifetimes[i] >= lifetime) {
4198 int diff = tkt_lifetimes[i] - lifetime;
4206 return best_i + TKTLIFEMINFIXED;