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);
775 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
776 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
778 // we found the ticket we are looking for
779 // check validity of timestamp
780 // We add a 5 minutes fudge factor to compensate for potential
781 // clock skew errors between the KDC and client OS
783 valid = ((creds.times.starttime > 0) &&
784 now >= (creds.times.starttime - 300) &&
785 now < (creds.times.endtime + 300) &&
786 !(creds.ticket_flags & TKT_FLG_INVALID));
788 if ( next->from_lsa) {
790 next->expiration_time = creds.times.endtime;
792 } else if ( valid ) {
794 next->expiration_time = creds.times.endtime;
795 next->renew = (creds.times.renew_till > creds.times.endtime) &&
796 (creds.ticket_flags & TKT_FLG_RENEWABLE);
799 next->expiration_time = 0;
803 pkrb5_free_cred_contents(ctx, &creds);
804 cc_code = KRB5_CC_END;
807 pkrb5_free_cred_contents(ctx, &creds);
810 if (cc_code == KRB5_CC_END) {
811 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
812 if (code) goto cleanup;
816 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
817 code = pkrb5_cc_set_flags(ctx, cc, flags);
822 pkrb5_free_unparsed_name(ctx,pname);
824 pkrb5_free_principal(ctx,principal);
828 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
830 struct principal_ccache_data * next = princ_cc_data;
831 char * response = NULL;
833 if ( !principal || !ccache )
837 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
839 // we always want to prefer the MS Kerberos LSA cache or
840 // the cache afscreds created specifically for the principal
841 // if the current entry is either one, drop the previous find
842 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
845 response = _strdup(next->ccache_name);
846 // MS Kerberos LSA is our best option so use it and quit
847 if ( next->from_lsa )
861 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
863 struct principal_ccache_data ** next = &princ_cc_data;
865 if ( !pname && !ccname )
869 if ( !strcmp((*next)->principal,pname) ||
870 !strcmp((*next)->ccache_name,ccname) ) {
872 free((*next)->principal);
873 free((*next)->ccache_name);
875 (*next) = (*next)->next;
882 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
884 struct cell_principal_map * next = cell_princ_map;
886 // Search the existing list to see if we have a match
888 for ( ; next ; next = next->next ) {
889 if ( !strcmp(next->cell, cell) ) {
890 if ( !strcmp(next->principal,pname) ) {
891 next->active = active;
894 // OpenAFS currently has a restriction of one active token per cell
895 // Therefore, whenever we update the table with a new active cell we
896 // must mark all of the other principal to cell entries as inactive.
904 // If not, match add a new node to the beginning of the list and assign init it
906 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
907 next->next = cell_princ_map;
908 cell_princ_map = next;
909 next->principal = _strdup(pname);
910 next->cell = _strdup(cell);
911 next->active = active;
916 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
918 struct cell_principal_map ** next = &cell_princ_map;
920 if ( !pname && !cell )
924 if ( !strcmp((*next)->principal,pname) ||
925 !strcmp((*next)->cell,cell) ) {
927 free((*next)->principal);
930 (*next) = (*next)->next;
936 // Returns (if possible) a principal which has been known in
937 // the past to have been used to obtain tokens for the specified
939 // TODO: Attempt to return one which has not yet expired by checking
940 // the principal/ccache data
942 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
944 struct cell_principal_map * next_map = cell_princ_map;
945 const char * princ = NULL;
952 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
955 next_map = next_map->next;
958 if ( !principals || !count )
961 *principals = (char **) malloc(sizeof(char *) * count);
962 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
964 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
965 (*principals)[i++] = _strdup(next_map->principal);
972 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
975 struct cell_principal_map * next_map = cell_princ_map;
976 const char * princ = NULL;
982 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
985 next_map = next_map->next;
991 *cells = (char **) malloc(sizeof(char *) * count);
992 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
994 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
995 (*cells)[i++] = _strdup(next_map->cell);
1001 /* Given a principal return an existing ccache or create one and return */
1003 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
1005 krb5_context ctx = NULL;
1006 char * pname = NULL;
1007 char * ccname = NULL;
1008 krb5_error_code code;
1010 if (!pkrb5_init_context)
1016 code = pkrb5_init_context(&ctx);
1017 if (code) goto cleanup;
1021 code = pkrb5_unparse_name(ctx, principal, &pname);
1022 if (code) goto cleanup;
1024 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
1025 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
1026 size_t len = strlen(pname) + 5;
1027 ccname = (char *)malloc(len);
1028 StringCbPrintf(ccname, len, "API:%s", pname);
1030 code = pkrb5_cc_resolve(ctx, ccname, cc);
1032 code = pkrb5_cc_default(ctx, cc);
1033 if (code) goto cleanup;
1040 pkrb5_free_unparsed_name(ctx,pname);
1041 if (ctx && (ctx != alt_ctx))
1042 pkrb5_free_context(ctx);
1047 // Import Microsoft Credentials into a new MIT ccache
1049 KFW_import_windows_lsa(void)
1051 krb5_context ctx = NULL;
1052 krb5_ccache cc = NULL;
1053 krb5_principal princ = NULL;
1054 char * pname = NULL;
1055 krb5_data * princ_realm;
1056 krb5_error_code code;
1057 char cell[128]="", realm[128]="", *def_realm = 0;
1059 DWORD dwMsLsaImport;
1061 if (!pkrb5_init_context)
1064 code = pkrb5_init_context(&ctx);
1065 if (code) goto cleanup;
1067 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
1068 if (code) goto cleanup;
1070 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
1072 code = pkrb5_cc_get_principal(ctx, cc, &princ);
1073 if ( code ) goto cleanup;
1076 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
1080 switch ( dwMsLsaImport ) {
1081 case 0: /* do not import */
1083 case 1: /* always import */
1085 case 2: { /* matching realm */
1086 char ms_realm[128] = "", *r;
1089 for ( r=ms_realm, j=0; j<krb5_princ_realm(ctx, princ)->length; r++, j++ ) {
1090 *r = krb5_princ_realm(ctx, princ)->data[j];
1094 if (code = pkrb5_get_default_realm(ctx, &def_realm))
1097 if (strcmp(def_realm, ms_realm))
1105 code = pkrb5_unparse_name(ctx,princ,&pname);
1106 if ( code ) goto cleanup;
1108 princ_realm = krb5_princ_realm(ctx, princ);
1109 for ( i=0; i<princ_realm->length; i++ ) {
1110 realm[i] = princ_realm->data[i];
1111 cell[i] = tolower(princ_realm->data[i]);
1116 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, DEFAULT_LIFETIME, NULL);
1117 if ( IsDebuggerPresent() ) {
1119 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1120 OutputDebugString(message);
1122 if ( code ) goto cleanup;
1124 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1128 pkrb5_free_unparsed_name(ctx,pname);
1130 pkrb5_free_principal(ctx,princ);
1132 pkrb5_free_default_realm(ctx, def_realm);
1134 pkrb5_cc_close(ctx,cc);
1136 pkrb5_free_context(ctx);
1138 #endif /* USE_MS2MIT */
1140 // If there are existing MIT credentials, copy them to a new
1141 // ccache named after the principal
1143 // Enumerate all existing MIT ccaches and construct entries
1144 // in the principal_ccache table
1146 // Enumerate all existing AFS Tokens and construct entries
1147 // in the cell_principal table
1149 KFW_import_ccache_data(void)
1151 krb5_context ctx = NULL;
1152 krb5_ccache cc = NULL;
1153 krb5_principal principal = NULL;
1155 krb5_error_code code;
1156 krb5_error_code cc_code;
1158 apiCB * cc_ctx = NULL;
1159 struct _infoNC ** pNCi = NULL;
1162 if ( !pcc_initialize )
1165 if ( IsDebuggerPresent() )
1166 OutputDebugString("KFW_import_ccache_data()\n");
1168 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1169 if (code) goto cleanup;
1171 code = pcc_get_NC_info(cc_ctx, &pNCi);
1172 if (code) goto cleanup;
1174 code = pkrb5_init_context(&ctx);
1175 if (code) goto cleanup;
1177 for ( i=0; pNCi[i]; i++ ) {
1178 if ( pNCi[i]->vers != CC_CRED_V5 )
1180 if ( IsDebuggerPresent() ) {
1181 OutputDebugString("Principal: ");
1182 OutputDebugString(pNCi[i]->principal);
1183 OutputDebugString(" in ccache ");
1184 OutputDebugString(pNCi[i]->name);
1185 OutputDebugString("\n");
1187 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1188 && strcmp(pNCi[i]->name,LSA_CCNAME)
1191 for ( j=0; pNCi[j]; j++ ) {
1192 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1198 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1199 if (code) goto loop_cleanup;
1202 krb5_ccache oldcc = 0;
1204 if ( IsDebuggerPresent() )
1205 OutputDebugString("copying ccache data to new ccache\n");
1207 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1208 if (code) goto loop_cleanup;
1209 code = pkrb5_cc_initialize(ctx, cc, principal);
1210 if (code) goto loop_cleanup;
1212 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1213 if (code) goto loop_cleanup;
1214 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1216 code = pkrb5_cc_close(ctx,cc);
1218 code = pkrb5_cc_close(ctx,oldcc);
1220 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1223 code = pkrb5_cc_close(ctx,oldcc);
1226 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1227 if (code) goto loop_cleanup;
1230 flags = 0; // turn off OPENCLOSE mode
1231 code = pkrb5_cc_set_flags(ctx, cc, flags);
1232 if ( code ) goto cleanup;
1234 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1236 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1238 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1239 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1240 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1241 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1242 if ( sname && cell && !strcmp("afs",sname->data) ) {
1243 struct ktc_principal aserver;
1244 struct ktc_principal aclient;
1245 struct ktc_token atoken;
1248 if ( IsDebuggerPresent() ) {
1249 OutputDebugString("Found AFS ticket: ");
1250 OutputDebugString(sname->data);
1252 OutputDebugString("/");
1253 OutputDebugString(cell->data);
1255 OutputDebugString("@");
1256 OutputDebugString(realm->data);
1257 OutputDebugString("\n");
1260 memset(&aserver, '\0', sizeof(aserver));
1261 StringCbCopyN( aserver.name, sizeof(aserver.name),
1262 sname->data, sizeof(aserver.name) - 1);
1263 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
1264 cell->data, sizeof(aserver.cell) - 1);
1266 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1268 // Found a token in AFS Client Server which matches
1269 char pname[128], *p, *q;
1270 for ( p=pname, q=aclient.name; *q; p++, q++)
1272 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1276 if ( IsDebuggerPresent() ) {
1277 OutputDebugString("Found AFS token: ");
1278 OutputDebugString(pname);
1279 OutputDebugString("\n");
1282 if ( strcmp(pname,pNCi[i]->principal) )
1284 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1286 // Attempt to import it
1287 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1289 if ( IsDebuggerPresent() ) {
1290 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1293 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data, DEFAULT_LIFETIME, NULL);
1294 if ( IsDebuggerPresent() ) {
1296 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1297 OutputDebugString(message);
1300 } else if ( IsDebuggerPresent() ) {
1301 OutputDebugString("Found ticket: ");
1302 OutputDebugString(sname->data);
1303 if ( cell && cell->data ) {
1304 OutputDebugString("/");
1305 OutputDebugString(cell->data);
1307 OutputDebugString("@");
1308 OutputDebugString(realm->data);
1309 OutputDebugString("\n");
1311 pkrb5_free_cred_contents(ctx, &creds);
1314 if (cc_code == KRB5_CC_END) {
1315 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1316 if (cc_code) goto loop_cleanup;
1320 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1321 code = pkrb5_cc_set_flags(ctx, cc, flags);
1323 pkrb5_cc_close(ctx,cc);
1327 pkrb5_free_principal(ctx,principal);
1334 pkrb5_free_context(ctx);
1336 pcc_free_NC_info(cc_ctx, &pNCi);
1338 pcc_shutdown(&cc_ctx);
1343 KFW_AFS_get_cred( char * username,
1350 static char reason[1024]="";
1351 krb5_context ctx = NULL;
1352 krb5_ccache cc = NULL;
1353 char * realm = NULL, * userrealm = NULL;
1354 krb5_principal principal = NULL;
1355 char * pname = NULL;
1356 krb5_error_code code;
1357 char local_cell[CELL_MAXNAMELEN+1];
1358 char **cells = NULL;
1360 struct afsconf_cell cellconfig;
1363 if (!pkrb5_init_context)
1366 if ( IsDebuggerPresent() ) {
1367 OutputDebugString("KFW_AFS_get_cred for token ");
1368 OutputDebugString(username);
1369 OutputDebugString(" in cell ");
1370 OutputDebugString(cell);
1371 OutputDebugString("\n");
1374 memset(&cellconfig, 0, sizeof(cellconfig));
1376 code = pkrb5_init_context(&ctx);
1377 if ( code ) goto cleanup;
1379 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1380 if ( code ) goto cleanup;
1382 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1384 userrealm = strchr(username,'@');
1386 pname = strdup(username);
1387 if (!KFW_accept_dotted_usernames()) {
1388 userrealm = strchr(pname, '@');
1391 /* handle kerberos iv notation */
1392 while ( dot = strchr(pname,'.') ) {
1398 size_t len = strlen(username) + strlen(realm) + 2;
1399 pname = malloc(len);
1400 if (pname == NULL) {
1401 code = KRB5KRB_ERR_GENERIC;
1404 StringCbCopy(pname, len, username);
1406 if (!KFW_accept_dotted_usernames()) {
1407 /* handle kerberos iv notation */
1408 while ( dot = strchr(pname,'.') ) {
1412 StringCbCat( pname, len, "@");
1413 StringCbCat( pname, len, realm);
1415 if ( IsDebuggerPresent() ) {
1416 OutputDebugString("Realm: ");
1417 OutputDebugString(realm);
1418 OutputDebugString("\n");
1421 code = pkrb5_parse_name(ctx, pname, &principal);
1422 if ( code ) goto cleanup;
1424 code = KFW_get_ccache(ctx, principal, &cc);
1425 if ( code ) goto cleanup;
1427 if ( lifetime == 0 )
1428 lifetime = DEFAULT_LIFETIME;
1430 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1431 if ( IsDebuggerPresent() ) {
1433 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1434 OutputDebugString(message);
1437 if (code && password && password[0] ) {
1438 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1443 0, /* forwardable */
1444 0, /* not proxiable */
1446 1, /* noaddresses */
1447 0 /* no public ip */
1449 pLeash_get_default_forwardable(),
1450 pLeash_get_default_proxiable(),
1451 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1452 pLeash_get_default_noaddresses(),
1453 pLeash_get_default_publicip()
1454 #endif /* USE_LEASH */
1457 if ( IsDebuggerPresent() ) {
1459 StringCbPrintf(message, sizeof(message), "KFW_kinit() returns: %d\n", code);
1460 OutputDebugString(message);
1462 if ( code ) goto cleanup;
1464 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1467 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1468 if ( IsDebuggerPresent() ) {
1470 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1471 OutputDebugString(message);
1473 if ( code ) goto cleanup;
1475 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1477 // Attempt to obtain new tokens for other cells supported by the same
1479 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1480 if ( cell_count > 1 ) {
1481 while ( cell_count-- ) {
1482 if ( strcmp(cells[cell_count],cell) ) {
1483 if ( IsDebuggerPresent() ) {
1485 StringCbPrintf(message, sizeof(message),
1486 "found another cell for the same principal: %s\n", cell);
1487 OutputDebugString(message);
1490 if (cellconfig.linkedCell) {
1491 free(cellconfig.linkedCell);
1492 cellconfig.linkedCell = NULL;
1494 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1495 if ( code ) continue;
1497 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1498 if ( IsDebuggerPresent() ) {
1499 OutputDebugString("Realm: ");
1500 OutputDebugString(realm);
1501 OutputDebugString("\n");
1504 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1505 if ( IsDebuggerPresent() ) {
1507 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1508 OutputDebugString(message);
1511 free(cells[cell_count]);
1514 } else if ( cell_count == 1 ) {
1523 pkrb5_cc_close(ctx, cc);
1524 if ( cellconfig.linkedCell )
1525 free(cellconfig.linkedCell);
1527 if ( code && reasonP ) {
1528 if (pkrb5_get_error_message) {
1529 char *msg = pkrb5_get_error_message(ctx, code);
1530 StringCbCopyN( reason, sizeof(reason),
1531 msg, sizeof(reason) - 1);
1533 pkrb5_free_error_message(ctx, msg);
1535 *reasonP = perror_message(code);
1542 KFW_AFS_destroy_tickets_for_cell(char * cell)
1544 krb5_context ctx = NULL;
1545 krb5_error_code code;
1547 char ** principals = NULL;
1549 if (!pkrb5_init_context)
1552 if ( IsDebuggerPresent() ) {
1553 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1554 OutputDebugString(cell);
1555 OutputDebugString("\n");
1558 code = pkrb5_init_context(&ctx);
1561 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1563 krb5_principal princ = 0;
1567 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1568 if ( cell_count > 1 ) {
1569 // TODO - What we really should do here is verify whether or not any of the
1570 // other cells which use this principal to obtain its credentials actually
1571 // have valid tokens or not. If they are currently using these credentials
1572 // we will skip them. For the time being we assume that if there is an active
1573 // map in the table that they are actively being used.
1577 code = pkrb5_parse_name(ctx, principals[count], &princ);
1578 if (code) goto loop_cleanup;
1580 code = KFW_get_ccache(ctx, princ, &cc);
1581 if (code) goto loop_cleanup;
1583 code = pkrb5_cc_destroy(ctx, cc);
1588 pkrb5_cc_close(ctx, cc);
1592 pkrb5_free_principal(ctx, princ);
1596 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1597 free(principals[count]);
1602 pkrb5_free_context(ctx);
1607 KFW_AFS_destroy_tickets_for_principal(char * user)
1609 krb5_context ctx = NULL;
1610 krb5_error_code code;
1612 char ** cells = NULL;
1613 krb5_principal princ = NULL;
1614 krb5_ccache cc = NULL;
1616 if (!pkrb5_init_context)
1619 if ( IsDebuggerPresent() ) {
1620 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1621 OutputDebugString(user);
1622 OutputDebugString("\n");
1625 code = pkrb5_init_context(&ctx);
1628 code = pkrb5_parse_name(ctx, user, &princ);
1629 if (code) goto loop_cleanup;
1631 code = KFW_get_ccache(ctx, princ, &cc);
1632 if (code) goto loop_cleanup;
1634 code = pkrb5_cc_destroy(ctx, cc);
1639 pkrb5_cc_close(ctx, cc);
1643 pkrb5_free_principal(ctx, princ);
1647 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1650 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1657 pkrb5_free_context(ctx);
1662 KFW_AFS_renew_expiring_tokens(void)
1664 krb5_error_code code = 0;
1665 krb5_context ctx = NULL;
1666 krb5_ccache cc = NULL;
1668 struct principal_ccache_data * pcc_next = princ_cc_data;
1671 const char * realm = NULL;
1672 char local_cell[CELL_MAXNAMELEN+1]="";
1673 struct afsconf_cell cellconfig;
1675 if (!pkrb5_init_context)
1678 if ( pcc_next == NULL ) // nothing to do
1681 if ( IsDebuggerPresent() ) {
1682 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1685 memset(&cellconfig, 0, sizeof(cellconfig));
1687 code = pkrb5_init_context(&ctx);
1688 if (code) goto cleanup;
1690 code = pkrb5_timeofday(ctx, &now);
1691 if (code) goto cleanup;
1693 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1694 if ( pcc_next->expired )
1697 if ( now >= (pcc_next->expiration_time) ) {
1698 if ( !pcc_next->from_lsa ) {
1699 pcc_next->expired = 1;
1704 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1705 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1708 code = KFW_renew(ctx,cc);
1710 if ( code && pcc_next->from_lsa)
1712 #endif /* USE_MS2MIT */
1715 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1716 if (code) goto loop_cleanup;
1718 // Attempt to obtain new tokens for other cells supported by the same
1720 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1721 if ( cell_count > 0 ) {
1722 while ( cell_count-- ) {
1723 if ( IsDebuggerPresent() ) {
1724 OutputDebugString("Cell: ");
1725 OutputDebugString(cells[cell_count]);
1726 OutputDebugString("\n");
1728 if (cellconfig.linkedCell) {
1729 free(cellconfig.linkedCell);
1730 cellconfig.linkedCell = NULL;
1732 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1733 if ( code ) continue;
1734 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1735 if ( IsDebuggerPresent() ) {
1736 OutputDebugString("Realm: ");
1737 OutputDebugString(realm);
1738 OutputDebugString("\n");
1740 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1741 if ( IsDebuggerPresent() ) {
1743 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1744 OutputDebugString(message);
1746 free(cells[cell_count]);
1754 pkrb5_cc_close(ctx,cc);
1761 pkrb5_cc_close(ctx,cc);
1763 pkrb5_free_context(ctx);
1764 if (cellconfig.linkedCell)
1765 free(cellconfig.linkedCell);
1772 KFW_AFS_renew_token_for_cell(char * cell)
1774 krb5_error_code code = 0;
1775 krb5_context ctx = NULL;
1777 char ** principals = NULL;
1779 if (!pkrb5_init_context)
1782 if ( IsDebuggerPresent() ) {
1783 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1784 OutputDebugString(cell);
1785 OutputDebugString("\n");
1788 code = pkrb5_init_context(&ctx);
1789 if (code) goto cleanup;
1791 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1793 // We know we must have a credential somewhere since we are
1794 // trying to renew a token
1796 KFW_import_ccache_data();
1797 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1800 krb5_principal princ = 0;
1801 krb5_principal service = 0;
1803 krb5_creds mcreds, creds;
1804 #endif /* COMMENT */
1806 const char * realm = NULL;
1807 struct afsconf_cell cellconfig;
1808 char local_cell[CELL_MAXNAMELEN+1];
1810 memset(&cellconfig, 0, sizeof(cellconfig));
1813 code = pkrb5_parse_name(ctx, principals[count], &princ);
1814 if (code) goto loop_cleanup;
1816 code = KFW_get_ccache(ctx, princ, &cc);
1817 if (code) goto loop_cleanup;
1819 if (cellconfig.linkedCell) {
1820 free(cellconfig.linkedCell);
1821 cellconfig.linkedCell = NULL;
1823 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1824 if ( code ) goto loop_cleanup;
1826 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1827 if ( IsDebuggerPresent() ) {
1828 OutputDebugString("Realm: ");
1829 OutputDebugString(realm);
1830 OutputDebugString("\n");
1834 /* krb5_cc_remove_cred() is not implemented
1837 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1838 realm, "afs", cell, NULL);
1840 memset(&mcreds, 0, sizeof(krb5_creds));
1841 mcreds.client = princ;
1842 mcreds.server = service;
1844 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1846 if ( IsDebuggerPresent() ) {
1847 char * cname, *sname;
1848 pkrb5_unparse_name(ctx, creds.client, &cname);
1849 pkrb5_unparse_name(ctx, creds.server, &sname);
1850 OutputDebugString("Removing credential for client \"");
1851 OutputDebugString(cname);
1852 OutputDebugString("\" and service \"");
1853 OutputDebugString(sname);
1854 OutputDebugString("\"\n");
1855 pkrb5_free_unparsed_name(ctx,cname);
1856 pkrb5_free_unparsed_name(ctx,sname);
1859 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1860 pkrb5_free_principal(ctx, creds.client);
1861 pkrb5_free_principal(ctx, creds.server);
1864 #endif /* COMMENT */
1866 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1867 if ( IsDebuggerPresent() ) {
1869 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1870 OutputDebugString(message);
1875 pkrb5_cc_close(ctx, cc);
1879 pkrb5_free_principal(ctx, princ);
1883 pkrb5_free_principal(ctx, service);
1886 if (cellconfig.linkedCell) {
1887 free(cellconfig.linkedCell);
1888 cellconfig.linkedCell = NULL;
1891 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1892 free(principals[count]);
1896 code = -1; // we did not renew the tokens
1900 pkrb5_free_context(ctx);
1901 return (code ? FALSE : TRUE);
1906 KFW_AFS_renew_tokens_for_all_cells(void)
1908 struct cell_principal_map * next = cell_princ_map;
1910 if ( IsDebuggerPresent() )
1911 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1916 for ( ; next ; next = next->next ) {
1918 KFW_AFS_renew_token_for_cell(next->cell);
1924 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1926 krb5_error_code code = 0;
1927 krb5_context ctx = NULL;
1928 krb5_ccache cc = NULL;
1929 krb5_principal me = NULL;
1930 krb5_principal server = NULL;
1931 krb5_creds my_creds;
1932 krb5_data *realm = NULL;
1934 if (!pkrb5_init_context)
1937 memset(&my_creds, 0, sizeof(krb5_creds));
1942 code = pkrb5_init_context(&ctx);
1943 if (code) goto cleanup;
1949 code = pkrb5_cc_default(ctx, &cc);
1950 if (code) goto cleanup;
1953 code = pkrb5_cc_get_principal(ctx, cc, &me);
1954 if (code) goto cleanup;
1956 realm = krb5_princ_realm(ctx, me);
1958 code = pkrb5_build_principal_ext(ctx, &server,
1959 realm->length,realm->data,
1960 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1961 realm->length,realm->data,
1966 if ( IsDebuggerPresent() ) {
1967 char * cname, *sname;
1968 pkrb5_unparse_name(ctx, me, &cname);
1969 pkrb5_unparse_name(ctx, server, &sname);
1970 OutputDebugString("Renewing credential for client \"");
1971 OutputDebugString(cname);
1972 OutputDebugString("\" and service \"");
1973 OutputDebugString(sname);
1974 OutputDebugString("\"\n");
1975 pkrb5_free_unparsed_name(ctx,cname);
1976 pkrb5_free_unparsed_name(ctx,sname);
1979 my_creds.client = me;
1980 my_creds.server = server;
1982 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1984 if ( IsDebuggerPresent() ) {
1986 StringCbPrintf(message, sizeof(message), "krb5_get_renewed_creds() failed: %d\n", code);
1987 OutputDebugString(message);
1992 code = pkrb5_cc_initialize(ctx, cc, me);
1994 if ( IsDebuggerPresent() ) {
1996 StringCbPrintf(message, sizeof(message), "krb5_cc_initialize() failed: %d\n", code);
1997 OutputDebugString(message);
2002 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2004 if ( IsDebuggerPresent() ) {
2006 StringCbPrintf(message, sizeof(message), "krb5_cc_store_cred() failed: %d\n", code);
2007 OutputDebugString(message);
2013 if (my_creds.client == me)
2014 my_creds.client = 0;
2015 if (my_creds.server == server)
2016 my_creds.server = 0;
2017 pkrb5_free_cred_contents(ctx, &my_creds);
2019 pkrb5_free_principal(ctx, me);
2021 pkrb5_free_principal(ctx, server);
2022 if (cc && (cc != alt_cc))
2023 pkrb5_cc_close(ctx, cc);
2024 if (ctx && (ctx != alt_ctx))
2025 pkrb5_free_context(ctx);
2030 KFW_kinit( krb5_context alt_ctx,
2033 char *principal_name,
2035 krb5_deltat lifetime,
2038 krb5_deltat renew_life,
2043 krb5_error_code code = 0;
2044 krb5_context ctx = NULL;
2045 krb5_ccache cc = NULL;
2046 krb5_principal me = NULL;
2048 krb5_creds my_creds;
2049 krb5_get_init_creds_opt options;
2050 krb5_address ** addrs = NULL;
2051 int i = 0, addr_count = 0;
2053 if (!pkrb5_init_context)
2056 pkrb5_get_init_creds_opt_init(&options);
2057 memset(&my_creds, 0, sizeof(my_creds));
2065 code = pkrb5_init_context(&ctx);
2066 if (code) goto cleanup;
2072 code = pkrb5_cc_default(ctx, &cc);
2073 if (code) goto cleanup;
2076 code = pkrb5_parse_name(ctx, principal_name, &me);
2080 code = pkrb5_unparse_name(ctx, me, &name);
2085 lifetime = DEFAULT_LIFETIME;
2092 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2093 pkrb5_get_init_creds_opt_set_forwardable(&options,
2094 forwardable ? 1 : 0);
2095 pkrb5_get_init_creds_opt_set_proxiable(&options,
2097 pkrb5_get_init_creds_opt_set_renew_life(&options,
2100 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2104 // we are going to add the public IP address specified by the user
2105 // to the list provided by the operating system
2106 krb5_address ** local_addrs=NULL;
2109 pkrb5_os_localaddr(ctx, &local_addrs);
2110 while ( local_addrs[i++] );
2113 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2115 pkrb5_free_addresses(ctx, local_addrs);
2118 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2120 while ( local_addrs[i] ) {
2121 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2122 if (addrs[i] == NULL) {
2123 pkrb5_free_addresses(ctx, local_addrs);
2127 addrs[i]->magic = local_addrs[i]->magic;
2128 addrs[i]->addrtype = local_addrs[i]->addrtype;
2129 addrs[i]->length = local_addrs[i]->length;
2130 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2131 if (!addrs[i]->contents) {
2132 pkrb5_free_addresses(ctx, local_addrs);
2136 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2137 local_addrs[i]->length); /* safe */
2140 pkrb5_free_addresses(ctx, local_addrs);
2142 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2143 if (addrs[i] == NULL)
2146 addrs[i]->magic = KV5M_ADDRESS;
2147 addrs[i]->addrtype = AF_INET;
2148 addrs[i]->length = 4;
2149 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2150 if (!addrs[i]->contents)
2153 netIPAddr = htonl(publicIP);
2154 memcpy(addrs[i]->contents,&netIPAddr,4);
2156 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2161 code = pkrb5_get_init_creds_password(ctx,
2164 password, // password
2165 KRB5_prompter, // prompter
2166 hParent, // prompter data
2173 code = pkrb5_cc_initialize(ctx, cc, me);
2177 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2183 for ( i=0;i<addr_count;i++ ) {
2185 if ( addrs[i]->contents )
2186 free(addrs[i]->contents);
2191 if (my_creds.client == me)
2192 my_creds.client = 0;
2193 pkrb5_free_cred_contents(ctx, &my_creds);
2195 pkrb5_free_unparsed_name(ctx, name);
2197 pkrb5_free_principal(ctx, me);
2198 if (cc && (cc != alt_cc))
2199 pkrb5_cc_close(ctx, cc);
2200 if (ctx && (ctx != alt_ctx))
2201 pkrb5_free_context(ctx);
2207 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2209 krb5_context ctx = NULL;
2210 krb5_ccache cc = NULL;
2211 krb5_error_code code;
2213 if (!pkrb5_init_context)
2222 code = pkrb5_init_context(&ctx);
2223 if (code) goto cleanup;
2229 code = pkrb5_cc_default(ctx, &cc);
2230 if (code) goto cleanup;
2233 code = pkrb5_cc_destroy(ctx, cc);
2234 if ( !code ) cc = 0;
2237 if (cc && (cc != alt_cc))
2238 pkrb5_cc_close(ctx, cc);
2239 if (ctx && (ctx != alt_ctx))
2240 pkrb5_free_context(ctx);
2248 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2250 NTSTATUS Status = 0;
2252 TOKEN_STATISTICS Stats;
2258 *ppSessionData = NULL;
2260 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2264 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2265 CloseHandle( TokenHandle );
2269 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2270 if ( FAILED(Status) || !ppSessionData )
2277 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2278 // cache. It validates whether or not it is reasonable to assume that if we
2279 // attempted to retrieve valid tickets we could do so. Microsoft does not
2280 // automatically renew expired tickets. Therefore, the cache could contain
2281 // expired or invalid tickets. Microsoft also caches the user's password
2282 // and will use it to retrieve new TGTs if the cache is empty and tickets
2286 MSLSA_IsKerberosLogon(VOID)
2288 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2289 BOOL Success = FALSE;
2291 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2292 if ( pSessionData->AuthenticationPackage.Buffer ) {
2298 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2299 usLength = (pSessionData->AuthenticationPackage).Length;
2302 StringCbCopyNW( buffer, sizeof(buffer)/sizeof(WCHAR),
2303 usBuffer, usLength);
2304 if ( !lstrcmpW(L"Kerberos",buffer) )
2308 pLsaFreeReturnBuffer(pSessionData);
2312 #endif /* USE_MS2MIT */
2314 static BOOL CALLBACK
2315 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2319 switch ( message ) {
2321 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2323 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2326 for ( i=0; i < mid_cnt ; i++ ) {
2327 if (mid_tb[i].echo == 0)
2328 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2329 else if (mid_tb[i].echo == 2)
2330 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2335 switch ( LOWORD(wParam) ) {
2337 for ( i=0; i < mid_cnt ; i++ ) {
2338 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2339 *mid_tb[i].buf = '\0';
2343 EndDialog(hDialog, LOWORD(wParam));
2351 lpwAlign( LPWORD lpIn )
2355 ul = (ULONG_PTR) lpIn;
2359 return (LPWORD) ul;;
2363 * dialog widths are measured in 1/4 character widths
2364 * dialog height are measured in 1/8 character heights
2368 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2369 char * ptext[], int numlines, int width,
2370 int tb_cnt, struct textField * tb)
2374 LPDLGITEMTEMPLATE lpdit;
2380 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2387 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2389 // Define a dialog box.
2391 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2392 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2393 | DS_SETFOREGROUND | DS_3DLOOK
2394 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2395 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2398 lpdt->cx = 20 + width * 4;
2399 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2401 lpw = (LPWORD) (lpdt + 1);
2402 *lpw++ = 0; // no menu
2403 *lpw++ = 0; // predefined dialog box class (by default)
2405 lpwsz = (LPWSTR) lpw;
2406 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2408 *lpw++ = 8; // font size (points)
2409 lpwsz = (LPWSTR) lpw;
2410 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2414 //-----------------------
2415 // Define an OK button.
2416 //-----------------------
2417 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2418 lpdit = (LPDLGITEMTEMPLATE) lpw;
2419 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2420 lpdit->dwExtendedStyle = 0;
2421 lpdit->x = (lpdt->cx - 14)/4 - 20;
2422 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2425 lpdit->id = IDOK; // OK button identifier
2427 lpw = (LPWORD) (lpdit + 1);
2429 *lpw++ = 0x0080; // button class
2431 lpwsz = (LPWSTR) lpw;
2432 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2434 *lpw++ = 0; // no creation data
2436 //-----------------------
2437 // Define an Cancel button.
2438 //-----------------------
2439 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2440 lpdit = (LPDLGITEMTEMPLATE) lpw;
2441 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2442 lpdit->dwExtendedStyle = 0;
2443 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2444 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2447 lpdit->id = IDCANCEL; // CANCEL button identifier
2449 lpw = (LPWORD) (lpdit + 1);
2451 *lpw++ = 0x0080; // button class
2453 lpwsz = (LPWSTR) lpw;
2454 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2456 *lpw++ = 0; // no creation data
2458 /* Add controls for preface data */
2459 for ( i=0; i<numlines; i++) {
2460 /*-----------------------
2461 * Define a static text control.
2462 *-----------------------*/
2463 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2464 lpdit = (LPDLGITEMTEMPLATE) lpw;
2465 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2466 lpdit->dwExtendedStyle = 0;
2468 lpdit->y = 10 + i * 14;
2469 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2471 lpdit->id = ID_TEXT + i; // text identifier
2473 lpw = (LPWORD) (lpdit + 1);
2475 *lpw++ = 0x0082; // static class
2477 lpwsz = (LPWSTR) lpw;
2478 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2479 -1, lpwsz, 2*width);
2481 *lpw++ = 0; // no creation data
2484 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2485 int len = (int)strlen(tb[i].label);
2490 for ( i=0; i<tb_cnt; i++) {
2492 /*-----------------------
2493 * Define a static text control.
2494 *-----------------------*/
2495 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2496 lpdit = (LPDLGITEMTEMPLATE) lpw;
2497 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2498 lpdit->dwExtendedStyle = 0;
2500 lpdit->y = 10 + (numlines + i + 1) * 14;
2501 lpdit->cx = pwid * 4;
2503 lpdit->id = ID_TEXT + numlines + i; // text identifier
2505 lpw = (LPWORD) (lpdit + 1);
2507 *lpw++ = 0x0082; // static class
2509 lpwsz = (LPWSTR) lpw;
2510 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2513 *lpw++ = 0; // no creation data
2515 /*-----------------------
2516 * Define an edit control.
2517 *-----------------------*/
2518 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2519 lpdit = (LPDLGITEMTEMPLATE) lpw;
2520 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2521 lpdit->dwExtendedStyle = 0;
2522 lpdit->x = 10 + (pwid + 1) * 4;
2523 lpdit->y = 10 + (numlines + i + 1) * 14;
2524 lpdit->cx = (width - (pwid + 1)) * 4;
2526 lpdit->id = ID_MID_TEXT + i; // identifier
2528 lpw = (LPWORD) (lpdit + 1);
2530 *lpw++ = 0x0081; // edit class
2532 lpwsz = (LPWSTR) lpw;
2533 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2536 *lpw++ = 0; // no creation data
2540 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2541 hwndOwner, (DLGPROC) MultiInputDialogProc);
2545 case 0: /* Timeout */
2553 StringCbPrintf(buf, sizeof(buf), "DialogBoxIndirect() failed: %d", GetLastError());
2554 MessageBox(hwndOwner,
2557 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2564 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2566 HINSTANCE hInst = 0;
2570 char * plines[16], *p = preface ? preface : "";
2573 for ( i=0; i<16; i++ )
2576 while (*p && numlines < 16) {
2577 plines[numlines++] = p;
2578 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2579 if ( *p == '\r' && *(p+1) == '\n' ) {
2582 } else if ( *p == '\n' ) {
2585 if ( strlen(plines[numlines-1]) > maxwidth )
2586 maxwidth = (int)strlen(plines[numlines-1]);
2589 for ( i=0;i<n;i++ ) {
2590 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2591 if ( maxwidth < len )
2595 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2598 static krb5_error_code KRB5_CALLCONV
2599 KRB5_prompter( krb5_context context,
2604 krb5_prompt prompts[])
2606 krb5_error_code errcode = 0;
2608 struct textField * tb = NULL;
2609 int len = 0, blen=0, nlen=0;
2610 HWND hParent = (HWND)data;
2613 nlen = (int)strlen(name)+2;
2616 blen = (int)strlen(banner)+2;
2618 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2621 memset(tb,0,sizeof(struct textField) * num_prompts);
2622 for ( i=0; i < num_prompts; i++ ) {
2623 tb[i].buf = prompts[i].reply->data;
2624 tb[i].len = prompts[i].reply->length;
2625 tb[i].label = prompts[i].prompt;
2627 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2630 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2632 for ( i=0; i < num_prompts; i++ )
2633 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2641 for (i = 0; i < num_prompts; i++) {
2642 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2649 KFW_AFS_wait_for_service_start(void)
2654 CurrentState = SERVICE_START_PENDING;
2655 memset(HostName, '\0', sizeof(HostName));
2656 gethostname(HostName, sizeof(HostName));
2658 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2660 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2662 if ( IsDebuggerPresent() ) {
2663 switch ( CurrentState ) {
2664 case SERVICE_STOPPED:
2665 OutputDebugString("SERVICE_STOPPED\n");
2667 case SERVICE_START_PENDING:
2668 OutputDebugString("SERVICE_START_PENDING\n");
2670 case SERVICE_STOP_PENDING:
2671 OutputDebugString("SERVICE_STOP_PENDING\n");
2673 case SERVICE_RUNNING:
2674 OutputDebugString("SERVICE_RUNNING\n");
2676 case SERVICE_CONTINUE_PENDING:
2677 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2679 case SERVICE_PAUSE_PENDING:
2680 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2682 case SERVICE_PAUSED:
2683 OutputDebugString("SERVICE_PAUSED\n");
2686 OutputDebugString("UNKNOWN Service State\n");
2689 if (CurrentState == SERVICE_STOPPED)
2691 if (CurrentState == SERVICE_RUNNING)
2707 memset(HostName, '\0', sizeof(HostName));
2708 gethostname(HostName, sizeof(HostName));
2709 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2711 if (CurrentState != SERVICE_RUNNING)
2714 rc = ktc_ForgetAllTokens();
2720 #define ALLOW_REGISTER 1
2722 ViceIDToUsername(char *username,
2723 char *realm_of_user,
2724 char *realm_of_cell,
2726 struct ktc_principal *aclient,
2727 struct ktc_principal *aserver,
2728 struct ktc_token *atoken)
2730 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2731 static char confdir[512] = { 0 };
2732 #ifdef AFS_ID_TO_NAME
2733 char username_copy[BUFSIZ];
2734 #endif /* AFS_ID_TO_NAME */
2735 long viceId = ANONYMOUSID; /* AFS uid of user */
2737 #ifdef ALLOW_REGISTER
2739 #endif /* ALLOW_REGISTER */
2741 if (confdir[0] == '\0')
2742 cm_GetConfigDir(confdir, sizeof(confdir));
2744 StringCbCopyN( lastcell, sizeof(lastcell),
2745 aserver->cell, sizeof(lastcell) - 1);
2747 if (!pr_Initialize (0, confdir, aserver->cell)) {
2748 char sname[PR_MAXNAMELEN];
2749 StringCbCopyN( sname, sizeof(sname),
2750 username, sizeof(sname) - 1);
2751 status = pr_SNameToId (sname, &viceId);
2756 * This is a crock, but it is Transarc's crock, so
2757 * we have to play along in order to get the
2758 * functionality. The way the afs id is stored is
2759 * as a string in the username field of the token.
2760 * Contrary to what you may think by looking at
2761 * the code for tokens, this hack (AFS ID %d) will
2762 * not work if you change %d to something else.
2766 * This code is taken from cklog -- it lets people
2767 * automatically register with the ptserver in foreign cells
2770 #ifdef ALLOW_REGISTER
2772 if (viceId != ANONYMOUSID) {
2773 #else /* ALLOW_REGISTER */
2774 if ((status == 0) && (viceId != ANONYMOUSID))
2775 #endif /* ALLOW_REGISTER */
2777 #ifdef AFS_ID_TO_NAME
2778 StringCbCopyN( username_copy, sizeof(username_copy),
2779 username, sizeof(username_copy) - 1);
2780 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2781 #endif /* AFS_ID_TO_NAME */
2783 #ifdef ALLOW_REGISTER
2784 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2786 StringCbCopyN( aclient->name, sizeof(aclient->name),
2787 username, sizeof(aclient->name) - 1);
2788 aclient->instance[0] = '\0';
2789 StringCbCopyN( aclient->cell, sizeof(aclient->cell),
2790 realm_of_user, sizeof(aclient->cell) - 1);
2791 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2793 if (status = pr_Initialize(1L, confdir, aserver->cell))
2795 status = pr_CreateUser(username, &id);
2799 #ifdef AFS_ID_TO_NAME
2800 StringCbCopyN( username_copy, sizeof(username_copy),
2801 username, sizeof(username_copy) - 1);
2802 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2803 #endif /* AFS_ID_TO_NAME */
2806 #endif /* ALLOW_REGISTER */
2812 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2813 krb5_error_code code;
2814 krb5_ticket *ticket;
2817 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2819 len = krb5_princ_realm(context, ticket->server)->length;
2820 if (len > destlen - 1)
2823 StringCbCopyN(dest, destlen, krb5_princ_realm(context, ticket->server)->data, len);
2825 pkrb5_free_ticket(context, ticket);
2831 krb5_context alt_ctx,
2836 int lifetime, /* unused parameter */
2844 #endif /* USE_KRB4 */
2845 struct ktc_principal aserver;
2846 struct ktc_principal aclient;
2847 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2848 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2849 char local_cell[CELL_MAXNAMELEN+1];
2850 char Dmycell[CELL_MAXNAMELEN+1];
2851 struct ktc_token atoken;
2852 struct ktc_token btoken;
2853 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2854 char RealmName[128];
2856 char ServiceName[128];
2860 krb5_context ctx = NULL;
2861 krb5_ccache cc = NULL;
2863 krb5_creds * k5creds = NULL;
2864 krb5_error_code code;
2865 krb5_principal client_principal = NULL;
2866 krb5_data * k5data = NULL;
2867 unsigned int i, retry = 0;
2870 memset(HostName, '\0', sizeof(HostName));
2871 gethostname(HostName, sizeof(HostName));
2872 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2873 if ( IsDebuggerPresent() )
2874 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2877 if (CurrentState != SERVICE_RUNNING) {
2878 if ( IsDebuggerPresent() )
2879 OutputDebugString("AFSD Service NOT RUNNING\n");
2883 if (!pkrb5_init_context)
2886 memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
2887 memset(RealmName, '\0', sizeof(RealmName));
2888 memset(CellName, '\0', sizeof(CellName));
2889 memset(ServiceName, '\0', sizeof(ServiceName));
2890 memset(realm_of_user, '\0', sizeof(realm_of_user));
2891 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2892 if (cell && cell[0])
2893 StringCbCopyN( Dmycell, sizeof(Dmycell),
2894 cell, sizeof(Dmycell) - 1);
2896 memset(Dmycell, '\0', sizeof(Dmycell));
2898 // NULL or empty cell returns information on local cell
2899 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2901 // KFW_AFS_error(rc, "get_cellconfig()");
2908 code = pkrb5_init_context(&ctx);
2909 if (code) goto cleanup;
2915 code = pkrb5_cc_default(ctx, &cc);
2916 if (code) goto skip_krb5_init;
2919 memset(&increds, 0, sizeof(increds));
2921 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2923 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2925 OutputDebugString("Principal Not Found for ccache\n");
2927 goto skip_krb5_init;
2930 if (!KFW_accept_dotted_usernames()) {
2931 /* look for client principals which cannot be distinguished
2932 * from Kerberos 4 multi-component principal names
2934 k5data = krb5_princ_component(ctx,client_principal,0);
2935 for ( i=0; i<k5data->length; i++ ) {
2936 if ( k5data->data[i] == '.' )
2939 if (i != k5data->length)
2941 OutputDebugString("Illegal Principal name contains dot in first component\n");
2942 rc = KRB5KRB_ERR_GENERIC;
2947 i = krb5_princ_realm(ctx, client_principal)->length;
2950 StringCbCopyN( realm_of_user, sizeof(realm_of_user),
2951 krb5_princ_realm(ctx, client_principal)->data, i);
2956 if ( !try_krb5 || !realm_of_user[0] ) {
2957 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2966 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
2967 afs_realm_of_cell(ctx, &ak_cellconfig),
2968 sizeof(realm_of_cell) - 1);
2970 if (strlen(service) == 0)
2971 StringCbCopy( ServiceName, sizeof(ServiceName), "afs");
2973 StringCbCopyN( ServiceName, sizeof(ServiceName),
2974 service, sizeof(ServiceName) - 1);
2976 if (strlen(cell) == 0)
2977 StringCbCopyN( CellName, sizeof(CellName),
2978 local_cell, sizeof(CellName) - 1);
2980 StringCbCopyN( CellName, sizeof(CellName),
2981 cell, sizeof(CellName) - 1);
2983 /* This is for Kerberos v4 only */
2984 if (strlen(realm) == 0)
2985 StringCbCopyN( RealmName, sizeof(RealmName),
2986 realm_of_cell, sizeof(RealmName) - 1);
2988 StringCbCopyN( RealmName, sizeof(RealmName),
2989 realm, sizeof(RealmName) - 1);
2991 memset(&creds, '\0', sizeof(creds));
2995 code = KRB5KRB_ERR_GENERIC;
2998 increds.client = client_principal;
2999 increds.times.endtime = 0;
3000 /* Ask for DES since that is what V4 understands */
3001 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
3003 /* If there was a specific realm we are supposed to try
3006 if (strlen(realm) != 0) {
3007 /* service/cell@REALM */
3009 code = pkrb5_build_principal(ctx, &increds.server,
3015 if ( IsDebuggerPresent() ) {
3016 char * cname, *sname;
3017 pkrb5_unparse_name(ctx, increds.client, &cname);
3018 pkrb5_unparse_name(ctx, increds.server, &sname);
3019 OutputDebugString("Getting tickets for \"");
3020 OutputDebugString(cname);
3021 OutputDebugString("\" and service \"");
3022 OutputDebugString(sname);
3023 OutputDebugString("\"\n");
3024 pkrb5_free_unparsed_name(ctx,cname);
3025 pkrb5_free_unparsed_name(ctx,sname);
3029 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3031 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3032 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3033 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3034 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3035 /* Or service@REALM */
3036 pkrb5_free_principal(ctx,increds.server);
3038 code = pkrb5_build_principal(ctx, &increds.server,
3044 if ( IsDebuggerPresent() ) {
3045 char * cname, *sname;
3046 pkrb5_unparse_name(ctx, increds.client, &cname);
3047 pkrb5_unparse_name(ctx, increds.server, &sname);
3048 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3049 OutputDebugString("Trying again: getting tickets for \"");
3050 OutputDebugString(cname);
3051 OutputDebugString("\" and service \"");
3052 OutputDebugString(sname);
3053 OutputDebugString("\"\n");
3054 pkrb5_free_unparsed_name(ctx,cname);
3055 pkrb5_free_unparsed_name(ctx,sname);
3059 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3063 /* we have a local realm for the cell */
3064 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3065 realm, sizeof(realm_of_cell) - 1);
3068 /* Otherwise, first try service/cell@CLIENT_REALM */
3069 if (code = pkrb5_build_principal(ctx, &increds.server,
3070 (int)strlen(realm_of_user),
3079 if ( IsDebuggerPresent() ) {
3080 char * cname, *sname;
3081 pkrb5_unparse_name(ctx, increds.client, &cname);
3082 pkrb5_unparse_name(ctx, increds.server, &sname);
3083 OutputDebugString("Getting tickets for \"");
3084 OutputDebugString(cname);
3085 OutputDebugString("\" and service \"");
3086 OutputDebugString(sname);
3087 OutputDebugString("\"\n");
3088 pkrb5_free_unparsed_name(ctx,cname);
3089 pkrb5_free_unparsed_name(ctx,sname);
3092 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3094 /* The client's realm is a local realm for the cell.
3095 * Save it so that later the pts registration will not
3098 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3099 realm_of_user, sizeof(realm_of_cell) - 1);
3102 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3103 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3104 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3105 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
3106 strcmp(realm_of_user, realm_of_cell)) {
3107 /* Then service/cell@CELL_REALM */
3108 pkrb5_free_principal(ctx,increds.server);
3110 code = pkrb5_build_principal(ctx, &increds.server,
3111 (int)strlen(realm_of_cell),
3116 if ( IsDebuggerPresent() ) {
3117 char * cname, *sname;
3118 pkrb5_unparse_name(ctx, increds.client, &cname);
3119 pkrb5_unparse_name(ctx, increds.server, &sname);
3120 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3121 OutputDebugString("Trying again: getting tickets for \"");
3122 OutputDebugString(cname);
3123 OutputDebugString("\" and service \"");
3124 OutputDebugString(sname);
3125 OutputDebugString("\"\n");
3126 pkrb5_free_unparsed_name(ctx,cname);
3127 pkrb5_free_unparsed_name(ctx,sname);
3131 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3133 if (!code && !strlen(realm_of_cell))
3134 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3137 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3138 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3139 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3140 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3141 /* Finally service@CELL_REALM */
3142 pkrb5_free_principal(ctx,increds.server);
3144 code = pkrb5_build_principal(ctx, &increds.server,
3145 (int)strlen(realm_of_cell),
3150 if ( IsDebuggerPresent() ) {
3151 char * cname, *sname;
3152 pkrb5_unparse_name(ctx, increds.client, &cname);
3153 pkrb5_unparse_name(ctx, increds.server, &sname);
3154 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3155 OutputDebugString("Trying again: getting tickets for \"");
3156 OutputDebugString(cname);
3157 OutputDebugString("\" and service \"");
3158 OutputDebugString(sname);
3159 OutputDebugString("\"\n");
3160 pkrb5_free_unparsed_name(ctx,cname);
3161 pkrb5_free_unparsed_name(ctx,sname);
3165 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3166 if (!code && !strlen(realm_of_cell))
3167 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3172 if ( IsDebuggerPresent() ) {
3174 StringCbPrintf(message, sizeof(message), "krb5_get_credentials returns: %d\n", code);
3175 OutputDebugString(message);
3181 /* This code inserts the entire K5 ticket into the token
3182 * No need to perform a krb524 translation which is
3183 * commented out in the code below
3185 if (KFW_use_krb524() ||
3186 k5creds->ticket.length > MAXKTCTICKETLEN)
3189 memset(&aserver, '\0', sizeof(aserver));
3190 StringCbCopyN( aserver.name, sizeof(aserver.name),
3191 ServiceName, sizeof(aserver.name) - 1);
3192 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
3193 CellName, sizeof(aserver.cell) - 1);
3195 memset(&atoken, '\0', sizeof(atoken));
3196 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3197 atoken.startTime = k5creds->times.starttime;
3198 atoken.endTime = k5creds->times.endtime;
3199 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3200 atoken.ticketLen = k5creds->ticket.length;
3201 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3204 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3205 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3206 if ( rc == KTC_NOCM && retry < 20 ) {
3209 goto retry_gettoken5;
3214 if (atoken.kvno == btoken.kvno &&
3215 atoken.ticketLen == btoken.ticketLen &&
3216 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3217 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3219 /* Success - Nothing to do */
3223 // * Reset the "aclient" structure before we call ktc_SetToken.
3224 // * This structure was first set by the ktc_GetToken call when
3225 // * we were comparing whether identical tokens already existed.
3227 len = min(k5creds->client->data[0].length, sizeof(aclient.name) - 1);
3228 StringCbCopyN( aclient.name, sizeof(aclient.name),
3229 k5creds->client->data[0].data, len);
3231 if ( k5creds->client->length > 1 ) {
3232 StringCbCat( aclient.name, sizeof(aclient.name), ".");
3233 len = min(k5creds->client->data[1].length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3234 StringCbCatN( aclient.name, sizeof(aclient.name),
3235 k5creds->client->data[1].data, len);
3237 aclient.instance[0] = '\0';
3239 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3240 realm_of_cell, sizeof(aclient.cell) - 1);
3242 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3243 /* For Khimaira, always append the realm name */
3244 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3245 StringCbCat( aclient.name, sizeof(aclient.name), "@");
3246 len = min(k5creds->client->realm.length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3247 StringCbCatN( aclient.name, sizeof(aclient.name), k5creds->client->realm.data, len);
3250 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3251 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3252 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3253 &aclient, &aserver, &atoken);
3256 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3257 smbname, sizeof(aclient.smbname) - 1);
3259 aclient.smbname[0] = '\0';
3262 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3264 goto cleanup; /* We have successfully inserted the token */
3270 /* Otherwise, the ticket could have been too large so try to
3271 * convert using the krb524d running with the KDC
3273 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3274 pkrb5_free_creds(ctx, k5creds);
3276 if ( IsDebuggerPresent() ) {
3278 StringCbPrintf(message, sizeof(message), "krb524_convert_creds_kdc returns: %d\n", code);
3279 OutputDebugString(message);
3284 #endif /* USE_KRB524 */
3288 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3289 if (code == NO_TKT_FIL) {
3290 // if the problem is that we have no krb4 tickets
3291 // do not attempt to continue
3294 if (code != KSUCCESS)
3295 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3297 if (code != KSUCCESS)
3299 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3301 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3306 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3308 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3323 memset(&aserver, '\0', sizeof(aserver));
3324 StringCbCopyN( aserver.name, sizeof(aserver.name), ServiceName, sizeof(aserver.name) - 1);
3325 StringCbCopyN( aserver.cell, sizeof(aserver.cell), CellName, sizeof(aserver.cell) - 1);
3327 memset(&atoken, '\0', sizeof(atoken));
3328 atoken.kvno = creds.kvno;
3329 atoken.startTime = creds.issue_date;
3330 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3331 memcpy(&atoken.sessionKey, creds.session, 8);
3332 atoken.ticketLen = creds.ticket_st.length;
3333 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3336 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3337 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3338 if ( rc == KTC_NOCM && retry < 20 ) {
3341 goto retry_gettoken;
3343 KFW_AFS_error(rc, "ktc_GetToken()");
3348 if (atoken.kvno == btoken.kvno &&
3349 atoken.ticketLen == btoken.ticketLen &&
3350 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3351 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3356 // * Reset the "aclient" structure before we call ktc_SetToken.
3357 // * This structure was first set by the ktc_GetToken call when
3358 // * we were comparing whether identical tokens already existed.
3360 StringCbCopyN( aclient.name, sizeof(aclient.name), creds.pname, sizeof(aclient.name) - 1);
3363 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3364 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3366 aclient.instance[0] = '\0';
3368 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3369 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3370 aclient.name[MAXKTCREALMLEN-1] = '\0';
3372 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3373 CellName, sizeof(aclient.cell) - 1);
3375 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3376 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3377 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3378 &aclient, &aserver, &atoken);
3381 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3382 smbname, sizeof(aclient.smbname) - 1);
3384 aclient.smbname[0] = '\0';
3387 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3389 KFW_AFS_error(rc, "ktc_SetToken()");
3395 if (client_principal)
3396 pkrb5_free_principal(ctx,client_principal);
3397 /* increds.client == client_principal */
3399 pkrb5_free_principal(ctx,increds.server);
3400 if (cc && (cc != alt_cc))
3401 pkrb5_cc_close(ctx, cc);
3402 if (ctx && (ctx != alt_ctx))
3403 pkrb5_free_context(ctx);
3404 if (ak_cellconfig.linkedCell)
3405 free(ak_cellconfig.linkedCell);
3407 return(rc? rc : code);
3410 /**************************************/
3411 /* afs_realm_of_cell(): */
3412 /**************************************/
3414 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3416 static char krbrlm[REALM_SZ+1]="";
3417 char ** realmlist=NULL;
3423 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3424 if ( !r && realmlist && realmlist[0] ) {
3425 StringCbCopyN( krbrlm, sizeof(krbrlm),
3426 realmlist[0], sizeof(krbrlm) - 1);
3427 pkrb5_free_host_realm(ctx, realmlist);
3433 char *t = cellconfig->name;
3438 if (islower(c)) c=toupper(c);
3446 /**************************************/
3447 /* KFW_AFS_get_cellconfig(): */
3448 /**************************************/
3450 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3453 char newcell[CELL_MAXNAMELEN+1];
3454 char linkedcell[CELL_MAXNAMELEN+1]="";
3456 local_cell[0] = (char)0;
3457 memset(cellconfig, 0, sizeof(*cellconfig));
3459 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3460 if (rc = cm_GetRootCellName(local_cell))
3465 if (strlen(cell) == 0)
3466 strcpy(cell, local_cell);
3468 rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3469 if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
3470 rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3473 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3477 StringCbCopyN( cellconfig->name, sizeof(cellconfig->name),
3478 newcell, sizeof(cellconfig->name) - 1);
3480 cellconfig->linkedCell = strdup(linkedcell);
3485 /**************************************/
3486 /* get_cellconfig_callback(): */
3487 /**************************************/
3489 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
3491 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3493 cc->hostAddr[cc->numServers] = *addrp;
3494 StringCbCopyN( cc->hostName[cc->numServers], sizeof(cc->hostName[cc->numServers]),
3495 namep, sizeof(cc->hostName[cc->numServers]) - 1);
3501 /**************************************/
3502 /* KFW_AFS_error(): */
3503 /**************************************/
3505 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3508 const char *errText;
3510 // Using AFS defines as error messages for now, until Transarc
3511 // gets back to me with "string" translations of each of these
3513 if (rc == KTC_ERROR)
3514 errText = "KTC_ERROR";
3515 else if (rc == KTC_TOOBIG)
3516 errText = "KTC_TOOBIG";
3517 else if (rc == KTC_INVAL)
3518 errText = "KTC_INVAL";
3519 else if (rc == KTC_NOENT)
3520 errText = "KTC_NOENT";
3521 else if (rc == KTC_PIOCTLFAIL)
3522 errText = "KTC_PIOCTLFAIL";
3523 else if (rc == KTC_NOPIOCTL)
3524 errText = "KTC_NOPIOCTL";
3525 else if (rc == KTC_NOCELL)
3526 errText = "KTC_NOCELL";
3527 else if (rc == KTC_NOCM)
3528 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3530 errText = "Unknown error!";
3532 StringCbPrintf(message, sizeof(message), "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3534 if ( IsDebuggerPresent() ) {
3535 OutputDebugString(message);
3536 OutputDebugString("\n");
3538 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3544 LPSTR lpszMachineName,
3545 LPSTR lpszServiceName,
3546 DWORD *lpdwCurrentState)
3549 SC_HANDLE schSCManager = NULL;
3550 SC_HANDLE schService = NULL;
3551 DWORD fdwDesiredAccess = 0;
3552 SERVICE_STATUS ssServiceStatus = {0};
3555 *lpdwCurrentState = 0;
3557 fdwDesiredAccess = GENERIC_READ;
3559 schSCManager = OpenSCManager(lpszMachineName,
3563 if(schSCManager == NULL)
3565 hr = GetLastError();
3569 schService = OpenService(schSCManager,
3573 if(schService == NULL)
3575 hr = GetLastError();
3579 fRet = QueryServiceStatus(schService,
3584 hr = GetLastError();
3588 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3592 CloseServiceHandle(schService);
3593 CloseServiceHandle(schSCManager);
3606 for (n = 0; fi[n].func_ptr_var; n++)
3607 *(fi[n].func_ptr_var) = 0;
3608 if (h) FreeLibrary(h);
3613 const char* dll_name,
3615 HINSTANCE* ph, // [out, optional] - DLL handle
3616 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3617 int cleanup, // cleanup function pointers and unload on error
3618 int go_on, // continue loading even if some functions cannot be loaded
3619 int silent // do not pop-up a system dialog if DLL cannot be loaded
3628 if (pindex) *pindex = -1;
3630 for (n = 0; fi[n].func_ptr_var; n++)
3631 *(fi[n].func_ptr_var) = 0;
3634 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3635 h = LoadLibrary(dll_name);
3643 for (i = 0; (go_on || !error) && (i < n); i++)
3645 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3651 *(fi[i].func_ptr_var) = p;
3654 if (pindex) *pindex = last_i;
3655 if (error && cleanup && !go_on) {
3656 for (i = 0; i < n; i++) {
3657 *(fi[i].func_ptr_var) = 0;
3663 if (error) return 0;
3667 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3669 krb5_context ctx = NULL;
3670 krb5_ccache cc = NULL;
3671 krb5_error_code code;
3673 const char * realm = NULL;
3674 krb5_principal principal = NULL;
3675 char * pname = NULL;
3676 char password[PROBE_PASSWORD_LEN+1];
3677 BOOL serverReachable = 0;
3679 if (!pkrb5_init_context)
3682 code = pkrb5_init_context(&ctx);
3683 if (code) goto cleanup;
3686 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3688 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3689 realm, PROBE_USERNAME, NULL, NULL);
3690 if ( code ) goto cleanup;
3692 code = KFW_get_ccache(ctx, principal, &cc);
3693 if ( code ) goto cleanup;
3695 code = pkrb5_unparse_name(ctx, principal, &pname);
3696 if ( code ) goto cleanup;
3698 pwdata.data = password;
3699 pwdata.length = PROBE_PASSWORD_LEN;
3700 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3703 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3706 password[PROBE_PASSWORD_LEN] = '\0';
3708 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3718 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3719 case KRB5KDC_ERR_CLIENT_REVOKED:
3720 case KRB5KDC_ERR_CLIENT_NOTYET:
3721 case KRB5KDC_ERR_PREAUTH_FAILED:
3722 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3723 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3724 serverReachable = TRUE;
3727 serverReachable = FALSE;
3732 pkrb5_free_unparsed_name(ctx,pname);
3734 pkrb5_free_principal(ctx,principal);
3736 pkrb5_cc_close(ctx,cc);
3738 pkrb5_free_context(ctx);
3740 return serverReachable;
3744 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
3746 krb5_context ctx = NULL;
3747 krb5_error_code code;
3748 krb5_ccache mslsa_ccache=NULL;
3749 krb5_principal princ = NULL;
3750 char * pname = NULL;
3753 if (!KFW_is_available())
3756 if (code = pkrb5_init_context(&ctx))
3759 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3762 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3765 if (code = pkrb5_unparse_name(ctx, princ, &pname))
3768 if ( strlen(pname) < *dwSize ) {
3769 StringCbCopyN(szUser, *dwSize, pname, (*dwSize) - 1);
3772 *dwSize = (DWORD)strlen(pname);
3776 pkrb5_free_unparsed_name(ctx, pname);
3779 pkrb5_free_principal(ctx, princ);
3782 pkrb5_cc_close(ctx, mslsa_ccache);
3785 pkrb5_free_context(ctx);
3790 KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
3792 // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
3793 PSID pSystemSID = NULL;
3794 DWORD SystemSIDlength = 0, UserSIDlength = 0;
3795 PACL ccacheACL = NULL;
3796 DWORD ccacheACLlength = 0;
3797 PTOKEN_USER pTokenUser = NULL;
3806 /* Get System SID */
3807 if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
3813 SystemSIDlength = GetLengthSid(pSystemSID);
3814 ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
3815 + SystemSIDlength - sizeof(DWORD);
3818 if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
3820 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
3821 pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
3823 GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
3828 UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
3830 ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
3835 ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
3840 InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
3841 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3842 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3845 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3846 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3847 pTokenUser->User.Sid);
3848 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3849 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3854 gle = GetLastError();
3855 if (gle != ERROR_NO_TOKEN)
3858 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3859 OWNER_SECURITY_INFORMATION,
3860 pTokenUser->User.Sid,
3864 gle = GetLastError();
3865 if (gle != ERROR_NO_TOKEN)
3869 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3870 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3875 gle = GetLastError();
3876 if (gle != ERROR_NO_TOKEN)
3883 LocalFree(pSystemSID);
3885 LocalFree(pTokenUser);
3887 LocalFree(ccacheACL);
3892 KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
3895 DWORD dwSize = size-1; /* leave room for nul */
3898 if (!hUserToken || !newfilename || size <= 0)
3901 *newfilename = '\0';
3903 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
3904 if ( !dwLen || dwLen > dwSize )
3905 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
3906 if ( !dwLen || dwLen > dwSize )
3909 newfilename[dwSize] = '\0';
3914 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
3916 char filename[MAX_PATH] = "";
3918 char cachename[MAX_PATH + 8] = "FILE:";
3919 krb5_context ctx = NULL;
3920 krb5_error_code code;
3921 krb5_principal princ = NULL;
3922 krb5_ccache cc = NULL;
3923 krb5_ccache ncc = NULL;
3925 if (!pkrb5_init_context || !user || !szLogonId)
3928 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
3929 if ( count > sizeof(filename) || count == 0 ) {
3930 GetWindowsDirectory(filename, sizeof(filename));
3933 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
3936 StringCbCat( filename, sizeof(filename), "\\");
3937 StringCbCat( filename, sizeof(filename), szLogonId);
3939 StringCbCat( cachename, sizeof(cachename), filename);
3941 DeleteFile(filename);
3943 code = pkrb5_init_context(&ctx);
3944 if (code) goto cleanup;
3946 code = pkrb5_parse_name(ctx, user, &princ);
3947 if (code) goto cleanup;
3949 code = KFW_get_ccache(ctx, princ, &cc);
3950 if (code) goto cleanup;
3952 code = pkrb5_cc_resolve(ctx, cachename, &ncc);
3953 if (code) goto cleanup;
3955 code = pkrb5_cc_initialize(ctx, ncc, princ);
3956 if (code) goto cleanup;
3958 code = KFW_AFS_set_file_cache_dacl(filename, NULL);
3959 if (code) goto cleanup;
3961 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3965 pkrb5_cc_close(ctx, cc);
3969 pkrb5_cc_close(ctx, ncc);
3973 pkrb5_free_principal(ctx, princ);
3978 pkrb5_free_context(ctx);
3982 KFW_AFS_copy_file_cache_to_default_cache(char * filename)
3984 char cachename[MAX_PATH + 8] = "FILE:";
3985 krb5_context ctx = NULL;
3986 krb5_error_code code;
3987 krb5_principal princ = NULL;
3988 krb5_ccache cc = NULL;
3989 krb5_ccache ncc = NULL;
3992 if (!pkrb5_init_context || !filename)
3995 if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
3998 code = pkrb5_init_context(&ctx);
4001 StringCbCat( cachename, sizeof(cachename), filename);
4003 code = pkrb5_cc_resolve(ctx, cachename, &cc);
4004 if (code) goto cleanup;
4006 code = pkrb5_cc_get_principal(ctx, cc, &princ);
4008 code = pkrb5_cc_default(ctx, &ncc);
4010 code = pkrb5_cc_initialize(ctx, ncc, princ);
4013 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
4016 pkrb5_cc_close(ctx, ncc);
4020 retval=0; /* success */
4024 pkrb5_cc_close(ctx, cc);
4028 DeleteFile(filename);
4031 pkrb5_free_principal(ctx, princ);
4036 pkrb5_free_context(ctx);
4041 /* We are including this
4043 /* Ticket lifetime. This defines the table used to lookup lifetime for the
4044 fixed part of rande of the one byte lifetime field. Values less than 0x80
4045 are intrpreted as the number of 5 minute intervals. Values from 0x80 to
4046 0xBF should be looked up in this table. The value of 0x80 is the same using
4047 both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days.
4048 The intervening values of have a fixed ratio of roughly 1.06914. The value
4049 oxFF is defined to mean a ticket has no expiration time. This should be
4050 used advisedly since individual servers may impose defacto upperbounds on
4051 ticket lifetimes. */
4053 #define TKTLIFENUMFIXED 64
4054 #define TKTLIFEMINFIXED 0x80
4055 #define TKTLIFEMAXFIXED 0xBF
4056 #define TKTLIFENOEXPIRE 0xFF
4057 #define MAXTKTLIFETIME (30*24*3600) /* 30 days */
4059 static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
4060 38400, /* 10.67 hours, 0.44 days */
4061 41055, /* 11.40 hours, 0.48 days */
4062 43894, /* 12.19 hours, 0.51 days */
4063 46929, /* 13.04 hours, 0.54 days */
4064 50174, /* 13.94 hours, 0.58 days */
4065 53643, /* 14.90 hours, 0.62 days */
4066 57352, /* 15.93 hours, 0.66 days */
4067 61318, /* 17.03 hours, 0.71 days */
4068 65558, /* 18.21 hours, 0.76 days */
4069 70091, /* 19.47 hours, 0.81 days */
4070 74937, /* 20.82 hours, 0.87 days */
4071 80119, /* 22.26 hours, 0.93 days */
4072 85658, /* 23.79 hours, 0.99 days */
4073 91581, /* 25.44 hours, 1.06 days */
4074 97914, /* 27.20 hours, 1.13 days */
4075 104684, /* 29.08 hours, 1.21 days */
4076 111922, /* 31.09 hours, 1.30 days */
4077 119661, /* 33.24 hours, 1.38 days */
4078 127935, /* 35.54 hours, 1.48 days */
4079 136781, /* 37.99 hours, 1.58 days */
4080 146239, /* 40.62 hours, 1.69 days */
4081 156350, /* 43.43 hours, 1.81 days */
4082 167161, /* 46.43 hours, 1.93 days */
4083 178720, /* 49.64 hours, 2.07 days */
4084 191077, /* 53.08 hours, 2.21 days */
4085 204289, /* 56.75 hours, 2.36 days */
4086 218415, /* 60.67 hours, 2.53 days */
4087 233517, /* 64.87 hours, 2.70 days */
4088 249664, /* 69.35 hours, 2.89 days */
4089 266926, /* 74.15 hours, 3.09 days */
4090 285383, /* 79.27 hours, 3.30 days */
4091 305116, /* 84.75 hours, 3.53 days */
4092 326213, /* 90.61 hours, 3.78 days */
4093 348769, /* 96.88 hours, 4.04 days */
4094 372885, /* 103.58 hours, 4.32 days */
4095 398668, /* 110.74 hours, 4.61 days */
4096 426234, /* 118.40 hours, 4.93 days */
4097 455705, /* 126.58 hours, 5.27 days */
4098 487215, /* 135.34 hours, 5.64 days */
4099 520904, /* 144.70 hours, 6.03 days */
4100 556921, /* 154.70 hours, 6.45 days */
4101 595430, /* 165.40 hours, 6.89 days */
4102 636601, /* 176.83 hours, 7.37 days */
4103 680618, /* 189.06 hours, 7.88 days */
4104 727680, /* 202.13 hours, 8.42 days */
4105 777995, /* 216.11 hours, 9.00 days */
4106 831789, /* 231.05 hours, 9.63 days */
4107 889303, /* 247.03 hours, 10.29 days */
4108 950794, /* 264.11 hours, 11.00 days */
4109 1016537, /* 282.37 hours, 11.77 days */
4110 1086825, /* 301.90 hours, 12.58 days */
4111 1161973, /* 322.77 hours, 13.45 days */
4112 1242318, /* 345.09 hours, 14.38 days */
4113 1328218, /* 368.95 hours, 15.37 days */
4114 1420057, /* 394.46 hours, 16.44 days */
4115 1518247, /* 421.74 hours, 17.57 days */
4116 1623226, /* 450.90 hours, 18.79 days */
4117 1735464, /* 482.07 hours, 20.09 days */
4118 1855462, /* 515.41 hours, 21.48 days */
4119 1983758, /* 551.04 hours, 22.96 days */
4120 2120925, /* 589.15 hours, 24.55 days */
4121 2267576, /* 629.88 hours, 26.25 days */
4122 2424367, /* 673.44 hours, 28.06 days */
4124 }; /* 720.00 hours, 30.00 days */
4126 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
4127 * returns the corresponding end time. There are four simple cases to be
4128 * handled. The first is a life of 0xff, meaning no expiration, and results in
4129 * an end time of 0xffffffff. The second is when life is less than the values
4130 * covered by the table. In this case, the end time is the start time plus the
4131 * number of 5 minute intervals specified by life. The third case returns
4132 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
4133 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
4134 * table to extract the lifetime in seconds, which is added to start to produce
4138 life_to_time(afs_uint32 start, unsigned char life)
4142 if (life == TKTLIFENOEXPIRE)
4144 if (life < TKTLIFEMINFIXED)
4145 return start + life * 5 * 60;
4146 if (life > TKTLIFEMAXFIXED)
4147 return start + MAXTKTLIFETIME;
4148 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
4149 return start + realLife;
4152 /* time_to_life - takes start and end times for the ticket and returns a
4153 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
4154 * lifetimes above 127*5minutes. First, the special case of (end ==
4155 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
4156 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
4157 * less than the first table entry are handled by rounding the requested
4158 * lifetime *up* to the next 5 minute interval. The final step is to search
4159 * the table for the smallest entry *greater than or equal* to the requested
4160 * entry. The actual code is prepared to handle the case where the table is
4161 * unordered but that it an unnecessary frill. */
4163 static unsigned char
4164 time_to_life(afs_uint32 start, afs_uint32 end)
4166 int lifetime = end - start;
4170 if (end == NEVERDATE)
4171 return TKTLIFENOEXPIRE;
4172 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
4174 if (lifetime < tkt_lifetimes[0])
4175 return (lifetime + 5 * 60 - 1) / (5 * 60);
4177 best = MAXKTCTICKETLIFETIME;
4178 for (i = 0; i < TKTLIFENUMFIXED; i++)
4179 if (tkt_lifetimes[i] >= lifetime) {
4180 int diff = tkt_lifetimes[i] - lifetime;
4188 return best_i + TKTLIFEMINFIXED;