2 * Copyright (c) 2004, 2005, 2006, 2007, 2008 Secure Endpoints Inc.
3 * Copyright (c) 2003 SkyRope, LLC
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * - Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * - Neither the name of Skyrope, LLC nor the names of its contributors may be
15 * used to endorse or promote products derived from this software without
16 * specific prior written permission from Skyrope, LLC.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Portions of this code are derived from portions of the MIT
31 * Leash Ticket Manager and LoadFuncs utilities. For these portions the
32 * following copyright applies.
34 * Copyright (c) 2003,2004 by the Massachusetts Institute of Technology.
35 * All rights reserved.
37 * Export of this software from the United States of America may
38 * require a specific license from the United States Government.
39 * It is the responsibility of any person or organization contemplating
40 * export to obtain such a license before exporting.
42 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
43 * distribute this software and its documentation for any purpose and
44 * without fee is hereby granted, provided that the above copyright
45 * notice appear in all copies and that both that copyright notice and
46 * this permission notice appear in supporting documentation, and that
47 * the name of M.I.T. not be used in advertising or publicity pertaining
48 * to distribution of the software without specific, written prior
49 * permission. Furthermore if you modify this software you must label
50 * your software as modified software and not distribute it in such a
51 * fashion that it might be confused with the original M.I.T. software.
52 * M.I.T. makes no representations about the suitability of
53 * this software for any purpose. It is provided "as is" without express
54 * or implied warranty.
66 /* Prevent inclusion of des.h to avoid conflicts with des types */
67 #define NO_DES_H_INCLUDE
69 #include "afskfw-int.h"
77 #include <afs/ptserver.h>
78 #include <afs/ptuser.h>
81 #include <WINNT\afsreg.h>
85 * TIMING _____________________________________________________________________
89 #define cminREMIND_TEST 1 // test every minute for expired creds
90 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
91 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
92 #define cminMINLIFE 30 // minimum life of Kerberos creds
94 #define c100ns1SECOND (LONGLONG)10000000
95 #define cmsec1SECOND 1000
96 #define cmsec1MINUTE 60000
97 #define csec1MINUTE 60
99 /* Function Pointer Declarations for Delayed Loading */
101 DECL_FUNC_PTR(cc_initialize);
102 DECL_FUNC_PTR(cc_shutdown);
103 DECL_FUNC_PTR(cc_get_NC_info);
104 DECL_FUNC_PTR(cc_free_NC_info);
108 DECL_FUNC_PTR(Leash_get_default_lifetime);
109 DECL_FUNC_PTR(Leash_get_default_forwardable);
110 DECL_FUNC_PTR(Leash_get_default_renew_till);
111 DECL_FUNC_PTR(Leash_get_default_noaddresses);
112 DECL_FUNC_PTR(Leash_get_default_proxiable);
113 DECL_FUNC_PTR(Leash_get_default_publicip);
114 DECL_FUNC_PTR(Leash_get_default_use_krb4);
115 DECL_FUNC_PTR(Leash_get_default_life_min);
116 DECL_FUNC_PTR(Leash_get_default_life_max);
117 DECL_FUNC_PTR(Leash_get_default_renew_min);
118 DECL_FUNC_PTR(Leash_get_default_renew_max);
119 DECL_FUNC_PTR(Leash_get_default_renewable);
120 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
124 DECL_FUNC_PTR(krb5_change_password);
125 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
126 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
127 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
128 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
129 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
130 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
131 DECL_FUNC_PTR(krb5_get_init_creds_password);
132 DECL_FUNC_PTR(krb5_build_principal_ext);
133 DECL_FUNC_PTR(krb5_cc_get_name);
134 DECL_FUNC_PTR(krb5_cc_resolve);
135 DECL_FUNC_PTR(krb5_cc_default);
136 DECL_FUNC_PTR(krb5_cc_default_name);
137 DECL_FUNC_PTR(krb5_cc_set_default_name);
138 DECL_FUNC_PTR(krb5_cc_initialize);
139 DECL_FUNC_PTR(krb5_cc_destroy);
140 DECL_FUNC_PTR(krb5_cc_close);
141 DECL_FUNC_PTR(krb5_cc_store_cred);
142 DECL_FUNC_PTR(krb5_cc_copy_creds);
143 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
144 DECL_FUNC_PTR(krb5_cc_get_principal);
145 DECL_FUNC_PTR(krb5_cc_start_seq_get);
146 DECL_FUNC_PTR(krb5_cc_next_cred);
147 DECL_FUNC_PTR(krb5_cc_end_seq_get);
148 DECL_FUNC_PTR(krb5_cc_remove_cred);
149 DECL_FUNC_PTR(krb5_cc_set_flags);
150 DECL_FUNC_PTR(krb5_cc_get_type);
151 DECL_FUNC_PTR(krb5_free_context);
152 DECL_FUNC_PTR(krb5_free_cred_contents);
153 DECL_FUNC_PTR(krb5_free_principal);
154 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
155 DECL_FUNC_PTR(krb5_init_context);
156 DECL_FUNC_PTR(krb5_parse_name);
157 DECL_FUNC_PTR(krb5_timeofday);
158 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
159 DECL_FUNC_PTR(krb5_unparse_name);
160 DECL_FUNC_PTR(krb5_get_credentials);
161 DECL_FUNC_PTR(krb5_mk_req);
162 DECL_FUNC_PTR(krb5_sname_to_principal);
163 DECL_FUNC_PTR(krb5_get_credentials_renew);
164 DECL_FUNC_PTR(krb5_free_data);
165 DECL_FUNC_PTR(krb5_free_data_contents);
166 DECL_FUNC_PTR(krb5_free_unparsed_name);
167 DECL_FUNC_PTR(krb5_os_localaddr);
168 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
169 DECL_FUNC_PTR(krb5_copy_data);
170 DECL_FUNC_PTR(krb5_free_creds);
171 DECL_FUNC_PTR(krb5_build_principal);
172 DECL_FUNC_PTR(krb5_get_renewed_creds);
173 DECL_FUNC_PTR(krb5_get_default_config_files);
174 DECL_FUNC_PTR(krb5_free_config_files);
175 DECL_FUNC_PTR(krb5_get_default_realm);
176 DECL_FUNC_PTR(krb5_free_default_realm);
177 DECL_FUNC_PTR(krb5_free_ticket);
178 DECL_FUNC_PTR(krb5_decode_ticket);
179 DECL_FUNC_PTR(krb5_get_host_realm);
180 DECL_FUNC_PTR(krb5_free_host_realm);
181 DECL_FUNC_PTR(krb5_free_addresses);
182 DECL_FUNC_PTR(krb5_c_random_make_octets);
183 DECL_FUNC_PTR(krb5_get_error_message);
184 DECL_FUNC_PTR(krb5_free_error_message);
188 DECL_FUNC_PTR(krb524_init_ets);
189 DECL_FUNC_PTR(krb524_convert_creds_kdc);
194 DECL_FUNC_PTR(krb_get_cred);
195 DECL_FUNC_PTR(tkt_string);
196 DECL_FUNC_PTR(krb_get_tf_realm);
197 DECL_FUNC_PTR(krb_mk_req);
201 DECL_FUNC_PTR(com_err);
202 DECL_FUNC_PTR(error_message);
205 DECL_FUNC_PTR(profile_init);
206 DECL_FUNC_PTR(profile_release);
207 DECL_FUNC_PTR(profile_get_subsection_names);
208 DECL_FUNC_PTR(profile_free_list);
209 DECL_FUNC_PTR(profile_get_string);
210 DECL_FUNC_PTR(profile_release_string);
213 DECL_FUNC_PTR(OpenSCManagerA);
214 DECL_FUNC_PTR(OpenServiceA);
215 DECL_FUNC_PTR(QueryServiceStatus);
216 DECL_FUNC_PTR(CloseServiceHandle);
218 DECL_FUNC_PTR(LsaNtStatusToWinError);
219 #endif /* USE_MS2MIT */
223 DECL_FUNC_PTR(LsaConnectUntrusted);
224 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
225 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
226 DECL_FUNC_PTR(LsaFreeReturnBuffer);
227 DECL_FUNC_PTR(LsaGetLogonSessionData);
228 #endif /* USE_MS2MIT */
231 FUNC_INFO ccapi_fi[] = {
232 MAKE_FUNC_INFO(cc_initialize),
233 MAKE_FUNC_INFO(cc_shutdown),
234 MAKE_FUNC_INFO(cc_get_NC_info),
235 MAKE_FUNC_INFO(cc_free_NC_info),
240 FUNC_INFO leash_fi[] = {
241 MAKE_FUNC_INFO(Leash_get_default_lifetime),
242 MAKE_FUNC_INFO(Leash_get_default_renew_till),
243 MAKE_FUNC_INFO(Leash_get_default_forwardable),
244 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
245 MAKE_FUNC_INFO(Leash_get_default_proxiable),
246 MAKE_FUNC_INFO(Leash_get_default_publicip),
247 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
248 MAKE_FUNC_INFO(Leash_get_default_life_min),
249 MAKE_FUNC_INFO(Leash_get_default_life_max),
250 MAKE_FUNC_INFO(Leash_get_default_renew_min),
251 MAKE_FUNC_INFO(Leash_get_default_renew_max),
252 MAKE_FUNC_INFO(Leash_get_default_renewable),
256 FUNC_INFO leash_opt_fi[] = {
257 MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
262 FUNC_INFO k5_fi[] = {
263 MAKE_FUNC_INFO(krb5_change_password),
264 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
265 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
266 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
267 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
268 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
269 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
270 MAKE_FUNC_INFO(krb5_get_init_creds_password),
271 MAKE_FUNC_INFO(krb5_build_principal_ext),
272 MAKE_FUNC_INFO(krb5_cc_get_name),
273 MAKE_FUNC_INFO(krb5_cc_resolve),
274 MAKE_FUNC_INFO(krb5_cc_default),
275 MAKE_FUNC_INFO(krb5_cc_default_name),
276 MAKE_FUNC_INFO(krb5_cc_set_default_name),
277 MAKE_FUNC_INFO(krb5_cc_initialize),
278 MAKE_FUNC_INFO(krb5_cc_destroy),
279 MAKE_FUNC_INFO(krb5_cc_close),
280 MAKE_FUNC_INFO(krb5_cc_copy_creds),
281 MAKE_FUNC_INFO(krb5_cc_store_cred),
282 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
283 MAKE_FUNC_INFO(krb5_cc_get_principal),
284 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
285 MAKE_FUNC_INFO(krb5_cc_next_cred),
286 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
287 MAKE_FUNC_INFO(krb5_cc_remove_cred),
288 MAKE_FUNC_INFO(krb5_cc_set_flags),
289 MAKE_FUNC_INFO(krb5_cc_get_type),
290 MAKE_FUNC_INFO(krb5_free_context),
291 MAKE_FUNC_INFO(krb5_free_cred_contents),
292 MAKE_FUNC_INFO(krb5_free_principal),
293 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
294 MAKE_FUNC_INFO(krb5_init_context),
295 MAKE_FUNC_INFO(krb5_parse_name),
296 MAKE_FUNC_INFO(krb5_timeofday),
297 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
298 MAKE_FUNC_INFO(krb5_unparse_name),
299 MAKE_FUNC_INFO(krb5_get_credentials),
300 MAKE_FUNC_INFO(krb5_mk_req),
301 MAKE_FUNC_INFO(krb5_sname_to_principal),
302 MAKE_FUNC_INFO(krb5_get_credentials_renew),
303 MAKE_FUNC_INFO(krb5_free_data),
304 MAKE_FUNC_INFO(krb5_free_data_contents),
305 MAKE_FUNC_INFO(krb5_free_unparsed_name),
306 MAKE_FUNC_INFO(krb5_os_localaddr),
307 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
308 MAKE_FUNC_INFO(krb5_copy_data),
309 MAKE_FUNC_INFO(krb5_free_creds),
310 MAKE_FUNC_INFO(krb5_build_principal),
311 MAKE_FUNC_INFO(krb5_get_renewed_creds),
312 MAKE_FUNC_INFO(krb5_free_addresses),
313 MAKE_FUNC_INFO(krb5_get_default_config_files),
314 MAKE_FUNC_INFO(krb5_free_config_files),
315 MAKE_FUNC_INFO(krb5_get_default_realm),
316 MAKE_FUNC_INFO(krb5_free_default_realm),
317 MAKE_FUNC_INFO(krb5_free_ticket),
318 MAKE_FUNC_INFO(krb5_decode_ticket),
319 MAKE_FUNC_INFO(krb5_get_host_realm),
320 MAKE_FUNC_INFO(krb5_free_host_realm),
321 MAKE_FUNC_INFO(krb5_free_addresses),
322 MAKE_FUNC_INFO(krb5_c_random_make_octets),
323 MAKE_FUNC_INFO(krb5_get_error_message),
324 MAKE_FUNC_INFO(krb5_free_error_message),
329 FUNC_INFO k4_fi[] = {
330 MAKE_FUNC_INFO(krb_get_cred),
331 MAKE_FUNC_INFO(krb_get_tf_realm),
332 MAKE_FUNC_INFO(krb_mk_req),
333 MAKE_FUNC_INFO(tkt_string),
339 FUNC_INFO k524_fi[] = {
340 MAKE_FUNC_INFO(krb524_init_ets),
341 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
346 FUNC_INFO profile_fi[] = {
347 MAKE_FUNC_INFO(profile_init),
348 MAKE_FUNC_INFO(profile_release),
349 MAKE_FUNC_INFO(profile_get_subsection_names),
350 MAKE_FUNC_INFO(profile_free_list),
351 MAKE_FUNC_INFO(profile_get_string),
352 MAKE_FUNC_INFO(profile_release_string),
356 FUNC_INFO ce_fi[] = {
357 MAKE_FUNC_INFO(com_err),
358 MAKE_FUNC_INFO(error_message),
362 FUNC_INFO service_fi[] = {
363 MAKE_FUNC_INFO(OpenSCManagerA),
364 MAKE_FUNC_INFO(OpenServiceA),
365 MAKE_FUNC_INFO(QueryServiceStatus),
366 MAKE_FUNC_INFO(CloseServiceHandle),
368 MAKE_FUNC_INFO(LsaNtStatusToWinError),
369 #endif /* USE_MS2MIT */
374 FUNC_INFO lsa_fi[] = {
375 MAKE_FUNC_INFO(LsaConnectUntrusted),
376 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
377 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
378 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
379 MAKE_FUNC_INFO(LsaGetLogonSessionData),
382 #endif /* USE_MS2MIT */
384 /* Static Prototypes */
385 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
386 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *, unsigned short);
387 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
388 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
389 void *data, const char *name, const char *banner, int num_prompts,
390 krb5_prompt prompts[]);
393 /* Static Declarations */
394 static int inited = 0;
395 static int mid_cnt = 0;
396 static struct textField * mid_tb = NULL;
397 static HINSTANCE hKrb5 = 0;
399 static HINSTANCE hKrb4 = 0;
400 #endif /* USE_KRB4 */
402 static HINSTANCE hKrb524 = 0;
405 static HINSTANCE hSecur32 = 0;
406 #endif /* USE_MS2MIT */
407 static HINSTANCE hAdvApi32 = 0;
408 static HINSTANCE hComErr = 0;
409 static HINSTANCE hService = 0;
410 static HINSTANCE hProfile = 0;
412 static HINSTANCE hLeash = 0;
413 static HINSTANCE hLeashOpt = 0;
415 static HINSTANCE hCCAPI = 0;
416 static struct principal_ccache_data * princ_cc_data = NULL;
417 static struct cell_principal_map * cell_princ_map = NULL;
422 static int inited = 0;
425 char mutexName[MAX_PATH];
426 HANDLE hMutex = NULL;
428 sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
430 hMutex = CreateMutex( NULL, TRUE, mutexName );
431 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
432 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
438 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
439 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
440 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
442 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
443 #endif /* USE_KRB4 */
444 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
446 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
447 #endif /* USE_MS2MIT */
449 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
452 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
453 LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
455 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
457 if ( KFW_is_available() ) {
458 char rootcell[CELL_MAXNAMELEN+1];
460 KFW_import_windows_lsa();
461 #endif /* USE_MS2MIT */
462 KFW_import_ccache_data();
463 KFW_AFS_renew_expiring_tokens();
465 /* WIN32 NOTE: no way to get max chars */
466 if (!cm_GetRootCellName(rootcell))
467 KFW_AFS_renew_token_for_cell(rootcell);
470 ReleaseMutex(hMutex);
480 FreeLibrary(hLeashOpt);
486 FreeLibrary(hKrb524);
492 FreeLibrary(hSecur32);
493 #endif /* USE_MS2MIT */
495 FreeLibrary(hService);
497 FreeLibrary(hComErr);
499 FreeLibrary(hProfile);
503 #endif /* USE_KRB4 */
508 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
511 static int init = TRUE;
512 static int bIsWow64 = FALSE;
516 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
518 hModule = GetModuleHandle(TEXT("kernel32"));
520 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
522 if (NULL != fnIsWow64Process)
524 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
526 // on error, assume FALSE.
527 // in other words, do nothing.
530 FreeLibrary(hModule);
538 KFW_accept_dotted_usernames(void)
544 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
545 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
546 if (code == ERROR_SUCCESS) {
548 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
549 (BYTE *) &value, &len);
550 RegCloseKey(parmKey);
552 if (code != ERROR_SUCCESS) {
553 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
554 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
555 if (code == ERROR_SUCCESS) {
557 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
558 (BYTE *) &value, &len);
559 RegCloseKey (parmKey);
573 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
574 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
575 if (code == ERROR_SUCCESS) {
576 len = sizeof(use524);
577 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
578 (BYTE *) &use524, &len);
579 RegCloseKey(parmKey);
581 if (code != ERROR_SUCCESS) {
582 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
583 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
584 if (code == ERROR_SUCCESS) {
585 len = sizeof(use524);
586 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
587 (BYTE *) &use524, &len);
588 RegCloseKey (parmKey);
595 KFW_is_available(void)
601 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
602 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
603 if (code == ERROR_SUCCESS) {
604 len = sizeof(enableKFW);
605 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
606 (BYTE *) &enableKFW, &len);
607 RegCloseKey (parmKey);
610 if (code != ERROR_SUCCESS) {
611 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
612 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
613 if (code == ERROR_SUCCESS) {
614 len = sizeof(enableKFW);
615 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
616 (BYTE *) &enableKFW, &len);
617 RegCloseKey (parmKey);
625 if ( hKrb5 && hComErr && hService &&
628 #endif /* USE_MS2MIT */
641 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
642 int FreeContextFlag, krb5_context * ctx,
647 int krb5Error = ((int)(rc & 255));
659 errText = pkrb5_get_error_message(ctx, rc);
660 _snprintf(message, sizeof(message),
661 "%s\n(Kerberos error %ld)\n\n%s failed",
665 pkrb5_free_error_message(ctx, errText);
667 if ( IsDebuggerPresent() )
668 OutputDebugString(message);
670 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
673 if (FreeContextFlag == 1)
675 if (ctx && *ctx != NULL)
677 if (cache && *cache != NULL) {
678 pkrb5_cc_close(*ctx, *cache);
682 pkrb5_free_context(*ctx);
691 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
693 struct principal_ccache_data * next = princ_cc_data;
694 krb5_principal principal = 0;
696 const char * ccname = NULL;
697 const char * cctype = NULL;
698 char * ccfullname = NULL;
699 krb5_error_code code = 0;
700 krb5_error_code cc_code = 0;
706 if (ctx == 0 || cc == 0)
709 code = pkrb5_cc_get_principal(ctx, cc, &principal);
712 code = pkrb5_unparse_name(ctx, principal, &pname);
713 if ( code ) goto cleanup;
715 ccname = pkrb5_cc_get_name(ctx, cc);
716 if (!ccname) goto cleanup;
718 cctype = pkrb5_cc_get_type(ctx, cc);
719 if (!cctype) goto cleanup;
721 ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
722 if (!ccfullname) goto cleanup;
724 sprintf(ccfullname, "%s:%s", cctype, ccname);
726 // Search the existing list to see if we have a match
728 for ( ; next ; next = next->next ) {
729 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
734 // If not, match add a new node to the beginning of the list and assign init it
736 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
737 next->next = princ_cc_data;
738 princ_cc_data = next;
739 next->principal = _strdup(pname);
740 next->ccache_name = ccfullname;
742 next->from_lsa = lsa;
744 next->expiration_time = 0;
748 flags = 0; // turn off OPENCLOSE mode
749 code = pkrb5_cc_set_flags(ctx, cc, flags);
750 if ( code ) goto cleanup;
752 code = pkrb5_timeofday(ctx, &now);
754 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
756 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
757 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
759 // we found the ticket we are looking for
760 // check validity of timestamp
761 // We add a 5 minutes fudge factor to compensate for potential
762 // clock skew errors between the KDC and client OS
764 valid = ((creds.times.starttime > 0) &&
765 now >= (creds.times.starttime - 300) &&
766 now < (creds.times.endtime + 300) &&
767 !(creds.ticket_flags & TKT_FLG_INVALID));
769 if ( next->from_lsa) {
771 next->expiration_time = creds.times.endtime;
773 } else if ( valid ) {
775 next->expiration_time = creds.times.endtime;
776 next->renew = (creds.times.renew_till > creds.times.endtime) &&
777 (creds.ticket_flags & TKT_FLG_RENEWABLE);
780 next->expiration_time = 0;
784 pkrb5_free_cred_contents(ctx, &creds);
785 cc_code = KRB5_CC_END;
788 pkrb5_free_cred_contents(ctx, &creds);
791 if (cc_code == KRB5_CC_END) {
792 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
793 if (code) goto cleanup;
797 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
798 code = pkrb5_cc_set_flags(ctx, cc, flags);
803 pkrb5_free_unparsed_name(ctx,pname);
805 pkrb5_free_principal(ctx,principal);
809 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
811 struct principal_ccache_data * next = princ_cc_data;
812 char * response = NULL;
814 if ( !principal || !ccache )
818 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
820 // we always want to prefer the MS Kerberos LSA cache or
821 // the cache afscreds created specifically for the principal
822 // if the current entry is either one, drop the previous find
823 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
826 response = _strdup(next->ccache_name);
827 // MS Kerberos LSA is our best option so use it and quit
828 if ( next->from_lsa )
842 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
844 struct principal_ccache_data ** next = &princ_cc_data;
846 if ( !pname && !ccname )
850 if ( !strcmp((*next)->principal,pname) ||
851 !strcmp((*next)->ccache_name,ccname) ) {
853 free((*next)->principal);
854 free((*next)->ccache_name);
856 (*next) = (*next)->next;
863 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
865 struct cell_principal_map * next = cell_princ_map;
867 // Search the existing list to see if we have a match
869 for ( ; next ; next = next->next ) {
870 if ( !strcmp(next->cell, cell) ) {
871 if ( !strcmp(next->principal,pname) ) {
872 next->active = active;
875 // OpenAFS currently has a restriction of one active token per cell
876 // Therefore, whenever we update the table with a new active cell we
877 // must mark all of the other principal to cell entries as inactive.
885 // If not, match add a new node to the beginning of the list and assign init it
887 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
888 next->next = cell_princ_map;
889 cell_princ_map = next;
890 next->principal = _strdup(pname);
891 next->cell = _strdup(cell);
892 next->active = active;
897 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
899 struct cell_principal_map ** next = &cell_princ_map;
901 if ( !pname && !cell )
905 if ( !strcmp((*next)->principal,pname) ||
906 !strcmp((*next)->cell,cell) ) {
908 free((*next)->principal);
911 (*next) = (*next)->next;
917 // Returns (if possible) a principal which has been known in
918 // the past to have been used to obtain tokens for the specified
920 // TODO: Attempt to return one which has not yet expired by checking
921 // the principal/ccache data
923 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
925 struct cell_principal_map * next_map = cell_princ_map;
926 const char * princ = NULL;
933 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
936 next_map = next_map->next;
939 if ( !principals || !count )
942 *principals = (char **) malloc(sizeof(char *) * count);
943 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
945 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
946 (*principals)[i++] = _strdup(next_map->principal);
953 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
956 struct cell_principal_map * next_map = cell_princ_map;
957 const char * princ = NULL;
963 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
966 next_map = next_map->next;
972 *cells = (char **) malloc(sizeof(char *) * count);
973 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
975 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
976 (*cells)[i++] = _strdup(next_map->cell);
982 /* Given a principal return an existing ccache or create one and return */
984 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
986 krb5_context ctx = NULL;
988 char * ccname = NULL;
989 krb5_error_code code;
991 if (!pkrb5_init_context)
997 code = pkrb5_init_context(&ctx);
998 if (code) goto cleanup;
1002 code = pkrb5_unparse_name(ctx, principal, &pname);
1003 if (code) goto cleanup;
1005 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
1006 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
1007 ccname = (char *)malloc(strlen(pname) + 5);
1008 sprintf(ccname,"API:%s",pname);
1010 code = pkrb5_cc_resolve(ctx, ccname, cc);
1012 code = pkrb5_cc_default(ctx, cc);
1013 if (code) goto cleanup;
1020 pkrb5_free_unparsed_name(ctx,pname);
1021 if (ctx && (ctx != alt_ctx))
1022 pkrb5_free_context(ctx);
1027 // Import Microsoft Credentials into a new MIT ccache
1029 KFW_import_windows_lsa(void)
1031 krb5_context ctx = NULL;
1032 krb5_ccache cc = NULL;
1033 krb5_principal princ = NULL;
1034 char * pname = NULL;
1035 krb5_data * princ_realm;
1036 krb5_error_code code;
1037 char cell[128]="", realm[128]="", *def_realm = 0;
1039 DWORD dwMsLsaImport;
1041 if (!pkrb5_init_context)
1044 code = pkrb5_init_context(&ctx);
1045 if (code) goto cleanup;
1047 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
1048 if (code) goto cleanup;
1050 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
1052 code = pkrb5_cc_get_principal(ctx, cc, &princ);
1053 if ( code ) goto cleanup;
1055 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
1056 switch ( dwMsLsaImport ) {
1057 case 0: /* do not import */
1059 case 1: /* always import */
1061 case 2: { /* matching realm */
1062 char ms_realm[128] = "", *r;
1065 for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) {
1066 *r = krb5_princ_realm(ctx, princ)->data[i];
1070 if (code = pkrb5_get_default_realm(ctx, &def_realm))
1073 if (strcmp(def_realm, ms_realm))
1081 code = pkrb5_unparse_name(ctx,princ,&pname);
1082 if ( code ) goto cleanup;
1084 princ_realm = krb5_princ_realm(ctx, princ);
1085 for ( i=0; i<princ_realm->length; i++ ) {
1086 realm[i] = princ_realm->data[i];
1087 cell[i] = tolower(princ_realm->data[i]);
1092 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
1093 if ( IsDebuggerPresent() ) {
1095 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1096 OutputDebugString(message);
1098 if ( code ) goto cleanup;
1100 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1104 pkrb5_free_unparsed_name(ctx,pname);
1106 pkrb5_free_principal(ctx,princ);
1108 pkrb5_free_default_realm(ctx, def_realm);
1110 pkrb5_cc_close(ctx,cc);
1112 pkrb5_free_context(ctx);
1114 #endif /* USE_MS2MIT */
1116 // If there are existing MIT credentials, copy them to a new
1117 // ccache named after the principal
1119 // Enumerate all existing MIT ccaches and construct entries
1120 // in the principal_ccache table
1122 // Enumerate all existing AFS Tokens and construct entries
1123 // in the cell_principal table
1125 KFW_import_ccache_data(void)
1127 krb5_context ctx = NULL;
1128 krb5_ccache cc = NULL;
1129 krb5_principal principal = NULL;
1131 krb5_error_code code;
1132 krb5_error_code cc_code;
1134 apiCB * cc_ctx = NULL;
1135 struct _infoNC ** pNCi = NULL;
1138 if ( !pcc_initialize )
1141 if ( IsDebuggerPresent() )
1142 OutputDebugString("KFW_import_ccache_data()\n");
1144 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1145 if (code) goto cleanup;
1147 code = pcc_get_NC_info(cc_ctx, &pNCi);
1148 if (code) goto cleanup;
1150 code = pkrb5_init_context(&ctx);
1151 if (code) goto cleanup;
1153 for ( i=0; pNCi[i]; i++ ) {
1154 if ( pNCi[i]->vers != CC_CRED_V5 )
1156 if ( IsDebuggerPresent() ) {
1157 OutputDebugString("Principal: ");
1158 OutputDebugString(pNCi[i]->principal);
1159 OutputDebugString(" in ccache ");
1160 OutputDebugString(pNCi[i]->name);
1161 OutputDebugString("\n");
1163 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1164 && strcmp(pNCi[i]->name,LSA_CCNAME)
1167 for ( j=0; pNCi[j]; j++ ) {
1168 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1174 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1175 if (code) goto loop_cleanup;
1178 krb5_ccache oldcc = 0;
1180 if ( IsDebuggerPresent() )
1181 OutputDebugString("copying ccache data to new ccache\n");
1183 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1184 if (code) goto loop_cleanup;
1185 code = pkrb5_cc_initialize(ctx, cc, principal);
1186 if (code) goto loop_cleanup;
1188 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1189 if (code) goto loop_cleanup;
1190 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1192 code = pkrb5_cc_close(ctx,cc);
1194 code = pkrb5_cc_close(ctx,oldcc);
1196 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1199 code = pkrb5_cc_close(ctx,oldcc);
1202 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1203 if (code) goto loop_cleanup;
1206 flags = 0; // turn off OPENCLOSE mode
1207 code = pkrb5_cc_set_flags(ctx, cc, flags);
1208 if ( code ) goto cleanup;
1210 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1212 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1214 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1215 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1216 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1217 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1218 if ( sname && cell && !strcmp("afs",sname->data) ) {
1219 struct ktc_principal aserver;
1220 struct ktc_principal aclient;
1221 struct ktc_token atoken;
1224 if ( IsDebuggerPresent() ) {
1225 OutputDebugString("Found AFS ticket: ");
1226 OutputDebugString(sname->data);
1228 OutputDebugString("/");
1229 OutputDebugString(cell->data);
1231 OutputDebugString("@");
1232 OutputDebugString(realm->data);
1233 OutputDebugString("\n");
1236 memset(&aserver, '\0', sizeof(aserver));
1237 strcpy(aserver.name, sname->data);
1238 strcpy(aserver.cell, cell->data);
1240 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1242 // Found a token in AFS Client Server which matches
1243 char pname[128], *p, *q;
1244 for ( p=pname, q=aclient.name; *q; p++, q++)
1246 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1250 if ( IsDebuggerPresent() ) {
1251 OutputDebugString("Found AFS token: ");
1252 OutputDebugString(pname);
1253 OutputDebugString("\n");
1256 if ( strcmp(pname,pNCi[i]->principal) )
1258 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1260 // Attempt to import it
1261 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1263 if ( IsDebuggerPresent() ) {
1264 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1267 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data,
1271 pLeash_get_default_lifetime(),
1272 #endif /* USE_LEASH */
1274 if ( IsDebuggerPresent() ) {
1276 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1277 OutputDebugString(message);
1280 } else if ( IsDebuggerPresent() ) {
1281 OutputDebugString("Found ticket: ");
1282 OutputDebugString(sname->data);
1283 if ( cell && cell->data ) {
1284 OutputDebugString("/");
1285 OutputDebugString(cell->data);
1287 OutputDebugString("@");
1288 OutputDebugString(realm->data);
1289 OutputDebugString("\n");
1291 pkrb5_free_cred_contents(ctx, &creds);
1294 if (cc_code == KRB5_CC_END) {
1295 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1296 if (cc_code) goto loop_cleanup;
1300 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1301 code = pkrb5_cc_set_flags(ctx, cc, flags);
1303 pkrb5_cc_close(ctx,cc);
1307 pkrb5_free_principal(ctx,principal);
1314 pkrb5_free_context(ctx);
1316 pcc_free_NC_info(cc_ctx, &pNCi);
1318 pcc_shutdown(&cc_ctx);
1323 KFW_AFS_get_cred( char * username,
1330 krb5_context ctx = NULL;
1331 krb5_ccache cc = NULL;
1332 char * realm = NULL, * userrealm = NULL;
1333 krb5_principal principal = NULL;
1334 char * pname = NULL;
1335 krb5_error_code code;
1336 char local_cell[CELL_MAXNAMELEN+1];
1337 char **cells = NULL;
1339 struct afsconf_cell cellconfig;
1342 if (!pkrb5_init_context)
1345 if ( IsDebuggerPresent() ) {
1346 OutputDebugString("KFW_AFS_get_cred for token ");
1347 OutputDebugString(username);
1348 OutputDebugString(" in cell ");
1349 OutputDebugString(cell);
1350 OutputDebugString("\n");
1353 memset(&cellconfig, 0, sizeof(cellconfig));
1355 code = pkrb5_init_context(&ctx);
1356 if ( code ) goto cleanup;
1358 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1359 if ( code ) goto cleanup;
1361 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1363 userrealm = strchr(username,'@');
1365 pname = strdup(username);
1366 if (!KFW_accept_dotted_usernames()) {
1367 userrealm = strchr(pname, '@');
1370 /* handle kerberos iv notation */
1371 while ( dot = strchr(pname,'.') ) {
1377 pname = malloc(strlen(username) + strlen(realm) + 2);
1379 strcpy(pname, username);
1381 if (!KFW_accept_dotted_usernames()) {
1382 /* handle kerberos iv notation */
1383 while ( dot = strchr(pname,'.') ) {
1388 strcat(pname,realm);
1390 if ( IsDebuggerPresent() ) {
1391 OutputDebugString("Realm: ");
1392 OutputDebugString(realm);
1393 OutputDebugString("\n");
1396 code = pkrb5_parse_name(ctx, pname, &principal);
1397 if ( code ) goto cleanup;
1399 code = KFW_get_ccache(ctx, principal, &cc);
1400 if ( code ) goto cleanup;
1402 if ( lifetime == 0 )
1406 lifetime = pLeash_get_default_lifetime();
1409 if ( password && password[0] ) {
1410 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1415 1, /* forwardable */
1416 0, /* not proxiable */
1418 1, /* noaddresses */
1419 0 /* no public ip */
1421 pLeash_get_default_forwardable(),
1422 pLeash_get_default_proxiable(),
1423 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1424 pLeash_get_default_noaddresses(),
1425 pLeash_get_default_publicip()
1426 #endif /* USE_LEASH */
1429 if ( IsDebuggerPresent() ) {
1431 sprintf(message,"KFW_kinit() returns: %d\n",code);
1432 OutputDebugString(message);
1434 if ( code ) goto cleanup;
1436 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1439 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1440 if ( IsDebuggerPresent() ) {
1442 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1443 OutputDebugString(message);
1445 if ( code ) goto cleanup;
1447 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1449 // Attempt to obtain new tokens for other cells supported by the same
1451 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1452 if ( cell_count > 1 ) {
1453 while ( cell_count-- ) {
1454 if ( strcmp(cells[cell_count],cell) ) {
1455 if ( IsDebuggerPresent() ) {
1457 sprintf(message,"found another cell for the same principal: %s\n",cell);
1458 OutputDebugString(message);
1461 if (cellconfig.linkedCell) {
1462 free(cellconfig.linkedCell);
1463 cellconfig.linkedCell = NULL;
1465 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1466 if ( code ) continue;
1468 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1469 if ( IsDebuggerPresent() ) {
1470 OutputDebugString("Realm: ");
1471 OutputDebugString(realm);
1472 OutputDebugString("\n");
1475 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1476 if ( IsDebuggerPresent() ) {
1478 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1479 OutputDebugString(message);
1482 free(cells[cell_count]);
1485 } else if ( cell_count == 1 ) {
1494 pkrb5_cc_close(ctx, cc);
1495 if ( cellconfig.linkedCell )
1496 free(cellconfig.linkedCell);
1498 if ( code && reasonP ) {
1499 char *msg = pkrb5_get_error_message(ctx, code);
1500 *reasonP = strdup(msg);
1501 pkrb5_free_error_message(ctx, msg);
1507 KFW_AFS_destroy_tickets_for_cell(char * cell)
1509 krb5_context ctx = NULL;
1510 krb5_error_code code;
1512 char ** principals = NULL;
1514 if (!pkrb5_init_context)
1517 if ( IsDebuggerPresent() ) {
1518 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1519 OutputDebugString(cell);
1520 OutputDebugString("\n");
1523 code = pkrb5_init_context(&ctx);
1526 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1528 krb5_principal princ = 0;
1532 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1533 if ( cell_count > 1 ) {
1534 // TODO - What we really should do here is verify whether or not any of the
1535 // other cells which use this principal to obtain its credentials actually
1536 // have valid tokens or not. If they are currently using these credentials
1537 // we will skip them. For the time being we assume that if there is an active
1538 // map in the table that they are actively being used.
1542 code = pkrb5_parse_name(ctx, principals[count], &princ);
1543 if (code) goto loop_cleanup;
1545 code = KFW_get_ccache(ctx, princ, &cc);
1546 if (code) goto loop_cleanup;
1548 code = pkrb5_cc_destroy(ctx, cc);
1553 pkrb5_cc_close(ctx, cc);
1557 pkrb5_free_principal(ctx, princ);
1561 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1562 free(principals[count]);
1567 pkrb5_free_context(ctx);
1572 KFW_AFS_destroy_tickets_for_principal(char * user)
1574 krb5_context ctx = NULL;
1575 krb5_error_code code;
1577 char ** cells = NULL;
1578 krb5_principal princ = NULL;
1579 krb5_ccache cc = NULL;
1581 if (!pkrb5_init_context)
1584 if ( IsDebuggerPresent() ) {
1585 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1586 OutputDebugString(user);
1587 OutputDebugString("\n");
1590 code = pkrb5_init_context(&ctx);
1593 code = pkrb5_parse_name(ctx, user, &princ);
1594 if (code) goto loop_cleanup;
1596 code = KFW_get_ccache(ctx, princ, &cc);
1597 if (code) goto loop_cleanup;
1599 code = pkrb5_cc_destroy(ctx, cc);
1604 pkrb5_cc_close(ctx, cc);
1608 pkrb5_free_principal(ctx, princ);
1612 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1615 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1622 pkrb5_free_context(ctx);
1627 KFW_AFS_renew_expiring_tokens(void)
1629 krb5_error_code code = 0;
1630 krb5_context ctx = NULL;
1631 krb5_ccache cc = NULL;
1633 struct principal_ccache_data * pcc_next = princ_cc_data;
1636 const char * realm = NULL;
1637 char local_cell[CELL_MAXNAMELEN+1]="";
1638 struct afsconf_cell cellconfig;
1640 if (!pkrb5_init_context)
1643 if ( pcc_next == NULL ) // nothing to do
1646 if ( IsDebuggerPresent() ) {
1647 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1650 memset(&cellconfig, 0, sizeof(cellconfig));
1652 code = pkrb5_init_context(&ctx);
1653 if (code) goto cleanup;
1655 code = pkrb5_timeofday(ctx, &now);
1656 if (code) goto cleanup;
1658 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1659 if ( pcc_next->expired )
1662 if ( now >= (pcc_next->expiration_time) ) {
1663 if ( !pcc_next->from_lsa ) {
1664 pcc_next->expired = 1;
1669 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1670 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1673 code = KFW_renew(ctx,cc);
1675 if ( code && pcc_next->from_lsa)
1677 #endif /* USE_MS2MIT */
1680 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1681 if (code) goto loop_cleanup;
1683 // Attempt to obtain new tokens for other cells supported by the same
1685 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1686 if ( cell_count > 0 ) {
1687 while ( cell_count-- ) {
1688 if ( IsDebuggerPresent() ) {
1689 OutputDebugString("Cell: ");
1690 OutputDebugString(cells[cell_count]);
1691 OutputDebugString("\n");
1693 if (cellconfig.linkedCell) {
1694 free(cellconfig.linkedCell);
1695 cellconfig.linkedCell = NULL;
1697 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1698 if ( code ) continue;
1699 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1700 if ( IsDebuggerPresent() ) {
1701 OutputDebugString("Realm: ");
1702 OutputDebugString(realm);
1703 OutputDebugString("\n");
1705 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1706 if ( IsDebuggerPresent() ) {
1708 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1709 OutputDebugString(message);
1711 free(cells[cell_count]);
1719 pkrb5_cc_close(ctx,cc);
1726 pkrb5_cc_close(ctx,cc);
1728 pkrb5_free_context(ctx);
1729 if (cellconfig.linkedCell)
1730 free(cellconfig.linkedCell);
1737 KFW_AFS_renew_token_for_cell(char * cell)
1739 krb5_error_code code = 0;
1740 krb5_context ctx = NULL;
1742 char ** principals = NULL;
1744 if (!pkrb5_init_context)
1747 if ( IsDebuggerPresent() ) {
1748 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1749 OutputDebugString(cell);
1750 OutputDebugString("\n");
1753 code = pkrb5_init_context(&ctx);
1754 if (code) goto cleanup;
1756 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1758 // We know we must have a credential somewhere since we are
1759 // trying to renew a token
1761 KFW_import_ccache_data();
1762 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1765 krb5_principal princ = 0;
1766 krb5_principal service = 0;
1768 krb5_creds mcreds, creds;
1769 #endif /* COMMENT */
1771 const char * realm = NULL;
1772 struct afsconf_cell cellconfig;
1773 char local_cell[CELL_MAXNAMELEN+1];
1775 memset(&cellconfig, 0, sizeof(cellconfig));
1778 code = pkrb5_parse_name(ctx, principals[count], &princ);
1779 if (code) goto loop_cleanup;
1781 code = KFW_get_ccache(ctx, princ, &cc);
1782 if (code) goto loop_cleanup;
1784 if (cellconfig.linkedCell) {
1785 free(cellconfig.linkedCell);
1786 cellconfig.linkedCell = NULL;
1788 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1789 if ( code ) goto loop_cleanup;
1791 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1792 if ( IsDebuggerPresent() ) {
1793 OutputDebugString("Realm: ");
1794 OutputDebugString(realm);
1795 OutputDebugString("\n");
1799 /* krb5_cc_remove_cred() is not implemented
1802 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1803 realm, "afs", cell, NULL);
1805 memset(&mcreds, 0, sizeof(krb5_creds));
1806 mcreds.client = princ;
1807 mcreds.server = service;
1809 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1811 if ( IsDebuggerPresent() ) {
1812 char * cname, *sname;
1813 pkrb5_unparse_name(ctx, creds.client, &cname);
1814 pkrb5_unparse_name(ctx, creds.server, &sname);
1815 OutputDebugString("Removing credential for client \"");
1816 OutputDebugString(cname);
1817 OutputDebugString("\" and service \"");
1818 OutputDebugString(sname);
1819 OutputDebugString("\"\n");
1820 pkrb5_free_unparsed_name(ctx,cname);
1821 pkrb5_free_unparsed_name(ctx,sname);
1824 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1825 pkrb5_free_principal(ctx, creds.client);
1826 pkrb5_free_principal(ctx, creds.server);
1829 #endif /* COMMENT */
1831 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1832 if ( IsDebuggerPresent() ) {
1834 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1835 OutputDebugString(message);
1840 pkrb5_cc_close(ctx, cc);
1844 pkrb5_free_principal(ctx, princ);
1848 pkrb5_free_principal(ctx, service);
1851 if (cellconfig.linkedCell) {
1852 free(cellconfig.linkedCell);
1853 cellconfig.linkedCell = NULL;
1856 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1857 free(principals[count]);
1861 code = -1; // we did not renew the tokens
1865 pkrb5_free_context(ctx);
1866 return (code ? FALSE : TRUE);
1871 KFW_AFS_renew_tokens_for_all_cells(void)
1873 struct cell_principal_map * next = cell_princ_map;
1875 if ( IsDebuggerPresent() )
1876 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1881 for ( ; next ; next = next->next ) {
1883 KFW_AFS_renew_token_for_cell(next->cell);
1889 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1891 krb5_error_code code = 0;
1892 krb5_context ctx = NULL;
1893 krb5_ccache cc = NULL;
1894 krb5_principal me = NULL;
1895 krb5_principal server = NULL;
1896 krb5_creds my_creds;
1897 krb5_data *realm = NULL;
1899 if (!pkrb5_init_context)
1902 memset(&my_creds, 0, sizeof(krb5_creds));
1907 code = pkrb5_init_context(&ctx);
1908 if (code) goto cleanup;
1914 code = pkrb5_cc_default(ctx, &cc);
1915 if (code) goto cleanup;
1918 code = pkrb5_cc_get_principal(ctx, cc, &me);
1919 if (code) goto cleanup;
1921 realm = krb5_princ_realm(ctx, me);
1923 code = pkrb5_build_principal_ext(ctx, &server,
1924 realm->length,realm->data,
1925 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1926 realm->length,realm->data,
1931 if ( IsDebuggerPresent() ) {
1932 char * cname, *sname;
1933 pkrb5_unparse_name(ctx, me, &cname);
1934 pkrb5_unparse_name(ctx, server, &sname);
1935 OutputDebugString("Renewing credential for client \"");
1936 OutputDebugString(cname);
1937 OutputDebugString("\" and service \"");
1938 OutputDebugString(sname);
1939 OutputDebugString("\"\n");
1940 pkrb5_free_unparsed_name(ctx,cname);
1941 pkrb5_free_unparsed_name(ctx,sname);
1944 my_creds.client = me;
1945 my_creds.server = server;
1947 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1949 if ( IsDebuggerPresent() ) {
1951 sprintf(message,"krb5_get_renewed_creds() failed: %d\n",code);
1952 OutputDebugString(message);
1957 code = pkrb5_cc_initialize(ctx, cc, me);
1959 if ( IsDebuggerPresent() ) {
1961 sprintf(message,"krb5_cc_initialize() failed: %d\n",code);
1962 OutputDebugString(message);
1967 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1969 if ( IsDebuggerPresent() ) {
1971 sprintf(message,"krb5_cc_store_cred() failed: %d\n",code);
1972 OutputDebugString(message);
1978 if (my_creds.client == me)
1979 my_creds.client = 0;
1980 if (my_creds.server == server)
1981 my_creds.server = 0;
1982 pkrb5_free_cred_contents(ctx, &my_creds);
1984 pkrb5_free_principal(ctx, me);
1986 pkrb5_free_principal(ctx, server);
1987 if (cc && (cc != alt_cc))
1988 pkrb5_cc_close(ctx, cc);
1989 if (ctx && (ctx != alt_ctx))
1990 pkrb5_free_context(ctx);
1995 KFW_kinit( krb5_context alt_ctx,
1998 char *principal_name,
2000 krb5_deltat lifetime,
2003 krb5_deltat renew_life,
2008 krb5_error_code code = 0;
2009 krb5_context ctx = NULL;
2010 krb5_ccache cc = NULL;
2011 krb5_principal me = NULL;
2013 krb5_creds my_creds;
2014 krb5_get_init_creds_opt options;
2015 krb5_address ** addrs = NULL;
2016 int i = 0, addr_count = 0;
2018 if (!pkrb5_init_context)
2021 pkrb5_get_init_creds_opt_init(&options);
2022 memset(&my_creds, 0, sizeof(my_creds));
2030 code = pkrb5_init_context(&ctx);
2031 if (code) goto cleanup;
2037 code = pkrb5_cc_default(ctx, &cc);
2038 if (code) goto cleanup;
2041 code = pkrb5_parse_name(ctx, principal_name, &me);
2045 code = pkrb5_unparse_name(ctx, me, &name);
2053 lifetime = pLeash_get_default_lifetime();
2054 #endif /* USE_LEASH */
2061 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2062 pkrb5_get_init_creds_opt_set_forwardable(&options,
2063 forwardable ? 1 : 0);
2064 pkrb5_get_init_creds_opt_set_proxiable(&options,
2066 pkrb5_get_init_creds_opt_set_renew_life(&options,
2069 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2073 // we are going to add the public IP address specified by the user
2074 // to the list provided by the operating system
2075 krb5_address ** local_addrs=NULL;
2078 pkrb5_os_localaddr(ctx, &local_addrs);
2079 while ( local_addrs[i++] );
2082 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2084 pkrb5_free_addresses(ctx, local_addrs);
2087 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2089 while ( local_addrs[i] ) {
2090 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2091 if (addrs[i] == NULL) {
2092 pkrb5_free_addresses(ctx, local_addrs);
2096 addrs[i]->magic = local_addrs[i]->magic;
2097 addrs[i]->addrtype = local_addrs[i]->addrtype;
2098 addrs[i]->length = local_addrs[i]->length;
2099 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2100 if (!addrs[i]->contents) {
2101 pkrb5_free_addresses(ctx, local_addrs);
2105 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2106 local_addrs[i]->length); /* safe */
2109 pkrb5_free_addresses(ctx, local_addrs);
2111 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2112 if (addrs[i] == NULL)
2115 addrs[i]->magic = KV5M_ADDRESS;
2116 addrs[i]->addrtype = AF_INET;
2117 addrs[i]->length = 4;
2118 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2119 if (!addrs[i]->contents)
2122 netIPAddr = htonl(publicIP);
2123 memcpy(addrs[i]->contents,&netIPAddr,4);
2125 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2130 code = pkrb5_get_init_creds_password(ctx,
2133 password, // password
2134 KRB5_prompter, // prompter
2135 hParent, // prompter data
2142 code = pkrb5_cc_initialize(ctx, cc, me);
2146 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2152 for ( i=0;i<addr_count;i++ ) {
2154 if ( addrs[i]->contents )
2155 free(addrs[i]->contents);
2160 if (my_creds.client == me)
2161 my_creds.client = 0;
2162 pkrb5_free_cred_contents(ctx, &my_creds);
2164 pkrb5_free_unparsed_name(ctx, name);
2166 pkrb5_free_principal(ctx, me);
2167 if (cc && (cc != alt_cc))
2168 pkrb5_cc_close(ctx, cc);
2169 if (ctx && (ctx != alt_ctx))
2170 pkrb5_free_context(ctx);
2176 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2178 krb5_context ctx = NULL;
2179 krb5_ccache cc = NULL;
2180 krb5_error_code code;
2182 if (!pkrb5_init_context)
2191 code = pkrb5_init_context(&ctx);
2192 if (code) goto cleanup;
2198 code = pkrb5_cc_default(ctx, &cc);
2199 if (code) goto cleanup;
2202 code = pkrb5_cc_destroy(ctx, cc);
2203 if ( !code ) cc = 0;
2206 if (cc && (cc != alt_cc))
2207 pkrb5_cc_close(ctx, cc);
2208 if (ctx && (ctx != alt_ctx))
2209 pkrb5_free_context(ctx);
2217 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2219 NTSTATUS Status = 0;
2221 TOKEN_STATISTICS Stats;
2227 *ppSessionData = NULL;
2229 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2233 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2234 CloseHandle( TokenHandle );
2238 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2239 if ( FAILED(Status) || !ppSessionData )
2246 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2247 // cache. It validates whether or not it is reasonable to assume that if we
2248 // attempted to retrieve valid tickets we could do so. Microsoft does not
2249 // automatically renew expired tickets. Therefore, the cache could contain
2250 // expired or invalid tickets. Microsoft also caches the user's password
2251 // and will use it to retrieve new TGTs if the cache is empty and tickets
2255 MSLSA_IsKerberosLogon(VOID)
2257 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2258 BOOL Success = FALSE;
2260 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2261 if ( pSessionData->AuthenticationPackage.Buffer ) {
2267 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2268 usLength = (pSessionData->AuthenticationPackage).Length;
2271 lstrcpynW (buffer, usBuffer, usLength);
2272 lstrcatW (buffer,L"");
2273 if ( !lstrcmpW(L"Kerberos",buffer) )
2277 pLsaFreeReturnBuffer(pSessionData);
2281 #endif /* USE_MS2MIT */
2283 static BOOL CALLBACK
2284 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2288 switch ( message ) {
2290 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2292 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2295 for ( i=0; i < mid_cnt ; i++ ) {
2296 if (mid_tb[i].echo == 0)
2297 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2298 else if (mid_tb[i].echo == 2)
2299 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2304 switch ( LOWORD(wParam) ) {
2306 for ( i=0; i < mid_cnt ; i++ ) {
2307 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2308 *mid_tb[i].buf = '\0';
2312 EndDialog(hDialog, LOWORD(wParam));
2320 lpwAlign( LPWORD lpIn )
2324 ul = (ULONG_PTR) lpIn;
2328 return (LPWORD) ul;;
2332 * dialog widths are measured in 1/4 character widths
2333 * dialog height are measured in 1/8 character heights
2337 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2338 char * ptext[], int numlines, int width,
2339 int tb_cnt, struct textField * tb)
2343 LPDLGITEMTEMPLATE lpdit;
2349 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2356 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2358 // Define a dialog box.
2360 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2361 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2362 | DS_SETFOREGROUND | DS_3DLOOK
2363 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2364 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2367 lpdt->cx = 20 + width * 4;
2368 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2370 lpw = (LPWORD) (lpdt + 1);
2371 *lpw++ = 0; // no menu
2372 *lpw++ = 0; // predefined dialog box class (by default)
2374 lpwsz = (LPWSTR) lpw;
2375 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2377 *lpw++ = 8; // font size (points)
2378 lpwsz = (LPWSTR) lpw;
2379 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2383 //-----------------------
2384 // Define an OK button.
2385 //-----------------------
2386 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2387 lpdit = (LPDLGITEMTEMPLATE) lpw;
2388 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2389 lpdit->dwExtendedStyle = 0;
2390 lpdit->x = (lpdt->cx - 14)/4 - 20;
2391 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2394 lpdit->id = IDOK; // OK button identifier
2396 lpw = (LPWORD) (lpdit + 1);
2398 *lpw++ = 0x0080; // button class
2400 lpwsz = (LPWSTR) lpw;
2401 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2403 *lpw++ = 0; // no creation data
2405 //-----------------------
2406 // Define an Cancel button.
2407 //-----------------------
2408 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2409 lpdit = (LPDLGITEMTEMPLATE) lpw;
2410 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2411 lpdit->dwExtendedStyle = 0;
2412 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2413 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2416 lpdit->id = IDCANCEL; // CANCEL button identifier
2418 lpw = (LPWORD) (lpdit + 1);
2420 *lpw++ = 0x0080; // button class
2422 lpwsz = (LPWSTR) lpw;
2423 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2425 *lpw++ = 0; // no creation data
2427 /* Add controls for preface data */
2428 for ( i=0; i<numlines; i++) {
2429 /*-----------------------
2430 * Define a static text control.
2431 *-----------------------*/
2432 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2433 lpdit = (LPDLGITEMTEMPLATE) lpw;
2434 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2435 lpdit->dwExtendedStyle = 0;
2437 lpdit->y = 10 + i * 14;
2438 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2440 lpdit->id = ID_TEXT + i; // text identifier
2442 lpw = (LPWORD) (lpdit + 1);
2444 *lpw++ = 0x0082; // static class
2446 lpwsz = (LPWSTR) lpw;
2447 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2448 -1, lpwsz, 2*width);
2450 *lpw++ = 0; // no creation data
2453 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2454 int len = (int)strlen(tb[i].label);
2459 for ( i=0; i<tb_cnt; i++) {
2461 /*-----------------------
2462 * Define a static text control.
2463 *-----------------------*/
2464 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2465 lpdit = (LPDLGITEMTEMPLATE) lpw;
2466 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2467 lpdit->dwExtendedStyle = 0;
2469 lpdit->y = 10 + (numlines + i + 1) * 14;
2470 lpdit->cx = pwid * 4;
2472 lpdit->id = ID_TEXT + numlines + i; // text identifier
2474 lpw = (LPWORD) (lpdit + 1);
2476 *lpw++ = 0x0082; // static class
2478 lpwsz = (LPWSTR) lpw;
2479 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2482 *lpw++ = 0; // no creation data
2484 /*-----------------------
2485 * Define an edit control.
2486 *-----------------------*/
2487 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2488 lpdit = (LPDLGITEMTEMPLATE) lpw;
2489 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2490 lpdit->dwExtendedStyle = 0;
2491 lpdit->x = 10 + (pwid + 1) * 4;
2492 lpdit->y = 10 + (numlines + i + 1) * 14;
2493 lpdit->cx = (width - (pwid + 1)) * 4;
2495 lpdit->id = ID_MID_TEXT + i; // identifier
2497 lpw = (LPWORD) (lpdit + 1);
2499 *lpw++ = 0x0081; // edit class
2501 lpwsz = (LPWSTR) lpw;
2502 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2505 *lpw++ = 0; // no creation data
2509 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2510 hwndOwner, (DLGPROC) MultiInputDialogProc);
2514 case 0: /* Timeout */
2522 sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
2523 MessageBox(hwndOwner,
2526 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2533 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2535 HINSTANCE hInst = 0;
2539 char * plines[16], *p = preface ? preface : "";
2542 for ( i=0; i<16; i++ )
2545 while (*p && numlines < 16) {
2546 plines[numlines++] = p;
2547 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2548 if ( *p == '\r' && *(p+1) == '\n' ) {
2551 } else if ( *p == '\n' ) {
2554 if ( strlen(plines[numlines-1]) > maxwidth )
2555 maxwidth = (int)strlen(plines[numlines-1]);
2558 for ( i=0;i<n;i++ ) {
2559 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2560 if ( maxwidth < len )
2564 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2567 static krb5_error_code KRB5_CALLCONV
2568 KRB5_prompter( krb5_context context,
2573 krb5_prompt prompts[])
2575 krb5_error_code errcode = 0;
2577 struct textField * tb = NULL;
2578 int len = 0, blen=0, nlen=0;
2579 HWND hParent = (HWND)data;
2582 nlen = (int)strlen(name)+2;
2585 blen = (int)strlen(banner)+2;
2587 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2590 memset(tb,0,sizeof(struct textField) * num_prompts);
2591 for ( i=0; i < num_prompts; i++ ) {
2592 tb[i].buf = prompts[i].reply->data;
2593 tb[i].len = prompts[i].reply->length;
2594 tb[i].label = prompts[i].prompt;
2596 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2599 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2601 for ( i=0; i < num_prompts; i++ )
2602 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2610 for (i = 0; i < num_prompts; i++) {
2611 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2618 KFW_AFS_wait_for_service_start(void)
2623 CurrentState = SERVICE_START_PENDING;
2624 memset(HostName, '\0', sizeof(HostName));
2625 gethostname(HostName, sizeof(HostName));
2627 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2629 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2631 if ( IsDebuggerPresent() ) {
2632 switch ( CurrentState ) {
2633 case SERVICE_STOPPED:
2634 OutputDebugString("SERVICE_STOPPED\n");
2636 case SERVICE_START_PENDING:
2637 OutputDebugString("SERVICE_START_PENDING\n");
2639 case SERVICE_STOP_PENDING:
2640 OutputDebugString("SERVICE_STOP_PENDING\n");
2642 case SERVICE_RUNNING:
2643 OutputDebugString("SERVICE_RUNNING\n");
2645 case SERVICE_CONTINUE_PENDING:
2646 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2648 case SERVICE_PAUSE_PENDING:
2649 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2651 case SERVICE_PAUSED:
2652 OutputDebugString("SERVICE_PAUSED\n");
2655 OutputDebugString("UNKNOWN Service State\n");
2658 if (CurrentState == SERVICE_STOPPED)
2660 if (CurrentState == SERVICE_RUNNING)
2676 memset(HostName, '\0', sizeof(HostName));
2677 gethostname(HostName, sizeof(HostName));
2678 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2680 if (CurrentState != SERVICE_RUNNING)
2683 rc = ktc_ForgetAllTokens();
2689 #define ALLOW_REGISTER 1
2691 ViceIDToUsername(char *username,
2692 char *realm_of_user,
2693 char *realm_of_cell,
2695 struct ktc_principal *aclient,
2696 struct ktc_principal *aserver,
2697 struct ktc_token *atoken)
2699 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2700 static char confdir[512] = { 0 };
2701 #ifdef AFS_ID_TO_NAME
2702 char username_copy[BUFSIZ];
2703 #endif /* AFS_ID_TO_NAME */
2704 long viceId = ANONYMOUSID; /* AFS uid of user */
2706 #ifdef ALLOW_REGISTER
2708 #endif /* ALLOW_REGISTER */
2710 if (confdir[0] == '\0')
2711 cm_GetConfigDir(confdir, sizeof(confdir));
2713 strcpy(lastcell, aserver->cell);
2715 if (!pr_Initialize (0, confdir, aserver->cell)) {
2716 char sname[PR_MAXNAMELEN];
2717 strncpy(sname, username, PR_MAXNAMELEN);
2718 sname[PR_MAXNAMELEN-1] = '\0';
2719 status = pr_SNameToId (sname, &viceId);
2724 * This is a crock, but it is Transarc's crock, so
2725 * we have to play along in order to get the
2726 * functionality. The way the afs id is stored is
2727 * as a string in the username field of the token.
2728 * Contrary to what you may think by looking at
2729 * the code for tokens, this hack (AFS ID %d) will
2730 * not work if you change %d to something else.
2734 * This code is taken from cklog -- it lets people
2735 * automatically register with the ptserver in foreign cells
2738 #ifdef ALLOW_REGISTER
2740 if (viceId != ANONYMOUSID) {
2741 #else /* ALLOW_REGISTER */
2742 if ((status == 0) && (viceId != ANONYMOUSID))
2743 #endif /* ALLOW_REGISTER */
2745 #ifdef AFS_ID_TO_NAME
2746 strncpy(username_copy, username, BUFSIZ);
2747 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2748 #endif /* AFS_ID_TO_NAME */
2750 #ifdef ALLOW_REGISTER
2751 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2753 strncpy(aclient->name, username, MAXKTCNAMELEN - 1);
2754 strcpy(aclient->instance, "");
2755 strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
2756 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2758 if (status = pr_Initialize(1L, confdir, aserver->cell))
2760 status = pr_CreateUser(username, &id);
2764 #ifdef AFS_ID_TO_NAME
2765 strncpy(username_copy, username, BUFSIZ);
2766 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2767 #endif /* AFS_ID_TO_NAME */
2770 #endif /* ALLOW_REGISTER */
2776 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2777 krb5_error_code code;
2778 krb5_ticket *ticket;
2781 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2783 len = krb5_princ_realm(context, ticket->server)->length;
2784 if (len > destlen - 1)
2787 strncpy(dest, krb5_princ_realm(context, ticket->server)->data, len);
2790 pkrb5_free_ticket(context, ticket);
2796 krb5_context alt_ctx,
2801 int lifetime, /* unused parameter */
2809 #endif /* USE_KRB4 */
2810 struct ktc_principal aserver;
2811 struct ktc_principal aclient;
2812 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2813 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2814 char local_cell[CELL_MAXNAMELEN+1];
2815 char Dmycell[CELL_MAXNAMELEN+1];
2816 struct ktc_token atoken;
2817 struct ktc_token btoken;
2818 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2819 char RealmName[128];
2821 char ServiceName[128];
2825 krb5_context ctx = NULL;
2826 krb5_ccache cc = NULL;
2828 krb5_creds * k5creds = NULL;
2829 krb5_error_code code;
2830 krb5_principal client_principal = NULL;
2831 krb5_data * k5data = NULL;
2835 memset(HostName, '\0', sizeof(HostName));
2836 gethostname(HostName, sizeof(HostName));
2837 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2838 if ( IsDebuggerPresent() )
2839 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2842 if (CurrentState != SERVICE_RUNNING) {
2843 if ( IsDebuggerPresent() )
2844 OutputDebugString("AFSD Service NOT RUNNING\n");
2848 if (!pkrb5_init_context)
2851 memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
2852 memset(RealmName, '\0', sizeof(RealmName));
2853 memset(CellName, '\0', sizeof(CellName));
2854 memset(ServiceName, '\0', sizeof(ServiceName));
2855 memset(realm_of_user, '\0', sizeof(realm_of_user));
2856 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2857 if (cell && cell[0])
2858 strcpy(Dmycell, cell);
2860 memset(Dmycell, '\0', sizeof(Dmycell));
2862 // NULL or empty cell returns information on local cell
2863 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2865 // KFW_AFS_error(rc, "get_cellconfig()");
2872 code = pkrb5_init_context(&ctx);
2873 if (code) goto cleanup;
2879 code = pkrb5_cc_default(ctx, &cc);
2880 if (code) goto skip_krb5_init;
2883 memset(&increds, 0, sizeof(increds));
2885 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2887 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2889 OutputDebugString("Principal Not Found for ccache\n");
2891 goto skip_krb5_init;
2894 if (!KFW_accept_dotted_usernames()) {
2895 /* look for client principals which cannot be distinguished
2896 * from Kerberos 4 multi-component principal names
2898 k5data = krb5_princ_component(ctx,client_principal,0);
2899 for ( i=0; i<k5data->length; i++ ) {
2900 if ( k5data->data[i] == '.' )
2903 if (i != k5data->length)
2905 OutputDebugString("Illegal Principal name contains dot in first component\n");
2906 rc = KRB5KRB_ERR_GENERIC;
2911 i = krb5_princ_realm(ctx, client_principal)->length;
2914 strncpy(realm_of_user,krb5_princ_realm(ctx, client_principal)->data,i);
2915 realm_of_user[i] = 0;
2920 if ( !try_krb5 || !realm_of_user[0] ) {
2921 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2930 strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig));
2932 if (strlen(service) == 0)
2933 strcpy(ServiceName, "afs");
2935 strcpy(ServiceName, service);
2937 if (strlen(cell) == 0)
2938 strcpy(CellName, local_cell);
2940 strcpy(CellName, cell);
2942 /* This is for Kerberos v4 only */
2943 if (strlen(realm) == 0)
2944 strcpy(RealmName, realm_of_cell);
2946 strcpy(RealmName, realm);
2948 memset(&creds, '\0', sizeof(creds));
2952 code = KRB5KRB_ERR_GENERIC;
2955 increds.client = client_principal;
2956 increds.times.endtime = 0;
2957 /* Ask for DES since that is what V4 understands */
2958 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
2960 /* If there was a specific realm we are supposed to try
2963 if (strlen(realm) != 0) {
2964 /* service/cell@REALM */
2966 code = pkrb5_build_principal(ctx, &increds.server,
2972 if ( IsDebuggerPresent() ) {
2973 char * cname, *sname;
2974 pkrb5_unparse_name(ctx, increds.client, &cname);
2975 pkrb5_unparse_name(ctx, increds.server, &sname);
2976 OutputDebugString("Getting tickets for \"");
2977 OutputDebugString(cname);
2978 OutputDebugString("\" and service \"");
2979 OutputDebugString(sname);
2980 OutputDebugString("\"\n");
2981 pkrb5_free_unparsed_name(ctx,cname);
2982 pkrb5_free_unparsed_name(ctx,sname);
2986 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2988 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2989 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
2990 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2991 code == KRB5KRB_AP_ERR_MSG_TYPE) {
2992 /* Or service@REALM */
2993 pkrb5_free_principal(ctx,increds.server);
2995 code = pkrb5_build_principal(ctx, &increds.server,
3001 if ( IsDebuggerPresent() ) {
3002 char * cname, *sname;
3003 pkrb5_unparse_name(ctx, increds.client, &cname);
3004 pkrb5_unparse_name(ctx, increds.server, &sname);
3005 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3006 OutputDebugString("Trying again: getting tickets for \"");
3007 OutputDebugString(cname);
3008 OutputDebugString("\" and service \"");
3009 OutputDebugString(sname);
3010 OutputDebugString("\"\n");
3011 pkrb5_free_unparsed_name(ctx,cname);
3012 pkrb5_free_unparsed_name(ctx,sname);
3016 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3020 /* we have a local realm for the cell */
3021 strcpy(realm_of_cell, realm);
3024 /* Otherwise, first try service/cell@CLIENT_REALM */
3025 if (code = pkrb5_build_principal(ctx, &increds.server,
3026 (int)strlen(realm_of_user),
3035 if ( IsDebuggerPresent() ) {
3036 char * cname, *sname;
3037 pkrb5_unparse_name(ctx, increds.client, &cname);
3038 pkrb5_unparse_name(ctx, increds.server, &sname);
3039 OutputDebugString("Getting tickets for \"");
3040 OutputDebugString(cname);
3041 OutputDebugString("\" and service \"");
3042 OutputDebugString(sname);
3043 OutputDebugString("\"\n");
3044 pkrb5_free_unparsed_name(ctx,cname);
3045 pkrb5_free_unparsed_name(ctx,sname);
3048 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3050 /* The client's realm is a local realm for the cell.
3051 * Save it so that later the pts registration will not
3054 strcpy(realm_of_cell, realm_of_user);
3057 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3058 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3059 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3060 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
3061 strcmp(realm_of_user, realm_of_cell)) {
3062 /* Then service/cell@CELL_REALM */
3063 pkrb5_free_principal(ctx,increds.server);
3065 code = pkrb5_build_principal(ctx, &increds.server,
3066 (int)strlen(realm_of_cell),
3071 if ( IsDebuggerPresent() ) {
3072 char * cname, *sname;
3073 pkrb5_unparse_name(ctx, increds.client, &cname);
3074 pkrb5_unparse_name(ctx, increds.server, &sname);
3075 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3076 OutputDebugString("Trying again: getting tickets for \"");
3077 OutputDebugString(cname);
3078 OutputDebugString("\" and service \"");
3079 OutputDebugString(sname);
3080 OutputDebugString("\"\n");
3081 pkrb5_free_unparsed_name(ctx,cname);
3082 pkrb5_free_unparsed_name(ctx,sname);
3086 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3088 if (!code && !strlen(realm_of_cell))
3089 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3092 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3093 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3094 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3095 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3096 /* Finally service@CELL_REALM */
3097 pkrb5_free_principal(ctx,increds.server);
3099 code = pkrb5_build_principal(ctx, &increds.server,
3100 (int)strlen(realm_of_cell),
3105 if ( IsDebuggerPresent() ) {
3106 char * cname, *sname;
3107 pkrb5_unparse_name(ctx, increds.client, &cname);
3108 pkrb5_unparse_name(ctx, increds.server, &sname);
3109 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3110 OutputDebugString("Trying again: getting tickets for \"");
3111 OutputDebugString(cname);
3112 OutputDebugString("\" and service \"");
3113 OutputDebugString(sname);
3114 OutputDebugString("\"\n");
3115 pkrb5_free_unparsed_name(ctx,cname);
3116 pkrb5_free_unparsed_name(ctx,sname);
3120 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3121 if (!code && !strlen(realm_of_cell))
3122 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3127 if ( IsDebuggerPresent() ) {
3129 sprintf(message,"krb5_get_credentials returns: %d\n",code);
3130 OutputDebugString(message);
3136 /* This code inserts the entire K5 ticket into the token
3137 * No need to perform a krb524 translation which is
3138 * commented out in the code below
3140 if (KFW_use_krb524() ||
3141 k5creds->ticket.length > MAXKTCTICKETLEN)
3144 memset(&aserver, '\0', sizeof(aserver));
3145 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
3146 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
3148 memset(&atoken, '\0', sizeof(atoken));
3149 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3150 atoken.startTime = k5creds->times.starttime;
3151 atoken.endTime = k5creds->times.endtime;
3152 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3153 atoken.ticketLen = k5creds->ticket.length;
3154 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3157 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3158 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3159 if ( rc == KTC_NOCM && retry < 20 ) {
3162 goto retry_gettoken5;
3167 if (atoken.kvno == btoken.kvno &&
3168 atoken.ticketLen == btoken.ticketLen &&
3169 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3170 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3172 /* Success - Nothing to do */
3176 // * Reset the "aclient" structure before we call ktc_SetToken.
3177 // * This structure was first set by the ktc_GetToken call when
3178 // * we were comparing whether identical tokens already existed.
3180 len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
3181 strncpy(aclient.name, k5creds->client->data[0].data, len);
3182 aclient.name[len] = '\0';
3184 if ( k5creds->client->length > 1 ) {
3186 strcat(aclient.name, ".");
3187 p = aclient.name + strlen(aclient.name);
3188 len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
3189 strncpy(p, k5creds->client->data[1].data, len);
3192 aclient.instance[0] = '\0';
3194 strcpy(aclient.cell, realm_of_cell);
3196 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3197 /* For Khimaira, always append the realm name */
3198 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3200 strcat(aclient.name, "@");
3201 p = aclient.name + strlen(aclient.name);
3202 len = min(k5creds->client->realm.length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
3203 strncpy(p, k5creds->client->realm.data, len);
3207 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3208 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3209 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3210 &aclient, &aserver, &atoken);
3213 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
3214 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
3216 aclient.smbname[0] = '\0';
3219 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3221 goto cleanup; /* We have successfully inserted the token */
3227 /* Otherwise, the ticket could have been too large so try to
3228 * convert using the krb524d running with the KDC
3230 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3231 pkrb5_free_creds(ctx, k5creds);
3233 if ( IsDebuggerPresent() ) {
3235 sprintf(message,"krb524_convert_creds_kdc returns: %d\n",code);
3236 OutputDebugString(message);
3241 #endif /* USE_KRB524 */
3245 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3246 if (code == NO_TKT_FIL) {
3247 // if the problem is that we have no krb4 tickets
3248 // do not attempt to continue
3251 if (code != KSUCCESS)
3252 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3254 if (code != KSUCCESS)
3256 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3258 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3263 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3265 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3280 memset(&aserver, '\0', sizeof(aserver));
3281 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
3282 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
3284 memset(&atoken, '\0', sizeof(atoken));
3285 atoken.kvno = creds.kvno;
3286 atoken.startTime = creds.issue_date;
3287 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3288 memcpy(&atoken.sessionKey, creds.session, 8);
3289 atoken.ticketLen = creds.ticket_st.length;
3290 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3293 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3294 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3295 if ( rc == KTC_NOCM && retry < 20 ) {
3298 goto retry_gettoken;
3300 KFW_AFS_error(rc, "ktc_GetToken()");
3305 if (atoken.kvno == btoken.kvno &&
3306 atoken.ticketLen == btoken.ticketLen &&
3307 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3308 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3313 // * Reset the "aclient" structure before we call ktc_SetToken.
3314 // * This structure was first set by the ktc_GetToken call when
3315 // * we were comparing whether identical tokens already existed.
3317 strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
3320 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3321 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3323 strcpy(aclient.instance, "");
3325 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3326 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3327 aclient.name[MAXKTCREALMLEN-1] = '\0';
3329 strcpy(aclient.cell, CellName);
3331 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3332 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3333 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3334 &aclient, &aserver, &atoken);
3337 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
3338 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
3340 aclient.smbname[0] = '\0';
3343 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3345 KFW_AFS_error(rc, "ktc_SetToken()");
3351 if (client_principal)
3352 pkrb5_free_principal(ctx,client_principal);
3353 /* increds.client == client_principal */
3355 pkrb5_free_principal(ctx,increds.server);
3356 if (cc && (cc != alt_cc))
3357 pkrb5_cc_close(ctx, cc);
3358 if (ctx && (ctx != alt_ctx))
3359 pkrb5_free_context(ctx);
3360 if (ak_cellconfig.linkedCell)
3361 free(ak_cellconfig.linkedCell);
3363 return(rc? rc : code);
3366 /**************************************/
3367 /* afs_realm_of_cell(): */
3368 /**************************************/
3370 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3372 static char krbrlm[REALM_SZ+1]="";
3373 char ** realmlist=NULL;
3379 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3380 if ( !r && realmlist && realmlist[0] ) {
3381 strcpy(krbrlm, realmlist[0]);
3382 pkrb5_free_host_realm(ctx, realmlist);
3388 char *t = cellconfig->name;
3393 if (islower(c)) c=toupper(c);
3401 /**************************************/
3402 /* KFW_AFS_get_cellconfig(): */
3403 /**************************************/
3405 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3408 char newcell[CELL_MAXNAMELEN+1];
3409 char linkedcell[CELL_MAXNAMELEN+1]="";
3411 local_cell[0] = (char)0;
3412 memset(cellconfig, 0, sizeof(*cellconfig));
3414 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3415 if (rc = cm_GetRootCellName(local_cell))
3420 if (strlen(cell) == 0)
3421 strcpy(cell, local_cell);
3423 rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3424 if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
3425 rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3428 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3432 strcpy(cellconfig->name, newcell);
3434 cellconfig->linkedCell = strdup(linkedcell);
3439 /**************************************/
3440 /* get_cellconfig_callback(): */
3441 /**************************************/
3443 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
3445 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3447 cc->hostAddr[cc->numServers] = *addrp;
3448 strcpy(cc->hostName[cc->numServers], namep);
3454 /**************************************/
3455 /* KFW_AFS_error(): */
3456 /**************************************/
3458 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3461 const char *errText;
3463 // Using AFS defines as error messages for now, until Transarc
3464 // gets back to me with "string" translations of each of these
3466 if (rc == KTC_ERROR)
3467 errText = "KTC_ERROR";
3468 else if (rc == KTC_TOOBIG)
3469 errText = "KTC_TOOBIG";
3470 else if (rc == KTC_INVAL)
3471 errText = "KTC_INVAL";
3472 else if (rc == KTC_NOENT)
3473 errText = "KTC_NOENT";
3474 else if (rc == KTC_PIOCTLFAIL)
3475 errText = "KTC_PIOCTLFAIL";
3476 else if (rc == KTC_NOPIOCTL)
3477 errText = "KTC_NOPIOCTL";
3478 else if (rc == KTC_NOCELL)
3479 errText = "KTC_NOCELL";
3480 else if (rc == KTC_NOCM)
3481 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3483 errText = "Unknown error!";
3485 sprintf(message, "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3487 if ( IsDebuggerPresent() ) {
3488 OutputDebugString(message);
3489 OutputDebugString("\n");
3491 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3497 LPSTR lpszMachineName,
3498 LPSTR lpszServiceName,
3499 DWORD *lpdwCurrentState)
3502 SC_HANDLE schSCManager = NULL;
3503 SC_HANDLE schService = NULL;
3504 DWORD fdwDesiredAccess = 0;
3505 SERVICE_STATUS ssServiceStatus = {0};
3508 *lpdwCurrentState = 0;
3510 fdwDesiredAccess = GENERIC_READ;
3512 schSCManager = OpenSCManager(lpszMachineName,
3516 if(schSCManager == NULL)
3518 hr = GetLastError();
3522 schService = OpenService(schSCManager,
3526 if(schService == NULL)
3528 hr = GetLastError();
3532 fRet = QueryServiceStatus(schService,
3537 hr = GetLastError();
3541 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3545 CloseServiceHandle(schService);
3546 CloseServiceHandle(schSCManager);
3559 for (n = 0; fi[n].func_ptr_var; n++)
3560 *(fi[n].func_ptr_var) = 0;
3561 if (h) FreeLibrary(h);
3566 const char* dll_name,
3568 HINSTANCE* ph, // [out, optional] - DLL handle
3569 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3570 int cleanup, // cleanup function pointers and unload on error
3571 int go_on, // continue loading even if some functions cannot be loaded
3572 int silent // do not pop-up a system dialog if DLL cannot be loaded
3581 if (pindex) *pindex = -1;
3583 for (n = 0; fi[n].func_ptr_var; n++)
3584 *(fi[n].func_ptr_var) = 0;
3587 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3588 h = LoadLibrary(dll_name);
3596 for (i = 0; (go_on || !error) && (i < n); i++)
3598 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3604 *(fi[i].func_ptr_var) = p;
3607 if (pindex) *pindex = last_i;
3608 if (error && cleanup && !go_on) {
3609 for (i = 0; i < n; i++) {
3610 *(fi[i].func_ptr_var) = 0;
3616 if (error) return 0;
3620 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3622 krb5_context ctx = NULL;
3623 krb5_ccache cc = NULL;
3624 krb5_error_code code;
3626 const char * realm = NULL;
3627 krb5_principal principal = NULL;
3628 char * pname = NULL;
3629 char password[PROBE_PASSWORD_LEN+1];
3630 BOOL serverReachable = 0;
3632 if (!pkrb5_init_context)
3635 code = pkrb5_init_context(&ctx);
3636 if (code) goto cleanup;
3639 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3641 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3642 realm, PROBE_USERNAME, NULL, NULL);
3643 if ( code ) goto cleanup;
3645 code = KFW_get_ccache(ctx, principal, &cc);
3646 if ( code ) goto cleanup;
3648 code = pkrb5_unparse_name(ctx, principal, &pname);
3649 if ( code ) goto cleanup;
3651 pwdata.data = password;
3652 pwdata.length = PROBE_PASSWORD_LEN;
3653 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3656 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3659 password[PROBE_PASSWORD_LEN] = '\0';
3661 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3671 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3672 case KRB5KDC_ERR_CLIENT_REVOKED:
3673 case KRB5KDC_ERR_CLIENT_NOTYET:
3674 case KRB5KDC_ERR_PREAUTH_FAILED:
3675 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3676 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3677 serverReachable = TRUE;
3680 serverReachable = FALSE;
3685 pkrb5_free_unparsed_name(ctx,pname);
3687 pkrb5_free_principal(ctx,principal);
3689 pkrb5_cc_close(ctx,cc);
3691 pkrb5_free_context(ctx);
3693 return serverReachable;
3697 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
3699 krb5_context ctx = NULL;
3700 krb5_error_code code;
3701 krb5_ccache mslsa_ccache=NULL;
3702 krb5_principal princ = NULL;
3703 char * pname = NULL;
3706 if (!KFW_is_available())
3709 if (code = pkrb5_init_context(&ctx))
3712 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3715 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3718 if (code = pkrb5_unparse_name(ctx, princ, &pname))
3721 if ( strlen(pname) < *dwSize ) {
3722 strncpy(szUser, pname, *dwSize);
3723 szUser[*dwSize-1] = '\0';
3726 *dwSize = (DWORD)strlen(pname);
3730 pkrb5_free_unparsed_name(ctx, pname);
3733 pkrb5_free_principal(ctx, princ);
3736 pkrb5_cc_close(ctx, mslsa_ccache);
3739 pkrb5_free_context(ctx);
3744 KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
3746 // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
3747 PSID pSystemSID = NULL;
3748 DWORD SystemSIDlength = 0, UserSIDlength = 0;
3749 PACL ccacheACL = NULL;
3750 DWORD ccacheACLlength = 0;
3751 PTOKEN_USER pTokenUser = NULL;
3760 /* Get System SID */
3761 if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
3767 SystemSIDlength = GetLengthSid(pSystemSID);
3768 ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
3769 + SystemSIDlength - sizeof(DWORD);
3772 if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
3774 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
3775 pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
3777 GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
3782 UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
3784 ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
3789 ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
3794 InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
3795 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3796 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3799 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3800 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3801 pTokenUser->User.Sid);
3802 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3803 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3808 gle = GetLastError();
3809 if (gle != ERROR_NO_TOKEN)
3812 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3813 OWNER_SECURITY_INFORMATION,
3814 pTokenUser->User.Sid,
3818 gle = GetLastError();
3819 if (gle != ERROR_NO_TOKEN)
3823 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3824 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3829 gle = GetLastError();
3830 if (gle != ERROR_NO_TOKEN)
3837 LocalFree(pSystemSID);
3839 LocalFree(pTokenUser);
3841 LocalFree(ccacheACL);
3846 KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
3849 DWORD dwSize = size-1; /* leave room for nul */
3852 if (!hUserToken || !newfilename || size <= 0)
3855 *newfilename = '\0';
3857 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
3858 if ( !dwLen || dwLen > dwSize )
3859 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
3860 if ( !dwLen || dwLen > dwSize )
3863 newfilename[dwSize] = '\0';
3868 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
3870 char filename[MAX_PATH] = "";
3872 char cachename[MAX_PATH + 8] = "FILE:";
3873 krb5_context ctx = NULL;
3874 krb5_error_code code;
3875 krb5_principal princ = NULL;
3876 krb5_ccache cc = NULL;
3877 krb5_ccache ncc = NULL;
3879 if (!pkrb5_init_context || !user || !szLogonId)
3882 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
3883 if ( count > sizeof(filename) || count == 0 ) {
3884 GetWindowsDirectory(filename, sizeof(filename));
3887 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
3890 strcat(filename, "\\");
3891 strcat(filename, szLogonId);
3893 strcat(cachename, filename);
3895 DeleteFile(filename);
3897 code = pkrb5_init_context(&ctx);
3898 if (code) goto cleanup;
3900 code = pkrb5_parse_name(ctx, user, &princ);
3901 if (code) goto cleanup;
3903 code = KFW_get_ccache(ctx, princ, &cc);
3904 if (code) goto cleanup;
3906 code = pkrb5_cc_resolve(ctx, cachename, &ncc);
3907 if (code) goto cleanup;
3909 code = pkrb5_cc_initialize(ctx, ncc, princ);
3910 if (code) goto cleanup;
3912 code = KFW_AFS_set_file_cache_dacl(filename, NULL);
3913 if (code) goto cleanup;
3915 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3919 pkrb5_cc_close(ctx, cc);
3923 pkrb5_cc_close(ctx, ncc);
3927 pkrb5_free_principal(ctx, princ);
3932 pkrb5_free_context(ctx);
3936 KFW_AFS_copy_file_cache_to_default_cache(char * filename)
3938 char cachename[MAX_PATH + 8] = "FILE:";
3939 krb5_context ctx = NULL;
3940 krb5_error_code code;
3941 krb5_principal princ = NULL;
3942 krb5_ccache cc = NULL;
3943 krb5_ccache ncc = NULL;
3946 if (!pkrb5_init_context || !filename)
3949 if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
3952 code = pkrb5_init_context(&ctx);
3955 strcat(cachename, filename);
3957 code = pkrb5_cc_resolve(ctx, cachename, &cc);
3958 if (code) goto cleanup;
3960 code = pkrb5_cc_get_principal(ctx, cc, &princ);
3962 code = pkrb5_cc_default(ctx, &ncc);
3964 code = pkrb5_cc_initialize(ctx, ncc, princ);
3967 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3970 pkrb5_cc_close(ctx, ncc);
3974 retval=0; /* success */
3978 pkrb5_cc_close(ctx, cc);
3982 DeleteFile(filename);
3985 pkrb5_free_principal(ctx, princ);
3990 pkrb5_free_context(ctx);
3995 /* We are including this
3997 /* Ticket lifetime. This defines the table used to lookup lifetime for the
3998 fixed part of rande of the one byte lifetime field. Values less than 0x80
3999 are intrpreted as the number of 5 minute intervals. Values from 0x80 to
4000 0xBF should be looked up in this table. The value of 0x80 is the same using
4001 both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days.
4002 The intervening values of have a fixed ratio of roughly 1.06914. The value
4003 oxFF is defined to mean a ticket has no expiration time. This should be
4004 used advisedly since individual servers may impose defacto upperbounds on
4005 ticket lifetimes. */
4007 #define TKTLIFENUMFIXED 64
4008 #define TKTLIFEMINFIXED 0x80
4009 #define TKTLIFEMAXFIXED 0xBF
4010 #define TKTLIFENOEXPIRE 0xFF
4011 #define MAXTKTLIFETIME (30*24*3600) /* 30 days */
4013 static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
4014 38400, /* 10.67 hours, 0.44 days */
4015 41055, /* 11.40 hours, 0.48 days */
4016 43894, /* 12.19 hours, 0.51 days */
4017 46929, /* 13.04 hours, 0.54 days */
4018 50174, /* 13.94 hours, 0.58 days */
4019 53643, /* 14.90 hours, 0.62 days */
4020 57352, /* 15.93 hours, 0.66 days */
4021 61318, /* 17.03 hours, 0.71 days */
4022 65558, /* 18.21 hours, 0.76 days */
4023 70091, /* 19.47 hours, 0.81 days */
4024 74937, /* 20.82 hours, 0.87 days */
4025 80119, /* 22.26 hours, 0.93 days */
4026 85658, /* 23.79 hours, 0.99 days */
4027 91581, /* 25.44 hours, 1.06 days */
4028 97914, /* 27.20 hours, 1.13 days */
4029 104684, /* 29.08 hours, 1.21 days */
4030 111922, /* 31.09 hours, 1.30 days */
4031 119661, /* 33.24 hours, 1.38 days */
4032 127935, /* 35.54 hours, 1.48 days */
4033 136781, /* 37.99 hours, 1.58 days */
4034 146239, /* 40.62 hours, 1.69 days */
4035 156350, /* 43.43 hours, 1.81 days */
4036 167161, /* 46.43 hours, 1.93 days */
4037 178720, /* 49.64 hours, 2.07 days */
4038 191077, /* 53.08 hours, 2.21 days */
4039 204289, /* 56.75 hours, 2.36 days */
4040 218415, /* 60.67 hours, 2.53 days */
4041 233517, /* 64.87 hours, 2.70 days */
4042 249664, /* 69.35 hours, 2.89 days */
4043 266926, /* 74.15 hours, 3.09 days */
4044 285383, /* 79.27 hours, 3.30 days */
4045 305116, /* 84.75 hours, 3.53 days */
4046 326213, /* 90.61 hours, 3.78 days */
4047 348769, /* 96.88 hours, 4.04 days */
4048 372885, /* 103.58 hours, 4.32 days */
4049 398668, /* 110.74 hours, 4.61 days */
4050 426234, /* 118.40 hours, 4.93 days */
4051 455705, /* 126.58 hours, 5.27 days */
4052 487215, /* 135.34 hours, 5.64 days */
4053 520904, /* 144.70 hours, 6.03 days */
4054 556921, /* 154.70 hours, 6.45 days */
4055 595430, /* 165.40 hours, 6.89 days */
4056 636601, /* 176.83 hours, 7.37 days */
4057 680618, /* 189.06 hours, 7.88 days */
4058 727680, /* 202.13 hours, 8.42 days */
4059 777995, /* 216.11 hours, 9.00 days */
4060 831789, /* 231.05 hours, 9.63 days */
4061 889303, /* 247.03 hours, 10.29 days */
4062 950794, /* 264.11 hours, 11.00 days */
4063 1016537, /* 282.37 hours, 11.77 days */
4064 1086825, /* 301.90 hours, 12.58 days */
4065 1161973, /* 322.77 hours, 13.45 days */
4066 1242318, /* 345.09 hours, 14.38 days */
4067 1328218, /* 368.95 hours, 15.37 days */
4068 1420057, /* 394.46 hours, 16.44 days */
4069 1518247, /* 421.74 hours, 17.57 days */
4070 1623226, /* 450.90 hours, 18.79 days */
4071 1735464, /* 482.07 hours, 20.09 days */
4072 1855462, /* 515.41 hours, 21.48 days */
4073 1983758, /* 551.04 hours, 22.96 days */
4074 2120925, /* 589.15 hours, 24.55 days */
4075 2267576, /* 629.88 hours, 26.25 days */
4076 2424367, /* 673.44 hours, 28.06 days */
4078 }; /* 720.00 hours, 30.00 days */
4080 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
4081 * returns the corresponding end time. There are four simple cases to be
4082 * handled. The first is a life of 0xff, meaning no expiration, and results in
4083 * an end time of 0xffffffff. The second is when life is less than the values
4084 * covered by the table. In this case, the end time is the start time plus the
4085 * number of 5 minute intervals specified by life. The third case returns
4086 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
4087 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
4088 * table to extract the lifetime in seconds, which is added to start to produce
4092 life_to_time(afs_uint32 start, unsigned char life)
4096 if (life == TKTLIFENOEXPIRE)
4098 if (life < TKTLIFEMINFIXED)
4099 return start + life * 5 * 60;
4100 if (life > TKTLIFEMAXFIXED)
4101 return start + MAXTKTLIFETIME;
4102 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
4103 return start + realLife;
4106 /* time_to_life - takes start and end times for the ticket and returns a
4107 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
4108 * lifetimes above 127*5minutes. First, the special case of (end ==
4109 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
4110 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
4111 * less than the first table entry are handled by rounding the requested
4112 * lifetime *up* to the next 5 minute interval. The final step is to search
4113 * the table for the smallest entry *greater than or equal* to the requested
4114 * entry. The actual code is prepared to handle the case where the table is
4115 * unordered but that it an unnecessary frill. */
4117 static unsigned char
4118 time_to_life(afs_uint32 start, afs_uint32 end)
4120 int lifetime = end - start;
4124 if (end == NEVERDATE)
4125 return TKTLIFENOEXPIRE;
4126 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
4128 if (lifetime < tkt_lifetimes[0])
4129 return (lifetime + 5 * 60 - 1) / (5 * 60);
4131 best = MAXKTCTICKETLIFETIME;
4132 for (i = 0; i < TKTLIFENUMFIXED; i++)
4133 if (tkt_lifetimes[i] >= lifetime) {
4134 int diff = tkt_lifetimes[i] - lifetime;
4142 return best_i + TKTLIFEMINFIXED;