2 * Copyright (c) 2004, 2005, 2006, 2007, 2008 Secure Endpoints Inc.
3 * Copyright (c) 2003 SkyRope, LLC
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * - Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * - Neither the name of Skyrope, LLC nor the names of its contributors may be
15 * used to endorse or promote products derived from this software without
16 * specific prior written permission from Skyrope, LLC.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Portions of this code are derived from portions of the MIT
31 * Leash Ticket Manager and LoadFuncs utilities. For these portions the
32 * following copyright applies.
34 * Copyright (c) 2003,2004 by the Massachusetts Institute of Technology.
35 * All rights reserved.
37 * Export of this software from the United States of America may
38 * require a specific license from the United States Government.
39 * It is the responsibility of any person or organization contemplating
40 * export to obtain such a license before exporting.
42 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
43 * distribute this software and its documentation for any purpose and
44 * without fee is hereby granted, provided that the above copyright
45 * notice appear in all copies and that both that copyright notice and
46 * this permission notice appear in supporting documentation, and that
47 * the name of M.I.T. not be used in advertising or publicity pertaining
48 * to distribution of the software without specific, written prior
49 * permission. Furthermore if you modify this software you must label
50 * your software as modified software and not distribute it in such a
51 * fashion that it might be confused with the original M.I.T. software.
52 * M.I.T. makes no representations about the suitability of
53 * this software for any purpose. It is provided "as is" without express
54 * or implied warranty.
66 /* Prevent inclusion of des.h to avoid conflicts with des types */
67 #define NO_DES_H_INCLUDE
69 #include <afsconfig.h>
70 #include <afs/param.h>
74 #include <afs/ptserver.h>
75 #include <afs/ptuser.h>
77 #include <WINNT\afsreg.h>
81 #include "afskfw-int.h"
89 * TIMING _____________________________________________________________________
93 #define cminREMIND_TEST 1 // test every minute for expired creds
94 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
95 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
96 #define cminMINLIFE 30 // minimum life of Kerberos creds
98 #define c100ns1SECOND (LONGLONG)10000000
99 #define cmsec1SECOND 1000
100 #define cmsec1MINUTE 60000
101 #define csec1MINUTE 60
103 /* Function Pointer Declarations for Delayed Loading */
105 DECL_FUNC_PTR(cc_initialize);
106 DECL_FUNC_PTR(cc_shutdown);
107 DECL_FUNC_PTR(cc_get_NC_info);
108 DECL_FUNC_PTR(cc_free_NC_info);
112 DECL_FUNC_PTR(Leash_get_default_lifetime);
113 DECL_FUNC_PTR(Leash_get_default_forwardable);
114 DECL_FUNC_PTR(Leash_get_default_renew_till);
115 DECL_FUNC_PTR(Leash_get_default_noaddresses);
116 DECL_FUNC_PTR(Leash_get_default_proxiable);
117 DECL_FUNC_PTR(Leash_get_default_publicip);
118 DECL_FUNC_PTR(Leash_get_default_use_krb4);
119 DECL_FUNC_PTR(Leash_get_default_life_min);
120 DECL_FUNC_PTR(Leash_get_default_life_max);
121 DECL_FUNC_PTR(Leash_get_default_renew_min);
122 DECL_FUNC_PTR(Leash_get_default_renew_max);
123 DECL_FUNC_PTR(Leash_get_default_renewable);
124 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
128 DECL_FUNC_PTR(krb5_change_password);
129 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
130 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
131 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
132 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
133 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
134 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
135 DECL_FUNC_PTR(krb5_get_init_creds_password);
136 DECL_FUNC_PTR(krb5_build_principal_ext);
137 DECL_FUNC_PTR(krb5_cc_get_name);
138 DECL_FUNC_PTR(krb5_cc_resolve);
139 DECL_FUNC_PTR(krb5_cc_default);
140 DECL_FUNC_PTR(krb5_cc_default_name);
141 DECL_FUNC_PTR(krb5_cc_set_default_name);
142 DECL_FUNC_PTR(krb5_cc_initialize);
143 DECL_FUNC_PTR(krb5_cc_destroy);
144 DECL_FUNC_PTR(krb5_cc_close);
145 DECL_FUNC_PTR(krb5_cc_store_cred);
146 DECL_FUNC_PTR(krb5_cc_copy_creds);
147 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
148 DECL_FUNC_PTR(krb5_cc_get_principal);
149 DECL_FUNC_PTR(krb5_cc_start_seq_get);
150 DECL_FUNC_PTR(krb5_cc_next_cred);
151 DECL_FUNC_PTR(krb5_cc_end_seq_get);
152 DECL_FUNC_PTR(krb5_cc_remove_cred);
153 DECL_FUNC_PTR(krb5_cc_set_flags);
154 DECL_FUNC_PTR(krb5_cc_get_type);
155 DECL_FUNC_PTR(krb5_free_context);
156 DECL_FUNC_PTR(krb5_free_cred_contents);
157 DECL_FUNC_PTR(krb5_free_principal);
158 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
159 DECL_FUNC_PTR(krb5_init_context);
160 DECL_FUNC_PTR(krb5_parse_name);
161 DECL_FUNC_PTR(krb5_timeofday);
162 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
163 DECL_FUNC_PTR(krb5_unparse_name);
164 DECL_FUNC_PTR(krb5_get_credentials);
165 DECL_FUNC_PTR(krb5_mk_req);
166 DECL_FUNC_PTR(krb5_sname_to_principal);
167 DECL_FUNC_PTR(krb5_get_credentials_renew);
168 DECL_FUNC_PTR(krb5_free_data);
169 DECL_FUNC_PTR(krb5_free_data_contents);
170 DECL_FUNC_PTR(krb5_free_unparsed_name);
171 DECL_FUNC_PTR(krb5_os_localaddr);
172 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
173 DECL_FUNC_PTR(krb5_copy_data);
174 DECL_FUNC_PTR(krb5_free_creds);
175 DECL_FUNC_PTR(krb5_build_principal);
176 DECL_FUNC_PTR(krb5_get_renewed_creds);
177 DECL_FUNC_PTR(krb5_get_default_config_files);
178 DECL_FUNC_PTR(krb5_free_config_files);
179 DECL_FUNC_PTR(krb5_get_default_realm);
180 DECL_FUNC_PTR(krb5_free_default_realm);
181 DECL_FUNC_PTR(krb5_free_ticket);
182 DECL_FUNC_PTR(krb5_decode_ticket);
183 DECL_FUNC_PTR(krb5_get_host_realm);
184 DECL_FUNC_PTR(krb5_free_host_realm);
185 DECL_FUNC_PTR(krb5_free_addresses);
186 DECL_FUNC_PTR(krb5_c_random_make_octets);
188 // Krb5 KFW 3.2 functions
189 DECL_FUNC_PTR(krb5_get_error_message);
190 DECL_FUNC_PTR(krb5_free_error_message);
194 DECL_FUNC_PTR(krb524_init_ets);
195 DECL_FUNC_PTR(krb524_convert_creds_kdc);
200 DECL_FUNC_PTR(krb_get_cred);
201 DECL_FUNC_PTR(tkt_string);
202 DECL_FUNC_PTR(krb_get_tf_realm);
203 DECL_FUNC_PTR(krb_mk_req);
207 DECL_FUNC_PTR(com_err);
208 DECL_FUNC_PTR(error_message);
211 DECL_FUNC_PTR(profile_init);
212 DECL_FUNC_PTR(profile_release);
213 DECL_FUNC_PTR(profile_get_subsection_names);
214 DECL_FUNC_PTR(profile_free_list);
215 DECL_FUNC_PTR(profile_get_string);
216 DECL_FUNC_PTR(profile_release_string);
219 DECL_FUNC_PTR(OpenSCManagerA);
220 DECL_FUNC_PTR(OpenServiceA);
221 DECL_FUNC_PTR(QueryServiceStatus);
222 DECL_FUNC_PTR(CloseServiceHandle);
224 DECL_FUNC_PTR(LsaNtStatusToWinError);
225 #endif /* USE_MS2MIT */
229 DECL_FUNC_PTR(LsaConnectUntrusted);
230 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
231 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
232 DECL_FUNC_PTR(LsaFreeReturnBuffer);
233 DECL_FUNC_PTR(LsaGetLogonSessionData);
234 #endif /* USE_MS2MIT */
237 FUNC_INFO ccapi_fi[] = {
238 MAKE_FUNC_INFO(cc_initialize),
239 MAKE_FUNC_INFO(cc_shutdown),
240 MAKE_FUNC_INFO(cc_get_NC_info),
241 MAKE_FUNC_INFO(cc_free_NC_info),
246 FUNC_INFO leash_fi[] = {
247 MAKE_FUNC_INFO(Leash_get_default_lifetime),
248 MAKE_FUNC_INFO(Leash_get_default_renew_till),
249 MAKE_FUNC_INFO(Leash_get_default_forwardable),
250 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
251 MAKE_FUNC_INFO(Leash_get_default_proxiable),
252 MAKE_FUNC_INFO(Leash_get_default_publicip),
253 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
254 MAKE_FUNC_INFO(Leash_get_default_life_min),
255 MAKE_FUNC_INFO(Leash_get_default_life_max),
256 MAKE_FUNC_INFO(Leash_get_default_renew_min),
257 MAKE_FUNC_INFO(Leash_get_default_renew_max),
258 MAKE_FUNC_INFO(Leash_get_default_renewable),
262 FUNC_INFO leash_opt_fi[] = {
263 MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
268 FUNC_INFO k5_fi[] = {
269 MAKE_FUNC_INFO(krb5_change_password),
270 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
271 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
272 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
273 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
274 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
275 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
276 MAKE_FUNC_INFO(krb5_get_init_creds_password),
277 MAKE_FUNC_INFO(krb5_build_principal_ext),
278 MAKE_FUNC_INFO(krb5_cc_get_name),
279 MAKE_FUNC_INFO(krb5_cc_resolve),
280 MAKE_FUNC_INFO(krb5_cc_default),
281 MAKE_FUNC_INFO(krb5_cc_default_name),
282 MAKE_FUNC_INFO(krb5_cc_set_default_name),
283 MAKE_FUNC_INFO(krb5_cc_initialize),
284 MAKE_FUNC_INFO(krb5_cc_destroy),
285 MAKE_FUNC_INFO(krb5_cc_close),
286 MAKE_FUNC_INFO(krb5_cc_copy_creds),
287 MAKE_FUNC_INFO(krb5_cc_store_cred),
288 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
289 MAKE_FUNC_INFO(krb5_cc_get_principal),
290 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
291 MAKE_FUNC_INFO(krb5_cc_next_cred),
292 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
293 MAKE_FUNC_INFO(krb5_cc_remove_cred),
294 MAKE_FUNC_INFO(krb5_cc_set_flags),
295 MAKE_FUNC_INFO(krb5_cc_get_type),
296 MAKE_FUNC_INFO(krb5_free_context),
297 MAKE_FUNC_INFO(krb5_free_cred_contents),
298 MAKE_FUNC_INFO(krb5_free_principal),
299 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
300 MAKE_FUNC_INFO(krb5_init_context),
301 MAKE_FUNC_INFO(krb5_parse_name),
302 MAKE_FUNC_INFO(krb5_timeofday),
303 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
304 MAKE_FUNC_INFO(krb5_unparse_name),
305 MAKE_FUNC_INFO(krb5_get_credentials),
306 MAKE_FUNC_INFO(krb5_mk_req),
307 MAKE_FUNC_INFO(krb5_sname_to_principal),
308 MAKE_FUNC_INFO(krb5_get_credentials_renew),
309 MAKE_FUNC_INFO(krb5_free_data),
310 MAKE_FUNC_INFO(krb5_free_data_contents),
311 MAKE_FUNC_INFO(krb5_free_unparsed_name),
312 MAKE_FUNC_INFO(krb5_os_localaddr),
313 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
314 MAKE_FUNC_INFO(krb5_copy_data),
315 MAKE_FUNC_INFO(krb5_free_creds),
316 MAKE_FUNC_INFO(krb5_build_principal),
317 MAKE_FUNC_INFO(krb5_get_renewed_creds),
318 MAKE_FUNC_INFO(krb5_free_addresses),
319 MAKE_FUNC_INFO(krb5_get_default_config_files),
320 MAKE_FUNC_INFO(krb5_free_config_files),
321 MAKE_FUNC_INFO(krb5_get_default_realm),
322 MAKE_FUNC_INFO(krb5_free_default_realm),
323 MAKE_FUNC_INFO(krb5_free_ticket),
324 MAKE_FUNC_INFO(krb5_decode_ticket),
325 MAKE_FUNC_INFO(krb5_get_host_realm),
326 MAKE_FUNC_INFO(krb5_free_host_realm),
327 MAKE_FUNC_INFO(krb5_free_addresses),
328 MAKE_FUNC_INFO(krb5_c_random_make_octets),
332 FUNC_INFO k5_kfw_32_fi[] = {
333 MAKE_FUNC_INFO(krb5_get_error_message),
334 MAKE_FUNC_INFO(krb5_free_error_message),
339 FUNC_INFO k4_fi[] = {
340 MAKE_FUNC_INFO(krb_get_cred),
341 MAKE_FUNC_INFO(krb_get_tf_realm),
342 MAKE_FUNC_INFO(krb_mk_req),
343 MAKE_FUNC_INFO(tkt_string),
349 FUNC_INFO k524_fi[] = {
350 MAKE_FUNC_INFO(krb524_init_ets),
351 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
356 FUNC_INFO profile_fi[] = {
357 MAKE_FUNC_INFO(profile_init),
358 MAKE_FUNC_INFO(profile_release),
359 MAKE_FUNC_INFO(profile_get_subsection_names),
360 MAKE_FUNC_INFO(profile_free_list),
361 MAKE_FUNC_INFO(profile_get_string),
362 MAKE_FUNC_INFO(profile_release_string),
366 FUNC_INFO ce_fi[] = {
367 MAKE_FUNC_INFO(com_err),
368 MAKE_FUNC_INFO(error_message),
372 FUNC_INFO service_fi[] = {
373 MAKE_FUNC_INFO(OpenSCManagerA),
374 MAKE_FUNC_INFO(OpenServiceA),
375 MAKE_FUNC_INFO(QueryServiceStatus),
376 MAKE_FUNC_INFO(CloseServiceHandle),
378 MAKE_FUNC_INFO(LsaNtStatusToWinError),
379 #endif /* USE_MS2MIT */
384 FUNC_INFO lsa_fi[] = {
385 MAKE_FUNC_INFO(LsaConnectUntrusted),
386 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
387 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
388 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
389 MAKE_FUNC_INFO(LsaGetLogonSessionData),
392 #endif /* USE_MS2MIT */
394 /* Static Prototypes */
395 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
396 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *, unsigned short);
397 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
398 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
399 void *data, const char *name, const char *banner, int num_prompts,
400 krb5_prompt prompts[]);
403 /* Static Declarations */
404 static int inited = 0;
405 static int mid_cnt = 0;
406 static struct textField * mid_tb = NULL;
407 static HINSTANCE hKrb5 = 0;
408 static HINSTANCE hKrb5_kfw_32 = 0;
410 static HINSTANCE hKrb4 = 0;
411 #endif /* USE_KRB4 */
413 static HINSTANCE hKrb524 = 0;
416 static HINSTANCE hSecur32 = 0;
417 #endif /* USE_MS2MIT */
418 static HINSTANCE hAdvApi32 = 0;
419 static HINSTANCE hComErr = 0;
420 static HINSTANCE hService = 0;
421 static HINSTANCE hProfile = 0;
423 static HINSTANCE hLeash = 0;
424 static HINSTANCE hLeashOpt = 0;
426 static HINSTANCE hCCAPI = 0;
427 static struct principal_ccache_data * princ_cc_data = NULL;
428 static struct cell_principal_map * cell_princ_map = NULL;
433 static int inited = 0;
436 char mutexName[MAX_PATH];
437 HANDLE hMutex = NULL;
439 StringCbPrintf( mutexName, sizeof(mutexName), "AFS KFW Init pid=%d", getpid());
441 hMutex = CreateMutex( NULL, TRUE, mutexName );
442 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
443 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
449 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
450 LoadFuncs(KRB5_DLL, k5_kfw_32_fi, &hKrb5_kfw_32, 0, 1, 0, 0);
451 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
452 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
454 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
455 #endif /* USE_KRB4 */
456 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
458 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
459 #endif /* USE_MS2MIT */
461 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
464 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
465 LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
467 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
469 if ( KFW_is_available() ) {
470 char rootcell[CELL_MAXNAMELEN+1];
472 KFW_import_windows_lsa();
473 #endif /* USE_MS2MIT */
474 KFW_import_ccache_data();
475 KFW_AFS_renew_expiring_tokens();
477 /* WIN32 NOTE: no way to get max chars */
478 if (!cm_GetRootCellName(rootcell))
479 KFW_AFS_renew_token_for_cell(rootcell);
482 ReleaseMutex(hMutex);
492 FreeLibrary(hLeashOpt);
498 FreeLibrary(hKrb524);
504 FreeLibrary(hSecur32);
505 #endif /* USE_MS2MIT */
507 FreeLibrary(hService);
509 FreeLibrary(hComErr);
511 FreeLibrary(hProfile);
515 #endif /* USE_KRB4 */
519 FreeLibrary(hKrb5_kfw_32);
522 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
525 static int init = TRUE;
526 static int bIsWow64 = FALSE;
530 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
532 hModule = GetModuleHandle(TEXT("kernel32"));
534 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
536 if (NULL != fnIsWow64Process)
538 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
540 // on error, assume FALSE.
541 // in other words, do nothing.
544 FreeLibrary(hModule);
552 KFW_accept_dotted_usernames(void)
558 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
559 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
560 if (code == ERROR_SUCCESS) {
562 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
563 (BYTE *) &value, &len);
564 RegCloseKey(parmKey);
566 if (code != ERROR_SUCCESS) {
567 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
568 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
569 if (code == ERROR_SUCCESS) {
571 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
572 (BYTE *) &value, &len);
573 RegCloseKey (parmKey);
587 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
588 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
589 if (code == ERROR_SUCCESS) {
590 len = sizeof(use524);
591 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
592 (BYTE *) &use524, &len);
593 RegCloseKey(parmKey);
595 if (code != ERROR_SUCCESS) {
596 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
597 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
598 if (code == ERROR_SUCCESS) {
599 len = sizeof(use524);
600 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
601 (BYTE *) &use524, &len);
602 RegCloseKey (parmKey);
609 KFW_is_available(void)
615 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
616 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
617 if (code == ERROR_SUCCESS) {
618 len = sizeof(enableKFW);
619 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
620 (BYTE *) &enableKFW, &len);
621 RegCloseKey (parmKey);
624 if (code != ERROR_SUCCESS) {
625 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
626 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
627 if (code == ERROR_SUCCESS) {
628 len = sizeof(enableKFW);
629 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
630 (BYTE *) &enableKFW, &len);
631 RegCloseKey (parmKey);
639 if ( hKrb5 && hComErr && hService &&
642 #endif /* USE_MS2MIT */
655 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
656 int FreeContextFlag, krb5_context * ctx,
661 int krb5Error = ((int)(rc & 255));
673 if (pkrb5_get_error_message)
674 errText = pkrb5_get_error_message(ctx, rc);
676 errText = perror_message(rc);
677 StringCbPrintf(message, sizeof(message),
678 "%s\n(Kerberos error %ld)\n\n%s failed",
682 if (pkrb5_free_error_message)
683 pkrb5_free_error_message(ctx, (char *)errText);
685 if ( IsDebuggerPresent() )
686 OutputDebugString(message);
688 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
691 if (FreeContextFlag == 1)
693 if (ctx && *ctx != NULL)
695 if (cache && *cache != NULL) {
696 pkrb5_cc_close(*ctx, *cache);
700 pkrb5_free_context(*ctx);
709 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
711 struct principal_ccache_data * next = princ_cc_data;
712 krb5_principal principal = 0;
714 const char * ccname = NULL;
715 const char * cctype = NULL;
716 char * ccfullname = NULL;
717 krb5_error_code code = 0;
718 krb5_error_code cc_code = 0;
724 if (ctx == 0 || cc == 0)
727 code = pkrb5_cc_get_principal(ctx, cc, &principal);
730 code = pkrb5_unparse_name(ctx, principal, &pname);
731 if ( code ) goto cleanup;
733 ccname = pkrb5_cc_get_name(ctx, cc);
734 if (!ccname) goto cleanup;
736 cctype = pkrb5_cc_get_type(ctx, cc);
737 if (!cctype) goto cleanup;
739 ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
740 if (!ccfullname) goto cleanup;
742 StringCbPrintf(ccfullname, sizeof(ccfullname), "%s:%s", cctype, ccname);
744 // Search the existing list to see if we have a match
746 for ( ; next ; next = next->next ) {
747 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
752 // If not, match add a new node to the beginning of the list and assign init it
754 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
755 next->next = princ_cc_data;
756 princ_cc_data = next;
757 next->principal = _strdup(pname);
758 next->ccache_name = ccfullname;
760 next->from_lsa = lsa;
762 next->expiration_time = 0;
766 flags = 0; // turn off OPENCLOSE mode
767 code = pkrb5_cc_set_flags(ctx, cc, flags);
768 if ( code ) goto cleanup;
770 code = pkrb5_timeofday(ctx, &now);
772 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
774 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
775 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
777 // we found the ticket we are looking for
778 // check validity of timestamp
779 // We add a 5 minutes fudge factor to compensate for potential
780 // clock skew errors between the KDC and client OS
782 valid = ((creds.times.starttime > 0) &&
783 now >= (creds.times.starttime - 300) &&
784 now < (creds.times.endtime + 300) &&
785 !(creds.ticket_flags & TKT_FLG_INVALID));
787 if ( next->from_lsa) {
789 next->expiration_time = creds.times.endtime;
791 } else if ( valid ) {
793 next->expiration_time = creds.times.endtime;
794 next->renew = (creds.times.renew_till > creds.times.endtime) &&
795 (creds.ticket_flags & TKT_FLG_RENEWABLE);
798 next->expiration_time = 0;
802 pkrb5_free_cred_contents(ctx, &creds);
803 cc_code = KRB5_CC_END;
806 pkrb5_free_cred_contents(ctx, &creds);
809 if (cc_code == KRB5_CC_END) {
810 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
811 if (code) goto cleanup;
815 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
816 code = pkrb5_cc_set_flags(ctx, cc, flags);
821 pkrb5_free_unparsed_name(ctx,pname);
823 pkrb5_free_principal(ctx,principal);
827 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
829 struct principal_ccache_data * next = princ_cc_data;
830 char * response = NULL;
832 if ( !principal || !ccache )
836 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
838 // we always want to prefer the MS Kerberos LSA cache or
839 // the cache afscreds created specifically for the principal
840 // if the current entry is either one, drop the previous find
841 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
844 response = _strdup(next->ccache_name);
845 // MS Kerberos LSA is our best option so use it and quit
846 if ( next->from_lsa )
860 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
862 struct principal_ccache_data ** next = &princ_cc_data;
864 if ( !pname && !ccname )
868 if ( !strcmp((*next)->principal,pname) ||
869 !strcmp((*next)->ccache_name,ccname) ) {
871 free((*next)->principal);
872 free((*next)->ccache_name);
874 (*next) = (*next)->next;
881 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
883 struct cell_principal_map * next = cell_princ_map;
885 // Search the existing list to see if we have a match
887 for ( ; next ; next = next->next ) {
888 if ( !strcmp(next->cell, cell) ) {
889 if ( !strcmp(next->principal,pname) ) {
890 next->active = active;
893 // OpenAFS currently has a restriction of one active token per cell
894 // Therefore, whenever we update the table with a new active cell we
895 // must mark all of the other principal to cell entries as inactive.
903 // If not, match add a new node to the beginning of the list and assign init it
905 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
906 next->next = cell_princ_map;
907 cell_princ_map = next;
908 next->principal = _strdup(pname);
909 next->cell = _strdup(cell);
910 next->active = active;
915 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
917 struct cell_principal_map ** next = &cell_princ_map;
919 if ( !pname && !cell )
923 if ( !strcmp((*next)->principal,pname) ||
924 !strcmp((*next)->cell,cell) ) {
926 free((*next)->principal);
929 (*next) = (*next)->next;
935 // Returns (if possible) a principal which has been known in
936 // the past to have been used to obtain tokens for the specified
938 // TODO: Attempt to return one which has not yet expired by checking
939 // the principal/ccache data
941 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
943 struct cell_principal_map * next_map = cell_princ_map;
944 const char * princ = NULL;
951 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
954 next_map = next_map->next;
957 if ( !principals || !count )
960 *principals = (char **) malloc(sizeof(char *) * count);
961 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
963 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
964 (*principals)[i++] = _strdup(next_map->principal);
971 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
974 struct cell_principal_map * next_map = cell_princ_map;
975 const char * princ = NULL;
981 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
984 next_map = next_map->next;
990 *cells = (char **) malloc(sizeof(char *) * count);
991 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
993 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
994 (*cells)[i++] = _strdup(next_map->cell);
1000 /* Given a principal return an existing ccache or create one and return */
1002 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
1004 krb5_context ctx = NULL;
1005 char * pname = NULL;
1006 char * ccname = NULL;
1007 krb5_error_code code;
1009 if (!pkrb5_init_context)
1015 code = pkrb5_init_context(&ctx);
1016 if (code) goto cleanup;
1020 code = pkrb5_unparse_name(ctx, principal, &pname);
1021 if (code) goto cleanup;
1023 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
1024 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
1025 size_t len = strlen(pname) + 5;
1026 ccname = (char *)malloc(len);
1027 StringCbPrintf(ccname, len, "API:%s", pname);
1029 code = pkrb5_cc_resolve(ctx, ccname, cc);
1031 code = pkrb5_cc_default(ctx, cc);
1032 if (code) goto cleanup;
1039 pkrb5_free_unparsed_name(ctx,pname);
1040 if (ctx && (ctx != alt_ctx))
1041 pkrb5_free_context(ctx);
1046 // Import Microsoft Credentials into a new MIT ccache
1048 KFW_import_windows_lsa(void)
1050 krb5_context ctx = NULL;
1051 krb5_ccache cc = NULL;
1052 krb5_principal princ = NULL;
1053 char * pname = NULL;
1054 krb5_data * princ_realm;
1055 krb5_error_code code;
1056 char cell[128]="", realm[128]="", *def_realm = 0;
1058 DWORD dwMsLsaImport;
1060 if (!pkrb5_init_context)
1063 code = pkrb5_init_context(&ctx);
1064 if (code) goto cleanup;
1066 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
1067 if (code) goto cleanup;
1069 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
1071 code = pkrb5_cc_get_principal(ctx, cc, &princ);
1072 if ( code ) goto cleanup;
1074 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
1075 switch ( dwMsLsaImport ) {
1076 case 0: /* do not import */
1078 case 1: /* always import */
1080 case 2: { /* matching realm */
1081 char ms_realm[128] = "", *r;
1084 for ( r=ms_realm, j=0; j<krb5_princ_realm(ctx, princ)->length; r++, j++ ) {
1085 *r = krb5_princ_realm(ctx, princ)->data[j];
1089 if (code = pkrb5_get_default_realm(ctx, &def_realm))
1092 if (strcmp(def_realm, ms_realm))
1100 code = pkrb5_unparse_name(ctx,princ,&pname);
1101 if ( code ) goto cleanup;
1103 princ_realm = krb5_princ_realm(ctx, princ);
1104 for ( i=0; i<princ_realm->length; i++ ) {
1105 realm[i] = princ_realm->data[i];
1106 cell[i] = tolower(princ_realm->data[i]);
1111 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
1112 if ( IsDebuggerPresent() ) {
1114 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1115 OutputDebugString(message);
1117 if ( code ) goto cleanup;
1119 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1123 pkrb5_free_unparsed_name(ctx,pname);
1125 pkrb5_free_principal(ctx,princ);
1127 pkrb5_free_default_realm(ctx, def_realm);
1129 pkrb5_cc_close(ctx,cc);
1131 pkrb5_free_context(ctx);
1133 #endif /* USE_MS2MIT */
1135 // If there are existing MIT credentials, copy them to a new
1136 // ccache named after the principal
1138 // Enumerate all existing MIT ccaches and construct entries
1139 // in the principal_ccache table
1141 // Enumerate all existing AFS Tokens and construct entries
1142 // in the cell_principal table
1144 KFW_import_ccache_data(void)
1146 krb5_context ctx = NULL;
1147 krb5_ccache cc = NULL;
1148 krb5_principal principal = NULL;
1150 krb5_error_code code;
1151 krb5_error_code cc_code;
1153 apiCB * cc_ctx = NULL;
1154 struct _infoNC ** pNCi = NULL;
1157 if ( !pcc_initialize )
1160 if ( IsDebuggerPresent() )
1161 OutputDebugString("KFW_import_ccache_data()\n");
1163 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1164 if (code) goto cleanup;
1166 code = pcc_get_NC_info(cc_ctx, &pNCi);
1167 if (code) goto cleanup;
1169 code = pkrb5_init_context(&ctx);
1170 if (code) goto cleanup;
1172 for ( i=0; pNCi[i]; i++ ) {
1173 if ( pNCi[i]->vers != CC_CRED_V5 )
1175 if ( IsDebuggerPresent() ) {
1176 OutputDebugString("Principal: ");
1177 OutputDebugString(pNCi[i]->principal);
1178 OutputDebugString(" in ccache ");
1179 OutputDebugString(pNCi[i]->name);
1180 OutputDebugString("\n");
1182 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1183 && strcmp(pNCi[i]->name,LSA_CCNAME)
1186 for ( j=0; pNCi[j]; j++ ) {
1187 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1193 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1194 if (code) goto loop_cleanup;
1197 krb5_ccache oldcc = 0;
1199 if ( IsDebuggerPresent() )
1200 OutputDebugString("copying ccache data to new ccache\n");
1202 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1203 if (code) goto loop_cleanup;
1204 code = pkrb5_cc_initialize(ctx, cc, principal);
1205 if (code) goto loop_cleanup;
1207 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1208 if (code) goto loop_cleanup;
1209 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1211 code = pkrb5_cc_close(ctx,cc);
1213 code = pkrb5_cc_close(ctx,oldcc);
1215 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1218 code = pkrb5_cc_close(ctx,oldcc);
1221 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1222 if (code) goto loop_cleanup;
1225 flags = 0; // turn off OPENCLOSE mode
1226 code = pkrb5_cc_set_flags(ctx, cc, flags);
1227 if ( code ) goto cleanup;
1229 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1231 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1233 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1234 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1235 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1236 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1237 if ( sname && cell && !strcmp("afs",sname->data) ) {
1238 struct ktc_principal aserver;
1239 struct ktc_principal aclient;
1240 struct ktc_token atoken;
1243 if ( IsDebuggerPresent() ) {
1244 OutputDebugString("Found AFS ticket: ");
1245 OutputDebugString(sname->data);
1247 OutputDebugString("/");
1248 OutputDebugString(cell->data);
1250 OutputDebugString("@");
1251 OutputDebugString(realm->data);
1252 OutputDebugString("\n");
1255 memset(&aserver, '\0', sizeof(aserver));
1256 StringCbCopyN( aserver.name, sizeof(aserver.name),
1257 sname->data, sizeof(aserver.name) - 1);
1258 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
1259 cell->data, sizeof(aserver.cell) - 1);
1261 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1263 // Found a token in AFS Client Server which matches
1264 char pname[128], *p, *q;
1265 for ( p=pname, q=aclient.name; *q; p++, q++)
1267 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1271 if ( IsDebuggerPresent() ) {
1272 OutputDebugString("Found AFS token: ");
1273 OutputDebugString(pname);
1274 OutputDebugString("\n");
1277 if ( strcmp(pname,pNCi[i]->principal) )
1279 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1281 // Attempt to import it
1282 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1284 if ( IsDebuggerPresent() ) {
1285 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1288 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data,
1292 pLeash_get_default_lifetime(),
1293 #endif /* USE_LEASH */
1295 if ( IsDebuggerPresent() ) {
1297 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1298 OutputDebugString(message);
1301 } else if ( IsDebuggerPresent() ) {
1302 OutputDebugString("Found ticket: ");
1303 OutputDebugString(sname->data);
1304 if ( cell && cell->data ) {
1305 OutputDebugString("/");
1306 OutputDebugString(cell->data);
1308 OutputDebugString("@");
1309 OutputDebugString(realm->data);
1310 OutputDebugString("\n");
1312 pkrb5_free_cred_contents(ctx, &creds);
1315 if (cc_code == KRB5_CC_END) {
1316 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1317 if (cc_code) goto loop_cleanup;
1321 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1322 code = pkrb5_cc_set_flags(ctx, cc, flags);
1324 pkrb5_cc_close(ctx,cc);
1328 pkrb5_free_principal(ctx,principal);
1335 pkrb5_free_context(ctx);
1337 pcc_free_NC_info(cc_ctx, &pNCi);
1339 pcc_shutdown(&cc_ctx);
1344 KFW_AFS_get_cred( char * username,
1351 static char reason[1024]="";
1352 krb5_context ctx = NULL;
1353 krb5_ccache cc = NULL;
1354 char * realm = NULL, * userrealm = NULL;
1355 krb5_principal principal = NULL;
1356 char * pname = NULL;
1357 krb5_error_code code;
1358 char local_cell[CELL_MAXNAMELEN+1];
1359 char **cells = NULL;
1361 struct afsconf_cell cellconfig;
1364 if (!pkrb5_init_context)
1367 if ( IsDebuggerPresent() ) {
1368 OutputDebugString("KFW_AFS_get_cred for token ");
1369 OutputDebugString(username);
1370 OutputDebugString(" in cell ");
1371 OutputDebugString(cell);
1372 OutputDebugString("\n");
1375 memset(&cellconfig, 0, sizeof(cellconfig));
1377 code = pkrb5_init_context(&ctx);
1378 if ( code ) goto cleanup;
1380 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1381 if ( code ) goto cleanup;
1383 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1385 userrealm = strchr(username,'@');
1387 pname = strdup(username);
1388 if (!KFW_accept_dotted_usernames()) {
1389 userrealm = strchr(pname, '@');
1392 /* handle kerberos iv notation */
1393 while ( dot = strchr(pname,'.') ) {
1399 size_t len = strlen(username) + strlen(realm) + 2;
1400 pname = malloc(len);
1401 if (pname == NULL) {
1402 code = KRB5KRB_ERR_GENERIC;
1405 StringCbCopy(pname, len, username);
1407 if (!KFW_accept_dotted_usernames()) {
1408 /* handle kerberos iv notation */
1409 while ( dot = strchr(pname,'.') ) {
1413 StringCbCat( pname, len, "@");
1414 StringCbCat( pname, len, realm);
1416 if ( IsDebuggerPresent() ) {
1417 OutputDebugString("Realm: ");
1418 OutputDebugString(realm);
1419 OutputDebugString("\n");
1422 code = pkrb5_parse_name(ctx, pname, &principal);
1423 if ( code ) goto cleanup;
1425 code = KFW_get_ccache(ctx, principal, &cc);
1426 if ( code ) goto cleanup;
1428 if ( lifetime == 0 )
1432 lifetime = pLeash_get_default_lifetime();
1435 if ( password && password[0] ) {
1436 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1441 1, /* forwardable */
1442 0, /* not proxiable */
1444 1, /* noaddresses */
1445 0 /* no public ip */
1447 pLeash_get_default_forwardable(),
1448 pLeash_get_default_proxiable(),
1449 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1450 pLeash_get_default_noaddresses(),
1451 pLeash_get_default_publicip()
1452 #endif /* USE_LEASH */
1455 if ( IsDebuggerPresent() ) {
1457 StringCbPrintf(message, sizeof(message), "KFW_kinit() returns: %d\n", code);
1458 OutputDebugString(message);
1460 if ( code ) goto cleanup;
1462 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1465 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1466 if ( IsDebuggerPresent() ) {
1468 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1469 OutputDebugString(message);
1471 if ( code ) goto cleanup;
1473 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1475 // Attempt to obtain new tokens for other cells supported by the same
1477 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1478 if ( cell_count > 1 ) {
1479 while ( cell_count-- ) {
1480 if ( strcmp(cells[cell_count],cell) ) {
1481 if ( IsDebuggerPresent() ) {
1483 StringCbPrintf(message, sizeof(message),
1484 "found another cell for the same principal: %s\n", cell);
1485 OutputDebugString(message);
1488 if (cellconfig.linkedCell) {
1489 free(cellconfig.linkedCell);
1490 cellconfig.linkedCell = NULL;
1492 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1493 if ( code ) continue;
1495 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1496 if ( IsDebuggerPresent() ) {
1497 OutputDebugString("Realm: ");
1498 OutputDebugString(realm);
1499 OutputDebugString("\n");
1502 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1503 if ( IsDebuggerPresent() ) {
1505 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1506 OutputDebugString(message);
1509 free(cells[cell_count]);
1512 } else if ( cell_count == 1 ) {
1521 pkrb5_cc_close(ctx, cc);
1522 if ( cellconfig.linkedCell )
1523 free(cellconfig.linkedCell);
1525 if ( code && reasonP ) {
1526 if (pkrb5_get_error_message) {
1527 char *msg = pkrb5_get_error_message(ctx, code);
1528 StringCbCopyN( reason, sizeof(reason),
1529 msg, sizeof(reason) - 1);
1531 pkrb5_free_error_message(ctx, msg);
1533 *reasonP = perror_message(code);
1540 KFW_AFS_destroy_tickets_for_cell(char * cell)
1542 krb5_context ctx = NULL;
1543 krb5_error_code code;
1545 char ** principals = NULL;
1547 if (!pkrb5_init_context)
1550 if ( IsDebuggerPresent() ) {
1551 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1552 OutputDebugString(cell);
1553 OutputDebugString("\n");
1556 code = pkrb5_init_context(&ctx);
1559 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1561 krb5_principal princ = 0;
1565 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1566 if ( cell_count > 1 ) {
1567 // TODO - What we really should do here is verify whether or not any of the
1568 // other cells which use this principal to obtain its credentials actually
1569 // have valid tokens or not. If they are currently using these credentials
1570 // we will skip them. For the time being we assume that if there is an active
1571 // map in the table that they are actively being used.
1575 code = pkrb5_parse_name(ctx, principals[count], &princ);
1576 if (code) goto loop_cleanup;
1578 code = KFW_get_ccache(ctx, princ, &cc);
1579 if (code) goto loop_cleanup;
1581 code = pkrb5_cc_destroy(ctx, cc);
1586 pkrb5_cc_close(ctx, cc);
1590 pkrb5_free_principal(ctx, princ);
1594 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1595 free(principals[count]);
1600 pkrb5_free_context(ctx);
1605 KFW_AFS_destroy_tickets_for_principal(char * user)
1607 krb5_context ctx = NULL;
1608 krb5_error_code code;
1610 char ** cells = NULL;
1611 krb5_principal princ = NULL;
1612 krb5_ccache cc = NULL;
1614 if (!pkrb5_init_context)
1617 if ( IsDebuggerPresent() ) {
1618 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1619 OutputDebugString(user);
1620 OutputDebugString("\n");
1623 code = pkrb5_init_context(&ctx);
1626 code = pkrb5_parse_name(ctx, user, &princ);
1627 if (code) goto loop_cleanup;
1629 code = KFW_get_ccache(ctx, princ, &cc);
1630 if (code) goto loop_cleanup;
1632 code = pkrb5_cc_destroy(ctx, cc);
1637 pkrb5_cc_close(ctx, cc);
1641 pkrb5_free_principal(ctx, princ);
1645 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1648 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1655 pkrb5_free_context(ctx);
1660 KFW_AFS_renew_expiring_tokens(void)
1662 krb5_error_code code = 0;
1663 krb5_context ctx = NULL;
1664 krb5_ccache cc = NULL;
1666 struct principal_ccache_data * pcc_next = princ_cc_data;
1669 const char * realm = NULL;
1670 char local_cell[CELL_MAXNAMELEN+1]="";
1671 struct afsconf_cell cellconfig;
1673 if (!pkrb5_init_context)
1676 if ( pcc_next == NULL ) // nothing to do
1679 if ( IsDebuggerPresent() ) {
1680 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1683 memset(&cellconfig, 0, sizeof(cellconfig));
1685 code = pkrb5_init_context(&ctx);
1686 if (code) goto cleanup;
1688 code = pkrb5_timeofday(ctx, &now);
1689 if (code) goto cleanup;
1691 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1692 if ( pcc_next->expired )
1695 if ( now >= (pcc_next->expiration_time) ) {
1696 if ( !pcc_next->from_lsa ) {
1697 pcc_next->expired = 1;
1702 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1703 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1706 code = KFW_renew(ctx,cc);
1708 if ( code && pcc_next->from_lsa)
1710 #endif /* USE_MS2MIT */
1713 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1714 if (code) goto loop_cleanup;
1716 // Attempt to obtain new tokens for other cells supported by the same
1718 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1719 if ( cell_count > 0 ) {
1720 while ( cell_count-- ) {
1721 if ( IsDebuggerPresent() ) {
1722 OutputDebugString("Cell: ");
1723 OutputDebugString(cells[cell_count]);
1724 OutputDebugString("\n");
1726 if (cellconfig.linkedCell) {
1727 free(cellconfig.linkedCell);
1728 cellconfig.linkedCell = NULL;
1730 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1731 if ( code ) continue;
1732 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1733 if ( IsDebuggerPresent() ) {
1734 OutputDebugString("Realm: ");
1735 OutputDebugString(realm);
1736 OutputDebugString("\n");
1738 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1739 if ( IsDebuggerPresent() ) {
1741 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1742 OutputDebugString(message);
1744 free(cells[cell_count]);
1752 pkrb5_cc_close(ctx,cc);
1759 pkrb5_cc_close(ctx,cc);
1761 pkrb5_free_context(ctx);
1762 if (cellconfig.linkedCell)
1763 free(cellconfig.linkedCell);
1770 KFW_AFS_renew_token_for_cell(char * cell)
1772 krb5_error_code code = 0;
1773 krb5_context ctx = NULL;
1775 char ** principals = NULL;
1777 if (!pkrb5_init_context)
1780 if ( IsDebuggerPresent() ) {
1781 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1782 OutputDebugString(cell);
1783 OutputDebugString("\n");
1786 code = pkrb5_init_context(&ctx);
1787 if (code) goto cleanup;
1789 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1791 // We know we must have a credential somewhere since we are
1792 // trying to renew a token
1794 KFW_import_ccache_data();
1795 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1798 krb5_principal princ = 0;
1799 krb5_principal service = 0;
1801 krb5_creds mcreds, creds;
1802 #endif /* COMMENT */
1804 const char * realm = NULL;
1805 struct afsconf_cell cellconfig;
1806 char local_cell[CELL_MAXNAMELEN+1];
1808 memset(&cellconfig, 0, sizeof(cellconfig));
1811 code = pkrb5_parse_name(ctx, principals[count], &princ);
1812 if (code) goto loop_cleanup;
1814 code = KFW_get_ccache(ctx, princ, &cc);
1815 if (code) goto loop_cleanup;
1817 if (cellconfig.linkedCell) {
1818 free(cellconfig.linkedCell);
1819 cellconfig.linkedCell = NULL;
1821 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1822 if ( code ) goto loop_cleanup;
1824 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1825 if ( IsDebuggerPresent() ) {
1826 OutputDebugString("Realm: ");
1827 OutputDebugString(realm);
1828 OutputDebugString("\n");
1832 /* krb5_cc_remove_cred() is not implemented
1835 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1836 realm, "afs", cell, NULL);
1838 memset(&mcreds, 0, sizeof(krb5_creds));
1839 mcreds.client = princ;
1840 mcreds.server = service;
1842 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1844 if ( IsDebuggerPresent() ) {
1845 char * cname, *sname;
1846 pkrb5_unparse_name(ctx, creds.client, &cname);
1847 pkrb5_unparse_name(ctx, creds.server, &sname);
1848 OutputDebugString("Removing credential for client \"");
1849 OutputDebugString(cname);
1850 OutputDebugString("\" and service \"");
1851 OutputDebugString(sname);
1852 OutputDebugString("\"\n");
1853 pkrb5_free_unparsed_name(ctx,cname);
1854 pkrb5_free_unparsed_name(ctx,sname);
1857 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1858 pkrb5_free_principal(ctx, creds.client);
1859 pkrb5_free_principal(ctx, creds.server);
1862 #endif /* COMMENT */
1864 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1865 if ( IsDebuggerPresent() ) {
1867 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1868 OutputDebugString(message);
1873 pkrb5_cc_close(ctx, cc);
1877 pkrb5_free_principal(ctx, princ);
1881 pkrb5_free_principal(ctx, service);
1884 if (cellconfig.linkedCell) {
1885 free(cellconfig.linkedCell);
1886 cellconfig.linkedCell = NULL;
1889 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1890 free(principals[count]);
1894 code = -1; // we did not renew the tokens
1898 pkrb5_free_context(ctx);
1899 return (code ? FALSE : TRUE);
1904 KFW_AFS_renew_tokens_for_all_cells(void)
1906 struct cell_principal_map * next = cell_princ_map;
1908 if ( IsDebuggerPresent() )
1909 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1914 for ( ; next ; next = next->next ) {
1916 KFW_AFS_renew_token_for_cell(next->cell);
1922 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1924 krb5_error_code code = 0;
1925 krb5_context ctx = NULL;
1926 krb5_ccache cc = NULL;
1927 krb5_principal me = NULL;
1928 krb5_principal server = NULL;
1929 krb5_creds my_creds;
1930 krb5_data *realm = NULL;
1932 if (!pkrb5_init_context)
1935 memset(&my_creds, 0, sizeof(krb5_creds));
1940 code = pkrb5_init_context(&ctx);
1941 if (code) goto cleanup;
1947 code = pkrb5_cc_default(ctx, &cc);
1948 if (code) goto cleanup;
1951 code = pkrb5_cc_get_principal(ctx, cc, &me);
1952 if (code) goto cleanup;
1954 realm = krb5_princ_realm(ctx, me);
1956 code = pkrb5_build_principal_ext(ctx, &server,
1957 realm->length,realm->data,
1958 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1959 realm->length,realm->data,
1964 if ( IsDebuggerPresent() ) {
1965 char * cname, *sname;
1966 pkrb5_unparse_name(ctx, me, &cname);
1967 pkrb5_unparse_name(ctx, server, &sname);
1968 OutputDebugString("Renewing credential for client \"");
1969 OutputDebugString(cname);
1970 OutputDebugString("\" and service \"");
1971 OutputDebugString(sname);
1972 OutputDebugString("\"\n");
1973 pkrb5_free_unparsed_name(ctx,cname);
1974 pkrb5_free_unparsed_name(ctx,sname);
1977 my_creds.client = me;
1978 my_creds.server = server;
1980 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1982 if ( IsDebuggerPresent() ) {
1984 StringCbPrintf(message, sizeof(message), "krb5_get_renewed_creds() failed: %d\n", code);
1985 OutputDebugString(message);
1990 code = pkrb5_cc_initialize(ctx, cc, me);
1992 if ( IsDebuggerPresent() ) {
1994 StringCbPrintf(message, sizeof(message), "krb5_cc_initialize() failed: %d\n", code);
1995 OutputDebugString(message);
2000 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2002 if ( IsDebuggerPresent() ) {
2004 StringCbPrintf(message, sizeof(message), "krb5_cc_store_cred() failed: %d\n", code);
2005 OutputDebugString(message);
2011 if (my_creds.client == me)
2012 my_creds.client = 0;
2013 if (my_creds.server == server)
2014 my_creds.server = 0;
2015 pkrb5_free_cred_contents(ctx, &my_creds);
2017 pkrb5_free_principal(ctx, me);
2019 pkrb5_free_principal(ctx, server);
2020 if (cc && (cc != alt_cc))
2021 pkrb5_cc_close(ctx, cc);
2022 if (ctx && (ctx != alt_ctx))
2023 pkrb5_free_context(ctx);
2028 KFW_kinit( krb5_context alt_ctx,
2031 char *principal_name,
2033 krb5_deltat lifetime,
2036 krb5_deltat renew_life,
2041 krb5_error_code code = 0;
2042 krb5_context ctx = NULL;
2043 krb5_ccache cc = NULL;
2044 krb5_principal me = NULL;
2046 krb5_creds my_creds;
2047 krb5_get_init_creds_opt options;
2048 krb5_address ** addrs = NULL;
2049 int i = 0, addr_count = 0;
2051 if (!pkrb5_init_context)
2054 pkrb5_get_init_creds_opt_init(&options);
2055 memset(&my_creds, 0, sizeof(my_creds));
2063 code = pkrb5_init_context(&ctx);
2064 if (code) goto cleanup;
2070 code = pkrb5_cc_default(ctx, &cc);
2071 if (code) goto cleanup;
2074 code = pkrb5_parse_name(ctx, principal_name, &me);
2078 code = pkrb5_unparse_name(ctx, me, &name);
2086 lifetime = pLeash_get_default_lifetime();
2087 #endif /* USE_LEASH */
2094 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2095 pkrb5_get_init_creds_opt_set_forwardable(&options,
2096 forwardable ? 1 : 0);
2097 pkrb5_get_init_creds_opt_set_proxiable(&options,
2099 pkrb5_get_init_creds_opt_set_renew_life(&options,
2102 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2106 // we are going to add the public IP address specified by the user
2107 // to the list provided by the operating system
2108 krb5_address ** local_addrs=NULL;
2111 pkrb5_os_localaddr(ctx, &local_addrs);
2112 while ( local_addrs[i++] );
2115 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2117 pkrb5_free_addresses(ctx, local_addrs);
2120 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2122 while ( local_addrs[i] ) {
2123 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2124 if (addrs[i] == NULL) {
2125 pkrb5_free_addresses(ctx, local_addrs);
2129 addrs[i]->magic = local_addrs[i]->magic;
2130 addrs[i]->addrtype = local_addrs[i]->addrtype;
2131 addrs[i]->length = local_addrs[i]->length;
2132 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2133 if (!addrs[i]->contents) {
2134 pkrb5_free_addresses(ctx, local_addrs);
2138 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2139 local_addrs[i]->length); /* safe */
2142 pkrb5_free_addresses(ctx, local_addrs);
2144 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2145 if (addrs[i] == NULL)
2148 addrs[i]->magic = KV5M_ADDRESS;
2149 addrs[i]->addrtype = AF_INET;
2150 addrs[i]->length = 4;
2151 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2152 if (!addrs[i]->contents)
2155 netIPAddr = htonl(publicIP);
2156 memcpy(addrs[i]->contents,&netIPAddr,4);
2158 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2163 code = pkrb5_get_init_creds_password(ctx,
2166 password, // password
2167 KRB5_prompter, // prompter
2168 hParent, // prompter data
2175 code = pkrb5_cc_initialize(ctx, cc, me);
2179 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2185 for ( i=0;i<addr_count;i++ ) {
2187 if ( addrs[i]->contents )
2188 free(addrs[i]->contents);
2193 if (my_creds.client == me)
2194 my_creds.client = 0;
2195 pkrb5_free_cred_contents(ctx, &my_creds);
2197 pkrb5_free_unparsed_name(ctx, name);
2199 pkrb5_free_principal(ctx, me);
2200 if (cc && (cc != alt_cc))
2201 pkrb5_cc_close(ctx, cc);
2202 if (ctx && (ctx != alt_ctx))
2203 pkrb5_free_context(ctx);
2209 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2211 krb5_context ctx = NULL;
2212 krb5_ccache cc = NULL;
2213 krb5_error_code code;
2215 if (!pkrb5_init_context)
2224 code = pkrb5_init_context(&ctx);
2225 if (code) goto cleanup;
2231 code = pkrb5_cc_default(ctx, &cc);
2232 if (code) goto cleanup;
2235 code = pkrb5_cc_destroy(ctx, cc);
2236 if ( !code ) cc = 0;
2239 if (cc && (cc != alt_cc))
2240 pkrb5_cc_close(ctx, cc);
2241 if (ctx && (ctx != alt_ctx))
2242 pkrb5_free_context(ctx);
2250 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2252 NTSTATUS Status = 0;
2254 TOKEN_STATISTICS Stats;
2260 *ppSessionData = NULL;
2262 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2266 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2267 CloseHandle( TokenHandle );
2271 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2272 if ( FAILED(Status) || !ppSessionData )
2279 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2280 // cache. It validates whether or not it is reasonable to assume that if we
2281 // attempted to retrieve valid tickets we could do so. Microsoft does not
2282 // automatically renew expired tickets. Therefore, the cache could contain
2283 // expired or invalid tickets. Microsoft also caches the user's password
2284 // and will use it to retrieve new TGTs if the cache is empty and tickets
2288 MSLSA_IsKerberosLogon(VOID)
2290 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2291 BOOL Success = FALSE;
2293 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2294 if ( pSessionData->AuthenticationPackage.Buffer ) {
2300 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2301 usLength = (pSessionData->AuthenticationPackage).Length;
2304 StringCbCopyNW( buffer, sizeof(buffer)/sizeof(WCHAR),
2305 usBuffer, usLength);
2306 if ( !lstrcmpW(L"Kerberos",buffer) )
2310 pLsaFreeReturnBuffer(pSessionData);
2314 #endif /* USE_MS2MIT */
2316 static BOOL CALLBACK
2317 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2321 switch ( message ) {
2323 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2325 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2328 for ( i=0; i < mid_cnt ; i++ ) {
2329 if (mid_tb[i].echo == 0)
2330 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2331 else if (mid_tb[i].echo == 2)
2332 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2337 switch ( LOWORD(wParam) ) {
2339 for ( i=0; i < mid_cnt ; i++ ) {
2340 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2341 *mid_tb[i].buf = '\0';
2345 EndDialog(hDialog, LOWORD(wParam));
2353 lpwAlign( LPWORD lpIn )
2357 ul = (ULONG_PTR) lpIn;
2361 return (LPWORD) ul;;
2365 * dialog widths are measured in 1/4 character widths
2366 * dialog height are measured in 1/8 character heights
2370 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2371 char * ptext[], int numlines, int width,
2372 int tb_cnt, struct textField * tb)
2376 LPDLGITEMTEMPLATE lpdit;
2382 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2389 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2391 // Define a dialog box.
2393 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2394 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2395 | DS_SETFOREGROUND | DS_3DLOOK
2396 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2397 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2400 lpdt->cx = 20 + width * 4;
2401 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2403 lpw = (LPWORD) (lpdt + 1);
2404 *lpw++ = 0; // no menu
2405 *lpw++ = 0; // predefined dialog box class (by default)
2407 lpwsz = (LPWSTR) lpw;
2408 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2410 *lpw++ = 8; // font size (points)
2411 lpwsz = (LPWSTR) lpw;
2412 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2416 //-----------------------
2417 // Define an OK button.
2418 //-----------------------
2419 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2420 lpdit = (LPDLGITEMTEMPLATE) lpw;
2421 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2422 lpdit->dwExtendedStyle = 0;
2423 lpdit->x = (lpdt->cx - 14)/4 - 20;
2424 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2427 lpdit->id = IDOK; // OK button identifier
2429 lpw = (LPWORD) (lpdit + 1);
2431 *lpw++ = 0x0080; // button class
2433 lpwsz = (LPWSTR) lpw;
2434 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2436 *lpw++ = 0; // no creation data
2438 //-----------------------
2439 // Define an Cancel button.
2440 //-----------------------
2441 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2442 lpdit = (LPDLGITEMTEMPLATE) lpw;
2443 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2444 lpdit->dwExtendedStyle = 0;
2445 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2446 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2449 lpdit->id = IDCANCEL; // CANCEL button identifier
2451 lpw = (LPWORD) (lpdit + 1);
2453 *lpw++ = 0x0080; // button class
2455 lpwsz = (LPWSTR) lpw;
2456 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2458 *lpw++ = 0; // no creation data
2460 /* Add controls for preface data */
2461 for ( i=0; i<numlines; i++) {
2462 /*-----------------------
2463 * Define a static text control.
2464 *-----------------------*/
2465 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2466 lpdit = (LPDLGITEMTEMPLATE) lpw;
2467 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2468 lpdit->dwExtendedStyle = 0;
2470 lpdit->y = 10 + i * 14;
2471 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2473 lpdit->id = ID_TEXT + i; // text identifier
2475 lpw = (LPWORD) (lpdit + 1);
2477 *lpw++ = 0x0082; // static class
2479 lpwsz = (LPWSTR) lpw;
2480 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2481 -1, lpwsz, 2*width);
2483 *lpw++ = 0; // no creation data
2486 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2487 int len = (int)strlen(tb[i].label);
2492 for ( i=0; i<tb_cnt; i++) {
2494 /*-----------------------
2495 * Define a static text control.
2496 *-----------------------*/
2497 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2498 lpdit = (LPDLGITEMTEMPLATE) lpw;
2499 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2500 lpdit->dwExtendedStyle = 0;
2502 lpdit->y = 10 + (numlines + i + 1) * 14;
2503 lpdit->cx = pwid * 4;
2505 lpdit->id = ID_TEXT + numlines + i; // text identifier
2507 lpw = (LPWORD) (lpdit + 1);
2509 *lpw++ = 0x0082; // static class
2511 lpwsz = (LPWSTR) lpw;
2512 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2515 *lpw++ = 0; // no creation data
2517 /*-----------------------
2518 * Define an edit control.
2519 *-----------------------*/
2520 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2521 lpdit = (LPDLGITEMTEMPLATE) lpw;
2522 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2523 lpdit->dwExtendedStyle = 0;
2524 lpdit->x = 10 + (pwid + 1) * 4;
2525 lpdit->y = 10 + (numlines + i + 1) * 14;
2526 lpdit->cx = (width - (pwid + 1)) * 4;
2528 lpdit->id = ID_MID_TEXT + i; // identifier
2530 lpw = (LPWORD) (lpdit + 1);
2532 *lpw++ = 0x0081; // edit class
2534 lpwsz = (LPWSTR) lpw;
2535 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2538 *lpw++ = 0; // no creation data
2542 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2543 hwndOwner, (DLGPROC) MultiInputDialogProc);
2547 case 0: /* Timeout */
2555 StringCbPrintf(buf, sizeof(buf), "DialogBoxIndirect() failed: %d", GetLastError());
2556 MessageBox(hwndOwner,
2559 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2566 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2568 HINSTANCE hInst = 0;
2572 char * plines[16], *p = preface ? preface : "";
2575 for ( i=0; i<16; i++ )
2578 while (*p && numlines < 16) {
2579 plines[numlines++] = p;
2580 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2581 if ( *p == '\r' && *(p+1) == '\n' ) {
2584 } else if ( *p == '\n' ) {
2587 if ( strlen(plines[numlines-1]) > maxwidth )
2588 maxwidth = (int)strlen(plines[numlines-1]);
2591 for ( i=0;i<n;i++ ) {
2592 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2593 if ( maxwidth < len )
2597 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2600 static krb5_error_code KRB5_CALLCONV
2601 KRB5_prompter( krb5_context context,
2606 krb5_prompt prompts[])
2608 krb5_error_code errcode = 0;
2610 struct textField * tb = NULL;
2611 int len = 0, blen=0, nlen=0;
2612 HWND hParent = (HWND)data;
2615 nlen = (int)strlen(name)+2;
2618 blen = (int)strlen(banner)+2;
2620 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2623 memset(tb,0,sizeof(struct textField) * num_prompts);
2624 for ( i=0; i < num_prompts; i++ ) {
2625 tb[i].buf = prompts[i].reply->data;
2626 tb[i].len = prompts[i].reply->length;
2627 tb[i].label = prompts[i].prompt;
2629 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2632 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2634 for ( i=0; i < num_prompts; i++ )
2635 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2643 for (i = 0; i < num_prompts; i++) {
2644 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2651 KFW_AFS_wait_for_service_start(void)
2656 CurrentState = SERVICE_START_PENDING;
2657 memset(HostName, '\0', sizeof(HostName));
2658 gethostname(HostName, sizeof(HostName));
2660 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2662 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2664 if ( IsDebuggerPresent() ) {
2665 switch ( CurrentState ) {
2666 case SERVICE_STOPPED:
2667 OutputDebugString("SERVICE_STOPPED\n");
2669 case SERVICE_START_PENDING:
2670 OutputDebugString("SERVICE_START_PENDING\n");
2672 case SERVICE_STOP_PENDING:
2673 OutputDebugString("SERVICE_STOP_PENDING\n");
2675 case SERVICE_RUNNING:
2676 OutputDebugString("SERVICE_RUNNING\n");
2678 case SERVICE_CONTINUE_PENDING:
2679 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2681 case SERVICE_PAUSE_PENDING:
2682 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2684 case SERVICE_PAUSED:
2685 OutputDebugString("SERVICE_PAUSED\n");
2688 OutputDebugString("UNKNOWN Service State\n");
2691 if (CurrentState == SERVICE_STOPPED)
2693 if (CurrentState == SERVICE_RUNNING)
2709 memset(HostName, '\0', sizeof(HostName));
2710 gethostname(HostName, sizeof(HostName));
2711 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2713 if (CurrentState != SERVICE_RUNNING)
2716 rc = ktc_ForgetAllTokens();
2722 #define ALLOW_REGISTER 1
2724 ViceIDToUsername(char *username,
2725 char *realm_of_user,
2726 char *realm_of_cell,
2728 struct ktc_principal *aclient,
2729 struct ktc_principal *aserver,
2730 struct ktc_token *atoken)
2732 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2733 static char confdir[512] = { 0 };
2734 #ifdef AFS_ID_TO_NAME
2735 char username_copy[BUFSIZ];
2736 #endif /* AFS_ID_TO_NAME */
2737 long viceId = ANONYMOUSID; /* AFS uid of user */
2739 #ifdef ALLOW_REGISTER
2741 #endif /* ALLOW_REGISTER */
2743 if (confdir[0] == '\0')
2744 cm_GetConfigDir(confdir, sizeof(confdir));
2746 StringCbCopyN( lastcell, sizeof(lastcell),
2747 aserver->cell, sizeof(lastcell) - 1);
2749 if (!pr_Initialize (0, confdir, aserver->cell)) {
2750 char sname[PR_MAXNAMELEN];
2751 StringCbCopyN( sname, sizeof(sname),
2752 username, sizeof(sname) - 1);
2753 status = pr_SNameToId (sname, &viceId);
2758 * This is a crock, but it is Transarc's crock, so
2759 * we have to play along in order to get the
2760 * functionality. The way the afs id is stored is
2761 * as a string in the username field of the token.
2762 * Contrary to what you may think by looking at
2763 * the code for tokens, this hack (AFS ID %d) will
2764 * not work if you change %d to something else.
2768 * This code is taken from cklog -- it lets people
2769 * automatically register with the ptserver in foreign cells
2772 #ifdef ALLOW_REGISTER
2774 if (viceId != ANONYMOUSID) {
2775 #else /* ALLOW_REGISTER */
2776 if ((status == 0) && (viceId != ANONYMOUSID))
2777 #endif /* ALLOW_REGISTER */
2779 #ifdef AFS_ID_TO_NAME
2780 StringCbCopyN( username_copy, sizeof(username_copy),
2781 username, sizeof(username_copy) - 1);
2782 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2783 #endif /* AFS_ID_TO_NAME */
2785 #ifdef ALLOW_REGISTER
2786 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2788 StringCbCopyN( aclient->name, sizeof(aclient->name),
2789 username, sizeof(aclient->name) - 1);
2790 aclient->instance[0] = '\0';
2791 StringCbCopyN( aclient->cell, sizeof(aclient->cell),
2792 realm_of_user, sizeof(aclient->cell) - 1);
2793 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2795 if (status = pr_Initialize(1L, confdir, aserver->cell))
2797 status = pr_CreateUser(username, &id);
2801 #ifdef AFS_ID_TO_NAME
2802 StringCbCopyN( username_copy, sizeof(username_copy),
2803 username, sizeof(username_copy) - 1);
2804 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2805 #endif /* AFS_ID_TO_NAME */
2808 #endif /* ALLOW_REGISTER */
2814 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2815 krb5_error_code code;
2816 krb5_ticket *ticket;
2819 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2821 len = krb5_princ_realm(context, ticket->server)->length;
2822 if (len > destlen - 1)
2825 StringCbCopyN(dest, destlen, krb5_princ_realm(context, ticket->server)->data, len);
2827 pkrb5_free_ticket(context, ticket);
2833 krb5_context alt_ctx,
2838 int lifetime, /* unused parameter */
2846 #endif /* USE_KRB4 */
2847 struct ktc_principal aserver;
2848 struct ktc_principal aclient;
2849 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2850 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2851 char local_cell[CELL_MAXNAMELEN+1];
2852 char Dmycell[CELL_MAXNAMELEN+1];
2853 struct ktc_token atoken;
2854 struct ktc_token btoken;
2855 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2856 char RealmName[128];
2858 char ServiceName[128];
2862 krb5_context ctx = NULL;
2863 krb5_ccache cc = NULL;
2865 krb5_creds * k5creds = NULL;
2866 krb5_error_code code;
2867 krb5_principal client_principal = NULL;
2868 krb5_data * k5data = NULL;
2869 unsigned int i, retry = 0;
2872 memset(HostName, '\0', sizeof(HostName));
2873 gethostname(HostName, sizeof(HostName));
2874 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2875 if ( IsDebuggerPresent() )
2876 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2879 if (CurrentState != SERVICE_RUNNING) {
2880 if ( IsDebuggerPresent() )
2881 OutputDebugString("AFSD Service NOT RUNNING\n");
2885 if (!pkrb5_init_context)
2888 memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
2889 memset(RealmName, '\0', sizeof(RealmName));
2890 memset(CellName, '\0', sizeof(CellName));
2891 memset(ServiceName, '\0', sizeof(ServiceName));
2892 memset(realm_of_user, '\0', sizeof(realm_of_user));
2893 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2894 if (cell && cell[0])
2895 StringCbCopyN( Dmycell, sizeof(Dmycell),
2896 cell, sizeof(Dmycell) - 1);
2898 memset(Dmycell, '\0', sizeof(Dmycell));
2900 // NULL or empty cell returns information on local cell
2901 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2903 // KFW_AFS_error(rc, "get_cellconfig()");
2910 code = pkrb5_init_context(&ctx);
2911 if (code) goto cleanup;
2917 code = pkrb5_cc_default(ctx, &cc);
2918 if (code) goto skip_krb5_init;
2921 memset(&increds, 0, sizeof(increds));
2923 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2925 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2927 OutputDebugString("Principal Not Found for ccache\n");
2929 goto skip_krb5_init;
2932 if (!KFW_accept_dotted_usernames()) {
2933 /* look for client principals which cannot be distinguished
2934 * from Kerberos 4 multi-component principal names
2936 k5data = krb5_princ_component(ctx,client_principal,0);
2937 for ( i=0; i<k5data->length; i++ ) {
2938 if ( k5data->data[i] == '.' )
2941 if (i != k5data->length)
2943 OutputDebugString("Illegal Principal name contains dot in first component\n");
2944 rc = KRB5KRB_ERR_GENERIC;
2949 i = krb5_princ_realm(ctx, client_principal)->length;
2952 StringCbCopyN( realm_of_user, sizeof(realm_of_user),
2953 krb5_princ_realm(ctx, client_principal)->data, i);
2958 if ( !try_krb5 || !realm_of_user[0] ) {
2959 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2968 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
2969 afs_realm_of_cell(ctx, &ak_cellconfig),
2970 sizeof(realm_of_cell) - 1);
2972 if (strlen(service) == 0)
2973 StringCbCopy( ServiceName, sizeof(ServiceName), "afs");
2975 StringCbCopyN( ServiceName, sizeof(ServiceName),
2976 service, sizeof(ServiceName) - 1);
2978 if (strlen(cell) == 0)
2979 StringCbCopyN( CellName, sizeof(CellName),
2980 local_cell, sizeof(CellName) - 1);
2982 StringCbCopyN( CellName, sizeof(CellName),
2983 cell, sizeof(CellName) - 1);
2985 /* This is for Kerberos v4 only */
2986 if (strlen(realm) == 0)
2987 StringCbCopyN( RealmName, sizeof(RealmName),
2988 realm_of_cell, sizeof(RealmName) - 1);
2990 StringCbCopyN( RealmName, sizeof(RealmName),
2991 realm, sizeof(RealmName) - 1);
2993 memset(&creds, '\0', sizeof(creds));
2997 code = KRB5KRB_ERR_GENERIC;
3000 increds.client = client_principal;
3001 increds.times.endtime = 0;
3002 /* Ask for DES since that is what V4 understands */
3003 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
3005 /* If there was a specific realm we are supposed to try
3008 if (strlen(realm) != 0) {
3009 /* service/cell@REALM */
3011 code = pkrb5_build_principal(ctx, &increds.server,
3017 if ( IsDebuggerPresent() ) {
3018 char * cname, *sname;
3019 pkrb5_unparse_name(ctx, increds.client, &cname);
3020 pkrb5_unparse_name(ctx, increds.server, &sname);
3021 OutputDebugString("Getting tickets for \"");
3022 OutputDebugString(cname);
3023 OutputDebugString("\" and service \"");
3024 OutputDebugString(sname);
3025 OutputDebugString("\"\n");
3026 pkrb5_free_unparsed_name(ctx,cname);
3027 pkrb5_free_unparsed_name(ctx,sname);
3031 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3033 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3034 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3035 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3036 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3037 /* Or service@REALM */
3038 pkrb5_free_principal(ctx,increds.server);
3040 code = pkrb5_build_principal(ctx, &increds.server,
3046 if ( IsDebuggerPresent() ) {
3047 char * cname, *sname;
3048 pkrb5_unparse_name(ctx, increds.client, &cname);
3049 pkrb5_unparse_name(ctx, increds.server, &sname);
3050 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3051 OutputDebugString("Trying again: getting tickets for \"");
3052 OutputDebugString(cname);
3053 OutputDebugString("\" and service \"");
3054 OutputDebugString(sname);
3055 OutputDebugString("\"\n");
3056 pkrb5_free_unparsed_name(ctx,cname);
3057 pkrb5_free_unparsed_name(ctx,sname);
3061 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3065 /* we have a local realm for the cell */
3066 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3067 realm, sizeof(realm_of_cell) - 1);
3070 /* Otherwise, first try service/cell@CLIENT_REALM */
3071 if (code = pkrb5_build_principal(ctx, &increds.server,
3072 (int)strlen(realm_of_user),
3081 if ( IsDebuggerPresent() ) {
3082 char * cname, *sname;
3083 pkrb5_unparse_name(ctx, increds.client, &cname);
3084 pkrb5_unparse_name(ctx, increds.server, &sname);
3085 OutputDebugString("Getting tickets for \"");
3086 OutputDebugString(cname);
3087 OutputDebugString("\" and service \"");
3088 OutputDebugString(sname);
3089 OutputDebugString("\"\n");
3090 pkrb5_free_unparsed_name(ctx,cname);
3091 pkrb5_free_unparsed_name(ctx,sname);
3094 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3096 /* The client's realm is a local realm for the cell.
3097 * Save it so that later the pts registration will not
3100 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3101 realm_of_user, sizeof(realm_of_cell) - 1);
3104 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3105 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3106 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3107 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
3108 strcmp(realm_of_user, realm_of_cell)) {
3109 /* Then service/cell@CELL_REALM */
3110 pkrb5_free_principal(ctx,increds.server);
3112 code = pkrb5_build_principal(ctx, &increds.server,
3113 (int)strlen(realm_of_cell),
3118 if ( IsDebuggerPresent() ) {
3119 char * cname, *sname;
3120 pkrb5_unparse_name(ctx, increds.client, &cname);
3121 pkrb5_unparse_name(ctx, increds.server, &sname);
3122 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3123 OutputDebugString("Trying again: getting tickets for \"");
3124 OutputDebugString(cname);
3125 OutputDebugString("\" and service \"");
3126 OutputDebugString(sname);
3127 OutputDebugString("\"\n");
3128 pkrb5_free_unparsed_name(ctx,cname);
3129 pkrb5_free_unparsed_name(ctx,sname);
3133 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3135 if (!code && !strlen(realm_of_cell))
3136 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3139 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3140 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3141 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3142 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3143 /* Finally service@CELL_REALM */
3144 pkrb5_free_principal(ctx,increds.server);
3146 code = pkrb5_build_principal(ctx, &increds.server,
3147 (int)strlen(realm_of_cell),
3152 if ( IsDebuggerPresent() ) {
3153 char * cname, *sname;
3154 pkrb5_unparse_name(ctx, increds.client, &cname);
3155 pkrb5_unparse_name(ctx, increds.server, &sname);
3156 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3157 OutputDebugString("Trying again: getting tickets for \"");
3158 OutputDebugString(cname);
3159 OutputDebugString("\" and service \"");
3160 OutputDebugString(sname);
3161 OutputDebugString("\"\n");
3162 pkrb5_free_unparsed_name(ctx,cname);
3163 pkrb5_free_unparsed_name(ctx,sname);
3167 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3168 if (!code && !strlen(realm_of_cell))
3169 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3174 if ( IsDebuggerPresent() ) {
3176 StringCbPrintf(message, sizeof(message), "krb5_get_credentials returns: %d\n", code);
3177 OutputDebugString(message);
3183 /* This code inserts the entire K5 ticket into the token
3184 * No need to perform a krb524 translation which is
3185 * commented out in the code below
3187 if (KFW_use_krb524() ||
3188 k5creds->ticket.length > MAXKTCTICKETLEN)
3191 memset(&aserver, '\0', sizeof(aserver));
3192 StringCbCopyN( aserver.name, sizeof(aserver.name),
3193 ServiceName, sizeof(aserver.name) - 1);
3194 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
3195 CellName, sizeof(aserver.cell) - 1);
3197 memset(&atoken, '\0', sizeof(atoken));
3198 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3199 atoken.startTime = k5creds->times.starttime;
3200 atoken.endTime = k5creds->times.endtime;
3201 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3202 atoken.ticketLen = k5creds->ticket.length;
3203 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3206 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3207 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3208 if ( rc == KTC_NOCM && retry < 20 ) {
3211 goto retry_gettoken5;
3216 if (atoken.kvno == btoken.kvno &&
3217 atoken.ticketLen == btoken.ticketLen &&
3218 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3219 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3221 /* Success - Nothing to do */
3225 // * Reset the "aclient" structure before we call ktc_SetToken.
3226 // * This structure was first set by the ktc_GetToken call when
3227 // * we were comparing whether identical tokens already existed.
3229 len = min(k5creds->client->data[0].length, sizeof(aclient.name) - 1);
3230 StringCbCopyN( aclient.name, sizeof(aclient.name),
3231 k5creds->client->data[0].data, len);
3233 if ( k5creds->client->length > 1 ) {
3234 StringCbCat( aclient.name, sizeof(aclient.name), ".");
3235 len = min(k5creds->client->data[1].length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3236 StringCbCatN( aclient.name, sizeof(aclient.name),
3237 k5creds->client->data[1].data, len);
3239 aclient.instance[0] = '\0';
3241 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3242 realm_of_cell, sizeof(aclient.cell) - 1);
3244 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3245 /* For Khimaira, always append the realm name */
3246 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3247 StringCbCat( aclient.name, sizeof(aclient.name), "@");
3248 len = min(k5creds->client->realm.length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3249 StringCbCatN( aclient.name, sizeof(aclient.name), k5creds->client->realm.data, len);
3252 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3253 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3254 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3255 &aclient, &aserver, &atoken);
3258 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3259 smbname, sizeof(aclient.smbname) - 1);
3261 aclient.smbname[0] = '\0';
3264 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3266 goto cleanup; /* We have successfully inserted the token */
3272 /* Otherwise, the ticket could have been too large so try to
3273 * convert using the krb524d running with the KDC
3275 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3276 pkrb5_free_creds(ctx, k5creds);
3278 if ( IsDebuggerPresent() ) {
3280 StringCbPrintf(message, sizeof(message), "krb524_convert_creds_kdc returns: %d\n", code);
3281 OutputDebugString(message);
3286 #endif /* USE_KRB524 */
3290 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3291 if (code == NO_TKT_FIL) {
3292 // if the problem is that we have no krb4 tickets
3293 // do not attempt to continue
3296 if (code != KSUCCESS)
3297 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3299 if (code != KSUCCESS)
3301 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3303 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3308 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3310 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3325 memset(&aserver, '\0', sizeof(aserver));
3326 StringCbCopyN( aserver.name, sizeof(aserver.name), ServiceName, sizeof(aserver.name) - 1);
3327 StringCbCopyN( aserver.cell, sizeof(aserver.cell), CellName, sizeof(aserver.cell) - 1);
3329 memset(&atoken, '\0', sizeof(atoken));
3330 atoken.kvno = creds.kvno;
3331 atoken.startTime = creds.issue_date;
3332 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3333 memcpy(&atoken.sessionKey, creds.session, 8);
3334 atoken.ticketLen = creds.ticket_st.length;
3335 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3338 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3339 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3340 if ( rc == KTC_NOCM && retry < 20 ) {
3343 goto retry_gettoken;
3345 KFW_AFS_error(rc, "ktc_GetToken()");
3350 if (atoken.kvno == btoken.kvno &&
3351 atoken.ticketLen == btoken.ticketLen &&
3352 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3353 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3358 // * Reset the "aclient" structure before we call ktc_SetToken.
3359 // * This structure was first set by the ktc_GetToken call when
3360 // * we were comparing whether identical tokens already existed.
3362 StringCbCopyN( aclient.name, sizeof(aclient.name), creds.pname, sizeof(aclient.name) - 1);
3365 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3366 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3368 aclient.instance[0] = '\0';
3370 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3371 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3372 aclient.name[MAXKTCREALMLEN-1] = '\0';
3374 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3375 CellName, sizeof(aclient.cell) - 1);
3377 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3378 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3379 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3380 &aclient, &aserver, &atoken);
3383 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3384 smbname, sizeof(aclient.smbname) - 1);
3386 aclient.smbname[0] = '\0';
3389 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3391 KFW_AFS_error(rc, "ktc_SetToken()");
3397 if (client_principal)
3398 pkrb5_free_principal(ctx,client_principal);
3399 /* increds.client == client_principal */
3401 pkrb5_free_principal(ctx,increds.server);
3402 if (cc && (cc != alt_cc))
3403 pkrb5_cc_close(ctx, cc);
3404 if (ctx && (ctx != alt_ctx))
3405 pkrb5_free_context(ctx);
3406 if (ak_cellconfig.linkedCell)
3407 free(ak_cellconfig.linkedCell);
3409 return(rc? rc : code);
3412 /**************************************/
3413 /* afs_realm_of_cell(): */
3414 /**************************************/
3416 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3418 static char krbrlm[REALM_SZ+1]="";
3419 char ** realmlist=NULL;
3425 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3426 if ( !r && realmlist && realmlist[0] ) {
3427 StringCbCopyN( krbrlm, sizeof(krbrlm),
3428 realmlist[0], sizeof(krbrlm) - 1);
3429 pkrb5_free_host_realm(ctx, realmlist);
3435 char *t = cellconfig->name;
3440 if (islower(c)) c=toupper(c);
3448 /**************************************/
3449 /* KFW_AFS_get_cellconfig(): */
3450 /**************************************/
3452 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3455 char newcell[CELL_MAXNAMELEN+1];
3456 char linkedcell[CELL_MAXNAMELEN+1]="";
3458 local_cell[0] = (char)0;
3459 memset(cellconfig, 0, sizeof(*cellconfig));
3461 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3462 if (rc = cm_GetRootCellName(local_cell))
3467 if (strlen(cell) == 0)
3468 strcpy(cell, local_cell);
3470 rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3471 if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
3472 rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3475 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3479 StringCbCopyN( cellconfig->name, sizeof(cellconfig->name),
3480 newcell, sizeof(cellconfig->name) - 1);
3482 cellconfig->linkedCell = strdup(linkedcell);
3487 /**************************************/
3488 /* get_cellconfig_callback(): */
3489 /**************************************/
3491 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
3493 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3495 cc->hostAddr[cc->numServers] = *addrp;
3496 StringCbCopyN( cc->hostName[cc->numServers], sizeof(cc->hostName[cc->numServers]),
3497 namep, sizeof(cc->hostName[cc->numServers]) - 1);
3503 /**************************************/
3504 /* KFW_AFS_error(): */
3505 /**************************************/
3507 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3510 const char *errText;
3512 // Using AFS defines as error messages for now, until Transarc
3513 // gets back to me with "string" translations of each of these
3515 if (rc == KTC_ERROR)
3516 errText = "KTC_ERROR";
3517 else if (rc == KTC_TOOBIG)
3518 errText = "KTC_TOOBIG";
3519 else if (rc == KTC_INVAL)
3520 errText = "KTC_INVAL";
3521 else if (rc == KTC_NOENT)
3522 errText = "KTC_NOENT";
3523 else if (rc == KTC_PIOCTLFAIL)
3524 errText = "KTC_PIOCTLFAIL";
3525 else if (rc == KTC_NOPIOCTL)
3526 errText = "KTC_NOPIOCTL";
3527 else if (rc == KTC_NOCELL)
3528 errText = "KTC_NOCELL";
3529 else if (rc == KTC_NOCM)
3530 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3532 errText = "Unknown error!";
3534 StringCbPrintf(message, sizeof(message), "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3536 if ( IsDebuggerPresent() ) {
3537 OutputDebugString(message);
3538 OutputDebugString("\n");
3540 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3546 LPSTR lpszMachineName,
3547 LPSTR lpszServiceName,
3548 DWORD *lpdwCurrentState)
3551 SC_HANDLE schSCManager = NULL;
3552 SC_HANDLE schService = NULL;
3553 DWORD fdwDesiredAccess = 0;
3554 SERVICE_STATUS ssServiceStatus = {0};
3557 *lpdwCurrentState = 0;
3559 fdwDesiredAccess = GENERIC_READ;
3561 schSCManager = OpenSCManager(lpszMachineName,
3565 if(schSCManager == NULL)
3567 hr = GetLastError();
3571 schService = OpenService(schSCManager,
3575 if(schService == NULL)
3577 hr = GetLastError();
3581 fRet = QueryServiceStatus(schService,
3586 hr = GetLastError();
3590 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3594 CloseServiceHandle(schService);
3595 CloseServiceHandle(schSCManager);
3608 for (n = 0; fi[n].func_ptr_var; n++)
3609 *(fi[n].func_ptr_var) = 0;
3610 if (h) FreeLibrary(h);
3615 const char* dll_name,
3617 HINSTANCE* ph, // [out, optional] - DLL handle
3618 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3619 int cleanup, // cleanup function pointers and unload on error
3620 int go_on, // continue loading even if some functions cannot be loaded
3621 int silent // do not pop-up a system dialog if DLL cannot be loaded
3630 if (pindex) *pindex = -1;
3632 for (n = 0; fi[n].func_ptr_var; n++)
3633 *(fi[n].func_ptr_var) = 0;
3636 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3637 h = LoadLibrary(dll_name);
3645 for (i = 0; (go_on || !error) && (i < n); i++)
3647 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3653 *(fi[i].func_ptr_var) = p;
3656 if (pindex) *pindex = last_i;
3657 if (error && cleanup && !go_on) {
3658 for (i = 0; i < n; i++) {
3659 *(fi[i].func_ptr_var) = 0;
3665 if (error) return 0;
3669 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3671 krb5_context ctx = NULL;
3672 krb5_ccache cc = NULL;
3673 krb5_error_code code;
3675 const char * realm = NULL;
3676 krb5_principal principal = NULL;
3677 char * pname = NULL;
3678 char password[PROBE_PASSWORD_LEN+1];
3679 BOOL serverReachable = 0;
3681 if (!pkrb5_init_context)
3684 code = pkrb5_init_context(&ctx);
3685 if (code) goto cleanup;
3688 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3690 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3691 realm, PROBE_USERNAME, NULL, NULL);
3692 if ( code ) goto cleanup;
3694 code = KFW_get_ccache(ctx, principal, &cc);
3695 if ( code ) goto cleanup;
3697 code = pkrb5_unparse_name(ctx, principal, &pname);
3698 if ( code ) goto cleanup;
3700 pwdata.data = password;
3701 pwdata.length = PROBE_PASSWORD_LEN;
3702 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3705 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3708 password[PROBE_PASSWORD_LEN] = '\0';
3710 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3720 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3721 case KRB5KDC_ERR_CLIENT_REVOKED:
3722 case KRB5KDC_ERR_CLIENT_NOTYET:
3723 case KRB5KDC_ERR_PREAUTH_FAILED:
3724 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3725 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3726 serverReachable = TRUE;
3729 serverReachable = FALSE;
3734 pkrb5_free_unparsed_name(ctx,pname);
3736 pkrb5_free_principal(ctx,principal);
3738 pkrb5_cc_close(ctx,cc);
3740 pkrb5_free_context(ctx);
3742 return serverReachable;
3746 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
3748 krb5_context ctx = NULL;
3749 krb5_error_code code;
3750 krb5_ccache mslsa_ccache=NULL;
3751 krb5_principal princ = NULL;
3752 char * pname = NULL;
3755 if (!KFW_is_available())
3758 if (code = pkrb5_init_context(&ctx))
3761 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3764 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3767 if (code = pkrb5_unparse_name(ctx, princ, &pname))
3770 if ( strlen(pname) < *dwSize ) {
3771 StringCbCopyN(szUser, *dwSize, pname, (*dwSize) - 1);
3774 *dwSize = (DWORD)strlen(pname);
3778 pkrb5_free_unparsed_name(ctx, pname);
3781 pkrb5_free_principal(ctx, princ);
3784 pkrb5_cc_close(ctx, mslsa_ccache);
3787 pkrb5_free_context(ctx);
3792 KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
3794 // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
3795 PSID pSystemSID = NULL;
3796 DWORD SystemSIDlength = 0, UserSIDlength = 0;
3797 PACL ccacheACL = NULL;
3798 DWORD ccacheACLlength = 0;
3799 PTOKEN_USER pTokenUser = NULL;
3808 /* Get System SID */
3809 if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
3815 SystemSIDlength = GetLengthSid(pSystemSID);
3816 ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
3817 + SystemSIDlength - sizeof(DWORD);
3820 if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
3822 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
3823 pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
3825 GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
3830 UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
3832 ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
3837 ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
3842 InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
3843 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3844 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3847 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3848 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3849 pTokenUser->User.Sid);
3850 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3851 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3856 gle = GetLastError();
3857 if (gle != ERROR_NO_TOKEN)
3860 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3861 OWNER_SECURITY_INFORMATION,
3862 pTokenUser->User.Sid,
3866 gle = GetLastError();
3867 if (gle != ERROR_NO_TOKEN)
3871 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3872 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3877 gle = GetLastError();
3878 if (gle != ERROR_NO_TOKEN)
3885 LocalFree(pSystemSID);
3887 LocalFree(pTokenUser);
3889 LocalFree(ccacheACL);
3894 KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
3897 DWORD dwSize = size-1; /* leave room for nul */
3900 if (!hUserToken || !newfilename || size <= 0)
3903 *newfilename = '\0';
3905 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
3906 if ( !dwLen || dwLen > dwSize )
3907 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
3908 if ( !dwLen || dwLen > dwSize )
3911 newfilename[dwSize] = '\0';
3916 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
3918 char filename[MAX_PATH] = "";
3920 char cachename[MAX_PATH + 8] = "FILE:";
3921 krb5_context ctx = NULL;
3922 krb5_error_code code;
3923 krb5_principal princ = NULL;
3924 krb5_ccache cc = NULL;
3925 krb5_ccache ncc = NULL;
3927 if (!pkrb5_init_context || !user || !szLogonId)
3930 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
3931 if ( count > sizeof(filename) || count == 0 ) {
3932 GetWindowsDirectory(filename, sizeof(filename));
3935 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
3938 StringCbCat( filename, sizeof(filename), "\\");
3939 StringCbCat( filename, sizeof(filename), szLogonId);
3941 StringCbCat( cachename, sizeof(cachename), filename);
3943 DeleteFile(filename);
3945 code = pkrb5_init_context(&ctx);
3946 if (code) goto cleanup;
3948 code = pkrb5_parse_name(ctx, user, &princ);
3949 if (code) goto cleanup;
3951 code = KFW_get_ccache(ctx, princ, &cc);
3952 if (code) goto cleanup;
3954 code = pkrb5_cc_resolve(ctx, cachename, &ncc);
3955 if (code) goto cleanup;
3957 code = pkrb5_cc_initialize(ctx, ncc, princ);
3958 if (code) goto cleanup;
3960 code = KFW_AFS_set_file_cache_dacl(filename, NULL);
3961 if (code) goto cleanup;
3963 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3967 pkrb5_cc_close(ctx, cc);
3971 pkrb5_cc_close(ctx, ncc);
3975 pkrb5_free_principal(ctx, princ);
3980 pkrb5_free_context(ctx);
3984 KFW_AFS_copy_file_cache_to_default_cache(char * filename)
3986 char cachename[MAX_PATH + 8] = "FILE:";
3987 krb5_context ctx = NULL;
3988 krb5_error_code code;
3989 krb5_principal princ = NULL;
3990 krb5_ccache cc = NULL;
3991 krb5_ccache ncc = NULL;
3994 if (!pkrb5_init_context || !filename)
3997 if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
4000 code = pkrb5_init_context(&ctx);
4003 StringCbCat( cachename, sizeof(cachename), filename);
4005 code = pkrb5_cc_resolve(ctx, cachename, &cc);
4006 if (code) goto cleanup;
4008 code = pkrb5_cc_get_principal(ctx, cc, &princ);
4010 code = pkrb5_cc_default(ctx, &ncc);
4012 code = pkrb5_cc_initialize(ctx, ncc, princ);
4015 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
4018 pkrb5_cc_close(ctx, ncc);
4022 retval=0; /* success */
4026 pkrb5_cc_close(ctx, cc);
4030 DeleteFile(filename);
4033 pkrb5_free_principal(ctx, princ);
4038 pkrb5_free_context(ctx);
4043 /* We are including this
4045 /* Ticket lifetime. This defines the table used to lookup lifetime for the
4046 fixed part of rande of the one byte lifetime field. Values less than 0x80
4047 are intrpreted as the number of 5 minute intervals. Values from 0x80 to
4048 0xBF should be looked up in this table. The value of 0x80 is the same using
4049 both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days.
4050 The intervening values of have a fixed ratio of roughly 1.06914. The value
4051 oxFF is defined to mean a ticket has no expiration time. This should be
4052 used advisedly since individual servers may impose defacto upperbounds on
4053 ticket lifetimes. */
4055 #define TKTLIFENUMFIXED 64
4056 #define TKTLIFEMINFIXED 0x80
4057 #define TKTLIFEMAXFIXED 0xBF
4058 #define TKTLIFENOEXPIRE 0xFF
4059 #define MAXTKTLIFETIME (30*24*3600) /* 30 days */
4061 static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
4062 38400, /* 10.67 hours, 0.44 days */
4063 41055, /* 11.40 hours, 0.48 days */
4064 43894, /* 12.19 hours, 0.51 days */
4065 46929, /* 13.04 hours, 0.54 days */
4066 50174, /* 13.94 hours, 0.58 days */
4067 53643, /* 14.90 hours, 0.62 days */
4068 57352, /* 15.93 hours, 0.66 days */
4069 61318, /* 17.03 hours, 0.71 days */
4070 65558, /* 18.21 hours, 0.76 days */
4071 70091, /* 19.47 hours, 0.81 days */
4072 74937, /* 20.82 hours, 0.87 days */
4073 80119, /* 22.26 hours, 0.93 days */
4074 85658, /* 23.79 hours, 0.99 days */
4075 91581, /* 25.44 hours, 1.06 days */
4076 97914, /* 27.20 hours, 1.13 days */
4077 104684, /* 29.08 hours, 1.21 days */
4078 111922, /* 31.09 hours, 1.30 days */
4079 119661, /* 33.24 hours, 1.38 days */
4080 127935, /* 35.54 hours, 1.48 days */
4081 136781, /* 37.99 hours, 1.58 days */
4082 146239, /* 40.62 hours, 1.69 days */
4083 156350, /* 43.43 hours, 1.81 days */
4084 167161, /* 46.43 hours, 1.93 days */
4085 178720, /* 49.64 hours, 2.07 days */
4086 191077, /* 53.08 hours, 2.21 days */
4087 204289, /* 56.75 hours, 2.36 days */
4088 218415, /* 60.67 hours, 2.53 days */
4089 233517, /* 64.87 hours, 2.70 days */
4090 249664, /* 69.35 hours, 2.89 days */
4091 266926, /* 74.15 hours, 3.09 days */
4092 285383, /* 79.27 hours, 3.30 days */
4093 305116, /* 84.75 hours, 3.53 days */
4094 326213, /* 90.61 hours, 3.78 days */
4095 348769, /* 96.88 hours, 4.04 days */
4096 372885, /* 103.58 hours, 4.32 days */
4097 398668, /* 110.74 hours, 4.61 days */
4098 426234, /* 118.40 hours, 4.93 days */
4099 455705, /* 126.58 hours, 5.27 days */
4100 487215, /* 135.34 hours, 5.64 days */
4101 520904, /* 144.70 hours, 6.03 days */
4102 556921, /* 154.70 hours, 6.45 days */
4103 595430, /* 165.40 hours, 6.89 days */
4104 636601, /* 176.83 hours, 7.37 days */
4105 680618, /* 189.06 hours, 7.88 days */
4106 727680, /* 202.13 hours, 8.42 days */
4107 777995, /* 216.11 hours, 9.00 days */
4108 831789, /* 231.05 hours, 9.63 days */
4109 889303, /* 247.03 hours, 10.29 days */
4110 950794, /* 264.11 hours, 11.00 days */
4111 1016537, /* 282.37 hours, 11.77 days */
4112 1086825, /* 301.90 hours, 12.58 days */
4113 1161973, /* 322.77 hours, 13.45 days */
4114 1242318, /* 345.09 hours, 14.38 days */
4115 1328218, /* 368.95 hours, 15.37 days */
4116 1420057, /* 394.46 hours, 16.44 days */
4117 1518247, /* 421.74 hours, 17.57 days */
4118 1623226, /* 450.90 hours, 18.79 days */
4119 1735464, /* 482.07 hours, 20.09 days */
4120 1855462, /* 515.41 hours, 21.48 days */
4121 1983758, /* 551.04 hours, 22.96 days */
4122 2120925, /* 589.15 hours, 24.55 days */
4123 2267576, /* 629.88 hours, 26.25 days */
4124 2424367, /* 673.44 hours, 28.06 days */
4126 }; /* 720.00 hours, 30.00 days */
4128 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
4129 * returns the corresponding end time. There are four simple cases to be
4130 * handled. The first is a life of 0xff, meaning no expiration, and results in
4131 * an end time of 0xffffffff. The second is when life is less than the values
4132 * covered by the table. In this case, the end time is the start time plus the
4133 * number of 5 minute intervals specified by life. The third case returns
4134 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
4135 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
4136 * table to extract the lifetime in seconds, which is added to start to produce
4140 life_to_time(afs_uint32 start, unsigned char life)
4144 if (life == TKTLIFENOEXPIRE)
4146 if (life < TKTLIFEMINFIXED)
4147 return start + life * 5 * 60;
4148 if (life > TKTLIFEMAXFIXED)
4149 return start + MAXTKTLIFETIME;
4150 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
4151 return start + realLife;
4154 /* time_to_life - takes start and end times for the ticket and returns a
4155 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
4156 * lifetimes above 127*5minutes. First, the special case of (end ==
4157 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
4158 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
4159 * less than the first table entry are handled by rounding the requested
4160 * lifetime *up* to the next 5 minute interval. The final step is to search
4161 * the table for the smallest entry *greater than or equal* to the requested
4162 * entry. The actual code is prepared to handle the case where the table is
4163 * unordered but that it an unnecessary frill. */
4165 static unsigned char
4166 time_to_life(afs_uint32 start, afs_uint32 end)
4168 int lifetime = end - start;
4172 if (end == NEVERDATE)
4173 return TKTLIFENOEXPIRE;
4174 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
4176 if (lifetime < tkt_lifetimes[0])
4177 return (lifetime + 5 * 60 - 1) / (5 * 60);
4179 best = MAXKTCTICKETLIFETIME;
4180 for (i = 0; i < TKTLIFENUMFIXED; i++)
4181 if (tkt_lifetimes[i] >= lifetime) {
4182 int diff = tkt_lifetimes[i] - lifetime;
4190 return best_i + TKTLIFEMINFIXED;