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>
82 * TIMING _____________________________________________________________________
86 #define cminREMIND_TEST 1 // test every minute for expired creds
87 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
88 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
89 #define cminMINLIFE 30 // minimum life of Kerberos creds
91 #define c100ns1SECOND (LONGLONG)10000000
92 #define cmsec1SECOND 1000
93 #define cmsec1MINUTE 60000
94 #define csec1MINUTE 60
96 /* Function Pointer Declarations for Delayed Loading */
98 DECL_FUNC_PTR(cc_initialize);
99 DECL_FUNC_PTR(cc_shutdown);
100 DECL_FUNC_PTR(cc_get_NC_info);
101 DECL_FUNC_PTR(cc_free_NC_info);
105 DECL_FUNC_PTR(Leash_get_default_lifetime);
106 DECL_FUNC_PTR(Leash_get_default_forwardable);
107 DECL_FUNC_PTR(Leash_get_default_renew_till);
108 DECL_FUNC_PTR(Leash_get_default_noaddresses);
109 DECL_FUNC_PTR(Leash_get_default_proxiable);
110 DECL_FUNC_PTR(Leash_get_default_publicip);
111 DECL_FUNC_PTR(Leash_get_default_use_krb4);
112 DECL_FUNC_PTR(Leash_get_default_life_min);
113 DECL_FUNC_PTR(Leash_get_default_life_max);
114 DECL_FUNC_PTR(Leash_get_default_renew_min);
115 DECL_FUNC_PTR(Leash_get_default_renew_max);
116 DECL_FUNC_PTR(Leash_get_default_renewable);
117 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
121 DECL_FUNC_PTR(krb5_change_password);
122 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
123 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
124 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
125 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
126 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
127 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
128 DECL_FUNC_PTR(krb5_get_init_creds_password);
129 DECL_FUNC_PTR(krb5_build_principal_ext);
130 DECL_FUNC_PTR(krb5_cc_get_name);
131 DECL_FUNC_PTR(krb5_cc_resolve);
132 DECL_FUNC_PTR(krb5_cc_default);
133 DECL_FUNC_PTR(krb5_cc_default_name);
134 DECL_FUNC_PTR(krb5_cc_set_default_name);
135 DECL_FUNC_PTR(krb5_cc_initialize);
136 DECL_FUNC_PTR(krb5_cc_destroy);
137 DECL_FUNC_PTR(krb5_cc_close);
138 DECL_FUNC_PTR(krb5_cc_store_cred);
139 DECL_FUNC_PTR(krb5_cc_copy_creds);
140 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
141 DECL_FUNC_PTR(krb5_cc_get_principal);
142 DECL_FUNC_PTR(krb5_cc_start_seq_get);
143 DECL_FUNC_PTR(krb5_cc_next_cred);
144 DECL_FUNC_PTR(krb5_cc_end_seq_get);
145 DECL_FUNC_PTR(krb5_cc_remove_cred);
146 DECL_FUNC_PTR(krb5_cc_set_flags);
147 DECL_FUNC_PTR(krb5_cc_get_type);
148 DECL_FUNC_PTR(krb5_free_context);
149 DECL_FUNC_PTR(krb5_free_cred_contents);
150 DECL_FUNC_PTR(krb5_free_principal);
151 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
152 DECL_FUNC_PTR(krb5_init_context);
153 DECL_FUNC_PTR(krb5_parse_name);
154 DECL_FUNC_PTR(krb5_timeofday);
155 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
156 DECL_FUNC_PTR(krb5_unparse_name);
157 DECL_FUNC_PTR(krb5_get_credentials);
158 DECL_FUNC_PTR(krb5_mk_req);
159 DECL_FUNC_PTR(krb5_sname_to_principal);
160 DECL_FUNC_PTR(krb5_get_credentials_renew);
161 DECL_FUNC_PTR(krb5_free_data);
162 DECL_FUNC_PTR(krb5_free_data_contents);
163 DECL_FUNC_PTR(krb5_free_unparsed_name);
164 DECL_FUNC_PTR(krb5_os_localaddr);
165 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
166 DECL_FUNC_PTR(krb5_copy_data);
167 DECL_FUNC_PTR(krb5_free_creds);
168 DECL_FUNC_PTR(krb5_build_principal);
169 DECL_FUNC_PTR(krb5_get_renewed_creds);
170 DECL_FUNC_PTR(krb5_get_default_config_files);
171 DECL_FUNC_PTR(krb5_free_config_files);
172 DECL_FUNC_PTR(krb5_get_default_realm);
173 DECL_FUNC_PTR(krb5_free_default_realm);
174 DECL_FUNC_PTR(krb5_free_ticket);
175 DECL_FUNC_PTR(krb5_decode_ticket);
176 DECL_FUNC_PTR(krb5_get_host_realm);
177 DECL_FUNC_PTR(krb5_free_host_realm);
178 DECL_FUNC_PTR(krb5_free_addresses);
179 DECL_FUNC_PTR(krb5_c_random_make_octets);
183 DECL_FUNC_PTR(krb524_init_ets);
184 DECL_FUNC_PTR(krb524_convert_creds_kdc);
189 DECL_FUNC_PTR(krb_get_cred);
190 DECL_FUNC_PTR(tkt_string);
191 DECL_FUNC_PTR(krb_get_tf_realm);
192 DECL_FUNC_PTR(krb_mk_req);
196 DECL_FUNC_PTR(com_err);
197 DECL_FUNC_PTR(error_message);
200 DECL_FUNC_PTR(profile_init);
201 DECL_FUNC_PTR(profile_release);
202 DECL_FUNC_PTR(profile_get_subsection_names);
203 DECL_FUNC_PTR(profile_free_list);
204 DECL_FUNC_PTR(profile_get_string);
205 DECL_FUNC_PTR(profile_release_string);
208 DECL_FUNC_PTR(OpenSCManagerA);
209 DECL_FUNC_PTR(OpenServiceA);
210 DECL_FUNC_PTR(QueryServiceStatus);
211 DECL_FUNC_PTR(CloseServiceHandle);
213 DECL_FUNC_PTR(LsaNtStatusToWinError);
214 #endif /* USE_MS2MIT */
218 DECL_FUNC_PTR(LsaConnectUntrusted);
219 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
220 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
221 DECL_FUNC_PTR(LsaFreeReturnBuffer);
222 DECL_FUNC_PTR(LsaGetLogonSessionData);
223 #endif /* USE_MS2MIT */
226 FUNC_INFO ccapi_fi[] = {
227 MAKE_FUNC_INFO(cc_initialize),
228 MAKE_FUNC_INFO(cc_shutdown),
229 MAKE_FUNC_INFO(cc_get_NC_info),
230 MAKE_FUNC_INFO(cc_free_NC_info),
235 FUNC_INFO leash_fi[] = {
236 MAKE_FUNC_INFO(Leash_get_default_lifetime),
237 MAKE_FUNC_INFO(Leash_get_default_renew_till),
238 MAKE_FUNC_INFO(Leash_get_default_forwardable),
239 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
240 MAKE_FUNC_INFO(Leash_get_default_proxiable),
241 MAKE_FUNC_INFO(Leash_get_default_publicip),
242 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
243 MAKE_FUNC_INFO(Leash_get_default_life_min),
244 MAKE_FUNC_INFO(Leash_get_default_life_max),
245 MAKE_FUNC_INFO(Leash_get_default_renew_min),
246 MAKE_FUNC_INFO(Leash_get_default_renew_max),
247 MAKE_FUNC_INFO(Leash_get_default_renewable),
251 FUNC_INFO leash_opt_fi[] = {
252 MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
257 FUNC_INFO k5_fi[] = {
258 MAKE_FUNC_INFO(krb5_change_password),
259 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
260 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
261 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
262 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
263 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
264 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
265 MAKE_FUNC_INFO(krb5_get_init_creds_password),
266 MAKE_FUNC_INFO(krb5_build_principal_ext),
267 MAKE_FUNC_INFO(krb5_cc_get_name),
268 MAKE_FUNC_INFO(krb5_cc_resolve),
269 MAKE_FUNC_INFO(krb5_cc_default),
270 MAKE_FUNC_INFO(krb5_cc_default_name),
271 MAKE_FUNC_INFO(krb5_cc_set_default_name),
272 MAKE_FUNC_INFO(krb5_cc_initialize),
273 MAKE_FUNC_INFO(krb5_cc_destroy),
274 MAKE_FUNC_INFO(krb5_cc_close),
275 MAKE_FUNC_INFO(krb5_cc_copy_creds),
276 MAKE_FUNC_INFO(krb5_cc_store_cred),
277 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
278 MAKE_FUNC_INFO(krb5_cc_get_principal),
279 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
280 MAKE_FUNC_INFO(krb5_cc_next_cred),
281 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
282 MAKE_FUNC_INFO(krb5_cc_remove_cred),
283 MAKE_FUNC_INFO(krb5_cc_set_flags),
284 MAKE_FUNC_INFO(krb5_cc_get_type),
285 MAKE_FUNC_INFO(krb5_free_context),
286 MAKE_FUNC_INFO(krb5_free_cred_contents),
287 MAKE_FUNC_INFO(krb5_free_principal),
288 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
289 MAKE_FUNC_INFO(krb5_init_context),
290 MAKE_FUNC_INFO(krb5_parse_name),
291 MAKE_FUNC_INFO(krb5_timeofday),
292 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
293 MAKE_FUNC_INFO(krb5_unparse_name),
294 MAKE_FUNC_INFO(krb5_get_credentials),
295 MAKE_FUNC_INFO(krb5_mk_req),
296 MAKE_FUNC_INFO(krb5_sname_to_principal),
297 MAKE_FUNC_INFO(krb5_get_credentials_renew),
298 MAKE_FUNC_INFO(krb5_free_data),
299 MAKE_FUNC_INFO(krb5_free_data_contents),
300 MAKE_FUNC_INFO(krb5_free_unparsed_name),
301 MAKE_FUNC_INFO(krb5_os_localaddr),
302 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
303 MAKE_FUNC_INFO(krb5_copy_data),
304 MAKE_FUNC_INFO(krb5_free_creds),
305 MAKE_FUNC_INFO(krb5_build_principal),
306 MAKE_FUNC_INFO(krb5_get_renewed_creds),
307 MAKE_FUNC_INFO(krb5_free_addresses),
308 MAKE_FUNC_INFO(krb5_get_default_config_files),
309 MAKE_FUNC_INFO(krb5_free_config_files),
310 MAKE_FUNC_INFO(krb5_get_default_realm),
311 MAKE_FUNC_INFO(krb5_free_default_realm),
312 MAKE_FUNC_INFO(krb5_free_ticket),
313 MAKE_FUNC_INFO(krb5_decode_ticket),
314 MAKE_FUNC_INFO(krb5_get_host_realm),
315 MAKE_FUNC_INFO(krb5_free_host_realm),
316 MAKE_FUNC_INFO(krb5_free_addresses),
317 MAKE_FUNC_INFO(krb5_c_random_make_octets),
322 FUNC_INFO k4_fi[] = {
323 MAKE_FUNC_INFO(krb_get_cred),
324 MAKE_FUNC_INFO(krb_get_tf_realm),
325 MAKE_FUNC_INFO(krb_mk_req),
326 MAKE_FUNC_INFO(tkt_string),
332 FUNC_INFO k524_fi[] = {
333 MAKE_FUNC_INFO(krb524_init_ets),
334 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
339 FUNC_INFO profile_fi[] = {
340 MAKE_FUNC_INFO(profile_init),
341 MAKE_FUNC_INFO(profile_release),
342 MAKE_FUNC_INFO(profile_get_subsection_names),
343 MAKE_FUNC_INFO(profile_free_list),
344 MAKE_FUNC_INFO(profile_get_string),
345 MAKE_FUNC_INFO(profile_release_string),
349 FUNC_INFO ce_fi[] = {
350 MAKE_FUNC_INFO(com_err),
351 MAKE_FUNC_INFO(error_message),
355 FUNC_INFO service_fi[] = {
356 MAKE_FUNC_INFO(OpenSCManagerA),
357 MAKE_FUNC_INFO(OpenServiceA),
358 MAKE_FUNC_INFO(QueryServiceStatus),
359 MAKE_FUNC_INFO(CloseServiceHandle),
361 MAKE_FUNC_INFO(LsaNtStatusToWinError),
362 #endif /* USE_MS2MIT */
367 FUNC_INFO lsa_fi[] = {
368 MAKE_FUNC_INFO(LsaConnectUntrusted),
369 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
370 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
371 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
372 MAKE_FUNC_INFO(LsaGetLogonSessionData),
375 #endif /* USE_MS2MIT */
377 /* Static Prototypes */
378 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
379 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *, unsigned short);
380 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
381 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
382 void *data, const char *name, const char *banner, int num_prompts,
383 krb5_prompt prompts[]);
386 /* Static Declarations */
387 static int inited = 0;
388 static int mid_cnt = 0;
389 static struct textField * mid_tb = NULL;
390 static HINSTANCE hKrb5 = 0;
392 static HINSTANCE hKrb4 = 0;
393 #endif /* USE_KRB4 */
395 static HINSTANCE hKrb524 = 0;
398 static HINSTANCE hSecur32 = 0;
399 #endif /* USE_MS2MIT */
400 static HINSTANCE hAdvApi32 = 0;
401 static HINSTANCE hComErr = 0;
402 static HINSTANCE hService = 0;
403 static HINSTANCE hProfile = 0;
405 static HINSTANCE hLeash = 0;
406 static HINSTANCE hLeashOpt = 0;
408 static HINSTANCE hCCAPI = 0;
409 static struct principal_ccache_data * princ_cc_data = NULL;
410 static struct cell_principal_map * cell_princ_map = NULL;
415 static int inited = 0;
418 char mutexName[MAX_PATH];
419 HANDLE hMutex = NULL;
421 sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
423 hMutex = CreateMutex( NULL, TRUE, mutexName );
424 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
425 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
431 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
432 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
433 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
435 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
436 #endif /* USE_KRB4 */
437 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
439 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
440 #endif /* USE_MS2MIT */
442 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
445 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
446 LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
448 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
450 if ( KFW_is_available() ) {
451 char rootcell[CELL_MAXNAMELEN+1];
453 KFW_import_windows_lsa();
454 #endif /* USE_MS2MIT */
455 KFW_import_ccache_data();
456 KFW_AFS_renew_expiring_tokens();
458 /* WIN32 NOTE: no way to get max chars */
459 if (!cm_GetRootCellName(rootcell))
460 KFW_AFS_renew_token_for_cell(rootcell);
463 ReleaseMutex(hMutex);
473 FreeLibrary(hLeashOpt);
479 FreeLibrary(hKrb524);
485 FreeLibrary(hSecur32);
486 #endif /* USE_MS2MIT */
488 FreeLibrary(hService);
490 FreeLibrary(hComErr);
492 FreeLibrary(hProfile);
496 #endif /* USE_KRB4 */
501 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
504 static int init = TRUE;
505 static int bIsWow64 = FALSE;
509 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
511 hModule = GetModuleHandle(TEXT("kernel32"));
513 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
515 if (NULL != fnIsWow64Process)
517 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
519 // on error, assume FALSE.
520 // in other words, do nothing.
523 FreeLibrary(hModule);
531 KFW_accept_dotted_usernames(void)
537 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
538 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
539 if (code == ERROR_SUCCESS) {
541 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
542 (BYTE *) &value, &len);
543 RegCloseKey(parmKey);
545 if (code != ERROR_SUCCESS) {
546 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
547 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
548 if (code == ERROR_SUCCESS) {
550 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
551 (BYTE *) &value, &len);
552 RegCloseKey (parmKey);
566 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
567 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
568 if (code == ERROR_SUCCESS) {
569 len = sizeof(use524);
570 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
571 (BYTE *) &use524, &len);
572 RegCloseKey(parmKey);
574 if (code != ERROR_SUCCESS) {
575 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
576 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
577 if (code == ERROR_SUCCESS) {
578 len = sizeof(use524);
579 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
580 (BYTE *) &use524, &len);
581 RegCloseKey (parmKey);
588 KFW_is_available(void)
594 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
595 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
596 if (code == ERROR_SUCCESS) {
597 len = sizeof(enableKFW);
598 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
599 (BYTE *) &enableKFW, &len);
600 RegCloseKey (parmKey);
603 if (code != ERROR_SUCCESS) {
604 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
605 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
606 if (code == ERROR_SUCCESS) {
607 len = sizeof(enableKFW);
608 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
609 (BYTE *) &enableKFW, &len);
610 RegCloseKey (parmKey);
618 if ( hKrb5 && hComErr && hService &&
621 #endif /* USE_MS2MIT */
634 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
635 int FreeContextFlag, krb5_context * ctx,
640 int krb5Error = ((int)(rc & 255));
652 errText = perror_message(rc);
653 _snprintf(message, sizeof(message),
654 "%s\n(Kerberos error %ld)\n\n%s failed",
659 if ( IsDebuggerPresent() )
660 OutputDebugString(message);
662 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
665 if (FreeContextFlag == 1)
667 if (ctx && *ctx != NULL)
669 if (cache && *cache != NULL) {
670 pkrb5_cc_close(*ctx, *cache);
674 pkrb5_free_context(*ctx);
683 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
685 struct principal_ccache_data * next = princ_cc_data;
686 krb5_principal principal = 0;
688 const char * ccname = NULL;
689 const char * cctype = NULL;
690 char * ccfullname = NULL;
691 krb5_error_code code = 0;
692 krb5_error_code cc_code = 0;
698 if (ctx == 0 || cc == 0)
701 code = pkrb5_cc_get_principal(ctx, cc, &principal);
704 code = pkrb5_unparse_name(ctx, principal, &pname);
705 if ( code ) goto cleanup;
707 ccname = pkrb5_cc_get_name(ctx, cc);
708 if (!ccname) goto cleanup;
710 cctype = pkrb5_cc_get_type(ctx, cc);
711 if (!cctype) goto cleanup;
713 ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
714 if (!ccfullname) goto cleanup;
716 sprintf(ccfullname, "%s:%s", cctype, ccname);
718 // Search the existing list to see if we have a match
720 for ( ; next ; next = next->next ) {
721 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
726 // If not, match add a new node to the beginning of the list and assign init it
728 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
729 next->next = princ_cc_data;
730 princ_cc_data = next;
731 next->principal = _strdup(pname);
732 next->ccache_name = ccfullname;
734 next->from_lsa = lsa;
736 next->expiration_time = 0;
740 flags = 0; // turn off OPENCLOSE mode
741 code = pkrb5_cc_set_flags(ctx, cc, flags);
742 if ( code ) goto cleanup;
744 code = pkrb5_timeofday(ctx, &now);
746 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
748 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
749 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
751 // we found the ticket we are looking for
752 // check validity of timestamp
753 // We add a 5 minutes fudge factor to compensate for potential
754 // clock skew errors between the KDC and client OS
756 valid = ((creds.times.starttime > 0) &&
757 now >= (creds.times.starttime - 300) &&
758 now < (creds.times.endtime + 300) &&
759 !(creds.ticket_flags & TKT_FLG_INVALID));
761 if ( next->from_lsa) {
763 next->expiration_time = creds.times.endtime;
765 } else if ( valid ) {
767 next->expiration_time = creds.times.endtime;
768 next->renew = (creds.times.renew_till > creds.times.endtime) &&
769 (creds.ticket_flags & TKT_FLG_RENEWABLE);
772 next->expiration_time = 0;
776 pkrb5_free_cred_contents(ctx, &creds);
777 cc_code = KRB5_CC_END;
780 pkrb5_free_cred_contents(ctx, &creds);
783 if (cc_code == KRB5_CC_END) {
784 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
785 if (code) goto cleanup;
789 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
790 code = pkrb5_cc_set_flags(ctx, cc, flags);
795 pkrb5_free_unparsed_name(ctx,pname);
797 pkrb5_free_principal(ctx,principal);
801 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
803 struct principal_ccache_data * next = princ_cc_data;
804 char * response = NULL;
806 if ( !principal || !ccache )
810 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
812 // we always want to prefer the MS Kerberos LSA cache or
813 // the cache afscreds created specifically for the principal
814 // if the current entry is either one, drop the previous find
815 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
818 response = _strdup(next->ccache_name);
819 // MS Kerberos LSA is our best option so use it and quit
820 if ( next->from_lsa )
834 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
836 struct principal_ccache_data ** next = &princ_cc_data;
838 if ( !pname && !ccname )
842 if ( !strcmp((*next)->principal,pname) ||
843 !strcmp((*next)->ccache_name,ccname) ) {
845 free((*next)->principal);
846 free((*next)->ccache_name);
848 (*next) = (*next)->next;
855 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
857 struct cell_principal_map * next = cell_princ_map;
859 // Search the existing list to see if we have a match
861 for ( ; next ; next = next->next ) {
862 if ( !strcmp(next->cell, cell) ) {
863 if ( !strcmp(next->principal,pname) ) {
864 next->active = active;
867 // OpenAFS currently has a restriction of one active token per cell
868 // Therefore, whenever we update the table with a new active cell we
869 // must mark all of the other principal to cell entries as inactive.
877 // If not, match add a new node to the beginning of the list and assign init it
879 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
880 next->next = cell_princ_map;
881 cell_princ_map = next;
882 next->principal = _strdup(pname);
883 next->cell = _strdup(cell);
884 next->active = active;
889 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
891 struct cell_principal_map ** next = &cell_princ_map;
893 if ( !pname && !cell )
897 if ( !strcmp((*next)->principal,pname) ||
898 !strcmp((*next)->cell,cell) ) {
900 free((*next)->principal);
903 (*next) = (*next)->next;
909 // Returns (if possible) a principal which has been known in
910 // the past to have been used to obtain tokens for the specified
912 // TODO: Attempt to return one which has not yet expired by checking
913 // the principal/ccache data
915 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
917 struct cell_principal_map * next_map = cell_princ_map;
918 const char * princ = NULL;
925 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
928 next_map = next_map->next;
931 if ( !principals || !count )
934 *principals = (char **) malloc(sizeof(char *) * count);
935 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
937 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
938 (*principals)[i++] = _strdup(next_map->principal);
945 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
948 struct cell_principal_map * next_map = cell_princ_map;
949 const char * princ = NULL;
955 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
958 next_map = next_map->next;
964 *cells = (char **) malloc(sizeof(char *) * count);
965 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
967 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
968 (*cells)[i++] = _strdup(next_map->cell);
974 /* Given a principal return an existing ccache or create one and return */
976 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
978 krb5_context ctx = NULL;
980 char * ccname = NULL;
981 krb5_error_code code;
983 if (!pkrb5_init_context)
989 code = pkrb5_init_context(&ctx);
990 if (code) goto cleanup;
994 code = pkrb5_unparse_name(ctx, principal, &pname);
995 if (code) goto cleanup;
997 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
998 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
999 ccname = (char *)malloc(strlen(pname) + 5);
1000 sprintf(ccname,"API:%s",pname);
1002 code = pkrb5_cc_resolve(ctx, ccname, cc);
1004 code = pkrb5_cc_default(ctx, cc);
1005 if (code) goto cleanup;
1012 pkrb5_free_unparsed_name(ctx,pname);
1013 if (ctx && (ctx != alt_ctx))
1014 pkrb5_free_context(ctx);
1019 // Import Microsoft Credentials into a new MIT ccache
1021 KFW_import_windows_lsa(void)
1023 krb5_context ctx = NULL;
1024 krb5_ccache cc = NULL;
1025 krb5_principal princ = NULL;
1026 char * pname = NULL;
1027 krb5_data * princ_realm;
1028 krb5_error_code code;
1029 char cell[128]="", realm[128]="", *def_realm = 0;
1031 DWORD dwMsLsaImport;
1033 if (!pkrb5_init_context)
1036 code = pkrb5_init_context(&ctx);
1037 if (code) goto cleanup;
1039 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
1040 if (code) goto cleanup;
1042 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
1044 code = pkrb5_cc_get_principal(ctx, cc, &princ);
1045 if ( code ) goto cleanup;
1047 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
1048 switch ( dwMsLsaImport ) {
1049 case 0: /* do not import */
1051 case 1: /* always import */
1053 case 2: { /* matching realm */
1054 char ms_realm[128] = "", *r;
1057 for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) {
1058 *r = krb5_princ_realm(ctx, princ)->data[i];
1062 if (code = pkrb5_get_default_realm(ctx, &def_realm))
1065 if (strcmp(def_realm, ms_realm))
1073 code = pkrb5_unparse_name(ctx,princ,&pname);
1074 if ( code ) goto cleanup;
1076 princ_realm = krb5_princ_realm(ctx, princ);
1077 for ( i=0; i<princ_realm->length; i++ ) {
1078 realm[i] = princ_realm->data[i];
1079 cell[i] = tolower(princ_realm->data[i]);
1084 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
1085 if ( IsDebuggerPresent() ) {
1087 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1088 OutputDebugString(message);
1090 if ( code ) goto cleanup;
1092 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1096 pkrb5_free_unparsed_name(ctx,pname);
1098 pkrb5_free_principal(ctx,princ);
1100 pkrb5_free_default_realm(ctx, def_realm);
1102 pkrb5_cc_close(ctx,cc);
1104 pkrb5_free_context(ctx);
1106 #endif /* USE_MS2MIT */
1108 // If there are existing MIT credentials, copy them to a new
1109 // ccache named after the principal
1111 // Enumerate all existing MIT ccaches and construct entries
1112 // in the principal_ccache table
1114 // Enumerate all existing AFS Tokens and construct entries
1115 // in the cell_principal table
1117 KFW_import_ccache_data(void)
1119 krb5_context ctx = NULL;
1120 krb5_ccache cc = NULL;
1121 krb5_principal principal = NULL;
1123 krb5_error_code code;
1124 krb5_error_code cc_code;
1126 apiCB * cc_ctx = NULL;
1127 struct _infoNC ** pNCi = NULL;
1130 if ( !pcc_initialize )
1133 if ( IsDebuggerPresent() )
1134 OutputDebugString("KFW_import_ccache_data()\n");
1136 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1137 if (code) goto cleanup;
1139 code = pcc_get_NC_info(cc_ctx, &pNCi);
1140 if (code) goto cleanup;
1142 code = pkrb5_init_context(&ctx);
1143 if (code) goto cleanup;
1145 for ( i=0; pNCi[i]; i++ ) {
1146 if ( pNCi[i]->vers != CC_CRED_V5 )
1148 if ( IsDebuggerPresent() ) {
1149 OutputDebugString("Principal: ");
1150 OutputDebugString(pNCi[i]->principal);
1151 OutputDebugString(" in ccache ");
1152 OutputDebugString(pNCi[i]->name);
1153 OutputDebugString("\n");
1155 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1156 && strcmp(pNCi[i]->name,LSA_CCNAME)
1159 for ( j=0; pNCi[j]; j++ ) {
1160 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1166 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1167 if (code) goto loop_cleanup;
1170 krb5_ccache oldcc = 0;
1172 if ( IsDebuggerPresent() )
1173 OutputDebugString("copying ccache data to new ccache\n");
1175 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1176 if (code) goto loop_cleanup;
1177 code = pkrb5_cc_initialize(ctx, cc, principal);
1178 if (code) goto loop_cleanup;
1180 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1181 if (code) goto loop_cleanup;
1182 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1184 code = pkrb5_cc_close(ctx,cc);
1186 code = pkrb5_cc_close(ctx,oldcc);
1188 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1191 code = pkrb5_cc_close(ctx,oldcc);
1194 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1195 if (code) goto loop_cleanup;
1198 flags = 0; // turn off OPENCLOSE mode
1199 code = pkrb5_cc_set_flags(ctx, cc, flags);
1200 if ( code ) goto cleanup;
1202 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1204 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1206 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1207 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1208 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1209 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1210 if ( sname && cell && !strcmp("afs",sname->data) ) {
1211 struct ktc_principal aserver;
1212 struct ktc_principal aclient;
1213 struct ktc_token atoken;
1216 if ( IsDebuggerPresent() ) {
1217 OutputDebugString("Found AFS ticket: ");
1218 OutputDebugString(sname->data);
1220 OutputDebugString("/");
1221 OutputDebugString(cell->data);
1223 OutputDebugString("@");
1224 OutputDebugString(realm->data);
1225 OutputDebugString("\n");
1228 memset(&aserver, '\0', sizeof(aserver));
1229 strcpy(aserver.name, sname->data);
1230 strcpy(aserver.cell, cell->data);
1232 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1234 // Found a token in AFS Client Server which matches
1235 char pname[128], *p, *q;
1236 for ( p=pname, q=aclient.name; *q; p++, q++)
1238 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1242 if ( IsDebuggerPresent() ) {
1243 OutputDebugString("Found AFS token: ");
1244 OutputDebugString(pname);
1245 OutputDebugString("\n");
1248 if ( strcmp(pname,pNCi[i]->principal) )
1250 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1252 // Attempt to import it
1253 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1255 if ( IsDebuggerPresent() ) {
1256 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1259 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data,
1263 pLeash_get_default_lifetime(),
1264 #endif /* USE_LEASH */
1266 if ( IsDebuggerPresent() ) {
1268 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1269 OutputDebugString(message);
1272 } else if ( IsDebuggerPresent() ) {
1273 OutputDebugString("Found ticket: ");
1274 OutputDebugString(sname->data);
1275 if ( cell && cell->data ) {
1276 OutputDebugString("/");
1277 OutputDebugString(cell->data);
1279 OutputDebugString("@");
1280 OutputDebugString(realm->data);
1281 OutputDebugString("\n");
1283 pkrb5_free_cred_contents(ctx, &creds);
1286 if (cc_code == KRB5_CC_END) {
1287 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1288 if (cc_code) goto loop_cleanup;
1292 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1293 code = pkrb5_cc_set_flags(ctx, cc, flags);
1295 pkrb5_cc_close(ctx,cc);
1299 pkrb5_free_principal(ctx,principal);
1306 pkrb5_free_context(ctx);
1308 pcc_free_NC_info(cc_ctx, &pNCi);
1310 pcc_shutdown(&cc_ctx);
1315 KFW_AFS_get_cred( char * username,
1322 krb5_context ctx = NULL;
1323 krb5_ccache cc = NULL;
1324 char * realm = NULL, * userrealm = NULL;
1325 krb5_principal principal = NULL;
1326 char * pname = NULL;
1327 krb5_error_code code;
1328 char local_cell[CELL_MAXNAMELEN+1];
1329 char **cells = NULL;
1331 struct afsconf_cell cellconfig;
1334 if (!pkrb5_init_context)
1337 if ( IsDebuggerPresent() ) {
1338 OutputDebugString("KFW_AFS_get_cred for token ");
1339 OutputDebugString(username);
1340 OutputDebugString(" in cell ");
1341 OutputDebugString(cell);
1342 OutputDebugString("\n");
1345 memset(&cellconfig, 0, sizeof(cellconfig));
1347 code = pkrb5_init_context(&ctx);
1348 if ( code ) goto cleanup;
1350 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1351 if ( code ) goto cleanup;
1353 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1355 userrealm = strchr(username,'@');
1357 pname = strdup(username);
1358 if (!KFW_accept_dotted_usernames()) {
1359 userrealm = strchr(pname, '@');
1362 /* handle kerberos iv notation */
1363 while ( dot = strchr(pname,'.') ) {
1369 pname = malloc(strlen(username) + strlen(realm) + 2);
1371 strcpy(pname, username);
1373 if (!KFW_accept_dotted_usernames()) {
1374 /* handle kerberos iv notation */
1375 while ( dot = strchr(pname,'.') ) {
1380 strcat(pname,realm);
1382 if ( IsDebuggerPresent() ) {
1383 OutputDebugString("Realm: ");
1384 OutputDebugString(realm);
1385 OutputDebugString("\n");
1388 code = pkrb5_parse_name(ctx, pname, &principal);
1389 if ( code ) goto cleanup;
1391 code = KFW_get_ccache(ctx, principal, &cc);
1392 if ( code ) goto cleanup;
1394 if ( lifetime == 0 )
1398 lifetime = pLeash_get_default_lifetime();
1401 if ( password && password[0] ) {
1402 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1407 1, /* forwardable */
1408 0, /* not proxiable */
1410 1, /* noaddresses */
1411 0 /* no public ip */
1413 pLeash_get_default_forwardable(),
1414 pLeash_get_default_proxiable(),
1415 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1416 pLeash_get_default_noaddresses(),
1417 pLeash_get_default_publicip()
1418 #endif /* USE_LEASH */
1421 if ( IsDebuggerPresent() ) {
1423 sprintf(message,"KFW_kinit() returns: %d\n",code);
1424 OutputDebugString(message);
1426 if ( code ) goto cleanup;
1428 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1431 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1432 if ( IsDebuggerPresent() ) {
1434 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1435 OutputDebugString(message);
1437 if ( code ) goto cleanup;
1439 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1441 // Attempt to obtain new tokens for other cells supported by the same
1443 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1444 if ( cell_count > 1 ) {
1445 while ( cell_count-- ) {
1446 if ( strcmp(cells[cell_count],cell) ) {
1447 if ( IsDebuggerPresent() ) {
1449 sprintf(message,"found another cell for the same principal: %s\n",cell);
1450 OutputDebugString(message);
1453 if (cellconfig.linkedCell) {
1454 free(cellconfig.linkedCell);
1455 cellconfig.linkedCell = NULL;
1457 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1458 if ( code ) continue;
1460 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1461 if ( IsDebuggerPresent() ) {
1462 OutputDebugString("Realm: ");
1463 OutputDebugString(realm);
1464 OutputDebugString("\n");
1467 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1468 if ( IsDebuggerPresent() ) {
1470 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1471 OutputDebugString(message);
1474 free(cells[cell_count]);
1477 } else if ( cell_count == 1 ) {
1486 pkrb5_cc_close(ctx, cc);
1487 if ( cellconfig.linkedCell )
1488 free(cellconfig.linkedCell);
1490 if ( code && reasonP ) {
1491 *reasonP = (char *)perror_message(code);
1497 KFW_AFS_destroy_tickets_for_cell(char * cell)
1499 krb5_context ctx = NULL;
1500 krb5_error_code code;
1502 char ** principals = NULL;
1504 if (!pkrb5_init_context)
1507 if ( IsDebuggerPresent() ) {
1508 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1509 OutputDebugString(cell);
1510 OutputDebugString("\n");
1513 code = pkrb5_init_context(&ctx);
1516 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1518 krb5_principal princ = 0;
1522 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1523 if ( cell_count > 1 ) {
1524 // TODO - What we really should do here is verify whether or not any of the
1525 // other cells which use this principal to obtain its credentials actually
1526 // have valid tokens or not. If they are currently using these credentials
1527 // we will skip them. For the time being we assume that if there is an active
1528 // map in the table that they are actively being used.
1532 code = pkrb5_parse_name(ctx, principals[count], &princ);
1533 if (code) goto loop_cleanup;
1535 code = KFW_get_ccache(ctx, princ, &cc);
1536 if (code) goto loop_cleanup;
1538 code = pkrb5_cc_destroy(ctx, cc);
1543 pkrb5_cc_close(ctx, cc);
1547 pkrb5_free_principal(ctx, princ);
1551 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1552 free(principals[count]);
1557 pkrb5_free_context(ctx);
1562 KFW_AFS_destroy_tickets_for_principal(char * user)
1564 krb5_context ctx = NULL;
1565 krb5_error_code code;
1567 char ** cells = NULL;
1568 krb5_principal princ = NULL;
1569 krb5_ccache cc = NULL;
1571 if (!pkrb5_init_context)
1574 if ( IsDebuggerPresent() ) {
1575 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1576 OutputDebugString(user);
1577 OutputDebugString("\n");
1580 code = pkrb5_init_context(&ctx);
1583 code = pkrb5_parse_name(ctx, user, &princ);
1584 if (code) goto loop_cleanup;
1586 code = KFW_get_ccache(ctx, princ, &cc);
1587 if (code) goto loop_cleanup;
1589 code = pkrb5_cc_destroy(ctx, cc);
1594 pkrb5_cc_close(ctx, cc);
1598 pkrb5_free_principal(ctx, princ);
1602 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1605 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1612 pkrb5_free_context(ctx);
1617 KFW_AFS_renew_expiring_tokens(void)
1619 krb5_error_code code = 0;
1620 krb5_context ctx = NULL;
1621 krb5_ccache cc = NULL;
1623 struct principal_ccache_data * pcc_next = princ_cc_data;
1626 const char * realm = NULL;
1627 char local_cell[CELL_MAXNAMELEN+1]="";
1628 struct afsconf_cell cellconfig;
1630 if (!pkrb5_init_context)
1633 if ( pcc_next == NULL ) // nothing to do
1636 if ( IsDebuggerPresent() ) {
1637 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1640 memset(&cellconfig, 0, sizeof(cellconfig));
1642 code = pkrb5_init_context(&ctx);
1643 if (code) goto cleanup;
1645 code = pkrb5_timeofday(ctx, &now);
1646 if (code) goto cleanup;
1648 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1649 if ( pcc_next->expired )
1652 if ( now >= (pcc_next->expiration_time) ) {
1653 if ( !pcc_next->from_lsa ) {
1654 pcc_next->expired = 1;
1659 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1660 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1663 code = KFW_renew(ctx,cc);
1665 if ( code && pcc_next->from_lsa)
1667 #endif /* USE_MS2MIT */
1670 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1671 if (code) goto loop_cleanup;
1673 // Attempt to obtain new tokens for other cells supported by the same
1675 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1676 if ( cell_count > 0 ) {
1677 while ( cell_count-- ) {
1678 if ( IsDebuggerPresent() ) {
1679 OutputDebugString("Cell: ");
1680 OutputDebugString(cells[cell_count]);
1681 OutputDebugString("\n");
1683 if (cellconfig.linkedCell) {
1684 free(cellconfig.linkedCell);
1685 cellconfig.linkedCell = NULL;
1687 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1688 if ( code ) continue;
1689 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1690 if ( IsDebuggerPresent() ) {
1691 OutputDebugString("Realm: ");
1692 OutputDebugString(realm);
1693 OutputDebugString("\n");
1695 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1696 if ( IsDebuggerPresent() ) {
1698 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1699 OutputDebugString(message);
1701 free(cells[cell_count]);
1709 pkrb5_cc_close(ctx,cc);
1716 pkrb5_cc_close(ctx,cc);
1718 pkrb5_free_context(ctx);
1719 if (cellconfig.linkedCell)
1720 free(cellconfig.linkedCell);
1727 KFW_AFS_renew_token_for_cell(char * cell)
1729 krb5_error_code code = 0;
1730 krb5_context ctx = NULL;
1732 char ** principals = NULL;
1734 if (!pkrb5_init_context)
1737 if ( IsDebuggerPresent() ) {
1738 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1739 OutputDebugString(cell);
1740 OutputDebugString("\n");
1743 code = pkrb5_init_context(&ctx);
1744 if (code) goto cleanup;
1746 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1748 // We know we must have a credential somewhere since we are
1749 // trying to renew a token
1751 KFW_import_ccache_data();
1752 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1755 krb5_principal princ = 0;
1756 krb5_principal service = 0;
1758 krb5_creds mcreds, creds;
1759 #endif /* COMMENT */
1761 const char * realm = NULL;
1762 struct afsconf_cell cellconfig;
1763 char local_cell[CELL_MAXNAMELEN+1];
1765 memset(&cellconfig, 0, sizeof(cellconfig));
1768 code = pkrb5_parse_name(ctx, principals[count], &princ);
1769 if (code) goto loop_cleanup;
1771 code = KFW_get_ccache(ctx, princ, &cc);
1772 if (code) goto loop_cleanup;
1774 if (cellconfig.linkedCell) {
1775 free(cellconfig.linkedCell);
1776 cellconfig.linkedCell = NULL;
1778 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1779 if ( code ) goto loop_cleanup;
1781 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1782 if ( IsDebuggerPresent() ) {
1783 OutputDebugString("Realm: ");
1784 OutputDebugString(realm);
1785 OutputDebugString("\n");
1789 /* krb5_cc_remove_cred() is not implemented
1792 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1793 realm, "afs", cell, NULL);
1795 memset(&mcreds, 0, sizeof(krb5_creds));
1796 mcreds.client = princ;
1797 mcreds.server = service;
1799 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1801 if ( IsDebuggerPresent() ) {
1802 char * cname, *sname;
1803 pkrb5_unparse_name(ctx, creds.client, &cname);
1804 pkrb5_unparse_name(ctx, creds.server, &sname);
1805 OutputDebugString("Removing credential for client \"");
1806 OutputDebugString(cname);
1807 OutputDebugString("\" and service \"");
1808 OutputDebugString(sname);
1809 OutputDebugString("\"\n");
1810 pkrb5_free_unparsed_name(ctx,cname);
1811 pkrb5_free_unparsed_name(ctx,sname);
1814 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1815 pkrb5_free_principal(ctx, creds.client);
1816 pkrb5_free_principal(ctx, creds.server);
1819 #endif /* COMMENT */
1821 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1822 if ( IsDebuggerPresent() ) {
1824 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1825 OutputDebugString(message);
1830 pkrb5_cc_close(ctx, cc);
1834 pkrb5_free_principal(ctx, princ);
1838 pkrb5_free_principal(ctx, service);
1841 if (cellconfig.linkedCell) {
1842 free(cellconfig.linkedCell);
1843 cellconfig.linkedCell = NULL;
1846 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1847 free(principals[count]);
1851 code = -1; // we did not renew the tokens
1855 pkrb5_free_context(ctx);
1856 return (code ? FALSE : TRUE);
1861 KFW_AFS_renew_tokens_for_all_cells(void)
1863 struct cell_principal_map * next = cell_princ_map;
1865 if ( IsDebuggerPresent() )
1866 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1871 for ( ; next ; next = next->next ) {
1873 KFW_AFS_renew_token_for_cell(next->cell);
1879 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1881 krb5_error_code code = 0;
1882 krb5_context ctx = NULL;
1883 krb5_ccache cc = NULL;
1884 krb5_principal me = NULL;
1885 krb5_principal server = NULL;
1886 krb5_creds my_creds;
1887 krb5_data *realm = NULL;
1889 if (!pkrb5_init_context)
1892 memset(&my_creds, 0, sizeof(krb5_creds));
1897 code = pkrb5_init_context(&ctx);
1898 if (code) goto cleanup;
1904 code = pkrb5_cc_default(ctx, &cc);
1905 if (code) goto cleanup;
1908 code = pkrb5_cc_get_principal(ctx, cc, &me);
1909 if (code) goto cleanup;
1911 realm = krb5_princ_realm(ctx, me);
1913 code = pkrb5_build_principal_ext(ctx, &server,
1914 realm->length,realm->data,
1915 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1916 realm->length,realm->data,
1921 if ( IsDebuggerPresent() ) {
1922 char * cname, *sname;
1923 pkrb5_unparse_name(ctx, me, &cname);
1924 pkrb5_unparse_name(ctx, server, &sname);
1925 OutputDebugString("Renewing credential for client \"");
1926 OutputDebugString(cname);
1927 OutputDebugString("\" and service \"");
1928 OutputDebugString(sname);
1929 OutputDebugString("\"\n");
1930 pkrb5_free_unparsed_name(ctx,cname);
1931 pkrb5_free_unparsed_name(ctx,sname);
1934 my_creds.client = me;
1935 my_creds.server = server;
1937 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1939 if ( IsDebuggerPresent() ) {
1941 sprintf(message,"krb5_get_renewed_creds() failed: %d\n",code);
1942 OutputDebugString(message);
1947 code = pkrb5_cc_initialize(ctx, cc, me);
1949 if ( IsDebuggerPresent() ) {
1951 sprintf(message,"krb5_cc_initialize() failed: %d\n",code);
1952 OutputDebugString(message);
1957 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1959 if ( IsDebuggerPresent() ) {
1961 sprintf(message,"krb5_cc_store_cred() failed: %d\n",code);
1962 OutputDebugString(message);
1968 if (my_creds.client == me)
1969 my_creds.client = 0;
1970 if (my_creds.server == server)
1971 my_creds.server = 0;
1972 pkrb5_free_cred_contents(ctx, &my_creds);
1974 pkrb5_free_principal(ctx, me);
1976 pkrb5_free_principal(ctx, server);
1977 if (cc && (cc != alt_cc))
1978 pkrb5_cc_close(ctx, cc);
1979 if (ctx && (ctx != alt_ctx))
1980 pkrb5_free_context(ctx);
1985 KFW_kinit( krb5_context alt_ctx,
1988 char *principal_name,
1990 krb5_deltat lifetime,
1993 krb5_deltat renew_life,
1998 krb5_error_code code = 0;
1999 krb5_context ctx = NULL;
2000 krb5_ccache cc = NULL;
2001 krb5_principal me = NULL;
2003 krb5_creds my_creds;
2004 krb5_get_init_creds_opt options;
2005 krb5_address ** addrs = NULL;
2006 int i = 0, addr_count = 0;
2008 if (!pkrb5_init_context)
2011 pkrb5_get_init_creds_opt_init(&options);
2012 memset(&my_creds, 0, sizeof(my_creds));
2020 code = pkrb5_init_context(&ctx);
2021 if (code) goto cleanup;
2027 code = pkrb5_cc_default(ctx, &cc);
2028 if (code) goto cleanup;
2031 code = pkrb5_parse_name(ctx, principal_name, &me);
2035 code = pkrb5_unparse_name(ctx, me, &name);
2043 lifetime = pLeash_get_default_lifetime();
2044 #endif /* USE_LEASH */
2051 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2052 pkrb5_get_init_creds_opt_set_forwardable(&options,
2053 forwardable ? 1 : 0);
2054 pkrb5_get_init_creds_opt_set_proxiable(&options,
2056 pkrb5_get_init_creds_opt_set_renew_life(&options,
2059 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2063 // we are going to add the public IP address specified by the user
2064 // to the list provided by the operating system
2065 krb5_address ** local_addrs=NULL;
2068 pkrb5_os_localaddr(ctx, &local_addrs);
2069 while ( local_addrs[i++] );
2072 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2074 pkrb5_free_addresses(ctx, local_addrs);
2077 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2079 while ( local_addrs[i] ) {
2080 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2081 if (addrs[i] == NULL) {
2082 pkrb5_free_addresses(ctx, local_addrs);
2086 addrs[i]->magic = local_addrs[i]->magic;
2087 addrs[i]->addrtype = local_addrs[i]->addrtype;
2088 addrs[i]->length = local_addrs[i]->length;
2089 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2090 if (!addrs[i]->contents) {
2091 pkrb5_free_addresses(ctx, local_addrs);
2095 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2096 local_addrs[i]->length); /* safe */
2099 pkrb5_free_addresses(ctx, local_addrs);
2101 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2102 if (addrs[i] == NULL)
2105 addrs[i]->magic = KV5M_ADDRESS;
2106 addrs[i]->addrtype = AF_INET;
2107 addrs[i]->length = 4;
2108 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2109 if (!addrs[i]->contents)
2112 netIPAddr = htonl(publicIP);
2113 memcpy(addrs[i]->contents,&netIPAddr,4);
2115 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2120 code = pkrb5_get_init_creds_password(ctx,
2123 password, // password
2124 KRB5_prompter, // prompter
2125 hParent, // prompter data
2132 code = pkrb5_cc_initialize(ctx, cc, me);
2136 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2142 for ( i=0;i<addr_count;i++ ) {
2144 if ( addrs[i]->contents )
2145 free(addrs[i]->contents);
2150 if (my_creds.client == me)
2151 my_creds.client = 0;
2152 pkrb5_free_cred_contents(ctx, &my_creds);
2154 pkrb5_free_unparsed_name(ctx, name);
2156 pkrb5_free_principal(ctx, me);
2157 if (cc && (cc != alt_cc))
2158 pkrb5_cc_close(ctx, cc);
2159 if (ctx && (ctx != alt_ctx))
2160 pkrb5_free_context(ctx);
2166 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2168 krb5_context ctx = NULL;
2169 krb5_ccache cc = NULL;
2170 krb5_error_code code;
2172 if (!pkrb5_init_context)
2181 code = pkrb5_init_context(&ctx);
2182 if (code) goto cleanup;
2188 code = pkrb5_cc_default(ctx, &cc);
2189 if (code) goto cleanup;
2192 code = pkrb5_cc_destroy(ctx, cc);
2193 if ( !code ) cc = 0;
2196 if (cc && (cc != alt_cc))
2197 pkrb5_cc_close(ctx, cc);
2198 if (ctx && (ctx != alt_ctx))
2199 pkrb5_free_context(ctx);
2207 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2209 NTSTATUS Status = 0;
2211 TOKEN_STATISTICS Stats;
2217 *ppSessionData = NULL;
2219 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2223 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2224 CloseHandle( TokenHandle );
2228 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2229 if ( FAILED(Status) || !ppSessionData )
2236 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2237 // cache. It validates whether or not it is reasonable to assume that if we
2238 // attempted to retrieve valid tickets we could do so. Microsoft does not
2239 // automatically renew expired tickets. Therefore, the cache could contain
2240 // expired or invalid tickets. Microsoft also caches the user's password
2241 // and will use it to retrieve new TGTs if the cache is empty and tickets
2245 MSLSA_IsKerberosLogon(VOID)
2247 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2248 BOOL Success = FALSE;
2250 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2251 if ( pSessionData->AuthenticationPackage.Buffer ) {
2257 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2258 usLength = (pSessionData->AuthenticationPackage).Length;
2261 lstrcpynW (buffer, usBuffer, usLength);
2262 lstrcatW (buffer,L"");
2263 if ( !lstrcmpW(L"Kerberos",buffer) )
2267 pLsaFreeReturnBuffer(pSessionData);
2271 #endif /* USE_MS2MIT */
2273 static BOOL CALLBACK
2274 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2278 switch ( message ) {
2280 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2282 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2285 for ( i=0; i < mid_cnt ; i++ ) {
2286 if (mid_tb[i].echo == 0)
2287 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2288 else if (mid_tb[i].echo == 2)
2289 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2294 switch ( LOWORD(wParam) ) {
2296 for ( i=0; i < mid_cnt ; i++ ) {
2297 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2298 *mid_tb[i].buf = '\0';
2302 EndDialog(hDialog, LOWORD(wParam));
2310 lpwAlign( LPWORD lpIn )
2314 ul = (ULONG_PTR) lpIn;
2318 return (LPWORD) ul;;
2322 * dialog widths are measured in 1/4 character widths
2323 * dialog height are measured in 1/8 character heights
2327 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2328 char * ptext[], int numlines, int width,
2329 int tb_cnt, struct textField * tb)
2333 LPDLGITEMTEMPLATE lpdit;
2339 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2346 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2348 // Define a dialog box.
2350 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2351 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2352 | DS_SETFOREGROUND | DS_3DLOOK
2353 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2354 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2357 lpdt->cx = 20 + width * 4;
2358 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2360 lpw = (LPWORD) (lpdt + 1);
2361 *lpw++ = 0; // no menu
2362 *lpw++ = 0; // predefined dialog box class (by default)
2364 lpwsz = (LPWSTR) lpw;
2365 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2367 *lpw++ = 8; // font size (points)
2368 lpwsz = (LPWSTR) lpw;
2369 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2373 //-----------------------
2374 // Define an OK button.
2375 //-----------------------
2376 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2377 lpdit = (LPDLGITEMTEMPLATE) lpw;
2378 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2379 lpdit->dwExtendedStyle = 0;
2380 lpdit->x = (lpdt->cx - 14)/4 - 20;
2381 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2384 lpdit->id = IDOK; // OK button identifier
2386 lpw = (LPWORD) (lpdit + 1);
2388 *lpw++ = 0x0080; // button class
2390 lpwsz = (LPWSTR) lpw;
2391 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2393 *lpw++ = 0; // no creation data
2395 //-----------------------
2396 // Define an Cancel button.
2397 //-----------------------
2398 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2399 lpdit = (LPDLGITEMTEMPLATE) lpw;
2400 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2401 lpdit->dwExtendedStyle = 0;
2402 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2403 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2406 lpdit->id = IDCANCEL; // CANCEL button identifier
2408 lpw = (LPWORD) (lpdit + 1);
2410 *lpw++ = 0x0080; // button class
2412 lpwsz = (LPWSTR) lpw;
2413 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2415 *lpw++ = 0; // no creation data
2417 /* Add controls for preface data */
2418 for ( i=0; i<numlines; i++) {
2419 /*-----------------------
2420 * Define a static text control.
2421 *-----------------------*/
2422 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2423 lpdit = (LPDLGITEMTEMPLATE) lpw;
2424 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2425 lpdit->dwExtendedStyle = 0;
2427 lpdit->y = 10 + i * 14;
2428 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2430 lpdit->id = ID_TEXT + i; // text identifier
2432 lpw = (LPWORD) (lpdit + 1);
2434 *lpw++ = 0x0082; // static class
2436 lpwsz = (LPWSTR) lpw;
2437 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2438 -1, lpwsz, 2*width);
2440 *lpw++ = 0; // no creation data
2443 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2444 int len = (int)strlen(tb[i].label);
2449 for ( i=0; i<tb_cnt; i++) {
2451 /*-----------------------
2452 * Define a static text control.
2453 *-----------------------*/
2454 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2455 lpdit = (LPDLGITEMTEMPLATE) lpw;
2456 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2457 lpdit->dwExtendedStyle = 0;
2459 lpdit->y = 10 + (numlines + i + 1) * 14;
2460 lpdit->cx = pwid * 4;
2462 lpdit->id = ID_TEXT + numlines + i; // text identifier
2464 lpw = (LPWORD) (lpdit + 1);
2466 *lpw++ = 0x0082; // static class
2468 lpwsz = (LPWSTR) lpw;
2469 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2472 *lpw++ = 0; // no creation data
2474 /*-----------------------
2475 * Define an edit control.
2476 *-----------------------*/
2477 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2478 lpdit = (LPDLGITEMTEMPLATE) lpw;
2479 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2480 lpdit->dwExtendedStyle = 0;
2481 lpdit->x = 10 + (pwid + 1) * 4;
2482 lpdit->y = 10 + (numlines + i + 1) * 14;
2483 lpdit->cx = (width - (pwid + 1)) * 4;
2485 lpdit->id = ID_MID_TEXT + i; // identifier
2487 lpw = (LPWORD) (lpdit + 1);
2489 *lpw++ = 0x0081; // edit class
2491 lpwsz = (LPWSTR) lpw;
2492 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2495 *lpw++ = 0; // no creation data
2499 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2500 hwndOwner, (DLGPROC) MultiInputDialogProc);
2504 case 0: /* Timeout */
2512 sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
2513 MessageBox(hwndOwner,
2516 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2523 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2525 HINSTANCE hInst = 0;
2529 char * plines[16], *p = preface ? preface : "";
2532 for ( i=0; i<16; i++ )
2535 while (*p && numlines < 16) {
2536 plines[numlines++] = p;
2537 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2538 if ( *p == '\r' && *(p+1) == '\n' ) {
2541 } else if ( *p == '\n' ) {
2544 if ( strlen(plines[numlines-1]) > maxwidth )
2545 maxwidth = (int)strlen(plines[numlines-1]);
2548 for ( i=0;i<n;i++ ) {
2549 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2550 if ( maxwidth < len )
2554 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2557 static krb5_error_code KRB5_CALLCONV
2558 KRB5_prompter( krb5_context context,
2563 krb5_prompt prompts[])
2565 krb5_error_code errcode = 0;
2567 struct textField * tb = NULL;
2568 int len = 0, blen=0, nlen=0;
2569 HWND hParent = (HWND)data;
2572 nlen = (int)strlen(name)+2;
2575 blen = (int)strlen(banner)+2;
2577 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2580 memset(tb,0,sizeof(struct textField) * num_prompts);
2581 for ( i=0; i < num_prompts; i++ ) {
2582 tb[i].buf = prompts[i].reply->data;
2583 tb[i].len = prompts[i].reply->length;
2584 tb[i].label = prompts[i].prompt;
2586 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2589 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2591 for ( i=0; i < num_prompts; i++ )
2592 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2600 for (i = 0; i < num_prompts; i++) {
2601 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2608 KFW_AFS_wait_for_service_start(void)
2613 CurrentState = SERVICE_START_PENDING;
2614 memset(HostName, '\0', sizeof(HostName));
2615 gethostname(HostName, sizeof(HostName));
2617 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2619 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2621 if ( IsDebuggerPresent() ) {
2622 switch ( CurrentState ) {
2623 case SERVICE_STOPPED:
2624 OutputDebugString("SERVICE_STOPPED\n");
2626 case SERVICE_START_PENDING:
2627 OutputDebugString("SERVICE_START_PENDING\n");
2629 case SERVICE_STOP_PENDING:
2630 OutputDebugString("SERVICE_STOP_PENDING\n");
2632 case SERVICE_RUNNING:
2633 OutputDebugString("SERVICE_RUNNING\n");
2635 case SERVICE_CONTINUE_PENDING:
2636 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2638 case SERVICE_PAUSE_PENDING:
2639 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2641 case SERVICE_PAUSED:
2642 OutputDebugString("SERVICE_PAUSED\n");
2645 OutputDebugString("UNKNOWN Service State\n");
2648 if (CurrentState == SERVICE_STOPPED)
2650 if (CurrentState == SERVICE_RUNNING)
2666 memset(HostName, '\0', sizeof(HostName));
2667 gethostname(HostName, sizeof(HostName));
2668 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2670 if (CurrentState != SERVICE_RUNNING)
2673 rc = ktc_ForgetAllTokens();
2679 #define ALLOW_REGISTER 1
2681 ViceIDToUsername(char *username,
2682 char *realm_of_user,
2683 char *realm_of_cell,
2685 struct ktc_principal *aclient,
2686 struct ktc_principal *aserver,
2687 struct ktc_token *atoken)
2689 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2690 static char confdir[512] = { 0 };
2691 #ifdef AFS_ID_TO_NAME
2692 char username_copy[BUFSIZ];
2693 #endif /* AFS_ID_TO_NAME */
2694 long viceId = ANONYMOUSID; /* AFS uid of user */
2696 #ifdef ALLOW_REGISTER
2698 #endif /* ALLOW_REGISTER */
2700 if (confdir[0] == '\0')
2701 cm_GetConfigDir(confdir, sizeof(confdir));
2703 strcpy(lastcell, aserver->cell);
2705 if (!pr_Initialize (0, confdir, aserver->cell)) {
2706 char sname[PR_MAXNAMELEN];
2707 strncpy(sname, username, PR_MAXNAMELEN);
2708 sname[PR_MAXNAMELEN-1] = '\0';
2709 status = pr_SNameToId (sname, &viceId);
2714 * This is a crock, but it is Transarc's crock, so
2715 * we have to play along in order to get the
2716 * functionality. The way the afs id is stored is
2717 * as a string in the username field of the token.
2718 * Contrary to what you may think by looking at
2719 * the code for tokens, this hack (AFS ID %d) will
2720 * not work if you change %d to something else.
2724 * This code is taken from cklog -- it lets people
2725 * automatically register with the ptserver in foreign cells
2728 #ifdef ALLOW_REGISTER
2730 if (viceId != ANONYMOUSID) {
2731 #else /* ALLOW_REGISTER */
2732 if ((status == 0) && (viceId != ANONYMOUSID))
2733 #endif /* ALLOW_REGISTER */
2735 #ifdef AFS_ID_TO_NAME
2736 strncpy(username_copy, username, BUFSIZ);
2737 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2738 #endif /* AFS_ID_TO_NAME */
2740 #ifdef ALLOW_REGISTER
2741 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2743 strncpy(aclient->name, username, MAXKTCNAMELEN - 1);
2744 strcpy(aclient->instance, "");
2745 strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
2746 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2748 if (status = pr_Initialize(1L, confdir, aserver->cell))
2750 status = pr_CreateUser(username, &id);
2754 #ifdef AFS_ID_TO_NAME
2755 strncpy(username_copy, username, BUFSIZ);
2756 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2757 #endif /* AFS_ID_TO_NAME */
2760 #endif /* ALLOW_REGISTER */
2766 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2767 krb5_error_code code;
2768 krb5_ticket *ticket;
2771 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2773 len = krb5_princ_realm(context, ticket->server)->length;
2774 if (len > destlen - 1)
2777 strncpy(dest, krb5_princ_realm(context, ticket->server)->data, len);
2780 pkrb5_free_ticket(context, ticket);
2786 krb5_context alt_ctx,
2791 int lifetime, /* unused parameter */
2799 #endif /* USE_KRB4 */
2800 struct ktc_principal aserver;
2801 struct ktc_principal aclient;
2802 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2803 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2804 char local_cell[CELL_MAXNAMELEN+1];
2805 char Dmycell[CELL_MAXNAMELEN+1];
2806 struct ktc_token atoken;
2807 struct ktc_token btoken;
2808 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2809 char RealmName[128];
2811 char ServiceName[128];
2815 krb5_context ctx = NULL;
2816 krb5_ccache cc = NULL;
2818 krb5_creds * k5creds = NULL;
2819 krb5_error_code code;
2820 krb5_principal client_principal = NULL;
2821 krb5_data * k5data = NULL;
2825 memset(HostName, '\0', sizeof(HostName));
2826 gethostname(HostName, sizeof(HostName));
2827 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2828 if ( IsDebuggerPresent() )
2829 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2832 if (CurrentState != SERVICE_RUNNING) {
2833 if ( IsDebuggerPresent() )
2834 OutputDebugString("AFSD Service NOT RUNNING\n");
2838 if (!pkrb5_init_context)
2841 memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
2842 memset(RealmName, '\0', sizeof(RealmName));
2843 memset(CellName, '\0', sizeof(CellName));
2844 memset(ServiceName, '\0', sizeof(ServiceName));
2845 memset(realm_of_user, '\0', sizeof(realm_of_user));
2846 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2847 if (cell && cell[0])
2848 strcpy(Dmycell, cell);
2850 memset(Dmycell, '\0', sizeof(Dmycell));
2852 // NULL or empty cell returns information on local cell
2853 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2855 // KFW_AFS_error(rc, "get_cellconfig()");
2862 code = pkrb5_init_context(&ctx);
2863 if (code) goto cleanup;
2869 code = pkrb5_cc_default(ctx, &cc);
2870 if (code) goto skip_krb5_init;
2873 memset((char *)&increds, 0, sizeof(increds));
2875 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2877 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2879 OutputDebugString("Principal Not Found for ccache\n");
2881 goto skip_krb5_init;
2884 if (!KFW_accept_dotted_usernames()) {
2885 /* look for client principals which cannot be distinguished
2886 * from Kerberos 4 multi-component principal names
2888 k5data = krb5_princ_component(ctx,client_principal,0);
2889 for ( i=0; i<k5data->length; i++ ) {
2890 if ( k5data->data[i] == '.' )
2893 if (i != k5data->length)
2895 OutputDebugString("Illegal Principal name contains dot in first component\n");
2896 rc = KRB5KRB_ERR_GENERIC;
2901 i = krb5_princ_realm(ctx, client_principal)->length;
2904 strncpy(realm_of_user,krb5_princ_realm(ctx, client_principal)->data,i);
2905 realm_of_user[i] = 0;
2910 if ( !try_krb5 || !realm_of_user[0] ) {
2911 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2920 strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig));
2922 if (strlen(service) == 0)
2923 strcpy(ServiceName, "afs");
2925 strcpy(ServiceName, service);
2927 if (strlen(cell) == 0)
2928 strcpy(CellName, local_cell);
2930 strcpy(CellName, cell);
2932 /* This is for Kerberos v4 only */
2933 if (strlen(realm) == 0)
2934 strcpy(RealmName, realm_of_cell);
2936 strcpy(RealmName, realm);
2938 memset(&creds, '\0', sizeof(creds));
2942 code = KRB5KRB_ERR_GENERIC;
2945 increds.client = client_principal;
2946 increds.times.endtime = 0;
2947 /* Ask for DES since that is what V4 understands */
2948 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
2950 /* If there was a specific realm we are supposed to try
2953 if (strlen(realm) != 0) {
2954 /* service/cell@REALM */
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("Getting tickets for \"");
2967 OutputDebugString(cname);
2968 OutputDebugString("\" and service \"");
2969 OutputDebugString(sname);
2970 OutputDebugString("\"\n");
2971 pkrb5_free_unparsed_name(ctx,cname);
2972 pkrb5_free_unparsed_name(ctx,sname);
2976 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2978 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2979 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
2980 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2981 code == KRB5KRB_AP_ERR_MSG_TYPE) {
2982 /* Or service@REALM */
2983 pkrb5_free_principal(ctx,increds.server);
2985 code = pkrb5_build_principal(ctx, &increds.server,
2991 if ( IsDebuggerPresent() ) {
2992 char * cname, *sname;
2993 pkrb5_unparse_name(ctx, increds.client, &cname);
2994 pkrb5_unparse_name(ctx, increds.server, &sname);
2995 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2996 OutputDebugString("Trying again: getting tickets for \"");
2997 OutputDebugString(cname);
2998 OutputDebugString("\" and service \"");
2999 OutputDebugString(sname);
3000 OutputDebugString("\"\n");
3001 pkrb5_free_unparsed_name(ctx,cname);
3002 pkrb5_free_unparsed_name(ctx,sname);
3006 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3010 /* we have a local realm for the cell */
3011 strcpy(realm_of_cell, realm);
3014 /* Otherwise, first try service/cell@CLIENT_REALM */
3015 if (code = pkrb5_build_principal(ctx, &increds.server,
3016 (int)strlen(realm_of_user),
3025 if ( IsDebuggerPresent() ) {
3026 char * cname, *sname;
3027 pkrb5_unparse_name(ctx, increds.client, &cname);
3028 pkrb5_unparse_name(ctx, increds.server, &sname);
3029 OutputDebugString("Getting tickets for \"");
3030 OutputDebugString(cname);
3031 OutputDebugString("\" and service \"");
3032 OutputDebugString(sname);
3033 OutputDebugString("\"\n");
3034 pkrb5_free_unparsed_name(ctx,cname);
3035 pkrb5_free_unparsed_name(ctx,sname);
3038 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3040 /* The client's realm is a local realm for the cell.
3041 * Save it so that later the pts registration will not
3044 strcpy(realm_of_cell, realm_of_user);
3047 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3048 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3049 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3050 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
3051 strcmp(realm_of_user, realm_of_cell)) {
3052 /* Then service/cell@CELL_REALM */
3053 pkrb5_free_principal(ctx,increds.server);
3055 code = pkrb5_build_principal(ctx, &increds.server,
3056 (int)strlen(realm_of_cell),
3061 if ( IsDebuggerPresent() ) {
3062 char * cname, *sname;
3063 pkrb5_unparse_name(ctx, increds.client, &cname);
3064 pkrb5_unparse_name(ctx, increds.server, &sname);
3065 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3066 OutputDebugString("Trying again: getting tickets for \"");
3067 OutputDebugString(cname);
3068 OutputDebugString("\" and service \"");
3069 OutputDebugString(sname);
3070 OutputDebugString("\"\n");
3071 pkrb5_free_unparsed_name(ctx,cname);
3072 pkrb5_free_unparsed_name(ctx,sname);
3076 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3078 if (!code && !strlen(realm_of_cell))
3079 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3082 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3083 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3084 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3085 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3086 /* Finally service@CELL_REALM */
3087 pkrb5_free_principal(ctx,increds.server);
3089 code = pkrb5_build_principal(ctx, &increds.server,
3090 (int)strlen(realm_of_cell),
3095 if ( IsDebuggerPresent() ) {
3096 char * cname, *sname;
3097 pkrb5_unparse_name(ctx, increds.client, &cname);
3098 pkrb5_unparse_name(ctx, increds.server, &sname);
3099 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3100 OutputDebugString("Trying again: getting tickets for \"");
3101 OutputDebugString(cname);
3102 OutputDebugString("\" and service \"");
3103 OutputDebugString(sname);
3104 OutputDebugString("\"\n");
3105 pkrb5_free_unparsed_name(ctx,cname);
3106 pkrb5_free_unparsed_name(ctx,sname);
3110 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3111 if (!code && !strlen(realm_of_cell))
3112 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3117 if ( IsDebuggerPresent() ) {
3119 sprintf(message,"krb5_get_credentials returns: %d\n",code);
3120 OutputDebugString(message);
3126 /* This code inserts the entire K5 ticket into the token
3127 * No need to perform a krb524 translation which is
3128 * commented out in the code below
3130 if (KFW_use_krb524() ||
3131 k5creds->ticket.length > MAXKTCTICKETLEN)
3134 memset(&aserver, '\0', sizeof(aserver));
3135 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
3136 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
3138 memset(&atoken, '\0', sizeof(atoken));
3139 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3140 atoken.startTime = k5creds->times.starttime;
3141 atoken.endTime = k5creds->times.endtime;
3142 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3143 atoken.ticketLen = k5creds->ticket.length;
3144 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3147 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3148 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3149 if ( rc == KTC_NOCM && retry < 20 ) {
3152 goto retry_gettoken5;
3157 if (atoken.kvno == btoken.kvno &&
3158 atoken.ticketLen == btoken.ticketLen &&
3159 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3160 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3162 /* Success - Nothing to do */
3166 // * Reset the "aclient" structure before we call ktc_SetToken.
3167 // * This structure was first set by the ktc_GetToken call when
3168 // * we were comparing whether identical tokens already existed.
3170 len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
3171 strncpy(aclient.name, k5creds->client->data[0].data, len);
3172 aclient.name[len] = '\0';
3174 if ( k5creds->client->length > 1 ) {
3176 strcat(aclient.name, ".");
3177 p = aclient.name + strlen(aclient.name);
3178 len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
3179 strncpy(p, k5creds->client->data[1].data, len);
3182 aclient.instance[0] = '\0';
3184 strcpy(aclient.cell, realm_of_cell);
3186 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3187 /* For Khimaira, always append the realm name */
3188 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3190 strcat(aclient.name, "@");
3191 p = aclient.name + strlen(aclient.name);
3192 len = min(k5creds->client->realm.length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
3193 strncpy(p, k5creds->client->realm.data, len);
3197 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3198 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3199 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3200 &aclient, &aserver, &atoken);
3203 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
3204 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
3206 aclient.smbname[0] = '\0';
3209 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3211 goto cleanup; /* We have successfully inserted the token */
3217 /* Otherwise, the ticket could have been too large so try to
3218 * convert using the krb524d running with the KDC
3220 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3221 pkrb5_free_creds(ctx, k5creds);
3223 if ( IsDebuggerPresent() ) {
3225 sprintf(message,"krb524_convert_creds_kdc returns: %d\n",code);
3226 OutputDebugString(message);
3231 #endif /* USE_KRB524 */
3235 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3236 if (code == NO_TKT_FIL) {
3237 // if the problem is that we have no krb4 tickets
3238 // do not attempt to continue
3241 if (code != KSUCCESS)
3242 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3244 if (code != KSUCCESS)
3246 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3248 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3253 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3255 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3270 memset(&aserver, '\0', sizeof(aserver));
3271 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
3272 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
3274 memset(&atoken, '\0', sizeof(atoken));
3275 atoken.kvno = creds.kvno;
3276 atoken.startTime = creds.issue_date;
3277 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3278 memcpy(&atoken.sessionKey, creds.session, 8);
3279 atoken.ticketLen = creds.ticket_st.length;
3280 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3283 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3284 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3285 if ( rc == KTC_NOCM && retry < 20 ) {
3288 goto retry_gettoken;
3290 KFW_AFS_error(rc, "ktc_GetToken()");
3295 if (atoken.kvno == btoken.kvno &&
3296 atoken.ticketLen == btoken.ticketLen &&
3297 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3298 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3303 // * Reset the "aclient" structure before we call ktc_SetToken.
3304 // * This structure was first set by the ktc_GetToken call when
3305 // * we were comparing whether identical tokens already existed.
3307 strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
3310 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3311 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3313 strcpy(aclient.instance, "");
3315 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3316 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3317 aclient.name[MAXKTCREALMLEN-1] = '\0';
3319 strcpy(aclient.cell, CellName);
3321 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3322 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3323 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3324 &aclient, &aserver, &atoken);
3327 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
3328 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
3330 aclient.smbname[0] = '\0';
3333 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3335 KFW_AFS_error(rc, "ktc_SetToken()");
3341 if (client_principal)
3342 pkrb5_free_principal(ctx,client_principal);
3343 /* increds.client == client_principal */
3345 pkrb5_free_principal(ctx,increds.server);
3346 if (cc && (cc != alt_cc))
3347 pkrb5_cc_close(ctx, cc);
3348 if (ctx && (ctx != alt_ctx))
3349 pkrb5_free_context(ctx);
3350 if (ak_cellconfig.linkedCell)
3351 free(ak_cellconfig.linkedCell);
3353 return(rc? rc : code);
3356 /**************************************/
3357 /* afs_realm_of_cell(): */
3358 /**************************************/
3360 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3362 static char krbrlm[REALM_SZ+1]="";
3363 char ** realmlist=NULL;
3369 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3370 if ( !r && realmlist && realmlist[0] ) {
3371 strcpy(krbrlm, realmlist[0]);
3372 pkrb5_free_host_realm(ctx, realmlist);
3378 char *t = cellconfig->name;
3383 if (islower(c)) c=toupper(c);
3391 /**************************************/
3392 /* KFW_AFS_get_cellconfig(): */
3393 /**************************************/
3395 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3398 char newcell[CELL_MAXNAMELEN+1];
3399 char linkedcell[CELL_MAXNAMELEN+1]="";
3401 local_cell[0] = (char)0;
3402 memset(cellconfig, 0, sizeof(*cellconfig));
3404 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3405 if (rc = cm_GetRootCellName(local_cell))
3410 if (strlen(cell) == 0)
3411 strcpy(cell, local_cell);
3413 rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3414 if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
3415 rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3416 #ifdef AFS_AFSDB_ENV
3419 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3424 strcpy(cellconfig->name, newcell);
3426 cellconfig->linkedCell = strdup(linkedcell);
3431 /**************************************/
3432 /* get_cellconfig_callback(): */
3433 /**************************************/
3435 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
3437 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3439 cc->hostAddr[cc->numServers] = *addrp;
3440 strcpy(cc->hostName[cc->numServers], namep);
3446 /**************************************/
3447 /* KFW_AFS_error(): */
3448 /**************************************/
3450 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3453 const char *errText;
3455 // Using AFS defines as error messages for now, until Transarc
3456 // gets back to me with "string" translations of each of these
3458 if (rc == KTC_ERROR)
3459 errText = "KTC_ERROR";
3460 else if (rc == KTC_TOOBIG)
3461 errText = "KTC_TOOBIG";
3462 else if (rc == KTC_INVAL)
3463 errText = "KTC_INVAL";
3464 else if (rc == KTC_NOENT)
3465 errText = "KTC_NOENT";
3466 else if (rc == KTC_PIOCTLFAIL)
3467 errText = "KTC_PIOCTLFAIL";
3468 else if (rc == KTC_NOPIOCTL)
3469 errText = "KTC_NOPIOCTL";
3470 else if (rc == KTC_NOCELL)
3471 errText = "KTC_NOCELL";
3472 else if (rc == KTC_NOCM)
3473 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3475 errText = "Unknown error!";
3477 sprintf(message, "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3479 if ( IsDebuggerPresent() ) {
3480 OutputDebugString(message);
3481 OutputDebugString("\n");
3483 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3489 LPSTR lpszMachineName,
3490 LPSTR lpszServiceName,
3491 DWORD *lpdwCurrentState)
3494 SC_HANDLE schSCManager = NULL;
3495 SC_HANDLE schService = NULL;
3496 DWORD fdwDesiredAccess = 0;
3497 SERVICE_STATUS ssServiceStatus = {0};
3500 *lpdwCurrentState = 0;
3502 fdwDesiredAccess = GENERIC_READ;
3504 schSCManager = OpenSCManager(lpszMachineName,
3508 if(schSCManager == NULL)
3510 hr = GetLastError();
3514 schService = OpenService(schSCManager,
3518 if(schService == NULL)
3520 hr = GetLastError();
3524 fRet = QueryServiceStatus(schService,
3529 hr = GetLastError();
3533 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3537 CloseServiceHandle(schService);
3538 CloseServiceHandle(schSCManager);
3551 for (n = 0; fi[n].func_ptr_var; n++)
3552 *(fi[n].func_ptr_var) = 0;
3553 if (h) FreeLibrary(h);
3558 const char* dll_name,
3560 HINSTANCE* ph, // [out, optional] - DLL handle
3561 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3562 int cleanup, // cleanup function pointers and unload on error
3563 int go_on, // continue loading even if some functions cannot be loaded
3564 int silent // do not pop-up a system dialog if DLL cannot be loaded
3573 if (pindex) *pindex = -1;
3575 for (n = 0; fi[n].func_ptr_var; n++)
3576 *(fi[n].func_ptr_var) = 0;
3579 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3580 h = LoadLibrary(dll_name);
3588 for (i = 0; (go_on || !error) && (i < n); i++)
3590 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3596 *(fi[i].func_ptr_var) = p;
3599 if (pindex) *pindex = last_i;
3600 if (error && cleanup && !go_on) {
3601 for (i = 0; i < n; i++) {
3602 *(fi[i].func_ptr_var) = 0;
3608 if (error) return 0;
3612 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3614 krb5_context ctx = NULL;
3615 krb5_ccache cc = NULL;
3616 krb5_error_code code;
3618 const char * realm = NULL;
3619 krb5_principal principal = NULL;
3620 char * pname = NULL;
3621 char password[PROBE_PASSWORD_LEN+1];
3622 BOOL serverReachable = 0;
3624 if (!pkrb5_init_context)
3627 code = pkrb5_init_context(&ctx);
3628 if (code) goto cleanup;
3631 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3633 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3634 realm, PROBE_USERNAME, NULL, NULL);
3635 if ( code ) goto cleanup;
3637 code = KFW_get_ccache(ctx, principal, &cc);
3638 if ( code ) goto cleanup;
3640 code = pkrb5_unparse_name(ctx, principal, &pname);
3641 if ( code ) goto cleanup;
3643 pwdata.data = password;
3644 pwdata.length = PROBE_PASSWORD_LEN;
3645 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3648 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3651 password[PROBE_PASSWORD_LEN] = '\0';
3653 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3663 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3664 case KRB5KDC_ERR_CLIENT_REVOKED:
3665 case KRB5KDC_ERR_CLIENT_NOTYET:
3666 case KRB5KDC_ERR_PREAUTH_FAILED:
3667 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3668 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3669 serverReachable = TRUE;
3672 serverReachable = FALSE;
3677 pkrb5_free_unparsed_name(ctx,pname);
3679 pkrb5_free_principal(ctx,principal);
3681 pkrb5_cc_close(ctx,cc);
3683 pkrb5_free_context(ctx);
3685 return serverReachable;
3689 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
3691 krb5_context ctx = NULL;
3692 krb5_error_code code;
3693 krb5_ccache mslsa_ccache=NULL;
3694 krb5_principal princ = NULL;
3695 char * pname = NULL;
3698 if (!KFW_is_available())
3701 if (code = pkrb5_init_context(&ctx))
3704 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3707 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3710 if (code = pkrb5_unparse_name(ctx, princ, &pname))
3713 if ( strlen(pname) < *dwSize ) {
3714 strncpy(szUser, pname, *dwSize);
3715 szUser[*dwSize-1] = '\0';
3718 *dwSize = (DWORD)strlen(pname);
3722 pkrb5_free_unparsed_name(ctx, pname);
3725 pkrb5_free_principal(ctx, princ);
3728 pkrb5_cc_close(ctx, mslsa_ccache);
3731 pkrb5_free_context(ctx);
3736 KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
3738 // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
3739 PSID pSystemSID = NULL;
3740 DWORD SystemSIDlength = 0, UserSIDlength = 0;
3741 PACL ccacheACL = NULL;
3742 DWORD ccacheACLlength = 0;
3743 PTOKEN_USER pTokenUser = NULL;
3752 /* Get System SID */
3753 if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
3759 SystemSIDlength = GetLengthSid(pSystemSID);
3760 ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
3761 + SystemSIDlength - sizeof(DWORD);
3764 if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
3766 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
3767 pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
3769 GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
3774 UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
3776 ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
3781 ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
3786 InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
3787 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3788 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3791 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3792 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3793 pTokenUser->User.Sid);
3794 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3795 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3800 gle = GetLastError();
3801 if (gle != ERROR_NO_TOKEN)
3804 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3805 OWNER_SECURITY_INFORMATION,
3806 pTokenUser->User.Sid,
3810 gle = GetLastError();
3811 if (gle != ERROR_NO_TOKEN)
3815 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3816 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3821 gle = GetLastError();
3822 if (gle != ERROR_NO_TOKEN)
3829 LocalFree(pSystemSID);
3831 LocalFree(pTokenUser);
3833 LocalFree(ccacheACL);
3838 KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
3841 DWORD dwSize = size-1; /* leave room for nul */
3844 if (!hUserToken || !newfilename || size <= 0)
3847 *newfilename = '\0';
3849 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
3850 if ( !dwLen || dwLen > dwSize )
3851 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
3852 if ( !dwLen || dwLen > dwSize )
3855 newfilename[dwSize] = '\0';
3860 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
3862 char filename[MAX_PATH] = "";
3864 char cachename[MAX_PATH + 8] = "FILE:";
3865 krb5_context ctx = NULL;
3866 krb5_error_code code;
3867 krb5_principal princ = NULL;
3868 krb5_ccache cc = NULL;
3869 krb5_ccache ncc = NULL;
3871 if (!pkrb5_init_context || !user || !szLogonId)
3874 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
3875 if ( count > sizeof(filename) || count == 0 ) {
3876 GetWindowsDirectory(filename, sizeof(filename));
3879 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
3882 strcat(filename, "\\");
3883 strcat(filename, szLogonId);
3885 strcat(cachename, filename);
3887 DeleteFile(filename);
3889 code = pkrb5_init_context(&ctx);
3890 if (code) goto cleanup;
3892 code = pkrb5_parse_name(ctx, user, &princ);
3893 if (code) goto cleanup;
3895 code = KFW_get_ccache(ctx, princ, &cc);
3896 if (code) goto cleanup;
3898 code = pkrb5_cc_resolve(ctx, cachename, &ncc);
3899 if (code) goto cleanup;
3901 code = pkrb5_cc_initialize(ctx, ncc, princ);
3902 if (code) goto cleanup;
3904 code = KFW_AFS_set_file_cache_dacl(filename, NULL);
3905 if (code) goto cleanup;
3907 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3911 pkrb5_cc_close(ctx, cc);
3915 pkrb5_cc_close(ctx, ncc);
3919 pkrb5_free_principal(ctx, princ);
3924 pkrb5_free_context(ctx);
3928 KFW_AFS_copy_file_cache_to_default_cache(char * filename)
3930 char cachename[MAX_PATH + 8] = "FILE:";
3931 krb5_context ctx = NULL;
3932 krb5_error_code code;
3933 krb5_principal princ = NULL;
3934 krb5_ccache cc = NULL;
3935 krb5_ccache ncc = NULL;
3938 if (!pkrb5_init_context || !filename)
3941 if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
3944 code = pkrb5_init_context(&ctx);
3947 strcat(cachename, filename);
3949 code = pkrb5_cc_resolve(ctx, cachename, &cc);
3950 if (code) goto cleanup;
3952 code = pkrb5_cc_get_principal(ctx, cc, &princ);
3954 code = pkrb5_cc_default(ctx, &ncc);
3956 code = pkrb5_cc_initialize(ctx, ncc, princ);
3959 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3962 pkrb5_cc_close(ctx, ncc);
3966 retval=0; /* success */
3970 pkrb5_cc_close(ctx, cc);
3974 DeleteFile(filename);
3977 pkrb5_free_principal(ctx, princ);
3982 pkrb5_free_context(ctx);
3987 /* We are including this
3989 /* Ticket lifetime. This defines the table used to lookup lifetime for the
3990 fixed part of rande of the one byte lifetime field. Values less than 0x80
3991 are intrpreted as the number of 5 minute intervals. Values from 0x80 to
3992 0xBF should be looked up in this table. The value of 0x80 is the same using
3993 both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days.
3994 The intervening values of have a fixed ratio of roughly 1.06914. The value
3995 oxFF is defined to mean a ticket has no expiration time. This should be
3996 used advisedly since individual servers may impose defacto upperbounds on
3997 ticket lifetimes. */
3999 #define TKTLIFENUMFIXED 64
4000 #define TKTLIFEMINFIXED 0x80
4001 #define TKTLIFEMAXFIXED 0xBF
4002 #define TKTLIFENOEXPIRE 0xFF
4003 #define MAXTKTLIFETIME (30*24*3600) /* 30 days */
4005 static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
4006 38400, /* 10.67 hours, 0.44 days */
4007 41055, /* 11.40 hours, 0.48 days */
4008 43894, /* 12.19 hours, 0.51 days */
4009 46929, /* 13.04 hours, 0.54 days */
4010 50174, /* 13.94 hours, 0.58 days */
4011 53643, /* 14.90 hours, 0.62 days */
4012 57352, /* 15.93 hours, 0.66 days */
4013 61318, /* 17.03 hours, 0.71 days */
4014 65558, /* 18.21 hours, 0.76 days */
4015 70091, /* 19.47 hours, 0.81 days */
4016 74937, /* 20.82 hours, 0.87 days */
4017 80119, /* 22.26 hours, 0.93 days */
4018 85658, /* 23.79 hours, 0.99 days */
4019 91581, /* 25.44 hours, 1.06 days */
4020 97914, /* 27.20 hours, 1.13 days */
4021 104684, /* 29.08 hours, 1.21 days */
4022 111922, /* 31.09 hours, 1.30 days */
4023 119661, /* 33.24 hours, 1.38 days */
4024 127935, /* 35.54 hours, 1.48 days */
4025 136781, /* 37.99 hours, 1.58 days */
4026 146239, /* 40.62 hours, 1.69 days */
4027 156350, /* 43.43 hours, 1.81 days */
4028 167161, /* 46.43 hours, 1.93 days */
4029 178720, /* 49.64 hours, 2.07 days */
4030 191077, /* 53.08 hours, 2.21 days */
4031 204289, /* 56.75 hours, 2.36 days */
4032 218415, /* 60.67 hours, 2.53 days */
4033 233517, /* 64.87 hours, 2.70 days */
4034 249664, /* 69.35 hours, 2.89 days */
4035 266926, /* 74.15 hours, 3.09 days */
4036 285383, /* 79.27 hours, 3.30 days */
4037 305116, /* 84.75 hours, 3.53 days */
4038 326213, /* 90.61 hours, 3.78 days */
4039 348769, /* 96.88 hours, 4.04 days */
4040 372885, /* 103.58 hours, 4.32 days */
4041 398668, /* 110.74 hours, 4.61 days */
4042 426234, /* 118.40 hours, 4.93 days */
4043 455705, /* 126.58 hours, 5.27 days */
4044 487215, /* 135.34 hours, 5.64 days */
4045 520904, /* 144.70 hours, 6.03 days */
4046 556921, /* 154.70 hours, 6.45 days */
4047 595430, /* 165.40 hours, 6.89 days */
4048 636601, /* 176.83 hours, 7.37 days */
4049 680618, /* 189.06 hours, 7.88 days */
4050 727680, /* 202.13 hours, 8.42 days */
4051 777995, /* 216.11 hours, 9.00 days */
4052 831789, /* 231.05 hours, 9.63 days */
4053 889303, /* 247.03 hours, 10.29 days */
4054 950794, /* 264.11 hours, 11.00 days */
4055 1016537, /* 282.37 hours, 11.77 days */
4056 1086825, /* 301.90 hours, 12.58 days */
4057 1161973, /* 322.77 hours, 13.45 days */
4058 1242318, /* 345.09 hours, 14.38 days */
4059 1328218, /* 368.95 hours, 15.37 days */
4060 1420057, /* 394.46 hours, 16.44 days */
4061 1518247, /* 421.74 hours, 17.57 days */
4062 1623226, /* 450.90 hours, 18.79 days */
4063 1735464, /* 482.07 hours, 20.09 days */
4064 1855462, /* 515.41 hours, 21.48 days */
4065 1983758, /* 551.04 hours, 22.96 days */
4066 2120925, /* 589.15 hours, 24.55 days */
4067 2267576, /* 629.88 hours, 26.25 days */
4068 2424367, /* 673.44 hours, 28.06 days */
4070 }; /* 720.00 hours, 30.00 days */
4072 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
4073 * returns the corresponding end time. There are four simple cases to be
4074 * handled. The first is a life of 0xff, meaning no expiration, and results in
4075 * an end time of 0xffffffff. The second is when life is less than the values
4076 * covered by the table. In this case, the end time is the start time plus the
4077 * number of 5 minute intervals specified by life. The third case returns
4078 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
4079 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
4080 * table to extract the lifetime in seconds, which is added to start to produce
4084 life_to_time(afs_uint32 start, unsigned char life)
4088 if (life == TKTLIFENOEXPIRE)
4090 if (life < TKTLIFEMINFIXED)
4091 return start + life * 5 * 60;
4092 if (life > TKTLIFEMAXFIXED)
4093 return start + MAXTKTLIFETIME;
4094 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
4095 return start + realLife;
4098 /* time_to_life - takes start and end times for the ticket and returns a
4099 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
4100 * lifetimes above 127*5minutes. First, the special case of (end ==
4101 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
4102 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
4103 * less than the first table entry are handled by rounding the requested
4104 * lifetime *up* to the next 5 minute interval. The final step is to search
4105 * the table for the smallest entry *greater than or equal* to the requested
4106 * entry. The actual code is prepared to handle the case where the table is
4107 * unordered but that it an unnecessary frill. */
4109 static unsigned char
4110 time_to_life(afs_uint32 start, afs_uint32 end)
4112 int lifetime = end - start;
4116 if (end == NEVERDATE)
4117 return TKTLIFENOEXPIRE;
4118 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
4120 if (lifetime < tkt_lifetimes[0])
4121 return (lifetime + 5 * 60 - 1) / (5 * 60);
4123 best = MAXKTCTICKETLIFETIME;
4124 for (i = 0; i < TKTLIFENUMFIXED; i++)
4125 if (tkt_lifetimes[i] >= lifetime) {
4126 int diff = tkt_lifetimes[i] - lifetime;
4134 return best_i + TKTLIFEMINFIXED;