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 <WINNT\afsreg.h>
76 #include "afskfw-int.h"
84 * TIMING _____________________________________________________________________
88 #define cminREMIND_TEST 1 // test every minute for expired creds
89 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
90 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
91 #define cminMINLIFE 30 // minimum life of Kerberos creds
93 #define c100ns1SECOND (LONGLONG)10000000
94 #define cmsec1SECOND 1000
95 #define cmsec1MINUTE 60000
96 #define csec1MINUTE 60
98 /* Function Pointer Declarations for Delayed Loading */
100 DECL_FUNC_PTR(cc_initialize);
101 DECL_FUNC_PTR(cc_shutdown);
102 DECL_FUNC_PTR(cc_get_NC_info);
103 DECL_FUNC_PTR(cc_free_NC_info);
107 DECL_FUNC_PTR(Leash_get_default_lifetime);
108 DECL_FUNC_PTR(Leash_get_default_forwardable);
109 DECL_FUNC_PTR(Leash_get_default_renew_till);
110 DECL_FUNC_PTR(Leash_get_default_noaddresses);
111 DECL_FUNC_PTR(Leash_get_default_proxiable);
112 DECL_FUNC_PTR(Leash_get_default_publicip);
113 DECL_FUNC_PTR(Leash_get_default_use_krb4);
114 DECL_FUNC_PTR(Leash_get_default_life_min);
115 DECL_FUNC_PTR(Leash_get_default_life_max);
116 DECL_FUNC_PTR(Leash_get_default_renew_min);
117 DECL_FUNC_PTR(Leash_get_default_renew_max);
118 DECL_FUNC_PTR(Leash_get_default_renewable);
119 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
123 DECL_FUNC_PTR(krb5_change_password);
124 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
125 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
126 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
127 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
128 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
129 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
130 DECL_FUNC_PTR(krb5_get_init_creds_password);
131 DECL_FUNC_PTR(krb5_build_principal_ext);
132 DECL_FUNC_PTR(krb5_cc_get_name);
133 DECL_FUNC_PTR(krb5_cc_resolve);
134 DECL_FUNC_PTR(krb5_cc_default);
135 DECL_FUNC_PTR(krb5_cc_default_name);
136 DECL_FUNC_PTR(krb5_cc_set_default_name);
137 DECL_FUNC_PTR(krb5_cc_initialize);
138 DECL_FUNC_PTR(krb5_cc_destroy);
139 DECL_FUNC_PTR(krb5_cc_close);
140 DECL_FUNC_PTR(krb5_cc_store_cred);
141 DECL_FUNC_PTR(krb5_cc_copy_creds);
142 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
143 DECL_FUNC_PTR(krb5_cc_get_principal);
144 DECL_FUNC_PTR(krb5_cc_start_seq_get);
145 DECL_FUNC_PTR(krb5_cc_next_cred);
146 DECL_FUNC_PTR(krb5_cc_end_seq_get);
147 DECL_FUNC_PTR(krb5_cc_remove_cred);
148 DECL_FUNC_PTR(krb5_cc_set_flags);
149 DECL_FUNC_PTR(krb5_cc_get_type);
150 DECL_FUNC_PTR(krb5_free_context);
151 DECL_FUNC_PTR(krb5_free_cred_contents);
152 DECL_FUNC_PTR(krb5_free_principal);
153 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
154 DECL_FUNC_PTR(krb5_init_context);
155 DECL_FUNC_PTR(krb5_parse_name);
156 DECL_FUNC_PTR(krb5_timeofday);
157 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
158 DECL_FUNC_PTR(krb5_unparse_name);
159 DECL_FUNC_PTR(krb5_get_credentials);
160 DECL_FUNC_PTR(krb5_mk_req);
161 DECL_FUNC_PTR(krb5_sname_to_principal);
162 DECL_FUNC_PTR(krb5_get_credentials_renew);
163 DECL_FUNC_PTR(krb5_free_data);
164 DECL_FUNC_PTR(krb5_free_data_contents);
165 DECL_FUNC_PTR(krb5_free_unparsed_name);
166 DECL_FUNC_PTR(krb5_os_localaddr);
167 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
168 DECL_FUNC_PTR(krb5_copy_data);
169 DECL_FUNC_PTR(krb5_free_creds);
170 DECL_FUNC_PTR(krb5_build_principal);
171 DECL_FUNC_PTR(krb5_get_renewed_creds);
172 DECL_FUNC_PTR(krb5_get_default_config_files);
173 DECL_FUNC_PTR(krb5_free_config_files);
174 DECL_FUNC_PTR(krb5_get_default_realm);
175 DECL_FUNC_PTR(krb5_free_default_realm);
176 DECL_FUNC_PTR(krb5_free_ticket);
177 DECL_FUNC_PTR(krb5_decode_ticket);
178 DECL_FUNC_PTR(krb5_get_host_realm);
179 DECL_FUNC_PTR(krb5_free_host_realm);
180 DECL_FUNC_PTR(krb5_free_addresses);
181 DECL_FUNC_PTR(krb5_c_random_make_octets);
183 // Krb5 KFW 3.2 functions
184 DECL_FUNC_PTR(krb5_get_error_message);
185 DECL_FUNC_PTR(krb5_free_error_message);
189 DECL_FUNC_PTR(krb524_init_ets);
190 DECL_FUNC_PTR(krb524_convert_creds_kdc);
195 DECL_FUNC_PTR(krb_get_cred);
196 DECL_FUNC_PTR(tkt_string);
197 DECL_FUNC_PTR(krb_get_tf_realm);
198 DECL_FUNC_PTR(krb_mk_req);
202 DECL_FUNC_PTR(com_err);
203 DECL_FUNC_PTR(error_message);
206 DECL_FUNC_PTR(profile_init);
207 DECL_FUNC_PTR(profile_release);
208 DECL_FUNC_PTR(profile_get_subsection_names);
209 DECL_FUNC_PTR(profile_free_list);
210 DECL_FUNC_PTR(profile_get_string);
211 DECL_FUNC_PTR(profile_release_string);
214 DECL_FUNC_PTR(OpenSCManagerA);
215 DECL_FUNC_PTR(OpenServiceA);
216 DECL_FUNC_PTR(QueryServiceStatus);
217 DECL_FUNC_PTR(CloseServiceHandle);
219 DECL_FUNC_PTR(LsaNtStatusToWinError);
220 #endif /* USE_MS2MIT */
224 DECL_FUNC_PTR(LsaConnectUntrusted);
225 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
226 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
227 DECL_FUNC_PTR(LsaFreeReturnBuffer);
228 DECL_FUNC_PTR(LsaGetLogonSessionData);
229 #endif /* USE_MS2MIT */
232 FUNC_INFO ccapi_fi[] = {
233 MAKE_FUNC_INFO(cc_initialize),
234 MAKE_FUNC_INFO(cc_shutdown),
235 MAKE_FUNC_INFO(cc_get_NC_info),
236 MAKE_FUNC_INFO(cc_free_NC_info),
241 FUNC_INFO leash_fi[] = {
242 MAKE_FUNC_INFO(Leash_get_default_lifetime),
243 MAKE_FUNC_INFO(Leash_get_default_renew_till),
244 MAKE_FUNC_INFO(Leash_get_default_forwardable),
245 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
246 MAKE_FUNC_INFO(Leash_get_default_proxiable),
247 MAKE_FUNC_INFO(Leash_get_default_publicip),
248 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
249 MAKE_FUNC_INFO(Leash_get_default_life_min),
250 MAKE_FUNC_INFO(Leash_get_default_life_max),
251 MAKE_FUNC_INFO(Leash_get_default_renew_min),
252 MAKE_FUNC_INFO(Leash_get_default_renew_max),
253 MAKE_FUNC_INFO(Leash_get_default_renewable),
257 FUNC_INFO leash_opt_fi[] = {
258 MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
263 FUNC_INFO k5_fi[] = {
264 MAKE_FUNC_INFO(krb5_change_password),
265 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
266 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
267 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
268 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
269 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
270 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
271 MAKE_FUNC_INFO(krb5_get_init_creds_password),
272 MAKE_FUNC_INFO(krb5_build_principal_ext),
273 MAKE_FUNC_INFO(krb5_cc_get_name),
274 MAKE_FUNC_INFO(krb5_cc_resolve),
275 MAKE_FUNC_INFO(krb5_cc_default),
276 MAKE_FUNC_INFO(krb5_cc_default_name),
277 MAKE_FUNC_INFO(krb5_cc_set_default_name),
278 MAKE_FUNC_INFO(krb5_cc_initialize),
279 MAKE_FUNC_INFO(krb5_cc_destroy),
280 MAKE_FUNC_INFO(krb5_cc_close),
281 MAKE_FUNC_INFO(krb5_cc_copy_creds),
282 MAKE_FUNC_INFO(krb5_cc_store_cred),
283 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
284 MAKE_FUNC_INFO(krb5_cc_get_principal),
285 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
286 MAKE_FUNC_INFO(krb5_cc_next_cred),
287 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
288 MAKE_FUNC_INFO(krb5_cc_remove_cred),
289 MAKE_FUNC_INFO(krb5_cc_set_flags),
290 MAKE_FUNC_INFO(krb5_cc_get_type),
291 MAKE_FUNC_INFO(krb5_free_context),
292 MAKE_FUNC_INFO(krb5_free_cred_contents),
293 MAKE_FUNC_INFO(krb5_free_principal),
294 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
295 MAKE_FUNC_INFO(krb5_init_context),
296 MAKE_FUNC_INFO(krb5_parse_name),
297 MAKE_FUNC_INFO(krb5_timeofday),
298 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
299 MAKE_FUNC_INFO(krb5_unparse_name),
300 MAKE_FUNC_INFO(krb5_get_credentials),
301 MAKE_FUNC_INFO(krb5_mk_req),
302 MAKE_FUNC_INFO(krb5_sname_to_principal),
303 MAKE_FUNC_INFO(krb5_get_credentials_renew),
304 MAKE_FUNC_INFO(krb5_free_data),
305 MAKE_FUNC_INFO(krb5_free_data_contents),
306 MAKE_FUNC_INFO(krb5_free_unparsed_name),
307 MAKE_FUNC_INFO(krb5_os_localaddr),
308 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
309 MAKE_FUNC_INFO(krb5_copy_data),
310 MAKE_FUNC_INFO(krb5_free_creds),
311 MAKE_FUNC_INFO(krb5_build_principal),
312 MAKE_FUNC_INFO(krb5_get_renewed_creds),
313 MAKE_FUNC_INFO(krb5_free_addresses),
314 MAKE_FUNC_INFO(krb5_get_default_config_files),
315 MAKE_FUNC_INFO(krb5_free_config_files),
316 MAKE_FUNC_INFO(krb5_get_default_realm),
317 MAKE_FUNC_INFO(krb5_free_default_realm),
318 MAKE_FUNC_INFO(krb5_free_ticket),
319 MAKE_FUNC_INFO(krb5_decode_ticket),
320 MAKE_FUNC_INFO(krb5_get_host_realm),
321 MAKE_FUNC_INFO(krb5_free_host_realm),
322 MAKE_FUNC_INFO(krb5_free_addresses),
323 MAKE_FUNC_INFO(krb5_c_random_make_octets),
327 FUNC_INFO k5_kfw_32_fi[] = {
328 MAKE_FUNC_INFO(krb5_get_error_message),
329 MAKE_FUNC_INFO(krb5_free_error_message),
334 FUNC_INFO k4_fi[] = {
335 MAKE_FUNC_INFO(krb_get_cred),
336 MAKE_FUNC_INFO(krb_get_tf_realm),
337 MAKE_FUNC_INFO(krb_mk_req),
338 MAKE_FUNC_INFO(tkt_string),
344 FUNC_INFO k524_fi[] = {
345 MAKE_FUNC_INFO(krb524_init_ets),
346 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
351 FUNC_INFO profile_fi[] = {
352 MAKE_FUNC_INFO(profile_init),
353 MAKE_FUNC_INFO(profile_release),
354 MAKE_FUNC_INFO(profile_get_subsection_names),
355 MAKE_FUNC_INFO(profile_free_list),
356 MAKE_FUNC_INFO(profile_get_string),
357 MAKE_FUNC_INFO(profile_release_string),
361 FUNC_INFO ce_fi[] = {
362 MAKE_FUNC_INFO(com_err),
363 MAKE_FUNC_INFO(error_message),
367 FUNC_INFO service_fi[] = {
368 MAKE_FUNC_INFO(OpenSCManagerA),
369 MAKE_FUNC_INFO(OpenServiceA),
370 MAKE_FUNC_INFO(QueryServiceStatus),
371 MAKE_FUNC_INFO(CloseServiceHandle),
373 MAKE_FUNC_INFO(LsaNtStatusToWinError),
374 #endif /* USE_MS2MIT */
379 FUNC_INFO lsa_fi[] = {
380 MAKE_FUNC_INFO(LsaConnectUntrusted),
381 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
382 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
383 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
384 MAKE_FUNC_INFO(LsaGetLogonSessionData),
387 #endif /* USE_MS2MIT */
389 /* Static Prototypes */
390 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
391 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *, unsigned short);
392 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
393 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
394 void *data, const char *name, const char *banner, int num_prompts,
395 krb5_prompt prompts[]);
398 /* Static Declarations */
399 static int inited = 0;
400 static int mid_cnt = 0;
401 static struct textField * mid_tb = NULL;
402 static HINSTANCE hKrb5 = 0;
403 static HINSTANCE hKrb5_kfw_32 = 0;
405 static HINSTANCE hKrb4 = 0;
406 #endif /* USE_KRB4 */
408 static HINSTANCE hKrb524 = 0;
411 static HINSTANCE hSecur32 = 0;
412 #endif /* USE_MS2MIT */
413 static HINSTANCE hAdvApi32 = 0;
414 static HINSTANCE hComErr = 0;
415 static HINSTANCE hService = 0;
416 static HINSTANCE hProfile = 0;
418 static HINSTANCE hLeash = 0;
419 static HINSTANCE hLeashOpt = 0;
421 static HINSTANCE hCCAPI = 0;
422 static struct principal_ccache_data * princ_cc_data = NULL;
423 static struct cell_principal_map * cell_princ_map = NULL;
426 #define DEFAULT_LIFETIME pLeash_get_default_lifetime()
428 #define DEFAULT_LIFETIME (24 * 60)
434 static int inited = 0;
437 char mutexName[MAX_PATH];
438 HANDLE hMutex = NULL;
440 StringCbPrintf( mutexName, sizeof(mutexName), "AFS KFW Init pid=%d", getpid());
442 hMutex = CreateMutex( NULL, TRUE, mutexName );
443 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
444 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
450 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
451 LoadFuncs(KRB5_DLL, k5_kfw_32_fi, &hKrb5_kfw_32, 0, 1, 0, 0);
452 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
453 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
455 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
456 #endif /* USE_KRB4 */
457 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
459 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
460 #endif /* USE_MS2MIT */
462 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
465 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
466 LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
468 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
470 if ( KFW_is_available() ) {
471 char rootcell[CELL_MAXNAMELEN+1];
473 KFW_import_windows_lsa();
474 #endif /* USE_MS2MIT */
475 KFW_import_ccache_data();
476 KFW_AFS_renew_expiring_tokens();
478 /* WIN32 NOTE: no way to get max chars */
479 if (!cm_GetRootCellName(rootcell))
480 KFW_AFS_renew_token_for_cell(rootcell);
483 ReleaseMutex(hMutex);
493 FreeLibrary(hLeashOpt);
499 FreeLibrary(hKrb524);
505 FreeLibrary(hSecur32);
506 #endif /* USE_MS2MIT */
508 FreeLibrary(hService);
510 FreeLibrary(hComErr);
512 FreeLibrary(hProfile);
516 #endif /* USE_KRB4 */
520 FreeLibrary(hKrb5_kfw_32);
523 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
526 static int init = TRUE;
527 static int bIsWow64 = FALSE;
531 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
533 hModule = GetModuleHandle(TEXT("kernel32"));
535 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
537 if (NULL != fnIsWow64Process)
539 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
541 // on error, assume FALSE.
542 // in other words, do nothing.
545 FreeLibrary(hModule);
553 KFW_accept_dotted_usernames(void)
559 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
560 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
561 if (code == ERROR_SUCCESS) {
563 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
564 (BYTE *) &value, &len);
565 RegCloseKey(parmKey);
567 if (code != ERROR_SUCCESS) {
568 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
569 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
570 if (code == ERROR_SUCCESS) {
572 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
573 (BYTE *) &value, &len);
574 RegCloseKey (parmKey);
588 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
589 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
590 if (code == ERROR_SUCCESS) {
591 len = sizeof(use524);
592 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
593 (BYTE *) &use524, &len);
594 RegCloseKey(parmKey);
596 if (code != ERROR_SUCCESS) {
597 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
598 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
599 if (code == ERROR_SUCCESS) {
600 len = sizeof(use524);
601 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
602 (BYTE *) &use524, &len);
603 RegCloseKey (parmKey);
610 KFW_is_available(void)
616 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
617 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
618 if (code == ERROR_SUCCESS) {
619 len = sizeof(enableKFW);
620 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
621 (BYTE *) &enableKFW, &len);
622 RegCloseKey (parmKey);
625 if (code != ERROR_SUCCESS) {
626 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
627 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
628 if (code == ERROR_SUCCESS) {
629 len = sizeof(enableKFW);
630 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
631 (BYTE *) &enableKFW, &len);
632 RegCloseKey (parmKey);
640 if ( hKrb5 && hComErr && hService &&
643 #endif /* USE_MS2MIT */
656 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
657 int FreeContextFlag, krb5_context * ctx,
662 int krb5Error = ((int)(rc & 255));
674 if (pkrb5_get_error_message)
675 errText = pkrb5_get_error_message(ctx, rc);
677 errText = perror_message(rc);
678 StringCbPrintf(message, sizeof(message),
679 "%s\n(Kerberos error %ld)\n\n%s failed",
683 if (pkrb5_free_error_message)
684 pkrb5_free_error_message(ctx, (char *)errText);
686 if ( IsDebuggerPresent() )
687 OutputDebugString(message);
689 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
692 if (FreeContextFlag == 1)
694 if (ctx && *ctx != NULL)
696 if (cache && *cache != NULL) {
697 pkrb5_cc_close(*ctx, *cache);
701 pkrb5_free_context(*ctx);
710 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
712 struct principal_ccache_data * next = princ_cc_data;
713 krb5_principal principal = 0;
715 const char * ccname = NULL;
716 const char * cctype = NULL;
717 char * ccfullname = NULL;
718 krb5_error_code code = 0;
719 krb5_error_code cc_code = 0;
725 if (ctx == 0 || cc == 0)
728 code = pkrb5_cc_get_principal(ctx, cc, &principal);
731 code = pkrb5_unparse_name(ctx, principal, &pname);
732 if ( code ) goto cleanup;
734 ccname = pkrb5_cc_get_name(ctx, cc);
735 if (!ccname) goto cleanup;
737 cctype = pkrb5_cc_get_type(ctx, cc);
738 if (!cctype) goto cleanup;
740 ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
741 if (!ccfullname) goto cleanup;
743 StringCbPrintf(ccfullname, sizeof(ccfullname), "%s:%s", cctype, ccname);
745 // Search the existing list to see if we have a match
747 for ( ; next ; next = next->next ) {
748 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
753 // If not, match add a new node to the beginning of the list and assign init it
755 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
756 next->next = princ_cc_data;
757 princ_cc_data = next;
758 next->principal = _strdup(pname);
759 next->ccache_name = ccfullname;
761 next->from_lsa = lsa;
763 next->expiration_time = 0;
767 flags = 0; // turn off OPENCLOSE mode
768 code = pkrb5_cc_set_flags(ctx, cc, flags);
769 if ( code ) goto cleanup;
771 code = pkrb5_timeofday(ctx, &now);
773 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
775 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
776 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
778 // we found the ticket we are looking for
779 // check validity of timestamp
780 // We add a 5 minutes fudge factor to compensate for potential
781 // clock skew errors between the KDC and client OS
783 valid = ((creds.times.starttime > 0) &&
784 now >= (creds.times.starttime - 300) &&
785 now < (creds.times.endtime + 300) &&
786 !(creds.ticket_flags & TKT_FLG_INVALID));
788 if ( next->from_lsa) {
790 next->expiration_time = creds.times.endtime;
792 } else if ( valid ) {
794 next->expiration_time = creds.times.endtime;
795 next->renew = (creds.times.renew_till > creds.times.endtime) &&
796 (creds.ticket_flags & TKT_FLG_RENEWABLE);
799 next->expiration_time = 0;
803 pkrb5_free_cred_contents(ctx, &creds);
804 cc_code = KRB5_CC_END;
807 pkrb5_free_cred_contents(ctx, &creds);
810 if (cc_code == KRB5_CC_END) {
811 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
812 if (code) goto cleanup;
816 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
817 code = pkrb5_cc_set_flags(ctx, cc, flags);
822 pkrb5_free_unparsed_name(ctx,pname);
824 pkrb5_free_principal(ctx,principal);
828 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
830 struct principal_ccache_data * next = princ_cc_data;
831 char * response = NULL;
833 if ( !principal || !ccache )
837 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
839 // we always want to prefer the MS Kerberos LSA cache or
840 // the cache afscreds created specifically for the principal
841 // if the current entry is either one, drop the previous find
842 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
845 response = _strdup(next->ccache_name);
846 // MS Kerberos LSA is our best option so use it and quit
847 if ( next->from_lsa )
861 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
863 struct principal_ccache_data ** next = &princ_cc_data;
865 if ( !pname && !ccname )
869 if ( !strcmp((*next)->principal,pname) ||
870 !strcmp((*next)->ccache_name,ccname) ) {
872 free((*next)->principal);
873 free((*next)->ccache_name);
875 (*next) = (*next)->next;
882 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
884 struct cell_principal_map * next = cell_princ_map;
886 // Search the existing list to see if we have a match
888 for ( ; next ; next = next->next ) {
889 if ( !strcmp(next->cell, cell) ) {
890 if ( !strcmp(next->principal,pname) ) {
891 next->active = active;
894 // OpenAFS currently has a restriction of one active token per cell
895 // Therefore, whenever we update the table with a new active cell we
896 // must mark all of the other principal to cell entries as inactive.
904 // If not, match add a new node to the beginning of the list and assign init it
906 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
907 next->next = cell_princ_map;
908 cell_princ_map = next;
909 next->principal = _strdup(pname);
910 next->cell = _strdup(cell);
911 next->active = active;
916 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
918 struct cell_principal_map ** next = &cell_princ_map;
920 if ( !pname && !cell )
924 if ( !strcmp((*next)->principal,pname) ||
925 !strcmp((*next)->cell,cell) ) {
927 free((*next)->principal);
930 (*next) = (*next)->next;
936 // Returns (if possible) a principal which has been known in
937 // the past to have been used to obtain tokens for the specified
939 // TODO: Attempt to return one which has not yet expired by checking
940 // the principal/ccache data
942 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
944 struct cell_principal_map * next_map = cell_princ_map;
945 const char * princ = NULL;
952 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
955 next_map = next_map->next;
958 if ( !principals || !count )
961 *principals = (char **) malloc(sizeof(char *) * count);
962 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
964 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
965 (*principals)[i++] = _strdup(next_map->principal);
972 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
975 struct cell_principal_map * next_map = cell_princ_map;
976 const char * princ = NULL;
982 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
985 next_map = next_map->next;
991 *cells = (char **) malloc(sizeof(char *) * count);
992 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
994 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
995 (*cells)[i++] = _strdup(next_map->cell);
1001 /* Given a principal return an existing ccache or create one and return */
1003 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
1005 krb5_context ctx = NULL;
1006 char * pname = NULL;
1007 char * ccname = NULL;
1008 krb5_error_code code;
1010 if (!pkrb5_init_context)
1011 return KRB5_CONFIG_CANTOPEN;
1016 code = pkrb5_init_context(&ctx);
1017 if (code) goto cleanup;
1021 code = pkrb5_unparse_name(ctx, principal, &pname);
1022 if (code) goto cleanup;
1024 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
1025 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
1026 size_t len = strlen(pname) + 5;
1027 ccname = (char *)malloc(len);
1028 StringCbPrintf(ccname, len, "API:%s", pname);
1030 code = pkrb5_cc_resolve(ctx, ccname, cc);
1032 code = pkrb5_cc_default(ctx, cc);
1033 if (code) goto cleanup;
1040 pkrb5_free_unparsed_name(ctx,pname);
1041 if (ctx && (ctx != alt_ctx))
1042 pkrb5_free_context(ctx);
1047 // Import Microsoft Credentials into a new MIT ccache
1049 KFW_import_windows_lsa(void)
1051 krb5_context ctx = NULL;
1052 krb5_ccache cc = NULL;
1053 krb5_principal princ = NULL;
1054 char * pname = NULL;
1055 krb5_data * princ_realm;
1056 krb5_error_code code;
1057 char cell[128]="", realm[128]="", *def_realm = 0;
1059 DWORD dwMsLsaImport;
1061 if (!pkrb5_init_context)
1064 code = pkrb5_init_context(&ctx);
1065 if (code) goto cleanup;
1067 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
1068 if (code) goto cleanup;
1070 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
1072 code = pkrb5_cc_get_principal(ctx, cc, &princ);
1073 if ( code ) goto cleanup;
1076 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
1080 switch ( dwMsLsaImport ) {
1081 case 0: /* do not import */
1083 case 1: /* always import */
1085 case 2: { /* matching realm */
1086 char ms_realm[128] = "", *r;
1089 for ( r=ms_realm, j=0; j<krb5_princ_realm(ctx, princ)->length; r++, j++ ) {
1090 *r = krb5_princ_realm(ctx, princ)->data[j];
1094 if (code = pkrb5_get_default_realm(ctx, &def_realm))
1097 if (strcmp(def_realm, ms_realm))
1105 code = pkrb5_unparse_name(ctx,princ,&pname);
1106 if ( code ) goto cleanup;
1108 princ_realm = krb5_princ_realm(ctx, princ);
1109 for ( i=0; i<princ_realm->length; i++ ) {
1110 realm[i] = princ_realm->data[i];
1111 cell[i] = tolower(princ_realm->data[i]);
1116 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, DEFAULT_LIFETIME, NULL);
1117 if ( IsDebuggerPresent() ) {
1119 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1120 OutputDebugString(message);
1122 if ( code ) goto cleanup;
1124 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1128 pkrb5_free_unparsed_name(ctx,pname);
1130 pkrb5_free_principal(ctx,princ);
1132 pkrb5_free_default_realm(ctx, def_realm);
1134 pkrb5_cc_close(ctx,cc);
1136 pkrb5_free_context(ctx);
1138 #endif /* USE_MS2MIT */
1140 // If there are existing MIT credentials, copy them to a new
1141 // ccache named after the principal
1143 // Enumerate all existing MIT ccaches and construct entries
1144 // in the principal_ccache table
1146 // Enumerate all existing AFS Tokens and construct entries
1147 // in the cell_principal table
1149 KFW_import_ccache_data(void)
1151 krb5_context ctx = NULL;
1152 krb5_ccache cc = NULL;
1153 krb5_principal principal = NULL;
1155 krb5_error_code code;
1156 krb5_error_code cc_code;
1158 apiCB * cc_ctx = NULL;
1159 struct _infoNC ** pNCi = NULL;
1162 if ( !pcc_initialize )
1165 if ( IsDebuggerPresent() )
1166 OutputDebugString("KFW_import_ccache_data()\n");
1168 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1169 if (code) goto cleanup;
1171 code = pcc_get_NC_info(cc_ctx, &pNCi);
1172 if (code) goto cleanup;
1174 code = pkrb5_init_context(&ctx);
1175 if (code) goto cleanup;
1177 for ( i=0; pNCi[i]; i++ ) {
1178 if ( pNCi[i]->vers != CC_CRED_V5 )
1180 if ( IsDebuggerPresent() ) {
1181 OutputDebugString("Principal: ");
1182 OutputDebugString(pNCi[i]->principal);
1183 OutputDebugString(" in ccache ");
1184 OutputDebugString(pNCi[i]->name);
1185 OutputDebugString("\n");
1187 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1188 && strcmp(pNCi[i]->name,LSA_CCNAME)
1191 for ( j=0; pNCi[j]; j++ ) {
1192 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1198 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1199 if (code) goto loop_cleanup;
1202 krb5_ccache oldcc = 0;
1204 if ( IsDebuggerPresent() )
1205 OutputDebugString("copying ccache data to new ccache\n");
1207 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1208 if (code) goto loop_cleanup;
1209 code = pkrb5_cc_initialize(ctx, cc, principal);
1210 if (code) goto loop_cleanup;
1212 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1213 if (code) goto loop_cleanup;
1214 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1216 code = pkrb5_cc_close(ctx,cc);
1218 code = pkrb5_cc_close(ctx,oldcc);
1220 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1223 code = pkrb5_cc_close(ctx,oldcc);
1226 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1227 if (code) goto loop_cleanup;
1230 flags = 0; // turn off OPENCLOSE mode
1231 code = pkrb5_cc_set_flags(ctx, cc, flags);
1232 if ( code ) goto cleanup;
1234 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1236 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1238 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1239 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1240 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1241 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1242 if ( sname && cell && !strcmp("afs",sname->data) ) {
1243 struct ktc_principal aserver;
1244 struct ktc_principal aclient;
1245 struct ktc_token atoken;
1248 if ( IsDebuggerPresent() ) {
1249 OutputDebugString("Found AFS ticket: ");
1250 OutputDebugString(sname->data);
1252 OutputDebugString("/");
1253 OutputDebugString(cell->data);
1255 OutputDebugString("@");
1256 OutputDebugString(realm->data);
1257 OutputDebugString("\n");
1260 memset(&aserver, '\0', sizeof(aserver));
1261 StringCbCopyN( aserver.name, sizeof(aserver.name),
1262 sname->data, sizeof(aserver.name) - 1);
1263 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
1264 cell->data, sizeof(aserver.cell) - 1);
1266 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1268 // Found a token in AFS Client Server which matches
1269 char pname[128], *p, *q;
1270 for ( p=pname, q=aclient.name; *q; p++, q++)
1272 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1276 if ( IsDebuggerPresent() ) {
1277 OutputDebugString("Found AFS token: ");
1278 OutputDebugString(pname);
1279 OutputDebugString("\n");
1282 if ( strcmp(pname,pNCi[i]->principal) )
1284 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1286 // Attempt to import it
1287 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1289 if ( IsDebuggerPresent() ) {
1290 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1293 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data, DEFAULT_LIFETIME, NULL);
1294 if ( IsDebuggerPresent() ) {
1296 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1297 OutputDebugString(message);
1300 } else if ( IsDebuggerPresent() ) {
1301 OutputDebugString("Found ticket: ");
1302 OutputDebugString(sname->data);
1303 if ( cell && cell->data ) {
1304 OutputDebugString("/");
1305 OutputDebugString(cell->data);
1307 OutputDebugString("@");
1308 OutputDebugString(realm->data);
1309 OutputDebugString("\n");
1311 pkrb5_free_cred_contents(ctx, &creds);
1314 if (cc_code == KRB5_CC_END) {
1315 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1316 if (cc_code) goto loop_cleanup;
1320 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1321 code = pkrb5_cc_set_flags(ctx, cc, flags);
1323 pkrb5_cc_close(ctx,cc);
1327 pkrb5_free_principal(ctx,principal);
1334 pkrb5_free_context(ctx);
1336 pcc_free_NC_info(cc_ctx, &pNCi);
1338 pcc_shutdown(&cc_ctx);
1343 KFW_AFS_get_cred( char * username,
1350 static char reason[1024]="";
1351 krb5_context ctx = NULL;
1352 krb5_ccache cc = NULL;
1353 char * realm = NULL, * userrealm = NULL;
1354 krb5_principal principal = NULL;
1355 char * pname = NULL;
1356 krb5_error_code code;
1357 char local_cell[CELL_MAXNAMELEN+1];
1358 char **cells = NULL;
1360 struct afsconf_cell cellconfig;
1363 if (!pkrb5_init_context)
1364 return KRB5_CONFIG_CANTOPEN;
1366 if ( IsDebuggerPresent() ) {
1367 OutputDebugString("KFW_AFS_get_cred for token ");
1368 OutputDebugString(username);
1369 OutputDebugString(" in cell ");
1370 OutputDebugString(cell);
1371 OutputDebugString("\n");
1374 memset(&cellconfig, 0, sizeof(cellconfig));
1376 code = pkrb5_init_context(&ctx);
1377 if ( code ) goto cleanup;
1379 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1380 if ( code ) goto cleanup;
1382 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1384 userrealm = strchr(username,'@');
1386 pname = strdup(username);
1387 if (!KFW_accept_dotted_usernames()) {
1388 userrealm = strchr(pname, '@');
1391 /* handle kerberos iv notation */
1392 while ( dot = strchr(pname,'.') ) {
1398 size_t len = strlen(username) + strlen(realm) + 2;
1399 pname = malloc(len);
1400 if (pname == NULL) {
1401 code = KRB5KRB_ERR_GENERIC;
1404 StringCbCopy(pname, len, username);
1406 if (!KFW_accept_dotted_usernames()) {
1407 /* handle kerberos iv notation */
1408 while ( dot = strchr(pname,'.') ) {
1412 StringCbCat( pname, len, "@");
1413 StringCbCat( pname, len, realm);
1415 if ( IsDebuggerPresent() ) {
1416 OutputDebugString("Realm of Cell: ");
1417 OutputDebugString(realm);
1418 OutputDebugString("\n");
1419 OutputDebugString("Realm of User: ");
1420 OutputDebugString(userrealm);
1421 OutputDebugString("\n");
1424 code = pkrb5_parse_name(ctx, pname, &principal);
1425 if ( code ) goto cleanup;
1427 code = KFW_get_ccache(ctx, principal, &cc);
1428 if ( code ) goto cleanup;
1430 if ( lifetime == 0 )
1431 lifetime = DEFAULT_LIFETIME;
1433 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1434 if ( IsDebuggerPresent() ) {
1436 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1437 OutputDebugString(message);
1440 if (code && password && password[0] ) {
1441 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1446 0, /* forwardable */
1447 0, /* not proxiable */
1449 1, /* noaddresses */
1450 0 /* no public ip */
1452 pLeash_get_default_forwardable(),
1453 pLeash_get_default_proxiable(),
1454 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1455 pLeash_get_default_noaddresses(),
1456 pLeash_get_default_publicip()
1457 #endif /* USE_LEASH */
1460 if ( IsDebuggerPresent() ) {
1462 StringCbPrintf(message, sizeof(message), "KFW_kinit() returns: %d\n", code);
1463 OutputDebugString(message);
1465 if ( code ) goto cleanup;
1467 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1470 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1471 if ( IsDebuggerPresent() ) {
1473 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1474 OutputDebugString(message);
1476 if ( code ) goto cleanup;
1478 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1480 // Attempt to obtain new tokens for other cells supported by the same
1482 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1483 if ( cell_count > 1 ) {
1484 while ( cell_count-- ) {
1485 if ( strcmp(cells[cell_count],cell) ) {
1486 if ( IsDebuggerPresent() ) {
1488 StringCbPrintf(message, sizeof(message),
1489 "found another cell for the same principal: %s\n", cell);
1490 OutputDebugString(message);
1493 if (cellconfig.linkedCell) {
1494 free(cellconfig.linkedCell);
1495 cellconfig.linkedCell = NULL;
1497 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1498 if ( code ) continue;
1500 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1501 if ( IsDebuggerPresent() ) {
1502 OutputDebugString("Realm: ");
1503 OutputDebugString(realm);
1504 OutputDebugString("\n");
1507 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1508 if ( IsDebuggerPresent() ) {
1510 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1511 OutputDebugString(message);
1514 free(cells[cell_count]);
1517 } else if ( cell_count == 1 ) {
1526 pkrb5_cc_close(ctx, cc);
1527 if ( cellconfig.linkedCell )
1528 free(cellconfig.linkedCell);
1530 if ( code && reasonP ) {
1531 if (pkrb5_get_error_message) {
1532 char *msg = pkrb5_get_error_message(ctx, code);
1533 StringCbCopyN( reason, sizeof(reason),
1534 msg, sizeof(reason) - 1);
1536 pkrb5_free_error_message(ctx, msg);
1538 *reasonP = perror_message(code);
1545 KFW_AFS_destroy_tickets_for_cell(char * cell)
1547 krb5_context ctx = NULL;
1548 krb5_error_code code;
1550 char ** principals = NULL;
1552 if (!pkrb5_init_context)
1553 return KRB5_CONFIG_CANTOPEN;
1555 if ( IsDebuggerPresent() ) {
1556 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1557 OutputDebugString(cell);
1558 OutputDebugString("\n");
1561 code = pkrb5_init_context(&ctx);
1564 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1566 krb5_principal princ = 0;
1570 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1571 if ( cell_count > 1 ) {
1572 // TODO - What we really should do here is verify whether or not any of the
1573 // other cells which use this principal to obtain its credentials actually
1574 // have valid tokens or not. If they are currently using these credentials
1575 // we will skip them. For the time being we assume that if there is an active
1576 // map in the table that they are actively being used.
1580 code = pkrb5_parse_name(ctx, principals[count], &princ);
1581 if (code) goto loop_cleanup;
1583 code = KFW_get_ccache(ctx, princ, &cc);
1584 if (code) goto loop_cleanup;
1586 code = pkrb5_cc_destroy(ctx, cc);
1591 pkrb5_cc_close(ctx, cc);
1595 pkrb5_free_principal(ctx, princ);
1599 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1600 free(principals[count]);
1605 pkrb5_free_context(ctx);
1610 KFW_AFS_destroy_tickets_for_principal(char * user)
1612 krb5_context ctx = NULL;
1613 krb5_error_code code;
1615 char ** cells = NULL;
1616 krb5_principal princ = NULL;
1617 krb5_ccache cc = NULL;
1619 if (!pkrb5_init_context)
1620 return KRB5_CONFIG_CANTOPEN;
1622 if ( IsDebuggerPresent() ) {
1623 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1624 OutputDebugString(user);
1625 OutputDebugString("\n");
1628 code = pkrb5_init_context(&ctx);
1631 code = pkrb5_parse_name(ctx, user, &princ);
1632 if (code) goto loop_cleanup;
1634 code = KFW_get_ccache(ctx, princ, &cc);
1635 if (code) goto loop_cleanup;
1637 code = pkrb5_cc_destroy(ctx, cc);
1642 pkrb5_cc_close(ctx, cc);
1646 pkrb5_free_principal(ctx, princ);
1650 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1653 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1660 pkrb5_free_context(ctx);
1665 KFW_AFS_renew_expiring_tokens(void)
1667 krb5_error_code code = 0;
1668 krb5_context ctx = NULL;
1669 krb5_ccache cc = NULL;
1671 struct principal_ccache_data * pcc_next = princ_cc_data;
1674 const char * realm = NULL;
1675 char local_cell[CELL_MAXNAMELEN+1]="";
1676 struct afsconf_cell cellconfig;
1678 if (!pkrb5_init_context)
1679 return KRB5_CONFIG_CANTOPEN;
1681 if ( pcc_next == NULL ) // nothing to do
1684 if ( IsDebuggerPresent() ) {
1685 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1688 memset(&cellconfig, 0, sizeof(cellconfig));
1690 code = pkrb5_init_context(&ctx);
1691 if (code) goto cleanup;
1693 code = pkrb5_timeofday(ctx, &now);
1694 if (code) goto cleanup;
1696 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1697 if ( pcc_next->expired )
1700 if ( now >= (pcc_next->expiration_time) ) {
1701 if ( !pcc_next->from_lsa ) {
1702 pcc_next->expired = 1;
1707 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1708 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1711 code = KFW_renew(ctx,cc);
1713 if ( code && pcc_next->from_lsa)
1715 #endif /* USE_MS2MIT */
1718 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1719 if (code) goto loop_cleanup;
1721 // Attempt to obtain new tokens for other cells supported by the same
1723 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1724 if ( cell_count > 0 ) {
1725 while ( cell_count-- ) {
1726 if ( IsDebuggerPresent() ) {
1727 OutputDebugString("Cell: ");
1728 OutputDebugString(cells[cell_count]);
1729 OutputDebugString("\n");
1731 if (cellconfig.linkedCell) {
1732 free(cellconfig.linkedCell);
1733 cellconfig.linkedCell = NULL;
1735 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1736 if ( code ) continue;
1737 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1738 if ( IsDebuggerPresent() ) {
1739 OutputDebugString("Realm: ");
1740 OutputDebugString(realm);
1741 OutputDebugString("\n");
1743 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1744 if ( IsDebuggerPresent() ) {
1746 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1747 OutputDebugString(message);
1749 free(cells[cell_count]);
1757 pkrb5_cc_close(ctx,cc);
1764 pkrb5_cc_close(ctx,cc);
1766 pkrb5_free_context(ctx);
1767 if (cellconfig.linkedCell)
1768 free(cellconfig.linkedCell);
1775 KFW_AFS_renew_token_for_cell(char * cell)
1777 krb5_error_code code = 0;
1778 krb5_context ctx = NULL;
1780 char ** principals = NULL;
1782 if (!pkrb5_init_context)
1783 return KRB5_CONFIG_CANTOPEN;
1785 if ( IsDebuggerPresent() ) {
1786 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1787 OutputDebugString(cell);
1788 OutputDebugString("\n");
1791 code = pkrb5_init_context(&ctx);
1792 if (code) goto cleanup;
1794 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1796 // We know we must have a credential somewhere since we are
1797 // trying to renew a token
1799 KFW_import_ccache_data();
1800 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1803 krb5_principal princ = 0;
1804 krb5_principal service = 0;
1806 krb5_creds mcreds, creds;
1807 #endif /* COMMENT */
1809 const char * realm = NULL;
1810 struct afsconf_cell cellconfig;
1811 char local_cell[CELL_MAXNAMELEN+1];
1813 memset(&cellconfig, 0, sizeof(cellconfig));
1816 code = pkrb5_parse_name(ctx, principals[count], &princ);
1817 if (code) goto loop_cleanup;
1819 code = KFW_get_ccache(ctx, princ, &cc);
1820 if (code) goto loop_cleanup;
1822 if (cellconfig.linkedCell) {
1823 free(cellconfig.linkedCell);
1824 cellconfig.linkedCell = NULL;
1826 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1827 if ( code ) goto loop_cleanup;
1829 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1830 if ( IsDebuggerPresent() ) {
1831 OutputDebugString("Realm: ");
1832 OutputDebugString(realm);
1833 OutputDebugString("\n");
1837 /* krb5_cc_remove_cred() is not implemented
1840 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1841 realm, "afs", cell, NULL);
1843 memset(&mcreds, 0, sizeof(krb5_creds));
1844 mcreds.client = princ;
1845 mcreds.server = service;
1847 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1849 if ( IsDebuggerPresent() ) {
1850 char * cname, *sname;
1851 pkrb5_unparse_name(ctx, creds.client, &cname);
1852 pkrb5_unparse_name(ctx, creds.server, &sname);
1853 OutputDebugString("Removing credential for client \"");
1854 OutputDebugString(cname);
1855 OutputDebugString("\" and service \"");
1856 OutputDebugString(sname);
1857 OutputDebugString("\"\n");
1858 pkrb5_free_unparsed_name(ctx,cname);
1859 pkrb5_free_unparsed_name(ctx,sname);
1862 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1863 pkrb5_free_principal(ctx, creds.client);
1864 pkrb5_free_principal(ctx, creds.server);
1867 #endif /* COMMENT */
1869 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1870 if ( IsDebuggerPresent() ) {
1872 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1873 OutputDebugString(message);
1878 pkrb5_cc_close(ctx, cc);
1882 pkrb5_free_principal(ctx, princ);
1886 pkrb5_free_principal(ctx, service);
1889 if (cellconfig.linkedCell) {
1890 free(cellconfig.linkedCell);
1891 cellconfig.linkedCell = NULL;
1894 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1895 free(principals[count]);
1899 code = -1; // we did not renew the tokens
1903 pkrb5_free_context(ctx);
1904 return (code ? FALSE : TRUE);
1909 KFW_AFS_renew_tokens_for_all_cells(void)
1911 struct cell_principal_map * next = cell_princ_map;
1913 if ( IsDebuggerPresent() )
1914 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1919 for ( ; next ; next = next->next ) {
1921 KFW_AFS_renew_token_for_cell(next->cell);
1927 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1929 krb5_error_code code = 0;
1930 krb5_context ctx = NULL;
1931 krb5_ccache cc = NULL;
1932 krb5_principal me = NULL;
1933 krb5_principal server = NULL;
1934 krb5_creds my_creds;
1935 krb5_data *realm = NULL;
1937 if (!pkrb5_init_context)
1938 return KRB5_CONFIG_CANTOPEN;
1940 memset(&my_creds, 0, sizeof(krb5_creds));
1945 code = pkrb5_init_context(&ctx);
1946 if (code) goto cleanup;
1952 code = pkrb5_cc_default(ctx, &cc);
1953 if (code) goto cleanup;
1956 code = pkrb5_cc_get_principal(ctx, cc, &me);
1957 if (code) goto cleanup;
1959 realm = krb5_princ_realm(ctx, me);
1961 code = pkrb5_build_principal_ext(ctx, &server,
1962 realm->length,realm->data,
1963 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1964 realm->length,realm->data,
1969 if ( IsDebuggerPresent() ) {
1970 char * cname, *sname;
1971 pkrb5_unparse_name(ctx, me, &cname);
1972 pkrb5_unparse_name(ctx, server, &sname);
1973 OutputDebugString("Renewing credential for client \"");
1974 OutputDebugString(cname);
1975 OutputDebugString("\" and service \"");
1976 OutputDebugString(sname);
1977 OutputDebugString("\"\n");
1978 pkrb5_free_unparsed_name(ctx,cname);
1979 pkrb5_free_unparsed_name(ctx,sname);
1982 my_creds.client = me;
1983 my_creds.server = server;
1985 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1987 if ( IsDebuggerPresent() ) {
1989 StringCbPrintf(message, sizeof(message), "krb5_get_renewed_creds() failed: %d\n", code);
1990 OutputDebugString(message);
1995 code = pkrb5_cc_initialize(ctx, cc, me);
1997 if ( IsDebuggerPresent() ) {
1999 StringCbPrintf(message, sizeof(message), "krb5_cc_initialize() failed: %d\n", code);
2000 OutputDebugString(message);
2005 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2007 if ( IsDebuggerPresent() ) {
2009 StringCbPrintf(message, sizeof(message), "krb5_cc_store_cred() failed: %d\n", code);
2010 OutputDebugString(message);
2016 if (my_creds.client == me)
2017 my_creds.client = 0;
2018 if (my_creds.server == server)
2019 my_creds.server = 0;
2020 pkrb5_free_cred_contents(ctx, &my_creds);
2022 pkrb5_free_principal(ctx, me);
2024 pkrb5_free_principal(ctx, server);
2025 if (cc && (cc != alt_cc))
2026 pkrb5_cc_close(ctx, cc);
2027 if (ctx && (ctx != alt_ctx))
2028 pkrb5_free_context(ctx);
2033 KFW_kinit( krb5_context alt_ctx,
2036 char *principal_name,
2038 krb5_deltat lifetime,
2041 krb5_deltat renew_life,
2046 krb5_error_code code = 0;
2047 krb5_context ctx = NULL;
2048 krb5_ccache cc = NULL;
2049 krb5_principal me = NULL;
2051 krb5_creds my_creds;
2052 krb5_get_init_creds_opt options;
2053 krb5_address ** addrs = NULL;
2054 int i = 0, addr_count = 0;
2056 if (!pkrb5_init_context)
2057 return KRB5_CONFIG_CANTOPEN;
2059 pkrb5_get_init_creds_opt_init(&options);
2060 memset(&my_creds, 0, sizeof(my_creds));
2068 code = pkrb5_init_context(&ctx);
2069 if (code) goto cleanup;
2075 code = pkrb5_cc_default(ctx, &cc);
2076 if (code) goto cleanup;
2079 code = pkrb5_parse_name(ctx, principal_name, &me);
2083 code = pkrb5_unparse_name(ctx, me, &name);
2088 lifetime = DEFAULT_LIFETIME;
2095 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2096 pkrb5_get_init_creds_opt_set_forwardable(&options,
2097 forwardable ? 1 : 0);
2098 pkrb5_get_init_creds_opt_set_proxiable(&options,
2100 pkrb5_get_init_creds_opt_set_renew_life(&options,
2103 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2107 // we are going to add the public IP address specified by the user
2108 // to the list provided by the operating system
2109 krb5_address ** local_addrs=NULL;
2112 pkrb5_os_localaddr(ctx, &local_addrs);
2113 while ( local_addrs[i++] );
2116 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2118 pkrb5_free_addresses(ctx, local_addrs);
2121 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2123 while ( local_addrs[i] ) {
2124 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2125 if (addrs[i] == NULL) {
2126 pkrb5_free_addresses(ctx, local_addrs);
2130 addrs[i]->magic = local_addrs[i]->magic;
2131 addrs[i]->addrtype = local_addrs[i]->addrtype;
2132 addrs[i]->length = local_addrs[i]->length;
2133 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2134 if (!addrs[i]->contents) {
2135 pkrb5_free_addresses(ctx, local_addrs);
2139 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2140 local_addrs[i]->length); /* safe */
2143 pkrb5_free_addresses(ctx, local_addrs);
2145 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2146 if (addrs[i] == NULL)
2149 addrs[i]->magic = KV5M_ADDRESS;
2150 addrs[i]->addrtype = AF_INET;
2151 addrs[i]->length = 4;
2152 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2153 if (!addrs[i]->contents)
2156 netIPAddr = htonl(publicIP);
2157 memcpy(addrs[i]->contents,&netIPAddr,4);
2159 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2164 code = pkrb5_get_init_creds_password(ctx,
2167 password, // password
2168 KRB5_prompter, // prompter
2169 hParent, // prompter data
2176 code = pkrb5_cc_initialize(ctx, cc, me);
2180 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2186 for ( i=0;i<addr_count;i++ ) {
2188 if ( addrs[i]->contents )
2189 free(addrs[i]->contents);
2194 if (my_creds.client == me)
2195 my_creds.client = 0;
2196 pkrb5_free_cred_contents(ctx, &my_creds);
2198 pkrb5_free_unparsed_name(ctx, name);
2200 pkrb5_free_principal(ctx, me);
2201 if (cc && (cc != alt_cc))
2202 pkrb5_cc_close(ctx, cc);
2203 if (ctx && (ctx != alt_ctx))
2204 pkrb5_free_context(ctx);
2210 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2212 krb5_context ctx = NULL;
2213 krb5_ccache cc = NULL;
2214 krb5_error_code code;
2216 if (!pkrb5_init_context)
2217 return KRB5_CONFIG_CANTOPEN;
2225 code = pkrb5_init_context(&ctx);
2226 if (code) goto cleanup;
2232 code = pkrb5_cc_default(ctx, &cc);
2233 if (code) goto cleanup;
2236 code = pkrb5_cc_destroy(ctx, cc);
2237 if ( !code ) cc = 0;
2240 if (cc && (cc != alt_cc))
2241 pkrb5_cc_close(ctx, cc);
2242 if (ctx && (ctx != alt_ctx))
2243 pkrb5_free_context(ctx);
2251 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2253 NTSTATUS Status = 0;
2255 TOKEN_STATISTICS Stats;
2261 *ppSessionData = NULL;
2263 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2267 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2268 CloseHandle( TokenHandle );
2272 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2273 if ( FAILED(Status) || !ppSessionData )
2280 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2281 // cache. It validates whether or not it is reasonable to assume that if we
2282 // attempted to retrieve valid tickets we could do so. Microsoft does not
2283 // automatically renew expired tickets. Therefore, the cache could contain
2284 // expired or invalid tickets. Microsoft also caches the user's password
2285 // and will use it to retrieve new TGTs if the cache is empty and tickets
2289 MSLSA_IsKerberosLogon(VOID)
2291 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2292 BOOL Success = FALSE;
2294 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2295 if ( pSessionData->AuthenticationPackage.Buffer ) {
2301 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2302 usLength = (pSessionData->AuthenticationPackage).Length;
2305 StringCbCopyNW( buffer, sizeof(buffer)/sizeof(WCHAR),
2306 usBuffer, usLength);
2307 if ( !lstrcmpW(L"Kerberos",buffer) )
2311 pLsaFreeReturnBuffer(pSessionData);
2315 #endif /* USE_MS2MIT */
2317 static BOOL CALLBACK
2318 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2322 switch ( message ) {
2324 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2326 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2329 for ( i=0; i < mid_cnt ; i++ ) {
2330 if (mid_tb[i].echo == 0)
2331 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2332 else if (mid_tb[i].echo == 2)
2333 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2338 switch ( LOWORD(wParam) ) {
2340 for ( i=0; i < mid_cnt ; i++ ) {
2341 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2342 *mid_tb[i].buf = '\0';
2346 EndDialog(hDialog, LOWORD(wParam));
2354 lpwAlign( LPWORD lpIn )
2358 ul = (ULONG_PTR) lpIn;
2362 return (LPWORD) ul;;
2366 * dialog widths are measured in 1/4 character widths
2367 * dialog height are measured in 1/8 character heights
2371 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2372 char * ptext[], int numlines, int width,
2373 int tb_cnt, struct textField * tb)
2377 LPDLGITEMTEMPLATE lpdit;
2383 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2390 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2392 // Define a dialog box.
2394 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2395 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2396 | DS_SETFOREGROUND | DS_3DLOOK
2397 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2398 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2401 lpdt->cx = 20 + width * 4;
2402 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2404 lpw = (LPWORD) (lpdt + 1);
2405 *lpw++ = 0; // no menu
2406 *lpw++ = 0; // predefined dialog box class (by default)
2408 lpwsz = (LPWSTR) lpw;
2409 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2411 *lpw++ = 8; // font size (points)
2412 lpwsz = (LPWSTR) lpw;
2413 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2417 //-----------------------
2418 // Define an OK button.
2419 //-----------------------
2420 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2421 lpdit = (LPDLGITEMTEMPLATE) lpw;
2422 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2423 lpdit->dwExtendedStyle = 0;
2424 lpdit->x = (lpdt->cx - 14)/4 - 20;
2425 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2428 lpdit->id = IDOK; // OK button identifier
2430 lpw = (LPWORD) (lpdit + 1);
2432 *lpw++ = 0x0080; // button class
2434 lpwsz = (LPWSTR) lpw;
2435 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2437 *lpw++ = 0; // no creation data
2439 //-----------------------
2440 // Define an Cancel button.
2441 //-----------------------
2442 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2443 lpdit = (LPDLGITEMTEMPLATE) lpw;
2444 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2445 lpdit->dwExtendedStyle = 0;
2446 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2447 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2450 lpdit->id = IDCANCEL; // CANCEL button identifier
2452 lpw = (LPWORD) (lpdit + 1);
2454 *lpw++ = 0x0080; // button class
2456 lpwsz = (LPWSTR) lpw;
2457 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2459 *lpw++ = 0; // no creation data
2461 /* Add controls for preface data */
2462 for ( i=0; i<numlines; i++) {
2463 /*-----------------------
2464 * Define a static text control.
2465 *-----------------------*/
2466 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2467 lpdit = (LPDLGITEMTEMPLATE) lpw;
2468 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2469 lpdit->dwExtendedStyle = 0;
2471 lpdit->y = 10 + i * 14;
2472 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2474 lpdit->id = ID_TEXT + i; // text identifier
2476 lpw = (LPWORD) (lpdit + 1);
2478 *lpw++ = 0x0082; // static class
2480 lpwsz = (LPWSTR) lpw;
2481 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2482 -1, lpwsz, 2*width);
2484 *lpw++ = 0; // no creation data
2487 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2488 int len = (int)strlen(tb[i].label);
2493 for ( i=0; i<tb_cnt; i++) {
2495 /*-----------------------
2496 * Define a static text control.
2497 *-----------------------*/
2498 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2499 lpdit = (LPDLGITEMTEMPLATE) lpw;
2500 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2501 lpdit->dwExtendedStyle = 0;
2503 lpdit->y = 10 + (numlines + i + 1) * 14;
2504 lpdit->cx = pwid * 4;
2506 lpdit->id = ID_TEXT + numlines + i; // text identifier
2508 lpw = (LPWORD) (lpdit + 1);
2510 *lpw++ = 0x0082; // static class
2512 lpwsz = (LPWSTR) lpw;
2513 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2516 *lpw++ = 0; // no creation data
2518 /*-----------------------
2519 * Define an edit control.
2520 *-----------------------*/
2521 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2522 lpdit = (LPDLGITEMTEMPLATE) lpw;
2523 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2524 lpdit->dwExtendedStyle = 0;
2525 lpdit->x = 10 + (pwid + 1) * 4;
2526 lpdit->y = 10 + (numlines + i + 1) * 14;
2527 lpdit->cx = (width - (pwid + 1)) * 4;
2529 lpdit->id = ID_MID_TEXT + i; // identifier
2531 lpw = (LPWORD) (lpdit + 1);
2533 *lpw++ = 0x0081; // edit class
2535 lpwsz = (LPWSTR) lpw;
2536 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2539 *lpw++ = 0; // no creation data
2543 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2544 hwndOwner, (DLGPROC) MultiInputDialogProc);
2548 case 0: /* Timeout */
2556 StringCbPrintf(buf, sizeof(buf), "DialogBoxIndirect() failed: %d", GetLastError());
2557 MessageBox(hwndOwner,
2560 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2567 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2569 HINSTANCE hInst = 0;
2573 char * plines[16], *p = preface ? preface : "";
2576 for ( i=0; i<16; i++ )
2579 while (*p && numlines < 16) {
2580 plines[numlines++] = p;
2581 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2582 if ( *p == '\r' && *(p+1) == '\n' ) {
2585 } else if ( *p == '\n' ) {
2588 if ( strlen(plines[numlines-1]) > maxwidth )
2589 maxwidth = (int)strlen(plines[numlines-1]);
2592 for ( i=0;i<n;i++ ) {
2593 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2594 if ( maxwidth < len )
2598 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2601 static krb5_error_code KRB5_CALLCONV
2602 KRB5_prompter( krb5_context context,
2607 krb5_prompt prompts[])
2609 krb5_error_code errcode = 0;
2611 struct textField * tb = NULL;
2612 int len = 0, blen=0, nlen=0;
2613 HWND hParent = (HWND)data;
2616 nlen = (int)strlen(name)+2;
2619 blen = (int)strlen(banner)+2;
2621 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2624 memset(tb,0,sizeof(struct textField) * num_prompts);
2625 for ( i=0; i < num_prompts; i++ ) {
2626 tb[i].buf = prompts[i].reply->data;
2627 tb[i].len = prompts[i].reply->length;
2628 tb[i].label = prompts[i].prompt;
2630 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2633 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2635 for ( i=0; i < num_prompts; i++ )
2636 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2644 for (i = 0; i < num_prompts; i++) {
2645 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2652 KFW_AFS_wait_for_service_start(void)
2657 CurrentState = SERVICE_START_PENDING;
2658 memset(HostName, '\0', sizeof(HostName));
2659 gethostname(HostName, sizeof(HostName));
2661 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2663 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2665 if ( IsDebuggerPresent() ) {
2666 switch ( CurrentState ) {
2667 case SERVICE_STOPPED:
2668 OutputDebugString("SERVICE_STOPPED\n");
2670 case SERVICE_START_PENDING:
2671 OutputDebugString("SERVICE_START_PENDING\n");
2673 case SERVICE_STOP_PENDING:
2674 OutputDebugString("SERVICE_STOP_PENDING\n");
2676 case SERVICE_RUNNING:
2677 OutputDebugString("SERVICE_RUNNING\n");
2679 case SERVICE_CONTINUE_PENDING:
2680 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2682 case SERVICE_PAUSE_PENDING:
2683 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2685 case SERVICE_PAUSED:
2686 OutputDebugString("SERVICE_PAUSED\n");
2689 OutputDebugString("UNKNOWN Service State\n");
2692 if (CurrentState == SERVICE_STOPPED)
2694 if (CurrentState == SERVICE_RUNNING)
2710 memset(HostName, '\0', sizeof(HostName));
2711 gethostname(HostName, sizeof(HostName));
2712 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2714 if (CurrentState != SERVICE_RUNNING)
2717 rc = ktc_ForgetAllTokens();
2723 #define ALLOW_REGISTER 1
2725 ViceIDToUsername(char *username,
2726 char *realm_of_user,
2727 char *realm_of_cell,
2729 struct ktc_principal *aclient,
2730 struct ktc_principal *aserver,
2731 struct ktc_token *atoken)
2733 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2734 static char confdir[512] = { 0 };
2735 #ifdef AFS_ID_TO_NAME
2736 char username_copy[BUFSIZ];
2737 #endif /* AFS_ID_TO_NAME */
2738 long viceId = ANONYMOUSID; /* AFS uid of user */
2740 #ifdef ALLOW_REGISTER
2742 #endif /* ALLOW_REGISTER */
2744 if (confdir[0] == '\0')
2745 cm_GetConfigDir(confdir, sizeof(confdir));
2747 StringCbCopyN( lastcell, sizeof(lastcell),
2748 aserver->cell, sizeof(lastcell) - 1);
2750 if (!pr_Initialize (0, confdir, aserver->cell)) {
2751 char sname[PR_MAXNAMELEN];
2752 StringCbCopyN( sname, sizeof(sname),
2753 username, sizeof(sname) - 1);
2754 status = pr_SNameToId (sname, &viceId);
2759 * This is a crock, but it is Transarc's crock, so
2760 * we have to play along in order to get the
2761 * functionality. The way the afs id is stored is
2762 * as a string in the username field of the token.
2763 * Contrary to what you may think by looking at
2764 * the code for tokens, this hack (AFS ID %d) will
2765 * not work if you change %d to something else.
2769 * This code is taken from cklog -- it lets people
2770 * automatically register with the ptserver in foreign cells
2773 #ifdef ALLOW_REGISTER
2775 if (viceId != ANONYMOUSID) {
2776 #else /* ALLOW_REGISTER */
2777 if ((status == 0) && (viceId != ANONYMOUSID))
2778 #endif /* ALLOW_REGISTER */
2780 #ifdef AFS_ID_TO_NAME
2781 StringCbCopyN( username_copy, sizeof(username_copy),
2782 username, sizeof(username_copy) - 1);
2783 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2784 #endif /* AFS_ID_TO_NAME */
2786 #ifdef ALLOW_REGISTER
2787 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2789 StringCbCopyN( aclient->name, sizeof(aclient->name),
2790 username, sizeof(aclient->name) - 1);
2791 aclient->instance[0] = '\0';
2792 StringCbCopyN( aclient->cell, sizeof(aclient->cell),
2793 realm_of_user, sizeof(aclient->cell) - 1);
2794 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2796 if (status = pr_Initialize(1L, confdir, aserver->cell))
2798 status = pr_CreateUser(username, &id);
2802 #ifdef AFS_ID_TO_NAME
2803 StringCbCopyN( username_copy, sizeof(username_copy),
2804 username, sizeof(username_copy) - 1);
2805 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2806 #endif /* AFS_ID_TO_NAME */
2809 #endif /* ALLOW_REGISTER */
2815 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2816 krb5_error_code code;
2817 krb5_ticket *ticket;
2820 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2822 len = krb5_princ_realm(context, ticket->server)->length;
2823 if (len > destlen - 1)
2826 StringCbCopyN(dest, destlen, krb5_princ_realm(context, ticket->server)->data, len);
2828 pkrb5_free_ticket(context, ticket);
2834 krb5_context alt_ctx,
2839 int lifetime, /* unused parameter */
2847 #endif /* USE_KRB4 */
2848 struct ktc_principal aserver;
2849 struct ktc_principal aclient;
2850 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2851 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2852 char local_cell[CELL_MAXNAMELEN+1];
2853 char Dmycell[CELL_MAXNAMELEN+1];
2854 struct ktc_token atoken;
2855 struct ktc_token btoken;
2856 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2857 char RealmName[128];
2859 char ServiceName[128];
2863 krb5_context ctx = NULL;
2864 krb5_ccache cc = NULL;
2866 krb5_creds * k5creds = NULL;
2867 krb5_error_code code;
2868 krb5_principal client_principal = NULL;
2869 krb5_data * k5data = NULL;
2870 unsigned int i, retry = 0;
2873 memset(HostName, '\0', sizeof(HostName));
2874 gethostname(HostName, sizeof(HostName));
2875 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2876 if ( IsDebuggerPresent() )
2877 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2880 if (CurrentState != SERVICE_RUNNING) {
2881 if ( IsDebuggerPresent() )
2882 OutputDebugString("AFSD Service NOT RUNNING\n");
2886 if (!pkrb5_init_context)
2887 return KRB5_CONFIG_CANTOPEN;
2889 memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
2890 memset(RealmName, '\0', sizeof(RealmName));
2891 memset(CellName, '\0', sizeof(CellName));
2892 memset(ServiceName, '\0', sizeof(ServiceName));
2893 memset(realm_of_user, '\0', sizeof(realm_of_user));
2894 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2895 if (cell && cell[0])
2896 StringCbCopyN( Dmycell, sizeof(Dmycell),
2897 cell, sizeof(Dmycell) - 1);
2899 memset(Dmycell, '\0', sizeof(Dmycell));
2901 // NULL or empty cell returns information on local cell
2902 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2904 // KFW_AFS_error(rc, "get_cellconfig()");
2911 code = pkrb5_init_context(&ctx);
2912 if (code) goto cleanup;
2918 code = pkrb5_cc_default(ctx, &cc);
2919 if (code) goto skip_krb5_init;
2922 memset(&increds, 0, sizeof(increds));
2924 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2926 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2928 OutputDebugString("Principal Not Found for ccache\n");
2930 goto skip_krb5_init;
2933 if (!KFW_accept_dotted_usernames()) {
2934 /* look for client principals which cannot be distinguished
2935 * from Kerberos 4 multi-component principal names
2937 k5data = krb5_princ_component(ctx,client_principal,0);
2938 for ( i=0; i<k5data->length; i++ ) {
2939 if ( k5data->data[i] == '.' )
2942 if (i != k5data->length)
2944 OutputDebugString("Illegal Principal name contains dot in first component\n");
2945 rc = KRB5KRB_ERR_GENERIC;
2950 i = krb5_princ_realm(ctx, client_principal)->length;
2953 StringCbCopyN( realm_of_user, sizeof(realm_of_user),
2954 krb5_princ_realm(ctx, client_principal)->data, i);
2959 if ( !try_krb5 || !realm_of_user[0] ) {
2960 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2969 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
2970 afs_realm_of_cell(ctx, &ak_cellconfig),
2971 sizeof(realm_of_cell) - 1);
2973 if (strlen(service) == 0)
2974 StringCbCopy( ServiceName, sizeof(ServiceName), "afs");
2976 StringCbCopyN( ServiceName, sizeof(ServiceName),
2977 service, sizeof(ServiceName) - 1);
2979 if (strlen(cell) == 0)
2980 StringCbCopyN( CellName, sizeof(CellName),
2981 local_cell, sizeof(CellName) - 1);
2983 StringCbCopyN( CellName, sizeof(CellName),
2984 cell, sizeof(CellName) - 1);
2986 /* This is for Kerberos v4 only */
2987 if (strlen(realm) == 0)
2988 StringCbCopyN( RealmName, sizeof(RealmName),
2989 realm_of_cell, sizeof(RealmName) - 1);
2991 StringCbCopyN( RealmName, sizeof(RealmName),
2992 realm, sizeof(RealmName) - 1);
2994 memset(&creds, '\0', sizeof(creds));
2998 code = KRB5KRB_ERR_GENERIC;
3001 increds.client = client_principal;
3002 increds.times.endtime = 0;
3003 /* Ask for DES since that is what V4 understands */
3004 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
3006 /* ALWAYS first try service/cell@CLIENT_REALM */
3007 if (code = pkrb5_build_principal(ctx, &increds.server,
3008 (int)strlen(realm_of_user),
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);
3030 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3032 /* The client's realm is a local realm for the cell.
3033 * Save it so that later the pts registration will not
3036 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3037 realm_of_user, sizeof(realm_of_cell) - 1);
3041 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3042 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3043 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3044 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3045 /* If there was a specific realm we are supposed to try
3048 if (strlen(realm) != 0) {
3049 /* service/cell@REALM */
3051 code = pkrb5_build_principal(ctx, &increds.server,
3057 if ( IsDebuggerPresent() ) {
3058 char * cname, *sname;
3059 pkrb5_unparse_name(ctx, increds.client, &cname);
3060 pkrb5_unparse_name(ctx, increds.server, &sname);
3061 OutputDebugString("Getting tickets for \"");
3062 OutputDebugString(cname);
3063 OutputDebugString("\" and service \"");
3064 OutputDebugString(sname);
3065 OutputDebugString("\"\n");
3066 pkrb5_free_unparsed_name(ctx,cname);
3067 pkrb5_free_unparsed_name(ctx,sname);
3071 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3073 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3074 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3075 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3076 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3077 /* Or service@REALM */
3078 pkrb5_free_principal(ctx,increds.server);
3080 code = pkrb5_build_principal(ctx, &increds.server,
3086 if ( IsDebuggerPresent() ) {
3087 char * cname, *sname;
3088 pkrb5_unparse_name(ctx, increds.client, &cname);
3089 pkrb5_unparse_name(ctx, increds.server, &sname);
3090 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3091 OutputDebugString("Trying again: getting tickets for \"");
3092 OutputDebugString(cname);
3093 OutputDebugString("\" and service \"");
3094 OutputDebugString(sname);
3095 OutputDebugString("\"\n");
3096 pkrb5_free_unparsed_name(ctx,cname);
3097 pkrb5_free_unparsed_name(ctx,sname);
3101 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3105 /* we have a local realm for the cell */
3106 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3107 realm, sizeof(realm_of_cell) - 1);
3110 if (strcmp(realm_of_user, realm_of_cell)) {
3111 /* Then service/cell@CELL_REALM */
3112 pkrb5_free_principal(ctx,increds.server);
3114 code = pkrb5_build_principal(ctx, &increds.server,
3115 (int)strlen(realm_of_cell),
3120 if ( IsDebuggerPresent() ) {
3121 char * cname, *sname;
3122 pkrb5_unparse_name(ctx, increds.client, &cname);
3123 pkrb5_unparse_name(ctx, increds.server, &sname);
3124 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3125 OutputDebugString("Trying again: getting tickets for \"");
3126 OutputDebugString(cname);
3127 OutputDebugString("\" and service \"");
3128 OutputDebugString(sname);
3129 OutputDebugString("\"\n");
3130 pkrb5_free_unparsed_name(ctx,cname);
3131 pkrb5_free_unparsed_name(ctx,sname);
3135 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3137 if (!code && !strlen(realm_of_cell))
3138 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3141 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3142 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3143 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3144 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3145 /* Finally service@CELL_REALM */
3146 pkrb5_free_principal(ctx,increds.server);
3148 code = pkrb5_build_principal(ctx, &increds.server,
3149 (int)strlen(realm_of_cell),
3154 if ( IsDebuggerPresent() ) {
3155 char * cname, *sname;
3156 pkrb5_unparse_name(ctx, increds.client, &cname);
3157 pkrb5_unparse_name(ctx, increds.server, &sname);
3158 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3159 OutputDebugString("Trying again: getting tickets for \"");
3160 OutputDebugString(cname);
3161 OutputDebugString("\" and service \"");
3162 OutputDebugString(sname);
3163 OutputDebugString("\"\n");
3164 pkrb5_free_unparsed_name(ctx,cname);
3165 pkrb5_free_unparsed_name(ctx,sname);
3169 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3170 if (!code && !strlen(realm_of_cell))
3171 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3177 if ( IsDebuggerPresent() ) {
3179 StringCbPrintf(message, sizeof(message), "krb5_get_credentials returns: %d\n", code);
3180 OutputDebugString(message);
3186 /* This code inserts the entire K5 ticket into the token
3187 * No need to perform a krb524 translation which is
3188 * commented out in the code below
3190 if (KFW_use_krb524() ||
3191 k5creds->ticket.length > MAXKTCTICKETLEN)
3194 memset(&aserver, '\0', sizeof(aserver));
3195 StringCbCopyN(aserver.name, sizeof(aserver.name),
3196 ServiceName, sizeof(aserver.name) - 1);
3197 StringCbCopyN(aserver.cell, sizeof(aserver.cell),
3198 CellName, sizeof(aserver.cell) - 1);
3200 memset(&atoken, '\0', sizeof(atoken));
3201 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3202 atoken.startTime = k5creds->times.starttime;
3203 atoken.endTime = k5creds->times.endtime;
3204 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3205 atoken.ticketLen = k5creds->ticket.length;
3206 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3209 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3210 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3211 if ( rc == KTC_NOCM && retry < 20 ) {
3214 goto retry_gettoken5;
3219 if (atoken.kvno == btoken.kvno &&
3220 atoken.ticketLen == btoken.ticketLen &&
3221 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3222 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3224 /* Success - Nothing to do */
3228 // * Reset the "aclient" structure before we call ktc_SetToken.
3229 // * This structure was first set by the ktc_GetToken call when
3230 // * we were comparing whether identical tokens already existed.
3232 len = min(k5creds->client->data[0].length, sizeof(aclient.name) - 1);
3233 StringCbCopyN( aclient.name, sizeof(aclient.name),
3234 k5creds->client->data[0].data, len);
3236 if ( k5creds->client->length > 1 ) {
3237 StringCbCat( aclient.name, sizeof(aclient.name), ".");
3238 len = min(k5creds->client->data[1].length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3239 StringCbCatN( aclient.name, sizeof(aclient.name),
3240 k5creds->client->data[1].data, len);
3242 aclient.instance[0] = '\0';
3244 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3245 realm_of_cell, sizeof(aclient.cell) - 1);
3247 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3248 /* For Khimaira, always append the realm name */
3249 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3250 StringCbCat( aclient.name, sizeof(aclient.name), "@");
3251 len = min(k5creds->client->realm.length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3252 StringCbCatN( aclient.name, sizeof(aclient.name), k5creds->client->realm.data, len);
3255 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3256 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3257 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3258 &aclient, &aserver, &atoken);
3261 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3262 smbname, sizeof(aclient.smbname) - 1);
3264 aclient.smbname[0] = '\0';
3267 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3269 goto cleanup; /* We have successfully inserted the token */
3275 /* Otherwise, the ticket could have been too large so try to
3276 * convert using the krb524d running with the KDC
3278 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3279 pkrb5_free_creds(ctx, k5creds);
3281 if ( IsDebuggerPresent() ) {
3283 StringCbPrintf(message, sizeof(message), "krb524_convert_creds_kdc returns: %d\n", code);
3284 OutputDebugString(message);
3289 #endif /* USE_KRB524 */
3293 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3294 if (code == NO_TKT_FIL) {
3295 // if the problem is that we have no krb4 tickets
3296 // do not attempt to continue
3299 if (code != KSUCCESS)
3300 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3302 if (code != KSUCCESS)
3304 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3306 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3311 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3313 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3328 memset(&aserver, '\0', sizeof(aserver));
3329 StringCbCopyN( aserver.name, sizeof(aserver.name), ServiceName, sizeof(aserver.name) - 1);
3330 StringCbCopyN( aserver.cell, sizeof(aserver.cell), CellName, sizeof(aserver.cell) - 1);
3332 memset(&atoken, '\0', sizeof(atoken));
3333 atoken.kvno = creds.kvno;
3334 atoken.startTime = creds.issue_date;
3335 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3336 memcpy(&atoken.sessionKey, creds.session, 8);
3337 atoken.ticketLen = creds.ticket_st.length;
3338 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3341 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3342 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3343 if ( rc == KTC_NOCM && retry < 20 ) {
3346 goto retry_gettoken;
3348 KFW_AFS_error(rc, "ktc_GetToken()");
3353 if (atoken.kvno == btoken.kvno &&
3354 atoken.ticketLen == btoken.ticketLen &&
3355 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3356 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3361 // * Reset the "aclient" structure before we call ktc_SetToken.
3362 // * This structure was first set by the ktc_GetToken call when
3363 // * we were comparing whether identical tokens already existed.
3365 StringCbCopyN( aclient.name, sizeof(aclient.name), creds.pname, sizeof(aclient.name) - 1);
3368 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3369 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3371 aclient.instance[0] = '\0';
3373 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3374 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3375 aclient.name[MAXKTCREALMLEN-1] = '\0';
3377 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3378 CellName, sizeof(aclient.cell) - 1);
3380 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3381 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3382 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3383 &aclient, &aserver, &atoken);
3386 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3387 smbname, sizeof(aclient.smbname) - 1);
3389 aclient.smbname[0] = '\0';
3392 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3394 KFW_AFS_error(rc, "ktc_SetToken()");
3400 if (client_principal)
3401 pkrb5_free_principal(ctx,client_principal);
3402 /* increds.client == client_principal */
3404 pkrb5_free_principal(ctx,increds.server);
3405 if (cc && (cc != alt_cc))
3406 pkrb5_cc_close(ctx, cc);
3407 if (ctx && (ctx != alt_ctx))
3408 pkrb5_free_context(ctx);
3409 if (ak_cellconfig.linkedCell)
3410 free(ak_cellconfig.linkedCell);
3412 return(rc? rc : code);
3415 /**************************************/
3416 /* afs_realm_of_cell(): */
3417 /**************************************/
3419 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3421 static char krbrlm[REALM_SZ+1]="";
3422 char ** realmlist=NULL;
3428 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3429 if ( !r && realmlist && realmlist[0] ) {
3430 StringCbCopyN( krbrlm, sizeof(krbrlm),
3431 realmlist[0], sizeof(krbrlm) - 1);
3432 pkrb5_free_host_realm(ctx, realmlist);
3438 char *t = cellconfig->name;
3443 if (islower(c)) c=toupper(c);
3451 /**************************************/
3452 /* KFW_AFS_get_cellconfig(): */
3453 /**************************************/
3455 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3458 char newcell[CELL_MAXNAMELEN+1];
3459 char linkedcell[CELL_MAXNAMELEN+1]="";
3461 local_cell[0] = (char)0;
3462 memset(cellconfig, 0, sizeof(*cellconfig));
3464 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3465 if (rc = cm_GetRootCellName(local_cell))
3470 if (strlen(cell) == 0)
3471 strcpy(cell, local_cell);
3473 rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3474 if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
3475 rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3478 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3482 StringCbCopyN( cellconfig->name, sizeof(cellconfig->name),
3483 newcell, sizeof(cellconfig->name) - 1);
3485 cellconfig->linkedCell = strdup(linkedcell);
3490 /**************************************/
3491 /* get_cellconfig_callback(): */
3492 /**************************************/
3494 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
3496 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3498 cc->hostAddr[cc->numServers] = *addrp;
3499 StringCbCopyN( cc->hostName[cc->numServers], sizeof(cc->hostName[cc->numServers]),
3500 namep, sizeof(cc->hostName[cc->numServers]) - 1);
3506 /**************************************/
3507 /* KFW_AFS_error(): */
3508 /**************************************/
3510 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3513 const char *errText;
3515 // Using AFS defines as error messages for now, until Transarc
3516 // gets back to me with "string" translations of each of these
3518 if (rc == KTC_ERROR)
3519 errText = "KTC_ERROR";
3520 else if (rc == KTC_TOOBIG)
3521 errText = "KTC_TOOBIG";
3522 else if (rc == KTC_INVAL)
3523 errText = "KTC_INVAL";
3524 else if (rc == KTC_NOENT)
3525 errText = "KTC_NOENT";
3526 else if (rc == KTC_PIOCTLFAIL)
3527 errText = "KTC_PIOCTLFAIL";
3528 else if (rc == KTC_NOPIOCTL)
3529 errText = "KTC_NOPIOCTL";
3530 else if (rc == KTC_NOCELL)
3531 errText = "KTC_NOCELL";
3532 else if (rc == KTC_NOCM)
3533 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3535 errText = "Unknown error!";
3537 StringCbPrintf(message, sizeof(message), "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3539 if ( IsDebuggerPresent() ) {
3540 OutputDebugString(message);
3541 OutputDebugString("\n");
3543 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3549 LPSTR lpszMachineName,
3550 LPSTR lpszServiceName,
3551 DWORD *lpdwCurrentState)
3554 SC_HANDLE schSCManager = NULL;
3555 SC_HANDLE schService = NULL;
3556 DWORD fdwDesiredAccess = 0;
3557 SERVICE_STATUS ssServiceStatus = {0};
3560 *lpdwCurrentState = 0;
3562 fdwDesiredAccess = GENERIC_READ;
3564 schSCManager = OpenSCManager(lpszMachineName,
3568 if(schSCManager == NULL)
3570 hr = GetLastError();
3574 schService = OpenService(schSCManager,
3578 if(schService == NULL)
3580 hr = GetLastError();
3584 fRet = QueryServiceStatus(schService,
3589 hr = GetLastError();
3593 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3597 CloseServiceHandle(schService);
3598 CloseServiceHandle(schSCManager);
3611 for (n = 0; fi[n].func_ptr_var; n++)
3612 *(fi[n].func_ptr_var) = 0;
3613 if (h) FreeLibrary(h);
3618 const char* dll_name,
3620 HINSTANCE* ph, // [out, optional] - DLL handle
3621 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3622 int cleanup, // cleanup function pointers and unload on error
3623 int go_on, // continue loading even if some functions cannot be loaded
3624 int silent // do not pop-up a system dialog if DLL cannot be loaded
3633 if (pindex) *pindex = -1;
3635 for (n = 0; fi[n].func_ptr_var; n++)
3636 *(fi[n].func_ptr_var) = 0;
3639 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3640 h = LoadLibrary(dll_name);
3648 for (i = 0; (go_on || !error) && (i < n); i++)
3650 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3656 *(fi[i].func_ptr_var) = p;
3659 if (pindex) *pindex = last_i;
3660 if (error && cleanup && !go_on) {
3661 for (i = 0; i < n; i++) {
3662 *(fi[i].func_ptr_var) = 0;
3668 if (error) return 0;
3672 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3674 krb5_context ctx = NULL;
3675 krb5_ccache cc = NULL;
3676 krb5_error_code code;
3678 const char * realm = NULL;
3679 krb5_principal principal = NULL;
3680 char * pname = NULL;
3681 char password[PROBE_PASSWORD_LEN+1];
3682 BOOL serverReachable = 0;
3684 if (!pkrb5_init_context)
3685 return KRB5_CONFIG_CANTOPEN;
3687 code = pkrb5_init_context(&ctx);
3688 if (code) goto cleanup;
3691 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3693 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3694 realm, PROBE_USERNAME, NULL, NULL);
3695 if ( code ) goto cleanup;
3697 code = KFW_get_ccache(ctx, principal, &cc);
3698 if ( code ) goto cleanup;
3700 code = pkrb5_unparse_name(ctx, principal, &pname);
3701 if ( code ) goto cleanup;
3703 pwdata.data = password;
3704 pwdata.length = PROBE_PASSWORD_LEN;
3705 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3708 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3711 password[PROBE_PASSWORD_LEN] = '\0';
3713 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3723 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3724 case KRB5KDC_ERR_CLIENT_REVOKED:
3725 case KRB5KDC_ERR_CLIENT_NOTYET:
3726 case KRB5KDC_ERR_PREAUTH_FAILED:
3727 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3728 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3729 serverReachable = TRUE;
3732 serverReachable = FALSE;
3737 pkrb5_free_unparsed_name(ctx,pname);
3739 pkrb5_free_principal(ctx,principal);
3741 pkrb5_cc_close(ctx,cc);
3743 pkrb5_free_context(ctx);
3745 return serverReachable;
3749 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
3751 krb5_context ctx = NULL;
3752 krb5_error_code code;
3753 krb5_ccache mslsa_ccache=NULL;
3754 krb5_principal princ = NULL;
3755 char * pname = NULL;
3758 if (!KFW_is_available())
3761 if (code = pkrb5_init_context(&ctx))
3764 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3767 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3770 if (code = pkrb5_unparse_name(ctx, princ, &pname))
3773 if ( strlen(pname) < *dwSize ) {
3774 StringCbCopyN(szUser, *dwSize, pname, (*dwSize) - 1);
3777 *dwSize = (DWORD)strlen(pname);
3781 pkrb5_free_unparsed_name(ctx, pname);
3784 pkrb5_free_principal(ctx, princ);
3787 pkrb5_cc_close(ctx, mslsa_ccache);
3790 pkrb5_free_context(ctx);
3795 KFW_AFS_set_file_cache_dacl(char *filename, HANDLE hUserToken)
3797 // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
3798 PSID pSystemSID = NULL;
3799 DWORD SystemSIDlength = 0, UserSIDlength = 0;
3800 PACL ccacheACL = NULL;
3801 DWORD ccacheACLlength = 0;
3802 PTOKEN_USER pTokenUser = NULL;
3811 /* Get System SID */
3812 if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
3818 SystemSIDlength = GetLengthSid(pSystemSID);
3819 ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
3820 + SystemSIDlength - sizeof(DWORD);
3823 if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
3825 if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
3826 pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
3828 GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen);
3833 UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
3835 ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
3840 ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
3845 InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
3846 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3847 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3850 AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
3851 STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
3852 pTokenUser->User.Sid);
3853 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3854 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3859 gle = GetLastError();
3860 if (gle != ERROR_NO_TOKEN)
3863 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3864 OWNER_SECURITY_INFORMATION,
3865 pTokenUser->User.Sid,
3869 gle = GetLastError();
3870 if (gle != ERROR_NO_TOKEN)
3874 if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
3875 DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
3880 gle = GetLastError();
3881 if (gle != ERROR_NO_TOKEN)
3888 LocalFree(pSystemSID);
3890 LocalFree(pTokenUser);
3892 LocalFree(ccacheACL);
3897 KFW_AFS_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
3900 DWORD dwSize = size-1; /* leave room for nul */
3903 if (!hUserToken || !newfilename || size <= 0)
3906 *newfilename = '\0';
3908 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
3909 if ( !dwLen || dwLen > dwSize )
3910 dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
3911 if ( !dwLen || dwLen > dwSize )
3914 newfilename[dwSize] = '\0';
3919 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
3921 char filename[MAX_PATH] = "";
3923 char cachename[MAX_PATH + 8] = "FILE:";
3924 krb5_context ctx = NULL;
3925 krb5_error_code code;
3926 krb5_principal princ = NULL;
3927 krb5_ccache cc = NULL;
3928 krb5_ccache ncc = NULL;
3930 if (!pkrb5_init_context || !user || !szLogonId)
3933 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
3934 if ( count > sizeof(filename) || count == 0 ) {
3935 GetWindowsDirectory(filename, sizeof(filename));
3938 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
3941 StringCbCat( filename, sizeof(filename), "\\");
3942 StringCbCat( filename, sizeof(filename), szLogonId);
3944 StringCbCat( cachename, sizeof(cachename), filename);
3946 DeleteFile(filename);
3948 code = pkrb5_init_context(&ctx);
3949 if (code) goto cleanup;
3951 code = pkrb5_parse_name(ctx, user, &princ);
3952 if (code) goto cleanup;
3954 code = KFW_get_ccache(ctx, princ, &cc);
3955 if (code) goto cleanup;
3957 code = pkrb5_cc_resolve(ctx, cachename, &ncc);
3958 if (code) goto cleanup;
3960 code = pkrb5_cc_initialize(ctx, ncc, princ);
3961 if (code) goto cleanup;
3963 code = KFW_AFS_set_file_cache_dacl(filename, NULL);
3964 if (code) goto cleanup;
3966 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3970 pkrb5_cc_close(ctx, cc);
3974 pkrb5_cc_close(ctx, ncc);
3978 pkrb5_free_principal(ctx, princ);
3983 pkrb5_free_context(ctx);
3987 KFW_AFS_copy_file_cache_to_default_cache(char * filename)
3989 char cachename[MAX_PATH + 8] = "FILE:";
3990 krb5_context ctx = NULL;
3991 krb5_error_code code;
3992 krb5_principal princ = NULL;
3993 krb5_ccache cc = NULL;
3994 krb5_ccache ncc = NULL;
3997 if (!pkrb5_init_context || !filename)
4000 if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
4003 code = pkrb5_init_context(&ctx);
4006 StringCbCat( cachename, sizeof(cachename), filename);
4008 code = pkrb5_cc_resolve(ctx, cachename, &cc);
4009 if (code) goto cleanup;
4011 code = pkrb5_cc_get_principal(ctx, cc, &princ);
4013 code = pkrb5_cc_default(ctx, &ncc);
4015 code = pkrb5_cc_initialize(ctx, ncc, princ);
4018 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
4021 pkrb5_cc_close(ctx, ncc);
4025 retval=0; /* success */
4029 pkrb5_cc_close(ctx, cc);
4033 DeleteFile(filename);
4036 pkrb5_free_principal(ctx, princ);
4041 pkrb5_free_context(ctx);
4046 /* We are including this
4048 /* Ticket lifetime. This defines the table used to lookup lifetime for the
4049 fixed part of rande of the one byte lifetime field. Values less than 0x80
4050 are intrpreted as the number of 5 minute intervals. Values from 0x80 to
4051 0xBF should be looked up in this table. The value of 0x80 is the same using
4052 both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days.
4053 The intervening values of have a fixed ratio of roughly 1.06914. The value
4054 oxFF is defined to mean a ticket has no expiration time. This should be
4055 used advisedly since individual servers may impose defacto upperbounds on
4056 ticket lifetimes. */
4058 #define TKTLIFENUMFIXED 64
4059 #define TKTLIFEMINFIXED 0x80
4060 #define TKTLIFEMAXFIXED 0xBF
4061 #define TKTLIFENOEXPIRE 0xFF
4062 #define MAXTKTLIFETIME (30*24*3600) /* 30 days */
4064 static const int tkt_lifetimes[TKTLIFENUMFIXED] = {
4065 38400, /* 10.67 hours, 0.44 days */
4066 41055, /* 11.40 hours, 0.48 days */
4067 43894, /* 12.19 hours, 0.51 days */
4068 46929, /* 13.04 hours, 0.54 days */
4069 50174, /* 13.94 hours, 0.58 days */
4070 53643, /* 14.90 hours, 0.62 days */
4071 57352, /* 15.93 hours, 0.66 days */
4072 61318, /* 17.03 hours, 0.71 days */
4073 65558, /* 18.21 hours, 0.76 days */
4074 70091, /* 19.47 hours, 0.81 days */
4075 74937, /* 20.82 hours, 0.87 days */
4076 80119, /* 22.26 hours, 0.93 days */
4077 85658, /* 23.79 hours, 0.99 days */
4078 91581, /* 25.44 hours, 1.06 days */
4079 97914, /* 27.20 hours, 1.13 days */
4080 104684, /* 29.08 hours, 1.21 days */
4081 111922, /* 31.09 hours, 1.30 days */
4082 119661, /* 33.24 hours, 1.38 days */
4083 127935, /* 35.54 hours, 1.48 days */
4084 136781, /* 37.99 hours, 1.58 days */
4085 146239, /* 40.62 hours, 1.69 days */
4086 156350, /* 43.43 hours, 1.81 days */
4087 167161, /* 46.43 hours, 1.93 days */
4088 178720, /* 49.64 hours, 2.07 days */
4089 191077, /* 53.08 hours, 2.21 days */
4090 204289, /* 56.75 hours, 2.36 days */
4091 218415, /* 60.67 hours, 2.53 days */
4092 233517, /* 64.87 hours, 2.70 days */
4093 249664, /* 69.35 hours, 2.89 days */
4094 266926, /* 74.15 hours, 3.09 days */
4095 285383, /* 79.27 hours, 3.30 days */
4096 305116, /* 84.75 hours, 3.53 days */
4097 326213, /* 90.61 hours, 3.78 days */
4098 348769, /* 96.88 hours, 4.04 days */
4099 372885, /* 103.58 hours, 4.32 days */
4100 398668, /* 110.74 hours, 4.61 days */
4101 426234, /* 118.40 hours, 4.93 days */
4102 455705, /* 126.58 hours, 5.27 days */
4103 487215, /* 135.34 hours, 5.64 days */
4104 520904, /* 144.70 hours, 6.03 days */
4105 556921, /* 154.70 hours, 6.45 days */
4106 595430, /* 165.40 hours, 6.89 days */
4107 636601, /* 176.83 hours, 7.37 days */
4108 680618, /* 189.06 hours, 7.88 days */
4109 727680, /* 202.13 hours, 8.42 days */
4110 777995, /* 216.11 hours, 9.00 days */
4111 831789, /* 231.05 hours, 9.63 days */
4112 889303, /* 247.03 hours, 10.29 days */
4113 950794, /* 264.11 hours, 11.00 days */
4114 1016537, /* 282.37 hours, 11.77 days */
4115 1086825, /* 301.90 hours, 12.58 days */
4116 1161973, /* 322.77 hours, 13.45 days */
4117 1242318, /* 345.09 hours, 14.38 days */
4118 1328218, /* 368.95 hours, 15.37 days */
4119 1420057, /* 394.46 hours, 16.44 days */
4120 1518247, /* 421.74 hours, 17.57 days */
4121 1623226, /* 450.90 hours, 18.79 days */
4122 1735464, /* 482.07 hours, 20.09 days */
4123 1855462, /* 515.41 hours, 21.48 days */
4124 1983758, /* 551.04 hours, 22.96 days */
4125 2120925, /* 589.15 hours, 24.55 days */
4126 2267576, /* 629.88 hours, 26.25 days */
4127 2424367, /* 673.44 hours, 28.06 days */
4129 }; /* 720.00 hours, 30.00 days */
4131 /* life_to_time - takes a start time and a Kerberos standard lifetime char and
4132 * returns the corresponding end time. There are four simple cases to be
4133 * handled. The first is a life of 0xff, meaning no expiration, and results in
4134 * an end time of 0xffffffff. The second is when life is less than the values
4135 * covered by the table. In this case, the end time is the start time plus the
4136 * number of 5 minute intervals specified by life. The third case returns
4137 * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The
4138 * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the
4139 * table to extract the lifetime in seconds, which is added to start to produce
4143 life_to_time(afs_uint32 start, unsigned char life)
4147 if (life == TKTLIFENOEXPIRE)
4149 if (life < TKTLIFEMINFIXED)
4150 return start + life * 5 * 60;
4151 if (life > TKTLIFEMAXFIXED)
4152 return start + MAXTKTLIFETIME;
4153 realLife = tkt_lifetimes[life - TKTLIFEMINFIXED];
4154 return start + realLife;
4157 /* time_to_life - takes start and end times for the ticket and returns a
4158 * Kerberos standard lifetime char possibily using the tkt_lifetimes table for
4159 * lifetimes above 127*5minutes. First, the special case of (end ==
4160 * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and
4161 * those greater than the maximum ticket lifetime are rejected. Then lifetimes
4162 * less than the first table entry are handled by rounding the requested
4163 * lifetime *up* to the next 5 minute interval. The final step is to search
4164 * the table for the smallest entry *greater than or equal* to the requested
4165 * entry. The actual code is prepared to handle the case where the table is
4166 * unordered but that it an unnecessary frill. */
4168 static unsigned char
4169 time_to_life(afs_uint32 start, afs_uint32 end)
4171 int lifetime = end - start;
4175 if (end == NEVERDATE)
4176 return TKTLIFENOEXPIRE;
4177 if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0))
4179 if (lifetime < tkt_lifetimes[0])
4180 return (lifetime + 5 * 60 - 1) / (5 * 60);
4182 best = MAXKTCTICKETLIFETIME;
4183 for (i = 0; i < TKTLIFENUMFIXED; i++)
4184 if (tkt_lifetimes[i] >= lifetime) {
4185 int diff = tkt_lifetimes[i] - lifetime;
4193 return best_i + TKTLIFEMINFIXED;