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)
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)
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: ");
1417 OutputDebugString(realm);
1418 OutputDebugString("\n");
1421 code = pkrb5_parse_name(ctx, pname, &principal);
1422 if ( code ) goto cleanup;
1424 code = KFW_get_ccache(ctx, principal, &cc);
1425 if ( code ) goto cleanup;
1427 if ( lifetime == 0 )
1428 lifetime = DEFAULT_LIFETIME;
1430 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1431 if ( IsDebuggerPresent() ) {
1433 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1434 OutputDebugString(message);
1437 if (code && password && password[0] ) {
1438 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1443 0, /* forwardable */
1444 0, /* not proxiable */
1446 1, /* noaddresses */
1447 0 /* no public ip */
1449 pLeash_get_default_forwardable(),
1450 pLeash_get_default_proxiable(),
1451 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1452 pLeash_get_default_noaddresses(),
1453 pLeash_get_default_publicip()
1454 #endif /* USE_LEASH */
1457 if ( IsDebuggerPresent() ) {
1459 StringCbPrintf(message, sizeof(message), "KFW_kinit() returns: %d\n", code);
1460 OutputDebugString(message);
1462 if ( code ) goto cleanup;
1464 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1467 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1468 if ( IsDebuggerPresent() ) {
1470 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1471 OutputDebugString(message);
1473 if ( code ) goto cleanup;
1475 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1477 // Attempt to obtain new tokens for other cells supported by the same
1479 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1480 if ( cell_count > 1 ) {
1481 while ( cell_count-- ) {
1482 if ( strcmp(cells[cell_count],cell) ) {
1483 if ( IsDebuggerPresent() ) {
1485 StringCbPrintf(message, sizeof(message),
1486 "found another cell for the same principal: %s\n", cell);
1487 OutputDebugString(message);
1490 if (cellconfig.linkedCell) {
1491 free(cellconfig.linkedCell);
1492 cellconfig.linkedCell = NULL;
1494 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1495 if ( code ) continue;
1497 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1498 if ( IsDebuggerPresent() ) {
1499 OutputDebugString("Realm: ");
1500 OutputDebugString(realm);
1501 OutputDebugString("\n");
1504 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1505 if ( IsDebuggerPresent() ) {
1507 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1508 OutputDebugString(message);
1511 free(cells[cell_count]);
1514 } else if ( cell_count == 1 ) {
1523 pkrb5_cc_close(ctx, cc);
1524 if ( cellconfig.linkedCell )
1525 free(cellconfig.linkedCell);
1527 if ( code && reasonP ) {
1528 if (pkrb5_get_error_message) {
1529 char *msg = pkrb5_get_error_message(ctx, code);
1530 StringCbCopyN( reason, sizeof(reason),
1531 msg, sizeof(reason) - 1);
1533 pkrb5_free_error_message(ctx, msg);
1535 *reasonP = perror_message(code);
1542 KFW_AFS_destroy_tickets_for_cell(char * cell)
1544 krb5_context ctx = NULL;
1545 krb5_error_code code;
1547 char ** principals = NULL;
1549 if (!pkrb5_init_context)
1552 if ( IsDebuggerPresent() ) {
1553 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1554 OutputDebugString(cell);
1555 OutputDebugString("\n");
1558 code = pkrb5_init_context(&ctx);
1561 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1563 krb5_principal princ = 0;
1567 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1568 if ( cell_count > 1 ) {
1569 // TODO - What we really should do here is verify whether or not any of the
1570 // other cells which use this principal to obtain its credentials actually
1571 // have valid tokens or not. If they are currently using these credentials
1572 // we will skip them. For the time being we assume that if there is an active
1573 // map in the table that they are actively being used.
1577 code = pkrb5_parse_name(ctx, principals[count], &princ);
1578 if (code) goto loop_cleanup;
1580 code = KFW_get_ccache(ctx, princ, &cc);
1581 if (code) goto loop_cleanup;
1583 code = pkrb5_cc_destroy(ctx, cc);
1588 pkrb5_cc_close(ctx, cc);
1592 pkrb5_free_principal(ctx, princ);
1596 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1597 free(principals[count]);
1602 pkrb5_free_context(ctx);
1607 KFW_AFS_destroy_tickets_for_principal(char * user)
1609 krb5_context ctx = NULL;
1610 krb5_error_code code;
1612 char ** cells = NULL;
1613 krb5_principal princ = NULL;
1614 krb5_ccache cc = NULL;
1616 if (!pkrb5_init_context)
1619 if ( IsDebuggerPresent() ) {
1620 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1621 OutputDebugString(user);
1622 OutputDebugString("\n");
1625 code = pkrb5_init_context(&ctx);
1628 code = pkrb5_parse_name(ctx, user, &princ);
1629 if (code) goto loop_cleanup;
1631 code = KFW_get_ccache(ctx, princ, &cc);
1632 if (code) goto loop_cleanup;
1634 code = pkrb5_cc_destroy(ctx, cc);
1639 pkrb5_cc_close(ctx, cc);
1643 pkrb5_free_principal(ctx, princ);
1647 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1650 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1657 pkrb5_free_context(ctx);
1662 KFW_AFS_renew_expiring_tokens(void)
1664 krb5_error_code code = 0;
1665 krb5_context ctx = NULL;
1666 krb5_ccache cc = NULL;
1668 struct principal_ccache_data * pcc_next = princ_cc_data;
1671 const char * realm = NULL;
1672 char local_cell[CELL_MAXNAMELEN+1]="";
1673 struct afsconf_cell cellconfig;
1675 if (!pkrb5_init_context)
1678 if ( pcc_next == NULL ) // nothing to do
1681 if ( IsDebuggerPresent() ) {
1682 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1685 memset(&cellconfig, 0, sizeof(cellconfig));
1687 code = pkrb5_init_context(&ctx);
1688 if (code) goto cleanup;
1690 code = pkrb5_timeofday(ctx, &now);
1691 if (code) goto cleanup;
1693 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1694 if ( pcc_next->expired )
1697 if ( now >= (pcc_next->expiration_time) ) {
1698 if ( !pcc_next->from_lsa ) {
1699 pcc_next->expired = 1;
1704 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1705 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1708 code = KFW_renew(ctx,cc);
1710 if ( code && pcc_next->from_lsa)
1712 #endif /* USE_MS2MIT */
1715 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1716 if (code) goto loop_cleanup;
1718 // Attempt to obtain new tokens for other cells supported by the same
1720 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1721 if ( cell_count > 0 ) {
1722 while ( cell_count-- ) {
1723 if ( IsDebuggerPresent() ) {
1724 OutputDebugString("Cell: ");
1725 OutputDebugString(cells[cell_count]);
1726 OutputDebugString("\n");
1728 if (cellconfig.linkedCell) {
1729 free(cellconfig.linkedCell);
1730 cellconfig.linkedCell = NULL;
1732 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1733 if ( code ) continue;
1734 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1735 if ( IsDebuggerPresent() ) {
1736 OutputDebugString("Realm: ");
1737 OutputDebugString(realm);
1738 OutputDebugString("\n");
1740 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1741 if ( IsDebuggerPresent() ) {
1743 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1744 OutputDebugString(message);
1746 free(cells[cell_count]);
1754 pkrb5_cc_close(ctx,cc);
1761 pkrb5_cc_close(ctx,cc);
1763 pkrb5_free_context(ctx);
1764 if (cellconfig.linkedCell)
1765 free(cellconfig.linkedCell);
1772 KFW_AFS_renew_token_for_cell(char * cell)
1774 krb5_error_code code = 0;
1775 krb5_context ctx = NULL;
1777 char ** principals = NULL;
1779 if (!pkrb5_init_context)
1782 if ( IsDebuggerPresent() ) {
1783 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1784 OutputDebugString(cell);
1785 OutputDebugString("\n");
1788 code = pkrb5_init_context(&ctx);
1789 if (code) goto cleanup;
1791 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1793 // We know we must have a credential somewhere since we are
1794 // trying to renew a token
1796 KFW_import_ccache_data();
1797 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1800 krb5_principal princ = 0;
1801 krb5_principal service = 0;
1803 krb5_creds mcreds, creds;
1804 #endif /* COMMENT */
1806 const char * realm = NULL;
1807 struct afsconf_cell cellconfig;
1808 char local_cell[CELL_MAXNAMELEN+1];
1810 memset(&cellconfig, 0, sizeof(cellconfig));
1813 code = pkrb5_parse_name(ctx, principals[count], &princ);
1814 if (code) goto loop_cleanup;
1816 code = KFW_get_ccache(ctx, princ, &cc);
1817 if (code) goto loop_cleanup;
1819 if (cellconfig.linkedCell) {
1820 free(cellconfig.linkedCell);
1821 cellconfig.linkedCell = NULL;
1823 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1824 if ( code ) goto loop_cleanup;
1826 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1827 if ( IsDebuggerPresent() ) {
1828 OutputDebugString("Realm: ");
1829 OutputDebugString(realm);
1830 OutputDebugString("\n");
1834 /* krb5_cc_remove_cred() is not implemented
1837 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1838 realm, "afs", cell, NULL);
1840 memset(&mcreds, 0, sizeof(krb5_creds));
1841 mcreds.client = princ;
1842 mcreds.server = service;
1844 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1846 if ( IsDebuggerPresent() ) {
1847 char * cname, *sname;
1848 pkrb5_unparse_name(ctx, creds.client, &cname);
1849 pkrb5_unparse_name(ctx, creds.server, &sname);
1850 OutputDebugString("Removing credential for client \"");
1851 OutputDebugString(cname);
1852 OutputDebugString("\" and service \"");
1853 OutputDebugString(sname);
1854 OutputDebugString("\"\n");
1855 pkrb5_free_unparsed_name(ctx,cname);
1856 pkrb5_free_unparsed_name(ctx,sname);
1859 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1860 pkrb5_free_principal(ctx, creds.client);
1861 pkrb5_free_principal(ctx, creds.server);
1864 #endif /* COMMENT */
1866 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1867 if ( IsDebuggerPresent() ) {
1869 StringCbPrintf(message, sizeof(message), "KFW_AFS_klog() returns: %d\n", code);
1870 OutputDebugString(message);
1875 pkrb5_cc_close(ctx, cc);
1879 pkrb5_free_principal(ctx, princ);
1883 pkrb5_free_principal(ctx, service);
1886 if (cellconfig.linkedCell) {
1887 free(cellconfig.linkedCell);
1888 cellconfig.linkedCell = NULL;
1891 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1892 free(principals[count]);
1896 code = -1; // we did not renew the tokens
1900 pkrb5_free_context(ctx);
1901 return (code ? FALSE : TRUE);
1906 KFW_AFS_renew_tokens_for_all_cells(void)
1908 struct cell_principal_map * next = cell_princ_map;
1910 if ( IsDebuggerPresent() )
1911 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1916 for ( ; next ; next = next->next ) {
1918 KFW_AFS_renew_token_for_cell(next->cell);
1924 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1926 krb5_error_code code = 0;
1927 krb5_context ctx = NULL;
1928 krb5_ccache cc = NULL;
1929 krb5_principal me = NULL;
1930 krb5_principal server = NULL;
1931 krb5_creds my_creds;
1932 krb5_data *realm = NULL;
1934 if (!pkrb5_init_context)
1937 memset(&my_creds, 0, sizeof(krb5_creds));
1942 code = pkrb5_init_context(&ctx);
1943 if (code) goto cleanup;
1949 code = pkrb5_cc_default(ctx, &cc);
1950 if (code) goto cleanup;
1953 code = pkrb5_cc_get_principal(ctx, cc, &me);
1954 if (code) goto cleanup;
1956 realm = krb5_princ_realm(ctx, me);
1958 code = pkrb5_build_principal_ext(ctx, &server,
1959 realm->length,realm->data,
1960 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1961 realm->length,realm->data,
1966 if ( IsDebuggerPresent() ) {
1967 char * cname, *sname;
1968 pkrb5_unparse_name(ctx, me, &cname);
1969 pkrb5_unparse_name(ctx, server, &sname);
1970 OutputDebugString("Renewing credential for client \"");
1971 OutputDebugString(cname);
1972 OutputDebugString("\" and service \"");
1973 OutputDebugString(sname);
1974 OutputDebugString("\"\n");
1975 pkrb5_free_unparsed_name(ctx,cname);
1976 pkrb5_free_unparsed_name(ctx,sname);
1979 my_creds.client = me;
1980 my_creds.server = server;
1982 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1984 if ( IsDebuggerPresent() ) {
1986 StringCbPrintf(message, sizeof(message), "krb5_get_renewed_creds() failed: %d\n", code);
1987 OutputDebugString(message);
1992 code = pkrb5_cc_initialize(ctx, cc, me);
1994 if ( IsDebuggerPresent() ) {
1996 StringCbPrintf(message, sizeof(message), "krb5_cc_initialize() failed: %d\n", code);
1997 OutputDebugString(message);
2002 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2004 if ( IsDebuggerPresent() ) {
2006 StringCbPrintf(message, sizeof(message), "krb5_cc_store_cred() failed: %d\n", code);
2007 OutputDebugString(message);
2013 if (my_creds.client == me)
2014 my_creds.client = 0;
2015 if (my_creds.server == server)
2016 my_creds.server = 0;
2017 pkrb5_free_cred_contents(ctx, &my_creds);
2019 pkrb5_free_principal(ctx, me);
2021 pkrb5_free_principal(ctx, server);
2022 if (cc && (cc != alt_cc))
2023 pkrb5_cc_close(ctx, cc);
2024 if (ctx && (ctx != alt_ctx))
2025 pkrb5_free_context(ctx);
2030 KFW_kinit( krb5_context alt_ctx,
2033 char *principal_name,
2035 krb5_deltat lifetime,
2038 krb5_deltat renew_life,
2043 krb5_error_code code = 0;
2044 krb5_context ctx = NULL;
2045 krb5_ccache cc = NULL;
2046 krb5_principal me = NULL;
2048 krb5_creds my_creds;
2049 krb5_get_init_creds_opt options;
2050 krb5_address ** addrs = NULL;
2051 int i = 0, addr_count = 0;
2053 if (!pkrb5_init_context)
2056 pkrb5_get_init_creds_opt_init(&options);
2057 memset(&my_creds, 0, sizeof(my_creds));
2065 code = pkrb5_init_context(&ctx);
2066 if (code) goto cleanup;
2072 code = pkrb5_cc_default(ctx, &cc);
2073 if (code) goto cleanup;
2076 code = pkrb5_parse_name(ctx, principal_name, &me);
2080 code = pkrb5_unparse_name(ctx, me, &name);
2085 lifetime = DEFAULT_LIFETIME;
2092 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2093 pkrb5_get_init_creds_opt_set_forwardable(&options,
2094 forwardable ? 1 : 0);
2095 pkrb5_get_init_creds_opt_set_proxiable(&options,
2097 pkrb5_get_init_creds_opt_set_renew_life(&options,
2100 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2104 // we are going to add the public IP address specified by the user
2105 // to the list provided by the operating system
2106 krb5_address ** local_addrs=NULL;
2109 pkrb5_os_localaddr(ctx, &local_addrs);
2110 while ( local_addrs[i++] );
2113 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2115 pkrb5_free_addresses(ctx, local_addrs);
2118 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2120 while ( local_addrs[i] ) {
2121 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2122 if (addrs[i] == NULL) {
2123 pkrb5_free_addresses(ctx, local_addrs);
2127 addrs[i]->magic = local_addrs[i]->magic;
2128 addrs[i]->addrtype = local_addrs[i]->addrtype;
2129 addrs[i]->length = local_addrs[i]->length;
2130 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2131 if (!addrs[i]->contents) {
2132 pkrb5_free_addresses(ctx, local_addrs);
2136 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2137 local_addrs[i]->length); /* safe */
2140 pkrb5_free_addresses(ctx, local_addrs);
2142 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2143 if (addrs[i] == NULL)
2146 addrs[i]->magic = KV5M_ADDRESS;
2147 addrs[i]->addrtype = AF_INET;
2148 addrs[i]->length = 4;
2149 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2150 if (!addrs[i]->contents)
2153 netIPAddr = htonl(publicIP);
2154 memcpy(addrs[i]->contents,&netIPAddr,4);
2156 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2161 code = pkrb5_get_init_creds_password(ctx,
2164 password, // password
2165 KRB5_prompter, // prompter
2166 hParent, // prompter data
2173 code = pkrb5_cc_initialize(ctx, cc, me);
2177 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2183 for ( i=0;i<addr_count;i++ ) {
2185 if ( addrs[i]->contents )
2186 free(addrs[i]->contents);
2191 if (my_creds.client == me)
2192 my_creds.client = 0;
2193 pkrb5_free_cred_contents(ctx, &my_creds);
2195 pkrb5_free_unparsed_name(ctx, name);
2197 pkrb5_free_principal(ctx, me);
2198 if (cc && (cc != alt_cc))
2199 pkrb5_cc_close(ctx, cc);
2200 if (ctx && (ctx != alt_ctx))
2201 pkrb5_free_context(ctx);
2207 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2209 krb5_context ctx = NULL;
2210 krb5_ccache cc = NULL;
2211 krb5_error_code code;
2213 if (!pkrb5_init_context)
2222 code = pkrb5_init_context(&ctx);
2223 if (code) goto cleanup;
2229 code = pkrb5_cc_default(ctx, &cc);
2230 if (code) goto cleanup;
2233 code = pkrb5_cc_destroy(ctx, cc);
2234 if ( !code ) cc = 0;
2237 if (cc && (cc != alt_cc))
2238 pkrb5_cc_close(ctx, cc);
2239 if (ctx && (ctx != alt_ctx))
2240 pkrb5_free_context(ctx);
2248 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2250 NTSTATUS Status = 0;
2252 TOKEN_STATISTICS Stats;
2258 *ppSessionData = NULL;
2260 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2264 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2265 CloseHandle( TokenHandle );
2269 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2270 if ( FAILED(Status) || !ppSessionData )
2277 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2278 // cache. It validates whether or not it is reasonable to assume that if we
2279 // attempted to retrieve valid tickets we could do so. Microsoft does not
2280 // automatically renew expired tickets. Therefore, the cache could contain
2281 // expired or invalid tickets. Microsoft also caches the user's password
2282 // and will use it to retrieve new TGTs if the cache is empty and tickets
2286 MSLSA_IsKerberosLogon(VOID)
2288 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2289 BOOL Success = FALSE;
2291 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2292 if ( pSessionData->AuthenticationPackage.Buffer ) {
2298 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2299 usLength = (pSessionData->AuthenticationPackage).Length;
2302 StringCbCopyNW( buffer, sizeof(buffer)/sizeof(WCHAR),
2303 usBuffer, usLength);
2304 if ( !lstrcmpW(L"Kerberos",buffer) )
2308 pLsaFreeReturnBuffer(pSessionData);
2312 #endif /* USE_MS2MIT */
2314 static BOOL CALLBACK
2315 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2319 switch ( message ) {
2321 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2323 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2326 for ( i=0; i < mid_cnt ; i++ ) {
2327 if (mid_tb[i].echo == 0)
2328 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2329 else if (mid_tb[i].echo == 2)
2330 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2335 switch ( LOWORD(wParam) ) {
2337 for ( i=0; i < mid_cnt ; i++ ) {
2338 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2339 *mid_tb[i].buf = '\0';
2343 EndDialog(hDialog, LOWORD(wParam));
2351 lpwAlign( LPWORD lpIn )
2355 ul = (ULONG_PTR) lpIn;
2359 return (LPWORD) ul;;
2363 * dialog widths are measured in 1/4 character widths
2364 * dialog height are measured in 1/8 character heights
2368 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2369 char * ptext[], int numlines, int width,
2370 int tb_cnt, struct textField * tb)
2374 LPDLGITEMTEMPLATE lpdit;
2380 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2387 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2389 // Define a dialog box.
2391 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2392 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2393 | DS_SETFOREGROUND | DS_3DLOOK
2394 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2395 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2398 lpdt->cx = 20 + width * 4;
2399 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2401 lpw = (LPWORD) (lpdt + 1);
2402 *lpw++ = 0; // no menu
2403 *lpw++ = 0; // predefined dialog box class (by default)
2405 lpwsz = (LPWSTR) lpw;
2406 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2408 *lpw++ = 8; // font size (points)
2409 lpwsz = (LPWSTR) lpw;
2410 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2414 //-----------------------
2415 // Define an OK button.
2416 //-----------------------
2417 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2418 lpdit = (LPDLGITEMTEMPLATE) lpw;
2419 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2420 lpdit->dwExtendedStyle = 0;
2421 lpdit->x = (lpdt->cx - 14)/4 - 20;
2422 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2425 lpdit->id = IDOK; // OK button identifier
2427 lpw = (LPWORD) (lpdit + 1);
2429 *lpw++ = 0x0080; // button class
2431 lpwsz = (LPWSTR) lpw;
2432 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2434 *lpw++ = 0; // no creation data
2436 //-----------------------
2437 // Define an Cancel button.
2438 //-----------------------
2439 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2440 lpdit = (LPDLGITEMTEMPLATE) lpw;
2441 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2442 lpdit->dwExtendedStyle = 0;
2443 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2444 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2447 lpdit->id = IDCANCEL; // CANCEL button identifier
2449 lpw = (LPWORD) (lpdit + 1);
2451 *lpw++ = 0x0080; // button class
2453 lpwsz = (LPWSTR) lpw;
2454 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2456 *lpw++ = 0; // no creation data
2458 /* Add controls for preface data */
2459 for ( i=0; i<numlines; i++) {
2460 /*-----------------------
2461 * Define a static text control.
2462 *-----------------------*/
2463 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2464 lpdit = (LPDLGITEMTEMPLATE) lpw;
2465 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2466 lpdit->dwExtendedStyle = 0;
2468 lpdit->y = 10 + i * 14;
2469 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2471 lpdit->id = ID_TEXT + i; // text identifier
2473 lpw = (LPWORD) (lpdit + 1);
2475 *lpw++ = 0x0082; // static class
2477 lpwsz = (LPWSTR) lpw;
2478 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2479 -1, lpwsz, 2*width);
2481 *lpw++ = 0; // no creation data
2484 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2485 int len = (int)strlen(tb[i].label);
2490 for ( i=0; i<tb_cnt; i++) {
2492 /*-----------------------
2493 * Define a static text control.
2494 *-----------------------*/
2495 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2496 lpdit = (LPDLGITEMTEMPLATE) lpw;
2497 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2498 lpdit->dwExtendedStyle = 0;
2500 lpdit->y = 10 + (numlines + i + 1) * 14;
2501 lpdit->cx = pwid * 4;
2503 lpdit->id = ID_TEXT + numlines + i; // text identifier
2505 lpw = (LPWORD) (lpdit + 1);
2507 *lpw++ = 0x0082; // static class
2509 lpwsz = (LPWSTR) lpw;
2510 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2513 *lpw++ = 0; // no creation data
2515 /*-----------------------
2516 * Define an edit control.
2517 *-----------------------*/
2518 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2519 lpdit = (LPDLGITEMTEMPLATE) lpw;
2520 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2521 lpdit->dwExtendedStyle = 0;
2522 lpdit->x = 10 + (pwid + 1) * 4;
2523 lpdit->y = 10 + (numlines + i + 1) * 14;
2524 lpdit->cx = (width - (pwid + 1)) * 4;
2526 lpdit->id = ID_MID_TEXT + i; // identifier
2528 lpw = (LPWORD) (lpdit + 1);
2530 *lpw++ = 0x0081; // edit class
2532 lpwsz = (LPWSTR) lpw;
2533 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2536 *lpw++ = 0; // no creation data
2540 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2541 hwndOwner, (DLGPROC) MultiInputDialogProc);
2545 case 0: /* Timeout */
2553 StringCbPrintf(buf, sizeof(buf), "DialogBoxIndirect() failed: %d", GetLastError());
2554 MessageBox(hwndOwner,
2557 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2564 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2566 HINSTANCE hInst = 0;
2570 char * plines[16], *p = preface ? preface : "";
2573 for ( i=0; i<16; i++ )
2576 while (*p && numlines < 16) {
2577 plines[numlines++] = p;
2578 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2579 if ( *p == '\r' && *(p+1) == '\n' ) {
2582 } else if ( *p == '\n' ) {
2585 if ( strlen(plines[numlines-1]) > maxwidth )
2586 maxwidth = (int)strlen(plines[numlines-1]);
2589 for ( i=0;i<n;i++ ) {
2590 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2591 if ( maxwidth < len )
2595 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2598 static krb5_error_code KRB5_CALLCONV
2599 KRB5_prompter( krb5_context context,
2604 krb5_prompt prompts[])
2606 krb5_error_code errcode = 0;
2608 struct textField * tb = NULL;
2609 int len = 0, blen=0, nlen=0;
2610 HWND hParent = (HWND)data;
2613 nlen = (int)strlen(name)+2;
2616 blen = (int)strlen(banner)+2;
2618 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2621 memset(tb,0,sizeof(struct textField) * num_prompts);
2622 for ( i=0; i < num_prompts; i++ ) {
2623 tb[i].buf = prompts[i].reply->data;
2624 tb[i].len = prompts[i].reply->length;
2625 tb[i].label = prompts[i].prompt;
2627 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2630 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2632 for ( i=0; i < num_prompts; i++ )
2633 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2641 for (i = 0; i < num_prompts; i++) {
2642 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2649 KFW_AFS_wait_for_service_start(void)
2654 CurrentState = SERVICE_START_PENDING;
2655 memset(HostName, '\0', sizeof(HostName));
2656 gethostname(HostName, sizeof(HostName));
2658 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2660 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2662 if ( IsDebuggerPresent() ) {
2663 switch ( CurrentState ) {
2664 case SERVICE_STOPPED:
2665 OutputDebugString("SERVICE_STOPPED\n");
2667 case SERVICE_START_PENDING:
2668 OutputDebugString("SERVICE_START_PENDING\n");
2670 case SERVICE_STOP_PENDING:
2671 OutputDebugString("SERVICE_STOP_PENDING\n");
2673 case SERVICE_RUNNING:
2674 OutputDebugString("SERVICE_RUNNING\n");
2676 case SERVICE_CONTINUE_PENDING:
2677 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2679 case SERVICE_PAUSE_PENDING:
2680 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2682 case SERVICE_PAUSED:
2683 OutputDebugString("SERVICE_PAUSED\n");
2686 OutputDebugString("UNKNOWN Service State\n");
2689 if (CurrentState == SERVICE_STOPPED)
2691 if (CurrentState == SERVICE_RUNNING)
2707 memset(HostName, '\0', sizeof(HostName));
2708 gethostname(HostName, sizeof(HostName));
2709 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2711 if (CurrentState != SERVICE_RUNNING)
2714 rc = ktc_ForgetAllTokens();
2720 #define ALLOW_REGISTER 1
2722 ViceIDToUsername(char *username,
2723 char *realm_of_user,
2724 char *realm_of_cell,
2726 struct ktc_principal *aclient,
2727 struct ktc_principal *aserver,
2728 struct ktc_token *atoken)
2730 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2731 static char confdir[512] = { 0 };
2732 #ifdef AFS_ID_TO_NAME
2733 char username_copy[BUFSIZ];
2734 #endif /* AFS_ID_TO_NAME */
2735 long viceId = ANONYMOUSID; /* AFS uid of user */
2737 #ifdef ALLOW_REGISTER
2739 #endif /* ALLOW_REGISTER */
2741 if (confdir[0] == '\0')
2742 cm_GetConfigDir(confdir, sizeof(confdir));
2744 StringCbCopyN( lastcell, sizeof(lastcell),
2745 aserver->cell, sizeof(lastcell) - 1);
2747 if (!pr_Initialize (0, confdir, aserver->cell)) {
2748 char sname[PR_MAXNAMELEN];
2749 StringCbCopyN( sname, sizeof(sname),
2750 username, sizeof(sname) - 1);
2751 status = pr_SNameToId (sname, &viceId);
2756 * This is a crock, but it is Transarc's crock, so
2757 * we have to play along in order to get the
2758 * functionality. The way the afs id is stored is
2759 * as a string in the username field of the token.
2760 * Contrary to what you may think by looking at
2761 * the code for tokens, this hack (AFS ID %d) will
2762 * not work if you change %d to something else.
2766 * This code is taken from cklog -- it lets people
2767 * automatically register with the ptserver in foreign cells
2770 #ifdef ALLOW_REGISTER
2772 if (viceId != ANONYMOUSID) {
2773 #else /* ALLOW_REGISTER */
2774 if ((status == 0) && (viceId != ANONYMOUSID))
2775 #endif /* ALLOW_REGISTER */
2777 #ifdef AFS_ID_TO_NAME
2778 StringCbCopyN( username_copy, sizeof(username_copy),
2779 username, sizeof(username_copy) - 1);
2780 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2781 #endif /* AFS_ID_TO_NAME */
2783 #ifdef ALLOW_REGISTER
2784 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2786 StringCbCopyN( aclient->name, sizeof(aclient->name),
2787 username, sizeof(aclient->name) - 1);
2788 aclient->instance[0] = '\0';
2789 StringCbCopyN( aclient->cell, sizeof(aclient->cell),
2790 realm_of_user, sizeof(aclient->cell) - 1);
2791 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2793 if (status = pr_Initialize(1L, confdir, aserver->cell))
2795 status = pr_CreateUser(username, &id);
2799 #ifdef AFS_ID_TO_NAME
2800 StringCbCopyN( username_copy, sizeof(username_copy),
2801 username, sizeof(username_copy) - 1);
2802 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2803 #endif /* AFS_ID_TO_NAME */
2806 #endif /* ALLOW_REGISTER */
2812 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2813 krb5_error_code code;
2814 krb5_ticket *ticket;
2817 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2819 len = krb5_princ_realm(context, ticket->server)->length;
2820 if (len > destlen - 1)
2823 StringCbCopyN(dest, destlen, krb5_princ_realm(context, ticket->server)->data, len);
2825 pkrb5_free_ticket(context, ticket);
2831 krb5_context alt_ctx,
2836 int lifetime, /* unused parameter */
2844 #endif /* USE_KRB4 */
2845 struct ktc_principal aserver;
2846 struct ktc_principal aclient;
2847 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2848 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2849 char local_cell[CELL_MAXNAMELEN+1];
2850 char Dmycell[CELL_MAXNAMELEN+1];
2851 struct ktc_token atoken;
2852 struct ktc_token btoken;
2853 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2854 char RealmName[128];
2856 char ServiceName[128];
2860 krb5_context ctx = NULL;
2861 krb5_ccache cc = NULL;
2863 krb5_creds * k5creds = NULL;
2864 krb5_error_code code;
2865 krb5_principal client_principal = NULL;
2866 krb5_data * k5data = NULL;
2867 unsigned int i, retry = 0;
2870 memset(HostName, '\0', sizeof(HostName));
2871 gethostname(HostName, sizeof(HostName));
2872 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2873 if ( IsDebuggerPresent() )
2874 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2877 if (CurrentState != SERVICE_RUNNING) {
2878 if ( IsDebuggerPresent() )
2879 OutputDebugString("AFSD Service NOT RUNNING\n");
2883 if (!pkrb5_init_context)
2886 memset(&ak_cellconfig, 0, sizeof(ak_cellconfig));
2887 memset(RealmName, '\0', sizeof(RealmName));
2888 memset(CellName, '\0', sizeof(CellName));
2889 memset(ServiceName, '\0', sizeof(ServiceName));
2890 memset(realm_of_user, '\0', sizeof(realm_of_user));
2891 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2892 if (cell && cell[0])
2893 StringCbCopyN( Dmycell, sizeof(Dmycell),
2894 cell, sizeof(Dmycell) - 1);
2896 memset(Dmycell, '\0', sizeof(Dmycell));
2898 // NULL or empty cell returns information on local cell
2899 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2901 // KFW_AFS_error(rc, "get_cellconfig()");
2908 code = pkrb5_init_context(&ctx);
2909 if (code) goto cleanup;
2915 code = pkrb5_cc_default(ctx, &cc);
2916 if (code) goto skip_krb5_init;
2919 memset(&increds, 0, sizeof(increds));
2921 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2923 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2925 OutputDebugString("Principal Not Found for ccache\n");
2927 goto skip_krb5_init;
2930 if (!KFW_accept_dotted_usernames()) {
2931 /* look for client principals which cannot be distinguished
2932 * from Kerberos 4 multi-component principal names
2934 k5data = krb5_princ_component(ctx,client_principal,0);
2935 for ( i=0; i<k5data->length; i++ ) {
2936 if ( k5data->data[i] == '.' )
2939 if (i != k5data->length)
2941 OutputDebugString("Illegal Principal name contains dot in first component\n");
2942 rc = KRB5KRB_ERR_GENERIC;
2947 i = krb5_princ_realm(ctx, client_principal)->length;
2950 StringCbCopyN( realm_of_user, sizeof(realm_of_user),
2951 krb5_princ_realm(ctx, client_principal)->data, i);
2956 if ( !try_krb5 || !realm_of_user[0] ) {
2957 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2966 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
2967 afs_realm_of_cell(ctx, &ak_cellconfig),
2968 sizeof(realm_of_cell) - 1);
2970 if (strlen(service) == 0)
2971 StringCbCopy( ServiceName, sizeof(ServiceName), "afs");
2973 StringCbCopyN( ServiceName, sizeof(ServiceName),
2974 service, sizeof(ServiceName) - 1);
2976 if (strlen(cell) == 0)
2977 StringCbCopyN( CellName, sizeof(CellName),
2978 local_cell, sizeof(CellName) - 1);
2980 StringCbCopyN( CellName, sizeof(CellName),
2981 cell, sizeof(CellName) - 1);
2983 /* This is for Kerberos v4 only */
2984 if (strlen(realm) == 0)
2985 StringCbCopyN( RealmName, sizeof(RealmName),
2986 realm_of_cell, sizeof(RealmName) - 1);
2988 StringCbCopyN( RealmName, sizeof(RealmName),
2989 realm, sizeof(RealmName) - 1);
2991 memset(&creds, '\0', sizeof(creds));
2995 code = KRB5KRB_ERR_GENERIC;
2998 increds.client = client_principal;
2999 increds.times.endtime = 0;
3000 /* Ask for DES since that is what V4 understands */
3001 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
3003 /* If there was a specific realm we are supposed to try
3006 if (strlen(realm) != 0) {
3007 /* service/cell@REALM */
3009 code = pkrb5_build_principal(ctx, &increds.server,
3015 if ( IsDebuggerPresent() ) {
3016 char * cname, *sname;
3017 pkrb5_unparse_name(ctx, increds.client, &cname);
3018 pkrb5_unparse_name(ctx, increds.server, &sname);
3019 OutputDebugString("Getting tickets for \"");
3020 OutputDebugString(cname);
3021 OutputDebugString("\" and service \"");
3022 OutputDebugString(sname);
3023 OutputDebugString("\"\n");
3024 pkrb5_free_unparsed_name(ctx,cname);
3025 pkrb5_free_unparsed_name(ctx,sname);
3029 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3031 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3032 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3033 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3034 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3035 /* Or service@REALM */
3036 pkrb5_free_principal(ctx,increds.server);
3038 code = pkrb5_build_principal(ctx, &increds.server,
3044 if ( IsDebuggerPresent() ) {
3045 char * cname, *sname;
3046 pkrb5_unparse_name(ctx, increds.client, &cname);
3047 pkrb5_unparse_name(ctx, increds.server, &sname);
3048 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3049 OutputDebugString("Trying again: getting tickets for \"");
3050 OutputDebugString(cname);
3051 OutputDebugString("\" and service \"");
3052 OutputDebugString(sname);
3053 OutputDebugString("\"\n");
3054 pkrb5_free_unparsed_name(ctx,cname);
3055 pkrb5_free_unparsed_name(ctx,sname);
3059 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3063 /* we have a local realm for the cell */
3064 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3065 realm, sizeof(realm_of_cell) - 1);
3068 /* Otherwise, first try service/cell@CLIENT_REALM */
3069 if (code = pkrb5_build_principal(ctx, &increds.server,
3070 (int)strlen(realm_of_user),
3079 if ( IsDebuggerPresent() ) {
3080 char * cname, *sname;
3081 pkrb5_unparse_name(ctx, increds.client, &cname);
3082 pkrb5_unparse_name(ctx, increds.server, &sname);
3083 OutputDebugString("Getting tickets for \"");
3084 OutputDebugString(cname);
3085 OutputDebugString("\" and service \"");
3086 OutputDebugString(sname);
3087 OutputDebugString("\"\n");
3088 pkrb5_free_unparsed_name(ctx,cname);
3089 pkrb5_free_unparsed_name(ctx,sname);
3092 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3094 /* The client's realm is a local realm for the cell.
3095 * Save it so that later the pts registration will not
3098 StringCbCopyN( realm_of_cell, sizeof(realm_of_cell),
3099 realm_of_user, sizeof(realm_of_cell) - 1);
3102 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3103 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3104 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3105 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
3106 strcmp(realm_of_user, realm_of_cell)) {
3107 /* Then service/cell@CELL_REALM */
3108 pkrb5_free_principal(ctx,increds.server);
3110 code = pkrb5_build_principal(ctx, &increds.server,
3111 (int)strlen(realm_of_cell),
3116 if ( IsDebuggerPresent() ) {
3117 char * cname, *sname;
3118 pkrb5_unparse_name(ctx, increds.client, &cname);
3119 pkrb5_unparse_name(ctx, increds.server, &sname);
3120 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3121 OutputDebugString("Trying again: getting tickets for \"");
3122 OutputDebugString(cname);
3123 OutputDebugString("\" and service \"");
3124 OutputDebugString(sname);
3125 OutputDebugString("\"\n");
3126 pkrb5_free_unparsed_name(ctx,cname);
3127 pkrb5_free_unparsed_name(ctx,sname);
3131 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3133 if (!code && !strlen(realm_of_cell))
3134 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3137 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3138 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3139 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3140 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3141 /* Finally service@CELL_REALM */
3142 pkrb5_free_principal(ctx,increds.server);
3144 code = pkrb5_build_principal(ctx, &increds.server,
3145 (int)strlen(realm_of_cell),
3150 if ( IsDebuggerPresent() ) {
3151 char * cname, *sname;
3152 pkrb5_unparse_name(ctx, increds.client, &cname);
3153 pkrb5_unparse_name(ctx, increds.server, &sname);
3154 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3155 OutputDebugString("Trying again: getting tickets for \"");
3156 OutputDebugString(cname);
3157 OutputDebugString("\" and service \"");
3158 OutputDebugString(sname);
3159 OutputDebugString("\"\n");
3160 pkrb5_free_unparsed_name(ctx,cname);
3161 pkrb5_free_unparsed_name(ctx,sname);
3165 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3166 if (!code && !strlen(realm_of_cell))
3167 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3172 if ( IsDebuggerPresent() ) {
3174 StringCbPrintf(message, sizeof(message), "krb5_get_credentials returns: %d\n", code);
3175 OutputDebugString(message);
3181 /* This code inserts the entire K5 ticket into the token
3182 * No need to perform a krb524 translation which is
3183 * commented out in the code below
3185 if (KFW_use_krb524() ||
3186 k5creds->ticket.length > MAXKTCTICKETLEN)
3189 memset(&aserver, '\0', sizeof(aserver));
3190 StringCbCopyN( aserver.name, sizeof(aserver.name),
3191 ServiceName, sizeof(aserver.name) - 1);
3192 StringCbCopyN( aserver.cell, sizeof(aserver.cell),
3193 CellName, sizeof(aserver.cell) - 1);
3195 memset(&atoken, '\0', sizeof(atoken));
3196 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3197 atoken.startTime = k5creds->times.starttime;
3198 atoken.endTime = k5creds->times.endtime;
3199 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3200 atoken.ticketLen = k5creds->ticket.length;
3201 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3204 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3205 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3206 if ( rc == KTC_NOCM && retry < 20 ) {
3209 goto retry_gettoken5;
3214 if (atoken.kvno == btoken.kvno &&
3215 atoken.ticketLen == btoken.ticketLen &&
3216 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3217 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3219 /* Success - Nothing to do */
3223 // * Reset the "aclient" structure before we call ktc_SetToken.
3224 // * This structure was first set by the ktc_GetToken call when
3225 // * we were comparing whether identical tokens already existed.
3227 len = min(k5creds->client->data[0].length, sizeof(aclient.name) - 1);
3228 StringCbCopyN( aclient.name, sizeof(aclient.name),
3229 k5creds->client->data[0].data, len);
3231 if ( k5creds->client->length > 1 ) {
3232 StringCbCat( aclient.name, sizeof(aclient.name), ".");
3233 len = min(k5creds->client->data[1].length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3234 StringCbCatN( aclient.name, sizeof(aclient.name),
3235 k5creds->client->data[1].data, len);
3237 aclient.instance[0] = '\0';
3239 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3240 realm_of_cell, sizeof(aclient.cell) - 1);
3242 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3243 /* For Khimaira, always append the realm name */
3244 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3245 StringCbCat( aclient.name, sizeof(aclient.name), "@");
3246 len = min(k5creds->client->realm.length, (int)(sizeof(aclient.name) - strlen(aclient.name) - 1));
3247 StringCbCatN( aclient.name, sizeof(aclient.name), k5creds->client->realm.data, len);
3250 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3251 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3252 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3253 &aclient, &aserver, &atoken);
3256 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3257 smbname, sizeof(aclient.smbname) - 1);
3259 aclient.smbname[0] = '\0';
3262 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3264 goto cleanup; /* We have successfully inserted the token */
3270 /* Otherwise, the ticket could have been too large so try to
3271 * convert using the krb524d running with the KDC
3273 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3274 pkrb5_free_creds(ctx, k5creds);
3276 if ( IsDebuggerPresent() ) {
3278 StringCbPrintf(message, sizeof(message), "krb524_convert_creds_kdc returns: %d\n", code);
3279 OutputDebugString(message);
3284 #endif /* USE_KRB524 */
3288 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3289 if (code == NO_TKT_FIL) {
3290 // if the problem is that we have no krb4 tickets
3291 // do not attempt to continue
3294 if (code != KSUCCESS)
3295 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3297 if (code != KSUCCESS)
3299 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3301 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3306 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3308 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3323 memset(&aserver, '\0', sizeof(aserver));
3324 StringCbCopyN( aserver.name, sizeof(aserver.name), ServiceName, sizeof(aserver.name) - 1);
3325 StringCbCopyN( aserver.cell, sizeof(aserver.cell), CellName, sizeof(aserver.cell) - 1);
3327 memset(&atoken, '\0', sizeof(atoken));
3328 atoken.kvno = creds.kvno;
3329 atoken.startTime = creds.issue_date;
3330 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3331 memcpy(&atoken.sessionKey, creds.session, 8);
3332 atoken.ticketLen = creds.ticket_st.length;
3333 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3336 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3337 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3338 if ( rc == KTC_NOCM && retry < 20 ) {
3341 goto retry_gettoken;
3343 KFW_AFS_error(rc, "ktc_GetToken()");
3348 if (atoken.kvno == btoken.kvno &&
3349 atoken.ticketLen == btoken.ticketLen &&
3350 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3351 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3356 // * Reset the "aclient" structure before we call ktc_SetToken.
3357 // * This structure was first set by the ktc_GetToken call when
3358 // * we were comparing whether identical tokens already existed.
3360 StringCbCopyN( aclient.name, sizeof(aclient.name), creds.pname, sizeof(aclient.name) - 1);
3363 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3364 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3366 aclient.instance[0] = '\0';
3368 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3369 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3370 aclient.name[MAXKTCREALMLEN-1] = '\0';
3372 StringCbCopyN( aclient.cell, sizeof(aclient.cell),
3373 CellName, sizeof(aclient.cell) - 1);
3375 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3376 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3377 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3378 &aclient, &aserver, &atoken);
3381 StringCbCopyN( aclient.smbname, sizeof(aclient.smbname),
3382 smbname, sizeof(aclient.smbname) - 1);
3384 aclient.smbname[0] = '\0';
3387 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3389 KFW_AFS_error(rc, "ktc_SetToken()");
3395 if (client_principal)
3396 pkrb5_free_principal(ctx,client_principal);
3397 /* increds.client == client_principal */
3399 pkrb5_free_principal(ctx,increds.server);
3400 if (cc && (cc != alt_cc))
3401 pkrb5_cc_close(ctx, cc);
3402 if (ctx && (ctx != alt_ctx))
3403 pkrb5_free_context(ctx);
3404 if (ak_cellconfig.linkedCell)
3405 free(ak_cellconfig.linkedCell);
3407 return(rc? rc : code);
3410 /**************************************/
3411 /* afs_realm_of_cell(): */
3412 /**************************************/
3414 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3416 static char krbrlm[REALM_SZ+1]="";
3417 char ** realmlist=NULL;
3423 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3424 if ( !r && realmlist && realmlist[0] ) {
3425 StringCbCopyN( krbrlm, sizeof(krbrlm),
3426 realmlist[0], sizeof(krbrlm) - 1);
3427 pkrb5_free_host_realm(ctx, realmlist);
3433 char *t = cellconfig->name;
3438 if (islower(c)) c=toupper(c);
3446 /**************************************/
3447 /* KFW_AFS_get_cellconfig(): */
3448 /**************************************/
3450 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3453 char newcell[CELL_MAXNAMELEN+1];
3454 char linkedcell[CELL_MAXNAMELEN+1]="";
3456 local_cell[0] = (char)0;
3457 memset(cellconfig, 0, sizeof(*cellconfig));
3459 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3460 if (rc = cm_GetRootCellName(local_cell))
3465 if (strlen(cell) == 0)
3466 strcpy(cell, local_cell);
3468 rc = cm_SearchCellRegistry(1, cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3469 if (rc && rc != CM_ERROR_FORCE_DNS_LOOKUP)
3470 rc = cm_SearchCellFileEx(cell, newcell, linkedcell, get_cellconfig_callback, (void*)cellconfig);
3473 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3477 StringCbCopyN( cellconfig->name, sizeof(cellconfig->name),
3478 newcell, sizeof(cellconfig->name) - 1);
3480 cellconfig->linkedCell = strdup(linkedcell);
3485 /**************************************/
3486 /* get_cellconfig_callback(): */
3487 /**************************************/
3489 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep, unsigned short ipRank)
3491 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3493 cc->hostAddr[cc->numServers] = *addrp;
3494 StringCbCopyN( cc->hostName[cc->numServers], sizeof(cc->hostName[cc->numServers]),
3495 namep, sizeof(cc->hostName[cc->numServers]) - 1);
3501 /**************************************/
3502 /* KFW_AFS_error(): */
3503 /**************************************/
3505 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3508 const char *errText;
3510 // Using AFS defines as error messages for now, until Transarc
3511 // gets back to me with "string" translations of each of these
3513 if (rc == KTC_ERROR)
3514 errText = "KTC_ERROR";
3515 else if (rc == KTC_TOOBIG)
3516 errText = "KTC_TOOBIG";
3517 else if (rc == KTC_INVAL)
3518 errText = "KTC_INVAL";
3519 else if (rc == KTC_NOENT)
3520 errText = "KTC_NOENT";
3521 else if (rc == KTC_PIOCTLFAIL)
3522 errText = "KTC_PIOCTLFAIL";
3523 else if (rc == KTC_NOPIOCTL)
3524 errText = "KTC_NOPIOCTL";
3525 else if (rc == KTC_NOCELL)
3526 errText = "KTC_NOCELL";
3527 else if (rc == KTC_NOCM)
3528 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3530 errText = "Unknown error!";
3532 StringCbPrintf(message, sizeof(message), "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3534 if ( IsDebuggerPresent() ) {
3535 OutputDebugString(message);
3536 OutputDebugString("\n");
3538 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3544 LPSTR lpszMachineName,
3545 LPSTR lpszServiceName,
3546 DWORD *lpdwCurrentState)
3549 SC_HANDLE schSCManager = NULL;
3550 SC_HANDLE schService = NULL;
3551 DWORD fdwDesiredAccess = 0;
3552 SERVICE_STATUS ssServiceStatus = {0};
3555 *lpdwCurrentState = 0;
3557 fdwDesiredAccess = GENERIC_READ;
3559 schSCManager = OpenSCManager(lpszMachineName,
3563 if(schSCManager == NULL)
3565 hr = GetLastError();
3569 schService = OpenService(schSCManager,
3573 if(schService == NULL)
3575 hr = GetLastError();
3579 fRet = QueryServiceStatus(schService,
3584 hr = GetLastError();
3588 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3592 CloseServiceHandle(schService);
3593 CloseServiceHandle(schSCManager);