2 * Copyright (c) 2004, 2005, 2006, 2007, 2008 Secure Endpoints Inc.
3 * Copyright (c) 2003 SkyRope, LLC
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * - Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * - Neither the name of Skyrope, LLC nor the names of its contributors may be
15 * used to endorse or promote products derived from this software without
16 * specific prior written permission from Skyrope, LLC.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Portions of this code are derived from portions of the MIT
31 * Leash Ticket Manager and LoadFuncs utilities. For these portions the
32 * following copyright applies.
34 * Copyright (c) 2003,2004 by the Massachusetts Institute of Technology.
35 * All rights reserved.
37 * Export of this software from the United States of America may
38 * require a specific license from the United States Government.
39 * It is the responsibility of any person or organization contemplating
40 * export to obtain such a license before exporting.
42 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
43 * distribute this software and its documentation for any purpose and
44 * without fee is hereby granted, provided that the above copyright
45 * notice appear in all copies and that both that copyright notice and
46 * this permission notice appear in supporting documentation, and that
47 * the name of M.I.T. not be used in advertising or publicity pertaining
48 * to distribution of the software without specific, written prior
49 * permission. Furthermore if you modify this software you must label
50 * your software as modified software and not distribute it in such a
51 * fashion that it might be confused with the original M.I.T. software.
52 * M.I.T. makes no representations about the suitability of
53 * this software for any purpose. It is provided "as is" without express
54 * or implied warranty.
64 #include <afsconfig.h>
65 #include <afs/param.h>
69 #include <afs/ptserver.h>
70 #include <afs/ptuser.h>
72 #include <afs/com_err.h>
74 #include <WINNT\afsreg.h>
78 #include "afskfw-int.h"
86 * TIMING _____________________________________________________________________
90 #define cminREMIND_TEST 1 // test every minute for expired creds
91 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
92 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
93 #define cminMINLIFE 30 // minimum life of Kerberos creds
95 #define c100ns1SECOND (LONGLONG)10000000
96 #define cmsec1SECOND 1000
97 #define cmsec1MINUTE 60000
98 #define csec1MINUTE 60
100 /* Function Pointer Declarations for Delayed Loading */
102 DECL_FUNC_PTR(cc_initialize);
103 DECL_FUNC_PTR(cc_shutdown);
104 DECL_FUNC_PTR(cc_get_NC_info);
105 DECL_FUNC_PTR(cc_free_NC_info);
109 DECL_FUNC_PTR(Leash_get_default_lifetime);
110 DECL_FUNC_PTR(Leash_get_default_forwardable);
111 DECL_FUNC_PTR(Leash_get_default_renew_till);
112 DECL_FUNC_PTR(Leash_get_default_noaddresses);
113 DECL_FUNC_PTR(Leash_get_default_proxiable);
114 DECL_FUNC_PTR(Leash_get_default_publicip);
115 DECL_FUNC_PTR(Leash_get_default_use_krb4);
116 DECL_FUNC_PTR(Leash_get_default_life_min);
117 DECL_FUNC_PTR(Leash_get_default_life_max);
118 DECL_FUNC_PTR(Leash_get_default_renew_min);
119 DECL_FUNC_PTR(Leash_get_default_renew_max);
120 DECL_FUNC_PTR(Leash_get_default_renewable);
121 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
125 DECL_FUNC_PTR(krb5_change_password);
126 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
127 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
128 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
129 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
130 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
131 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
132 DECL_FUNC_PTR(krb5_get_init_creds_password);
133 DECL_FUNC_PTR(krb5_build_principal_ext);
134 DECL_FUNC_PTR(krb5_cc_get_name);
135 DECL_FUNC_PTR(krb5_cc_resolve);
136 DECL_FUNC_PTR(krb5_cc_default);
137 DECL_FUNC_PTR(krb5_cc_default_name);
138 DECL_FUNC_PTR(krb5_cc_set_default_name);
139 DECL_FUNC_PTR(krb5_cc_initialize);
140 DECL_FUNC_PTR(krb5_cc_destroy);
141 DECL_FUNC_PTR(krb5_cc_close);
142 DECL_FUNC_PTR(krb5_cc_store_cred);
143 DECL_FUNC_PTR(krb5_cc_copy_creds);
144 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
145 DECL_FUNC_PTR(krb5_cc_get_principal);
146 DECL_FUNC_PTR(krb5_cc_start_seq_get);
147 DECL_FUNC_PTR(krb5_cc_next_cred);
148 DECL_FUNC_PTR(krb5_cc_end_seq_get);
149 DECL_FUNC_PTR(krb5_cc_remove_cred);
150 DECL_FUNC_PTR(krb5_cc_set_flags);
151 DECL_FUNC_PTR(krb5_cc_get_type);
152 DECL_FUNC_PTR(krb5_free_context);
153 DECL_FUNC_PTR(krb5_free_cred_contents);
154 DECL_FUNC_PTR(krb5_free_principal);
155 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
156 DECL_FUNC_PTR(krb5_init_context);
157 DECL_FUNC_PTR(krb5_parse_name);
158 DECL_FUNC_PTR(krb5_timeofday);
159 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
160 DECL_FUNC_PTR(krb5_unparse_name);
161 DECL_FUNC_PTR(krb5_get_credentials);
162 DECL_FUNC_PTR(krb5_mk_req);
163 DECL_FUNC_PTR(krb5_sname_to_principal);
164 DECL_FUNC_PTR(krb5_get_credentials_renew);
165 DECL_FUNC_PTR(krb5_free_data);
166 DECL_FUNC_PTR(krb5_free_data_contents);
167 DECL_FUNC_PTR(krb5_free_unparsed_name);
168 DECL_FUNC_PTR(krb5_os_localaddr);
169 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
170 DECL_FUNC_PTR(krb5_copy_data);
171 DECL_FUNC_PTR(krb5_free_creds);
172 DECL_FUNC_PTR(krb5_build_principal);
173 DECL_FUNC_PTR(krb5_get_renewed_creds);
174 DECL_FUNC_PTR(krb5_get_default_config_files);
175 DECL_FUNC_PTR(krb5_free_config_files);
176 DECL_FUNC_PTR(krb5_get_default_realm);
177 DECL_FUNC_PTR(krb5_free_default_realm);
178 DECL_FUNC_PTR(krb5_free_ticket);
179 DECL_FUNC_PTR(krb5_decode_ticket);
180 DECL_FUNC_PTR(krb5_get_host_realm);
181 DECL_FUNC_PTR(krb5_free_host_realm);
182 DECL_FUNC_PTR(krb5_free_addresses);
183 DECL_FUNC_PTR(krb5_c_random_make_octets);
185 // Krb5 KFW 3.2 functions
186 DECL_FUNC_PTR(krb5_get_error_message);
187 DECL_FUNC_PTR(krb5_free_error_message);
191 DECL_FUNC_PTR(krb524_init_ets);
192 DECL_FUNC_PTR(krb524_convert_creds_kdc);
197 DECL_FUNC_PTR(krb_get_cred);
198 DECL_FUNC_PTR(tkt_string);
199 DECL_FUNC_PTR(krb_get_tf_realm);
200 DECL_FUNC_PTR(krb_mk_req);
204 DECL_FUNC_PTR(com_err);
205 DECL_FUNC_PTR(error_message);
208 DECL_FUNC_PTR(profile_init);
209 DECL_FUNC_PTR(profile_release);
210 DECL_FUNC_PTR(profile_get_subsection_names);
211 DECL_FUNC_PTR(profile_free_list);
212 DECL_FUNC_PTR(profile_get_string);
213 DECL_FUNC_PTR(profile_release_string);
216 DECL_FUNC_PTR(OpenSCManagerA);
217 DECL_FUNC_PTR(OpenServiceA);
218 DECL_FUNC_PTR(QueryServiceStatus);
219 DECL_FUNC_PTR(CloseServiceHandle);
221 DECL_FUNC_PTR(LsaNtStatusToWinError);
222 #endif /* USE_MS2MIT */
226 DECL_FUNC_PTR(LsaConnectUntrusted);
227 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
228 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
229 DECL_FUNC_PTR(LsaFreeReturnBuffer);
230 DECL_FUNC_PTR(LsaGetLogonSessionData);
231 #endif /* USE_MS2MIT */
234 FUNC_INFO ccapi_fi[] = {
235 MAKE_FUNC_INFO(cc_initialize),
236 MAKE_FUNC_INFO(cc_shutdown),
237 MAKE_FUNC_INFO(cc_get_NC_info),
238 MAKE_FUNC_INFO(cc_free_NC_info),
243 FUNC_INFO leash_fi[] = {
244 MAKE_FUNC_INFO(Leash_get_default_lifetime),
245 MAKE_FUNC_INFO(Leash_get_default_renew_till),
246 MAKE_FUNC_INFO(Leash_get_default_forwardable),
247 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
248 MAKE_FUNC_INFO(Leash_get_default_proxiable),
249 MAKE_FUNC_INFO(Leash_get_default_publicip),
250 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
251 MAKE_FUNC_INFO(Leash_get_default_life_min),
252 MAKE_FUNC_INFO(Leash_get_default_life_max),
253 MAKE_FUNC_INFO(Leash_get_default_renew_min),
254 MAKE_FUNC_INFO(Leash_get_default_renew_max),
255 MAKE_FUNC_INFO(Leash_get_default_renewable),
259 FUNC_INFO leash_opt_fi[] = {
260 MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
265 FUNC_INFO k5_fi[] = {
266 MAKE_FUNC_INFO(krb5_change_password),
267 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
268 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
269 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
270 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
271 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
272 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
273 MAKE_FUNC_INFO(krb5_get_init_creds_password),
274 MAKE_FUNC_INFO(krb5_build_principal_ext),
275 MAKE_FUNC_INFO(krb5_cc_get_name),
276 MAKE_FUNC_INFO(krb5_cc_resolve),
277 MAKE_FUNC_INFO(krb5_cc_default),
278 MAKE_FUNC_INFO(krb5_cc_default_name),
279 MAKE_FUNC_INFO(krb5_cc_set_default_name),
280 MAKE_FUNC_INFO(krb5_cc_initialize),
281 MAKE_FUNC_INFO(krb5_cc_destroy),
282 MAKE_FUNC_INFO(krb5_cc_close),
283 MAKE_FUNC_INFO(krb5_cc_copy_creds),
284 MAKE_FUNC_INFO(krb5_cc_store_cred),
285 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
286 MAKE_FUNC_INFO(krb5_cc_get_principal),
287 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
288 MAKE_FUNC_INFO(krb5_cc_next_cred),
289 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
290 MAKE_FUNC_INFO(krb5_cc_remove_cred),
291 MAKE_FUNC_INFO(krb5_cc_set_flags),
292 MAKE_FUNC_INFO(krb5_cc_get_type),
293 MAKE_FUNC_INFO(krb5_free_context),
294 MAKE_FUNC_INFO(krb5_free_cred_contents),
295 MAKE_FUNC_INFO(krb5_free_principal),
296 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
297 MAKE_FUNC_INFO(krb5_init_context),
298 MAKE_FUNC_INFO(krb5_parse_name),
299 MAKE_FUNC_INFO(krb5_timeofday),
300 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
301 MAKE_FUNC_INFO(krb5_unparse_name),
302 MAKE_FUNC_INFO(krb5_get_credentials),
303 MAKE_FUNC_INFO(krb5_mk_req),
304 MAKE_FUNC_INFO(krb5_sname_to_principal),
305 MAKE_FUNC_INFO(krb5_get_credentials_renew),
306 MAKE_FUNC_INFO(krb5_free_data),
307 MAKE_FUNC_INFO(krb5_free_data_contents),
308 MAKE_FUNC_INFO(krb5_free_unparsed_name),
309 MAKE_FUNC_INFO(krb5_os_localaddr),
310 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
311 MAKE_FUNC_INFO(krb5_copy_data),
312 MAKE_FUNC_INFO(krb5_free_creds),
313 MAKE_FUNC_INFO(krb5_build_principal),
314 MAKE_FUNC_INFO(krb5_get_renewed_creds),
315 MAKE_FUNC_INFO(krb5_free_addresses),
316 MAKE_FUNC_INFO(krb5_get_default_config_files),
317 MAKE_FUNC_INFO(krb5_free_config_files),
318 MAKE_FUNC_INFO(krb5_get_default_realm),
319 MAKE_FUNC_INFO(krb5_free_default_realm),
320 MAKE_FUNC_INFO(krb5_free_ticket),
321 MAKE_FUNC_INFO(krb5_decode_ticket),
322 MAKE_FUNC_INFO(krb5_get_host_realm),
323 MAKE_FUNC_INFO(krb5_free_host_realm),
324 MAKE_FUNC_INFO(krb5_free_addresses),
325 MAKE_FUNC_INFO(krb5_c_random_make_octets),
329 FUNC_INFO k5_kfw_32_fi[] = {
330 MAKE_FUNC_INFO(krb5_get_error_message),
331 MAKE_FUNC_INFO(krb5_free_error_message),
336 FUNC_INFO k4_fi[] = {
337 MAKE_FUNC_INFO(krb_get_cred),
338 MAKE_FUNC_INFO(krb_get_tf_realm),
339 MAKE_FUNC_INFO(krb_mk_req),
340 MAKE_FUNC_INFO(tkt_string),
346 FUNC_INFO k524_fi[] = {
347 MAKE_FUNC_INFO(krb524_init_ets),
348 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
353 FUNC_INFO profile_fi[] = {
354 MAKE_FUNC_INFO(profile_init),
355 MAKE_FUNC_INFO(profile_release),
356 MAKE_FUNC_INFO(profile_get_subsection_names),
357 MAKE_FUNC_INFO(profile_free_list),
358 MAKE_FUNC_INFO(profile_get_string),
359 MAKE_FUNC_INFO(profile_release_string),
363 FUNC_INFO ce_fi[] = {
364 MAKE_FUNC_INFO(com_err),
365 MAKE_FUNC_INFO(error_message),
369 FUNC_INFO service_fi[] = {
370 MAKE_FUNC_INFO(OpenSCManagerA),
371 MAKE_FUNC_INFO(OpenServiceA),
372 MAKE_FUNC_INFO(QueryServiceStatus),
373 MAKE_FUNC_INFO(CloseServiceHandle),
375 MAKE_FUNC_INFO(LsaNtStatusToWinError),
376 #endif /* USE_MS2MIT */
381 FUNC_INFO lsa_fi[] = {
382 MAKE_FUNC_INFO(LsaConnectUntrusted),
383 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
384 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
385 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
386 MAKE_FUNC_INFO(LsaGetLogonSessionData),
389 #endif /* USE_MS2MIT */
391 /* Static Prototypes */
392 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
393 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *, unsigned short);
394 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
395 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
396 void *data, const char *name, const char *banner, int num_prompts,
397 krb5_prompt prompts[]);
400 /* Static Declarations */
401 static int inited = 0;
402 static int mid_cnt = 0;
403 static struct textField * mid_tb = NULL;
404 static HINSTANCE hKrb5 = 0;
405 static HINSTANCE hKrb5_kfw_32 = 0;
407 static HINSTANCE hKrb4 = 0;
408 #endif /* USE_KRB4 */
410 static HINSTANCE hKrb524 = 0;
413 static HINSTANCE hSecur32 = 0;
414 #endif /* USE_MS2MIT */
415 static HINSTANCE hAdvApi32 = 0;
416 static HINSTANCE hComErr = 0;
417 static HINSTANCE hService = 0;
418 static HINSTANCE hProfile = 0;
420 static HINSTANCE hLeash = 0;
421 static HINSTANCE hLeashOpt = 0;
423 static HINSTANCE hCCAPI = 0;
424 static struct principal_ccache_data * princ_cc_data = NULL;
425 static struct cell_principal_map * cell_princ_map = NULL;
428 #define DEFAULT_LIFETIME pLeash_get_default_lifetime()
430 #define DEFAULT_LIFETIME (24 * 60)
436 static int inited = 0;
439 char mutexName[MAX_PATH];
440 HANDLE hMutex = NULL;
442 StringCbPrintf( mutexName, sizeof(mutexName), "AFS KFW Init pid=%d", getpid());
444 hMutex = CreateMutex( NULL, TRUE, mutexName );
445 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
446 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
452 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
453 LoadFuncs(KRB5_DLL, k5_kfw_32_fi, &hKrb5_kfw_32, 0, 1, 0, 0);
454 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
455 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
457 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
458 #endif /* USE_KRB4 */
459 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
461 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
462 #endif /* USE_MS2MIT */
464 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
467 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
468 LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
470 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
472 if ( KFW_is_available() ) {
473 char rootcell[CELL_MAXNAMELEN+1];
475 KFW_import_windows_lsa();
476 #endif /* USE_MS2MIT */
477 KFW_import_ccache_data();
478 KFW_AFS_renew_expiring_tokens();
480 /* WIN32 NOTE: no way to get max chars */
481 if (!cm_GetRootCellName(rootcell))
482 KFW_AFS_renew_token_for_cell(rootcell);
485 ReleaseMutex(hMutex);
488 initialize_KTC_error_table();
489 initialize_PT_error_table();
498 FreeLibrary(hLeashOpt);
504 FreeLibrary(hKrb524);
510 FreeLibrary(hSecur32);
511 #endif /* USE_MS2MIT */
513 FreeLibrary(hService);
515 FreeLibrary(hComErr);
517 FreeLibrary(hProfile);
521 #endif /* USE_KRB4 */
525 FreeLibrary(hKrb5_kfw_32);
528 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
531 static int init = TRUE;
532 static int bIsWow64 = FALSE;
536 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
538 hModule = GetModuleHandle(TEXT("kernel32"));
540 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
542 if (NULL != fnIsWow64Process)
544 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
546 // on error, assume FALSE.
547 // in other words, do nothing.
550 FreeLibrary(hModule);
558 KFW_accept_dotted_usernames(void)
564 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
565 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
566 if (code == ERROR_SUCCESS) {
568 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
569 (BYTE *) &value, &len);
570 RegCloseKey(parmKey);
572 if (code != ERROR_SUCCESS) {
573 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
574 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
575 if (code == ERROR_SUCCESS) {
577 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
578 (BYTE *) &value, &len);
579 RegCloseKey (parmKey);
593 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
594 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
595 if (code == ERROR_SUCCESS) {
596 len = sizeof(use524);
597 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
598 (BYTE *) &use524, &len);
599 RegCloseKey(parmKey);
601 if (code != ERROR_SUCCESS) {
602 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
603 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
604 if (code == ERROR_SUCCESS) {
605 len = sizeof(use524);
606 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
607 (BYTE *) &use524, &len);
608 RegCloseKey (parmKey);
615 KFW_is_available(void)
621 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
622 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
623 if (code == ERROR_SUCCESS) {
624 len = sizeof(enableKFW);
625 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
626 (BYTE *) &enableKFW, &len);
627 RegCloseKey (parmKey);
630 if (code != ERROR_SUCCESS) {
631 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
632 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
633 if (code == ERROR_SUCCESS) {
634 len = sizeof(enableKFW);
635 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
636 (BYTE *) &enableKFW, &len);
637 RegCloseKey (parmKey);
645 if ( hKrb5 && hComErr && hService &&
648 #endif /* USE_MS2MIT */
661 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
662 int FreeContextFlag, krb5_context * ctx,
667 int krb5Error = ((int)(rc & 255));
679 if (pkrb5_get_error_message)
680 errText = pkrb5_get_error_message(ctx, rc);
682 errText = perror_message(rc);
683 StringCbPrintf(message, sizeof(message),
684 "%s\n(Kerberos error %ld)\n\n%s failed",
688 if (pkrb5_free_error_message)
689 pkrb5_free_error_message(ctx, (char *)errText);
691 if ( IsDebuggerPresent() )
692 OutputDebugString(message);
694 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
697 if (FreeContextFlag == 1)
699 if (ctx && *ctx != NULL)
701 if (cache && *cache != NULL) {
702 pkrb5_cc_close(*ctx, *cache);
706 pkrb5_free_context(*ctx);
715 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
717 struct principal_ccache_data * next = princ_cc_data;
718 krb5_principal principal = 0;
720 const char * ccname = NULL;
721 const char * cctype = NULL;
722 char * ccfullname = NULL;
723 krb5_error_code code = 0;
724 krb5_error_code cc_code = 0;
730 if (ctx == 0 || cc == 0)
733 code = pkrb5_cc_get_principal(ctx, cc, &principal);
736 code = pkrb5_unparse_name(ctx, principal, &pname);
737 if ( code ) goto cleanup;
739 ccname = pkrb5_cc_get_name(ctx, cc);
740 if (!ccname) goto cleanup;
742 cctype = pkrb5_cc_get_type(ctx, cc);
743 if (!cctype) goto cleanup;
745 ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
746 if (!ccfullname) goto cleanup;
748 StringCbPrintf(ccfullname, sizeof(ccfullname), "%s:%s", cctype, ccname);
750 // Search the existing list to see if we have a match
752 for ( ; next ; next = next->next ) {
753 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
758 // If not, match add a new node to the beginning of the list and assign init it
760 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
761 next->next = princ_cc_data;
762 princ_cc_data = next;
763 next->principal = _strdup(pname);
764 next->ccache_name = ccfullname;
766 next->from_lsa = lsa;
768 next->expiration_time = 0;
772 flags = 0; // turn off OPENCLOSE mode
773 code = pkrb5_cc_set_flags(ctx, cc, flags);
774 if ( code ) goto cleanup;
776 code = pkrb5_timeofday(ctx, &now);
778 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
779 if (cc_code) goto cleanup;
781 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
782 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
784 // we found the ticket we are looking for
785 // check validity of timestamp
786 // We add a 5 minutes fudge factor to compensate for potential
787 // clock skew errors between the KDC and client OS
789 valid = ((creds.times.starttime > 0) &&
790 now >= (creds.times.starttime - 300) &&
791 now < (creds.times.endtime + 300) &&
792 !(creds.ticket_flags & TKT_FLG_INVALID));
794 if ( next->from_lsa) {
796 next->expiration_time = creds.times.endtime;
798 } else if ( valid ) {
800 next->expiration_time = creds.times.endtime;
801 next->renew = (creds.times.renew_till > creds.times.endtime) &&
802 (creds.ticket_flags & TKT_FLG_RENEWABLE);
805 next->expiration_time = 0;
809 pkrb5_free_cred_contents(ctx, &creds);
810 cc_code = KRB5_CC_END;
813 pkrb5_free_cred_contents(ctx, &creds);
816 if (cc_code == KRB5_CC_END) {
817 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
818 if (code) goto cleanup;
822 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
823 code = pkrb5_cc_set_flags(ctx, cc, flags);
828 pkrb5_free_unparsed_name(ctx,pname);
830 pkrb5_free_principal(ctx,principal);
834 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
836 struct principal_ccache_data * next = princ_cc_data;
837 char * response = NULL;
839 if ( !principal || !ccache )
843 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
845 // we always want to prefer the MS Kerberos LSA cache or
846 // the cache afscreds created specifically for the principal
847 // if the current entry is either one, drop the previous find
848 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
851 response = _strdup(next->ccache_name);
852 // MS Kerberos LSA is our best option so use it and quit
853 if ( next->from_lsa )
867 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
869 struct principal_ccache_data ** next = &princ_cc_data;
871 if ( !pname && !ccname )
875 if ( !strcmp((*next)->principal,pname) ||
876 !strcmp((*next)->ccache_name,ccname) ) {
878 free((*next)->principal);
879 free((*next)->ccache_name);
881 (*next) = (*next)->next;
888 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
890 struct cell_principal_map * next = cell_princ_map;
892 // Search the existing list to see if we have a match
894 for ( ; next ; next = next->next ) {
895 if ( !strcmp(next->cell, cell) ) {
896 if ( !strcmp(next->principal,pname) ) {
897 next->active = active;
900 // OpenAFS currently has a restriction of one active token per cell
901 // Therefore, whenever we update the table with a new active cell we
902 // must mark all of the other principal to cell entries as inactive.
910 // If not, match add a new node to the beginning of the list and assign init it
912 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
913 next->next = cell_princ_map;
914 cell_princ_map = next;
915 next->principal = _strdup(pname);
916 next->cell = _strdup(cell);
917 next->active = active;
922 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
924 struct cell_principal_map ** next = &cell_princ_map;
926 if ( !pname && !cell )
930 if ( !strcmp((*next)->principal,pname) ||
931 !strcmp((*next)->cell,cell) ) {
933 free((*next)->principal);
936 (*next) = (*next)->next;
942 // Returns (if possible) a principal which has been known in
943 // the past to have been used to obtain tokens for the specified
945 // TODO: Attempt to return one which has not yet expired by checking
946 // the principal/ccache data
948 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
950 struct cell_principal_map * next_map = cell_princ_map;
951 const char * princ = NULL;
958 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
961 next_map = next_map->next;
964 if ( !principals || !count )
967 *principals = (char **) malloc(sizeof(char *) * count);
968 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
970 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
971 (*principals)[i++] = _strdup(next_map->principal);
978 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
981 struct cell_principal_map * next_map = cell_princ_map;
982 const char * princ = NULL;
988 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
991 next_map = next_map->next;
997 *cells = (char **) malloc(sizeof(char *) * count);
998 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
1000 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
1001 (*cells)[i++] = _strdup(next_map->cell);
1007 /* Given a principal return an existing ccache or create one and return */
1009 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
1011 krb5_context ctx = NULL;
1012 char * pname = NULL;
1013 char * ccname = NULL;
1014 krb5_error_code code;
1016 if (!pkrb5_init_context)
1017 return KRB5_CONFIG_CANTOPEN;
1022 code = pkrb5_init_context(&ctx);
1023 if (code) goto cleanup;
1027 code = pkrb5_unparse_name(ctx, principal, &pname);
1028 if (code) goto cleanup;
1030 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
1031 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
1032 size_t len = strlen(pname) + 5;
1033 ccname = (char *)malloc(len);
1034 StringCbPrintf(ccname, len, "API:%s", pname);
1036 code = pkrb5_cc_resolve(ctx, ccname, cc);
1038 code = pkrb5_cc_default(ctx, cc);
1039 if (code) goto cleanup;
1046 pkrb5_free_unparsed_name(ctx,pname);
1047 if (ctx && (ctx != alt_ctx))
1048 pkrb5_free_context(ctx);
1053 // Import Microsoft Credentials into a new MIT ccache
1055 KFW_import_windows_lsa(void)
1057 krb5_context ctx = NULL;
1058 krb5_ccache cc = NULL;
1059 krb5_principal princ = NULL;
1060 char * pname = NULL;
1061 krb5_data * princ_realm;
1062 krb5_error_code code;
1063 char cell[128]="", realm[128]="", *def_realm = 0;
1065 DWORD dwMsLsaImport;
1067 if (!pkrb5_init_context)
1070 code = pkrb5_init_context(&ctx);
1071 if (code) goto cleanup;
1073 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
1074 if (code) goto cleanup;
1076 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
1078 code = pkrb5_cc_get_principal(ctx, cc, &princ);
1079 if ( code ) goto cleanup;
1082 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
1086 switch ( dwMsLsaImport ) {
1087 case 0: /* do not import */
1089 case 1: /* always import */
1091 case 2: { /* matching realm */
1092 char ms_realm[128] = "", *r;
1095 for ( r=ms_realm, j=0; j<krb5_princ_realm(ctx, princ)->length; r++, j++ ) {
1096 *r = krb5_princ_realm(ctx, princ)->data[j];
1100 if (code = pkrb5_get_default_realm(ctx, &def_realm))
1103 if (strcmp(def_realm, ms_realm))
1111 code = pkrb5_unparse_name(ctx,princ,&pname);
1112 if ( code ) goto cleanup;
1114 princ_realm = krb5_princ_realm(ctx, princ);
1115 for ( i=0; i<princ_realm->length; i++ ) {
1116 realm[i] = princ_realm->data[i];
1117 cell[i] = tolower(princ_realm->data[i]);
1122 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, DEFAULT_LIFETIME, NULL);
1123 if ( IsDebuggerPresent() ) {
1125 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1126 OutputDebugString(message);
1128 if ( code ) goto cleanup;
1130 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1134 pkrb5_free_unparsed_name(ctx,pname);
1136 pkrb5_free_principal(ctx,princ);
1138 pkrb5_free_default_realm(ctx, def_realm);
1140 pkrb5_cc_close(ctx,cc);
1142 pkrb5_free_context(ctx);
1144 #endif /* USE_MS2MIT */
1146 // If there are existing MIT credentials, copy them to a new
1147 // ccache named after the principal
1149 // Enumerate all existing MIT ccaches and construct entries
1150 // in the principal_ccache table
1152 // Enumerate all existing AFS Tokens and construct entries
1153 // in the cell_principal table
1155 KFW_import_ccache_data(void)
1157 krb5_context ctx = NULL;
1158 krb5_ccache cc = NULL;
1159 krb5_principal principal = NULL;
1161 krb5_error_code code;
1162 krb5_error_code cc_code;
1164 apiCB * cc_ctx = NULL;
1165 struct _infoNC ** pNCi = NULL;
1168 if ( !pcc_initialize )
1171 if ( IsDebuggerPresent() )
1172 OutputDebugString("KFW_import_ccache_data()\n");
1174 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1175 if (code) goto cleanup;
1177 code = pcc_get_NC_info(cc_ctx, &pNCi);
1178 if (code) goto cleanup;
1180 code = pkrb5_init_context(&ctx);
1181 if (code) goto cleanup;
1183 for ( i=0; pNCi[i]; i++ ) {
1184 if ( pNCi[i]->vers != CC_CRED_V5 )
1186 if ( IsDebuggerPresent() ) {
1187 OutputDebugString("Principal: ");
1188 OutputDebugString(pNCi[i]->principal);
1189 OutputDebugString(" in ccache ");
1190 OutputDebugString(pNCi[i]->name);
1191 OutputDebugString("\n");
1193 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1194 && strcmp(pNCi[i]->name,LSA_CCNAME)
1197 for ( j=0; pNCi[j]; j++ ) {
1198 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1204 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1205 if (code) goto loop_cleanup;
1208 krb5_ccache oldcc = 0;
1210 if ( IsDebuggerPresent() )
1211 OutputDebugString("copying ccache data to new ccache\n");
1213 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1214 if (code) goto loop_cleanup;
1215 code = pkrb5_cc_initialize(ctx, cc, principal);
1216 if (code) goto loop_cleanup;
1218 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1219 if (code) goto loop_cleanup;
1220 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1222 code = pkrb5_cc_close(ctx,cc);
1224 code = pkrb5_cc_close(ctx,oldcc);
1226 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1229 code = pkrb5_cc_close(ctx,oldcc);
1232 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1233 if (code) goto loop_cleanup;
1236 flags = 0; // turn off OPENCLOSE mode
1237 code = pkrb5_cc_set_flags(ctx, cc, flags);
1238 if ( code ) goto cleanup;
1240 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1242 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1243 if (cc_code) goto cleanup;
1245 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1246 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1247 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1248 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1249 if ( sname && cell && !strcmp("afs",sname->data) ) {
1250 struct ktc_principal aserver;
1251 struct ktc_principal aclient;
1252 struct ktc_token atoken;
1255 if ( IsDebuggerPresent() ) {
1256 OutputDebugString("Found AFS ticket: ");
1257 OutputDebugString(sname->data);
1259 OutputDebugString("/");
1260 OutputDebugString(cell->data);
1262 OutputDebugString("@");
1263 OutputDebugString(realm->data);
1264 OutputDebugString("\n");
1267 memset(&aserver, '\0', sizeof(aserver));
1268 StringCbCopyN( aserver.name, sizeof(aserver.name),
1269 sname->data, sizeof(aserver.name) - 1);
1270 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
1271 cell->data, sizeof(aserver.cell) - 1);
1273 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1275 // Found a token in AFS Client Server which matches
1276 char pname[128], *p, *q;
1277 for ( p=pname, q=aclient.name; *q; p++, q++)
1279 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1283 if ( IsDebuggerPresent() ) {
1284 OutputDebugString("Found AFS token: ");
1285 OutputDebugString(pname);
1286 OutputDebugString("\n");
1289 if ( strcmp(pname,pNCi[i]->principal) )
1291 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1293 // Attempt to import it
1294 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1296 if ( IsDebuggerPresent() ) {
1297 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1300 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data, DEFAULT_LIFETIME, NULL);
1301 if ( IsDebuggerPresent() ) {
1303 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1304 OutputDebugString(message);
1307 } else if ( IsDebuggerPresent() ) {
1308 OutputDebugString("Found ticket: ");
1309 OutputDebugString(sname->data);
1310 if ( cell && cell->data ) {
1311 OutputDebugString("/");
1312 OutputDebugString(cell->data);
1314 OutputDebugString("@");
1315 OutputDebugString(realm->data);
1316 OutputDebugString("\n");
1318 pkrb5_free_cred_contents(ctx, &creds);
1321 if (cc_code == KRB5_CC_END) {
1322 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1323 if (cc_code) goto loop_cleanup;
1327 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1328 code = pkrb5_cc_set_flags(ctx, cc, flags);
1330 pkrb5_cc_close(ctx,cc);
1334 pkrb5_free_principal(ctx,principal);
1341 pkrb5_free_context(ctx);
1343 pcc_free_NC_info(cc_ctx, &pNCi);
1345 pcc_shutdown(&cc_ctx);
1350 KFW_AFS_get_cred( char * username,
1357 static char reason[1024]="";
1358 krb5_context ctx = NULL;
1359 krb5_ccache cc = NULL;
1360 char * realm = NULL, * userrealm = NULL;
1361 krb5_principal principal = NULL;
1362 char * pname = NULL;
1363 krb5_error_code code;
1364 char local_cell[CELL_MAXNAMELEN+1];
1365 char **cells = NULL;
1367 struct afsconf_cell cellconfig;
1370 if (!pkrb5_init_context)
1371 return KRB5_CONFIG_CANTOPEN;
1373 if ( IsDebuggerPresent() ) {
1374 OutputDebugString("KFW_AFS_get_cred for token ");
1375 OutputDebugString(username);
1376 OutputDebugString(" in cell ");
1377 OutputDebugString(cell);
1378 OutputDebugString("\n");
1381 memset(&cellconfig, 0, sizeof(cellconfig));
1383 code = pkrb5_init_context(&ctx);
1384 if ( code ) goto cleanup;
1386 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1387 if ( code ) goto cleanup;
1389 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1391 userrealm = strchr(username,'@');
1393 pname = strdup(username);
1394 if (!KFW_accept_dotted_usernames()) {
1395 userrealm = strchr(pname, '@');
1398 /* handle kerberos iv notation */
1399 while ( dot = strchr(pname,'.') ) {
1406 size_t len = strlen(username) + strlen(realm) + 2;
1407 pname = malloc(len);
1408 if (pname == NULL) {
1409 code = KRB5KRB_ERR_GENERIC;
1412 StringCbCopy(pname, len, username);
1414 if (!KFW_accept_dotted_usernames()) {
1415 /* handle kerberos iv notation */
1416 while ( dot = strchr(pname,'.') ) {
1420 StringCbCat( pname, len, "@");
1421 StringCbCat( pname, len, realm);
1423 if ( IsDebuggerPresent() ) {
1424 OutputDebugString("Realm of Cell: ");
1425 OutputDebugString(realm);
1426 OutputDebugString("\n");
1427 OutputDebugString("Realm of User: ");
1428 OutputDebugString(userrealm?userrealm:"<NULL>");
1429 OutputDebugString("\n");
1432 code = pkrb5_parse_name(ctx, pname, &principal);
1433 if ( code ) goto cleanup;
1435 code = KFW_get_ccache(ctx, principal, &cc);
1436 if ( code ) goto cleanup;
1438 if ( lifetime == 0 )
1439 lifetime = DEFAULT_LIFETIME;
1441 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1442 if ( IsDebuggerPresent() ) {
1444 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1445 OutputDebugString(message);
1448 if (code && password && password[0] ) {
1449 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1454 0, /* forwardable */
1455 0, /* not proxiable */
1457 1, /* noaddresses */
1458 0 /* no public ip */
1460 pLeash_get_default_forwardable(),
1461 pLeash_get_default_proxiable(),
1462 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1463 pLeash_get_default_noaddresses(),
1464 pLeash_get_default_publicip()
1465 #endif /* USE_LEASH */
1468 if ( IsDebuggerPresent() ) {
1470 StringCbPrintf(message, sizeof(message), "KFW_kinit() returns: %d\n", code);
1471 OutputDebugString(message);
1473 if ( code ) goto cleanup;
1475 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1478 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1479 if ( IsDebuggerPresent() ) {
1481 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1482 OutputDebugString(message);
1484 if ( code ) goto cleanup;
1486 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1488 // Attempt to obtain new tokens for other cells supported by the same
1490 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1491 if ( cell_count > 1 ) {
1492 while ( cell_count-- ) {
1493 if ( strcmp(cells[cell_count],cell) ) {
1494 if ( IsDebuggerPresent() ) {
1496 StringCbPrintf(message, sizeof(message),
1497 "found another cell for the same principal: %s\n", cell);
1498 OutputDebugString(message);
1501 if (cellconfig.linkedCell) {
1502 free(cellconfig.linkedCell);
1503 cellconfig.linkedCell = NULL;
1505 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1506 if ( code ) continue;
1508 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1509 if ( IsDebuggerPresent() ) {
1510 OutputDebugString("Realm: ");
1511 OutputDebugString(realm);
1512 OutputDebugString("\n");
1515 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1516 if ( IsDebuggerPresent() ) {
1518 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1519 OutputDebugString(message);
1522 free(cells[cell_count]);
1525 } else if ( cell_count == 1 ) {
1534 pkrb5_cc_close(ctx, cc);
1535 if ( cellconfig.linkedCell )
1536 free(cellconfig.linkedCell);
1538 if ( code && reasonP ) {
1540 char *msg = (char *)afs_error_message(code);
1541 if (strncmp(msg, "unknown", strlen(msg)) == 0) {
1542 if (pkrb5_get_error_message) {
1543 msg = pkrb5_get_error_message(ctx, code);
1546 msg = (char *)perror_message(code);
1548 StringCbCopyN( reason, sizeof(reason),
1549 msg, sizeof(reason) - 1);
1552 pkrb5_free_error_message(ctx, msg);
1558 KFW_AFS_destroy_tickets_for_cell(char * cell)
1560 krb5_context ctx = NULL;
1561 krb5_error_code code;
1563 char ** principals = NULL;
1565 if (!pkrb5_init_context)
1566 return KRB5_CONFIG_CANTOPEN;
1568 if ( IsDebuggerPresent() ) {
1569 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1570 OutputDebugString(cell);
1571 OutputDebugString("\n");
1574 code = pkrb5_init_context(&ctx);
1577 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1579 krb5_principal princ = 0;
1583 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1584 if ( cell_count > 1 ) {
1585 // TODO - What we really should do here is verify whether or not any of the
1586 // other cells which use this principal to obtain its credentials actually
1587 // have valid tokens or not. If they are currently using these credentials
1588 // we will skip them. For the time being we assume that if there is an active
1589 // map in the table that they are actively being used.
1593 code = pkrb5_parse_name(ctx, principals[count], &princ);
1594 if (code) goto loop_cleanup;
1596 code = KFW_get_ccache(ctx, princ, &cc);
1597 if (code) goto loop_cleanup;
1599 code = pkrb5_cc_destroy(ctx, cc);
1604 pkrb5_cc_close(ctx, cc);
1608 pkrb5_free_principal(ctx, princ);
1612 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1613 free(principals[count]);
1618 pkrb5_free_context(ctx);
1623 KFW_AFS_destroy_tickets_for_principal(char * user)
1625 krb5_context ctx = NULL;
1626 krb5_error_code code;
1628 char ** cells = NULL;
1629 krb5_principal princ = NULL;
1630 krb5_ccache cc = NULL;
1632 if (!pkrb5_init_context)
1633 return KRB5_CONFIG_CANTOPEN;
1635 if ( IsDebuggerPresent() ) {
1636 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1637 OutputDebugString(user);
1638 OutputDebugString("\n");
1641 code = pkrb5_init_context(&ctx);
1644 code = pkrb5_parse_name(ctx, user, &princ);
1645 if (code) goto loop_cleanup;
1647 code = KFW_get_ccache(ctx, princ, &cc);
1648 if (code) goto loop_cleanup;
1650 code = pkrb5_cc_destroy(ctx, cc);
1655 pkrb5_cc_close(ctx, cc);
1659 pkrb5_free_principal(ctx, princ);
1663 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1666 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1673 pkrb5_free_context(ctx);
1678 KFW_AFS_renew_expiring_tokens(void)
1680 krb5_error_code code = 0;
1681 krb5_context ctx = NULL;
1682 krb5_ccache cc = NULL;
1684 struct principal_ccache_data * pcc_next = princ_cc_data;
1687 const char * realm = NULL;
1688 char local_cell[CELL_MAXNAMELEN+1]="";
1689 struct afsconf_cell cellconfig;
1691 if (!pkrb5_init_context)
1692 return KRB5_CONFIG_CANTOPEN;
1694 if ( pcc_next == NULL ) // nothing to do
1697 if ( IsDebuggerPresent() ) {
1698 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1701 memset(&cellconfig, 0, sizeof(cellconfig));
1703 code = pkrb5_init_context(&ctx);
1704 if (code) goto cleanup;
1706 code = pkrb5_timeofday(ctx, &now);
1707 if (code) goto cleanup;
1709 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1710 if ( pcc_next->expired )
1713 if ( now >= (pcc_next->expiration_time) ) {
1714 if ( !pcc_next->from_lsa ) {
1715 pcc_next->expired = 1;
1720 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1721 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1724 code = KFW_renew(ctx,cc);
1726 if ( code && pcc_next->from_lsa)
1728 #endif /* USE_MS2MIT */
1731 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1732 if (code) goto loop_cleanup;
1734 // Attempt to obtain new tokens for other cells supported by the same
1736 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1737 if ( cell_count > 0 ) {
1738 while ( cell_count-- ) {
1739 if ( IsDebuggerPresent() ) {
1740 OutputDebugString("Cell: ");
1741 OutputDebugString(cells[cell_count]);
1742 OutputDebugString("\n");
1744 if (cellconfig.linkedCell) {
1745 free(cellconfig.linkedCell);
1746 cellconfig.linkedCell = NULL;
1748 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1749 if ( code ) continue;
1750 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1751 if ( IsDebuggerPresent() ) {
1752 OutputDebugString("Realm: ");
1753 OutputDebugString(realm);
1754 OutputDebugString("\n");
1756 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1757 if ( IsDebuggerPresent() ) {
1759 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1760 OutputDebugString(message);
1762 free(cells[cell_count]);
1770 pkrb5_cc_close(ctx,cc);
1777 pkrb5_cc_close(ctx,cc);
1779 pkrb5_free_context(ctx);
1780 if (cellconfig.linkedCell)
1781 free(cellconfig.linkedCell);
1788 KFW_AFS_renew_token_for_cell(char * cell)
1790 krb5_error_code code = 0;
1791 krb5_context ctx = NULL;
1793 char ** principals = NULL;
1795 if (!pkrb5_init_context)
1796 return KRB5_CONFIG_CANTOPEN;
1798 if ( IsDebuggerPresent() ) {
1799 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1800 OutputDebugString(cell);
1801 OutputDebugString("\n");
1804 code = pkrb5_init_context(&ctx);
1805 if (code) goto cleanup;
1807 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1809 // We know we must have a credential somewhere since we are
1810 // trying to renew a token
1812 KFW_import_ccache_data();
1813 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1816 krb5_principal princ = 0;
1817 krb5_principal service = 0;
1819 krb5_creds mcreds, creds;
1820 #endif /* COMMENT */
1822 const char * realm = NULL;
1823 struct afsconf_cell cellconfig;
1824 char local_cell[CELL_MAXNAMELEN+1];
1826 memset(&cellconfig, 0, sizeof(cellconfig));
1829 code = pkrb5_parse_name(ctx, principals[count], &princ);
1830 if (code) goto loop_cleanup;
1832 code = KFW_get_ccache(ctx, princ, &cc);
1833 if (code) goto loop_cleanup;
1835 if (cellconfig.linkedCell) {
1836 free(cellconfig.linkedCell);
1837 cellconfig.linkedCell = NULL;
1839 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1840 if ( code ) goto loop_cleanup;
1842 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1843 if ( IsDebuggerPresent() ) {
1844 OutputDebugString("Realm: ");
1845 OutputDebugString(realm);
1846 OutputDebugString("\n");
1850 /* krb5_cc_remove_cred() is not implemented
1853 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1854 realm, "afs", cell, NULL);
1856 memset(&mcreds, 0, sizeof(krb5_creds));
1857 mcreds.client = princ;
1858 mcreds.server = service;
1860 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1862 if ( IsDebuggerPresent() ) {
1863 char * cname, *sname;
1864 pkrb5_unparse_name(ctx, creds.client, &cname);
1865 pkrb5_unparse_name(ctx, creds.server, &sname);
1866 OutputDebugString("Removing credential for client \"");
1867 OutputDebugString(cname);
1868 OutputDebugString("\" and service \"");
1869 OutputDebugString(sname);
1870 OutputDebugString("\"\n");
1871 pkrb5_free_unparsed_name(ctx,cname);
1872 pkrb5_free_unparsed_name(ctx,sname);
1875 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1876 pkrb5_free_principal(ctx, creds.client);
1877 pkrb5_free_principal(ctx, creds.server);
1880 #endif /* COMMENT */
1882 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1883 if ( IsDebuggerPresent() ) {
1885 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1886 OutputDebugString(message);
1891 pkrb5_cc_close(ctx, cc);
1895 pkrb5_free_principal(ctx, princ);
1899 pkrb5_free_principal(ctx, service);
1902 if (cellconfig.linkedCell) {
1903 free(cellconfig.linkedCell);
1904 cellconfig.linkedCell = NULL;
1907 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1908 free(principals[count]);
1912 code = -1; // we did not renew the tokens
1916 pkrb5_free_context(ctx);
1917 return (code ? FALSE : TRUE);
1922 KFW_AFS_renew_tokens_for_all_cells(void)
1924 struct cell_principal_map * next = cell_princ_map;
1926 if ( IsDebuggerPresent() )
1927 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1932 for ( ; next ; next = next->next ) {
1934 KFW_AFS_renew_token_for_cell(next->cell);
1940 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1942 krb5_error_code code = 0;
1943 krb5_context ctx = NULL;
1944 krb5_ccache cc = NULL;
1945 krb5_principal me = NULL;
1946 krb5_principal server = NULL;
1947 krb5_creds my_creds;
1948 krb5_data *realm = NULL;
1950 if (!pkrb5_init_context)
1951 return KRB5_CONFIG_CANTOPEN;
1953 memset(&my_creds, 0, sizeof(krb5_creds));
1958 code = pkrb5_init_context(&ctx);
1959 if (code) goto cleanup;
1965 code = pkrb5_cc_default(ctx, &cc);
1966 if (code) goto cleanup;
1969 code = pkrb5_cc_get_principal(ctx, cc, &me);
1970 if (code) goto cleanup;
1972 realm = krb5_princ_realm(ctx, me);
1974 code = pkrb5_build_principal_ext(ctx, &server,
1975 realm->length,realm->data,
1976 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1977 realm->length,realm->data,
1982 if ( IsDebuggerPresent() ) {
1983 char * cname, *sname;
1984 pkrb5_unparse_name(ctx, me, &cname);
1985 pkrb5_unparse_name(ctx, server, &sname);
1986 OutputDebugString("Renewing credential for client \"");
1987 OutputDebugString(cname);
1988 OutputDebugString("\" and service \"");
1989 OutputDebugString(sname);
1990 OutputDebugString("\"\n");
1991 pkrb5_free_unparsed_name(ctx,cname);
1992 pkrb5_free_unparsed_name(ctx,sname);
1995 my_creds.client = me;
1996 my_creds.server = server;
1998 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
2000 if ( IsDebuggerPresent() ) {
2002 StringCbPrintf(message, sizeof(message), "krb5_get_renewed_creds() failed: %d\n", code);
2003 OutputDebugString(message);
2008 code = pkrb5_cc_initialize(ctx, cc, me);
2010 if ( IsDebuggerPresent() ) {
2012 StringCbPrintf(message, sizeof(message), "krb5_cc_initialize() failed: %d\n", code);
2013 OutputDebugString(message);
2018 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2020 if ( IsDebuggerPresent() ) {
2022 StringCbPrintf(message, sizeof(message), "krb5_cc_store_cred() failed: %d\n", code);
2023 OutputDebugString(message);
2029 if (my_creds.client == me)
2030 my_creds.client = 0;
2031 if (my_creds.server == server)
2032 my_creds.server = 0;
2033 pkrb5_free_cred_contents(ctx, &my_creds);
2035 pkrb5_free_principal(ctx, me);
2037 pkrb5_free_principal(ctx, server);
2038 if (cc && (cc != alt_cc))
2039 pkrb5_cc_close(ctx, cc);
2040 if (ctx && (ctx != alt_ctx))
2041 pkrb5_free_context(ctx);
2046 KFW_kinit( krb5_context alt_ctx,
2049 char *principal_name,
2051 krb5_deltat lifetime,
2054 krb5_deltat renew_life,
2059 krb5_error_code code = 0;
2060 krb5_context ctx = NULL;
2061 krb5_ccache cc = NULL;
2062 krb5_principal me = NULL;
2064 krb5_creds my_creds;
2065 krb5_get_init_creds_opt options;
2066 krb5_address ** addrs = NULL;
2067 int i = 0, addr_count = 0;
2069 if (!pkrb5_init_context)
2070 return KRB5_CONFIG_CANTOPEN;
2072 pkrb5_get_init_creds_opt_init(&options);
2073 memset(&my_creds, 0, sizeof(my_creds));
2081 code = pkrb5_init_context(&ctx);
2082 if (code) goto cleanup;
2088 code = pkrb5_cc_default(ctx, &cc);
2089 if (code) goto cleanup;
2092 code = pkrb5_parse_name(ctx, principal_name, &me);
2096 code = pkrb5_unparse_name(ctx, me, &name);
2101 lifetime = DEFAULT_LIFETIME;
2108 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2109 pkrb5_get_init_creds_opt_set_forwardable(&options,
2110 forwardable ? 1 : 0);
2111 pkrb5_get_init_creds_opt_set_proxiable(&options,
2113 pkrb5_get_init_creds_opt_set_renew_life(&options,
2116 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2120 // we are going to add the public IP address specified by the user
2121 // to the list provided by the operating system
2122 krb5_address ** local_addrs=NULL;
2125 pkrb5_os_localaddr(ctx, &local_addrs);
2126 while ( local_addrs[i++] );
2129 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2131 pkrb5_free_addresses(ctx, local_addrs);
2134 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2136 while ( local_addrs[i] ) {
2137 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2138 if (addrs[i] == NULL) {
2139 pkrb5_free_addresses(ctx, local_addrs);
2143 addrs[i]->magic = local_addrs[i]->magic;
2144 addrs[i]->addrtype = local_addrs[i]->addrtype;
2145 addrs[i]->length = local_addrs[i]->length;
2146 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2147 if (!addrs[i]->contents) {
2148 pkrb5_free_addresses(ctx, local_addrs);
2152 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2153 local_addrs[i]->length); /* safe */
2156 pkrb5_free_addresses(ctx, local_addrs);
2158 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2159 if (addrs[i] == NULL)
2162 addrs[i]->magic = KV5M_ADDRESS;
2163 addrs[i]->addrtype = AF_INET;
2164 addrs[i]->length = 4;
2165 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2166 if (!addrs[i]->contents)
2169 netIPAddr = htonl(publicIP);
2170 memcpy(addrs[i]->contents,&netIPAddr,4);
2172 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2177 code = pkrb5_get_init_creds_password(ctx,
2180 password, // password
2181 KRB5_prompter, // prompter
2182 hParent, // prompter data
2189 code = pkrb5_cc_initialize(ctx, cc, me);
2193 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2199 for ( i=0;i<addr_count;i++ ) {
2201 if ( addrs[i]->contents )
2202 free(addrs[i]->contents);
2207 if (my_creds.client == me)
2208 my_creds.client = 0;
2209 pkrb5_free_cred_contents(ctx, &my_creds);
2211 pkrb5_free_unparsed_name(ctx, name);
2213 pkrb5_free_principal(ctx, me);
2214 if (cc && (cc != alt_cc))
2215 pkrb5_cc_close(ctx, cc);
2216 if (ctx && (ctx != alt_ctx))
2217 pkrb5_free_context(ctx);
2223 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2225 krb5_context ctx = NULL;
2226 krb5_ccache cc = NULL;
2227 krb5_error_code code;
2229 if (!pkrb5_init_context)
2230 return KRB5_CONFIG_CANTOPEN;
2238 code = pkrb5_init_context(&ctx);
2239 if (code) goto cleanup;
2245 code = pkrb5_cc_default(ctx, &cc);
2246 if (code) goto cleanup;
2249 code = pkrb5_cc_destroy(ctx, cc);
2250 if ( !code ) cc = 0;
2253 if (cc && (cc != alt_cc))
2254 pkrb5_cc_close(ctx, cc);
2255 if (ctx && (ctx != alt_ctx))
2256 pkrb5_free_context(ctx);
2264 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2266 NTSTATUS Status = 0;
2268 TOKEN_STATISTICS Stats;
2274 *ppSessionData = NULL;
2276 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2280 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2281 CloseHandle( TokenHandle );
2285 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2286 if ( FAILED(Status) || !ppSessionData )
2293 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2294 // cache. It validates whether or not it is reasonable to assume that if we
2295 // attempted to retrieve valid tickets we could do so. Microsoft does not
2296 // automatically renew expired tickets. Therefore, the cache could contain
2297 // expired or invalid tickets. Microsoft also caches the user's password
2298 // and will use it to retrieve new TGTs if the cache is empty and tickets
2302 MSLSA_IsKerberosLogon(VOID)
2304 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2305 BOOL Success = FALSE;
2307 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2308 if ( pSessionData->AuthenticationPackage.Buffer ) {
2314 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2315 usLength = (pSessionData->AuthenticationPackage).Length;
2318 StringCbCopyNW( buffer, sizeof(buffer)/sizeof(WCHAR),
2319 usBuffer, usLength);
2320 if ( !lstrcmpW(L"Kerberos",buffer) )
2324 pLsaFreeReturnBuffer(pSessionData);
2328 #endif /* USE_MS2MIT */
2330 static BOOL CALLBACK
2331 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2335 switch ( message ) {
2337 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2339 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2342 for ( i=0; i < mid_cnt ; i++ ) {
2343 if (mid_tb[i].echo == 0)
2344 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2345 else if (mid_tb[i].echo == 2)
2346 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2351 switch ( LOWORD(wParam) ) {
2353 for ( i=0; i < mid_cnt ; i++ ) {
2354 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2355 *mid_tb[i].buf = '\0';
2359 EndDialog(hDialog, LOWORD(wParam));
2367 lpwAlign( LPWORD lpIn )
2371 ul = (ULONG_PTR) lpIn;
2375 return (LPWORD) ul;;
2379 * dialog widths are measured in 1/4 character widths
2380 * dialog height are measured in 1/8 character heights
2384 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2385 char * ptext[], int numlines, int width,
2386 int tb_cnt, struct textField * tb)
2390 LPDLGITEMTEMPLATE lpdit;
2396 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2403 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2405 // Define a dialog box.
2407 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2408 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2409 | DS_SETFOREGROUND | DS_3DLOOK
2410 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2411 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2414 lpdt->cx = 20 + width * 4;
2415 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2417 lpw = (LPWORD) (lpdt + 1);
2418 *lpw++ = 0; // no menu
2419 *lpw++ = 0; // predefined dialog box class (by default)
2421 lpwsz = (LPWSTR) lpw;
2422 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2424 *lpw++ = 8; // font size (points)
2425 lpwsz = (LPWSTR) lpw;
2426 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2430 //-----------------------
2431 // Define an OK button.
2432 //-----------------------
2433 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2434 lpdit = (LPDLGITEMTEMPLATE) lpw;
2435 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2436 lpdit->dwExtendedStyle = 0;
2437 lpdit->x = (lpdt->cx - 14)/4 - 20;
2438 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2441 lpdit->id = IDOK; // OK button identifier
2443 lpw = (LPWORD) (lpdit + 1);
2445 *lpw++ = 0x0080; // button class
2447 lpwsz = (LPWSTR) lpw;
2448 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2450 *lpw++ = 0; // no creation data
2452 //-----------------------
2453 // Define an Cancel button.
2454 //-----------------------
2455 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2456 lpdit = (LPDLGITEMTEMPLATE) lpw;
2457 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2458 lpdit->dwExtendedStyle = 0;
2459 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2460 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2463 lpdit->id = IDCANCEL; // CANCEL button identifier
2465 lpw = (LPWORD) (lpdit + 1);
2467 *lpw++ = 0x0080; // button class
2469 lpwsz = (LPWSTR) lpw;
2470 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2472 *lpw++ = 0; // no creation data
2474 /* Add controls for preface data */
2475 for ( i=0; i<numlines; i++) {
2476 /*-----------------------
2477 * Define a static text control.
2478 *-----------------------*/
2479 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2480 lpdit = (LPDLGITEMTEMPLATE) lpw;
2481 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2482 lpdit->dwExtendedStyle = 0;
2484 lpdit->y = 10 + i * 14;
2485 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2487 lpdit->id = ID_TEXT + i; // text identifier
2489 lpw = (LPWORD) (lpdit + 1);
2491 *lpw++ = 0x0082; // static class
2493 lpwsz = (LPWSTR) lpw;
2494 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2495 -1, lpwsz, 2*width);
2497 *lpw++ = 0; // no creation data
2500 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2501 int len = (int)strlen(tb[i].label);
2506 for ( i=0; i<tb_cnt; i++) {
2508 /*-----------------------
2509 * Define a static text control.
2510 *-----------------------*/
2511 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2512 lpdit = (LPDLGITEMTEMPLATE) lpw;
2513 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2514 lpdit->dwExtendedStyle = 0;
2516 lpdit->y = 10 + (numlines + i + 1) * 14;
2517 lpdit->cx = pwid * 4;
2519 lpdit->id = ID_TEXT + numlines + i; // text identifier
2521 lpw = (LPWORD) (lpdit + 1);
2523 *lpw++ = 0x0082; // static class
2525 lpwsz = (LPWSTR) lpw;
2526 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2529 *lpw++ = 0; // no creation data
2531 /*-----------------------
2532 * Define an edit control.
2533 *-----------------------*/
2534 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2535 lpdit = (LPDLGITEMTEMPLATE) lpw;
2536 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2537 lpdit->dwExtendedStyle = 0;
2538 lpdit->x = 10 + (pwid + 1) * 4;
2539 lpdit->y = 10 + (numlines + i + 1) * 14;
2540 lpdit->cx = (width - (pwid + 1)) * 4;
2542 lpdit->id = ID_MID_TEXT + i; // identifier
2544 lpw = (LPWORD) (lpdit + 1);
2546 *lpw++ = 0x0081; // edit class
2548 lpwsz = (LPWSTR) lpw;
2549 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2552 *lpw++ = 0; // no creation data
2556 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2557 hwndOwner, (DLGPROC) MultiInputDialogProc);
2561 case 0: /* Timeout */
2569 StringCbPrintf(buf, sizeof(buf), "DialogBoxIndirect() failed: %d", GetLastError());
2570 MessageBox(hwndOwner,
2573 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2580 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2582 HINSTANCE hInst = 0;
2586 char * plines[16], *p = preface ? preface : "";
2589 for ( i=0; i<16; i++ )
2592 while (*p && numlines < 16) {
2593 plines[numlines++] = p;
2594 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2595 if ( *p == '\r' && *(p+1) == '\n' ) {
2598 } else if ( *p == '\n' ) {
2601 if ( strlen(plines[numlines-1]) > maxwidth )
2602 maxwidth = (int)strlen(plines[numlines-1]);
2605 for ( i=0;i<n;i++ ) {
2606 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2607 if ( maxwidth < len )
2611 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2614 static krb5_error_code KRB5_CALLCONV
2615 KRB5_prompter( krb5_context context,
2620 krb5_prompt prompts[])
2622 krb5_error_code errcode = 0;
2624 struct textField * tb = NULL;
2625 int len = 0, blen=0, nlen=0;
2626 HWND hParent = (HWND)data;
2629 nlen = (int)strlen(name)+2;
2632 blen = (int)strlen(banner)+2;
2634 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2637 memset(tb,0,sizeof(struct textField) * num_prompts);
2638 for ( i=0; i < num_prompts; i++ ) {
2639 tb[i].buf = prompts[i].reply->data;
2640 tb[i].len = prompts[i].reply->length;
2641 tb[i].label = prompts[i].prompt;
2643 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2646 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2648 for ( i=0; i < num_prompts; i++ )
2649 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2657 for (i = 0; i < num_prompts; i++) {
2658 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2665 KFW_AFS_wait_for_service_start(void)
2670 CurrentState = SERVICE_START_PENDING;
2671 memset(HostName, '\0', sizeof(HostName));
2672 gethostname(HostName, sizeof(HostName));
2674 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2676 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2678 if ( IsDebuggerPresent() ) {
2679 switch ( CurrentState ) {
2680 case SERVICE_STOPPED:
2681 OutputDebugString("SERVICE_STOPPED\n");
2683 case SERVICE_START_PENDING:
2684 OutputDebugString("SERVICE_START_PENDING\n");
2686 case SERVICE_STOP_PENDING:
2687 OutputDebugString("SERVICE_STOP_PENDING\n");
2689 case SERVICE_RUNNING:
2690 OutputDebugString("SERVICE_RUNNING\n");
2692 case SERVICE_CONTINUE_PENDING:
2693 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2695 case SERVICE_PAUSE_PENDING:
2696 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2698 case SERVICE_PAUSED:
2699 OutputDebugString("SERVICE_PAUSED\n");
2702 OutputDebugString("UNKNOWN Service State\n");
2705 if (CurrentState == SERVICE_STOPPED)
2707 if (CurrentState == SERVICE_RUNNING)
2723 memset(HostName, '\0', sizeof(HostName));
2724 gethostname(HostName, sizeof(HostName));
2725 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2727 if (CurrentState != SERVICE_RUNNING)
2730 rc = ktc_ForgetAllTokens();
2736 #define ALLOW_REGISTER 1
2738 ViceIDToUsername(char *username,
2739 char *realm_of_user,
2740 char *realm_of_cell,
2742 struct ktc_principal *aclient,
2743 struct ktc_principal *aserver,
2744 struct ktc_token *atoken)
2746 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2747 static char confdir[512] = { 0 };
2748 #ifdef AFS_ID_TO_NAME
2749 char username_copy[BUFSIZ];
2750 #endif /* AFS_ID_TO_NAME */
2751 long viceId = ANONYMOUSID; /* AFS uid of user */
2753 #ifdef ALLOW_REGISTER
2755 #endif /* ALLOW_REGISTER */
2757 if (confdir[0] == '\0')
2758 cm_GetConfigDir(confdir, sizeof(confdir));
2760 StringCbCopyN( lastcell, sizeof(lastcell),
2761 aserver->cell, sizeof(lastcell) - 1);
2763 if (!pr_Initialize (0, confdir, aserver->cell)) {
2764 char sname[PR_MAXNAMELEN];
2765 StringCbCopyN( sname, sizeof(sname),
2766 username, sizeof(sname) - 1);
2767 status = pr_SNameToId (sname, &viceId);
2772 * This is a crock, but it is Transarc's crock, so
2773 * we have to play along in order to get the
2774 * functionality. The way the afs id is stored is
2775 * as a string in the username field of the token.
2776 * Contrary to what you may think by looking at
2777 * the code for tokens, this hack (AFS ID %d) will
2778 * not work if you change %d to something else.
2782 * This code is taken from cklog -- it lets people
2783 * automatically register with the ptserver in foreign cells
2786 #ifdef ALLOW_REGISTER
2788 if (viceId != ANONYMOUSID) {
2789 #else /* ALLOW_REGISTER */
2790 if ((status == 0) && (viceId != ANONYMOUSID))
2791 #endif /* ALLOW_REGISTER */
2793 #ifdef AFS_ID_TO_NAME
2794 StringCbCopyN( username_copy, sizeof(username_copy),
2795 username, sizeof(username_copy) - 1);
2796 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2797 #endif /* AFS_ID_TO_NAME */
2799 #ifdef ALLOW_REGISTER
2800 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2802 StringCbCopyN( aclient->name, sizeof(aclient->name),
2803 username, sizeof(aclient->name) - 1);
2804 aclient->instance[0] = '\0';
2805 StringCbCopyN( aclient->cell, sizeof(aclient->cell),
2806 realm_of_user, sizeof(aclient->cell) - 1);
2807 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2809 if (status = pr_Initialize(1L, confdir, aserver->cell))
2811 status = pr_CreateUser(username, &id);
2815 #ifdef AFS_ID_TO_NAME
2816 StringCbCopyN( username_copy, sizeof(username_copy),
2817 username, sizeof(username_copy) - 1);
2818 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2819 #endif /* AFS_ID_TO_NAME */
2822 #endif /* ALLOW_REGISTER */
2828 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2829 krb5_error_code code;
2830 krb5_ticket *ticket;
2833 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2835 len = krb5_princ_realm(context, ticket->server)->length;
2836 if (len > destlen - 1)
2839 StringCbCopyN(dest, destlen, krb5_princ_realm(context, ticket->server)->data, len);
2841 pkrb5_free_ticket(context, ticket);
2847 krb5_context alt_ctx,
2852 int lifetime, /* unused parameter */
2860 #endif /* USE_KRB4 */
2861 struct ktc_principal aserver;
2862 struct ktc_principal aclient;
2863 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2864 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2865 char local_cell[CELL_MAXNAMELEN+1];
2866 char Dmycell[CELL_MAXNAMELEN+1];
2867 struct ktc_token atoken;
2868 struct ktc_token btoken;
2869 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2870 char RealmName[128];
2872 char ServiceName[128];
2876 krb5_context ctx = NULL;
2877 krb5_ccache cc = NULL;
2879 krb5_creds * k5creds = NULL;
2880 krb5_error_code code;
2881 krb5_principal client_principal = NULL;
2882 krb5_data * k5data = NULL;
2883 unsigned int i, retry = 0;
2886 memset(HostName, '\0', sizeof(HostName));
2887 gethostname(HostName, sizeof(HostName));
2888 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2889 if ( IsDebuggerPresent() )
2890 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2893 if (CurrentState != SERVICE_RUNNING) {
2894 if ( IsDebuggerPresent() )
2895 OutputDebugString("AFSD Service NOT RUNNING\n");
2899 if (!pkrb5_init_context)
2900 return KRB5_CONFIG_CANTOPEN;
2902 memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
2903 memset(RealmName, '\0', sizeof(RealmName));
2904 memset(CellName, '\0', sizeof(CellName));
2905 memset(ServiceName, '\0', sizeof(ServiceName));
2906 memset(realm_of_user, '\0', sizeof(realm_of_user));
2907 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2908 if (cell && cell[0])
2909 StringCbCopyN( Dmycell, sizeof(Dmycell),
2910 cell, sizeof(Dmycell) - 1);
2912 memset(Dmycell, '\0', sizeof(Dmycell));
2914 // NULL or empty cell returns information on local cell
2915 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2917 // KFW_AFS_error(rc, "get_cellconfig()");
2924 code = pkrb5_init_context(&ctx);
2925 if (code) goto cleanup;
2931 code = pkrb5_cc_default(ctx, &cc);
2932 if (code) goto skip_krb5_init;
2935 memset(&increds, 0, sizeof(increds));
2937 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2939 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2941 OutputDebugString("Principal Not Found for ccache\n");
2943 goto skip_krb5_init;
2946 if (!KFW_accept_dotted_usernames()) {
2947 /* look for client principals which cannot be distinguished
2948 * from Kerberos 4 multi-component principal names
2950 k5data = krb5_princ_component(ctx,client_principal,0);
2951 for ( i=0; i<k5data->length; i++ ) {
2952 if ( k5data->data[i] == '.' )
2955 if (i != k5data->length)
2957 OutputDebugString("Illegal Principal name contains dot in first component\n");
2958 rc = KRB5KRB_ERR_GENERIC;
2963 i = krb5_princ_realm(ctx, client_principal)->length;
2966 StringCbCopyN( realm_of_user, sizeof(realm_of_user),
2967 krb5_princ_realm(ctx, client_principal)->data, i);
2972 if ( !try_krb5 || !realm_of_user[0] ) {
2973 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2982 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
2983 afs_realm_of_cell(ctx, &ak_cellconfig),
2984 sizeof(realm_of_cell) - 1);
2986 if (strlen(service) == 0)
2987 StringCbCopy( ServiceName, sizeof(ServiceName), "afs");
2989 StringCbCopyN( ServiceName, sizeof(ServiceName),
2990 service, sizeof(ServiceName) - 1);
2992 if (strlen(cell) == 0)
2993 StringCbCopyN( CellName, sizeof(CellName),
2994 local_cell, sizeof(CellName) - 1);
2996 StringCbCopyN( CellName, sizeof(CellName),
2997 cell, sizeof(CellName) - 1);
2999 /* This is for Kerberos v4 only */
3000 if (strlen(realm) == 0)
3001 StringCbCopyN( RealmName, sizeof(RealmName),
3002 realm_of_cell, sizeof(RealmName) - 1);
3004 StringCbCopyN( RealmName, sizeof(RealmName),
3005 realm, sizeof(RealmName) - 1);
3007 memset(&creds, '\0', sizeof(creds));
3011 code = KRB5KRB_ERR_GENERIC;
3014 increds.client = client_principal;
3015 increds.times.endtime = 0;
3016 /* Ask for DES since that is what V4 understands */
3017 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
3019 /* ALWAYS first try service/cell@CLIENT_REALM */
3020 if (code = pkrb5_build_principal(ctx, &increds.server,
3021 (int)strlen(realm_of_user),
3030 if ( IsDebuggerPresent() ) {
3031 char * cname, *sname;
3032 pkrb5_unparse_name(ctx, increds.client, &cname);
3033 pkrb5_unparse_name(ctx, increds.server, &sname);
3034 OutputDebugString("Getting tickets for \"");
3035 OutputDebugString(cname);
3036 OutputDebugString("\" and service \"");
3037 OutputDebugString(sname);
3038 OutputDebugString("\"\n");
3039 pkrb5_free_unparsed_name(ctx,cname);
3040 pkrb5_free_unparsed_name(ctx,sname);
3043 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3045 /* The client's realm is a local realm for the cell.
3046 * Save it so that later the pts registration will not
3049 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3050 realm_of_user, sizeof(realm_of_cell) - 1);
3054 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3055 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3056 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3057 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3058 /* If there was a specific realm we are supposed to try
3061 if (strlen(realm) != 0) {
3062 /* service/cell@REALM */
3064 code = pkrb5_build_principal(ctx, &increds.server,
3070 if ( IsDebuggerPresent() ) {
3071 char * cname, *sname;
3072 pkrb5_unparse_name(ctx, increds.client, &cname);
3073 pkrb5_unparse_name(ctx, increds.server, &sname);
3074 OutputDebugString("Getting tickets for \"");
3075 OutputDebugString(cname);
3076 OutputDebugString("\" and service \"");
3077 OutputDebugString(sname);
3078 OutputDebugString("\"\n");
3079 pkrb5_free_unparsed_name(ctx,cname);
3080 pkrb5_free_unparsed_name(ctx,sname);
3084 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3086 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3087 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3088 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3089 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3090 /* Or service@REALM */
3091 pkrb5_free_principal(ctx,increds.server);
3093 code = pkrb5_build_principal(ctx, &increds.server,
3099 if ( IsDebuggerPresent() ) {
3100 char * cname, *sname;
3101 pkrb5_unparse_name(ctx, increds.client, &cname);
3102 pkrb5_unparse_name(ctx, increds.server, &sname);
3103 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3104 OutputDebugString("Trying again: getting tickets for \"");
3105 OutputDebugString(cname);
3106 OutputDebugString("\" and service \"");
3107 OutputDebugString(sname);
3108 OutputDebugString("\"\n");
3109 pkrb5_free_unparsed_name(ctx,cname);
3110 pkrb5_free_unparsed_name(ctx,sname);
3114 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3118 /* we have a local realm for the cell */
3119 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3120 realm, sizeof(realm_of_cell) - 1);
3123 if (strcmp(realm_of_user, realm_of_cell)) {
3124 /* Then service/cell@CELL_REALM */
3125 pkrb5_free_principal(ctx,increds.server);
3127 code = pkrb5_build_principal(ctx, &increds.server,
3128 (int)strlen(realm_of_cell),
3133 if ( IsDebuggerPresent() ) {
3134 char * cname, *sname;
3135 pkrb5_unparse_name(ctx, increds.client, &cname);
3136 pkrb5_unparse_name(ctx, increds.server, &sname);
3137 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3138 OutputDebugString("Trying again: getting tickets for \"");
3139 OutputDebugString(cname);
3140 OutputDebugString("\" and service \"");
3141 OutputDebugString(sname);
3142 OutputDebugString("\"\n");
3143 pkrb5_free_unparsed_name(ctx,cname);
3144 pkrb5_free_unparsed_name(ctx,sname);
3148 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3150 if (!code && !strlen(realm_of_cell))
3151 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3154 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3155 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3156 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3157 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3158 /* Finally service@CELL_REALM */
3159 pkrb5_free_principal(ctx,increds.server);
3161 code = pkrb5_build_principal(ctx, &increds.server,
3162 (int)strlen(realm_of_cell),
3167 if ( IsDebuggerPresent() ) {
3168 char * cname, *sname;
3169 pkrb5_unparse_name(ctx, increds.client, &cname);
3170 pkrb5_unparse_name(ctx, increds.server, &sname);
3171 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3172 OutputDebugString("Trying again: getting tickets for \"");
3173 OutputDebugString(cname);
3174 OutputDebugString("\" and service \"");
3175 OutputDebugString(sname);
3176 OutputDebugString("\"\n");
3177 pkrb5_free_unparsed_name(ctx,cname);
3178 pkrb5_free_unparsed_name(ctx,sname);
3182 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3183 if (!code && !strlen(realm_of_cell))
3184 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3190 if ( IsDebuggerPresent() ) {
3192 StringCbPrintf(message, sizeof(message), "krb5_get_credentials returns: %d\n", code);
3193 OutputDebugString(message);
3199 /* This code inserts the entire K5 ticket into the token
3200 * No need to perform a krb524 translation which is
3201 * commented out in the code below
3203 if (KFW_use_krb524() ||
3204 k5creds->ticket.length > MAXKTCTICKETLEN) {
3205 if ( IsDebuggerPresent() ) {
3207 StringCbPrintf(message, sizeof(message),
3208 "switching to krb524 .. ticket length %u\n",
3209 k5creds->ticket.length);
3210 OutputDebugString(message);
3214 memset(&aserver, '\0', sizeof(aserver));
3215 StringCbCopyN(aserver.name, sizeof(aserver.name),
3216 ServiceName, sizeof(aserver.name) - 1);
3217 StringCbCopyN(aserver.cell, sizeof(aserver.cell),
3218 CellName, sizeof(aserver.cell) - 1);
3220 memset(&atoken, '\0', sizeof(atoken));
3221 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3222 atoken.startTime = k5creds->times.starttime;
3223 atoken.endTime = k5creds->times.endtime;
3224 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3225 atoken.ticketLen = k5creds->ticket.length;
3226 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3229 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3230 if ( IsDebuggerPresent() ) {
3232 StringCbPrintf(message, sizeof(message), "ktc_GetToken returns: %d\n", rc);
3233 OutputDebugString(message);
3235 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3236 if ( rc == KTC_NOCM && retry < 20 ) {
3239 goto retry_gettoken5;
3244 if (atoken.kvno == btoken.kvno &&
3245 atoken.ticketLen == btoken.ticketLen &&
3246 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3247 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3249 /* Success - Nothing to do */
3253 // * Reset the "aclient" structure before we call ktc_SetToken.
3254 // * This structure was first set by the ktc_GetToken call when
3255 // * we were comparing whether identical tokens already existed.
3257 len = min(k5creds->client->data[0].length, sizeof(aclient.name) - 1);
3258 StringCbCopyN( aclient.name, sizeof(aclient.name),
3259 k5creds->client->data[0].data, len);
3261 if ( k5creds->client->length > 1 ) {
3262 StringCbCat( aclient.name, sizeof(aclient.name), ".");
3263 len = min(k5creds->client->data[1].length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3264 StringCbCatN( aclient.name, sizeof(aclient.name),
3265 k5creds->client->data[1].data, len);
3267 aclient.instance[0] = '\0';
3269 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3270 realm_of_cell, sizeof(aclient.cell) - 1);
3272 /* For Khimaira, always append the realm name */
3273 StringCbCat( aclient.name, sizeof(aclient.name), "@");
3274 len = min(k5creds->client->realm.length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3275 StringCbCatN( aclient.name, sizeof(aclient.name), k5creds->client->realm.data, len);
3277 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3278 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3279 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3280 &aclient, &aserver, &atoken);
3283 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3284 smbname, sizeof(aclient.smbname) - 1);
3286 aclient.smbname[0] = '\0';
3288 if ( IsDebuggerPresent() ) {
3290 StringCbPrintf(message, sizeof(message), "aclient.name: %s\n", aclient.name);
3291 OutputDebugString(message);
3292 StringCbPrintf(message, sizeof(message), "aclient.smbname: %s\n", aclient.smbname);
3293 OutputDebugString(message);
3296 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3297 if ( IsDebuggerPresent() ) {
3299 StringCbPrintf(message, sizeof(message), "ktc_SetToken returns: %d\n", rc);
3300 OutputDebugString(message);
3303 goto cleanup; /* We have successfully inserted the token */
3309 /* Otherwise, the ticket could have been too large so try to
3310 * convert using the krb524d running with the KDC
3312 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3313 pkrb5_free_creds(ctx, k5creds);
3315 if ( IsDebuggerPresent() ) {
3317 StringCbPrintf(message, sizeof(message), "krb524_convert_creds_kdc returns: %d\n", code);
3318 OutputDebugString(message);
3323 #endif /* USE_KRB524 */
3327 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3328 if (code == NO_TKT_FIL) {
3329 // if the problem is that we have no krb4 tickets
3330 // do not attempt to continue
3333 if (code != KSUCCESS)
3334 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3336 if (code != KSUCCESS)
3338 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3340 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3345 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3347 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3362 memset(&aserver, '\0', sizeof(aserver));
3363 StringCbCopyN( aserver.name, sizeof(aserver.name), ServiceName, sizeof(aserver.name) - 1);
3364 StringCbCopyN( aserver.cell, sizeof(aserver.cell), CellName, sizeof(aserver.cell) - 1);
3366 memset(&atoken, '\0', sizeof(atoken));
3367 atoken.kvno = creds.kvno;
3368 atoken.startTime = creds.issue_date;
3369 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3370 memcpy(&atoken.sessionKey, creds.session, 8);
3371 atoken.ticketLen = creds.ticket_st.length;
3372 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3375 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3376 if ( IsDebuggerPresent() ) {
3378 StringCbPrintf(message, sizeof(message), "ktc_GetToken returns: %d\n", rc);
3379 OutputDebugString(message);
3381 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3382 if ( rc == KTC_NOCM && retry < 20 ) {
3385 goto retry_gettoken;
3387 KFW_AFS_error(rc, "ktc_GetToken()");
3392 if (atoken.kvno == btoken.kvno &&
3393 atoken.ticketLen == btoken.ticketLen &&
3394 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3395 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3400 // * Reset the "aclient" structure before we call ktc_SetToken.
3401 // * This structure was first set by the ktc_GetToken call when
3402 // * we were comparing whether identical tokens already existed.
3404 StringCbCopyN( aclient.name, sizeof(aclient.name), creds.pname, sizeof(aclient.name) - 1);
3407 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3408 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3410 aclient.instance[0] = '\0';
3412 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3413 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3414 aclient.name[MAXKTCREALMLEN-1] = '\0';
3416 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3417 CellName, sizeof(aclient.cell) - 1);
3419 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3420 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3421 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3422 &aclient, &aserver, &atoken);
3425 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3426 smbname, sizeof(aclient.smbname) - 1);
3428 aclient.smbname[0] = '\0';
3431 if ( IsDebuggerPresent() ) {
3433 StringCbPrintf(message, sizeof(message), "aclient.name: %s\n", aclient.name);
3434 OutputDebugString(message);
3435 StringCbPrintf(message, sizeof(message), "aclient.smbname: %s\n", aclient.smbname);
3436 OutputDebugString(message);
3439 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3441 KFW_AFS_error(rc, "ktc_SetToken()");
3447 if (client_principal)
3448 pkrb5_free_principal(ctx,client_principal);
3449 /* increds.client == client_principal */
3451 pkrb5_free_principal(ctx,increds.server);
3452 if (cc && (cc != alt_cc))
3453 pkrb5_cc_close(ctx, cc);
3454 if (ctx && (ctx != alt_ctx))
3455 pkrb5_free_context(ctx);
3456 if (ak_cellconfig.linkedCell)
3457 free(ak_cellconfig.linkedCell);
3459 return(rc? rc : code);
3462 /**************************************/
3463 /* afs_realm_of_cell(): */
3464 /**************************************/
3466 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3468 static char krbrlm[REALM_SZ+1]="";
3469 char ** realmlist=NULL;
3475 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3476 if ( !r && realmlist && realmlist[0] ) {
3477 StringCbCopyN( krbrlm, sizeof(krbrlm),
3478 realmlist[0], sizeof(krbrlm) - 1);
3479 pkrb5_free_host_realm(ctx, realmlist);
3485 char *t = cellconfig->name;
3490 if (islower(c)) c=toupper(c);
3498 /**************************************/
3499 /* KFW_AFS_get_cellconfig(): */
3500 /**************************************/
3502 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3505 char newcell[CELL_MAXNAMELEN+1];
3506 char linkedcell[CELL_MAXNAMELEN+1]="";
3508 local_cell[0] = (char)0;
3509 memset(cellconfig, 0, sizeof(*cellconfig));
3511 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3512 if (rc = cm_GetRootCellName(local_cell))
3517 if (strlen(cell) == 0)
3518 strcpy(cell, local_cell);
3520 rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3521 if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
3522 rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3525 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3529 StringCbCopyN( cellconfig->name, sizeof(cellconfig->name),
3530 newcell, sizeof(cellconfig->name) - 1);
3532 cellconfig->linkedCell = strdup(linkedcell);
3537 /**************************************/
3538 /* get_cellconfig_callback(): */
3539 /**************************************/
3541 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
3543 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3545 cc->hostAddr[cc->numServers] = *addrp;
3546 StringCbCopyN( cc->hostName[cc->numServers], sizeof(cc->hostName[cc->numServers]),
3547 namep, sizeof(cc->hostName[cc->numServers]) - 1);
3553 /**************************************/
3554 /* KFW_AFS_error(): */
3555 /**************************************/
3557 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3560 const char *errText;
3562 // Using AFS defines as error messages for now, until Transarc
3563 // gets back to me with "string" translations of each of these
3565 if (rc == KTC_ERROR)
3566 errText = "KTC_ERROR";
3567 else if (rc == KTC_TOOBIG)
3568 errText = "KTC_TOOBIG";
3569 else if (rc == KTC_INVAL)
3570 errText = "KTC_INVAL";
3571 else if (rc == KTC_NOENT)
3572 errText = "KTC_NOENT";
3573 else if (rc == KTC_PIOCTLFAIL)
3574 errText = "KTC_PIOCTLFAIL";
3575 else if (rc == KTC_NOPIOCTL)
3576 errText = "KTC_NOPIOCTL";
3577 else if (rc == KTC_NOCELL)
3578 errText = "KTC_NOCELL";
3579 else if (rc == KTC_NOCM)
3580 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3582 errText = "Unknown error!";
3584 StringCbPrintf(message, sizeof(message), "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3586 if ( IsDebuggerPresent() ) {
3587 OutputDebugString(message);
3588 OutputDebugString("\n");