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 <WINNT\afsreg.h>
76 #include "afskfw-int.h"
84 * TIMING _____________________________________________________________________
88 #define cminREMIND_TEST 1 // test every minute for expired creds
89 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
90 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
91 #define cminMINLIFE 30 // minimum life of Kerberos creds
93 #define c100ns1SECOND (LONGLONG)10000000
94 #define cmsec1SECOND 1000
95 #define cmsec1MINUTE 60000
96 #define csec1MINUTE 60
98 /* Function Pointer Declarations for Delayed Loading */
100 DECL_FUNC_PTR(cc_initialize);
101 DECL_FUNC_PTR(cc_shutdown);
102 DECL_FUNC_PTR(cc_get_NC_info);
103 DECL_FUNC_PTR(cc_free_NC_info);
107 DECL_FUNC_PTR(Leash_get_default_lifetime);
108 DECL_FUNC_PTR(Leash_get_default_forwardable);
109 DECL_FUNC_PTR(Leash_get_default_renew_till);
110 DECL_FUNC_PTR(Leash_get_default_noaddresses);
111 DECL_FUNC_PTR(Leash_get_default_proxiable);
112 DECL_FUNC_PTR(Leash_get_default_publicip);
113 DECL_FUNC_PTR(Leash_get_default_use_krb4);
114 DECL_FUNC_PTR(Leash_get_default_life_min);
115 DECL_FUNC_PTR(Leash_get_default_life_max);
116 DECL_FUNC_PTR(Leash_get_default_renew_min);
117 DECL_FUNC_PTR(Leash_get_default_renew_max);
118 DECL_FUNC_PTR(Leash_get_default_renewable);
119 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
123 DECL_FUNC_PTR(krb5_change_password);
124 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
125 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
126 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
127 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
128 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
129 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
130 DECL_FUNC_PTR(krb5_get_init_creds_password);
131 DECL_FUNC_PTR(krb5_build_principal_ext);
132 DECL_FUNC_PTR(krb5_cc_get_name);
133 DECL_FUNC_PTR(krb5_cc_resolve);
134 DECL_FUNC_PTR(krb5_cc_default);
135 DECL_FUNC_PTR(krb5_cc_default_name);
136 DECL_FUNC_PTR(krb5_cc_set_default_name);
137 DECL_FUNC_PTR(krb5_cc_initialize);
138 DECL_FUNC_PTR(krb5_cc_destroy);
139 DECL_FUNC_PTR(krb5_cc_close);
140 DECL_FUNC_PTR(krb5_cc_store_cred);
141 DECL_FUNC_PTR(krb5_cc_copy_creds);
142 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
143 DECL_FUNC_PTR(krb5_cc_get_principal);
144 DECL_FUNC_PTR(krb5_cc_start_seq_get);
145 DECL_FUNC_PTR(krb5_cc_next_cred);
146 DECL_FUNC_PTR(krb5_cc_end_seq_get);
147 DECL_FUNC_PTR(krb5_cc_remove_cred);
148 DECL_FUNC_PTR(krb5_cc_set_flags);
149 DECL_FUNC_PTR(krb5_cc_get_type);
150 DECL_FUNC_PTR(krb5_free_context);
151 DECL_FUNC_PTR(krb5_free_cred_contents);
152 DECL_FUNC_PTR(krb5_free_principal);
153 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
154 DECL_FUNC_PTR(krb5_init_context);
155 DECL_FUNC_PTR(krb5_parse_name);
156 DECL_FUNC_PTR(krb5_timeofday);
157 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
158 DECL_FUNC_PTR(krb5_unparse_name);
159 DECL_FUNC_PTR(krb5_get_credentials);
160 DECL_FUNC_PTR(krb5_mk_req);
161 DECL_FUNC_PTR(krb5_sname_to_principal);
162 DECL_FUNC_PTR(krb5_get_credentials_renew);
163 DECL_FUNC_PTR(krb5_free_data);
164 DECL_FUNC_PTR(krb5_free_data_contents);
165 DECL_FUNC_PTR(krb5_free_unparsed_name);
166 DECL_FUNC_PTR(krb5_os_localaddr);
167 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
168 DECL_FUNC_PTR(krb5_copy_data);
169 DECL_FUNC_PTR(krb5_free_creds);
170 DECL_FUNC_PTR(krb5_build_principal);
171 DECL_FUNC_PTR(krb5_get_renewed_creds);
172 DECL_FUNC_PTR(krb5_get_default_config_files);
173 DECL_FUNC_PTR(krb5_free_config_files);
174 DECL_FUNC_PTR(krb5_get_default_realm);
175 DECL_FUNC_PTR(krb5_free_default_realm);
176 DECL_FUNC_PTR(krb5_free_ticket);
177 DECL_FUNC_PTR(krb5_decode_ticket);
178 DECL_FUNC_PTR(krb5_get_host_realm);
179 DECL_FUNC_PTR(krb5_free_host_realm);
180 DECL_FUNC_PTR(krb5_free_addresses);
181 DECL_FUNC_PTR(krb5_c_random_make_octets);
183 // Krb5 KFW 3.2 functions
184 DECL_FUNC_PTR(krb5_get_error_message);
185 DECL_FUNC_PTR(krb5_free_error_message);
189 DECL_FUNC_PTR(krb524_init_ets);
190 DECL_FUNC_PTR(krb524_convert_creds_kdc);
195 DECL_FUNC_PTR(krb_get_cred);
196 DECL_FUNC_PTR(tkt_string);
197 DECL_FUNC_PTR(krb_get_tf_realm);
198 DECL_FUNC_PTR(krb_mk_req);
202 DECL_FUNC_PTR(com_err);
203 DECL_FUNC_PTR(error_message);
206 DECL_FUNC_PTR(profile_init);
207 DECL_FUNC_PTR(profile_release);
208 DECL_FUNC_PTR(profile_get_subsection_names);
209 DECL_FUNC_PTR(profile_free_list);
210 DECL_FUNC_PTR(profile_get_string);
211 DECL_FUNC_PTR(profile_release_string);
214 DECL_FUNC_PTR(OpenSCManagerA);
215 DECL_FUNC_PTR(OpenServiceA);
216 DECL_FUNC_PTR(QueryServiceStatus);
217 DECL_FUNC_PTR(CloseServiceHandle);
219 DECL_FUNC_PTR(LsaNtStatusToWinError);
220 #endif /* USE_MS2MIT */
224 DECL_FUNC_PTR(LsaConnectUntrusted);
225 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
226 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
227 DECL_FUNC_PTR(LsaFreeReturnBuffer);
228 DECL_FUNC_PTR(LsaGetLogonSessionData);
229 #endif /* USE_MS2MIT */
232 FUNC_INFO ccapi_fi[] = {
233 MAKE_FUNC_INFO(cc_initialize),
234 MAKE_FUNC_INFO(cc_shutdown),
235 MAKE_FUNC_INFO(cc_get_NC_info),
236 MAKE_FUNC_INFO(cc_free_NC_info),
241 FUNC_INFO leash_fi[] = {
242 MAKE_FUNC_INFO(Leash_get_default_lifetime),
243 MAKE_FUNC_INFO(Leash_get_default_renew_till),
244 MAKE_FUNC_INFO(Leash_get_default_forwardable),
245 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
246 MAKE_FUNC_INFO(Leash_get_default_proxiable),
247 MAKE_FUNC_INFO(Leash_get_default_publicip),
248 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
249 MAKE_FUNC_INFO(Leash_get_default_life_min),
250 MAKE_FUNC_INFO(Leash_get_default_life_max),
251 MAKE_FUNC_INFO(Leash_get_default_renew_min),
252 MAKE_FUNC_INFO(Leash_get_default_renew_max),
253 MAKE_FUNC_INFO(Leash_get_default_renewable),
257 FUNC_INFO leash_opt_fi[] = {
258 MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
263 FUNC_INFO k5_fi[] = {
264 MAKE_FUNC_INFO(krb5_change_password),
265 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
266 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
267 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
268 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
269 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
270 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
271 MAKE_FUNC_INFO(krb5_get_init_creds_password),
272 MAKE_FUNC_INFO(krb5_build_principal_ext),
273 MAKE_FUNC_INFO(krb5_cc_get_name),
274 MAKE_FUNC_INFO(krb5_cc_resolve),
275 MAKE_FUNC_INFO(krb5_cc_default),
276 MAKE_FUNC_INFO(krb5_cc_default_name),
277 MAKE_FUNC_INFO(krb5_cc_set_default_name),
278 MAKE_FUNC_INFO(krb5_cc_initialize),
279 MAKE_FUNC_INFO(krb5_cc_destroy),
280 MAKE_FUNC_INFO(krb5_cc_close),
281 MAKE_FUNC_INFO(krb5_cc_copy_creds),
282 MAKE_FUNC_INFO(krb5_cc_store_cred),
283 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
284 MAKE_FUNC_INFO(krb5_cc_get_principal),
285 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
286 MAKE_FUNC_INFO(krb5_cc_next_cred),
287 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
288 MAKE_FUNC_INFO(krb5_cc_remove_cred),
289 MAKE_FUNC_INFO(krb5_cc_set_flags),
290 MAKE_FUNC_INFO(krb5_cc_get_type),
291 MAKE_FUNC_INFO(krb5_free_context),
292 MAKE_FUNC_INFO(krb5_free_cred_contents),
293 MAKE_FUNC_INFO(krb5_free_principal),
294 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
295 MAKE_FUNC_INFO(krb5_init_context),
296 MAKE_FUNC_INFO(krb5_parse_name),
297 MAKE_FUNC_INFO(krb5_timeofday),
298 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
299 MAKE_FUNC_INFO(krb5_unparse_name),
300 MAKE_FUNC_INFO(krb5_get_credentials),
301 MAKE_FUNC_INFO(krb5_mk_req),
302 MAKE_FUNC_INFO(krb5_sname_to_principal),
303 MAKE_FUNC_INFO(krb5_get_credentials_renew),
304 MAKE_FUNC_INFO(krb5_free_data),
305 MAKE_FUNC_INFO(krb5_free_data_contents),
306 MAKE_FUNC_INFO(krb5_free_unparsed_name),
307 MAKE_FUNC_INFO(krb5_os_localaddr),
308 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
309 MAKE_FUNC_INFO(krb5_copy_data),
310 MAKE_FUNC_INFO(krb5_free_creds),
311 MAKE_FUNC_INFO(krb5_build_principal),
312 MAKE_FUNC_INFO(krb5_get_renewed_creds),
313 MAKE_FUNC_INFO(krb5_free_addresses),
314 MAKE_FUNC_INFO(krb5_get_default_config_files),
315 MAKE_FUNC_INFO(krb5_free_config_files),
316 MAKE_FUNC_INFO(krb5_get_default_realm),
317 MAKE_FUNC_INFO(krb5_free_default_realm),
318 MAKE_FUNC_INFO(krb5_free_ticket),
319 MAKE_FUNC_INFO(krb5_decode_ticket),
320 MAKE_FUNC_INFO(krb5_get_host_realm),
321 MAKE_FUNC_INFO(krb5_free_host_realm),
322 MAKE_FUNC_INFO(krb5_free_addresses),
323 MAKE_FUNC_INFO(krb5_c_random_make_octets),
327 FUNC_INFO k5_kfw_32_fi[] = {
328 MAKE_FUNC_INFO(krb5_get_error_message),
329 MAKE_FUNC_INFO(krb5_free_error_message),
334 FUNC_INFO k4_fi[] = {
335 MAKE_FUNC_INFO(krb_get_cred),
336 MAKE_FUNC_INFO(krb_get_tf_realm),
337 MAKE_FUNC_INFO(krb_mk_req),
338 MAKE_FUNC_INFO(tkt_string),
344 FUNC_INFO k524_fi[] = {
345 MAKE_FUNC_INFO(krb524_init_ets),
346 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
351 FUNC_INFO profile_fi[] = {
352 MAKE_FUNC_INFO(profile_init),
353 MAKE_FUNC_INFO(profile_release),
354 MAKE_FUNC_INFO(profile_get_subsection_names),
355 MAKE_FUNC_INFO(profile_free_list),
356 MAKE_FUNC_INFO(profile_get_string),
357 MAKE_FUNC_INFO(profile_release_string),
361 FUNC_INFO ce_fi[] = {
362 MAKE_FUNC_INFO(com_err),
363 MAKE_FUNC_INFO(error_message),
367 FUNC_INFO service_fi[] = {
368 MAKE_FUNC_INFO(OpenSCManagerA),
369 MAKE_FUNC_INFO(OpenServiceA),
370 MAKE_FUNC_INFO(QueryServiceStatus),
371 MAKE_FUNC_INFO(CloseServiceHandle),
373 MAKE_FUNC_INFO(LsaNtStatusToWinError),
374 #endif /* USE_MS2MIT */
379 FUNC_INFO lsa_fi[] = {
380 MAKE_FUNC_INFO(LsaConnectUntrusted),
381 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
382 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
383 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
384 MAKE_FUNC_INFO(LsaGetLogonSessionData),
387 #endif /* USE_MS2MIT */
389 /* Static Prototypes */
390 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
391 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *, unsigned short);
392 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
393 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
394 void *data, const char *name, const char *banner, int num_prompts,
395 krb5_prompt prompts[]);
398 /* Static Declarations */
399 static int inited = 0;
400 static int mid_cnt = 0;
401 static struct textField * mid_tb = NULL;
402 static HINSTANCE hKrb5 = 0;
403 static HINSTANCE hKrb5_kfw_32 = 0;
405 static HINSTANCE hKrb4 = 0;
406 #endif /* USE_KRB4 */
408 static HINSTANCE hKrb524 = 0;
411 static HINSTANCE hSecur32 = 0;
412 #endif /* USE_MS2MIT */
413 static HINSTANCE hAdvApi32 = 0;
414 static HINSTANCE hComErr = 0;
415 static HINSTANCE hService = 0;
416 static HINSTANCE hProfile = 0;
418 static HINSTANCE hLeash = 0;
419 static HINSTANCE hLeashOpt = 0;
421 static HINSTANCE hCCAPI = 0;
422 static struct principal_ccache_data * princ_cc_data = NULL;
423 static struct cell_principal_map * cell_princ_map = NULL;
426 #define DEFAULT_LIFETIME pLeash_get_default_lifetime()
428 #define DEFAULT_LIFETIME (24 * 60)
434 static int inited = 0;
437 char mutexName[MAX_PATH];
438 HANDLE hMutex = NULL;
440 StringCbPrintf( mutexName, sizeof(mutexName), "AFS KFW Init pid=%d", getpid());
442 hMutex = CreateMutex( NULL, TRUE, mutexName );
443 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
444 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
450 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
451 LoadFuncs(KRB5_DLL, k5_kfw_32_fi, &hKrb5_kfw_32, 0, 1, 0, 0);
452 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
453 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
455 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
456 #endif /* USE_KRB4 */
457 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
459 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
460 #endif /* USE_MS2MIT */
462 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
465 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
466 LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
468 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
470 if ( KFW_is_available() ) {
471 char rootcell[CELL_MAXNAMELEN+1];
473 KFW_import_windows_lsa();
474 #endif /* USE_MS2MIT */
475 KFW_import_ccache_data();
476 KFW_AFS_renew_expiring_tokens();
478 /* WIN32 NOTE: no way to get max chars */
479 if (!cm_GetRootCellName(rootcell))
480 KFW_AFS_renew_token_for_cell(rootcell);
483 ReleaseMutex(hMutex);
493 FreeLibrary(hLeashOpt);
499 FreeLibrary(hKrb524);
505 FreeLibrary(hSecur32);
506 #endif /* USE_MS2MIT */
508 FreeLibrary(hService);
510 FreeLibrary(hComErr);
512 FreeLibrary(hProfile);
516 #endif /* USE_KRB4 */
520 FreeLibrary(hKrb5_kfw_32);
523 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
526 static int init = TRUE;
527 static int bIsWow64 = FALSE;
531 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
533 hModule = GetModuleHandle(TEXT("kernel32"));
535 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
537 if (NULL != fnIsWow64Process)
539 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
541 // on error, assume FALSE.
542 // in other words, do nothing.
545 FreeLibrary(hModule);
553 KFW_accept_dotted_usernames(void)
559 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
560 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
561 if (code == ERROR_SUCCESS) {
563 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
564 (BYTE *) &value, &len);
565 RegCloseKey(parmKey);
567 if (code != ERROR_SUCCESS) {
568 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
569 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
570 if (code == ERROR_SUCCESS) {
572 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
573 (BYTE *) &value, &len);
574 RegCloseKey (parmKey);
588 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
589 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
590 if (code == ERROR_SUCCESS) {
591 len = sizeof(use524);
592 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
593 (BYTE *) &use524, &len);
594 RegCloseKey(parmKey);
596 if (code != ERROR_SUCCESS) {
597 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
598 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
599 if (code == ERROR_SUCCESS) {
600 len = sizeof(use524);
601 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
602 (BYTE *) &use524, &len);
603 RegCloseKey (parmKey);
610 KFW_is_available(void)
616 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
617 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
618 if (code == ERROR_SUCCESS) {
619 len = sizeof(enableKFW);
620 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
621 (BYTE *) &enableKFW, &len);
622 RegCloseKey (parmKey);
625 if (code != ERROR_SUCCESS) {
626 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
627 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
628 if (code == ERROR_SUCCESS) {
629 len = sizeof(enableKFW);
630 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
631 (BYTE *) &enableKFW, &len);
632 RegCloseKey (parmKey);
640 if ( hKrb5 && hComErr && hService &&
643 #endif /* USE_MS2MIT */
656 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
657 int FreeContextFlag, krb5_context * ctx,
662 int krb5Error = ((int)(rc & 255));
674 if (pkrb5_get_error_message)
675 errText = pkrb5_get_error_message(ctx, rc);
677 errText = perror_message(rc);
678 StringCbPrintf(message, sizeof(message),
679 "%s\n(Kerberos error %ld)\n\n%s failed",
683 if (pkrb5_free_error_message)
684 pkrb5_free_error_message(ctx, (char *)errText);
686 if ( IsDebuggerPresent() )
687 OutputDebugString(message);
689 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
692 if (FreeContextFlag == 1)
694 if (ctx && *ctx != NULL)
696 if (cache && *cache != NULL) {
697 pkrb5_cc_close(*ctx, *cache);
701 pkrb5_free_context(*ctx);
710 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
712 struct principal_ccache_data * next = princ_cc_data;
713 krb5_principal principal = 0;
715 const char * ccname = NULL;
716 const char * cctype = NULL;
717 char * ccfullname = NULL;
718 krb5_error_code code = 0;
719 krb5_error_code cc_code = 0;
725 if (ctx == 0 || cc == 0)
728 code = pkrb5_cc_get_principal(ctx, cc, &principal);
731 code = pkrb5_unparse_name(ctx, principal, &pname);
732 if ( code ) goto cleanup;
734 ccname = pkrb5_cc_get_name(ctx, cc);
735 if (!ccname) goto cleanup;
737 cctype = pkrb5_cc_get_type(ctx, cc);
738 if (!cctype) goto cleanup;
740 ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
741 if (!ccfullname) goto cleanup;
743 StringCbPrintf(ccfullname, sizeof(ccfullname), "%s:%s", cctype, ccname);
745 // Search the existing list to see if we have a match
747 for ( ; next ; next = next->next ) {
748 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
753 // If not, match add a new node to the beginning of the list and assign init it
755 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
756 next->next = princ_cc_data;
757 princ_cc_data = next;
758 next->principal = _strdup(pname);
759 next->ccache_name = ccfullname;
761 next->from_lsa = lsa;
763 next->expiration_time = 0;
767 flags = 0; // turn off OPENCLOSE mode
768 code = pkrb5_cc_set_flags(ctx, cc, flags);
769 if ( code ) goto cleanup;
771 code = pkrb5_timeofday(ctx, &now);
773 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
774 if (cc_code) goto cleanup;
776 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
777 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
779 // we found the ticket we are looking for
780 // check validity of timestamp
781 // We add a 5 minutes fudge factor to compensate for potential
782 // clock skew errors between the KDC and client OS
784 valid = ((creds.times.starttime > 0) &&
785 now >= (creds.times.starttime - 300) &&
786 now < (creds.times.endtime + 300) &&
787 !(creds.ticket_flags & TKT_FLG_INVALID));
789 if ( next->from_lsa) {
791 next->expiration_time = creds.times.endtime;
793 } else if ( valid ) {
795 next->expiration_time = creds.times.endtime;
796 next->renew = (creds.times.renew_till > creds.times.endtime) &&
797 (creds.ticket_flags & TKT_FLG_RENEWABLE);
800 next->expiration_time = 0;
804 pkrb5_free_cred_contents(ctx, &creds);
805 cc_code = KRB5_CC_END;
808 pkrb5_free_cred_contents(ctx, &creds);
811 if (cc_code == KRB5_CC_END) {
812 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
813 if (code) goto cleanup;
817 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
818 code = pkrb5_cc_set_flags(ctx, cc, flags);
823 pkrb5_free_unparsed_name(ctx,pname);
825 pkrb5_free_principal(ctx,principal);
829 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
831 struct principal_ccache_data * next = princ_cc_data;
832 char * response = NULL;
834 if ( !principal || !ccache )
838 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
840 // we always want to prefer the MS Kerberos LSA cache or
841 // the cache afscreds created specifically for the principal
842 // if the current entry is either one, drop the previous find
843 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
846 response = _strdup(next->ccache_name);
847 // MS Kerberos LSA is our best option so use it and quit
848 if ( next->from_lsa )
862 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
864 struct principal_ccache_data ** next = &princ_cc_data;
866 if ( !pname && !ccname )
870 if ( !strcmp((*next)->principal,pname) ||
871 !strcmp((*next)->ccache_name,ccname) ) {
873 free((*next)->principal);
874 free((*next)->ccache_name);
876 (*next) = (*next)->next;
883 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
885 struct cell_principal_map * next = cell_princ_map;
887 // Search the existing list to see if we have a match
889 for ( ; next ; next = next->next ) {
890 if ( !strcmp(next->cell, cell) ) {
891 if ( !strcmp(next->principal,pname) ) {
892 next->active = active;
895 // OpenAFS currently has a restriction of one active token per cell
896 // Therefore, whenever we update the table with a new active cell we
897 // must mark all of the other principal to cell entries as inactive.
905 // If not, match add a new node to the beginning of the list and assign init it
907 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
908 next->next = cell_princ_map;
909 cell_princ_map = next;
910 next->principal = _strdup(pname);
911 next->cell = _strdup(cell);
912 next->active = active;
917 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
919 struct cell_principal_map ** next = &cell_princ_map;
921 if ( !pname && !cell )
925 if ( !strcmp((*next)->principal,pname) ||
926 !strcmp((*next)->cell,cell) ) {
928 free((*next)->principal);
931 (*next) = (*next)->next;
937 // Returns (if possible) a principal which has been known in
938 // the past to have been used to obtain tokens for the specified
940 // TODO: Attempt to return one which has not yet expired by checking
941 // the principal/ccache data
943 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
945 struct cell_principal_map * next_map = cell_princ_map;
946 const char * princ = NULL;
953 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
956 next_map = next_map->next;
959 if ( !principals || !count )
962 *principals = (char **) malloc(sizeof(char *) * count);
963 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
965 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
966 (*principals)[i++] = _strdup(next_map->principal);
973 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
976 struct cell_principal_map * next_map = cell_princ_map;
977 const char * princ = NULL;
983 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
986 next_map = next_map->next;
992 *cells = (char **) malloc(sizeof(char *) * count);
993 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
995 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
996 (*cells)[i++] = _strdup(next_map->cell);
1002 /* Given a principal return an existing ccache or create one and return */
1004 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
1006 krb5_context ctx = NULL;
1007 char * pname = NULL;
1008 char * ccname = NULL;
1009 krb5_error_code code;
1011 if (!pkrb5_init_context)
1012 return KRB5_CONFIG_CANTOPEN;
1017 code = pkrb5_init_context(&ctx);
1018 if (code) goto cleanup;
1022 code = pkrb5_unparse_name(ctx, principal, &pname);
1023 if (code) goto cleanup;
1025 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
1026 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
1027 size_t len = strlen(pname) + 5;
1028 ccname = (char *)malloc(len);
1029 StringCbPrintf(ccname, len, "API:%s", pname);
1031 code = pkrb5_cc_resolve(ctx, ccname, cc);
1033 code = pkrb5_cc_default(ctx, cc);
1034 if (code) goto cleanup;
1041 pkrb5_free_unparsed_name(ctx,pname);
1042 if (ctx && (ctx != alt_ctx))
1043 pkrb5_free_context(ctx);
1048 // Import Microsoft Credentials into a new MIT ccache
1050 KFW_import_windows_lsa(void)
1052 krb5_context ctx = NULL;
1053 krb5_ccache cc = NULL;
1054 krb5_principal princ = NULL;
1055 char * pname = NULL;
1056 krb5_data * princ_realm;
1057 krb5_error_code code;
1058 char cell[128]="", realm[128]="", *def_realm = 0;
1060 DWORD dwMsLsaImport;
1062 if (!pkrb5_init_context)
1065 code = pkrb5_init_context(&ctx);
1066 if (code) goto cleanup;
1068 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
1069 if (code) goto cleanup;
1071 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
1073 code = pkrb5_cc_get_principal(ctx, cc, &princ);
1074 if ( code ) goto cleanup;
1077 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
1081 switch ( dwMsLsaImport ) {
1082 case 0: /* do not import */
1084 case 1: /* always import */
1086 case 2: { /* matching realm */
1087 char ms_realm[128] = "", *r;
1090 for ( r=ms_realm, j=0; j<krb5_princ_realm(ctx, princ)->length; r++, j++ ) {
1091 *r = krb5_princ_realm(ctx, princ)->data[j];
1095 if (code = pkrb5_get_default_realm(ctx, &def_realm))
1098 if (strcmp(def_realm, ms_realm))
1106 code = pkrb5_unparse_name(ctx,princ,&pname);
1107 if ( code ) goto cleanup;
1109 princ_realm = krb5_princ_realm(ctx, princ);
1110 for ( i=0; i<princ_realm->length; i++ ) {
1111 realm[i] = princ_realm->data[i];
1112 cell[i] = tolower(princ_realm->data[i]);
1117 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, DEFAULT_LIFETIME, NULL);
1118 if ( IsDebuggerPresent() ) {
1120 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1121 OutputDebugString(message);
1123 if ( code ) goto cleanup;
1125 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1129 pkrb5_free_unparsed_name(ctx,pname);
1131 pkrb5_free_principal(ctx,princ);
1133 pkrb5_free_default_realm(ctx, def_realm);
1135 pkrb5_cc_close(ctx,cc);
1137 pkrb5_free_context(ctx);
1139 #endif /* USE_MS2MIT */
1141 // If there are existing MIT credentials, copy them to a new
1142 // ccache named after the principal
1144 // Enumerate all existing MIT ccaches and construct entries
1145 // in the principal_ccache table
1147 // Enumerate all existing AFS Tokens and construct entries
1148 // in the cell_principal table
1150 KFW_import_ccache_data(void)
1152 krb5_context ctx = NULL;
1153 krb5_ccache cc = NULL;
1154 krb5_principal principal = NULL;
1156 krb5_error_code code;
1157 krb5_error_code cc_code;
1159 apiCB * cc_ctx = NULL;
1160 struct _infoNC ** pNCi = NULL;
1163 if ( !pcc_initialize )
1166 if ( IsDebuggerPresent() )
1167 OutputDebugString("KFW_import_ccache_data()\n");
1169 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1170 if (code) goto cleanup;
1172 code = pcc_get_NC_info(cc_ctx, &pNCi);
1173 if (code) goto cleanup;
1175 code = pkrb5_init_context(&ctx);
1176 if (code) goto cleanup;
1178 for ( i=0; pNCi[i]; i++ ) {
1179 if ( pNCi[i]->vers != CC_CRED_V5 )
1181 if ( IsDebuggerPresent() ) {
1182 OutputDebugString("Principal: ");
1183 OutputDebugString(pNCi[i]->principal);
1184 OutputDebugString(" in ccache ");
1185 OutputDebugString(pNCi[i]->name);
1186 OutputDebugString("\n");
1188 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1189 && strcmp(pNCi[i]->name,LSA_CCNAME)
1192 for ( j=0; pNCi[j]; j++ ) {
1193 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1199 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1200 if (code) goto loop_cleanup;
1203 krb5_ccache oldcc = 0;
1205 if ( IsDebuggerPresent() )
1206 OutputDebugString("copying ccache data to new ccache\n");
1208 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1209 if (code) goto loop_cleanup;
1210 code = pkrb5_cc_initialize(ctx, cc, principal);
1211 if (code) goto loop_cleanup;
1213 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1214 if (code) goto loop_cleanup;
1215 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1217 code = pkrb5_cc_close(ctx,cc);
1219 code = pkrb5_cc_close(ctx,oldcc);
1221 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1224 code = pkrb5_cc_close(ctx,oldcc);
1227 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1228 if (code) goto loop_cleanup;
1231 flags = 0; // turn off OPENCLOSE mode
1232 code = pkrb5_cc_set_flags(ctx, cc, flags);
1233 if ( code ) goto cleanup;
1235 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1237 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1238 if (cc_code) goto cleanup;
1240 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1241 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1242 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1243 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1244 if ( sname && cell && !strcmp("afs",sname->data) ) {
1245 struct ktc_principal aserver;
1246 struct ktc_principal aclient;
1247 struct ktc_token atoken;
1250 if ( IsDebuggerPresent() ) {
1251 OutputDebugString("Found AFS ticket: ");
1252 OutputDebugString(sname->data);
1254 OutputDebugString("/");
1255 OutputDebugString(cell->data);
1257 OutputDebugString("@");
1258 OutputDebugString(realm->data);
1259 OutputDebugString("\n");
1262 memset(&aserver, '\0', sizeof(aserver));
1263 StringCbCopyN( aserver.name, sizeof(aserver.name),
1264 sname->data, sizeof(aserver.name) - 1);
1265 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
1266 cell->data, sizeof(aserver.cell) - 1);
1268 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1270 // Found a token in AFS Client Server which matches
1271 char pname[128], *p, *q;
1272 for ( p=pname, q=aclient.name; *q; p++, q++)
1274 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1278 if ( IsDebuggerPresent() ) {
1279 OutputDebugString("Found AFS token: ");
1280 OutputDebugString(pname);
1281 OutputDebugString("\n");
1284 if ( strcmp(pname,pNCi[i]->principal) )
1286 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1288 // Attempt to import it
1289 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1291 if ( IsDebuggerPresent() ) {
1292 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1295 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data, DEFAULT_LIFETIME, NULL);
1296 if ( IsDebuggerPresent() ) {
1298 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1299 OutputDebugString(message);
1302 } else if ( IsDebuggerPresent() ) {
1303 OutputDebugString("Found ticket: ");
1304 OutputDebugString(sname->data);
1305 if ( cell && cell->data ) {
1306 OutputDebugString("/");
1307 OutputDebugString(cell->data);
1309 OutputDebugString("@");
1310 OutputDebugString(realm->data);
1311 OutputDebugString("\n");
1313 pkrb5_free_cred_contents(ctx, &creds);
1316 if (cc_code == KRB5_CC_END) {
1317 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1318 if (cc_code) goto loop_cleanup;
1322 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1323 code = pkrb5_cc_set_flags(ctx, cc, flags);
1325 pkrb5_cc_close(ctx,cc);
1329 pkrb5_free_principal(ctx,principal);
1336 pkrb5_free_context(ctx);
1338 pcc_free_NC_info(cc_ctx, &pNCi);
1340 pcc_shutdown(&cc_ctx);
1345 KFW_AFS_get_cred( char * username,
1352 static char reason[1024]="";
1353 krb5_context ctx = NULL;
1354 krb5_ccache cc = NULL;
1355 char * realm = NULL, * userrealm = NULL;
1356 krb5_principal principal = NULL;
1357 char * pname = NULL;
1358 krb5_error_code code;
1359 char local_cell[CELL_MAXNAMELEN+1];
1360 char **cells = NULL;
1362 struct afsconf_cell cellconfig;
1365 if (!pkrb5_init_context)
1366 return KRB5_CONFIG_CANTOPEN;
1368 if ( IsDebuggerPresent() ) {
1369 OutputDebugString("KFW_AFS_get_cred for token ");
1370 OutputDebugString(username);
1371 OutputDebugString(" in cell ");
1372 OutputDebugString(cell);
1373 OutputDebugString("\n");
1376 memset(&cellconfig, 0, sizeof(cellconfig));
1378 code = pkrb5_init_context(&ctx);
1379 if ( code ) goto cleanup;
1381 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1382 if ( code ) goto cleanup;
1384 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1386 userrealm = strchr(username,'@');
1388 pname = strdup(username);
1389 if (!KFW_accept_dotted_usernames()) {
1390 userrealm = strchr(pname, '@');
1393 /* handle kerberos iv notation */
1394 while ( dot = strchr(pname,'.') ) {
1400 size_t len = strlen(username) + strlen(realm) + 2;
1401 pname = malloc(len);
1402 if (pname == NULL) {
1403 code = KRB5KRB_ERR_GENERIC;
1406 StringCbCopy(pname, len, username);
1408 if (!KFW_accept_dotted_usernames()) {
1409 /* handle kerberos iv notation */
1410 while ( dot = strchr(pname,'.') ) {
1414 StringCbCat( pname, len, "@");
1415 StringCbCat( pname, len, realm);
1417 if ( IsDebuggerPresent() ) {
1418 OutputDebugString("Realm of Cell: ");
1419 OutputDebugString(realm);
1420 OutputDebugString("\n");
1421 OutputDebugString("Realm of User: ");
1422 OutputDebugString(userrealm);
1423 OutputDebugString("\n");
1426 code = pkrb5_parse_name(ctx, pname, &principal);
1427 if ( code ) goto cleanup;
1429 code = KFW_get_ccache(ctx, principal, &cc);
1430 if ( code ) goto cleanup;
1432 if ( lifetime == 0 )
1433 lifetime = DEFAULT_LIFETIME;
1435 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1436 if ( IsDebuggerPresent() ) {
1438 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1439 OutputDebugString(message);
1442 if (code && password && password[0] ) {
1443 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1448 0, /* forwardable */
1449 0, /* not proxiable */
1451 1, /* noaddresses */
1452 0 /* no public ip */
1454 pLeash_get_default_forwardable(),
1455 pLeash_get_default_proxiable(),
1456 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1457 pLeash_get_default_noaddresses(),
1458 pLeash_get_default_publicip()
1459 #endif /* USE_LEASH */
1462 if ( IsDebuggerPresent() ) {
1464 StringCbPrintf(message, sizeof(message), "KFW_kinit() returns: %d\n", code);
1465 OutputDebugString(message);
1467 if ( code ) goto cleanup;
1469 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1472 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1473 if ( IsDebuggerPresent() ) {
1475 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1476 OutputDebugString(message);
1478 if ( code ) goto cleanup;
1480 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1482 // Attempt to obtain new tokens for other cells supported by the same
1484 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1485 if ( cell_count > 1 ) {
1486 while ( cell_count-- ) {
1487 if ( strcmp(cells[cell_count],cell) ) {
1488 if ( IsDebuggerPresent() ) {
1490 StringCbPrintf(message, sizeof(message),
1491 "found another cell for the same principal: %s\n", cell);
1492 OutputDebugString(message);
1495 if (cellconfig.linkedCell) {
1496 free(cellconfig.linkedCell);
1497 cellconfig.linkedCell = NULL;
1499 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1500 if ( code ) continue;
1502 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1503 if ( IsDebuggerPresent() ) {
1504 OutputDebugString("Realm: ");
1505 OutputDebugString(realm);
1506 OutputDebugString("\n");
1509 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1510 if ( IsDebuggerPresent() ) {
1512 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1513 OutputDebugString(message);
1516 free(cells[cell_count]);
1519 } else if ( cell_count == 1 ) {
1528 pkrb5_cc_close(ctx, cc);
1529 if ( cellconfig.linkedCell )
1530 free(cellconfig.linkedCell);
1532 if ( code && reasonP ) {
1533 if (pkrb5_get_error_message) {
1534 char *msg = pkrb5_get_error_message(ctx, code);
1535 StringCbCopyN( reason, sizeof(reason),
1536 msg, sizeof(reason) - 1);
1538 pkrb5_free_error_message(ctx, msg);
1540 *reasonP = perror_message(code);
1547 KFW_AFS_destroy_tickets_for_cell(char * cell)
1549 krb5_context ctx = NULL;
1550 krb5_error_code code;
1552 char ** principals = NULL;
1554 if (!pkrb5_init_context)
1555 return KRB5_CONFIG_CANTOPEN;
1557 if ( IsDebuggerPresent() ) {
1558 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1559 OutputDebugString(cell);
1560 OutputDebugString("\n");
1563 code = pkrb5_init_context(&ctx);
1566 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1568 krb5_principal princ = 0;
1572 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1573 if ( cell_count > 1 ) {
1574 // TODO - What we really should do here is verify whether or not any of the
1575 // other cells which use this principal to obtain its credentials actually
1576 // have valid tokens or not. If they are currently using these credentials
1577 // we will skip them. For the time being we assume that if there is an active
1578 // map in the table that they are actively being used.
1582 code = pkrb5_parse_name(ctx, principals[count], &princ);
1583 if (code) goto loop_cleanup;
1585 code = KFW_get_ccache(ctx, princ, &cc);
1586 if (code) goto loop_cleanup;
1588 code = pkrb5_cc_destroy(ctx, cc);
1593 pkrb5_cc_close(ctx, cc);
1597 pkrb5_free_principal(ctx, princ);
1601 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1602 free(principals[count]);
1607 pkrb5_free_context(ctx);
1612 KFW_AFS_destroy_tickets_for_principal(char * user)
1614 krb5_context ctx = NULL;
1615 krb5_error_code code;
1617 char ** cells = NULL;
1618 krb5_principal princ = NULL;
1619 krb5_ccache cc = NULL;
1621 if (!pkrb5_init_context)
1622 return KRB5_CONFIG_CANTOPEN;
1624 if ( IsDebuggerPresent() ) {
1625 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1626 OutputDebugString(user);
1627 OutputDebugString("\n");
1630 code = pkrb5_init_context(&ctx);
1633 code = pkrb5_parse_name(ctx, user, &princ);
1634 if (code) goto loop_cleanup;
1636 code = KFW_get_ccache(ctx, princ, &cc);
1637 if (code) goto loop_cleanup;
1639 code = pkrb5_cc_destroy(ctx, cc);
1644 pkrb5_cc_close(ctx, cc);
1648 pkrb5_free_principal(ctx, princ);
1652 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1655 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1662 pkrb5_free_context(ctx);
1667 KFW_AFS_renew_expiring_tokens(void)
1669 krb5_error_code code = 0;
1670 krb5_context ctx = NULL;
1671 krb5_ccache cc = NULL;
1673 struct principal_ccache_data * pcc_next = princ_cc_data;
1676 const char * realm = NULL;
1677 char local_cell[CELL_MAXNAMELEN+1]="";
1678 struct afsconf_cell cellconfig;
1680 if (!pkrb5_init_context)
1681 return KRB5_CONFIG_CANTOPEN;
1683 if ( pcc_next == NULL ) // nothing to do
1686 if ( IsDebuggerPresent() ) {
1687 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1690 memset(&cellconfig, 0, sizeof(cellconfig));
1692 code = pkrb5_init_context(&ctx);
1693 if (code) goto cleanup;
1695 code = pkrb5_timeofday(ctx, &now);
1696 if (code) goto cleanup;
1698 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1699 if ( pcc_next->expired )
1702 if ( now >= (pcc_next->expiration_time) ) {
1703 if ( !pcc_next->from_lsa ) {
1704 pcc_next->expired = 1;
1709 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1710 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1713 code = KFW_renew(ctx,cc);
1715 if ( code && pcc_next->from_lsa)
1717 #endif /* USE_MS2MIT */
1720 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1721 if (code) goto loop_cleanup;
1723 // Attempt to obtain new tokens for other cells supported by the same
1725 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1726 if ( cell_count > 0 ) {
1727 while ( cell_count-- ) {
1728 if ( IsDebuggerPresent() ) {
1729 OutputDebugString("Cell: ");
1730 OutputDebugString(cells[cell_count]);
1731 OutputDebugString("\n");
1733 if (cellconfig.linkedCell) {
1734 free(cellconfig.linkedCell);
1735 cellconfig.linkedCell = NULL;
1737 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1738 if ( code ) continue;
1739 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1740 if ( IsDebuggerPresent() ) {
1741 OutputDebugString("Realm: ");
1742 OutputDebugString(realm);
1743 OutputDebugString("\n");
1745 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1746 if ( IsDebuggerPresent() ) {
1748 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1749 OutputDebugString(message);
1751 free(cells[cell_count]);
1759 pkrb5_cc_close(ctx,cc);
1766 pkrb5_cc_close(ctx,cc);
1768 pkrb5_free_context(ctx);
1769 if (cellconfig.linkedCell)
1770 free(cellconfig.linkedCell);
1777 KFW_AFS_renew_token_for_cell(char * cell)
1779 krb5_error_code code = 0;
1780 krb5_context ctx = NULL;
1782 char ** principals = NULL;
1784 if (!pkrb5_init_context)
1785 return KRB5_CONFIG_CANTOPEN;
1787 if ( IsDebuggerPresent() ) {
1788 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1789 OutputDebugString(cell);
1790 OutputDebugString("\n");
1793 code = pkrb5_init_context(&ctx);
1794 if (code) goto cleanup;
1796 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1798 // We know we must have a credential somewhere since we are
1799 // trying to renew a token
1801 KFW_import_ccache_data();
1802 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1805 krb5_principal princ = 0;
1806 krb5_principal service = 0;
1808 krb5_creds mcreds, creds;
1809 #endif /* COMMENT */
1811 const char * realm = NULL;
1812 struct afsconf_cell cellconfig;
1813 char local_cell[CELL_MAXNAMELEN+1];
1815 memset(&cellconfig, 0, sizeof(cellconfig));
1818 code = pkrb5_parse_name(ctx, principals[count], &princ);
1819 if (code) goto loop_cleanup;
1821 code = KFW_get_ccache(ctx, princ, &cc);
1822 if (code) goto loop_cleanup;
1824 if (cellconfig.linkedCell) {
1825 free(cellconfig.linkedCell);
1826 cellconfig.linkedCell = NULL;
1828 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1829 if ( code ) goto loop_cleanup;
1831 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1832 if ( IsDebuggerPresent() ) {
1833 OutputDebugString("Realm: ");
1834 OutputDebugString(realm);
1835 OutputDebugString("\n");
1839 /* krb5_cc_remove_cred() is not implemented
1842 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1843 realm, "afs", cell, NULL);
1845 memset(&mcreds, 0, sizeof(krb5_creds));
1846 mcreds.client = princ;
1847 mcreds.server = service;
1849 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1851 if ( IsDebuggerPresent() ) {
1852 char * cname, *sname;
1853 pkrb5_unparse_name(ctx, creds.client, &cname);
1854 pkrb5_unparse_name(ctx, creds.server, &sname);
1855 OutputDebugString("Removing credential for client \"");
1856 OutputDebugString(cname);
1857 OutputDebugString("\" and service \"");
1858 OutputDebugString(sname);
1859 OutputDebugString("\"\n");
1860 pkrb5_free_unparsed_name(ctx,cname);
1861 pkrb5_free_unparsed_name(ctx,sname);
1864 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1865 pkrb5_free_principal(ctx, creds.client);
1866 pkrb5_free_principal(ctx, creds.server);
1869 #endif /* COMMENT */
1871 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1872 if ( IsDebuggerPresent() ) {
1874 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1875 OutputDebugString(message);
1880 pkrb5_cc_close(ctx, cc);
1884 pkrb5_free_principal(ctx, princ);
1888 pkrb5_free_principal(ctx, service);
1891 if (cellconfig.linkedCell) {
1892 free(cellconfig.linkedCell);
1893 cellconfig.linkedCell = NULL;
1896 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1897 free(principals[count]);
1901 code = -1; // we did not renew the tokens
1905 pkrb5_free_context(ctx);
1906 return (code ? FALSE : TRUE);
1911 KFW_AFS_renew_tokens_for_all_cells(void)
1913 struct cell_principal_map * next = cell_princ_map;
1915 if ( IsDebuggerPresent() )
1916 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1921 for ( ; next ; next = next->next ) {
1923 KFW_AFS_renew_token_for_cell(next->cell);
1929 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1931 krb5_error_code code = 0;
1932 krb5_context ctx = NULL;
1933 krb5_ccache cc = NULL;
1934 krb5_principal me = NULL;
1935 krb5_principal server = NULL;
1936 krb5_creds my_creds;
1937 krb5_data *realm = NULL;
1939 if (!pkrb5_init_context)
1940 return KRB5_CONFIG_CANTOPEN;
1942 memset(&my_creds, 0, sizeof(krb5_creds));
1947 code = pkrb5_init_context(&ctx);
1948 if (code) goto cleanup;
1954 code = pkrb5_cc_default(ctx, &cc);
1955 if (code) goto cleanup;
1958 code = pkrb5_cc_get_principal(ctx, cc, &me);
1959 if (code) goto cleanup;
1961 realm = krb5_princ_realm(ctx, me);
1963 code = pkrb5_build_principal_ext(ctx, &server,
1964 realm->length,realm->data,
1965 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1966 realm->length,realm->data,
1971 if ( IsDebuggerPresent() ) {
1972 char * cname, *sname;
1973 pkrb5_unparse_name(ctx, me, &cname);
1974 pkrb5_unparse_name(ctx, server, &sname);
1975 OutputDebugString("Renewing credential for client \"");
1976 OutputDebugString(cname);
1977 OutputDebugString("\" and service \"");
1978 OutputDebugString(sname);
1979 OutputDebugString("\"\n");
1980 pkrb5_free_unparsed_name(ctx,cname);
1981 pkrb5_free_unparsed_name(ctx,sname);
1984 my_creds.client = me;
1985 my_creds.server = server;
1987 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1989 if ( IsDebuggerPresent() ) {
1991 StringCbPrintf(message, sizeof(message), "krb5_get_renewed_creds() failed: %d\n", code);
1992 OutputDebugString(message);
1997 code = pkrb5_cc_initialize(ctx, cc, me);
1999 if ( IsDebuggerPresent() ) {
2001 StringCbPrintf(message, sizeof(message), "krb5_cc_initialize() failed: %d\n", code);
2002 OutputDebugString(message);
2007 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2009 if ( IsDebuggerPresent() ) {
2011 StringCbPrintf(message, sizeof(message), "krb5_cc_store_cred() failed: %d\n", code);
2012 OutputDebugString(message);
2018 if (my_creds.client == me)
2019 my_creds.client = 0;
2020 if (my_creds.server == server)
2021 my_creds.server = 0;
2022 pkrb5_free_cred_contents(ctx, &my_creds);
2024 pkrb5_free_principal(ctx, me);
2026 pkrb5_free_principal(ctx, server);
2027 if (cc && (cc != alt_cc))
2028 pkrb5_cc_close(ctx, cc);
2029 if (ctx && (ctx != alt_ctx))
2030 pkrb5_free_context(ctx);
2035 KFW_kinit( krb5_context alt_ctx,
2038 char *principal_name,
2040 krb5_deltat lifetime,
2043 krb5_deltat renew_life,
2048 krb5_error_code code = 0;
2049 krb5_context ctx = NULL;
2050 krb5_ccache cc = NULL;
2051 krb5_principal me = NULL;
2053 krb5_creds my_creds;
2054 krb5_get_init_creds_opt options;
2055 krb5_address ** addrs = NULL;
2056 int i = 0, addr_count = 0;
2058 if (!pkrb5_init_context)
2059 return KRB5_CONFIG_CANTOPEN;
2061 pkrb5_get_init_creds_opt_init(&options);
2062 memset(&my_creds, 0, sizeof(my_creds));
2070 code = pkrb5_init_context(&ctx);
2071 if (code) goto cleanup;
2077 code = pkrb5_cc_default(ctx, &cc);
2078 if (code) goto cleanup;
2081 code = pkrb5_parse_name(ctx, principal_name, &me);
2085 code = pkrb5_unparse_name(ctx, me, &name);
2090 lifetime = DEFAULT_LIFETIME;
2097 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2098 pkrb5_get_init_creds_opt_set_forwardable(&options,
2099 forwardable ? 1 : 0);
2100 pkrb5_get_init_creds_opt_set_proxiable(&options,
2102 pkrb5_get_init_creds_opt_set_renew_life(&options,
2105 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2109 // we are going to add the public IP address specified by the user
2110 // to the list provided by the operating system
2111 krb5_address ** local_addrs=NULL;
2114 pkrb5_os_localaddr(ctx, &local_addrs);
2115 while ( local_addrs[i++] );
2118 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2120 pkrb5_free_addresses(ctx, local_addrs);
2123 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2125 while ( local_addrs[i] ) {
2126 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2127 if (addrs[i] == NULL) {
2128 pkrb5_free_addresses(ctx, local_addrs);
2132 addrs[i]->magic = local_addrs[i]->magic;
2133 addrs[i]->addrtype = local_addrs[i]->addrtype;
2134 addrs[i]->length = local_addrs[i]->length;
2135 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2136 if (!addrs[i]->contents) {
2137 pkrb5_free_addresses(ctx, local_addrs);
2141 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2142 local_addrs[i]->length); /* safe */
2145 pkrb5_free_addresses(ctx, local_addrs);
2147 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2148 if (addrs[i] == NULL)
2151 addrs[i]->magic = KV5M_ADDRESS;
2152 addrs[i]->addrtype = AF_INET;
2153 addrs[i]->length = 4;
2154 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2155 if (!addrs[i]->contents)
2158 netIPAddr = htonl(publicIP);
2159 memcpy(addrs[i]->contents,&netIPAddr,4);
2161 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2166 code = pkrb5_get_init_creds_password(ctx,
2169 password, // password
2170 KRB5_prompter, // prompter
2171 hParent, // prompter data
2178 code = pkrb5_cc_initialize(ctx, cc, me);
2182 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2188 for ( i=0;i<addr_count;i++ ) {
2190 if ( addrs[i]->contents )
2191 free(addrs[i]->contents);
2196 if (my_creds.client == me)
2197 my_creds.client = 0;
2198 pkrb5_free_cred_contents(ctx, &my_creds);
2200 pkrb5_free_unparsed_name(ctx, name);
2202 pkrb5_free_principal(ctx, me);
2203 if (cc && (cc != alt_cc))
2204 pkrb5_cc_close(ctx, cc);
2205 if (ctx && (ctx != alt_ctx))
2206 pkrb5_free_context(ctx);
2212 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2214 krb5_context ctx = NULL;
2215 krb5_ccache cc = NULL;
2216 krb5_error_code code;
2218 if (!pkrb5_init_context)
2219 return KRB5_CONFIG_CANTOPEN;
2227 code = pkrb5_init_context(&ctx);
2228 if (code) goto cleanup;
2234 code = pkrb5_cc_default(ctx, &cc);
2235 if (code) goto cleanup;
2238 code = pkrb5_cc_destroy(ctx, cc);
2239 if ( !code ) cc = 0;
2242 if (cc && (cc != alt_cc))
2243 pkrb5_cc_close(ctx, cc);
2244 if (ctx && (ctx != alt_ctx))
2245 pkrb5_free_context(ctx);
2253 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2255 NTSTATUS Status = 0;
2257 TOKEN_STATISTICS Stats;
2263 *ppSessionData = NULL;
2265 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2269 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2270 CloseHandle( TokenHandle );
2274 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2275 if ( FAILED(Status) || !ppSessionData )
2282 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2283 // cache. It validates whether or not it is reasonable to assume that if we
2284 // attempted to retrieve valid tickets we could do so. Microsoft does not
2285 // automatically renew expired tickets. Therefore, the cache could contain
2286 // expired or invalid tickets. Microsoft also caches the user's password
2287 // and will use it to retrieve new TGTs if the cache is empty and tickets
2291 MSLSA_IsKerberosLogon(VOID)
2293 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2294 BOOL Success = FALSE;
2296 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2297 if ( pSessionData->AuthenticationPackage.Buffer ) {
2303 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2304 usLength = (pSessionData->AuthenticationPackage).Length;
2307 StringCbCopyNW( buffer, sizeof(buffer)/sizeof(WCHAR),
2308 usBuffer, usLength);
2309 if ( !lstrcmpW(L"Kerberos",buffer) )
2313 pLsaFreeReturnBuffer(pSessionData);
2317 #endif /* USE_MS2MIT */
2319 static BOOL CALLBACK
2320 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2324 switch ( message ) {
2326 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2328 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2331 for ( i=0; i < mid_cnt ; i++ ) {
2332 if (mid_tb[i].echo == 0)
2333 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2334 else if (mid_tb[i].echo == 2)
2335 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2340 switch ( LOWORD(wParam) ) {
2342 for ( i=0; i < mid_cnt ; i++ ) {
2343 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2344 *mid_tb[i].buf = '\0';
2348 EndDialog(hDialog, LOWORD(wParam));
2356 lpwAlign( LPWORD lpIn )
2360 ul = (ULONG_PTR) lpIn;
2364 return (LPWORD) ul;;
2368 * dialog widths are measured in 1/4 character widths
2369 * dialog height are measured in 1/8 character heights
2373 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2374 char * ptext[], int numlines, int width,
2375 int tb_cnt, struct textField * tb)
2379 LPDLGITEMTEMPLATE lpdit;
2385 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2392 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2394 // Define a dialog box.
2396 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2397 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2398 | DS_SETFOREGROUND | DS_3DLOOK
2399 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2400 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2403 lpdt->cx = 20 + width * 4;
2404 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2406 lpw = (LPWORD) (lpdt + 1);
2407 *lpw++ = 0; // no menu
2408 *lpw++ = 0; // predefined dialog box class (by default)
2410 lpwsz = (LPWSTR) lpw;
2411 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2413 *lpw++ = 8; // font size (points)
2414 lpwsz = (LPWSTR) lpw;
2415 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2419 //-----------------------
2420 // Define an OK button.
2421 //-----------------------
2422 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2423 lpdit = (LPDLGITEMTEMPLATE) lpw;
2424 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2425 lpdit->dwExtendedStyle = 0;
2426 lpdit->x = (lpdt->cx - 14)/4 - 20;
2427 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2430 lpdit->id = IDOK; // OK button identifier
2432 lpw = (LPWORD) (lpdit + 1);
2434 *lpw++ = 0x0080; // button class
2436 lpwsz = (LPWSTR) lpw;
2437 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2439 *lpw++ = 0; // no creation data
2441 //-----------------------
2442 // Define an Cancel button.
2443 //-----------------------
2444 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2445 lpdit = (LPDLGITEMTEMPLATE) lpw;
2446 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2447 lpdit->dwExtendedStyle = 0;
2448 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2449 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2452 lpdit->id = IDCANCEL; // CANCEL button identifier
2454 lpw = (LPWORD) (lpdit + 1);
2456 *lpw++ = 0x0080; // button class
2458 lpwsz = (LPWSTR) lpw;
2459 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2461 *lpw++ = 0; // no creation data
2463 /* Add controls for preface data */
2464 for ( i=0; i<numlines; i++) {
2465 /*-----------------------
2466 * Define a static text control.
2467 *-----------------------*/
2468 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2469 lpdit = (LPDLGITEMTEMPLATE) lpw;
2470 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2471 lpdit->dwExtendedStyle = 0;
2473 lpdit->y = 10 + i * 14;
2474 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2476 lpdit->id = ID_TEXT + i; // text identifier
2478 lpw = (LPWORD) (lpdit + 1);
2480 *lpw++ = 0x0082; // static class
2482 lpwsz = (LPWSTR) lpw;
2483 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2484 -1, lpwsz, 2*width);
2486 *lpw++ = 0; // no creation data
2489 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2490 int len = (int)strlen(tb[i].label);
2495 for ( i=0; i<tb_cnt; i++) {
2497 /*-----------------------
2498 * Define a static text control.
2499 *-----------------------*/
2500 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2501 lpdit = (LPDLGITEMTEMPLATE) lpw;
2502 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2503 lpdit->dwExtendedStyle = 0;
2505 lpdit->y = 10 + (numlines + i + 1) * 14;
2506 lpdit->cx = pwid * 4;
2508 lpdit->id = ID_TEXT + numlines + i; // text identifier
2510 lpw = (LPWORD) (lpdit + 1);
2512 *lpw++ = 0x0082; // static class
2514 lpwsz = (LPWSTR) lpw;
2515 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2518 *lpw++ = 0; // no creation data
2520 /*-----------------------
2521 * Define an edit control.
2522 *-----------------------*/
2523 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2524 lpdit = (LPDLGITEMTEMPLATE) lpw;
2525 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2526 lpdit->dwExtendedStyle = 0;
2527 lpdit->x = 10 + (pwid + 1) * 4;
2528 lpdit->y = 10 + (numlines + i + 1) * 14;
2529 lpdit->cx = (width - (pwid + 1)) * 4;
2531 lpdit->id = ID_MID_TEXT + i; // identifier
2533 lpw = (LPWORD) (lpdit + 1);
2535 *lpw++ = 0x0081; // edit class
2537 lpwsz = (LPWSTR) lpw;
2538 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2541 *lpw++ = 0; // no creation data
2545 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2546 hwndOwner, (DLGPROC) MultiInputDialogProc);
2550 case 0: /* Timeout */
2558 StringCbPrintf(buf, sizeof(buf), "DialogBoxIndirect() failed: %d", GetLastError());
2559 MessageBox(hwndOwner,
2562 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2569 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2571 HINSTANCE hInst = 0;
2575 char * plines[16], *p = preface ? preface : "";
2578 for ( i=0; i<16; i++ )
2581 while (*p && numlines < 16) {
2582 plines[numlines++] = p;
2583 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2584 if ( *p == '\r' && *(p+1) == '\n' ) {
2587 } else if ( *p == '\n' ) {
2590 if ( strlen(plines[numlines-1]) > maxwidth )
2591 maxwidth = (int)strlen(plines[numlines-1]);
2594 for ( i=0;i<n;i++ ) {
2595 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2596 if ( maxwidth < len )
2600 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2603 static krb5_error_code KRB5_CALLCONV
2604 KRB5_prompter( krb5_context context,
2609 krb5_prompt prompts[])
2611 krb5_error_code errcode = 0;
2613 struct textField * tb = NULL;
2614 int len = 0, blen=0, nlen=0;
2615 HWND hParent = (HWND)data;
2618 nlen = (int)strlen(name)+2;
2621 blen = (int)strlen(banner)+2;
2623 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2626 memset(tb,0,sizeof(struct textField) * num_prompts);
2627 for ( i=0; i < num_prompts; i++ ) {
2628 tb[i].buf = prompts[i].reply->data;
2629 tb[i].len = prompts[i].reply->length;
2630 tb[i].label = prompts[i].prompt;
2632 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2635 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2637 for ( i=0; i < num_prompts; i++ )
2638 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2646 for (i = 0; i < num_prompts; i++) {
2647 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2654 KFW_AFS_wait_for_service_start(void)
2659 CurrentState = SERVICE_START_PENDING;
2660 memset(HostName, '\0', sizeof(HostName));
2661 gethostname(HostName, sizeof(HostName));
2663 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2665 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2667 if ( IsDebuggerPresent() ) {
2668 switch ( CurrentState ) {
2669 case SERVICE_STOPPED:
2670 OutputDebugString("SERVICE_STOPPED\n");
2672 case SERVICE_START_PENDING:
2673 OutputDebugString("SERVICE_START_PENDING\n");
2675 case SERVICE_STOP_PENDING:
2676 OutputDebugString("SERVICE_STOP_PENDING\n");
2678 case SERVICE_RUNNING:
2679 OutputDebugString("SERVICE_RUNNING\n");
2681 case SERVICE_CONTINUE_PENDING:
2682 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2684 case SERVICE_PAUSE_PENDING:
2685 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2687 case SERVICE_PAUSED:
2688 OutputDebugString("SERVICE_PAUSED\n");
2691 OutputDebugString("UNKNOWN Service State\n");
2694 if (CurrentState == SERVICE_STOPPED)
2696 if (CurrentState == SERVICE_RUNNING)
2712 memset(HostName, '\0', sizeof(HostName));
2713 gethostname(HostName, sizeof(HostName));
2714 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2716 if (CurrentState != SERVICE_RUNNING)
2719 rc = ktc_ForgetAllTokens();
2725 #define ALLOW_REGISTER 1
2727 ViceIDToUsername(char *username,
2728 char *realm_of_user,
2729 char *realm_of_cell,
2731 struct ktc_principal *aclient,
2732 struct ktc_principal *aserver,
2733 struct ktc_token *atoken)
2735 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2736 static char confdir[512] = { 0 };
2737 #ifdef AFS_ID_TO_NAME
2738 char username_copy[BUFSIZ];
2739 #endif /* AFS_ID_TO_NAME */
2740 long viceId = ANONYMOUSID; /* AFS uid of user */
2742 #ifdef ALLOW_REGISTER
2744 #endif /* ALLOW_REGISTER */
2746 if (confdir[0] == '\0')
2747 cm_GetConfigDir(confdir, sizeof(confdir));
2749 StringCbCopyN( lastcell, sizeof(lastcell),
2750 aserver->cell, sizeof(lastcell) - 1);
2752 if (!pr_Initialize (0, confdir, aserver->cell)) {
2753 char sname[PR_MAXNAMELEN];
2754 StringCbCopyN( sname, sizeof(sname),
2755 username, sizeof(sname) - 1);
2756 status = pr_SNameToId (sname, &viceId);
2761 * This is a crock, but it is Transarc's crock, so
2762 * we have to play along in order to get the
2763 * functionality. The way the afs id is stored is
2764 * as a string in the username field of the token.
2765 * Contrary to what you may think by looking at
2766 * the code for tokens, this hack (AFS ID %d) will
2767 * not work if you change %d to something else.
2771 * This code is taken from cklog -- it lets people
2772 * automatically register with the ptserver in foreign cells
2775 #ifdef ALLOW_REGISTER
2777 if (viceId != ANONYMOUSID) {
2778 #else /* ALLOW_REGISTER */
2779 if ((status == 0) && (viceId != ANONYMOUSID))
2780 #endif /* ALLOW_REGISTER */
2782 #ifdef AFS_ID_TO_NAME
2783 StringCbCopyN( username_copy, sizeof(username_copy),
2784 username, sizeof(username_copy) - 1);
2785 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2786 #endif /* AFS_ID_TO_NAME */
2788 #ifdef ALLOW_REGISTER
2789 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2791 StringCbCopyN( aclient->name, sizeof(aclient->name),
2792 username, sizeof(aclient->name) - 1);
2793 aclient->instance[0] = '\0';
2794 StringCbCopyN( aclient->cell, sizeof(aclient->cell),
2795 realm_of_user, sizeof(aclient->cell) - 1);
2796 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2798 if (status = pr_Initialize(1L, confdir, aserver->cell))
2800 status = pr_CreateUser(username, &id);
2804 #ifdef AFS_ID_TO_NAME
2805 StringCbCopyN( username_copy, sizeof(username_copy),
2806 username, sizeof(username_copy) - 1);
2807 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2808 #endif /* AFS_ID_TO_NAME */
2811 #endif /* ALLOW_REGISTER */
2817 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2818 krb5_error_code code;
2819 krb5_ticket *ticket;
2822 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2824 len = krb5_princ_realm(context, ticket->server)->length;
2825 if (len > destlen - 1)
2828 StringCbCopyN(dest, destlen, krb5_princ_realm(context, ticket->server)->data, len);
2830 pkrb5_free_ticket(context, ticket);
2836 krb5_context alt_ctx,
2841 int lifetime, /* unused parameter */
2849 #endif /* USE_KRB4 */
2850 struct ktc_principal aserver;
2851 struct ktc_principal aclient;
2852 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2853 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2854 char local_cell[CELL_MAXNAMELEN+1];
2855 char Dmycell[CELL_MAXNAMELEN+1];
2856 struct ktc_token atoken;
2857 struct ktc_token btoken;
2858 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2859 char RealmName[128];
2861 char ServiceName[128];
2865 krb5_context ctx = NULL;
2866 krb5_ccache cc = NULL;
2868 krb5_creds * k5creds = NULL;
2869 krb5_error_code code;
2870 krb5_principal client_principal = NULL;
2871 krb5_data * k5data = NULL;
2872 unsigned int i, retry = 0;
2875 memset(HostName, '\0', sizeof(HostName));
2876 gethostname(HostName, sizeof(HostName));
2877 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2878 if ( IsDebuggerPresent() )
2879 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2882 if (CurrentState != SERVICE_RUNNING) {
2883 if ( IsDebuggerPresent() )
2884 OutputDebugString("AFSD Service NOT RUNNING\n");
2888 if (!pkrb5_init_context)
2889 return KRB5_CONFIG_CANTOPEN;
2891 memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
2892 memset(RealmName, '\0', sizeof(RealmName));
2893 memset(CellName, '\0', sizeof(CellName));
2894 memset(ServiceName, '\0', sizeof(ServiceName));
2895 memset(realm_of_user, '\0', sizeof(realm_of_user));
2896 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2897 if (cell && cell[0])
2898 StringCbCopyN( Dmycell, sizeof(Dmycell),
2899 cell, sizeof(Dmycell) - 1);
2901 memset(Dmycell, '\0', sizeof(Dmycell));
2903 // NULL or empty cell returns information on local cell
2904 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2906 // KFW_AFS_error(rc, "get_cellconfig()");
2913 code = pkrb5_init_context(&ctx);
2914 if (code) goto cleanup;
2920 code = pkrb5_cc_default(ctx, &cc);
2921 if (code) goto skip_krb5_init;
2924 memset(&increds, 0, sizeof(increds));
2926 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2928 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2930 OutputDebugString("Principal Not Found for ccache\n");
2932 goto skip_krb5_init;
2935 if (!KFW_accept_dotted_usernames()) {
2936 /* look for client principals which cannot be distinguished
2937 * from Kerberos 4 multi-component principal names
2939 k5data = krb5_princ_component(ctx,client_principal,0);
2940 for ( i=0; i<k5data->length; i++ ) {
2941 if ( k5data->data[i] == '.' )
2944 if (i != k5data->length)
2946 OutputDebugString("Illegal Principal name contains dot in first component\n");
2947 rc = KRB5KRB_ERR_GENERIC;
2952 i = krb5_princ_realm(ctx, client_principal)->length;
2955 StringCbCopyN( realm_of_user, sizeof(realm_of_user),
2956 krb5_princ_realm(ctx, client_principal)->data, i);
2961 if ( !try_krb5 || !realm_of_user[0] ) {
2962 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2971 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
2972 afs_realm_of_cell(ctx, &ak_cellconfig),
2973 sizeof(realm_of_cell) - 1);
2975 if (strlen(service) == 0)
2976 StringCbCopy( ServiceName, sizeof(ServiceName), "afs");
2978 StringCbCopyN( ServiceName, sizeof(ServiceName),
2979 service, sizeof(ServiceName) - 1);
2981 if (strlen(cell) == 0)
2982 StringCbCopyN( CellName, sizeof(CellName),
2983 local_cell, sizeof(CellName) - 1);
2985 StringCbCopyN( CellName, sizeof(CellName),
2986 cell, sizeof(CellName) - 1);
2988 /* This is for Kerberos v4 only */
2989 if (strlen(realm) == 0)
2990 StringCbCopyN( RealmName, sizeof(RealmName),
2991 realm_of_cell, sizeof(RealmName) - 1);
2993 StringCbCopyN( RealmName, sizeof(RealmName),
2994 realm, sizeof(RealmName) - 1);
2996 memset(&creds, '\0', sizeof(creds));
3000 code = KRB5KRB_ERR_GENERIC;
3003 increds.client = client_principal;
3004 increds.times.endtime = 0;
3005 /* Ask for DES since that is what V4 understands */
3006 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
3008 /* ALWAYS first try service/cell@CLIENT_REALM */
3009 if (code = pkrb5_build_principal(ctx, &increds.server,
3010 (int)strlen(realm_of_user),
3019 if ( IsDebuggerPresent() ) {
3020 char * cname, *sname;
3021 pkrb5_unparse_name(ctx, increds.client, &cname);
3022 pkrb5_unparse_name(ctx, increds.server, &sname);
3023 OutputDebugString("Getting tickets for \"");
3024 OutputDebugString(cname);
3025 OutputDebugString("\" and service \"");
3026 OutputDebugString(sname);
3027 OutputDebugString("\"\n");
3028 pkrb5_free_unparsed_name(ctx,cname);
3029 pkrb5_free_unparsed_name(ctx,sname);
3032 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3034 /* The client's realm is a local realm for the cell.
3035 * Save it so that later the pts registration will not
3038 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3039 realm_of_user, sizeof(realm_of_cell) - 1);
3043 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3044 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3045 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3046 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3047 /* If there was a specific realm we are supposed to try
3050 if (strlen(realm) != 0) {
3051 /* service/cell@REALM */
3053 code = pkrb5_build_principal(ctx, &increds.server,
3059 if ( IsDebuggerPresent() ) {
3060 char * cname, *sname;
3061 pkrb5_unparse_name(ctx, increds.client, &cname);
3062 pkrb5_unparse_name(ctx, increds.server, &sname);
3063 OutputDebugString("Getting tickets for \"");
3064 OutputDebugString(cname);
3065 OutputDebugString("\" and service \"");
3066 OutputDebugString(sname);
3067 OutputDebugString("\"\n");
3068 pkrb5_free_unparsed_name(ctx,cname);
3069 pkrb5_free_unparsed_name(ctx,sname);
3073 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3075 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3076 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3077 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3078 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3079 /* Or service@REALM */
3080 pkrb5_free_principal(ctx,increds.server);
3082 code = pkrb5_build_principal(ctx, &increds.server,
3088 if ( IsDebuggerPresent() ) {
3089 char * cname, *sname;
3090 pkrb5_unparse_name(ctx, increds.client, &cname);
3091 pkrb5_unparse_name(ctx, increds.server, &sname);
3092 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3093 OutputDebugString("Trying again: getting tickets for \"");
3094 OutputDebugString(cname);
3095 OutputDebugString("\" and service \"");
3096 OutputDebugString(sname);
3097 OutputDebugString("\"\n");
3098 pkrb5_free_unparsed_name(ctx,cname);
3099 pkrb5_free_unparsed_name(ctx,sname);
3103 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3107 /* we have a local realm for the cell */
3108 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3109 realm, sizeof(realm_of_cell) - 1);
3112 if (strcmp(realm_of_user, realm_of_cell)) {
3113 /* Then service/cell@CELL_REALM */
3114 pkrb5_free_principal(ctx,increds.server);
3116 code = pkrb5_build_principal(ctx, &increds.server,
3117 (int)strlen(realm_of_cell),
3122 if ( IsDebuggerPresent() ) {
3123 char * cname, *sname;
3124 pkrb5_unparse_name(ctx, increds.client, &cname);
3125 pkrb5_unparse_name(ctx, increds.server, &sname);
3126 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3127 OutputDebugString("Trying again: getting tickets for \"");
3128 OutputDebugString(cname);
3129 OutputDebugString("\" and service \"");
3130 OutputDebugString(sname);
3131 OutputDebugString("\"\n");
3132 pkrb5_free_unparsed_name(ctx,cname);
3133 pkrb5_free_unparsed_name(ctx,sname);
3137 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3139 if (!code && !strlen(realm_of_cell))
3140 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3143 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3144 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3145 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3146 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3147 /* Finally service@CELL_REALM */
3148 pkrb5_free_principal(ctx,increds.server);
3150 code = pkrb5_build_principal(ctx, &increds.server,
3151 (int)strlen(realm_of_cell),
3156 if ( IsDebuggerPresent() ) {
3157 char * cname, *sname;
3158 pkrb5_unparse_name(ctx, increds.client, &cname);
3159 pkrb5_unparse_name(ctx, increds.server, &sname);
3160 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3161 OutputDebugString("Trying again: getting tickets for \"");
3162 OutputDebugString(cname);
3163 OutputDebugString("\" and service \"");
3164 OutputDebugString(sname);
3165 OutputDebugString("\"\n");
3166 pkrb5_free_unparsed_name(ctx,cname);
3167 pkrb5_free_unparsed_name(ctx,sname);
3171 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3172 if (!code && !strlen(realm_of_cell))
3173 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3179 if ( IsDebuggerPresent() ) {
3181 StringCbPrintf(message, sizeof(message), "krb5_get_credentials returns: %d\n", code);
3182 OutputDebugString(message);
3188 /* This code inserts the entire K5 ticket into the token
3189 * No need to perform a krb524 translation which is
3190 * commented out in the code below
3192 if (KFW_use_krb524() ||
3193 k5creds->ticket.length > MAXKTCTICKETLEN)
3196 memset(&aserver, '\0', sizeof(aserver));
3197 StringCbCopyN(aserver.name, sizeof(aserver.name),
3198 ServiceName, sizeof(aserver.name) - 1);
3199 StringCbCopyN(aserver.cell, sizeof(aserver.cell),
3200 CellName, sizeof(aserver.cell) - 1);
3202 memset(&atoken, '\0', sizeof(atoken));
3203 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3204 atoken.startTime = k5creds->times.starttime;
3205 atoken.endTime = k5creds->times.endtime;
3206 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3207 atoken.ticketLen = k5creds->ticket.length;
3208 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3211 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3212 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3213 if ( rc == KTC_NOCM && retry < 20 ) {
3216 goto retry_gettoken5;
3221 if (atoken.kvno == btoken.kvno &&
3222 atoken.ticketLen == btoken.ticketLen &&
3223 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3224 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3226 /* Success - Nothing to do */
3230 // * Reset the "aclient" structure before we call ktc_SetToken.
3231 // * This structure was first set by the ktc_GetToken call when
3232 // * we were comparing whether identical tokens already existed.
3234 len = min(k5creds->client->data[0].length, sizeof(aclient.name) - 1);
3235 StringCbCopyN( aclient.name, sizeof(aclient.name),
3236 k5creds->client->data[0].data, len);
3238 if ( k5creds->client->length > 1 ) {
3239 StringCbCat( aclient.name, sizeof(aclient.name), ".");
3240 len = min(k5creds->client->data[1].length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3241 StringCbCatN( aclient.name, sizeof(aclient.name),
3242 k5creds->client->data[1].data, len);
3244 aclient.instance[0] = '\0';
3246 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3247 realm_of_cell, sizeof(aclient.cell) - 1);
3249 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3250 /* For Khimaira, always append the realm name */
3251 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3252 StringCbCat( aclient.name, sizeof(aclient.name), "@");
3253 len = min(k5creds->client->realm.length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3254 StringCbCatN( aclient.name, sizeof(aclient.name), k5creds->client->realm.data, len);
3257 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3258 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3259 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3260 &aclient, &aserver, &atoken);
3263 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3264 smbname, sizeof(aclient.smbname) - 1);
3266 aclient.smbname[0] = '\0';
3269 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3271 goto cleanup; /* We have successfully inserted the token */
3277 /* Otherwise, the ticket could have been too large so try to
3278 * convert using the krb524d running with the KDC
3280 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3281 pkrb5_free_creds(ctx, k5creds);
3283 if ( IsDebuggerPresent() ) {
3285 StringCbPrintf(message, sizeof(message), "krb524_convert_creds_kdc returns: %d\n", code);
3286 OutputDebugString(message);
3291 #endif /* USE_KRB524 */
3295 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3296 if (code == NO_TKT_FIL) {
3297 // if the problem is that we have no krb4 tickets
3298 // do not attempt to continue
3301 if (code != KSUCCESS)
3302 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3304 if (code != KSUCCESS)
3306 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3308 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3313 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3315 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3330 memset(&aserver, '\0', sizeof(aserver));
3331 StringCbCopyN( aserver.name, sizeof(aserver.name), ServiceName, sizeof(aserver.name) - 1);
3332 StringCbCopyN( aserver.cell, sizeof(aserver.cell), CellName, sizeof(aserver.cell) - 1);
3334 memset(&atoken, '\0', sizeof(atoken));
3335 atoken.kvno = creds.kvno;
3336 atoken.startTime = creds.issue_date;
3337 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3338 memcpy(&atoken.sessionKey, creds.session, 8);
3339 atoken.ticketLen = creds.ticket_st.length;
3340 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3343 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3344 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3345 if ( rc == KTC_NOCM && retry < 20 ) {
3348 goto retry_gettoken;
3350 KFW_AFS_error(rc, "ktc_GetToken()");
3355 if (atoken.kvno == btoken.kvno &&
3356 atoken.ticketLen == btoken.ticketLen &&
3357 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3358 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3363 // * Reset the "aclient" structure before we call ktc_SetToken.
3364 // * This structure was first set by the ktc_GetToken call when
3365 // * we were comparing whether identical tokens already existed.
3367 StringCbCopyN( aclient.name, sizeof(aclient.name), creds.pname, sizeof(aclient.name) - 1);
3370 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3371 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3373 aclient.instance[0] = '\0';
3375 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3376 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3377 aclient.name[MAXKTCREALMLEN-1] = '\0';
3379 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3380 CellName, sizeof(aclient.cell) - 1);
3382 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3383 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3384 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3385 &aclient, &aserver, &atoken);
3388 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3389 smbname, sizeof(aclient.smbname) - 1);
3391 aclient.smbname[0] = '\0';
3394 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3396 KFW_AFS_error(rc, "ktc_SetToken()");
3402 if (client_principal)
3403 pkrb5_free_principal(ctx,client_principal);
3404 /* increds.client == client_principal */
3406 pkrb5_free_principal(ctx,increds.server);
3407 if (cc && (cc != alt_cc))
3408 pkrb5_cc_close(ctx, cc);
3409 if (ctx && (ctx != alt_ctx))
3410 pkrb5_free_context(ctx);
3411 if (ak_cellconfig.linkedCell)
3412 free(ak_cellconfig.linkedCell);
3414 return(rc? rc : code);
3417 /**************************************/
3418 /* afs_realm_of_cell(): */
3419 /**************************************/
3421 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3423 static char krbrlm[REALM_SZ+1]="";
3424 char ** realmlist=NULL;
3430 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3431 if ( !r && realmlist && realmlist[0] ) {
3432 StringCbCopyN( krbrlm, sizeof(krbrlm),
3433 realmlist[0], sizeof(krbrlm) - 1);
3434 pkrb5_free_host_realm(ctx, realmlist);
3440 char *t = cellconfig->name;
3445 if (islower(c)) c=toupper(c);
3453 /**************************************/
3454 /* KFW_AFS_get_cellconfig(): */
3455 /**************************************/
3457 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3460 char newcell[CELL_MAXNAMELEN+1];
3461 char linkedcell[CELL_MAXNAMELEN+1]="";
3463 local_cell[0] = (char)0;
3464 memset(cellconfig, 0, sizeof(*cellconfig));
3466 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3467 if (rc = cm_GetRootCellName(local_cell))
3472 if (strlen(cell) == 0)
3473 strcpy(cell, local_cell);
3475 rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3476 if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
3477 rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3480 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3484 StringCbCopyN( cellconfig->name, sizeof(cellconfig->name),
3485 newcell, sizeof(cellconfig->name) - 1);
3487 cellconfig->linkedCell = strdup(linkedcell);
3492 /**************************************/
3493 /* get_cellconfig_callback(): */
3494 /**************************************/
3496 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
3498 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3500 cc->hostAddr[cc->numServers] = *addrp;
3501 StringCbCopyN( cc->hostName[cc->numServers], sizeof(cc->hostName[cc->numServers]),
3502 namep, sizeof(cc->hostName[cc->numServers]) - 1);
3508 /**************************************/
3509 /* KFW_AFS_error(): */
3510 /**************************************/
3512 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3515 const char *errText;
3517 // Using AFS defines as error messages for now, until Transarc
3518 // gets back to me with "string" translations of each of these
3520 if (rc == KTC_ERROR)
3521 errText = "KTC_ERROR";
3522 else if (rc == KTC_TOOBIG)
3523 errText = "KTC_TOOBIG";
3524 else if (rc == KTC_INVAL)
3525 errText = "KTC_INVAL";
3526 else if (rc == KTC_NOENT)
3527 errText = "KTC_NOENT";
3528 else if (rc == KTC_PIOCTLFAIL)
3529 errText = "KTC_PIOCTLFAIL";
3530 else if (rc == KTC_NOPIOCTL)
3531 errText = "KTC_NOPIOCTL";
3532 else if (rc == KTC_NOCELL)
3533 errText = "KTC_NOCELL";
3534 else if (rc == KTC_NOCM)
3535 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3537 errText = "Unknown error!";
3539 StringCbPrintf(message, sizeof(message), "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3541 if ( IsDebuggerPresent() ) {
3542 OutputDebugString(message);
3543 OutputDebugString("\n");
3545 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3551 LPSTR lpszMachineName,
3552 LPSTR lpszServiceName,
3553 DWORD *lpdwCurrentState)
3556 SC_HANDLE schSCManager = NULL;
3557 SC_HANDLE schService = NULL;
3558 DWORD fdwDesiredAccess = 0;
3559 SERVICE_STATUS ssServiceStatus = {0};
3562 *lpdwCurrentState = 0;
3564 fdwDesiredAccess = GENERIC_READ;
3566 schSCManager = OpenSCManager(lpszMachineName,
3570 if(schSCManager == NULL)
3572 hr = GetLastError();
3576 schService = OpenService(schSCManager,
3580 if(schService == NULL)
3582 hr = GetLastError();
3586 fRet = QueryServiceStatus(schService,
3591 hr = GetLastError();
3595 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3599 CloseServiceHandle(schService);
3600 CloseServiceHandle(schSCManager);
3613 for (n = 0; fi[n].func_ptr_var; n++)
3614 *(fi[n].func_ptr_var) = 0;
3615 if (h) FreeLibrary(h);
3620 const char* dll_name,
3622 HINSTANCE* ph, // [out, optional] - DLL handle
3623 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3624 int cleanup, // cleanup function pointers and unload on error
3625 int go_on, // continue loading even if some functions cannot be loaded
3626 int silent // do not pop-up a system dialog if DLL cannot be loaded
3635 if (pindex) *pindex = -1;
3637 for (n = 0; fi[n].func_ptr_var; n++)
3638 *(fi[n].func_ptr_var) = 0;
3641 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3642 h = LoadLibrary(dll_name);
3650 for (i = 0; (go_on || !error) && (i < n); i++)
3652 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3658 *(fi[i].func_ptr_var) = p;
3661 if (pindex) *pindex = last_i;
3662 if (error && cleanup && !go_on) {
3663 for (i = 0; i < n; i++) {
3664 *(fi[i].func_ptr_var) = 0;
3670 if (error) return 0;
3674 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3676 krb5_context ctx = NULL;
3677 krb5_ccache cc = NULL;
3678 krb5_error_code code;
3680 const char * realm = NULL;
3681 krb5_principal principal = NULL;
3682 char * pname = NULL;
3683 char password[PROBE_PASSWORD_LEN+1];
3684 BOOL serverReachable = 0;
3686 if (!pkrb5_init_context)
3687 return KRB5_CONFIG_CANTOPEN;
3689 code = pkrb5_init_context(&ctx);
3690 if (code) goto cleanup;
3693 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3695 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3696 realm, PROBE_USERNAME, NULL, NULL);
3697 if ( code ) goto cleanup;
3699 code = KFW_get_ccache(ctx, principal, &cc);
3700 if ( code ) goto cleanup;
3702 code = pkrb5_unparse_name(ctx, principal, &pname);
3703 if ( code ) goto cleanup;
3705 pwdata.data = password;
3706 pwdata.length = PROBE_PASSWORD_LEN;
3707 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3710 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3713 password[PROBE_PASSWORD_LEN] = '\0';
3715 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3725 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3726 case KRB5KDC_ERR_CLIENT_REVOKED:
3727 case KRB5KDC_ERR_CLIENT_NOTYET:
3728 case KRB5KDC_ERR_PREAUTH_FAILED:
3729 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3730 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3731 serverReachable = TRUE;
3734 serverReachable = FALSE;
3739 pkrb5_free_unparsed_name(ctx,pname);
3741 pkrb5_free_principal(ctx,principal);
3743 pkrb5_cc_close(ctx,cc);
3745 pkrb5_free_context(ctx);
3747 return serverReachable;
3751 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
3753 krb5_context ctx = NULL;
3754 krb5_error_code code;
3755 krb5_ccache mslsa_ccache=NULL;
3756 krb5_principal princ = NULL;
3757 char * pname = NULL;
3760 if (!KFW_is_available())
3763 if (code = pkrb5_init_context(&ctx))
3766 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3769 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3772 if (code = pkrb5_unparse_name(ctx, princ, &pname))
3775 if ( strlen(pname) < *dwSize ) {
3776 StringCbCopyN(szUser, *dwSize, pname, (*dwSize) - 1);
3779 *dwSize = (DWORD)strlen(pname);
3783 pkrb5_free_unparsed_name(ctx, pname);
3786 pkrb5_free_principal(ctx, princ);
3789 pkrb5_cc_close(ctx, mslsa_ccache);
3792 pkrb5_free_context(ctx);
3797 KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
3799 // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
3800 PSID pSystemSID = NULL;
3801 DWORD SystemSIDlength = 0, UserSIDlength = 0;
3802 PACL ccacheACL = NULL;
3803 DWORD ccacheACLlength = 0;
3804 PTOKEN_USER pTokenUser = NULL;
3813 /* Get System SID */
3814 if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
3820 SystemSIDlength = GetLengthSid(pSystemSID);
3821 ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
3822 + SystemSIDlength - sizeof(DWORD);
3825 if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
3827 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
3828 pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
3830 GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
3835 UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
3837 ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
3842 ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
3847 InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
3848 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3849 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3852 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3853 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3854 pTokenUser->User.Sid);
3855 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3856 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3861 gle = GetLastError();
3862 if (gle != ERROR_NO_TOKEN)
3865 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3866 OWNER_SECURITY_INFORMATION,
3867 pTokenUser->User.Sid,
3871 gle = GetLastError();
3872 if (gle != ERROR_NO_TOKEN)
3876 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3877 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3882 gle = GetLastError();
3883 if (gle != ERROR_NO_TOKEN)
3890 LocalFree(pSystemSID);
3892 LocalFree(pTokenUser);
3894 LocalFree(ccacheACL);
3899 KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
3902 DWORD dwSize = size-1; /* leave room for nul */
3905 if (!hUserToken || !newfilename || size <= 0)
3908 *newfilename = '\0';
3910 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
3911 if ( !dwLen || dwLen > dwSize )
3912 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
3913 if ( !dwLen || dwLen > dwSize )
3916 newfilename[dwSize] = '\0';
3921 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
3923 char filename[MAX_PATH] = "";
3925 char cachename[MAX_PATH + 8] = "FILE:";
3926 krb5_context ctx = NULL;
3927 krb5_error_code code;
3928 krb5_principal princ = NULL;
3929 krb5_ccache cc = NULL;
3930 krb5_ccache ncc = NULL;
3932 if (!pkrb5_init_context || !user || !szLogonId)
3935 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
3936 if ( count > sizeof(filename) || count == 0 ) {
3937 GetWindowsDirectory(filename, sizeof(filename));
3940 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
3943 StringCbCat( filename, sizeof(filename), "\\");
3944 StringCbCat( filename, sizeof(filename), szLogonId);
3946 StringCbCat( cachename, sizeof(cachename), filename);
3948 DeleteFile(filename);
3950 code = pkrb5_init_context(&ctx);
3951 if (code) goto cleanup;
3953 code = pkrb5_parse_name(ctx, user, &princ);
3954 if (code) goto cleanup;
3956 code = KFW_get_ccache(ctx, princ, &cc);
3957 if (code) goto cleanup;
3959 code = pkrb5_cc_resolve(ctx, cachename, &ncc);
3960 if (code) goto cleanup;
3962 code = pkrb5_cc_initialize(ctx, ncc, princ);
3963 if (code) goto cleanup;
3965 code = KFW_AFS_set_file_cache_dacl(filename, NULL);
3966 if (code) goto cleanup;
3968 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3972 pkrb5_cc_close(ctx, cc);
3976 pkrb5_cc_close(ctx, ncc);
3980 pkrb5_free_principal(ctx, princ);
3985 pkrb5_free_context(ctx);
3989 KFW_AFS_copy_file_cache_to_default_cache(char * filename)
3991 char cachename[MAX_PATH + 8] = "FILE:";
3992 krb5_context ctx = NULL;
3993 krb5_error_code code;
3994 krb5_principal princ = NULL;
3995 krb5_ccache cc = NULL;
3996 krb5_ccache ncc = NULL;
3999 if (!pkrb5_init_context || !filename)
4002 if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
4005 code = pkrb5_init_context(&ctx);
4008 StringCbCat( cachename, sizeof(cachename), filename);
4010 code = pkrb5_cc_resolve(ctx, cachename, &cc);
4011 if (code) goto cleanup;
4013 code = pkrb5_cc_get_principal(ctx, cc, &princ);
4015 code = pkrb5_cc_default(ctx, &ncc);
4017 code = pkrb5_cc_initialize(ctx, ncc, princ);
4020 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
4023 pkrb5_cc_close(ctx, ncc);
4027 retval=0; /* success */
4031 pkrb5_cc_close(ctx, cc);
4035 DeleteFile(filename);
4038 pkrb5_free_principal(ctx, princ);
4043 pkrb5_free_context(ctx);
4048 /* We are including this
4050 /* Ticket lifetime. This defines the table used to lookup lifetime for the
4051 fixed part of rande of the one byte lifetime field. Values less than 0x80
4052 are intrpreted as the number of 5 minute intervals. Values from 0x80 to
4053 0xBF should be looked up in this table. The value of 0x80 is the same using
4054 both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days.
4055 The intervening values of have a fixed ratio of roughly 1.06914. The value
4056 oxFF is defined to mean a ticket has no expiration time. This should be
4057 used advisedly since individual servers may impose defacto upperbounds on
4058 ticket lifetimes. */
4060 #define TKTLIFENUMFIXED 64
4061 #define TKTLIFEMINFIXED 0x80
4062 #define TKTLIFEMAXFIXED 0xBF
4063 #define TKTLIFENOEXPIRE 0xFF
4064 #define MAXTKTLIFETIME (30*24*3600) /* 30 days */
4066 static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
4067 38400, /* 10.67 hours, 0.44 days */
4068 41055, /* 11.40 hours, 0.48 days */
4069 43894, /* 12.19 hours, 0.51 days */
4070 46929, /* 13.04 hours, 0.54 days */
4071 50174, /* 13.94 hours, 0.58 days */
4072 53643, /* 14.90 hours, 0.62 days */
4073 57352, /* 15.93 hours, 0.66 days */
4074 61318, /* 17.03 hours, 0.71 days */
4075 65558, /* 18.21 hours, 0.76 days */
4076 70091, /* 19.47 hours, 0.81 days */
4077 74937, /* 20.82 hours, 0.87 days */
4078 80119, /* 22.26 hours, 0.93 days */
4079 85658, /* 23.79 hours, 0.99 days */
4080 91581, /* 25.44 hours, 1.06 days */
4081 97914, /* 27.20 hours, 1.13 days */
4082 104684, /* 29.08 hours, 1.21 days */
4083 111922, /* 31.09 hours, 1.30 days */
4084 119661, /* 33.24 hours, 1.38 days */
4085 127935, /* 35.54 hours, 1.48 days */
4086 136781, /* 37.99 hours, 1.58 days */
4087 146239, /* 40.62 hours, 1.69 days */
4088 156350, /* 43.43 hours, 1.81 days */
4089 167161, /* 46.43 hours, 1.93 days */
4090 178720, /* 49.64 hours, 2.07 days */
4091 191077, /* 53.08 hours, 2.21 days */
4092 204289, /* 56.75 hours, 2.36 days */
4093 218415, /* 60.67 hours, 2.53 days */
4094 233517, /* 64.87 hours, 2.70 days */
4095 249664, /* 69.35 hours, 2.89 days */
4096 266926, /* 74.15 hours, 3.09 days */
4097 285383, /* 79.27 hours, 3.30 days */
4098 305116, /* 84.75 hours, 3.53 days */
4099 326213, /* 90.61 hours, 3.78 days */
4100 348769, /* 96.88 hours, 4.04 days */
4101 372885, /* 103.58 hours, 4.32 days */
4102 398668, /* 110.74 hours, 4.61 days */
4103 426234, /* 118.40 hours, 4.93 days */
4104 455705, /* 126.58 hours, 5.27 days */
4105 487215, /* 135.34 hours, 5.64 days */
4106 520904, /* 144.70 hours, 6.03 days */
4107 556921, /* 154.70 hours, 6.45 days */
4108 595430, /* 165.40 hours, 6.89 days */
4109 636601, /* 176.83 hours, 7.37 days */
4110 680618, /* 189.06 hours, 7.88 days */
4111 727680, /* 202.13 hours, 8.42 days */
4112 777995, /* 216.11 hours, 9.00 days */
4113 831789, /* 231.05 hours, 9.63 days */
4114 889303, /* 247.03 hours, 10.29 days */
4115 950794, /* 264.11 hours, 11.00 days */
4116 1016537, /* 282.37 hours, 11.77 days */
4117 1086825, /* 301.90 hours, 12.58 days */
4118 1161973, /* 322.77 hours, 13.45 days */
4119 1242318, /* 345.09 hours, 14.38 days */
4120 1328218, /* 368.95 hours, 15.37 days */
4121 1420057, /* 394.46 hours, 16.44 days */
4122 1518247, /* 421.74 hours, 17.57 days */
4123 1623226, /* 450.90 hours, 18.79 days */
4124 1735464, /* 482.07 hours, 20.09 days */
4125 1855462, /* 515.41 hours, 21.48 days */
4126 1983758, /* 551.04 hours, 22.96 days */
4127 2120925, /* 589.15 hours, 24.55 days */
4128 2267576, /* 629.88 hours, 26.25 days */
4129 2424367, /* 673.44 hours, 28.06 days */
4131 }; /* 720.00 hours, 30.00 days */
4133 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
4134 * returns the corresponding end time. There are four simple cases to be
4135 * handled. The first is a life of 0xff, meaning no expiration, and results in
4136 * an end time of 0xffffffff. The second is when life is less than the values
4137 * covered by the table. In this case, the end time is the start time plus the
4138 * number of 5 minute intervals specified by life. The third case returns
4139 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
4140 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
4141 * table to extract the lifetime in seconds, which is added to start to produce
4145 life_to_time(afs_uint32 start, unsigned char life)
4149 if (life == TKTLIFENOEXPIRE)
4151 if (life < TKTLIFEMINFIXED)
4152 return start + life * 5 * 60;
4153 if (life > TKTLIFEMAXFIXED)
4154 return start + MAXTKTLIFETIME;
4155 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
4156 return start + realLife;
4159 /* time_to_life - takes start and end times for the ticket and returns a
4160 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
4161 * lifetimes above 127*5minutes. First, the special case of (end ==
4162 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
4163 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
4164 * less than the first table entry are handled by rounding the requested
4165 * lifetime *up* to the next 5 minute interval. The final step is to search
4166 * the table for the smallest entry *greater than or equal* to the requested
4167 * entry. The actual code is prepared to handle the case where the table is
4168 * unordered but that it an unnecessary frill. */
4170 static unsigned char
4171 time_to_life(afs_uint32 start, afs_uint32 end)
4173 int lifetime = end - start;
4177 if (end == NEVERDATE)
4178 return TKTLIFENOEXPIRE;
4179 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
4181 if (lifetime < tkt_lifetimes[0])
4182 return (lifetime + 5 * 60 - 1) / (5 * 60);
4184 best = MAXKTCTICKETLIFETIME;
4185 for (i = 0; i < TKTLIFENUMFIXED; i++)
4186 if (tkt_lifetimes[i] >= lifetime) {
4187 int diff = tkt_lifetimes[i] - lifetime;
4195 return best_i + TKTLIFEMINFIXED;