2 * Copyright (c) 2004, 2005, 2006, 2007, 2008 Secure Endpoints Inc.
3 * Copyright (c) 2003 SkyRope, LLC
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * - Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * - Neither the name of Skyrope, LLC nor the names of its contributors may be
15 * used to endorse or promote products derived from this software without
16 * specific prior written permission from Skyrope, LLC.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
22 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 * Portions of this code are derived from portions of the MIT
31 * Leash Ticket Manager and LoadFuncs utilities. For these portions the
32 * following copyright applies.
34 * Copyright (c) 2003,2004 by the Massachusetts Institute of Technology.
35 * All rights reserved.
37 * Export of this software from the United States of America may
38 * require a specific license from the United States Government.
39 * It is the responsibility of any person or organization contemplating
40 * export to obtain such a license before exporting.
42 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
43 * distribute this software and its documentation for any purpose and
44 * without fee is hereby granted, provided that the above copyright
45 * notice appear in all copies and that both that copyright notice and
46 * this permission notice appear in supporting documentation, and that
47 * the name of M.I.T. not be used in advertising or publicity pertaining
48 * to distribution of the software without specific, written prior
49 * permission. Furthermore if you modify this software you must label
50 * your software as modified software and not distribute it in such a
51 * fashion that it might be confused with the original M.I.T. software.
52 * M.I.T. makes no representations about the suitability of
53 * this software for any purpose. It is provided "as is" without express
54 * or implied warranty.
66 #include "afskfw-int.h"
74 #include <afs/ptserver.h>
75 #include <afs/ptuser.h>
78 #include <WINNT\afsreg.h>
81 * TIMING _____________________________________________________________________
85 #define cminREMIND_TEST 1 // test every minute for expired creds
86 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
87 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
88 #define cminMINLIFE 30 // minimum life of Kerberos creds
90 #define c100ns1SECOND (LONGLONG)10000000
91 #define cmsec1SECOND 1000
92 #define cmsec1MINUTE 60000
93 #define csec1MINUTE 60
95 /* Function Pointer Declarations for Delayed Loading */
97 DECL_FUNC_PTR(cc_initialize);
98 DECL_FUNC_PTR(cc_shutdown);
99 DECL_FUNC_PTR(cc_get_NC_info);
100 DECL_FUNC_PTR(cc_free_NC_info);
104 DECL_FUNC_PTR(Leash_get_default_lifetime);
105 DECL_FUNC_PTR(Leash_get_default_forwardable);
106 DECL_FUNC_PTR(Leash_get_default_renew_till);
107 DECL_FUNC_PTR(Leash_get_default_noaddresses);
108 DECL_FUNC_PTR(Leash_get_default_proxiable);
109 DECL_FUNC_PTR(Leash_get_default_publicip);
110 DECL_FUNC_PTR(Leash_get_default_use_krb4);
111 DECL_FUNC_PTR(Leash_get_default_life_min);
112 DECL_FUNC_PTR(Leash_get_default_life_max);
113 DECL_FUNC_PTR(Leash_get_default_renew_min);
114 DECL_FUNC_PTR(Leash_get_default_renew_max);
115 DECL_FUNC_PTR(Leash_get_default_renewable);
116 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
120 DECL_FUNC_PTR(krb5_change_password);
121 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
122 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
123 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
124 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
125 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
126 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
127 DECL_FUNC_PTR(krb5_get_init_creds_password);
128 DECL_FUNC_PTR(krb5_build_principal_ext);
129 DECL_FUNC_PTR(krb5_cc_get_name);
130 DECL_FUNC_PTR(krb5_cc_resolve);
131 DECL_FUNC_PTR(krb5_cc_default);
132 DECL_FUNC_PTR(krb5_cc_default_name);
133 DECL_FUNC_PTR(krb5_cc_set_default_name);
134 DECL_FUNC_PTR(krb5_cc_initialize);
135 DECL_FUNC_PTR(krb5_cc_destroy);
136 DECL_FUNC_PTR(krb5_cc_close);
137 DECL_FUNC_PTR(krb5_cc_store_cred);
138 DECL_FUNC_PTR(krb5_cc_copy_creds);
139 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
140 DECL_FUNC_PTR(krb5_cc_get_principal);
141 DECL_FUNC_PTR(krb5_cc_start_seq_get);
142 DECL_FUNC_PTR(krb5_cc_next_cred);
143 DECL_FUNC_PTR(krb5_cc_end_seq_get);
144 DECL_FUNC_PTR(krb5_cc_remove_cred);
145 DECL_FUNC_PTR(krb5_cc_set_flags);
146 DECL_FUNC_PTR(krb5_cc_get_type);
147 DECL_FUNC_PTR(krb5_free_context);
148 DECL_FUNC_PTR(krb5_free_cred_contents);
149 DECL_FUNC_PTR(krb5_free_principal);
150 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
151 DECL_FUNC_PTR(krb5_init_context);
152 DECL_FUNC_PTR(krb5_parse_name);
153 DECL_FUNC_PTR(krb5_timeofday);
154 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
155 DECL_FUNC_PTR(krb5_unparse_name);
156 DECL_FUNC_PTR(krb5_get_credentials);
157 DECL_FUNC_PTR(krb5_mk_req);
158 DECL_FUNC_PTR(krb5_sname_to_principal);
159 DECL_FUNC_PTR(krb5_get_credentials_renew);
160 DECL_FUNC_PTR(krb5_free_data);
161 DECL_FUNC_PTR(krb5_free_data_contents);
162 DECL_FUNC_PTR(krb5_free_unparsed_name);
163 DECL_FUNC_PTR(krb5_os_localaddr);
164 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
165 DECL_FUNC_PTR(krb5_copy_data);
166 DECL_FUNC_PTR(krb5_free_creds);
167 DECL_FUNC_PTR(krb5_build_principal);
168 DECL_FUNC_PTR(krb5_get_renewed_creds);
169 DECL_FUNC_PTR(krb5_get_default_config_files);
170 DECL_FUNC_PTR(krb5_free_config_files);
171 DECL_FUNC_PTR(krb5_get_default_realm);
172 DECL_FUNC_PTR(krb5_free_default_realm);
173 DECL_FUNC_PTR(krb5_free_ticket);
174 DECL_FUNC_PTR(krb5_decode_ticket);
175 DECL_FUNC_PTR(krb5_get_host_realm);
176 DECL_FUNC_PTR(krb5_free_host_realm);
177 DECL_FUNC_PTR(krb5_free_addresses);
178 DECL_FUNC_PTR(krb5_c_random_make_octets);
182 DECL_FUNC_PTR(krb524_init_ets);
183 DECL_FUNC_PTR(krb524_convert_creds_kdc);
188 DECL_FUNC_PTR(krb_get_cred);
189 DECL_FUNC_PTR(tkt_string);
190 DECL_FUNC_PTR(krb_get_tf_realm);
191 DECL_FUNC_PTR(krb_mk_req);
195 DECL_FUNC_PTR(com_err);
196 DECL_FUNC_PTR(error_message);
199 DECL_FUNC_PTR(profile_init);
200 DECL_FUNC_PTR(profile_release);
201 DECL_FUNC_PTR(profile_get_subsection_names);
202 DECL_FUNC_PTR(profile_free_list);
203 DECL_FUNC_PTR(profile_get_string);
204 DECL_FUNC_PTR(profile_release_string);
207 DECL_FUNC_PTR(OpenSCManagerA);
208 DECL_FUNC_PTR(OpenServiceA);
209 DECL_FUNC_PTR(QueryServiceStatus);
210 DECL_FUNC_PTR(CloseServiceHandle);
212 DECL_FUNC_PTR(LsaNtStatusToWinError);
213 #endif /* USE_MS2MIT */
217 DECL_FUNC_PTR(LsaConnectUntrusted);
218 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
219 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
220 DECL_FUNC_PTR(LsaFreeReturnBuffer);
221 DECL_FUNC_PTR(LsaGetLogonSessionData);
222 #endif /* USE_MS2MIT */
225 FUNC_INFO ccapi_fi[] = {
226 MAKE_FUNC_INFO(cc_initialize),
227 MAKE_FUNC_INFO(cc_shutdown),
228 MAKE_FUNC_INFO(cc_get_NC_info),
229 MAKE_FUNC_INFO(cc_free_NC_info),
234 FUNC_INFO leash_fi[] = {
235 MAKE_FUNC_INFO(Leash_get_default_lifetime),
236 MAKE_FUNC_INFO(Leash_get_default_renew_till),
237 MAKE_FUNC_INFO(Leash_get_default_forwardable),
238 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
239 MAKE_FUNC_INFO(Leash_get_default_proxiable),
240 MAKE_FUNC_INFO(Leash_get_default_publicip),
241 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
242 MAKE_FUNC_INFO(Leash_get_default_life_min),
243 MAKE_FUNC_INFO(Leash_get_default_life_max),
244 MAKE_FUNC_INFO(Leash_get_default_renew_min),
245 MAKE_FUNC_INFO(Leash_get_default_renew_max),
246 MAKE_FUNC_INFO(Leash_get_default_renewable),
250 FUNC_INFO leash_opt_fi[] = {
251 MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
256 FUNC_INFO k5_fi[] = {
257 MAKE_FUNC_INFO(krb5_change_password),
258 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
259 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
260 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
261 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
262 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
263 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
264 MAKE_FUNC_INFO(krb5_get_init_creds_password),
265 MAKE_FUNC_INFO(krb5_build_principal_ext),
266 MAKE_FUNC_INFO(krb5_cc_get_name),
267 MAKE_FUNC_INFO(krb5_cc_resolve),
268 MAKE_FUNC_INFO(krb5_cc_default),
269 MAKE_FUNC_INFO(krb5_cc_default_name),
270 MAKE_FUNC_INFO(krb5_cc_set_default_name),
271 MAKE_FUNC_INFO(krb5_cc_initialize),
272 MAKE_FUNC_INFO(krb5_cc_destroy),
273 MAKE_FUNC_INFO(krb5_cc_close),
274 MAKE_FUNC_INFO(krb5_cc_copy_creds),
275 MAKE_FUNC_INFO(krb5_cc_store_cred),
276 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
277 MAKE_FUNC_INFO(krb5_cc_get_principal),
278 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
279 MAKE_FUNC_INFO(krb5_cc_next_cred),
280 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
281 MAKE_FUNC_INFO(krb5_cc_remove_cred),
282 MAKE_FUNC_INFO(krb5_cc_set_flags),
283 MAKE_FUNC_INFO(krb5_cc_get_type),
284 MAKE_FUNC_INFO(krb5_free_context),
285 MAKE_FUNC_INFO(krb5_free_cred_contents),
286 MAKE_FUNC_INFO(krb5_free_principal),
287 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
288 MAKE_FUNC_INFO(krb5_init_context),
289 MAKE_FUNC_INFO(krb5_parse_name),
290 MAKE_FUNC_INFO(krb5_timeofday),
291 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
292 MAKE_FUNC_INFO(krb5_unparse_name),
293 MAKE_FUNC_INFO(krb5_get_credentials),
294 MAKE_FUNC_INFO(krb5_mk_req),
295 MAKE_FUNC_INFO(krb5_sname_to_principal),
296 MAKE_FUNC_INFO(krb5_get_credentials_renew),
297 MAKE_FUNC_INFO(krb5_free_data),
298 MAKE_FUNC_INFO(krb5_free_data_contents),
299 MAKE_FUNC_INFO(krb5_free_unparsed_name),
300 MAKE_FUNC_INFO(krb5_os_localaddr),
301 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
302 MAKE_FUNC_INFO(krb5_copy_data),
303 MAKE_FUNC_INFO(krb5_free_creds),
304 MAKE_FUNC_INFO(krb5_build_principal),
305 MAKE_FUNC_INFO(krb5_get_renewed_creds),
306 MAKE_FUNC_INFO(krb5_free_addresses),
307 MAKE_FUNC_INFO(krb5_get_default_config_files),
308 MAKE_FUNC_INFO(krb5_free_config_files),
309 MAKE_FUNC_INFO(krb5_get_default_realm),
310 MAKE_FUNC_INFO(krb5_free_default_realm),
311 MAKE_FUNC_INFO(krb5_free_ticket),
312 MAKE_FUNC_INFO(krb5_decode_ticket),
313 MAKE_FUNC_INFO(krb5_get_host_realm),
314 MAKE_FUNC_INFO(krb5_free_host_realm),
315 MAKE_FUNC_INFO(krb5_free_addresses),
316 MAKE_FUNC_INFO(krb5_c_random_make_octets),
321 FUNC_INFO k4_fi[] = {
322 MAKE_FUNC_INFO(krb_get_cred),
323 MAKE_FUNC_INFO(krb_get_tf_realm),
324 MAKE_FUNC_INFO(krb_mk_req),
325 MAKE_FUNC_INFO(tkt_string),
331 FUNC_INFO k524_fi[] = {
332 MAKE_FUNC_INFO(krb524_init_ets),
333 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
338 FUNC_INFO profile_fi[] = {
339 MAKE_FUNC_INFO(profile_init),
340 MAKE_FUNC_INFO(profile_release),
341 MAKE_FUNC_INFO(profile_get_subsection_names),
342 MAKE_FUNC_INFO(profile_free_list),
343 MAKE_FUNC_INFO(profile_get_string),
344 MAKE_FUNC_INFO(profile_release_string),
348 FUNC_INFO ce_fi[] = {
349 MAKE_FUNC_INFO(com_err),
350 MAKE_FUNC_INFO(error_message),
354 FUNC_INFO service_fi[] = {
355 MAKE_FUNC_INFO(OpenSCManagerA),
356 MAKE_FUNC_INFO(OpenServiceA),
357 MAKE_FUNC_INFO(QueryServiceStatus),
358 MAKE_FUNC_INFO(CloseServiceHandle),
360 MAKE_FUNC_INFO(LsaNtStatusToWinError),
361 #endif /* USE_MS2MIT */
366 FUNC_INFO lsa_fi[] = {
367 MAKE_FUNC_INFO(LsaConnectUntrusted),
368 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
369 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
370 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
371 MAKE_FUNC_INFO(LsaGetLogonSessionData),
374 #endif /* USE_MS2MIT */
376 /* Static Prototypes */
377 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
378 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
379 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
380 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
381 void *data, const char *name, const char *banner, int num_prompts,
382 krb5_prompt prompts[]);
385 /* Static Declarations */
386 static int inited = 0;
387 static int mid_cnt = 0;
388 static struct textField * mid_tb = NULL;
389 static HINSTANCE hKrb5 = 0;
391 static HINSTANCE hKrb4 = 0;
392 #endif /* USE_KRB4 */
394 static HINSTANCE hKrb524 = 0;
397 static HINSTANCE hSecur32 = 0;
398 #endif /* USE_MS2MIT */
399 static HINSTANCE hAdvApi32 = 0;
400 static HINSTANCE hComErr = 0;
401 static HINSTANCE hService = 0;
402 static HINSTANCE hProfile = 0;
404 static HINSTANCE hLeash = 0;
405 static HINSTANCE hLeashOpt = 0;
407 static HINSTANCE hCCAPI = 0;
408 static struct principal_ccache_data * princ_cc_data = NULL;
409 static struct cell_principal_map * cell_princ_map = NULL;
414 static int inited = 0;
417 char mutexName[MAX_PATH];
418 HANDLE hMutex = NULL;
420 sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
422 hMutex = CreateMutex( NULL, TRUE, mutexName );
423 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
424 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
430 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
431 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
432 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
434 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
435 #endif /* USE_KRB4 */
436 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
438 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
439 #endif /* USE_MS2MIT */
441 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
444 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
445 LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
447 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
449 if ( KFW_is_available() ) {
450 char rootcell[MAXCELLCHARS+1];
452 KFW_import_windows_lsa();
453 #endif /* USE_MS2MIT */
454 KFW_import_ccache_data();
455 KFW_AFS_renew_expiring_tokens();
457 /* WIN32 NOTE: no way to get max chars */
458 if (!cm_GetRootCellName(rootcell))
459 KFW_AFS_renew_token_for_cell(rootcell);
462 ReleaseMutex(hMutex);
472 FreeLibrary(hLeashOpt);
478 FreeLibrary(hKrb524);
484 FreeLibrary(hSecur32);
485 #endif /* USE_MS2MIT */
487 FreeLibrary(hService);
489 FreeLibrary(hComErr);
491 FreeLibrary(hProfile);
495 #endif /* USE_KRB4 */
500 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
503 static int init = TRUE;
504 static int bIsWow64 = FALSE;
508 LPFN_ISWOW64PROCESS fnIsWow64Process = NULL;
510 hModule = GetModuleHandle(TEXT("kernel32"));
512 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process");
514 if (NULL != fnIsWow64Process)
516 if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
518 // on error, assume FALSE.
519 // in other words, do nothing.
522 FreeLibrary(hModule);
530 KFW_accept_dotted_usernames(void)
536 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
537 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
538 if (code == ERROR_SUCCESS) {
540 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
541 (BYTE *) &value, &len);
542 RegCloseKey(parmKey);
544 if (code != ERROR_SUCCESS) {
545 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
546 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
547 if (code == ERROR_SUCCESS) {
549 code = RegQueryValueEx(parmKey, "AcceptDottedPrincipalNames", NULL, NULL,
550 (BYTE *) &value, &len);
551 RegCloseKey (parmKey);
565 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
566 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
567 if (code == ERROR_SUCCESS) {
568 len = sizeof(use524);
569 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
570 (BYTE *) &use524, &len);
571 RegCloseKey(parmKey);
573 if (code != ERROR_SUCCESS) {
574 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
575 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
576 if (code == ERROR_SUCCESS) {
577 len = sizeof(use524);
578 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
579 (BYTE *) &use524, &len);
580 RegCloseKey (parmKey);
587 KFW_is_available(void)
593 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
594 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
595 if (code == ERROR_SUCCESS) {
596 len = sizeof(enableKFW);
597 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
598 (BYTE *) &enableKFW, &len);
599 RegCloseKey (parmKey);
602 if (code != ERROR_SUCCESS) {
603 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
604 0, (IsWow64()?KEY_WOW64_64KEY:0)|KEY_QUERY_VALUE, &parmKey);
605 if (code == ERROR_SUCCESS) {
606 len = sizeof(enableKFW);
607 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
608 (BYTE *) &enableKFW, &len);
609 RegCloseKey (parmKey);
617 if ( hKrb5 && hComErr && hService &&
620 #endif /* USE_MS2MIT */
633 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
634 int FreeContextFlag, krb5_context * ctx,
639 int krb5Error = ((int)(rc & 255));
651 errText = perror_message(rc);
652 _snprintf(message, sizeof(message),
653 "%s\n(Kerberos error %ld)\n\n%s failed",
658 if ( IsDebuggerPresent() )
659 OutputDebugString(message);
661 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
664 if (FreeContextFlag == 1)
666 if (ctx && *ctx != NULL)
668 if (cache && *cache != NULL) {
669 pkrb5_cc_close(*ctx, *cache);
673 pkrb5_free_context(*ctx);
682 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
684 struct principal_ccache_data * next = princ_cc_data;
685 krb5_principal principal = 0;
687 const char * ccname = NULL;
688 const char * cctype = NULL;
689 char * ccfullname = NULL;
690 krb5_error_code code = 0;
691 krb5_error_code cc_code = 0;
697 if (ctx == 0 || cc == 0)
700 code = pkrb5_cc_get_principal(ctx, cc, &principal);
703 code = pkrb5_unparse_name(ctx, principal, &pname);
704 if ( code ) goto cleanup;
706 ccname = pkrb5_cc_get_name(ctx, cc);
707 if (!ccname) goto cleanup;
709 cctype = pkrb5_cc_get_type(ctx, cc);
710 if (!cctype) goto cleanup;
712 ccfullname = malloc(strlen(ccname) + strlen(cctype) + 2);
713 if (!ccfullname) goto cleanup;
715 sprintf(ccfullname, "%s:%s", cctype, ccname);
717 // Search the existing list to see if we have a match
719 for ( ; next ; next = next->next ) {
720 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccfullname) )
725 // If not, match add a new node to the beginning of the list and assign init it
727 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
728 next->next = princ_cc_data;
729 princ_cc_data = next;
730 next->principal = _strdup(pname);
731 next->ccache_name = ccfullname;
733 next->from_lsa = lsa;
735 next->expiration_time = 0;
739 flags = 0; // turn off OPENCLOSE mode
740 code = pkrb5_cc_set_flags(ctx, cc, flags);
741 if ( code ) goto cleanup;
743 code = pkrb5_timeofday(ctx, &now);
745 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
747 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
748 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
750 // we found the ticket we are looking for
751 // check validity of timestamp
752 // We add a 5 minutes fudge factor to compensate for potential
753 // clock skew errors between the KDC and client OS
755 valid = ((creds.times.starttime > 0) &&
756 now >= (creds.times.starttime - 300) &&
757 now < (creds.times.endtime + 300) &&
758 !(creds.ticket_flags & TKT_FLG_INVALID));
760 if ( next->from_lsa) {
762 next->expiration_time = creds.times.endtime;
764 } else if ( valid ) {
766 next->expiration_time = creds.times.endtime;
767 next->renew = (creds.times.renew_till > creds.times.endtime) &&
768 (creds.ticket_flags & TKT_FLG_RENEWABLE);
771 next->expiration_time = 0;
775 pkrb5_free_cred_contents(ctx, &creds);
776 cc_code = KRB5_CC_END;
779 pkrb5_free_cred_contents(ctx, &creds);
782 if (cc_code == KRB5_CC_END) {
783 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
784 if (code) goto cleanup;
788 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
789 code = pkrb5_cc_set_flags(ctx, cc, flags);
794 pkrb5_free_unparsed_name(ctx,pname);
796 pkrb5_free_principal(ctx,principal);
800 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
802 struct principal_ccache_data * next = princ_cc_data;
803 char * response = NULL;
805 if ( !principal || !ccache )
809 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
811 // we always want to prefer the MS Kerberos LSA cache or
812 // the cache afscreds created specifically for the principal
813 // if the current entry is either one, drop the previous find
814 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
817 response = _strdup(next->ccache_name);
818 // MS Kerberos LSA is our best option so use it and quit
819 if ( next->from_lsa )
833 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
835 struct principal_ccache_data ** next = &princ_cc_data;
837 if ( !pname && !ccname )
841 if ( !strcmp((*next)->principal,pname) ||
842 !strcmp((*next)->ccache_name,ccname) ) {
844 free((*next)->principal);
845 free((*next)->ccache_name);
847 (*next) = (*next)->next;
854 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
856 struct cell_principal_map * next = cell_princ_map;
858 // Search the existing list to see if we have a match
860 for ( ; next ; next = next->next ) {
861 if ( !strcmp(next->cell, cell) ) {
862 if ( !strcmp(next->principal,pname) ) {
863 next->active = active;
866 // OpenAFS currently has a restriction of one active token per cell
867 // Therefore, whenever we update the table with a new active cell we
868 // must mark all of the other principal to cell entries as inactive.
876 // If not, match add a new node to the beginning of the list and assign init it
878 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
879 next->next = cell_princ_map;
880 cell_princ_map = next;
881 next->principal = _strdup(pname);
882 next->cell = _strdup(cell);
883 next->active = active;
888 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
890 struct cell_principal_map ** next = &cell_princ_map;
892 if ( !pname && !cell )
896 if ( !strcmp((*next)->principal,pname) ||
897 !strcmp((*next)->cell,cell) ) {
899 free((*next)->principal);
902 (*next) = (*next)->next;
908 // Returns (if possible) a principal which has been known in
909 // the past to have been used to obtain tokens for the specified
911 // TODO: Attempt to return one which has not yet expired by checking
912 // the principal/ccache data
914 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
916 struct cell_principal_map * next_map = cell_princ_map;
917 const char * princ = NULL;
924 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
927 next_map = next_map->next;
930 if ( !principals || !count )
933 *principals = (char **) malloc(sizeof(char *) * count);
934 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
936 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
937 (*principals)[i++] = _strdup(next_map->principal);
944 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
947 struct cell_principal_map * next_map = cell_princ_map;
948 const char * princ = NULL;
954 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
957 next_map = next_map->next;
963 *cells = (char **) malloc(sizeof(char *) * count);
964 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
966 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
967 (*cells)[i++] = _strdup(next_map->cell);
973 /* Given a principal return an existing ccache or create one and return */
975 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
977 krb5_context ctx = NULL;
979 char * ccname = NULL;
980 krb5_error_code code;
982 if (!pkrb5_init_context)
988 code = pkrb5_init_context(&ctx);
989 if (code) goto cleanup;
993 code = pkrb5_unparse_name(ctx, principal, &pname);
994 if (code) goto cleanup;
996 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
997 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
998 ccname = (char *)malloc(strlen(pname) + 5);
999 sprintf(ccname,"API:%s",pname);
1001 code = pkrb5_cc_resolve(ctx, ccname, cc);
1003 code = pkrb5_cc_default(ctx, cc);
1004 if (code) goto cleanup;
1011 pkrb5_free_unparsed_name(ctx,pname);
1012 if (ctx && (ctx != alt_ctx))
1013 pkrb5_free_context(ctx);
1018 // Import Microsoft Credentials into a new MIT ccache
1020 KFW_import_windows_lsa(void)
1022 krb5_context ctx = NULL;
1023 krb5_ccache cc = NULL;
1024 krb5_principal princ = NULL;
1025 char * pname = NULL;
1026 krb5_data * princ_realm;
1027 krb5_error_code code;
1028 char cell[128]="", realm[128]="", *def_realm = 0;
1030 DWORD dwMsLsaImport;
1032 if (!pkrb5_init_context)
1035 code = pkrb5_init_context(&ctx);
1036 if (code) goto cleanup;
1038 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
1039 if (code) goto cleanup;
1041 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
1043 code = pkrb5_cc_get_principal(ctx, cc, &princ);
1044 if ( code ) goto cleanup;
1046 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
1047 switch ( dwMsLsaImport ) {
1048 case 0: /* do not import */
1050 case 1: /* always import */
1052 case 2: { /* matching realm */
1053 char ms_realm[128] = "", *r;
1056 for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) {
1057 *r = krb5_princ_realm(ctx, princ)->data[i];
1061 if (code = pkrb5_get_default_realm(ctx, &def_realm))
1064 if (strcmp(def_realm, ms_realm))
1072 code = pkrb5_unparse_name(ctx,princ,&pname);
1073 if ( code ) goto cleanup;
1075 princ_realm = krb5_princ_realm(ctx, princ);
1076 for ( i=0; i<princ_realm->length; i++ ) {
1077 realm[i] = princ_realm->data[i];
1078 cell[i] = tolower(princ_realm->data[i]);
1083 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
1084 if ( IsDebuggerPresent() ) {
1086 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1087 OutputDebugString(message);
1089 if ( code ) goto cleanup;
1091 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1095 pkrb5_free_unparsed_name(ctx,pname);
1097 pkrb5_free_principal(ctx,princ);
1099 pkrb5_free_default_realm(ctx, def_realm);
1101 pkrb5_cc_close(ctx,cc);
1103 pkrb5_free_context(ctx);
1105 #endif /* USE_MS2MIT */
1107 // If there are existing MIT credentials, copy them to a new
1108 // ccache named after the principal
1110 // Enumerate all existing MIT ccaches and construct entries
1111 // in the principal_ccache table
1113 // Enumerate all existing AFS Tokens and construct entries
1114 // in the cell_principal table
1116 KFW_import_ccache_data(void)
1118 krb5_context ctx = NULL;
1119 krb5_ccache cc = NULL;
1120 krb5_principal principal = NULL;
1122 krb5_error_code code;
1123 krb5_error_code cc_code;
1125 apiCB * cc_ctx = NULL;
1126 struct _infoNC ** pNCi = NULL;
1129 if ( !pcc_initialize )
1132 if ( IsDebuggerPresent() )
1133 OutputDebugString("KFW_import_ccache_data()\n");
1135 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1136 if (code) goto cleanup;
1138 code = pcc_get_NC_info(cc_ctx, &pNCi);
1139 if (code) goto cleanup;
1141 code = pkrb5_init_context(&ctx);
1142 if (code) goto cleanup;
1144 for ( i=0; pNCi[i]; i++ ) {
1145 if ( pNCi[i]->vers != CC_CRED_V5 )
1147 if ( IsDebuggerPresent() ) {
1148 OutputDebugString("Principal: ");
1149 OutputDebugString(pNCi[i]->principal);
1150 OutputDebugString(" in ccache ");
1151 OutputDebugString(pNCi[i]->name);
1152 OutputDebugString("\n");
1154 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1155 && strcmp(pNCi[i]->name,LSA_CCNAME)
1158 for ( j=0; pNCi[j]; j++ ) {
1159 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1165 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1166 if (code) goto loop_cleanup;
1169 krb5_ccache oldcc = 0;
1171 if ( IsDebuggerPresent() )
1172 OutputDebugString("copying ccache data to new ccache\n");
1174 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1175 if (code) goto loop_cleanup;
1176 code = pkrb5_cc_initialize(ctx, cc, principal);
1177 if (code) goto loop_cleanup;
1179 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1180 if (code) goto loop_cleanup;
1181 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1183 code = pkrb5_cc_close(ctx,cc);
1185 code = pkrb5_cc_close(ctx,oldcc);
1187 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1190 code = pkrb5_cc_close(ctx,oldcc);
1193 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1194 if (code) goto loop_cleanup;
1197 flags = 0; // turn off OPENCLOSE mode
1198 code = pkrb5_cc_set_flags(ctx, cc, flags);
1199 if ( code ) goto cleanup;
1201 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1203 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1205 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1206 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1207 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1208 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1209 if ( sname && cell && !strcmp("afs",sname->data) ) {
1210 struct ktc_principal aserver;
1211 struct ktc_principal aclient;
1212 struct ktc_token atoken;
1215 if ( IsDebuggerPresent() ) {
1216 OutputDebugString("Found AFS ticket: ");
1217 OutputDebugString(sname->data);
1219 OutputDebugString("/");
1220 OutputDebugString(cell->data);
1222 OutputDebugString("@");
1223 OutputDebugString(realm->data);
1224 OutputDebugString("\n");
1227 memset(&aserver, '\0', sizeof(aserver));
1228 strcpy(aserver.name, sname->data);
1229 strcpy(aserver.cell, cell->data);
1231 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1233 // Found a token in AFS Client Server which matches
1234 char pname[128], *p, *q;
1235 for ( p=pname, q=aclient.name; *q; p++, q++)
1237 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1241 if ( IsDebuggerPresent() ) {
1242 OutputDebugString("Found AFS token: ");
1243 OutputDebugString(pname);
1244 OutputDebugString("\n");
1247 if ( strcmp(pname,pNCi[i]->principal) )
1249 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1251 // Attempt to import it
1252 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1254 if ( IsDebuggerPresent() ) {
1255 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1258 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data,
1262 pLeash_get_default_lifetime(),
1263 #endif /* USE_LEASH */
1265 if ( IsDebuggerPresent() ) {
1267 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1268 OutputDebugString(message);
1271 } else if ( IsDebuggerPresent() ) {
1272 OutputDebugString("Found ticket: ");
1273 OutputDebugString(sname->data);
1274 if ( cell && cell->data ) {
1275 OutputDebugString("/");
1276 OutputDebugString(cell->data);
1278 OutputDebugString("@");
1279 OutputDebugString(realm->data);
1280 OutputDebugString("\n");
1282 pkrb5_free_cred_contents(ctx, &creds);
1285 if (cc_code == KRB5_CC_END) {
1286 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1287 if (cc_code) goto loop_cleanup;
1291 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1292 code = pkrb5_cc_set_flags(ctx, cc, flags);
1294 pkrb5_cc_close(ctx,cc);
1298 pkrb5_free_principal(ctx,principal);
1305 pkrb5_free_context(ctx);
1307 pcc_free_NC_info(cc_ctx, &pNCi);
1309 pcc_shutdown(&cc_ctx);
1314 KFW_AFS_get_cred( char * username,
1321 krb5_context ctx = NULL;
1322 krb5_ccache cc = NULL;
1323 char * realm = NULL, * userrealm = NULL;
1324 krb5_principal principal = NULL;
1325 char * pname = NULL;
1326 krb5_error_code code;
1327 char local_cell[CELL_MAXNAMELEN+1];
1328 char **cells = NULL;
1330 struct afsconf_cell cellconfig;
1333 if (!pkrb5_init_context)
1336 if ( IsDebuggerPresent() ) {
1337 OutputDebugString("KFW_AFS_get_cred for token ");
1338 OutputDebugString(username);
1339 OutputDebugString(" in cell ");
1340 OutputDebugString(cell);
1341 OutputDebugString("\n");
1344 code = pkrb5_init_context(&ctx);
1345 if ( code ) goto cleanup;
1347 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1348 if ( code ) goto cleanup;
1350 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1352 userrealm = strchr(username,'@');
1354 pname = strdup(username);
1355 if (!KFW_accept_dotted_usernames()) {
1356 userrealm = strchr(pname, '@');
1359 /* handle kerberos iv notation */
1360 while ( dot = strchr(pname,'.') ) {
1366 pname = malloc(strlen(username) + strlen(realm) + 2);
1368 strcpy(pname, username);
1370 if (!KFW_accept_dotted_usernames()) {
1371 /* handle kerberos iv notation */
1372 while ( dot = strchr(pname,'.') ) {
1377 strcat(pname,realm);
1379 if ( IsDebuggerPresent() ) {
1380 OutputDebugString("Realm: ");
1381 OutputDebugString(realm);
1382 OutputDebugString("\n");
1385 code = pkrb5_parse_name(ctx, pname, &principal);
1386 if ( code ) goto cleanup;
1388 code = KFW_get_ccache(ctx, principal, &cc);
1389 if ( code ) goto cleanup;
1391 if ( lifetime == 0 )
1395 lifetime = pLeash_get_default_lifetime();
1398 if ( password && password[0] ) {
1399 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1404 1, /* forwardable */
1405 0, /* not proxiable */
1407 1, /* noaddresses */
1408 0 /* no public ip */
1410 pLeash_get_default_forwardable(),
1411 pLeash_get_default_proxiable(),
1412 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1413 pLeash_get_default_noaddresses(),
1414 pLeash_get_default_publicip()
1415 #endif /* USE_LEASH */
1418 if ( IsDebuggerPresent() ) {
1420 sprintf(message,"KFW_kinit() returns: %d\n",code);
1421 OutputDebugString(message);
1423 if ( code ) goto cleanup;
1425 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1428 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime, smbname);
1429 if ( IsDebuggerPresent() ) {
1431 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1432 OutputDebugString(message);
1434 if ( code ) goto cleanup;
1436 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1438 // Attempt to obtain new tokens for other cells supported by the same
1440 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1441 if ( cell_count > 1 ) {
1442 while ( cell_count-- ) {
1443 if ( strcmp(cells[cell_count],cell) ) {
1444 if ( IsDebuggerPresent() ) {
1446 sprintf(message,"found another cell for the same principal: %s\n",cell);
1447 OutputDebugString(message);
1449 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1450 if ( code ) continue;
1452 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1453 if ( IsDebuggerPresent() ) {
1454 OutputDebugString("Realm: ");
1455 OutputDebugString(realm);
1456 OutputDebugString("\n");
1459 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime, smbname);
1460 if ( IsDebuggerPresent() ) {
1462 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1463 OutputDebugString(message);
1466 free(cells[cell_count]);
1469 } else if ( cell_count == 1 ) {
1478 pkrb5_cc_close(ctx, cc);
1480 if ( code && reasonP ) {
1481 *reasonP = (char *)perror_message(code);
1487 KFW_AFS_destroy_tickets_for_cell(char * cell)
1489 krb5_context ctx = NULL;
1490 krb5_error_code code;
1492 char ** principals = NULL;
1494 if (!pkrb5_init_context)
1497 if ( IsDebuggerPresent() ) {
1498 OutputDebugString("KFW_AFS_destroy_tickets_for_cell: ");
1499 OutputDebugString(cell);
1500 OutputDebugString("\n");
1503 code = pkrb5_init_context(&ctx);
1506 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1508 krb5_principal princ = 0;
1512 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1513 if ( cell_count > 1 ) {
1514 // TODO - What we really should do here is verify whether or not any of the
1515 // other cells which use this principal to obtain its credentials actually
1516 // have valid tokens or not. If they are currently using these credentials
1517 // we will skip them. For the time being we assume that if there is an active
1518 // map in the table that they are actively being used.
1522 code = pkrb5_parse_name(ctx, principals[count], &princ);
1523 if (code) goto loop_cleanup;
1525 code = KFW_get_ccache(ctx, princ, &cc);
1526 if (code) goto loop_cleanup;
1528 code = pkrb5_cc_destroy(ctx, cc);
1533 pkrb5_cc_close(ctx, cc);
1537 pkrb5_free_principal(ctx, princ);
1541 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1542 free(principals[count]);
1547 pkrb5_free_context(ctx);
1552 KFW_AFS_destroy_tickets_for_principal(char * user)
1554 krb5_context ctx = NULL;
1555 krb5_error_code code;
1557 char ** cells = NULL;
1558 krb5_principal princ = NULL;
1559 krb5_ccache cc = NULL;
1561 if (!pkrb5_init_context)
1564 if ( IsDebuggerPresent() ) {
1565 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1566 OutputDebugString(user);
1567 OutputDebugString("\n");
1570 code = pkrb5_init_context(&ctx);
1573 code = pkrb5_parse_name(ctx, user, &princ);
1574 if (code) goto loop_cleanup;
1576 code = KFW_get_ccache(ctx, princ, &cc);
1577 if (code) goto loop_cleanup;
1579 code = pkrb5_cc_destroy(ctx, cc);
1584 pkrb5_cc_close(ctx, cc);
1588 pkrb5_free_principal(ctx, princ);
1592 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1595 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1602 pkrb5_free_context(ctx);
1607 KFW_AFS_renew_expiring_tokens(void)
1609 krb5_error_code code = 0;
1610 krb5_context ctx = NULL;
1611 krb5_ccache cc = NULL;
1613 struct principal_ccache_data * pcc_next = princ_cc_data;
1616 const char * realm = NULL;
1617 char local_cell[CELL_MAXNAMELEN+1]="";
1618 struct afsconf_cell cellconfig;
1620 if (!pkrb5_init_context)
1623 if ( pcc_next == NULL ) // nothing to do
1626 if ( IsDebuggerPresent() ) {
1627 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1630 code = pkrb5_init_context(&ctx);
1631 if (code) goto cleanup;
1633 code = pkrb5_timeofday(ctx, &now);
1634 if (code) goto cleanup;
1636 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1637 if ( pcc_next->expired )
1640 if ( now >= (pcc_next->expiration_time) ) {
1641 if ( !pcc_next->from_lsa ) {
1642 pcc_next->expired = 1;
1647 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1648 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1651 code = KFW_renew(ctx,cc);
1653 if ( code && pcc_next->from_lsa)
1655 #endif /* USE_MS2MIT */
1658 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1659 if (code) goto loop_cleanup;
1661 // Attempt to obtain new tokens for other cells supported by the same
1663 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1664 if ( cell_count > 0 ) {
1665 while ( cell_count-- ) {
1666 if ( IsDebuggerPresent() ) {
1667 OutputDebugString("Cell: ");
1668 OutputDebugString(cells[cell_count]);
1669 OutputDebugString("\n");
1671 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1672 if ( code ) continue;
1673 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1674 if ( IsDebuggerPresent() ) {
1675 OutputDebugString("Realm: ");
1676 OutputDebugString(realm);
1677 OutputDebugString("\n");
1679 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1680 if ( IsDebuggerPresent() ) {
1682 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1683 OutputDebugString(message);
1685 free(cells[cell_count]);
1693 pkrb5_cc_close(ctx,cc);
1700 pkrb5_cc_close(ctx,cc);
1702 pkrb5_free_context(ctx);
1709 KFW_AFS_renew_token_for_cell(char * cell)
1711 krb5_error_code code = 0;
1712 krb5_context ctx = NULL;
1714 char ** principals = NULL;
1716 if (!pkrb5_init_context)
1719 if ( IsDebuggerPresent() ) {
1720 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1721 OutputDebugString(cell);
1722 OutputDebugString("\n");
1725 code = pkrb5_init_context(&ctx);
1726 if (code) goto cleanup;
1728 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1730 // We know we must have a credential somewhere since we are
1731 // trying to renew a token
1733 KFW_import_ccache_data();
1734 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1737 krb5_principal princ = 0;
1738 krb5_principal service = 0;
1740 krb5_creds mcreds, creds;
1741 #endif /* COMMENT */
1743 const char * realm = NULL;
1744 struct afsconf_cell cellconfig;
1745 char local_cell[CELL_MAXNAMELEN+1];
1748 code = pkrb5_parse_name(ctx, principals[count], &princ);
1749 if (code) goto loop_cleanup;
1751 code = KFW_get_ccache(ctx, princ, &cc);
1752 if (code) goto loop_cleanup;
1754 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1755 if ( code ) goto loop_cleanup;
1757 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1758 if ( IsDebuggerPresent() ) {
1759 OutputDebugString("Realm: ");
1760 OutputDebugString(realm);
1761 OutputDebugString("\n");
1765 /* krb5_cc_remove_cred() is not implemented
1768 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1769 realm, "afs", cell, NULL);
1771 memset(&mcreds, 0, sizeof(krb5_creds));
1772 mcreds.client = princ;
1773 mcreds.server = service;
1775 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1777 if ( IsDebuggerPresent() ) {
1778 char * cname, *sname;
1779 pkrb5_unparse_name(ctx, creds.client, &cname);
1780 pkrb5_unparse_name(ctx, creds.server, &sname);
1781 OutputDebugString("Removing credential for client \"");
1782 OutputDebugString(cname);
1783 OutputDebugString("\" and service \"");
1784 OutputDebugString(sname);
1785 OutputDebugString("\"\n");
1786 pkrb5_free_unparsed_name(ctx,cname);
1787 pkrb5_free_unparsed_name(ctx,sname);
1790 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1791 pkrb5_free_principal(ctx, creds.client);
1792 pkrb5_free_principal(ctx, creds.server);
1795 #endif /* COMMENT */
1797 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1798 if ( IsDebuggerPresent() ) {
1800 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1801 OutputDebugString(message);
1806 pkrb5_cc_close(ctx, cc);
1810 pkrb5_free_principal(ctx, princ);
1814 pkrb5_free_principal(ctx, service);
1818 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1819 free(principals[count]);
1823 code = -1; // we did not renew the tokens
1827 pkrb5_free_context(ctx);
1828 return (code ? FALSE : TRUE);
1833 KFW_AFS_renew_tokens_for_all_cells(void)
1835 struct cell_principal_map * next = cell_princ_map;
1837 if ( IsDebuggerPresent() )
1838 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1843 for ( ; next ; next = next->next ) {
1845 KFW_AFS_renew_token_for_cell(next->cell);
1851 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1853 krb5_error_code code = 0;
1854 krb5_context ctx = NULL;
1855 krb5_ccache cc = NULL;
1856 krb5_principal me = NULL;
1857 krb5_principal server = NULL;
1858 krb5_creds my_creds;
1859 krb5_data *realm = NULL;
1861 if (!pkrb5_init_context)
1864 memset(&my_creds, 0, sizeof(krb5_creds));
1869 code = pkrb5_init_context(&ctx);
1870 if (code) goto cleanup;
1876 code = pkrb5_cc_default(ctx, &cc);
1877 if (code) goto cleanup;
1880 code = pkrb5_cc_get_principal(ctx, cc, &me);
1881 if (code) goto cleanup;
1883 realm = krb5_princ_realm(ctx, me);
1885 code = pkrb5_build_principal_ext(ctx, &server,
1886 realm->length,realm->data,
1887 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1888 realm->length,realm->data,
1893 if ( IsDebuggerPresent() ) {
1894 char * cname, *sname;
1895 pkrb5_unparse_name(ctx, me, &cname);
1896 pkrb5_unparse_name(ctx, server, &sname);
1897 OutputDebugString("Renewing credential for client \"");
1898 OutputDebugString(cname);
1899 OutputDebugString("\" and service \"");
1900 OutputDebugString(sname);
1901 OutputDebugString("\"\n");
1902 pkrb5_free_unparsed_name(ctx,cname);
1903 pkrb5_free_unparsed_name(ctx,sname);
1906 my_creds.client = me;
1907 my_creds.server = server;
1909 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1911 if ( IsDebuggerPresent() ) {
1913 sprintf(message,"krb5_get_renewed_creds() failed: %d\n",code);
1914 OutputDebugString(message);
1919 code = pkrb5_cc_initialize(ctx, cc, me);
1921 if ( IsDebuggerPresent() ) {
1923 sprintf(message,"krb5_cc_initialize() failed: %d\n",code);
1924 OutputDebugString(message);
1929 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1931 if ( IsDebuggerPresent() ) {
1933 sprintf(message,"krb5_cc_store_cred() failed: %d\n",code);
1934 OutputDebugString(message);
1940 if (my_creds.client == me)
1941 my_creds.client = 0;
1942 if (my_creds.server == server)
1943 my_creds.server = 0;
1944 pkrb5_free_cred_contents(ctx, &my_creds);
1946 pkrb5_free_principal(ctx, me);
1948 pkrb5_free_principal(ctx, server);
1949 if (cc && (cc != alt_cc))
1950 pkrb5_cc_close(ctx, cc);
1951 if (ctx && (ctx != alt_ctx))
1952 pkrb5_free_context(ctx);
1957 KFW_kinit( krb5_context alt_ctx,
1960 char *principal_name,
1962 krb5_deltat lifetime,
1965 krb5_deltat renew_life,
1970 krb5_error_code code = 0;
1971 krb5_context ctx = NULL;
1972 krb5_ccache cc = NULL;
1973 krb5_principal me = NULL;
1975 krb5_creds my_creds;
1976 krb5_get_init_creds_opt options;
1977 krb5_address ** addrs = NULL;
1978 int i = 0, addr_count = 0;
1980 if (!pkrb5_init_context)
1983 pkrb5_get_init_creds_opt_init(&options);
1984 memset(&my_creds, 0, sizeof(my_creds));
1992 code = pkrb5_init_context(&ctx);
1993 if (code) goto cleanup;
1999 code = pkrb5_cc_default(ctx, &cc);
2000 if (code) goto cleanup;
2003 code = pkrb5_parse_name(ctx, principal_name, &me);
2007 code = pkrb5_unparse_name(ctx, me, &name);
2015 lifetime = pLeash_get_default_lifetime();
2016 #endif /* USE_LEASH */
2023 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
2024 pkrb5_get_init_creds_opt_set_forwardable(&options,
2025 forwardable ? 1 : 0);
2026 pkrb5_get_init_creds_opt_set_proxiable(&options,
2028 pkrb5_get_init_creds_opt_set_renew_life(&options,
2031 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
2035 // we are going to add the public IP address specified by the user
2036 // to the list provided by the operating system
2037 krb5_address ** local_addrs=NULL;
2040 pkrb5_os_localaddr(ctx, &local_addrs);
2041 while ( local_addrs[i++] );
2044 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
2046 pkrb5_free_addresses(ctx, local_addrs);
2049 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
2051 while ( local_addrs[i] ) {
2052 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2053 if (addrs[i] == NULL) {
2054 pkrb5_free_addresses(ctx, local_addrs);
2058 addrs[i]->magic = local_addrs[i]->magic;
2059 addrs[i]->addrtype = local_addrs[i]->addrtype;
2060 addrs[i]->length = local_addrs[i]->length;
2061 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2062 if (!addrs[i]->contents) {
2063 pkrb5_free_addresses(ctx, local_addrs);
2067 memcpy(addrs[i]->contents,local_addrs[i]->contents,
2068 local_addrs[i]->length); /* safe */
2071 pkrb5_free_addresses(ctx, local_addrs);
2073 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
2074 if (addrs[i] == NULL)
2077 addrs[i]->magic = KV5M_ADDRESS;
2078 addrs[i]->addrtype = AF_INET;
2079 addrs[i]->length = 4;
2080 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
2081 if (!addrs[i]->contents)
2084 netIPAddr = htonl(publicIP);
2085 memcpy(addrs[i]->contents,&netIPAddr,4);
2087 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
2092 code = pkrb5_get_init_creds_password(ctx,
2095 password, // password
2096 KRB5_prompter, // prompter
2097 hParent, // prompter data
2104 code = pkrb5_cc_initialize(ctx, cc, me);
2108 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
2114 for ( i=0;i<addr_count;i++ ) {
2116 if ( addrs[i]->contents )
2117 free(addrs[i]->contents);
2122 if (my_creds.client == me)
2123 my_creds.client = 0;
2124 pkrb5_free_cred_contents(ctx, &my_creds);
2126 pkrb5_free_unparsed_name(ctx, name);
2128 pkrb5_free_principal(ctx, me);
2129 if (cc && (cc != alt_cc))
2130 pkrb5_cc_close(ctx, cc);
2131 if (ctx && (ctx != alt_ctx))
2132 pkrb5_free_context(ctx);
2138 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2140 krb5_context ctx = NULL;
2141 krb5_ccache cc = NULL;
2142 krb5_error_code code;
2144 if (!pkrb5_init_context)
2153 code = pkrb5_init_context(&ctx);
2154 if (code) goto cleanup;
2160 code = pkrb5_cc_default(ctx, &cc);
2161 if (code) goto cleanup;
2164 code = pkrb5_cc_destroy(ctx, cc);
2165 if ( !code ) cc = 0;
2168 if (cc && (cc != alt_cc))
2169 pkrb5_cc_close(ctx, cc);
2170 if (ctx && (ctx != alt_ctx))
2171 pkrb5_free_context(ctx);
2179 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2181 NTSTATUS Status = 0;
2183 TOKEN_STATISTICS Stats;
2189 *ppSessionData = NULL;
2191 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2195 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2196 CloseHandle( TokenHandle );
2200 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2201 if ( FAILED(Status) || !ppSessionData )
2208 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2209 // cache. It validates whether or not it is reasonable to assume that if we
2210 // attempted to retrieve valid tickets we could do so. Microsoft does not
2211 // automatically renew expired tickets. Therefore, the cache could contain
2212 // expired or invalid tickets. Microsoft also caches the user's password
2213 // and will use it to retrieve new TGTs if the cache is empty and tickets
2217 MSLSA_IsKerberosLogon(VOID)
2219 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2220 BOOL Success = FALSE;
2222 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2223 if ( pSessionData->AuthenticationPackage.Buffer ) {
2229 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2230 usLength = (pSessionData->AuthenticationPackage).Length;
2233 lstrcpynW (buffer, usBuffer, usLength);
2234 lstrcatW (buffer,L"");
2235 if ( !lstrcmpW(L"Kerberos",buffer) )
2239 pLsaFreeReturnBuffer(pSessionData);
2243 #endif /* USE_MS2MIT */
2245 static BOOL CALLBACK
2246 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2250 switch ( message ) {
2252 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2254 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2257 for ( i=0; i < mid_cnt ; i++ ) {
2258 if (mid_tb[i].echo == 0)
2259 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2260 else if (mid_tb[i].echo == 2)
2261 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2266 switch ( LOWORD(wParam) ) {
2268 for ( i=0; i < mid_cnt ; i++ ) {
2269 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2270 *mid_tb[i].buf = '\0';
2274 EndDialog(hDialog, LOWORD(wParam));
2282 lpwAlign( LPWORD lpIn )
2286 ul = (ULONG_PTR) lpIn;
2290 return (LPWORD) ul;;
2294 * dialog widths are measured in 1/4 character widths
2295 * dialog height are measured in 1/8 character heights
2299 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2300 char * ptext[], int numlines, int width,
2301 int tb_cnt, struct textField * tb)
2305 LPDLGITEMTEMPLATE lpdit;
2311 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2318 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2320 // Define a dialog box.
2322 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2323 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2324 | DS_SETFOREGROUND | DS_3DLOOK
2325 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2326 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2329 lpdt->cx = 20 + width * 4;
2330 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2332 lpw = (LPWORD) (lpdt + 1);
2333 *lpw++ = 0; // no menu
2334 *lpw++ = 0; // predefined dialog box class (by default)
2336 lpwsz = (LPWSTR) lpw;
2337 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2339 *lpw++ = 8; // font size (points)
2340 lpwsz = (LPWSTR) lpw;
2341 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2345 //-----------------------
2346 // Define an OK button.
2347 //-----------------------
2348 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2349 lpdit = (LPDLGITEMTEMPLATE) lpw;
2350 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2351 lpdit->dwExtendedStyle = 0;
2352 lpdit->x = (lpdt->cx - 14)/4 - 20;
2353 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2356 lpdit->id = IDOK; // OK button identifier
2358 lpw = (LPWORD) (lpdit + 1);
2360 *lpw++ = 0x0080; // button class
2362 lpwsz = (LPWSTR) lpw;
2363 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2365 *lpw++ = 0; // no creation data
2367 //-----------------------
2368 // Define an Cancel button.
2369 //-----------------------
2370 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2371 lpdit = (LPDLGITEMTEMPLATE) lpw;
2372 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2373 lpdit->dwExtendedStyle = 0;
2374 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2375 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2378 lpdit->id = IDCANCEL; // CANCEL button identifier
2380 lpw = (LPWORD) (lpdit + 1);
2382 *lpw++ = 0x0080; // button class
2384 lpwsz = (LPWSTR) lpw;
2385 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2387 *lpw++ = 0; // no creation data
2389 /* Add controls for preface data */
2390 for ( i=0; i<numlines; i++) {
2391 /*-----------------------
2392 * Define a static text control.
2393 *-----------------------*/
2394 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2395 lpdit = (LPDLGITEMTEMPLATE) lpw;
2396 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2397 lpdit->dwExtendedStyle = 0;
2399 lpdit->y = 10 + i * 14;
2400 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2402 lpdit->id = ID_TEXT + i; // text identifier
2404 lpw = (LPWORD) (lpdit + 1);
2406 *lpw++ = 0x0082; // static class
2408 lpwsz = (LPWSTR) lpw;
2409 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2410 -1, lpwsz, 2*width);
2412 *lpw++ = 0; // no creation data
2415 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2416 int len = (int)strlen(tb[i].label);
2421 for ( i=0; i<tb_cnt; i++) {
2423 /*-----------------------
2424 * Define a static text control.
2425 *-----------------------*/
2426 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2427 lpdit = (LPDLGITEMTEMPLATE) lpw;
2428 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2429 lpdit->dwExtendedStyle = 0;
2431 lpdit->y = 10 + (numlines + i + 1) * 14;
2432 lpdit->cx = pwid * 4;
2434 lpdit->id = ID_TEXT + numlines + i; // text identifier
2436 lpw = (LPWORD) (lpdit + 1);
2438 *lpw++ = 0x0082; // static class
2440 lpwsz = (LPWSTR) lpw;
2441 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2444 *lpw++ = 0; // no creation data
2446 /*-----------------------
2447 * Define an edit control.
2448 *-----------------------*/
2449 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2450 lpdit = (LPDLGITEMTEMPLATE) lpw;
2451 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2452 lpdit->dwExtendedStyle = 0;
2453 lpdit->x = 10 + (pwid + 1) * 4;
2454 lpdit->y = 10 + (numlines + i + 1) * 14;
2455 lpdit->cx = (width - (pwid + 1)) * 4;
2457 lpdit->id = ID_MID_TEXT + i; // identifier
2459 lpw = (LPWORD) (lpdit + 1);
2461 *lpw++ = 0x0081; // edit class
2463 lpwsz = (LPWSTR) lpw;
2464 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2467 *lpw++ = 0; // no creation data
2471 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2472 hwndOwner, (DLGPROC) MultiInputDialogProc);
2476 case 0: /* Timeout */
2484 sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
2485 MessageBox(hwndOwner,
2488 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2495 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2497 HINSTANCE hInst = 0;
2501 char * plines[16], *p = preface ? preface : "";
2504 for ( i=0; i<16; i++ )
2507 while (*p && numlines < 16) {
2508 plines[numlines++] = p;
2509 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2510 if ( *p == '\r' && *(p+1) == '\n' ) {
2513 } else if ( *p == '\n' ) {
2516 if ( strlen(plines[numlines-1]) > maxwidth )
2517 maxwidth = (int)strlen(plines[numlines-1]);
2520 for ( i=0;i<n;i++ ) {
2521 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2522 if ( maxwidth < len )
2526 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2529 static krb5_error_code KRB5_CALLCONV
2530 KRB5_prompter( krb5_context context,
2535 krb5_prompt prompts[])
2537 krb5_error_code errcode = 0;
2539 struct textField * tb = NULL;
2540 int len = 0, blen=0, nlen=0;
2541 HWND hParent = (HWND)data;
2544 nlen = (int)strlen(name)+2;
2547 blen = (int)strlen(banner)+2;
2549 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2552 memset(tb,0,sizeof(struct textField) * num_prompts);
2553 for ( i=0; i < num_prompts; i++ ) {
2554 tb[i].buf = prompts[i].reply->data;
2555 tb[i].len = prompts[i].reply->length;
2556 tb[i].label = prompts[i].prompt;
2558 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2561 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2563 for ( i=0; i < num_prompts; i++ )
2564 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2572 for (i = 0; i < num_prompts; i++) {
2573 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2580 KFW_AFS_wait_for_service_start(void)
2585 CurrentState = SERVICE_START_PENDING;
2586 memset(HostName, '\0', sizeof(HostName));
2587 gethostname(HostName, sizeof(HostName));
2589 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2591 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2593 if ( IsDebuggerPresent() ) {
2594 switch ( CurrentState ) {
2595 case SERVICE_STOPPED:
2596 OutputDebugString("SERVICE_STOPPED\n");
2598 case SERVICE_START_PENDING:
2599 OutputDebugString("SERVICE_START_PENDING\n");
2601 case SERVICE_STOP_PENDING:
2602 OutputDebugString("SERVICE_STOP_PENDING\n");
2604 case SERVICE_RUNNING:
2605 OutputDebugString("SERVICE_RUNNING\n");
2607 case SERVICE_CONTINUE_PENDING:
2608 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2610 case SERVICE_PAUSE_PENDING:
2611 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2613 case SERVICE_PAUSED:
2614 OutputDebugString("SERVICE_PAUSED\n");
2617 OutputDebugString("UNKNOWN Service State\n");
2620 if (CurrentState == SERVICE_STOPPED)
2622 if (CurrentState == SERVICE_RUNNING)
2638 memset(HostName, '\0', sizeof(HostName));
2639 gethostname(HostName, sizeof(HostName));
2640 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2642 if (CurrentState != SERVICE_RUNNING)
2645 rc = ktc_ForgetAllTokens();
2651 #define ALLOW_REGISTER 1
2653 ViceIDToUsername(char *username,
2654 char *realm_of_user,
2655 char *realm_of_cell,
2657 struct ktc_principal *aclient,
2658 struct ktc_principal *aserver,
2659 struct ktc_token *atoken)
2661 static char lastcell[CELL_MAXNAMELEN+1] = { 0 };
2662 static char confdir[512] = { 0 };
2663 #ifdef AFS_ID_TO_NAME
2664 char username_copy[BUFSIZ];
2665 #endif /* AFS_ID_TO_NAME */
2666 long viceId = ANONYMOUSID; /* AFS uid of user */
2668 #ifdef ALLOW_REGISTER
2670 #endif /* ALLOW_REGISTER */
2672 if (confdir[0] == '\0')
2673 cm_GetConfigDir(confdir, sizeof(confdir));
2675 strcpy(lastcell, aserver->cell);
2677 if (!pr_Initialize (0, confdir, aserver->cell)) {
2678 char sname[PR_MAXNAMELEN];
2679 strncpy(sname, username, PR_MAXNAMELEN);
2680 sname[PR_MAXNAMELEN-1] = '\0';
2681 status = pr_SNameToId (sname, &viceId);
2686 * This is a crock, but it is Transarc's crock, so
2687 * we have to play along in order to get the
2688 * functionality. The way the afs id is stored is
2689 * as a string in the username field of the token.
2690 * Contrary to what you may think by looking at
2691 * the code for tokens, this hack (AFS ID %d) will
2692 * not work if you change %d to something else.
2696 * This code is taken from cklog -- it lets people
2697 * automatically register with the ptserver in foreign cells
2700 #ifdef ALLOW_REGISTER
2702 if (viceId != ANONYMOUSID) {
2703 #else /* ALLOW_REGISTER */
2704 if ((status == 0) && (viceId != ANONYMOUSID))
2705 #endif /* ALLOW_REGISTER */
2707 #ifdef AFS_ID_TO_NAME
2708 strncpy(username_copy, username, BUFSIZ);
2709 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2710 #endif /* AFS_ID_TO_NAME */
2712 #ifdef ALLOW_REGISTER
2713 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2715 strncpy(aclient->name, username, MAXKTCNAMELEN - 1);
2716 strcpy(aclient->instance, "");
2717 strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
2718 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2720 if (status = pr_Initialize(1L, confdir, aserver->cell))
2722 status = pr_CreateUser(username, &id);
2726 #ifdef AFS_ID_TO_NAME
2727 strncpy(username_copy, username, BUFSIZ);
2728 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2729 #endif /* AFS_ID_TO_NAME */
2732 #endif /* ALLOW_REGISTER */
2738 copy_realm_of_ticket(krb5_context context, char * dest, size_t destlen, krb5_creds *v5cred) {
2739 krb5_error_code code;
2740 krb5_ticket *ticket;
2743 code = pkrb5_decode_ticket(&v5cred->ticket, &ticket);
2745 len = krb5_princ_realm(context, ticket->server)->length;
2746 if (len > destlen - 1)
2749 strncpy(dest, krb5_princ_realm(context, ticket->server)->data, len);
2752 pkrb5_free_ticket(context, ticket);
2758 krb5_context alt_ctx,
2763 int lifetime, /* unused parameter */
2771 #endif /* USE_KRB4 */
2772 struct ktc_principal aserver;
2773 struct ktc_principal aclient;
2774 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2775 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2776 char local_cell[CELL_MAXNAMELEN+1];
2777 char Dmycell[CELL_MAXNAMELEN+1];
2778 struct ktc_token atoken;
2779 struct ktc_token btoken;
2780 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2781 char RealmName[128];
2783 char ServiceName[128];
2787 krb5_context ctx = NULL;
2788 krb5_ccache cc = NULL;
2790 krb5_creds * k5creds = NULL;
2791 krb5_error_code code;
2792 krb5_principal client_principal = NULL;
2793 krb5_data * k5data = NULL;
2797 memset(HostName, '\0', sizeof(HostName));
2798 gethostname(HostName, sizeof(HostName));
2799 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2800 if ( IsDebuggerPresent() )
2801 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2804 if (CurrentState != SERVICE_RUNNING) {
2805 if ( IsDebuggerPresent() )
2806 OutputDebugString("AFSD Service NOT RUNNING\n");
2810 if (!pkrb5_init_context)
2813 memset(RealmName, '\0', sizeof(RealmName));
2814 memset(CellName, '\0', sizeof(CellName));
2815 memset(ServiceName, '\0', sizeof(ServiceName));
2816 memset(realm_of_user, '\0', sizeof(realm_of_user));
2817 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2818 if (cell && cell[0])
2819 strcpy(Dmycell, cell);
2821 memset(Dmycell, '\0', sizeof(Dmycell));
2823 // NULL or empty cell returns information on local cell
2824 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2826 // KFW_AFS_error(rc, "get_cellconfig()");
2833 code = pkrb5_init_context(&ctx);
2834 if (code) goto cleanup;
2840 code = pkrb5_cc_default(ctx, &cc);
2841 if (code) goto skip_krb5_init;
2844 memset((char *)&increds, 0, sizeof(increds));
2846 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2848 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2850 OutputDebugString("Principal Not Found for ccache\n");
2852 goto skip_krb5_init;
2855 if (!KFW_accept_dotted_usernames()) {
2856 /* look for client principals which cannot be distinguished
2857 * from Kerberos 4 multi-component principal names
2859 k5data = krb5_princ_component(ctx,client_principal,0);
2860 for ( i=0; i<k5data->length; i++ ) {
2861 if ( k5data->data[i] == '.' )
2864 if (i != k5data->length)
2866 OutputDebugString("Illegal Principal name contains dot in first component\n");
2867 rc = KRB5KRB_ERR_GENERIC;
2872 i = krb5_princ_realm(ctx, client_principal)->length;
2875 strncpy(realm_of_user,krb5_princ_realm(ctx, client_principal)->data,i);
2876 realm_of_user[i] = 0;
2881 if ( !try_krb5 || !realm_of_user[0] ) {
2882 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2891 strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig));
2893 if (strlen(service) == 0)
2894 strcpy(ServiceName, "afs");
2896 strcpy(ServiceName, service);
2898 if (strlen(cell) == 0)
2899 strcpy(CellName, local_cell);
2901 strcpy(CellName, cell);
2903 /* This is for Kerberos v4 only */
2904 if (strlen(realm) == 0)
2905 strcpy(RealmName, realm_of_cell);
2907 strcpy(RealmName, realm);
2909 memset(&creds, '\0', sizeof(creds));
2913 code = KRB5KRB_ERR_GENERIC;
2916 increds.client = client_principal;
2917 increds.times.endtime = 0;
2918 /* Ask for DES since that is what V4 understands */
2919 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
2921 /* If there was a specific realm we are supposed to try
2924 if (strlen(realm) != 0) {
2925 /* service/cell@REALM */
2927 code = pkrb5_build_principal(ctx, &increds.server,
2933 if ( IsDebuggerPresent() ) {
2934 char * cname, *sname;
2935 pkrb5_unparse_name(ctx, increds.client, &cname);
2936 pkrb5_unparse_name(ctx, increds.server, &sname);
2937 OutputDebugString("Getting tickets for \"");
2938 OutputDebugString(cname);
2939 OutputDebugString("\" and service \"");
2940 OutputDebugString(sname);
2941 OutputDebugString("\"\n");
2942 pkrb5_free_unparsed_name(ctx,cname);
2943 pkrb5_free_unparsed_name(ctx,sname);
2947 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2949 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2950 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
2951 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2952 code == KRB5KRB_AP_ERR_MSG_TYPE) {
2953 /* Or service@REALM */
2954 pkrb5_free_principal(ctx,increds.server);
2956 code = pkrb5_build_principal(ctx, &increds.server,
2962 if ( IsDebuggerPresent() ) {
2963 char * cname, *sname;
2964 pkrb5_unparse_name(ctx, increds.client, &cname);
2965 pkrb5_unparse_name(ctx, increds.server, &sname);
2966 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2967 OutputDebugString("Trying again: getting tickets for \"");
2968 OutputDebugString(cname);
2969 OutputDebugString("\" and service \"");
2970 OutputDebugString(sname);
2971 OutputDebugString("\"\n");
2972 pkrb5_free_unparsed_name(ctx,cname);
2973 pkrb5_free_unparsed_name(ctx,sname);
2977 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2981 /* we have a local realm for the cell */
2982 strcpy(realm_of_cell, realm);
2985 /* Otherwise, first try service/cell@CLIENT_REALM */
2986 if (code = pkrb5_build_principal(ctx, &increds.server,
2987 (int)strlen(realm_of_user),
2996 if ( IsDebuggerPresent() ) {
2997 char * cname, *sname;
2998 pkrb5_unparse_name(ctx, increds.client, &cname);
2999 pkrb5_unparse_name(ctx, increds.server, &sname);
3000 OutputDebugString("Getting tickets for \"");
3001 OutputDebugString(cname);
3002 OutputDebugString("\" and service \"");
3003 OutputDebugString(sname);
3004 OutputDebugString("\"\n");
3005 pkrb5_free_unparsed_name(ctx,cname);
3006 pkrb5_free_unparsed_name(ctx,sname);
3009 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3011 /* The client's realm is a local realm for the cell.
3012 * Save it so that later the pts registration will not
3015 strcpy(realm_of_cell, realm_of_user);
3018 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3019 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3020 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3021 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
3022 strcmp(realm_of_user, realm_of_cell)) {
3023 /* Then service/cell@CELL_REALM */
3024 pkrb5_free_principal(ctx,increds.server);
3026 code = pkrb5_build_principal(ctx, &increds.server,
3027 (int)strlen(realm_of_cell),
3032 if ( IsDebuggerPresent() ) {
3033 char * cname, *sname;
3034 pkrb5_unparse_name(ctx, increds.client, &cname);
3035 pkrb5_unparse_name(ctx, increds.server, &sname);
3036 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3037 OutputDebugString("Trying again: getting tickets for \"");
3038 OutputDebugString(cname);
3039 OutputDebugString("\" and service \"");
3040 OutputDebugString(sname);
3041 OutputDebugString("\"\n");
3042 pkrb5_free_unparsed_name(ctx,cname);
3043 pkrb5_free_unparsed_name(ctx,sname);
3047 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3049 if (!code && !strlen(realm_of_cell))
3050 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3053 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
3054 code == KRB5_ERR_HOST_REALM_UNKNOWN ||
3055 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
3056 code == KRB5KRB_AP_ERR_MSG_TYPE) {
3057 /* Finally service@CELL_REALM */
3058 pkrb5_free_principal(ctx,increds.server);
3060 code = pkrb5_build_principal(ctx, &increds.server,
3061 (int)strlen(realm_of_cell),
3066 if ( IsDebuggerPresent() ) {
3067 char * cname, *sname;
3068 pkrb5_unparse_name(ctx, increds.client, &cname);
3069 pkrb5_unparse_name(ctx, increds.server, &sname);
3070 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
3071 OutputDebugString("Trying again: getting tickets for \"");
3072 OutputDebugString(cname);
3073 OutputDebugString("\" and service \"");
3074 OutputDebugString(sname);
3075 OutputDebugString("\"\n");
3076 pkrb5_free_unparsed_name(ctx,cname);
3077 pkrb5_free_unparsed_name(ctx,sname);
3081 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
3082 if (!code && !strlen(realm_of_cell))
3083 copy_realm_of_ticket(ctx, realm_of_cell, sizeof(realm_of_cell), k5creds);
3088 if ( IsDebuggerPresent() ) {
3090 sprintf(message,"krb5_get_credentials returns: %d\n",code);
3091 OutputDebugString(message);
3097 /* This code inserts the entire K5 ticket into the token
3098 * No need to perform a krb524 translation which is
3099 * commented out in the code below
3101 if (KFW_use_krb524() ||
3102 k5creds->ticket.length > MAXKTCTICKETLEN)
3105 memset(&aserver, '\0', sizeof(aserver));
3106 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
3107 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
3109 memset(&atoken, '\0', sizeof(atoken));
3110 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
3111 atoken.startTime = k5creds->times.starttime;
3112 atoken.endTime = k5creds->times.endtime;
3113 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
3114 atoken.ticketLen = k5creds->ticket.length;
3115 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
3118 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3119 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3120 if ( rc == KTC_NOCM && retry < 20 ) {
3123 goto retry_gettoken5;
3128 if (atoken.kvno == btoken.kvno &&
3129 atoken.ticketLen == btoken.ticketLen &&
3130 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3131 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3133 /* Success - Nothing to do */
3137 // * Reset the "aclient" structure before we call ktc_SetToken.
3138 // * This structure was first set by the ktc_GetToken call when
3139 // * we were comparing whether identical tokens already existed.
3141 len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
3142 strncpy(aclient.name, k5creds->client->data[0].data, len);
3143 aclient.name[len] = '\0';
3145 if ( k5creds->client->length > 1 ) {
3147 strcat(aclient.name, ".");
3148 p = aclient.name + strlen(aclient.name);
3149 len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
3150 strncpy(p, k5creds->client->data[1].data, len);
3153 aclient.instance[0] = '\0';
3155 strcpy(aclient.cell, realm_of_cell);
3157 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
3158 /* For Khimaira, always append the realm name */
3159 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
3161 strcat(aclient.name, "@");
3162 p = aclient.name + strlen(aclient.name);
3163 len = min(k5creds->client->realm.length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
3164 strncpy(p, k5creds->client->realm.data, len);
3168 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3169 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3170 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3171 &aclient, &aserver, &atoken);
3174 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
3175 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
3177 aclient.smbname[0] = '\0';
3180 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
3182 goto cleanup; /* We have successfully inserted the token */
3188 /* Otherwise, the ticket could have been too large so try to
3189 * convert using the krb524d running with the KDC
3191 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
3192 pkrb5_free_creds(ctx, k5creds);
3194 if ( IsDebuggerPresent() ) {
3196 sprintf(message,"krb524_convert_creds_kdc returns: %d\n",code);
3197 OutputDebugString(message);
3202 #endif /* USE_KRB524 */
3206 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
3207 if (code == NO_TKT_FIL) {
3208 // if the problem is that we have no krb4 tickets
3209 // do not attempt to continue
3212 if (code != KSUCCESS)
3213 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3215 if (code != KSUCCESS)
3217 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3219 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3224 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3226 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3241 memset(&aserver, '\0', sizeof(aserver));
3242 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
3243 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
3245 memset(&atoken, '\0', sizeof(atoken));
3246 atoken.kvno = creds.kvno;
3247 atoken.startTime = creds.issue_date;
3248 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3249 memcpy(&atoken.sessionKey, creds.session, 8);
3250 atoken.ticketLen = creds.ticket_st.length;
3251 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3254 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3255 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3256 if ( rc == KTC_NOCM && retry < 20 ) {
3259 goto retry_gettoken;
3261 KFW_AFS_error(rc, "ktc_GetToken()");
3266 if (atoken.kvno == btoken.kvno &&
3267 atoken.ticketLen == btoken.ticketLen &&
3268 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3269 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3274 // * Reset the "aclient" structure before we call ktc_SetToken.
3275 // * This structure was first set by the ktc_GetToken call when
3276 // * we were comparing whether identical tokens already existed.
3278 strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
3281 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3282 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3284 strcpy(aclient.instance, "");
3286 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3287 strncat(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3288 aclient.name[MAXKTCREALMLEN-1] = '\0';
3290 strcpy(aclient.cell, CellName);
3292 GetEnvironmentVariable(DO_NOT_REGISTER_VARNAME, NULL, 0);
3293 if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
3294 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3295 &aclient, &aserver, &atoken);
3298 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
3299 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
3301 aclient.smbname[0] = '\0';
3304 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3306 KFW_AFS_error(rc, "ktc_SetToken()");
3312 if (client_principal)
3313 pkrb5_free_principal(ctx,client_principal);
3314 /* increds.client == client_principal */
3316 pkrb5_free_principal(ctx,increds.server);
3317 if (cc && (cc != alt_cc))
3318 pkrb5_cc_close(ctx, cc);
3319 if (ctx && (ctx != alt_ctx))
3320 pkrb5_free_context(ctx);
3322 return(rc? rc : code);
3325 /**************************************/
3326 /* afs_realm_of_cell(): */
3327 /**************************************/
3329 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3331 static char krbrlm[REALM_SZ+1]="";
3332 char ** realmlist=NULL;
3338 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3339 if ( !r && realmlist && realmlist[0] ) {
3340 strcpy(krbrlm, realmlist[0]);
3341 pkrb5_free_host_realm(ctx, realmlist);
3347 char *t = cellconfig->name;
3352 if (islower(c)) c=toupper(c);
3360 /**************************************/
3361 /* KFW_AFS_get_cellconfig(): */
3362 /**************************************/
3364 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3367 char newcell[CELL_MAXNAMELEN+1];
3369 local_cell[0] = (char)0;
3370 memset(cellconfig, 0, sizeof(*cellconfig));
3372 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3373 if (rc = cm_GetRootCellName(local_cell))
3378 if (strlen(cell) == 0)
3379 strcpy(cell, local_cell);
3381 /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
3382 strcpy(cellconfig->name, cell);
3384 rc = cm_SearchCellFile(cell, newcell, get_cellconfig_callback, (void*)cellconfig);
3385 #ifdef AFS_AFSDB_ENV
3388 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3394 /**************************************/
3395 /* get_cellconfig_callback(): */
3396 /**************************************/
3398 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep)
3400 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3402 cc->hostAddr[cc->numServers] = *addrp;
3403 strcpy(cc->hostName[cc->numServers], namep);
3409 /**************************************/
3410 /* KFW_AFS_error(): */
3411 /**************************************/
3413 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3416 const char *errText;
3418 // Using AFS defines as error messages for now, until Transarc
3419 // gets back to me with "string" translations of each of these
3421 if (rc == KTC_ERROR)
3422 errText = "KTC_ERROR";
3423 else if (rc == KTC_TOOBIG)
3424 errText = "KTC_TOOBIG";
3425 else if (rc == KTC_INVAL)
3426 errText = "KTC_INVAL";
3427 else if (rc == KTC_NOENT)
3428 errText = "KTC_NOENT";
3429 else if (rc == KTC_PIOCTLFAIL)
3430 errText = "KTC_PIOCTLFAIL";
3431 else if (rc == KTC_NOPIOCTL)
3432 errText = "KTC_NOPIOCTL";
3433 else if (rc == KTC_NOCELL)
3434 errText = "KTC_NOCELL";
3435 else if (rc == KTC_NOCM)
3436 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3438 errText = "Unknown error!";
3440 sprintf(message, "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3442 if ( IsDebuggerPresent() ) {
3443 OutputDebugString(message);
3444 OutputDebugString("\n");
3446 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3452 LPSTR lpszMachineName,
3453 LPSTR lpszServiceName,
3454 DWORD *lpdwCurrentState)
3457 SC_HANDLE schSCManager = NULL;
3458 SC_HANDLE schService = NULL;
3459 DWORD fdwDesiredAccess = 0;
3460 SERVICE_STATUS ssServiceStatus = {0};
3463 *lpdwCurrentState = 0;
3465 fdwDesiredAccess = GENERIC_READ;
3467 schSCManager = OpenSCManager(lpszMachineName,
3471 if(schSCManager == NULL)
3473 hr = GetLastError();
3477 schService = OpenService(schSCManager,
3481 if(schService == NULL)
3483 hr = GetLastError();
3487 fRet = QueryServiceStatus(schService,
3492 hr = GetLastError();
3496 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3500 CloseServiceHandle(schService);
3501 CloseServiceHandle(schSCManager);
3514 for (n = 0; fi[n].func_ptr_var; n++)
3515 *(fi[n].func_ptr_var) = 0;
3516 if (h) FreeLibrary(h);
3521 const char* dll_name,
3523 HINSTANCE* ph, // [out, optional] - DLL handle
3524 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3525 int cleanup, // cleanup function pointers and unload on error
3526 int go_on, // continue loading even if some functions cannot be loaded
3527 int silent // do not pop-up a system dialog if DLL cannot be loaded
3536 if (pindex) *pindex = -1;
3538 for (n = 0; fi[n].func_ptr_var; n++)
3539 *(fi[n].func_ptr_var) = 0;
3542 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3543 h = LoadLibrary(dll_name);
3551 for (i = 0; (go_on || !error) && (i < n); i++)
3553 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3559 *(fi[i].func_ptr_var) = p;
3562 if (pindex) *pindex = last_i;
3563 if (error && cleanup && !go_on) {
3564 for (i = 0; i < n; i++) {
3565 *(fi[i].func_ptr_var) = 0;
3571 if (error) return 0;
3575 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3577 krb5_context ctx = NULL;
3578 krb5_ccache cc = NULL;
3579 krb5_error_code code;
3581 const char * realm = NULL;
3582 krb5_principal principal = NULL;
3583 char * pname = NULL;
3584 char password[PROBE_PASSWORD_LEN+1];
3585 BOOL serverReachable = 0;
3587 if (!pkrb5_init_context)
3590 code = pkrb5_init_context(&ctx);
3591 if (code) goto cleanup;
3594 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3596 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3597 realm, PROBE_USERNAME, NULL, NULL);
3598 if ( code ) goto cleanup;
3600 code = KFW_get_ccache(ctx, principal, &cc);
3601 if ( code ) goto cleanup;
3603 code = pkrb5_unparse_name(ctx, principal, &pname);
3604 if ( code ) goto cleanup;
3606 pwdata.data = password;
3607 pwdata.length = PROBE_PASSWORD_LEN;
3608 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3611 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3614 password[PROBE_PASSWORD_LEN] = '\0';
3616 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,