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 #include "afskfw-int.h"
74 #include <afs/ptserver.h>
75 #include <afs/ptuser.h>
78 #include <WINNT\afsreg.h>
81 * TIMING _____________________________________________________________________
85 #define cminREMIND_TEST 1 // test every minute for expired creds
86 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
87 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
88 #define cminMINLIFE 30 // minimum life of Kerberos creds
90 #define c100ns1SECOND (LONGLONG)10000000
91 #define cmsec1SECOND 1000
92 #define cmsec1MINUTE 60000
93 #define csec1MINUTE 60
95 /* Function Pointer Declarations for Delayed Loading */
97 DECL_FUNC_PTR(cc_initialize);
98 DECL_FUNC_PTR(cc_shutdown);
99 DECL_FUNC_PTR(cc_get_NC_info);
100 DECL_FUNC_PTR(cc_free_NC_info);
104 DECL_FUNC_PTR(Leash_get_default_lifetime);
105 DECL_FUNC_PTR(Leash_get_default_forwardable);
106 DECL_FUNC_PTR(Leash_get_default_renew_till);
107 DECL_FUNC_PTR(Leash_get_default_noaddresses);
108 DECL_FUNC_PTR(Leash_get_default_proxiable);
109 DECL_FUNC_PTR(Leash_get_default_publicip);
110 DECL_FUNC_PTR(Leash_get_default_use_krb4);
111 DECL_FUNC_PTR(Leash_get_default_life_min);
112 DECL_FUNC_PTR(Leash_get_default_life_max);
113 DECL_FUNC_PTR(Leash_get_default_renew_min);
114 DECL_FUNC_PTR(Leash_get_default_renew_max);
115 DECL_FUNC_PTR(Leash_get_default_renewable);
116 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
120 DECL_FUNC_PTR(krb5_change_password);
121 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
122 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
123 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
124 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
125 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
126 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
127 DECL_FUNC_PTR(krb5_get_init_creds_password);
128 DECL_FUNC_PTR(krb5_build_principal_ext);
129 DECL_FUNC_PTR(krb5_cc_get_name);
130 DECL_FUNC_PTR(krb5_cc_resolve);
131 DECL_FUNC_PTR(krb5_cc_default);
132 DECL_FUNC_PTR(krb5_cc_default_name);
133 DECL_FUNC_PTR(krb5_cc_set_default_name);
134 DECL_FUNC_PTR(krb5_cc_initialize);
135 DECL_FUNC_PTR(krb5_cc_destroy);
136 DECL_FUNC_PTR(krb5_cc_close);
137 DECL_FUNC_PTR(krb5_cc_store_cred);
138 DECL_FUNC_PTR(krb5_cc_copy_creds);
139 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
140 DECL_FUNC_PTR(krb5_cc_get_principal);
141 DECL_FUNC_PTR(krb5_cc_start_seq_get);
142 DECL_FUNC_PTR(krb5_cc_next_cred);
143 DECL_FUNC_PTR(krb5_cc_end_seq_get);
144 DECL_FUNC_PTR(krb5_cc_remove_cred);
145 DECL_FUNC_PTR(krb5_cc_set_flags);
146 DECL_FUNC_PTR(krb5_cc_get_type);
147 DECL_FUNC_PTR(krb5_free_context);
148 DECL_FUNC_PTR(krb5_free_cred_contents);
149 DECL_FUNC_PTR(krb5_free_principal);
150 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
151 DECL_FUNC_PTR(krb5_init_context);
152 DECL_FUNC_PTR(krb5_parse_name);
153 DECL_FUNC_PTR(krb5_timeofday);
154 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
155 DECL_FUNC_PTR(krb5_unparse_name);
156 DECL_FUNC_PTR(krb5_get_credentials);
157 DECL_FUNC_PTR(krb5_mk_req);
158 DECL_FUNC_PTR(krb5_sname_to_principal);
159 DECL_FUNC_PTR(krb5_get_credentials_renew);
160 DECL_FUNC_PTR(krb5_free_data);
161 DECL_FUNC_PTR(krb5_free_data_contents);
162 DECL_FUNC_PTR(krb5_free_unparsed_name);
163 DECL_FUNC_PTR(krb5_os_localaddr);
164 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
165 DECL_FUNC_PTR(krb5_copy_data);
166 DECL_FUNC_PTR(krb5_free_creds);
167 DECL_FUNC_PTR(krb5_build_principal);
168 DECL_FUNC_PTR(krb5_get_renewed_creds);
169 DECL_FUNC_PTR(krb5_get_default_config_files);
170 DECL_FUNC_PTR(krb5_free_config_files);
171 DECL_FUNC_PTR(krb5_get_default_realm);
172 DECL_FUNC_PTR(krb5_free_default_realm);
173 DECL_FUNC_PTR(krb5_free_ticket);
174 DECL_FUNC_PTR(krb5_decode_ticket);
175 DECL_FUNC_PTR(krb5_get_host_realm);
176 DECL_FUNC_PTR(krb5_free_host_realm);
177 DECL_FUNC_PTR(krb5_free_addresses);
178 DECL_FUNC_PTR(krb5_c_random_make_octets);
182 DECL_FUNC_PTR(krb524_init_ets);
183 DECL_FUNC_PTR(krb524_convert_creds_kdc);
188 DECL_FUNC_PTR(krb_get_cred);
189 DECL_FUNC_PTR(tkt_string);
190 DECL_FUNC_PTR(krb_get_tf_realm);
191 DECL_FUNC_PTR(krb_mk_req);
195 DECL_FUNC_PTR(com_err);
196 DECL_FUNC_PTR(error_message);
199 DECL_FUNC_PTR(profile_init);
200 DECL_FUNC_PTR(profile_release);
201 DECL_FUNC_PTR(profile_get_subsection_names);
202 DECL_FUNC_PTR(profile_free_list);
203 DECL_FUNC_PTR(profile_get_string);
204 DECL_FUNC_PTR(profile_release_string);
207 DECL_FUNC_PTR(OpenSCManagerA);
208 DECL_FUNC_PTR(OpenServiceA);
209 DECL_FUNC_PTR(QueryServiceStatus);
210 DECL_FUNC_PTR(CloseServiceHandle);
212 DECL_FUNC_PTR(LsaNtStatusToWinError);
213 #endif /* USE_MS2MIT */
217 DECL_FUNC_PTR(LsaConnectUntrusted);
218 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
219 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
220 DECL_FUNC_PTR(LsaFreeReturnBuffer);
221 DECL_FUNC_PTR(LsaGetLogonSessionData);
222 #endif /* USE_MS2MIT */
225 FUNC_INFO ccapi_fi[] = {
226 MAKE_FUNC_INFO(cc_initialize),
227 MAKE_FUNC_INFO(cc_shutdown),
228 MAKE_FUNC_INFO(cc_get_NC_info),
229 MAKE_FUNC_INFO(cc_free_NC_info),
234 FUNC_INFO leash_fi[] = {
235 MAKE_FUNC_INFO(Leash_get_default_lifetime),
236 MAKE_FUNC_INFO(Leash_get_default_renew_till),
237 MAKE_FUNC_INFO(Leash_get_default_forwardable),
238 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
239 MAKE_FUNC_INFO(Leash_get_default_proxiable),
240 MAKE_FUNC_INFO(Leash_get_default_publicip),
241 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
242 MAKE_FUNC_INFO(Leash_get_default_life_min),
243 MAKE_FUNC_INFO(Leash_get_default_life_max),
244 MAKE_FUNC_INFO(Leash_get_default_renew_min),
245 MAKE_FUNC_INFO(Leash_get_default_renew_max),
246 MAKE_FUNC_INFO(Leash_get_default_renewable),
250 FUNC_INFO leash_opt_fi[] = {
251 MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
256 FUNC_INFO k5_fi[] = {
257 MAKE_FUNC_INFO(krb5_change_password),
258 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
259 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
260 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
261 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
262 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
263 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
264 MAKE_FUNC_INFO(krb5_get_init_creds_password),
265 MAKE_FUNC_INFO(krb5_build_principal_ext),
266 MAKE_FUNC_INFO(krb5_cc_get_name),
267 MAKE_FUNC_INFO(krb5_cc_resolve),
268 MAKE_FUNC_INFO(krb5_cc_default),
269 MAKE_FUNC_INFO(krb5_cc_default_name),
270 MAKE_FUNC_INFO(krb5_cc_set_default_name),
271 MAKE_FUNC_INFO(krb5_cc_initialize),
272 MAKE_FUNC_INFO(krb5_cc_destroy),
273 MAKE_FUNC_INFO(krb5_cc_close),
274 MAKE_FUNC_INFO(krb5_cc_copy_creds),
275 MAKE_FUNC_INFO(krb5_cc_store_cred),
276 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
277 MAKE_FUNC_INFO(krb5_cc_get_principal),
278 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
279 MAKE_FUNC_INFO(krb5_cc_next_cred),
280 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
281 MAKE_FUNC_INFO(krb5_cc_remove_cred),
282 MAKE_FUNC_INFO(krb5_cc_set_flags),
283 MAKE_FUNC_INFO(krb5_cc_get_type),
284 MAKE_FUNC_INFO(krb5_free_context),
285 MAKE_FUNC_INFO(krb5_free_cred_contents),
286 MAKE_FUNC_INFO(krb5_free_principal),
287 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
288 MAKE_FUNC_INFO(krb5_init_context),
289 MAKE_FUNC_INFO(krb5_parse_name),
290 MAKE_FUNC_INFO(krb5_timeofday),
291 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
292 MAKE_FUNC_INFO(krb5_unparse_name),
293 MAKE_FUNC_INFO(krb5_get_credentials),
294 MAKE_FUNC_INFO(krb5_mk_req),
295 MAKE_FUNC_INFO(krb5_sname_to_principal),
296 MAKE_FUNC_INFO(krb5_get_credentials_renew),
297 MAKE_FUNC_INFO(krb5_free_data),
298 MAKE_FUNC_INFO(krb5_free_data_contents),
299 MAKE_FUNC_INFO(krb5_free_unparsed_name),
300 MAKE_FUNC_INFO(krb5_os_localaddr),
301 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
302 MAKE_FUNC_INFO(krb5_copy_data),
303 MAKE_FUNC_INFO(krb5_free_creds),
304 MAKE_FUNC_INFO(krb5_build_principal),
305 MAKE_FUNC_INFO(krb5_get_renewed_creds),
306 MAKE_FUNC_INFO(krb5_free_addresses),
307 MAKE_FUNC_INFO(krb5_get_default_config_files),
308 MAKE_FUNC_INFO(krb5_free_config_files),
309 MAKE_FUNC_INFO(krb5_get_default_realm),
310 MAKE_FUNC_INFO(krb5_free_default_realm),
311 MAKE_FUNC_INFO(krb5_free_ticket),
312 MAKE_FUNC_INFO(krb5_decode_ticket),
313 MAKE_FUNC_INFO(krb5_get_host_realm),
314 MAKE_FUNC_INFO(krb5_free_host_realm),
315 MAKE_FUNC_INFO(krb5_free_addresses),
316 MAKE_FUNC_INFO(krb5_c_random_make_octets),
321 FUNC_INFO k4_fi[] = {
322 MAKE_FUNC_INFO(krb_get_cred),
323 MAKE_FUNC_INFO(krb_get_tf_realm),
324 MAKE_FUNC_INFO(krb_mk_req),
325 MAKE_FUNC_INFO(tkt_string),
331 FUNC_INFO k524_fi[] = {
332 MAKE_FUNC_INFO(krb524_init_ets),
333 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
338 FUNC_INFO profile_fi[] = {
339 MAKE_FUNC_INFO(profile_init),
340 MAKE_FUNC_INFO(profile_release),
341 MAKE_FUNC_INFO(profile_get_subsection_names),
342 MAKE_FUNC_INFO(profile_free_list),
343 MAKE_FUNC_INFO(profile_get_string),
344 MAKE_FUNC_INFO(profile_release_string),
348 FUNC_INFO ce_fi[] = {
349 MAKE_FUNC_INFO(com_err),
350 MAKE_FUNC_INFO(error_message),
354 FUNC_INFO service_fi[] = {
355 MAKE_FUNC_INFO(OpenSCManagerA),
356 MAKE_FUNC_INFO(OpenServiceA),
357 MAKE_FUNC_INFO(QueryServiceStatus),
358 MAKE_FUNC_INFO(CloseServiceHandle),
360 MAKE_FUNC_INFO(LsaNtStatusToWinError),
361 #endif /* USE_MS2MIT */
366 FUNC_INFO lsa_fi[] = {
367 MAKE_FUNC_INFO(LsaConnectUntrusted),
368 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
369 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
370 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
371 MAKE_FUNC_INFO(LsaGetLogonSessionData),
374 #endif /* USE_MS2MIT */
376 /* Static Prototypes */
377 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
378 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
379 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
380 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
381 void *data, const char *name, const char *banner, int num_prompts,
382 krb5_prompt prompts[]);
385 /* Static Declarations */
386 static int inited = 0;
387 static int mid_cnt = 0;
388 static struct textField * mid_tb = NULL;
389 static HINSTANCE hKrb5 = 0;
391 static HINSTANCE hKrb4 = 0;
392 #endif /* USE_KRB4 */
394 static HINSTANCE hKrb524 = 0;
397 static HINSTANCE hSecur32 = 0;
398 #endif /* USE_MS2MIT */
399 static HINSTANCE hAdvApi32 = 0;
400 static HINSTANCE hComErr = 0;
401 static HINSTANCE hService = 0;
402 static HINSTANCE hProfile = 0;
404 static HINSTANCE hLeash = 0;
405 static HINSTANCE hLeashOpt = 0;
407 static HINSTANCE hCCAPI = 0;
408 static struct principal_ccache_data * princ_cc_data = NULL;
409 static struct cell_principal_map * cell_princ_map = NULL;
414 static int inited = 0;
417 char mutexName[MAX_PATH];
418 HANDLE hMutex = NULL;
420 sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
422 hMutex = CreateMutex( NULL, TRUE, mutexName );
423 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
424 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
430 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
431 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
432 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
434 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
435 #endif /* USE_KRB4 */
436 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
438 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
439 #endif /* USE_MS2MIT */
441 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
444 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
445 LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
447 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
449 if ( KFW_is_available() ) {
450 char rootcell[MAXCELLCHARS+1];
452 KFW_import_windows_lsa();
453 #endif /* USE_MS2MIT */
454 KFW_import_ccache_data();
455 KFW_AFS_renew_expiring_tokens();
457 /* WIN32 NOTE: no way to get max chars */
458 if (!cm_GetRootCellName(rootcell))
459 KFW_AFS_renew_token_for_cell(rootcell);
462 ReleaseMutex(hMutex);
472 FreeLibrary(hLeashOpt);
478 FreeLibrary(hKrb524);
484 FreeLibrary(hSecur32);
485 #endif /* USE_MS2MIT */
487 FreeLibrary(hService);
489 FreeLibrary(hComErr);
491 FreeLibrary(hProfile);
495 #endif /* USE_KRB4 */
500 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
503 static int init = TRUE;
504 static int bIsWow64 = FALSE;
508 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
510 hModule = GetModuleHandle(TEXT("kernel32"));
512 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
514 if (NULL != fnIsWow64Process)
516 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
518 // on error, assume FALSE.
519 // in other words, do nothing.
522 FreeLibrary(hModule);
530 KFW_accept_dotted_usernames(void)
536 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
537 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
538 if (code == ERROR_SUCCESS) {
540 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
541 (BYTE *) &value, &len);
542 RegCloseKey(parmKey);
544 if (code != ERROR_SUCCESS) {
545 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
546 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
547 if (code == ERROR_SUCCESS) {
549 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
550 (BYTE *) &value, &len);
551 RegCloseKey (parmKey);
565 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
566 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
567 if (code == ERROR_SUCCESS) {
568 len = sizeof(use524);
569 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
570 (BYTE *) &use524, &len);
571 RegCloseKey(parmKey);
573 if (code != ERROR_SUCCESS) {
574 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
575 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
576 if (code == ERROR_SUCCESS) {
577 len = sizeof(use524);
578 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
579 (BYTE *) &use524, &len);
580 RegCloseKey (parmKey);
587 KFW_is_available(void)
593 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
594 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
595 if (code == ERROR_SUCCESS) {
596 len = sizeof(enableKFW);
597 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
598 (BYTE *) &enableKFW, &len);
599 RegCloseKey (parmKey);
602 if (code != ERROR_SUCCESS) {
603 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
604 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
605 if (code == ERROR_SUCCESS) {
606 len = sizeof(enableKFW);
607 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
608 (BYTE *) &enableKFW, &len);
609 RegCloseKey (parmKey);
617 if ( hKrb5 && hComErr && hService &&
620 #endif /* USE_MS2MIT */
633 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
634 int FreeContextFlag, krb5_context * ctx,
639 int krb5Error = ((int)(rc & 255));
651 errText = perror_message(rc);
652 _snprintf(message, sizeof(message),
653 "%s\n(Kerberos error %ld)\n\n%s failed",
658 if ( IsDebuggerPresent() )
659 OutputDebugString(message);
661 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
664 if (FreeContextFlag == 1)
666 if (ctx && *ctx != NULL)
668 if (cache && *cache != NULL) {
669 pkrb5_cc_close(*ctx, *cache);
673 pkrb5_free_context(*ctx);
682 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
684 struct principal_ccache_data * next = princ_cc_data;
685 krb5_principal principal = 0;
687 const char * ccname = NULL;
688 const char * cctype = NULL;
689 char * ccfullname = NULL;
690 krb5_error_code code = 0;
691 krb5_error_code cc_code = 0;
697 if (ctx == 0 || cc == 0)
700 code = pkrb5_cc_get_principal(ctx, cc, &principal);
703 code = pkrb5_unparse_name(ctx, principal, &pname);
704 if ( code ) goto cleanup;
706 ccname = pkrb5_cc_get_name(ctx, cc);
707 if (!ccname) goto cleanup;
709 cctype = pkrb5_cc_get_type(ctx, cc);
710 if (!cctype) goto cleanup;
712 ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
713 if (!ccfullname) goto cleanup;
715 sprintf(ccfullname, "%s:%s", cctype, ccname);
717 // Search the existing list to see if we have a match
719 for ( ; next ; next = next->next ) {
720 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
725 // If not, match add a new node to the beginning of the list and assign init it
727 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
728 next->next = princ_cc_data;
729 princ_cc_data = next;
730 next->principal = _strdup(pname);
731 next->ccache_name = ccfullname;
733 next->from_lsa = lsa;
735 next->expiration_time = 0;
739 flags = 0; // turn off OPENCLOSE mode
740 code = pkrb5_cc_set_flags(ctx, cc, flags);
741 if ( code ) goto cleanup;
743 code = pkrb5_timeofday(ctx, &now);
745 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
747 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
748 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
750 // we found the ticket we are looking for
751 // check validity of timestamp
752 // We add a 5 minutes fudge factor to compensate for potential
753 // clock skew errors between the KDC and client OS
755 valid = ((creds.times.starttime > 0) &&
756 now >= (creds.times.starttime - 300) &&
757 now < (creds.times.endtime + 300) &&
758 !(creds.ticket_flags & TKT_FLG_INVALID));
760 if ( next->from_lsa) {
762 next->expiration_time = creds.times.endtime;
764 } else if ( valid ) {
766 next->expiration_time = creds.times.endtime;
767 next->renew = (creds.times.renew_till > creds.times.endtime) &&
768 (creds.ticket_flags & TKT_FLG_RENEWABLE);
771 next->expiration_time = 0;
775 pkrb5_free_cred_contents(ctx, &creds);
776 cc_code = KRB5_CC_END;
779 pkrb5_free_cred_contents(ctx, &creds);
782 if (cc_code == KRB5_CC_END) {
783 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
784 if (code) goto cleanup;
788 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
789 code = pkrb5_cc_set_flags(ctx, cc, flags);
794 pkrb5_free_unparsed_name(ctx,pname);
796 pkrb5_free_principal(ctx,principal);
800 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
802 struct principal_ccache_data * next = princ_cc_data;
803 char * response = NULL;
805 if ( !principal || !ccache )
809 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
811 // we always want to prefer the MS Kerberos LSA cache or
812 // the cache afscreds created specifically for the principal
813 // if the current entry is either one, drop the previous find
814 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
817 response = _strdup(next->ccache_name);
818 // MS Kerberos LSA is our best option so use it and quit
819 if ( next->from_lsa )
833 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
835 struct principal_ccache_data ** next = &princ_cc_data;
837 if ( !pname && !ccname )
841 if ( !strcmp((*next)->principal,pname) ||
842 !strcmp((*next)->ccache_name,ccname) ) {
844 free((*next)->principal);
845 free((*next)->ccache_name);
847 (*next) = (*next)->next;
854 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
856 struct cell_principal_map * next = cell_princ_map;
858 // Search the existing list to see if we have a match
860 for ( ; next ; next = next->next ) {
861 if ( !strcmp(next->cell, cell) ) {
862 if ( !strcmp(next->principal,pname) ) {
863 next->active = active;
866 // OpenAFS currently has a restriction of one active token per cell
867 // Therefore, whenever we update the table with a new active cell we
868 // must mark all of the other principal to cell entries as inactive.
876 // If not, match add a new node to the beginning of the list and assign init it
878 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
879 next->next = cell_princ_map;
880 cell_princ_map = next;
881 next->principal = _strdup(pname);
882 next->cell = _strdup(cell);
883 next->active = active;
888 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
890 struct cell_principal_map ** next = &cell_princ_map;
892 if ( !pname && !cell )
896 if ( !strcmp((*next)->principal,pname) ||
897 !strcmp((*next)->cell,cell) ) {
899 free((*next)->principal);
902 (*next) = (*next)->next;
908 // Returns (if possible) a principal which has been known in
909 // the past to have been used to obtain tokens for the specified
911 // TODO: Attempt to return one which has not yet expired by checking
912 // the principal/ccache data
914 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
916 struct cell_principal_map * next_map = cell_princ_map;
917 const char * princ = NULL;
924 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
927 next_map = next_map->next;
930 if ( !principals || !count )
933 *principals = (char **) malloc(sizeof(char *) * count);
934 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
936 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
937 (*principals)[i++] = _strdup(next_map->principal);
944 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
947 struct cell_principal_map * next_map = cell_princ_map;
948 const char * princ = NULL;
954 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
957 next_map = next_map->next;
963 *cells = (char **) malloc(sizeof(char *) * count);
964 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
966 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
967 (*cells)[i++] = _strdup(next_map->cell);
973 /* Given a principal return an existing ccache or create one and return */
975 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
977 krb5_context ctx = NULL;
979 char * ccname = NULL;
980 krb5_error_code code;
982 if (!pkrb5_init_context)
988 code = pkrb5_init_context(&ctx);
989 if (code) goto cleanup;
993 code = pkrb5_unparse_name(ctx, principal, &pname);
994 if (code) goto cleanup;
996 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
997 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
998 ccname = (char *)malloc(strlen(pname) + 5);
999 sprintf(ccname,"API:%s",pname);
1001 code = pkrb5_cc_resolve(ctx, ccname, cc);
1003 code = pkrb5_cc_default(ctx, cc);
1004 if (code) goto cleanup;
1011 pkrb5_free_unparsed_name(ctx,pname);
1012 if (ctx && (ctx != alt_ctx))
1013 pkrb5_free_context(ctx);
1018 // Import Microsoft Credentials into a new MIT ccache
1020 KFW_import_windows_lsa(void)
1022 krb5_context ctx = NULL;
1023 krb5_ccache cc = NULL;
1024 krb5_principal princ = NULL;
1025 char * pname = NULL;
1026 krb5_data * princ_realm;
1027 krb5_error_code code;
1028 char cell[128]="", realm[128]="", *def_realm = 0;
1030 DWORD dwMsLsaImport;
1032 if (!pkrb5_init_context)
1035 code = pkrb5_init_context(&ctx);
1036 if (code) goto cleanup;
1038 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
1039 if (code) goto cleanup;
1041 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
1043 code = pkrb5_cc_get_principal(ctx, cc, &princ);
1044 if ( code ) goto cleanup;
1046 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
1047 switch ( dwMsLsaImport ) {
1048 case 0: /* do not import */
1050 case 1: /* always import */
1052 case 2: { /* matching realm */
1053 char ms_realm[128] = "", *r;
1056 for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) {
1057 *r = krb5_princ_realm(ctx, princ)->data[i];
1061 if (code = pkrb5_get_default_realm(ctx, &def_realm))
1064 if (strcmp(def_realm, ms_realm))
1072 code = pkrb5_unparse_name(ctx,princ,&pname);
1073 if ( code ) goto cleanup;
1075 princ_realm = krb5_princ_realm(ctx, princ);
1076 for ( i=0; i<princ_realm->length; i++ ) {
1077 realm[i] = princ_realm->data[i];
1078 cell[i] = tolower(princ_realm->data[i]);
1083 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
1084 if ( IsDebuggerPresent() ) {
1086 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1087 OutputDebugString(message);
1089 if ( code ) goto cleanup;
1091 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1095 pkrb5_free_unparsed_name(ctx,pname);
1097 pkrb5_free_principal(ctx,princ);
1099 pkrb5_free_default_realm(ctx, def_realm);
1101 pkrb5_cc_close(ctx,cc);
1103 pkrb5_free_context(ctx);
1105 #endif /* USE_MS2MIT */
1107 // If there are existing MIT credentials, copy them to a new
1108 // ccache named after the principal
1110 // Enumerate all existing MIT ccaches and construct entries
1111 // in the principal_ccache table
1113 // Enumerate all existing AFS Tokens and construct entries
1114 // in the cell_principal table
1116 KFW_import_ccache_data(void)
1118 krb5_context ctx = NULL;
1119 krb5_ccache cc = NULL;
1120 krb5_principal principal = NULL;
1122 krb5_error_code code;
1123 krb5_error_code cc_code;
1125 apiCB * cc_ctx = NULL;
1126 struct _infoNC ** pNCi = NULL;
1129 if ( !pcc_initialize )
1132 if ( IsDebuggerPresent() )
1133 OutputDebugString("KFW_import_ccache_data()\n");
1135 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1136 if (code) goto cleanup;
1138 code = pcc_get_NC_info(cc_ctx, &pNCi);
1139 if (code) goto cleanup;
1141 code = pkrb5_init_context(&ctx);
1142 if (code) goto cleanup;
1144 for ( i=0; pNCi[i]; i++ ) {
1145 if ( pNCi[i]->vers != CC_CRED_V5 )
1147 if ( IsDebuggerPresent() ) {
1148 OutputDebugString("Principal: ");
1149 OutputDebugString(pNCi[i]->principal);
1150 OutputDebugString(" in ccache ");
1151 OutputDebugString(pNCi[i]->name);
1152 OutputDebugString("\n");
1154 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1155 && strcmp(pNCi[i]->name,LSA_CCNAME)
1158 for ( j=0; pNCi[j]; j++ ) {
1159 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1165 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1166 if (code) goto loop_cleanup;
1169 krb5_ccache oldcc = 0;
1171 if ( IsDebuggerPresent() )
1172 OutputDebugString("copying ccache data to new ccache\n");
1174 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1175 if (code) goto loop_cleanup;
1176 code = pkrb5_cc_initialize(ctx, cc, principal);
1177 if (code) goto loop_cleanup;
1179 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1180 if (code) goto loop_cleanup;
1181 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1183 code = pkrb5_cc_close(ctx,cc);
1185 code = pkrb5_cc_close(ctx,oldcc);
1187 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1190 code = pkrb5_cc_close(ctx,oldcc);
1193 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1194 if (code) goto loop_cleanup;
1197 flags = 0; // turn off OPENCLOSE mode
1198 code = pkrb5_cc_set_flags(ctx, cc, flags);
1199 if ( code ) goto cleanup;
1201 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1203 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1205 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1206 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1207 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1208 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1209 if ( sname && cell && !strcmp("afs",sname->data) ) {
1210 struct ktc_principal aserver;
1211 struct ktc_principal aclient;
1212 struct ktc_token atoken;
1215 if ( IsDebuggerPresent() ) {
1216 OutputDebugString("Found AFS ticket: ");
1217 OutputDebugString(sname->data);
1219 OutputDebugString("/");
1220 OutputDebugString(cell->data);
1222 OutputDebugString("@");
1223 OutputDebugString(realm->data);
1224 OutputDebugString("\n");
1227 memset(&aserver, '\0', sizeof(aserver));
1228 strcpy(aserver.name, sname->data);
1229 strcpy(aserver.cell, cell->data);
1231 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1233 // Found a token in AFS Client Server which matches
1234 char pname[128], *p, *q;
1235 for ( p=pname, q=aclient.name; *q; p++, q++)
1237 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1241 if ( IsDebuggerPresent() ) {
1242 OutputDebugString("Found AFS token: ");
1243 OutputDebugString(pname);
1244 OutputDebugString("\n");
1247 if ( strcmp(pname,pNCi[i]->principal) )
1249 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1251 // Attempt to import it
1252 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1254 if ( IsDebuggerPresent() ) {
1255 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1258 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data,
1262 pLeash_get_default_lifetime(),
1263 #endif /* USE_LEASH */
1265 if ( IsDebuggerPresent() ) {
1267 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1268 OutputDebugString(message);
1271 } else if ( IsDebuggerPresent() ) {
1272 OutputDebugString("Found ticket: ");
1273 OutputDebugString(sname->data);
1274 if ( cell && cell->data ) {
1275 OutputDebugString("/");
1276 OutputDebugString(cell->data);
1278 OutputDebugString("@");
1279 OutputDebugString(realm->data);
1280 OutputDebugString("\n");
1282 pkrb5_free_cred_contents(ctx, &creds);
1285 if (cc_code == KRB5_CC_END) {
1286 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1287 if (cc_code) goto loop_cleanup;
1291 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1292 code = pkrb5_cc_set_flags(ctx, cc, flags);
1294 pkrb5_cc_close(ctx,cc);
1298 pkrb5_free_principal(ctx,principal);
1305 pkrb5_free_context(ctx);
1307 pcc_free_NC_info(cc_ctx, &pNCi);
1309 pcc_shutdown(&cc_ctx);
1314 KFW_AFS_get_cred( char * username,
1321 krb5_context ctx = NULL;
1322 krb5_ccache cc = NULL;
1323 char * realm = NULL, * userrealm = NULL;
1324 krb5_principal principal = NULL;
1325 char * pname = NULL;
1326 krb5_error_code code;
1327 char local_cell[MAXCELLCHARS+1];
1328 char **cells = NULL;
1330 struct afsconf_cell cellconfig;
1333 if (!pkrb5_init_context)
1336 if ( IsDebuggerPresent() ) {
1337 OutputDebugString("KFW_AFS_get_cred for token ");
1338 OutputDebugString(username);
1339 OutputDebugString(" in cell ");
1340 OutputDebugString(cell);
1341 OutputDebugString("\n");
1344 code = pkrb5_init_context(&ctx);
1345 if ( code ) goto cleanup;
1347 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1348 if ( code ) goto cleanup;
1350 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1352 userrealm = strchr(username,'@');
1354 pname = strdup(username);
1355 if (!KFW_accept_dotted_usernames()) {
1356 userrealm = strchr(pname, '@');
1359 /* handle kerberos iv notation */
1360 while ( dot = strchr(pname,'.') ) {
1366 pname = malloc(strlen(username) + strlen(realm) + 2);
1368 strcpy(pname, username);
1370 if (!KFW_accept_dotted_usernames()) {
1371 /* handle kerberos iv notation */
1372 while ( dot = strchr(pname,'.') ) {
1377 strcat(pname,realm);
1379 if ( IsDebuggerPresent() ) {
1380 OutputDebugString("Realm: ");
1381 OutputDebugString(realm);
1382 OutputDebugString("\n");
1385 code = pkrb5_parse_name(ctx, pname, &principal);
1386 if ( code ) goto cleanup;
1388 code = KFW_get_ccache(ctx, principal, &cc);
1389 if ( code ) goto cleanup;
1391 if ( lifetime == 0 )
1395 lifetime = pLeash_get_default_lifetime();
1398 if ( password && password[0] ) {
1399 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1404 1, /* forwardable */
1405 0, /* not proxiable */
1407 1, /* noaddresses */
1408 0 /* no public ip */
1410 pLeash_get_default_forwardable(),
1411 pLeash_get_default_proxiable(),
1412 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1413 pLeash_get_default_noaddresses(),
1414 pLeash_get_default_publicip()
1415 #endif /* USE_LEASH */
1418 if ( IsDebuggerPresent() ) {
1420 sprintf(message,"KFW_kinit() returns: %d\n",code);
1421 OutputDebugString(message);
1423 if ( code ) goto cleanup;
1425 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1428 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1429 if ( IsDebuggerPresent() ) {
1431 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1432 OutputDebugString(message);
1434 if ( code ) goto cleanup;
1436 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1438 // Attempt to obtain new tokens for other cells supported by the same
1440 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1441 if ( cell_count > 1 ) {
1442 while ( cell_count-- ) {
1443 if ( strcmp(cells[cell_count],cell) ) {
1444 if ( IsDebuggerPresent() ) {
1446 sprintf(message,"found another cell for the same principal: %s\n",cell);
1447 OutputDebugString(message);
1449 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1450 if ( code ) continue;
1452 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1453 if ( IsDebuggerPresent() ) {
1454 OutputDebugString("Realm: ");
1455 OutputDebugString(realm);
1456 OutputDebugString("\n");
1459 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1460 if ( IsDebuggerPresent() ) {
1462 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1463 OutputDebugString(message);
1466 free(cells[cell_count]);
1469 } else if ( cell_count == 1 ) {
1478 pkrb5_cc_close(ctx, cc);
1480 if ( code && reasonP ) {
1481 *reasonP = (char *)perror_message(code);
1487 KFW_AFS_destroy_tickets_for_cell(char * cell)
1489 krb5_context ctx = NULL;
1490 krb5_error_code code;
1492 char ** principals = NULL;
1494 if (!pkrb5_init_context)
1497 if ( IsDebuggerPresent() ) {
1498 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1499 OutputDebugString(cell);
1500 OutputDebugString("\n");
1503 code = pkrb5_init_context(&ctx);
1506 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1508 krb5_principal princ = 0;
1512 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1513 if ( cell_count > 1 ) {
1514 // TODO - What we really should do here is verify whether or not any of the
1515 // other cells which use this principal to obtain its credentials actually
1516 // have valid tokens or not. If they are currently using these credentials
1517 // we will skip them. For the time being we assume that if there is an active
1518 // map in the table that they are actively being used.
1522 code = pkrb5_parse_name(ctx, principals[count], &princ);
1523 if (code) goto loop_cleanup;
1525 code = KFW_get_ccache(ctx, princ, &cc);
1526 if (code) goto loop_cleanup;
1528 code = pkrb5_cc_destroy(ctx, cc);
1533 pkrb5_cc_close(ctx, cc);
1537 pkrb5_free_principal(ctx, princ);
1541 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1542 free(principals[count]);
1547 pkrb5_free_context(ctx);
1552 KFW_AFS_destroy_tickets_for_principal(char * user)
1554 krb5_context ctx = NULL;
1555 krb5_error_code code;
1557 char ** cells = NULL;
1558 krb5_principal princ = NULL;
1559 krb5_ccache cc = NULL;
1561 if (!pkrb5_init_context)
1564 if ( IsDebuggerPresent() ) {
1565 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1566 OutputDebugString(user);
1567 OutputDebugString("\n");
1570 code = pkrb5_init_context(&ctx);
1573 code = pkrb5_parse_name(ctx, user, &princ);
1574 if (code) goto loop_cleanup;
1576 code = KFW_get_ccache(ctx, princ, &cc);
1577 if (code) goto loop_cleanup;
1579 code = pkrb5_cc_destroy(ctx, cc);
1584 pkrb5_cc_close(ctx, cc);
1588 pkrb5_free_principal(ctx, princ);
1592 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1595 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1602 pkrb5_free_context(ctx);
1607 KFW_AFS_renew_expiring_tokens(void)
1609 krb5_error_code code = 0;
1610 krb5_context ctx = NULL;
1611 krb5_ccache cc = NULL;
1613 struct principal_ccache_data * pcc_next = princ_cc_data;
1616 const char * realm = NULL;
1617 char local_cell[MAXCELLCHARS+1]="";
1618 struct afsconf_cell cellconfig;
1620 if (!pkrb5_init_context)
1623 if ( pcc_next == NULL ) // nothing to do
1626 if ( IsDebuggerPresent() ) {
1627 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1630 code = pkrb5_init_context(&ctx);
1631 if (code) goto cleanup;
1633 code = pkrb5_timeofday(ctx, &now);
1634 if (code) goto cleanup;
1636 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1637 if ( pcc_next->expired )
1640 if ( now >= (pcc_next->expiration_time) ) {
1641 if ( !pcc_next->from_lsa ) {
1642 pcc_next->expired = 1;
1647 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1648 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1651 code = KFW_renew(ctx,cc);
1653 if ( code && pcc_next->from_lsa)
1655 #endif /* USE_MS2MIT */
1658 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1659 if (code) goto loop_cleanup;
1661 // Attempt to obtain new tokens for other cells supported by the same
1663 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1664 if ( cell_count > 0 ) {
1665 while ( cell_count-- ) {
1666 if ( IsDebuggerPresent() ) {
1667 OutputDebugString("Cell: ");
1668 OutputDebugString(cells[cell_count]);
1669 OutputDebugString("\n");
1671 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1672 if ( code ) continue;
1673 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1674 if ( IsDebuggerPresent() ) {
1675 OutputDebugString("Realm: ");
1676 OutputDebugString(realm);
1677 OutputDebugString("\n");
1679 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1680 if ( IsDebuggerPresent() ) {
1682 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1683 OutputDebugString(message);
1685 free(cells[cell_count]);
1693 pkrb5_cc_close(ctx,cc);
1700 pkrb5_cc_close(ctx,cc);
1702 pkrb5_free_context(ctx);
1709 KFW_AFS_renew_token_for_cell(char * cell)
1711 krb5_error_code code = 0;
1712 krb5_context ctx = NULL;
1714 char ** principals = NULL;
1716 if (!pkrb5_init_context)
1719 if ( IsDebuggerPresent() ) {
1720 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1721 OutputDebugString(cell);
1722 OutputDebugString("\n");
1725 code = pkrb5_init_context(&ctx);
1726 if (code) goto cleanup;
1728 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1730 // We know we must have a credential somewhere since we are
1731 // trying to renew a token
1733 KFW_import_ccache_data();
1734 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1737 krb5_principal princ = 0;
1738 krb5_principal service = 0;
1740 krb5_creds mcreds, creds;
1741 #endif /* COMMENT */
1743 const char * realm = NULL;
1744 struct afsconf_cell cellconfig;
1745 char local_cell[MAXCELLCHARS+1];
1748 code = pkrb5_parse_name(ctx, principals[count], &princ);
1749 if (code) goto loop_cleanup;
1751 code = KFW_get_ccache(ctx, princ, &cc);
1752 if (code) goto loop_cleanup;
1754 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1755 if ( code ) goto loop_cleanup;
1757 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1758 if ( IsDebuggerPresent() ) {
1759 OutputDebugString("Realm: ");
1760 OutputDebugString(realm);
1761 OutputDebugString("\n");
1765 /* krb5_cc_remove_cred() is not implemented
1768 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1769 realm, "afs", cell, NULL);
1771 memset(&mcreds, 0, sizeof(krb5_creds));
1772 mcreds.client = princ;
1773 mcreds.server = service;
1775 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1777 if ( IsDebuggerPresent() ) {
1778 char * cname, *sname;
1779 pkrb5_unparse_name(ctx, creds.client, &cname);
1780 pkrb5_unparse_name(ctx, creds.server, &sname);
1781 OutputDebugString("Removing credential for client \"");
1782 OutputDebugString(cname);
1783 OutputDebugString("\" and service \"");
1784 OutputDebugString(sname);
1785 OutputDebugString("\"\n");
1786 pkrb5_free_unparsed_name(ctx,cname);
1787 pkrb5_free_unparsed_name(ctx,sname);
1790 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1791 pkrb5_free_principal(ctx, creds.client);
1792 pkrb5_free_principal(ctx, creds.server);
1795 #endif /* COMMENT */
1797 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1798 if ( IsDebuggerPresent() ) {
1800 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1801 OutputDebugString(message);
1806 pkrb5_cc_close(ctx, cc);
1810 pkrb5_free_principal(ctx, princ);
1814 pkrb5_free_principal(ctx, service);
1818 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1819 free(principals[count]);
1823 code = -1; // we did not renew the tokens
1827 pkrb5_free_context(ctx);
1828 return (code ? FALSE : TRUE);
1833 KFW_AFS_renew_tokens_for_all_cells(void)
1835 struct cell_principal_map * next = cell_princ_map;
1837 if ( IsDebuggerPresent() )
1838 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1843 for ( ; next ; next = next->next ) {
1845 KFW_AFS_renew_token_for_cell(next->cell);
1851 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1853 krb5_error_code code = 0;
1854 krb5_context ctx = NULL;
1855 krb5_ccache cc = NULL;
1856 krb5_principal me = NULL;
1857 krb5_principal server = NULL;
1858 krb5_creds my_creds;
1859 krb5_data *realm = NULL;
1861 if (!pkrb5_init_context)
1864 memset(&my_creds, 0, sizeof(krb5_creds));
1869 code = pkrb5_init_context(&ctx);
1870 if (code) goto cleanup;
1876 code = pkrb5_cc_default(ctx, &cc);
1877 if (code) goto cleanup;
1880 code = pkrb5_cc_get_principal(ctx, cc, &me);
1881 if (code) goto cleanup;
1883 realm = krb5_princ_realm(ctx, me);
1885 code = pkrb5_build_principal_ext(ctx, &server,
1886 realm->length,realm->data,
1887 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1888 realm->length,realm->data,
1893 if ( IsDebuggerPresent() ) {
1894 char * cname, *sname;
1895 pkrb5_unparse_name(ctx, me, &cname);
1896 pkrb5_unparse_name(ctx, server, &sname);
1897 OutputDebugString("Renewing credential for client \"");
1898 OutputDebugString(cname);
1899 OutputDebugString("\" and service \"");
1900 OutputDebugString(sname);
1901 OutputDebugString("\"\n");
1902 pkrb5_free_unparsed_name(ctx,cname);
1903 pkrb5_free_unparsed_name(ctx,sname);
1906 my_creds.client = me;
1907 my_creds.server = server;
1909 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1911 if ( IsDebuggerPresent() ) {
1913 sprintf(message,"krb5_get_renewed_creds() failed: %d\n",code);
1914 OutputDebugString(message);
1919 code = pkrb5_cc_initialize(ctx, cc, me);
1921 if ( IsDebuggerPresent() ) {
1923 sprintf(message,"krb5_cc_initialize() failed: %d\n",code);
1924 OutputDebugString(message);
1929 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1931 if ( IsDebuggerPresent() ) {
1933 sprintf(message,"krb5_cc_store_cred() failed: %d\n",code);
1934 OutputDebugString(message);
1940 if (my_creds.client == me)
1941 my_creds.client = 0;
1942 if (my_creds.server == server)
1943 my_creds.server = 0;
1944 pkrb5_free_cred_contents(ctx, &my_creds);
1946 pkrb5_free_principal(ctx, me);
1948 pkrb5_free_principal(ctx, server);
1949 if (cc && (cc != alt_cc))
1950 pkrb5_cc_close(ctx, cc);
1951 if (ctx && (ctx != alt_ctx))
1952 pkrb5_free_context(ctx);
1957 KFW_kinit( krb5_context alt_ctx,
1960 char *principal_name,
1962 krb5_deltat lifetime,
1965 krb5_deltat renew_life,
1970 krb5_error_code code = 0;
1971 krb5_context ctx = NULL;
1972 krb5_ccache cc = NULL;
1973 krb5_principal me = NULL;
1975 krb5_creds my_creds;
1976 krb5_get_init_creds_opt options;
1977 krb5_address ** addrs = NULL;
1978 int i = 0, addr_count = 0;
1980 if (!pkrb5_init_context)
1983 pkrb5_get_init_creds_opt_init(&options);
1984 memset(&my_creds, 0, sizeof(my_creds));
1992 code = pkrb5_init_context(&ctx);
1993 if (code) goto cleanup;
1999 code = pkrb5_cc_default(ctx, &cc);
2000 if (code) goto cleanup;
2003 code = pkrb5_parse_name(ctx, principal_name, &me);
2007 code = pkrb5_unparse_name(ctx, me, &name);
2015 lifetime = pLeash_get_default_lifetime();
2016 #endif /* USE_LEASH */
2023 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2024 pkrb5_get_init_creds_opt_set_forwardable(&options,
2025 forwardable ? 1 : 0);
2026 pkrb5_get_init_creds_opt_set_proxiable(&options,
2028 pkrb5_get_init_creds_opt_set_renew_life(&options,
2031 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2035 // we are going to add the public IP address specified by the user
2036 // to the list provided by the operating system
2037 krb5_address ** local_addrs=NULL;
2040 pkrb5_os_localaddr(ctx, &local_addrs);
2041 while ( local_addrs[i++] );
2044 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2046 pkrb5_free_addresses(ctx, local_addrs);
2049 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2051 while ( local_addrs[i] ) {
2052 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2053 if (addrs[i] == NULL) {
2054 pkrb5_free_addresses(ctx, local_addrs);
2058 addrs[i]->magic = local_addrs[i]->magic;
2059 addrs[i]->addrtype = local_addrs[i]->addrtype;
2060 addrs[i]->length = local_addrs[i]->length;
2061 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2062 if (!addrs[i]->contents) {
2063 pkrb5_free_addresses(ctx, local_addrs);
2067 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2068 local_addrs[i]->length); /* safe */
2071 pkrb5_free_addresses(ctx, local_addrs);
2073 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2074 if (addrs[i] == NULL)
2077 addrs[i]->magic = KV5M_ADDRESS;
2078 addrs[i]->addrtype = AF_INET;
2079 addrs[i]->length = 4;
2080 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2081 if (!addrs[i]->contents)
2084 netIPAddr = htonl(publicIP);
2085 memcpy(addrs[i]->contents,&netIPAddr,4);
2087 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2092 code = pkrb5_get_init_creds_password(ctx,
2095 password, // password
2096 KRB5_prompter, // prompter
2097 hParent, // prompter data
2104 code = pkrb5_cc_initialize(ctx, cc, me);
2108 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2114 for ( i=0;i<addr_count;i++ ) {
2116 if ( addrs[i]->contents )
2117 free(addrs[i]->contents);
2122 if (my_creds.client == me)
2123 my_creds.client = 0;
2124 pkrb5_free_cred_contents(ctx, &my_creds);
2126 pkrb5_free_unparsed_name(ctx, name);
2128 pkrb5_free_principal(ctx, me);
2129 if (cc && (cc != alt_cc))
2130 pkrb5_cc_close(ctx, cc);
2131 if (ctx && (ctx != alt_ctx))
2132 pkrb5_free_context(ctx);
2138 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2140 krb5_context ctx = NULL;
2141 krb5_ccache cc = NULL;
2142 krb5_error_code code;
2144 if (!pkrb5_init_context)
2153 code = pkrb5_init_context(&ctx);
2154 if (code) goto cleanup;
2160 code = pkrb5_cc_default(ctx, &cc);
2161 if (code) goto cleanup;
2164 code = pkrb5_cc_destroy(ctx, cc);
2165 if ( !code ) cc = 0;
2168 if (cc && (cc != alt_cc))
2169 pkrb5_cc_close(ctx, cc);
2170 if (ctx && (ctx != alt_ctx))
2171 pkrb5_free_context(ctx);
2179 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2181 NTSTATUS Status = 0;
2183 TOKEN_STATISTICS Stats;
2189 *ppSessionData = NULL;
2191 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2195 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2196 CloseHandle( TokenHandle );
2200 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2201 if ( FAILED(Status) || !ppSessionData )
2208 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2209 // cache. It validates whether or not it is reasonable to assume that if we
2210 // attempted to retrieve valid tickets we could do so. Microsoft does not
2211 // automatically renew expired tickets. Therefore, the cache could contain
2212 // expired or invalid tickets. Microsoft also caches the user's password
2213 // and will use it to retrieve new TGTs if the cache is empty and tickets
2217 MSLSA_IsKerberosLogon(VOID)
2219 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2220 BOOL Success = FALSE;
2222 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2223 if ( pSessionData->AuthenticationPackage.Buffer ) {
2229 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2230 usLength = (pSessionData->AuthenticationPackage).Length;
2233 lstrcpynW (buffer, usBuffer, usLength);
2234 lstrcatW (buffer,L"");
2235 if ( !lstrcmpW(L"Kerberos",buffer) )
2239 pLsaFreeReturnBuffer(pSessionData);
2243 #endif /* USE_MS2MIT */
2245 static BOOL CALLBACK
2246 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2250 switch ( message ) {
2252 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2254 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2257 for ( i=0; i < mid_cnt ; i++ ) {
2258 if (mid_tb[i].echo == 0)
2259 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2260 else if (mid_tb[i].echo == 2)
2261 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2266 switch ( LOWORD(wParam) ) {
2268 for ( i=0; i < mid_cnt ; i++ ) {
2269 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2270 *mid_tb[i].buf = '\0';
2274 EndDialog(hDialog, LOWORD(wParam));
2282 lpwAlign( LPWORD lpIn )
2286 ul = (ULONG_PTR) lpIn;
2290 return (LPWORD) ul;;
2294 * dialog widths are measured in 1/4 character widths
2295 * dialog height are measured in 1/8 character heights
2299 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2300 char * ptext[], int numlines, int width,
2301 int tb_cnt, struct textField * tb)
2305 LPDLGITEMTEMPLATE lpdit;
2311 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2318 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2320 // Define a dialog box.
2322 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2323 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2324 | DS_SETFOREGROUND | DS_3DLOOK
2325 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2326 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2329 lpdt->cx = 20 + width * 4;
2330 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2332 lpw = (LPWORD) (lpdt + 1);
2333 *lpw++ = 0; // no menu
2334 *lpw++ = 0; // predefined dialog box class (by default)
2336 lpwsz = (LPWSTR) lpw;
2337 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2339 *lpw++ = 8; // font size (points)
2340 lpwsz = (LPWSTR) lpw;
2341 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2345 //-----------------------
2346 // Define an OK button.
2347 //-----------------------
2348 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2349 lpdit = (LPDLGITEMTEMPLATE) lpw;
2350 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2351 lpdit->dwExtendedStyle = 0;
2352 lpdit->x = (lpdt->cx - 14)/4 - 20;
2353 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2356 lpdit->id = IDOK; // OK button identifier
2358 lpw = (LPWORD) (lpdit + 1);
2360 *lpw++ = 0x0080; // button class
2362 lpwsz = (LPWSTR) lpw;
2363 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2365 *lpw++ = 0; // no creation data
2367 //-----------------------
2368 // Define an Cancel button.
2369 //-----------------------
2370 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2371 lpdit = (LPDLGITEMTEMPLATE) lpw;
2372 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2373 lpdit->dwExtendedStyle = 0;
2374 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2375 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2378 lpdit->id = IDCANCEL; // CANCEL button identifier
2380 lpw = (LPWORD) (lpdit + 1);
2382 *lpw++ = 0x0080; // button class
2384 lpwsz = (LPWSTR) lpw;
2385 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2387 *lpw++ = 0; // no creation data
2389 /* Add controls for preface data */
2390 for ( i=0; i<numlines; i++) {
2391 /*-----------------------
2392 * Define a static text control.
2393 *-----------------------*/
2394 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2395 lpdit = (LPDLGITEMTEMPLATE) lpw;
2396 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2397 lpdit->dwExtendedStyle = 0;
2399 lpdit->y = 10 + i * 14;
2400 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2402 lpdit->id = ID_TEXT + i; // text identifier
2404 lpw = (LPWORD) (lpdit + 1);
2406 *lpw++ = 0x0082; // static class
2408 lpwsz = (LPWSTR) lpw;
2409 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2410 -1, lpwsz, 2*width);
2412 *lpw++ = 0; // no creation data
2415 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2416 int len = (int)strlen(tb[i].label);
2421 for ( i=0; i<tb_cnt; i++) {
2423 /*-----------------------
2424 * Define a static text control.
2425 *-----------------------*/
2426 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2427 lpdit = (LPDLGITEMTEMPLATE) lpw;
2428 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2429 lpdit->dwExtendedStyle = 0;
2431 lpdit->y = 10 + (numlines + i + 1) * 14;
2432 lpdit->cx = pwid * 4;
2434 lpdit->id = ID_TEXT + numlines + i; // text identifier
2436 lpw = (LPWORD) (lpdit + 1);
2438 *lpw++ = 0x0082; // static class
2440 lpwsz = (LPWSTR) lpw;
2441 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2444 *lpw++ = 0; // no creation data
2446 /*-----------------------
2447 * Define an edit control.
2448 *-----------------------*/
2449 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2450 lpdit = (LPDLGITEMTEMPLATE) lpw;
2451 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2452 lpdit->dwExtendedStyle = 0;
2453 lpdit->x = 10 + (pwid + 1) * 4;
2454 lpdit->y = 10 + (numlines + i + 1) * 14;
2455 lpdit->cx = (width - (pwid + 1)) * 4;
2457 lpdit->id = ID_MID_TEXT + i; // identifier
2459 lpw = (LPWORD) (lpdit + 1);
2461 *lpw++ = 0x0081; // edit class
2463 lpwsz = (LPWSTR) lpw;
2464 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2467 *lpw++ = 0; // no creation data
2471 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2472 hwndOwner, (DLGPROC) MultiInputDialogProc);
2476 case 0: /* Timeout */
2484 sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
2485 MessageBox(hwndOwner,
2488 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2495 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2497 HINSTANCE hInst = 0;
2501 char * plines[16], *p = preface ? preface : "";
2504 for ( i=0; i<16; i++ )
2507 while (*p && numlines < 16) {
2508 plines[numlines++] = p;
2509 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2510 if ( *p == '\r' && *(p+1) == '\n' ) {
2513 } else if ( *p == '\n' ) {
2516 if ( strlen(plines[numlines-1]) > maxwidth )
2517 maxwidth = (int)strlen(plines[numlines-1]);
2520 for ( i=0;i<n;i++ ) {
2521 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2522 if ( maxwidth < len )
2526 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2529 static krb5_error_code KRB5_CALLCONV
2530 KRB5_prompter( krb5_context context,
2535 krb5_prompt prompts[])
2537 krb5_error_code errcode = 0;
2539 struct textField * tb = NULL;
2540 int len = 0, blen=0, nlen=0;
2541 HWND hParent = (HWND)data;
2544 nlen = (int)strlen(name)+2;
2547 blen = (int)strlen(banner)+2;
2549 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2552 memset(tb,0,sizeof(struct textField) * num_prompts);
2553 for ( i=0; i < num_prompts; i++ ) {
2554 tb[i].buf = prompts[i].reply->data;
2555 tb[i].len = prompts[i].reply->length;
2556 tb[i].label = prompts[i].prompt;
2558 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2561 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2563 for ( i=0; i < num_prompts; i++ )
2564 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2572 for (i = 0; i < num_prompts; i++) {
2573 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2580 KFW_AFS_wait_for_service_start(void)
2585 CurrentState = SERVICE_START_PENDING;
2586 memset(HostName, '\0', sizeof(HostName));
2587 gethostname(HostName, sizeof(HostName));
2589 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2591 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2593 if ( IsDebuggerPresent() ) {
2594 switch ( CurrentState ) {
2595 case SERVICE_STOPPED:
2596 OutputDebugString("SERVICE_STOPPED\n");
2598 case SERVICE_START_PENDING:
2599 OutputDebugString("SERVICE_START_PENDING\n");
2601 case SERVICE_STOP_PENDING:
2602 OutputDebugString("SERVICE_STOP_PENDING\n");
2604 case SERVICE_RUNNING:
2605 OutputDebugString("SERVICE_RUNNING\n");
2607 case SERVICE_CONTINUE_PENDING:
2608 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2610 case SERVICE_PAUSE_PENDING:
2611 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2613 case SERVICE_PAUSED:
2614 OutputDebugString("SERVICE_PAUSED\n");
2617 OutputDebugString("UNKNOWN Service State\n");
2620 if (CurrentState == SERVICE_STOPPED)
2622 if (CurrentState == SERVICE_RUNNING)
2638 memset(HostName, '\0', sizeof(HostName));
2639 gethostname(HostName, sizeof(HostName));
2640 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2642 if (CurrentState != SERVICE_RUNNING)
2645 rc = ktc_ForgetAllTokens();
2651 #define ALLOW_REGISTER 1
2653 ViceIDToUsername(char *username,
2654 char *realm_of_user,
2655 char *realm_of_cell,
2657 struct ktc_principal *aclient,
2658 struct ktc_principal *aserver,
2659 struct ktc_token *atoken)
2661 static char lastcell[MAXCELLCHARS+1] = { 0 };
2662 static char confdir[512] = { 0 };
2663 #ifdef AFS_ID_TO_NAME
2664 char username_copy[BUFSIZ];
2665 #endif /* AFS_ID_TO_NAME */
2666 long viceId = ANONYMOUSID; /* AFS uid of user */
2668 #ifdef ALLOW_REGISTER
2670 #endif /* ALLOW_REGISTER */
2672 if (confdir[0] == '\0')
2673 cm_GetConfigDir(confdir, sizeof(confdir));
2675 strcpy(lastcell, aserver->cell);
2677 if (!pr_Initialize (0, confdir, aserver->cell)) {
2678 char sname[PR_MAXNAMELEN];
2679 strncpy(sname, username, PR_MAXNAMELEN);
2680 sname[PR_MAXNAMELEN-1] = '\0';
2681 status = pr_SNameToId (sname, &viceId);
2686 * This is a crock, but it is Transarc's crock, so
2687 * we have to play along in order to get the
2688 * functionality. The way the afs id is stored is
2689 * as a string in the username field of the token.
2690 * Contrary to what you may think by looking at
2691 * the code for tokens, this hack (AFS ID %d) will
2692 * not work if you change %d to something else.
2696 * This code is taken from cklog -- it lets people
2697 * automatically register with the ptserver in foreign cells
2700 #ifdef ALLOW_REGISTER
2702 if (viceId != ANONYMOUSID) {
2703 #else /* ALLOW_REGISTER */
2704 if ((status == 0) && (viceId != ANONYMOUSID))
2705 #endif /* ALLOW_REGISTER */
2707 #ifdef AFS_ID_TO_NAME
2708 strncpy(username_copy, username, BUFSIZ);
2709 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2710 #endif /* AFS_ID_TO_NAME */
2712 #ifdef ALLOW_REGISTER
2713 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2715 strncpy(aclient->name, username, MAXKTCNAMELEN - 1);
2716 strcpy(aclient->instance, "");
2717 strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
2718 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2720 if (status = pr_Initialize(1L, confdir, aserver->cell))
2722 status = pr_CreateUser(username, &id);
2726 #ifdef AFS_ID_TO_NAME
2727 strncpy(username_copy, username, BUFSIZ);
2728 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2729 #endif /* AFS_ID_TO_NAME */
2732 #endif /* ALLOW_REGISTER */
2738 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2739 krb5_error_code code;
2740 krb5_ticket *ticket;
2743 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2745 len = krb5_princ_realm(context, ticket->server)->length;
2746 if (len > destlen - 1)
2749 strncpy(dest, krb5_princ_realm(context, ticket->server)->data, len);
2752 pkrb5_free_ticket(context, ticket);
2758 krb5_context alt_ctx,
2763 int lifetime, /* unused parameter */
2771 #endif /* USE_KRB4 */
2772 struct ktc_principal aserver;
2773 struct ktc_principal aclient;
2774 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2775 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2776 char local_cell[MAXCELLCHARS+1];
2777 char Dmycell[MAXCELLCHARS+1];
2778 struct ktc_token atoken;
2779 struct ktc_token btoken;
2780 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2781 char RealmName[128];
2783 char ServiceName[128];
2787 krb5_context ctx = NULL;
2788 krb5_ccache cc = NULL;
2790 krb5_creds * k5creds = NULL;
2791 krb5_error_code code;
2792 krb5_principal client_principal = NULL;
2793 krb5_data * k5data = NULL;
2797 memset(HostName, '\0', sizeof(HostName));
2798 gethostname(HostName, sizeof(HostName));
2799 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2800 if ( IsDebuggerPresent() )
2801 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2804 if (CurrentState != SERVICE_RUNNING) {
2805 if ( IsDebuggerPresent() )
2806 OutputDebugString("AFSD Service NOT RUNNING\n");
2810 if (!pkrb5_init_context)
2813 memset(RealmName, '\0', sizeof(RealmName));
2814 memset(CellName, '\0', sizeof(CellName));
2815 memset(ServiceName, '\0', sizeof(ServiceName));
2816 memset(realm_of_user, '\0', sizeof(realm_of_user));
2817 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2818 if (cell && cell[0])
2819 strcpy(Dmycell, cell);
2821 memset(Dmycell, '\0', sizeof(Dmycell));
2823 // NULL or empty cell returns information on local cell
2824 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2826 // KFW_AFS_error(rc, "get_cellconfig()");
2833 code = pkrb5_init_context(&ctx);
2834 if (code) goto cleanup;
2840 code = pkrb5_cc_default(ctx, &cc);
2841 if (code) goto skip_krb5_init;
2844 memset((char *)&increds, 0, sizeof(increds));
2846 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2848 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2850 OutputDebugString("Principal Not Found for ccache\n");
2852 goto skip_krb5_init;
2855 if (!KFW_accept_dotted_usernames()) {
2856 /* look for client principals which cannot be distinguished
2857 * from Kerberos 4 multi-component principal names
2859 k5data = krb5_princ_component(ctx,client_principal,0);
2860 for ( i=0; i<k5data->length; i++ ) {
2861 if ( k5data->data[i] == '.' )
2864 if (i != k5data->length)
2866 OutputDebugString("Illegal Principal name contains dot in first component\n");
2867 rc = KRB5KRB_ERR_GENERIC;
2872 i = krb5_princ_realm(ctx, client_principal)->length;
2875 strncpy(realm_of_user,krb5_princ_realm(ctx, client_principal)->data,i);
2876 realm_of_user[i] = 0;
2881 if ( !try_krb5 || !realm_of_user[0] ) {
2882 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2891 strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig));
2893 if (strlen(service) == 0)
2894 strcpy(ServiceName, "afs");
2896 strcpy(ServiceName, service);
2898 if (strlen(cell) == 0)
2899 strcpy(CellName, local_cell);
2901 strcpy(CellName, cell);
2903 /* This is for Kerberos v4 only */
2904 if (strlen(realm) == 0)
2905 strcpy(RealmName, realm_of_cell);
2907 strcpy(RealmName, realm);
2909 memset(&creds, '\0', sizeof(creds));
2913 code = KRB5KRB_ERR_GENERIC;
2916 increds.client = client_principal;
2917 increds.times.endtime = 0;
2918 /* Ask for DES since that is what V4 understands */
2919 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
2921 /* If there was a specific realm we are supposed to try
2924 if (strlen(realm) != 0) {
2925 /* service/cell@REALM */
2927 code = pkrb5_build_principal(ctx, &increds.server,
2933 if ( IsDebuggerPresent() ) {
2934 char * cname, *sname;
2935 pkrb5_unparse_name(ctx, increds.client, &cname);
2936 pkrb5_unparse_name(ctx, increds.server, &sname);
2937 OutputDebugString("Getting tickets for \"");
2938 OutputDebugString(cname);
2939 OutputDebugString("\" and service \"");
2940 OutputDebugString(sname);
2941 OutputDebugString("\"\n");
2942 pkrb5_free_unparsed_name(ctx,cname);
2943 pkrb5_free_unparsed_name(ctx,sname);
2947 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2949 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2950 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
2951 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2952 code == KRB5KRB_AP_ERR_MSG_TYPE) {
2953 /* Or service@REALM */
2954 pkrb5_free_principal(ctx,increds.server);
2956 code = pkrb5_build_principal(ctx, &increds.server,
2962 if ( IsDebuggerPresent() ) {
2963 char * cname, *sname;
2964 pkrb5_unparse_name(ctx, increds.client, &cname);
2965 pkrb5_unparse_name(ctx, increds.server, &sname);
2966 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2967 OutputDebugString("Trying again: getting tickets for \"");
2968 OutputDebugString(cname);
2969 OutputDebugString("\" and service \"");
2970 OutputDebugString(sname);
2971 OutputDebugString("\"\n");
2972 pkrb5_free_unparsed_name(ctx,cname);
2973 pkrb5_free_unparsed_name(ctx,sname);
2977 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2981 /* we have a local realm for the cell */
2982 strcpy(realm_of_cell, realm);
2985 /* Otherwise, first try service/cell@CLIENT_REALM */
2986 if (code = pkrb5_build_principal(ctx, &increds.server,
2987 (int)strlen(realm_of_user),
2996 if ( IsDebuggerPresent() ) {
2997 char * cname, *sname;
2998 pkrb5_unparse_name(ctx, increds.client, &cname);
2999 pkrb5_unparse_name(ctx, increds.server, &sname);
3000 OutputDebugString("Getting tickets for \"");
3001 OutputDebugString(cname);
3002 OutputDebugString("\" and service \"");
3003 OutputDebugString(sname);
3004 OutputDebugString("\"\n");
3005 pkrb5_free_unparsed_name(ctx,cname);
3006 pkrb5_free_unparsed_name(ctx,sname);
3009 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3011 /* The client's realm is a local realm for the cell.
3012 * Save it so that later the pts registration will not
3015 strcpy(realm_of_cell, realm_of_user);
3018 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3019 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3020 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3021 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
3022 strcmp(realm_of_user, realm_of_cell)) {
3023 /* Then service/cell@CELL_REALM */
3024 pkrb5_free_principal(ctx,increds.server);
3026 code = pkrb5_build_principal(ctx, &increds.server,
3027 (int)strlen(realm_of_cell),
3032 if ( IsDebuggerPresent() ) {
3033 char * cname, *sname;
3034 pkrb5_unparse_name(ctx, increds.client, &cname);
3035 pkrb5_unparse_name(ctx, increds.server, &sname);
3036 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3037 OutputDebugString("Trying again: getting tickets for \"");
3038 OutputDebugString(cname);
3039 OutputDebugString("\" and service \"");
3040 OutputDebugString(sname);
3041 OutputDebugString("\"\n");
3042 pkrb5_free_unparsed_name(ctx,cname);
3043 pkrb5_free_unparsed_name(ctx,sname);
3047 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3049 if (!code && !strlen(realm_of_cell))
3050 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3053 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3054 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3055 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3056 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3057 /* Finally service@CELL_REALM */
3058 pkrb5_free_principal(ctx,increds.server);
3060 code = pkrb5_build_principal(ctx, &increds.server,
3061 (int)strlen(realm_of_cell),
3066 if ( IsDebuggerPresent() ) {
3067 char * cname, *sname;
3068 pkrb5_unparse_name(ctx, increds.client, &cname);
3069 pkrb5_unparse_name(ctx, increds.server, &sname);
3070 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3071 OutputDebugString("Trying again: getting tickets for \"");
3072 OutputDebugString(cname);
3073 OutputDebugString("\" and service \"");
3074 OutputDebugString(sname);
3075 OutputDebugString("\"\n");
3076 pkrb5_free_unparsed_name(ctx,cname);
3077 pkrb5_free_unparsed_name(ctx,sname);
3081 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3082 if (!code && !strlen(realm_of_cell))
3083 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3088 if ( IsDebuggerPresent() ) {
3090 sprintf(message,"krb5_get_credentials returns: %d\n",code);
3091 OutputDebugString(message);
3097 /* This code inserts the entire K5 ticket into the token
3098 * No need to perform a krb524 translation which is
3099 * commented out in the code below
3101 if (KFW_use_krb524() ||
3102 k5creds->ticket.length > MAXKTCTICKETLEN)
3105 memset(&aserver, '\0', sizeof(aserver));
3106 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
3107 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
3109 memset(&atoken, '\0', sizeof(atoken));
3110 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3111 atoken.startTime = k5creds->times.starttime;
3112 atoken.endTime = k5creds->times.endtime;
3113 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3114 atoken.ticketLen = k5creds->ticket.length;
3115 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3118 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3119 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3120 if ( rc == KTC_NOCM && retry < 20 ) {
3123 goto retry_gettoken5;
3128 if (atoken.kvno == btoken.kvno &&
3129 atoken.ticketLen == btoken.ticketLen &&
3130 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3131 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3133 /* Success - Nothing to do */
3137 // * Reset the "aclient" structure before we call ktc_SetToken.
3138 // * This structure was first set by the ktc_GetToken call when
3139 // * we were comparing whether identical tokens already existed.
3141 len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
3142 strncpy(aclient.name, k5creds->client->data[0].data, len);
3143 aclient.name[len] = '\0';
3145 if ( k5creds->client->length > 1 ) {
3147 strcat(aclient.name, ".");
3148 p = aclient.name + strlen(aclient.name);
3149 len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
3150 strncpy(p, k5creds->client->data[1].data, len);
3153 aclient.instance[0] = '\0';
3155 strcpy(aclient.cell, realm_of_cell);
3157 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3158 /* For Khimaira, always append the realm name */
3159 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3161 strcat(aclient.name, "@");
3162 p = aclient.name + strlen(aclient.name);
3163 len = min(k5creds->client->realm.length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
3164 strncpy(p, k5creds->client->realm.data, len);
3168 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3169 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3170 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3171 &aclient, &aserver, &atoken);
3174 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
3175 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
3177 aclient.smbname[0] = '\0';
3180 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3182 goto cleanup; /* We have successfully inserted the token */
3188 /* Otherwise, the ticket could have been too large so try to
3189 * convert using the krb524d running with the KDC
3191 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3192 pkrb5_free_creds(ctx, k5creds);
3194 if ( IsDebuggerPresent() ) {
3196 sprintf(message,"krb524_convert_creds_kdc returns: %d\n",code);
3197 OutputDebugString(message);
3202 #endif /* USE_KRB524 */
3206 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3207 if (code == NO_TKT_FIL) {
3208 // if the problem is that we have no krb4 tickets
3209 // do not attempt to continue
3212 if (code != KSUCCESS)
3213 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3215 if (code != KSUCCESS)
3217 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3219 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3224 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3226 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3241 memset(&aserver, '\0', sizeof(aserver));
3242 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
3243 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
3245 memset(&atoken, '\0', sizeof(atoken));
3246 atoken.kvno = creds.kvno;
3247 atoken.startTime = creds.issue_date;
3248 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3249 memcpy(&atoken.sessionKey, creds.session, 8);
3250 atoken.ticketLen = creds.ticket_st.length;
3251 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3254 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3255 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3256 if ( rc == KTC_NOCM && retry < 20 ) {
3259 goto retry_gettoken;
3261 KFW_AFS_error(rc, "ktc_GetToken()");
3266 if (atoken.kvno == btoken.kvno &&
3267 atoken.ticketLen == btoken.ticketLen &&
3268 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3269 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3274 // * Reset the "aclient" structure before we call ktc_SetToken.
3275 // * This structure was first set by the ktc_GetToken call when
3276 // * we were comparing whether identical tokens already existed.
3278 strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
3281 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3282 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3284 strcpy(aclient.instance, "");
3286 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3287 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3288 aclient.name[MAXKTCREALMLEN-1] = '\0';
3290 strcpy(aclient.cell, CellName);
3292 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3293 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3294 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3295 &aclient, &aserver, &atoken);
3298 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
3299 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
3301 aclient.smbname[0] = '\0';
3304 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3306 KFW_AFS_error(rc, "ktc_SetToken()");
3312 if (client_principal)
3313 pkrb5_free_principal(ctx,client_principal);
3314 /* increds.client == client_principal */
3316 pkrb5_free_principal(ctx,increds.server);
3317 if (cc && (cc != alt_cc))
3318 pkrb5_cc_close(ctx, cc);
3319 if (ctx && (ctx != alt_ctx))
3320 pkrb5_free_context(ctx);
3322 return(rc? rc : code);
3325 /**************************************/
3326 /* afs_realm_of_cell(): */
3327 /**************************************/
3329 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3331 static char krbrlm[REALM_SZ+1]="";
3332 char ** realmlist=NULL;
3338 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3339 if ( !r && realmlist && realmlist[0] ) {
3340 strcpy(krbrlm, realmlist[0]);
3341 pkrb5_free_host_realm(ctx, realmlist);
3347 char *t = cellconfig->name;
3352 if (islower(c)) c=toupper(c);
3360 /**************************************/
3361 /* KFW_AFS_get_cellconfig(): */
3362 /**************************************/
3364 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3367 char newcell[MAXCELLCHARS+1];
3369 local_cell[0] = (char)0;
3370 memset(cellconfig, 0, sizeof(*cellconfig));
3372 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3373 if (rc = cm_GetRootCellName(local_cell))
3378 if (strlen(cell) == 0)
3379 strcpy(cell, local_cell);
3381 /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
3382 strcpy(cellconfig->name, cell);
3384 rc = cm_SearchCellFile(cell, newcell, get_cellconfig_callback, (void*)cellconfig);
3385 #ifdef AFS_AFSDB_ENV
3388 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3394 /**************************************/
3395 /* get_cellconfig_callback(): */
3396 /**************************************/
3398 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep)
3400 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3402 cc->hostAddr[cc->numServers] = *addrp;
3403 strcpy(cc->hostName[cc->numServers], namep);
3409 /**************************************/
3410 /* KFW_AFS_error(): */
3411 /**************************************/
3413 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3416 const char *errText;
3418 // Using AFS defines as error messages for now, until Transarc
3419 // gets back to me with "string" translations of each of these
3421 if (rc == KTC_ERROR)
3422 errText = "KTC_ERROR";
3423 else if (rc == KTC_TOOBIG)
3424 errText = "KTC_TOOBIG";
3425 else if (rc == KTC_INVAL)
3426 errText = "KTC_INVAL";
3427 else if (rc == KTC_NOENT)
3428 errText = "KTC_NOENT";
3429 else if (rc == KTC_PIOCTLFAIL)
3430 errText = "KTC_PIOCTLFAIL";
3431 else if (rc == KTC_NOPIOCTL)
3432 errText = "KTC_NOPIOCTL";
3433 else if (rc == KTC_NOCELL)
3434 errText = "KTC_NOCELL";
3435 else if (rc == KTC_NOCM)
3436 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3438 errText = "Unknown error!";
3440 sprintf(message, "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3442 if ( IsDebuggerPresent() ) {
3443 OutputDebugString(message);
3444 OutputDebugString("\n");
3446 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3452 LPSTR lpszMachineName,
3453 LPSTR lpszServiceName,
3454 DWORD *lpdwCurrentState)
3457 SC_HANDLE schSCManager = NULL;
3458 SC_HANDLE schService = NULL;
3459 DWORD fdwDesiredAccess = 0;
3460 SERVICE_STATUS ssServiceStatus = {0};
3463 *lpdwCurrentState = 0;
3465 fdwDesiredAccess = GENERIC_READ;
3467 schSCManager = OpenSCManager(lpszMachineName,
3471 if(schSCManager == NULL)
3473 hr = GetLastError();
3477 schService = OpenService(schSCManager,
3481 if(schService == NULL)
3483 hr = GetLastError();
3487 fRet = QueryServiceStatus(schService,
3492 hr = GetLastError();
3496 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3500 CloseServiceHandle(schService);
3501 CloseServiceHandle(schSCManager);
3514 for (n = 0; fi[n].func_ptr_var; n++)
3515 *(fi[n].func_ptr_var) = 0;
3516 if (h) FreeLibrary(h);
3521 const char* dll_name,
3523 HINSTANCE* ph, // [out, optional] - DLL handle
3524 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3525 int cleanup, // cleanup function pointers and unload on error
3526 int go_on, // continue loading even if some functions cannot be loaded
3527 int silent // do not pop-up a system dialog if DLL cannot be loaded
3536 if (pindex) *pindex = -1;
3538 for (n = 0; fi[n].func_ptr_var; n++)
3539 *(fi[n].func_ptr_var) = 0;
3542 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3543 h = LoadLibrary(dll_name);
3551 for (i = 0; (go_on || !error) && (i < n); i++)
3553 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3559 *(fi[i].func_ptr_var) = p;
3562 if (pindex) *pindex = last_i;
3563 if (error && cleanup && !go_on) {
3564 for (i = 0; i < n; i++) {
3565 *(fi[i].func_ptr_var) = 0;
3571 if (error) return 0;
3575 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3577 krb5_context ctx = NULL;
3578 krb5_ccache cc = NULL;
3579 krb5_error_code code;
3581 const char * realm = NULL;
3582 krb5_principal principal = NULL;
3583 char * pname = NULL;
3584 char password[PROBE_PASSWORD_LEN+1];
3585 BOOL serverReachable = 0;
3587 if (!pkrb5_init_context)
3590 code = pkrb5_init_context(&ctx);
3591 if (code) goto cleanup;
3594 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3596 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3597 realm, PROBE_USERNAME, NULL, NULL);
3598 if ( code ) goto cleanup;
3600 code = KFW_get_ccache(ctx, principal, &cc);
3601 if ( code ) goto cleanup;
3603 code = pkrb5_unparse_name(ctx, principal, &pname);
3604 if ( code ) goto cleanup;
3606 pwdata.data = password;
3607 pwdata.length = PROBE_PASSWORD_LEN;
3608 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3611 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3614 password[PROBE_PASSWORD_LEN] = '\0';
3616 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3626 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3627 case KRB5KDC_ERR_CLIENT_REVOKED:
3628 case KRB5KDC_ERR_CLIENT_NOTYET:
3629 case KRB5KDC_ERR_PREAUTH_FAILED:
3630 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3631 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3632 serverReachable = TRUE;
3635 serverReachable = FALSE;
3640 pkrb5_free_unparsed_name(ctx,pname);
3642 pkrb5_free_principal(ctx,principal);
3644 pkrb5_cc_close(ctx,cc);
3646 pkrb5_free_context(ctx);
3648 return serverReachable;
3652 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
3654 krb5_context ctx = NULL;
3655 krb5_error_code code;
3656 krb5_ccache mslsa_ccache=NULL;
3657 krb5_principal princ = NULL;
3658 char * pname = NULL;
3661 if (!KFW_is_available())
3664 if (code = pkrb5_init_context(&ctx))
3667 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3670 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3673 if (code = pkrb5_unparse_name(ctx, princ, &pname))
3676 if ( strlen(pname) < *dwSize ) {
3677 strncpy(szUser, pname, *dwSize);
3678 szUser[*dwSize-1] = '\0';
3681 *dwSize = (DWORD)strlen(pname);
3685 pkrb5_free_unparsed_name(ctx, pname);
3688 pkrb5_free_principal(ctx, princ);
3691 pkrb5_cc_close(ctx, mslsa_ccache);
3694 pkrb5_free_context(ctx);
3699 KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
3701 // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
3702 PSID pSystemSID = NULL;
3703 DWORD SystemSIDlength = 0, UserSIDlength = 0;
3704 PACL ccacheACL = NULL;
3705 DWORD ccacheACLlength = 0;
3706 PTOKEN_USER pTokenUser = NULL;
3715 /* Get System SID */
3716 if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
3722 SystemSIDlength = GetLengthSid(pSystemSID);
3723 ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
3724 + SystemSIDlength - sizeof(DWORD);
3727 if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
3729 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
3730 pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
3732 GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
3737 UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
3739 ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
3744 ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
3749 InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
3750 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3751 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3754 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3755 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3756 pTokenUser->User.Sid);
3757 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3758 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3763 gle = GetLastError();
3764 if (gle != ERROR_NO_TOKEN)
3767 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3768 OWNER_SECURITY_INFORMATION,
3769 pTokenUser->User.Sid,
3773 gle = GetLastError();
3774 if (gle != ERROR_NO_TOKEN)
3778 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3779 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3784 gle = GetLastError();
3785 if (gle != ERROR_NO_TOKEN)
3792 LocalFree(pSystemSID);
3794 LocalFree(pTokenUser);
3796 LocalFree(ccacheACL);
3801 KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
3804 DWORD dwSize = size-1; /* leave room for nul */
3807 if (!hUserToken || !newfilename || size <= 0)
3810 *newfilename = '\0';
3812 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
3813 if ( !dwLen || dwLen > dwSize )
3814 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
3815 if ( !dwLen || dwLen > dwSize )
3818 newfilename[dwSize] = '\0';
3823 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
3825 char filename[MAX_PATH] = "";
3827 char cachename[MAX_PATH + 8] = "FILE:";
3828 krb5_context ctx = NULL;
3829 krb5_error_code code;
3830 krb5_principal princ = NULL;
3831 krb5_ccache cc = NULL;
3832 krb5_ccache ncc = NULL;
3834 if (!pkrb5_init_context || !user || !szLogonId)
3837 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
3838 if ( count > sizeof(filename) || count == 0 ) {
3839 GetWindowsDirectory(filename, sizeof(filename));
3842 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
3845 strcat(filename, "\\");
3846 strcat(filename, szLogonId);
3848 strcat(cachename, filename);
3850 DeleteFile(filename);
3852 code = pkrb5_init_context(&ctx);
3853 if (code) goto cleanup;
3855 code = pkrb5_parse_name(ctx, user, &princ);
3856 if (code) goto cleanup;
3858 code = KFW_get_ccache(ctx, princ, &cc);
3859 if (code) goto cleanup;
3861 code = pkrb5_cc_resolve(ctx, cachename, &ncc);
3862 if (code) goto cleanup;
3864 code = pkrb5_cc_initialize(ctx, ncc, princ);
3865 if (code) goto cleanup;
3867 code = KFW_AFS_set_file_cache_dacl(filename, NULL);
3868 if (code) goto cleanup;
3870 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3874 pkrb5_cc_close(ctx, cc);
3878 pkrb5_cc_close(ctx, ncc);
3882 pkrb5_free_principal(ctx, princ);
3887 pkrb5_free_context(ctx);
3891 KFW_AFS_copy_file_cache_to_default_cache(char * filename)
3893 char cachename[MAX_PATH + 8] = "FILE:";
3894 krb5_context ctx = NULL;
3895 krb5_error_code code;
3896 krb5_principal princ = NULL;
3897 krb5_ccache cc = NULL;
3898 krb5_ccache ncc = NULL;
3901 if (!pkrb5_init_context || !filename)
3904 if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
3907 code = pkrb5_init_context(&ctx);
3910 strcat(cachename, filename);
3912 code = pkrb5_cc_resolve(ctx, cachename, &cc);
3913 if (code) goto cleanup;
3915 code = pkrb5_cc_get_principal(ctx, cc, &princ);
3917 code = pkrb5_cc_default(ctx, &ncc);
3919 code = pkrb5_cc_initialize(ctx, ncc, princ);
3922 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3925 pkrb5_cc_close(ctx, ncc);
3929 retval=0; /* success */
3933 pkrb5_cc_close(ctx, cc);
3937 DeleteFile(filename);
3940 pkrb5_free_principal(ctx, princ);
3945 pkrb5_free_context(ctx);
3950 /* We are including this
3952 /* Ticket lifetime. This defines the table used to lookup lifetime for the
3953 fixed part of rande of the one byte lifetime field. Values less than 0x80
3954 are intrpreted as the number of 5 minute intervals. Values from 0x80 to
3955 0xBF should be looked up in this table. The value of 0x80 is the same using
3956 both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days.
3957 The intervening values of have a fixed ratio of roughly 1.06914. The value
3958 oxFF is defined to mean a ticket has no expiration time. This should be
3959 used advisedly since individual servers may impose defacto upperbounds on
3960 ticket lifetimes. */
3962 #define TKTLIFENUMFIXED 64
3963 #define TKTLIFEMINFIXED 0x80
3964 #define TKTLIFEMAXFIXED 0xBF
3965 #define TKTLIFENOEXPIRE 0xFF
3966 #define MAXTKTLIFETIME (30*24*3600) /* 30 days */
3968 static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
3969 38400, /* 10.67 hours, 0.44 days */
3970 41055, /* 11.40 hours, 0.48 days */
3971 43894, /* 12.19 hours, 0.51 days */
3972 46929, /* 13.04 hours, 0.54 days */
3973 50174, /* 13.94 hours, 0.58 days */
3974 53643, /* 14.90 hours, 0.62 days */
3975 57352, /* 15.93 hours, 0.66 days */
3976 61318, /* 17.03 hours, 0.71 days */
3977 65558, /* 18.21 hours, 0.76 days */
3978 70091, /* 19.47 hours, 0.81 days */
3979 74937, /* 20.82 hours, 0.87 days */
3980 80119, /* 22.26 hours, 0.93 days */
3981 85658, /* 23.79 hours, 0.99 days */
3982 91581, /* 25.44 hours, 1.06 days */
3983 97914, /* 27.20 hours, 1.13 days */
3984 104684, /* 29.08 hours, 1.21 days */
3985 111922, /* 31.09 hours, 1.30 days */
3986 119661, /* 33.24 hours, 1.38 days */
3987 127935, /* 35.54 hours, 1.48 days */
3988 136781, /* 37.99 hours, 1.58 days */
3989 146239, /* 40.62 hours, 1.69 days */
3990 156350, /* 43.43 hours, 1.81 days */
3991 167161, /* 46.43 hours, 1.93 days */
3992 178720, /* 49.64 hours, 2.07 days */
3993 191077, /* 53.08 hours, 2.21 days */
3994 204289, /* 56.75 hours, 2.36 days */
3995 218415, /* 60.67 hours, 2.53 days */
3996 233517, /* 64.87 hours, 2.70 days */
3997 249664, /* 69.35 hours, 2.89 days */
3998 266926, /* 74.15 hours, 3.09 days */
3999 285383, /* 79.27 hours, 3.30 days */
4000 305116, /* 84.75 hours, 3.53 days */
4001 326213, /* 90.61 hours, 3.78 days */
4002 348769, /* 96.88 hours, 4.04 days */
4003 372885, /* 103.58 hours, 4.32 days */
4004 398668, /* 110.74 hours, 4.61 days */
4005 426234, /* 118.40 hours, 4.93 days */
4006 455705, /* 126.58 hours, 5.27 days */
4007 487215, /* 135.34 hours, 5.64 days */
4008 520904, /* 144.70 hours, 6.03 days */
4009 556921, /* 154.70 hours, 6.45 days */
4010 595430, /* 165.40 hours, 6.89 days */
4011 636601, /* 176.83 hours, 7.37 days */
4012 680618, /* 189.06 hours, 7.88 days */
4013 727680, /* 202.13 hours, 8.42 days */
4014 777995, /* 216.11 hours, 9.00 days */
4015 831789, /* 231.05 hours, 9.63 days */
4016 889303, /* 247.03 hours, 10.29 days */
4017 950794, /* 264.11 hours, 11.00 days */
4018 1016537, /* 282.37 hours, 11.77 days */
4019 1086825, /* 301.90 hours, 12.58 days */
4020 1161973, /* 322.77 hours, 13.45 days */
4021 1242318, /* 345.09 hours, 14.38 days */
4022 1328218, /* 368.95 hours, 15.37 days */
4023 1420057, /* 394.46 hours, 16.44 days */
4024 1518247, /* 421.74 hours, 17.57 days */
4025 1623226, /* 450.90 hours, 18.79 days */
4026 1735464, /* 482.07 hours, 20.09 days */
4027 1855462, /* 515.41 hours, 21.48 days */
4028 1983758, /* 551.04 hours, 22.96 days */
4029 2120925, /* 589.15 hours, 24.55 days */
4030 2267576, /* 629.88 hours, 26.25 days */
4031 2424367, /* 673.44 hours, 28.06 days */
4033 }; /* 720.00 hours, 30.00 days */
4035 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
4036 * returns the corresponding end time. There are four simple cases to be
4037 * handled. The first is a life of 0xff, meaning no expiration, and results in
4038 * an end time of 0xffffffff. The second is when life is less than the values
4039 * covered by the table. In this case, the end time is the start time plus the
4040 * number of 5 minute intervals specified by life. The third case returns
4041 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
4042 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
4043 * table to extract the lifetime in seconds, which is added to start to produce
4047 life_to_time(afs_uint32 start, unsigned char life)
4051 if (life == TKTLIFENOEXPIRE)
4053 if (life < TKTLIFEMINFIXED)
4054 return start + life * 5 * 60;
4055 if (life > TKTLIFEMAXFIXED)
4056 return start + MAXTKTLIFETIME;
4057 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
4058 return start + realLife;
4061 /* time_to_life - takes start and end times for the ticket and returns a
4062 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
4063 * lifetimes above 127*5minutes. First, the special case of (end ==
4064 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
4065 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
4066 * less than the first table entry are handled by rounding the requested
4067 * lifetime *up* to the next 5 minute interval. The final step is to search
4068 * the table for the smallest entry *greater than or equal* to the requested
4069 * entry. The actual code is prepared to handle the case where the table is
4070 * unordered but that it an unnecessary frill. */
4072 static unsigned char
4073 time_to_life(afs_uint32 start, afs_uint32 end)
4075 int lifetime = end - start;
4079 if (end == NEVERDATE)
4080 return TKTLIFENOEXPIRE;
4081 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
4083 if (lifetime < tkt_lifetimes[0])
4084 return (lifetime + 5 * 60 - 1) / (5 * 60);
4086 best = MAXKTCTICKETLIFETIME;
4087 for (i = 0; i < TKTLIFENUMFIXED; i++)
4088 if (tkt_lifetimes[i] >= lifetime) {
4089 int diff = tkt_lifetimes[i] - lifetime;
4097 return best_i + TKTLIFEMINFIXED;