2 * Copyright (c) 2003 SkyRope, LLC
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
8 * - Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * - Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * - Neither the name of Skyrope, LLC nor the names of its contributors may be
14 * used to endorse or promote products derived from this software without
15 * specific prior written permission from Skyrope, LLC.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * Portions of this code are derived from portions of the MIT
30 * Leash Ticket Manager and LoadFuncs utilities. For these portions the
31 * following copyright applies.
33 * Copyright (c) 2003,2004 by the Massachusetts Institute of Technology.
34 * All rights reserved.
36 * Export of this software from the United States of America may
37 * require a specific license from the United States Government.
38 * It is the responsibility of any person or organization contemplating
39 * export to obtain such a license before exporting.
41 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
42 * distribute this software and its documentation for any purpose and
43 * without fee is hereby granted, provided that the above copyright
44 * notice appear in all copies and that both that copyright notice and
45 * this permission notice appear in supporting documentation, and that
46 * the name of M.I.T. not be used in advertising or publicity pertaining
47 * to distribution of the software without specific, written prior
48 * permission. Furthermore if you modify this software you must label
49 * your software as modified software and not distribute it in such a
50 * fashion that it might be confused with the original M.I.T. software.
51 * M.I.T. makes no representations about the suitability of
52 * this software for any purpose. It is provided "as is" without express
53 * or implied warranty.
60 #include "afskfw-int.h"
64 #include <rxkad_prototypes.h> /* for life_to_time */
65 #include <afs/ptserver.h>
66 #include <afs/ptuser.h>
68 #include <WINNT\afsreg.h>
71 * TIMING _____________________________________________________________________
75 #define cminREMIND_TEST 1 // test every minute for expired creds
76 #define cminREMIND_WARN 15 // warn if creds expire in 15 minutes
77 #define cminRENEW 20 // renew creds when there are 20 minutes remaining
78 #define cminMINLIFE 30 // minimum life of Kerberos creds
80 #define c100ns1SECOND (LONGLONG)10000000
81 #define cmsec1SECOND 1000
82 #define cmsec1MINUTE 60000
83 #define csec1MINUTE 60
85 /* Function Pointer Declarations for Delayed Loading */
87 DECL_FUNC_PTR(cc_initialize);
88 DECL_FUNC_PTR(cc_shutdown);
89 DECL_FUNC_PTR(cc_get_NC_info);
90 DECL_FUNC_PTR(cc_free_NC_info);
93 DECL_FUNC_PTR(Leash_get_default_lifetime);
94 DECL_FUNC_PTR(Leash_get_default_forwardable);
95 DECL_FUNC_PTR(Leash_get_default_renew_till);
96 DECL_FUNC_PTR(Leash_get_default_noaddresses);
97 DECL_FUNC_PTR(Leash_get_default_proxiable);
98 DECL_FUNC_PTR(Leash_get_default_publicip);
99 DECL_FUNC_PTR(Leash_get_default_use_krb4);
100 DECL_FUNC_PTR(Leash_get_default_life_min);
101 DECL_FUNC_PTR(Leash_get_default_life_max);
102 DECL_FUNC_PTR(Leash_get_default_renew_min);
103 DECL_FUNC_PTR(Leash_get_default_renew_max);
104 DECL_FUNC_PTR(Leash_get_default_renewable);
105 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
108 DECL_FUNC_PTR(krb5_change_password);
109 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
110 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
111 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
112 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
113 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
114 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
115 DECL_FUNC_PTR(krb5_get_init_creds_password);
116 DECL_FUNC_PTR(krb5_build_principal_ext);
117 DECL_FUNC_PTR(krb5_cc_get_name);
118 DECL_FUNC_PTR(krb5_cc_resolve);
119 DECL_FUNC_PTR(krb5_cc_default);
120 DECL_FUNC_PTR(krb5_cc_default_name);
121 DECL_FUNC_PTR(krb5_cc_set_default_name);
122 DECL_FUNC_PTR(krb5_cc_initialize);
123 DECL_FUNC_PTR(krb5_cc_destroy);
124 DECL_FUNC_PTR(krb5_cc_close);
125 DECL_FUNC_PTR(krb5_cc_store_cred);
126 DECL_FUNC_PTR(krb5_cc_copy_creds);
127 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
128 DECL_FUNC_PTR(krb5_cc_get_principal);
129 DECL_FUNC_PTR(krb5_cc_start_seq_get);
130 DECL_FUNC_PTR(krb5_cc_next_cred);
131 DECL_FUNC_PTR(krb5_cc_end_seq_get);
132 DECL_FUNC_PTR(krb5_cc_remove_cred);
133 DECL_FUNC_PTR(krb5_cc_set_flags);
134 DECL_FUNC_PTR(krb5_cc_get_type);
135 DECL_FUNC_PTR(krb5_free_context);
136 DECL_FUNC_PTR(krb5_free_cred_contents);
137 DECL_FUNC_PTR(krb5_free_principal);
138 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
139 DECL_FUNC_PTR(krb5_init_context);
140 DECL_FUNC_PTR(krb5_parse_name);
141 DECL_FUNC_PTR(krb5_timeofday);
142 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
143 DECL_FUNC_PTR(krb5_unparse_name);
144 DECL_FUNC_PTR(krb5_get_credentials);
145 DECL_FUNC_PTR(krb5_mk_req);
146 DECL_FUNC_PTR(krb5_sname_to_principal);
147 DECL_FUNC_PTR(krb5_get_credentials_renew);
148 DECL_FUNC_PTR(krb5_free_data);
149 DECL_FUNC_PTR(krb5_free_data_contents);
150 DECL_FUNC_PTR(krb5_free_unparsed_name);
151 DECL_FUNC_PTR(krb5_os_localaddr);
152 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
153 DECL_FUNC_PTR(krb5_copy_data);
154 DECL_FUNC_PTR(krb5_free_creds);
155 DECL_FUNC_PTR(krb5_build_principal);
156 DECL_FUNC_PTR(krb5_get_renewed_creds);
157 DECL_FUNC_PTR(krb5_get_default_config_files);
158 DECL_FUNC_PTR(krb5_free_config_files);
159 DECL_FUNC_PTR(krb5_get_default_realm);
160 DECL_FUNC_PTR(krb5_free_default_realm);
161 DECL_FUNC_PTR(krb5_free_ticket);
162 DECL_FUNC_PTR(krb5_decode_ticket);
163 DECL_FUNC_PTR(krb5_get_host_realm);
164 DECL_FUNC_PTR(krb5_free_host_realm);
165 DECL_FUNC_PTR(krb5_free_addresses);
166 DECL_FUNC_PTR(krb5_c_random_make_octets);
169 DECL_FUNC_PTR(krb524_init_ets);
170 DECL_FUNC_PTR(krb524_convert_creds_kdc);
173 DECL_FUNC_PTR(krb_get_cred);
174 DECL_FUNC_PTR(tkt_string);
175 DECL_FUNC_PTR(krb_get_tf_realm);
176 DECL_FUNC_PTR(krb_mk_req);
179 DECL_FUNC_PTR(com_err);
180 DECL_FUNC_PTR(error_message);
183 DECL_FUNC_PTR(profile_init);
184 DECL_FUNC_PTR(profile_release);
185 DECL_FUNC_PTR(profile_get_subsection_names);
186 DECL_FUNC_PTR(profile_free_list);
187 DECL_FUNC_PTR(profile_get_string);
188 DECL_FUNC_PTR(profile_release_string);
191 DECL_FUNC_PTR(OpenSCManagerA);
192 DECL_FUNC_PTR(OpenServiceA);
193 DECL_FUNC_PTR(QueryServiceStatus);
194 DECL_FUNC_PTR(CloseServiceHandle);
196 DECL_FUNC_PTR(LsaNtStatusToWinError);
197 #endif /* USE_MS2MIT */
201 DECL_FUNC_PTR(LsaConnectUntrusted);
202 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
203 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
204 DECL_FUNC_PTR(LsaFreeReturnBuffer);
205 DECL_FUNC_PTR(LsaGetLogonSessionData);
206 #endif /* USE_MS2MIT */
209 FUNC_INFO ccapi_fi[] = {
210 MAKE_FUNC_INFO(cc_initialize),
211 MAKE_FUNC_INFO(cc_shutdown),
212 MAKE_FUNC_INFO(cc_get_NC_info),
213 MAKE_FUNC_INFO(cc_free_NC_info),
217 FUNC_INFO leash_fi[] = {
218 MAKE_FUNC_INFO(Leash_get_default_lifetime),
219 MAKE_FUNC_INFO(Leash_get_default_renew_till),
220 MAKE_FUNC_INFO(Leash_get_default_forwardable),
221 MAKE_FUNC_INFO(Leash_get_default_noaddresses),
222 MAKE_FUNC_INFO(Leash_get_default_proxiable),
223 MAKE_FUNC_INFO(Leash_get_default_publicip),
224 MAKE_FUNC_INFO(Leash_get_default_use_krb4),
225 MAKE_FUNC_INFO(Leash_get_default_life_min),
226 MAKE_FUNC_INFO(Leash_get_default_life_max),
227 MAKE_FUNC_INFO(Leash_get_default_renew_min),
228 MAKE_FUNC_INFO(Leash_get_default_renew_max),
229 MAKE_FUNC_INFO(Leash_get_default_renewable),
233 FUNC_INFO leash_opt_fi[] = {
234 MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
238 FUNC_INFO k5_fi[] = {
239 MAKE_FUNC_INFO(krb5_change_password),
240 MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
241 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
242 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
243 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
244 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
245 MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
246 MAKE_FUNC_INFO(krb5_get_init_creds_password),
247 MAKE_FUNC_INFO(krb5_build_principal_ext),
248 MAKE_FUNC_INFO(krb5_cc_get_name),
249 MAKE_FUNC_INFO(krb5_cc_resolve),
250 MAKE_FUNC_INFO(krb5_cc_default),
251 MAKE_FUNC_INFO(krb5_cc_default_name),
252 MAKE_FUNC_INFO(krb5_cc_set_default_name),
253 MAKE_FUNC_INFO(krb5_cc_initialize),
254 MAKE_FUNC_INFO(krb5_cc_destroy),
255 MAKE_FUNC_INFO(krb5_cc_close),
256 MAKE_FUNC_INFO(krb5_cc_copy_creds),
257 MAKE_FUNC_INFO(krb5_cc_store_cred),
258 MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
259 MAKE_FUNC_INFO(krb5_cc_get_principal),
260 MAKE_FUNC_INFO(krb5_cc_start_seq_get),
261 MAKE_FUNC_INFO(krb5_cc_next_cred),
262 MAKE_FUNC_INFO(krb5_cc_end_seq_get),
263 MAKE_FUNC_INFO(krb5_cc_remove_cred),
264 MAKE_FUNC_INFO(krb5_cc_set_flags),
265 MAKE_FUNC_INFO(krb5_cc_get_type),
266 MAKE_FUNC_INFO(krb5_free_context),
267 MAKE_FUNC_INFO(krb5_free_cred_contents),
268 MAKE_FUNC_INFO(krb5_free_principal),
269 MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
270 MAKE_FUNC_INFO(krb5_init_context),
271 MAKE_FUNC_INFO(krb5_parse_name),
272 MAKE_FUNC_INFO(krb5_timeofday),
273 MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
274 MAKE_FUNC_INFO(krb5_unparse_name),
275 MAKE_FUNC_INFO(krb5_get_credentials),
276 MAKE_FUNC_INFO(krb5_mk_req),
277 MAKE_FUNC_INFO(krb5_sname_to_principal),
278 MAKE_FUNC_INFO(krb5_get_credentials_renew),
279 MAKE_FUNC_INFO(krb5_free_data),
280 MAKE_FUNC_INFO(krb5_free_data_contents),
281 MAKE_FUNC_INFO(krb5_free_unparsed_name),
282 MAKE_FUNC_INFO(krb5_os_localaddr),
283 MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
284 MAKE_FUNC_INFO(krb5_copy_data),
285 MAKE_FUNC_INFO(krb5_free_creds),
286 MAKE_FUNC_INFO(krb5_build_principal),
287 MAKE_FUNC_INFO(krb5_get_renewed_creds),
288 MAKE_FUNC_INFO(krb5_free_addresses),
289 MAKE_FUNC_INFO(krb5_get_default_config_files),
290 MAKE_FUNC_INFO(krb5_free_config_files),
291 MAKE_FUNC_INFO(krb5_get_default_realm),
292 MAKE_FUNC_INFO(krb5_free_default_realm),
293 MAKE_FUNC_INFO(krb5_free_ticket),
294 MAKE_FUNC_INFO(krb5_decode_ticket),
295 MAKE_FUNC_INFO(krb5_get_host_realm),
296 MAKE_FUNC_INFO(krb5_free_host_realm),
297 MAKE_FUNC_INFO(krb5_free_addresses),
298 MAKE_FUNC_INFO(krb5_c_random_make_octets),
303 FUNC_INFO k4_fi[] = {
304 MAKE_FUNC_INFO(krb_get_cred),
305 MAKE_FUNC_INFO(krb_get_tf_realm),
306 MAKE_FUNC_INFO(krb_mk_req),
307 MAKE_FUNC_INFO(tkt_string),
312 FUNC_INFO k524_fi[] = {
313 MAKE_FUNC_INFO(krb524_init_ets),
314 MAKE_FUNC_INFO(krb524_convert_creds_kdc),
318 FUNC_INFO profile_fi[] = {
319 MAKE_FUNC_INFO(profile_init),
320 MAKE_FUNC_INFO(profile_release),
321 MAKE_FUNC_INFO(profile_get_subsection_names),
322 MAKE_FUNC_INFO(profile_free_list),
323 MAKE_FUNC_INFO(profile_get_string),
324 MAKE_FUNC_INFO(profile_release_string),
328 FUNC_INFO ce_fi[] = {
329 MAKE_FUNC_INFO(com_err),
330 MAKE_FUNC_INFO(error_message),
334 FUNC_INFO service_fi[] = {
335 MAKE_FUNC_INFO(OpenSCManagerA),
336 MAKE_FUNC_INFO(OpenServiceA),
337 MAKE_FUNC_INFO(QueryServiceStatus),
338 MAKE_FUNC_INFO(CloseServiceHandle),
340 MAKE_FUNC_INFO(LsaNtStatusToWinError),
341 #endif /* USE_MS2MIT */
346 FUNC_INFO lsa_fi[] = {
347 MAKE_FUNC_INFO(LsaConnectUntrusted),
348 MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
349 MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
350 MAKE_FUNC_INFO(LsaFreeReturnBuffer),
351 MAKE_FUNC_INFO(LsaGetLogonSessionData),
354 #endif /* USE_MS2MIT */
356 /* Static Prototypes */
357 char *afs_realm_of_cell(krb5_context, struct afsconf_cell *);
358 static long get_cellconfig_callback(void *, struct sockaddr_in *, char *);
359 int KFW_AFS_get_cellconfig(char *, struct afsconf_cell *, char *);
360 static krb5_error_code KRB5_CALLCONV KRB5_prompter( krb5_context context,
361 void *data, const char *name, const char *banner, int num_prompts,
362 krb5_prompt prompts[]);
365 /* Static Declarations */
366 static int inited = 0;
367 static int mid_cnt = 0;
368 static struct textField * mid_tb = NULL;
369 static HINSTANCE hKrb5 = 0;
371 static HINSTANCE hKrb4 = 0;
372 #endif /* USE_KRB4 */
373 static HINSTANCE hKrb524 = 0;
375 static HINSTANCE hSecur32 = 0;
376 #endif /* USE_MS2MIT */
377 static HINSTANCE hAdvApi32 = 0;
378 static HINSTANCE hComErr = 0;
379 static HINSTANCE hService = 0;
380 static HINSTANCE hProfile = 0;
381 static HINSTANCE hLeash = 0;
382 static HINSTANCE hLeashOpt = 0;
383 static HINSTANCE hCCAPI = 0;
384 static struct principal_ccache_data * princ_cc_data = NULL;
385 static struct cell_principal_map * cell_princ_map = NULL;
390 static int inited = 0;
393 char mutexName[MAX_PATH];
394 HANDLE hMutex = NULL;
396 sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
398 hMutex = CreateMutex( NULL, TRUE, mutexName );
399 if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
400 if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
406 LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
408 LoadFuncs(KRB4_DLL, k4_fi, &hKrb4, 0, 1, 0, 0);
409 #endif /* USE_KRB4 */
410 LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
411 LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
413 LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
414 #endif /* USE_MS2MIT */
415 LoadFuncs(KRB524_DLL, k524_fi, &hKrb524, 0, 1, 1, 1);
416 LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
417 LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
418 LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
419 LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
421 if ( KFW_is_available() ) {
422 char rootcell[MAXCELLCHARS+1];
424 KFW_import_windows_lsa();
425 #endif /* USE_MS2MIT */
426 KFW_import_ccache_data();
427 KFW_AFS_renew_expiring_tokens();
429 /* WIN32 NOTE: no way to get max chars */
430 if (!cm_GetRootCellName(rootcell))
431 KFW_AFS_renew_token_for_cell(rootcell);
434 ReleaseMutex(hMutex);
443 FreeLibrary(hLeashOpt);
449 FreeLibrary(hKrb524);
452 FreeLibrary(hSecur32);
453 #endif /* USE_MS2MIT */
455 FreeLibrary(hService);
457 FreeLibrary(hComErr);
459 FreeLibrary(hProfile);
463 #endif /* USE_KRB4 */
475 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
476 0, KEY_QUERY_VALUE, &parmKey);
477 if (code == ERROR_SUCCESS) {
478 len = sizeof(use524);
479 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
480 (BYTE *) &use524, &len);
481 RegCloseKey(parmKey);
483 if (code != ERROR_SUCCESS) {
484 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
485 0, KEY_QUERY_VALUE, &parmKey);
486 if (code == ERROR_SUCCESS) {
487 len = sizeof(use524);
488 code = RegQueryValueEx(parmKey, "Use524", NULL, NULL,
489 (BYTE *) &use524, &len);
490 RegCloseKey (parmKey);
497 KFW_is_available(void)
503 code = RegOpenKeyEx(HKEY_CURRENT_USER, AFSREG_USER_OPENAFS_SUBKEY,
504 0, KEY_QUERY_VALUE, &parmKey);
505 if (code == ERROR_SUCCESS) {
506 len = sizeof(enableKFW);
507 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
508 (BYTE *) &enableKFW, &len);
509 RegCloseKey (parmKey);
512 if (code != ERROR_SUCCESS) {
513 code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
514 0, KEY_QUERY_VALUE, &parmKey);
515 if (code == ERROR_SUCCESS) {
516 len = sizeof(enableKFW);
517 code = RegQueryValueEx(parmKey, "EnableKFW", NULL, NULL,
518 (BYTE *) &enableKFW, &len);
519 RegCloseKey (parmKey);
527 if ( hKrb5 && hComErr && hService &&
530 #endif /* USE_MS2MIT */
532 hProfile && hLeash && hCCAPI )
538 KRB5_error(krb5_error_code rc, LPCSTR FailedFunctionName,
539 int FreeContextFlag, krb5_context * ctx,
544 int krb5Error = ((int)(rc & 255));
556 errText = perror_message(rc);
557 _snprintf(message, sizeof(message),
558 "%s\n(Kerberos error %ld)\n\n%s failed",
563 if ( IsDebuggerPresent() )
564 OutputDebugString(message);
566 MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |
569 if (FreeContextFlag == 1)
571 if (ctx && *ctx != NULL)
573 if (cache && *cache != NULL) {
574 pkrb5_cc_close(*ctx, *cache);
578 pkrb5_free_context(*ctx);
587 KFW_AFS_update_princ_ccache_data(krb5_context ctx, krb5_ccache cc, int lsa)
589 struct principal_ccache_data * next = princ_cc_data;
590 krb5_principal principal = 0;
592 const char * ccname = NULL;
593 krb5_error_code code = 0;
594 krb5_error_code cc_code = 0;
600 if (ctx == 0 || cc == 0)
603 code = pkrb5_cc_get_principal(ctx, cc, &principal);
606 code = pkrb5_unparse_name(ctx, principal, &pname);
607 if ( code ) goto cleanup;
609 ccname = pkrb5_cc_get_name(ctx, cc);
610 if (!ccname) goto cleanup;
612 // Search the existing list to see if we have a match
614 for ( ; next ; next = next->next ) {
615 if ( !strcmp(next->principal,pname) && !strcmp(next->ccache_name, ccname) )
620 // If not, match add a new node to the beginning of the list and assign init it
622 next = (struct principal_ccache_data *) malloc(sizeof(struct principal_ccache_data));
623 next->next = princ_cc_data;
624 princ_cc_data = next;
625 next->principal = _strdup(pname);
626 next->ccache_name = _strdup(ccname);
627 next->from_lsa = lsa;
629 next->expiration_time = 0;
633 flags = 0; // turn off OPENCLOSE mode
634 code = pkrb5_cc_set_flags(ctx, cc, flags);
635 if ( code ) goto cleanup;
637 code = pkrb5_timeofday(ctx, &now);
639 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
641 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
642 if ( creds.ticket_flags & TKT_FLG_INITIAL ) {
644 // we found the ticket we are looking for
645 // check validity of timestamp
646 // We add a 5 minutes fudge factor to compensate for potential
647 // clock skew errors between the KDC and client OS
649 valid = ((creds.times.starttime > 0) &&
650 now >= (creds.times.starttime - 300) &&
651 now < (creds.times.endtime + 300) &&
652 !(creds.ticket_flags & TKT_FLG_INVALID));
654 if ( next->from_lsa) {
656 next->expiration_time = creds.times.endtime;
658 } else if ( valid ) {
660 next->expiration_time = creds.times.endtime;
661 next->renew = (creds.times.renew_till > creds.times.endtime) &&
662 (creds.ticket_flags & TKT_FLG_RENEWABLE);
665 next->expiration_time = 0;
669 pkrb5_free_cred_contents(ctx, &creds);
670 cc_code = KRB5_CC_END;
673 pkrb5_free_cred_contents(ctx, &creds);
676 if (cc_code == KRB5_CC_END) {
677 code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
678 if (code) goto cleanup;
682 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
683 code = pkrb5_cc_set_flags(ctx, cc, flags);
686 pkrb5_free_unparsed_name(ctx,pname);
688 pkrb5_free_principal(ctx,principal);
692 KFW_AFS_find_ccache_for_principal(krb5_context ctx, char * principal, char **ccache, int valid_only)
694 struct principal_ccache_data * next = princ_cc_data;
695 char * response = NULL;
697 if ( !principal || !ccache )
701 if ( (!valid_only || !next->expired) && !strcmp(next->principal,principal) ) {
703 // we always want to prefer the MS Kerberos LSA cache or
704 // the cache afscreds created specifically for the principal
705 // if the current entry is either one, drop the previous find
706 if ( next->from_lsa || !strcmp(next->ccache_name,principal) )
709 response = _strdup(next->ccache_name);
710 // MS Kerberos LSA is our best option so use it and quit
711 if ( next->from_lsa )
725 KFW_AFS_delete_princ_ccache_data(krb5_context ctx, char * pname, char * ccname)
727 struct principal_ccache_data ** next = &princ_cc_data;
729 if ( !pname && !ccname )
733 if ( !strcmp((*next)->principal,pname) ||
734 !strcmp((*next)->ccache_name,ccname) ) {
736 free((*next)->principal);
737 free((*next)->ccache_name);
739 (*next) = (*next)->next;
746 KFW_AFS_update_cell_princ_map(krb5_context ctx, char * cell, char *pname, int active)
748 struct cell_principal_map * next = cell_princ_map;
750 // Search the existing list to see if we have a match
752 for ( ; next ; next = next->next ) {
753 if ( !strcmp(next->cell, cell) ) {
754 if ( !strcmp(next->principal,pname) ) {
755 next->active = active;
758 // OpenAFS currently has a restriction of one active token per cell
759 // Therefore, whenever we update the table with a new active cell we
760 // must mark all of the other principal to cell entries as inactive.
768 // If not, match add a new node to the beginning of the list and assign init it
770 next = (struct cell_principal_map *) malloc(sizeof(struct cell_principal_map));
771 next->next = cell_princ_map;
772 cell_princ_map = next;
773 next->principal = _strdup(pname);
774 next->cell = _strdup(cell);
775 next->active = active;
780 KFW_AFS_delete_cell_princ_maps(krb5_context ctx, char * pname, char * cell)
782 struct cell_principal_map ** next = &cell_princ_map;
784 if ( !pname && !cell )
788 if ( !strcmp((*next)->principal,pname) ||
789 !strcmp((*next)->cell,cell) ) {
791 free((*next)->principal);
794 (*next) = (*next)->next;
800 // Returns (if possible) a principal which has been known in
801 // the past to have been used to obtain tokens for the specified
803 // TODO: Attempt to return one which has not yet expired by checking
804 // the principal/ccache data
806 KFW_AFS_find_principals_for_cell(krb5_context ctx, char * cell, char **principals[], int active_only)
808 struct cell_principal_map * next_map = cell_princ_map;
809 const char * princ = NULL;
816 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
819 next_map = next_map->next;
822 if ( !principals || !count )
825 *principals = (char **) malloc(sizeof(char *) * count);
826 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
828 if ( (!active_only || next_map->active) && !strcmp(next_map->cell,cell) ) {
829 (*principals)[i++] = _strdup(next_map->principal);
836 KFW_AFS_find_cells_for_princ(krb5_context ctx, char * pname, char **cells[], int active_only)
839 struct cell_principal_map * next_map = cell_princ_map;
840 const char * princ = NULL;
846 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
849 next_map = next_map->next;
855 *cells = (char **) malloc(sizeof(char *) * count);
856 for ( next_map = cell_princ_map, i=0 ; next_map && i<count; next_map = next_map->next )
858 if ( (!active_only || next_map->active) && !strcmp(next_map->principal,pname) ) {
859 (*cells)[i++] = _strdup(next_map->cell);
865 /* Given a principal return an existing ccache or create one and return */
867 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
872 krb5_error_code code;
874 if (!pkrb5_init_context)
880 code = pkrb5_init_context(&ctx);
881 if (code) goto cleanup;
885 code = pkrb5_unparse_name(ctx, principal, &pname);
886 if (code) goto cleanup;
888 if ( !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,TRUE) &&
889 !KFW_AFS_find_ccache_for_principal(ctx,pname,&ccname,FALSE)) {
890 ccname = (char *)malloc(strlen(pname) + 5);
891 sprintf(ccname,"API:%s",pname);
893 code = pkrb5_cc_resolve(ctx, ccname, cc);
895 code = pkrb5_cc_default(ctx, cc);
896 if (code) goto cleanup;
903 pkrb5_free_unparsed_name(ctx,pname);
904 if (ctx && (ctx != alt_ctx))
905 pkrb5_free_context(ctx);
910 // Import Microsoft Credentials into a new MIT ccache
912 KFW_import_windows_lsa(void)
914 krb5_context ctx = 0;
916 krb5_principal princ = 0;
918 krb5_data * princ_realm;
919 krb5_error_code code;
920 char cell[128]="", realm[128]="", *def_realm = 0;
924 if (!pkrb5_init_context)
928 if ( !MSLSA_IsKerberosLogon() )
932 code = pkrb5_init_context(&ctx);
933 if (code) goto cleanup;
935 code = pkrb5_cc_resolve(ctx, LSA_CCNAME, &cc);
936 if (code) goto cleanup;
938 KFW_AFS_update_princ_ccache_data(ctx, cc, TRUE);
940 code = pkrb5_cc_get_principal(ctx, cc, &princ);
941 if ( code ) goto cleanup;
943 dwMsLsaImport = pLeash_get_default_mslsa_import ? pLeash_get_default_mslsa_import() : 1;
944 switch ( dwMsLsaImport ) {
945 case 0: /* do not import */
947 case 1: /* always import */
949 case 2: { /* matching realm */
950 char ms_realm[128] = "", *r;
953 for ( r=ms_realm, i=0; i<krb5_princ_realm(ctx, princ)->length; r++, i++ ) {
954 *r = krb5_princ_realm(ctx, princ)->data[i];
958 if (code = pkrb5_get_default_realm(ctx, &def_realm))
961 if (strcmp(def_realm, ms_realm))
969 code = pkrb5_unparse_name(ctx,princ,&pname);
970 if ( code ) goto cleanup;
972 princ_realm = krb5_princ_realm(ctx, princ);
973 for ( i=0; i<princ_realm->length; i++ ) {
974 realm[i] = princ_realm->data[i];
975 cell[i] = tolower(princ_realm->data[i]);
980 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, pLeash_get_default_lifetime(),NULL);
981 if ( IsDebuggerPresent() ) {
983 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
984 OutputDebugString(message);
986 if ( code ) goto cleanup;
988 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
992 pkrb5_free_unparsed_name(ctx,pname);
994 pkrb5_free_principal(ctx,princ);
996 pkrb5_free_default_realm(ctx, def_realm);
998 pkrb5_cc_close(ctx,cc);
1000 pkrb5_free_context(ctx);
1002 #endif /* USE_MS2MIT */
1004 // If there are existing MIT credentials, copy them to a new
1005 // ccache named after the principal
1007 // Enumerate all existing MIT ccaches and construct entries
1008 // in the principal_ccache table
1010 // Enumerate all existing AFS Tokens and construct entries
1011 // in the cell_principal table
1013 KFW_import_ccache_data(void)
1015 krb5_context ctx = 0;
1017 krb5_principal principal = 0;
1019 krb5_error_code code;
1020 krb5_error_code cc_code;
1023 struct _infoNC ** pNCi = NULL;
1026 if ( !pcc_initialize )
1029 if ( IsDebuggerPresent() )
1030 OutputDebugString("KFW_import_ccache_data()\n");
1032 code = pcc_initialize(&cc_ctx, CC_API_VER_2, NULL, NULL);
1033 if (code) goto cleanup;
1035 code = pcc_get_NC_info(cc_ctx, &pNCi);
1036 if (code) goto cleanup;
1038 code = pkrb5_init_context(&ctx);
1039 if (code) goto cleanup;
1041 for ( i=0; pNCi[i]; i++ ) {
1042 if ( pNCi[i]->vers != CC_CRED_V5 )
1044 if ( IsDebuggerPresent() ) {
1045 OutputDebugString("Principal: ");
1046 OutputDebugString(pNCi[i]->principal);
1047 OutputDebugString(" in ccache ");
1048 OutputDebugString(pNCi[i]->name);
1049 OutputDebugString("\n");
1051 if ( strcmp(pNCi[i]->name,pNCi[i]->principal)
1052 && strcmp(pNCi[i]->name,LSA_CCNAME)
1055 for ( j=0; pNCi[j]; j++ ) {
1056 if (!strcmp(pNCi[j]->name,pNCi[i]->principal)) {
1062 code = pkrb5_cc_resolve(ctx, pNCi[i]->principal, &cc);
1063 if (code) goto loop_cleanup;
1066 krb5_ccache oldcc = 0;
1068 if ( IsDebuggerPresent() )
1069 OutputDebugString("copying ccache data to new ccache\n");
1071 code = pkrb5_parse_name(ctx, pNCi[i]->principal, &principal);
1072 if (code) goto loop_cleanup;
1073 code = pkrb5_cc_initialize(ctx, cc, principal);
1074 if (code) goto loop_cleanup;
1076 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &oldcc);
1077 if (code) goto loop_cleanup;
1078 code = pkrb5_cc_copy_creds(ctx,oldcc,cc);
1080 code = pkrb5_cc_close(ctx,cc);
1082 code = pkrb5_cc_close(ctx,oldcc);
1084 KRB5_error(code, "krb5_cc_copy_creds", 0, NULL, NULL);
1087 code = pkrb5_cc_close(ctx,oldcc);
1090 code = pkrb5_cc_resolve(ctx, pNCi[i]->name, &cc);
1091 if (code) goto loop_cleanup;
1094 flags = 0; // turn off OPENCLOSE mode
1095 code = pkrb5_cc_set_flags(ctx, cc, flags);
1096 if ( code ) goto cleanup;
1098 KFW_AFS_update_princ_ccache_data(ctx, cc, !strcmp(pNCi[i]->name,LSA_CCNAME));
1100 cc_code = pkrb5_cc_start_seq_get(ctx, cc, &cur);
1102 while (!(cc_code = pkrb5_cc_next_cred(ctx, cc, &cur, &creds))) {
1103 krb5_data * sname = krb5_princ_name(ctx, creds.server);
1104 krb5_data * cell = krb5_princ_component(ctx, creds.server, 1);
1105 krb5_data * realm = krb5_princ_realm(ctx, creds.server);
1106 if ( sname && cell && !strcmp("afs",sname->data) ) {
1107 struct ktc_principal aserver;
1108 struct ktc_principal aclient;
1109 struct ktc_token atoken;
1112 if ( IsDebuggerPresent() ) {
1113 OutputDebugString("Found AFS ticket: ");
1114 OutputDebugString(sname->data);
1116 OutputDebugString("/");
1117 OutputDebugString(cell->data);
1119 OutputDebugString("@");
1120 OutputDebugString(realm->data);
1121 OutputDebugString("\n");
1124 memset(&aserver, '\0', sizeof(aserver));
1125 strcpy(aserver.name, sname->data);
1126 strcpy(aserver.cell, cell->data);
1128 code = ktc_GetToken(&aserver, &atoken, sizeof(atoken), &aclient);
1130 // Found a token in AFS Client Server which matches
1131 char pname[128], *p, *q;
1132 for ( p=pname, q=aclient.name; *q; p++, q++)
1134 for ( *p++ = '@', q=aclient.cell; *q; p++, q++)
1138 if ( IsDebuggerPresent() ) {
1139 OutputDebugString("Found AFS token: ");
1140 OutputDebugString(pname);
1141 OutputDebugString("\n");
1144 if ( strcmp(pname,pNCi[i]->principal) )
1146 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1148 // Attempt to import it
1149 KFW_AFS_update_cell_princ_map(ctx, cell->data, pNCi[i]->principal, active);
1151 if ( IsDebuggerPresent() ) {
1152 OutputDebugString("Calling KFW_AFS_klog() to obtain token\n");
1155 code = KFW_AFS_klog(ctx, cc, "afs", cell->data, realm->data, pLeash_get_default_lifetime(),NULL);
1156 if ( IsDebuggerPresent() ) {
1158 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1159 OutputDebugString(message);
1162 } else if ( IsDebuggerPresent() ) {
1163 OutputDebugString("Found ticket: ");
1164 OutputDebugString(sname->data);
1165 if ( cell && cell->data ) {
1166 OutputDebugString("/");
1167 OutputDebugString(cell->data);
1169 OutputDebugString("@");
1170 OutputDebugString(realm->data);
1171 OutputDebugString("\n");
1173 pkrb5_free_cred_contents(ctx, &creds);
1176 if (cc_code == KRB5_CC_END) {
1177 cc_code = pkrb5_cc_end_seq_get(ctx, cc, &cur);
1178 if (cc_code) goto loop_cleanup;
1182 flags = KRB5_TC_OPENCLOSE; //turn on OPENCLOSE
1183 code = pkrb5_cc_set_flags(ctx, cc, flags);
1185 pkrb5_cc_close(ctx,cc);
1189 pkrb5_free_principal(ctx,principal);
1196 pkrb5_free_context(ctx);
1198 pcc_free_NC_info(cc_ctx, &pNCi);
1200 pcc_shutdown(&cc_ctx);
1205 KFW_AFS_get_cred( char * username,
1212 krb5_context ctx = 0;
1214 char * realm = 0, * userrealm = 0;
1215 krb5_principal principal = 0;
1217 krb5_error_code code;
1218 char local_cell[MAXCELLCHARS+1];
1219 char **cells = NULL;
1221 struct afsconf_cell cellconfig;
1225 if (!pkrb5_init_context)
1228 if ( IsDebuggerPresent() ) {
1229 OutputDebugString("KFW_AFS_get_cred for token ");
1230 OutputDebugString(username);
1231 OutputDebugString(" in cell ");
1232 OutputDebugString(cell);
1233 OutputDebugString("\n");
1236 code = pkrb5_init_context(&ctx);
1237 if ( code ) goto cleanup;
1239 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1240 if ( code ) goto cleanup;
1242 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1244 userrealm = strchr(username,'@');
1246 pname = strdup(username);
1247 userrealm = strchr(pname, '@');
1250 /* handle kerberos iv notation */
1251 while ( dot = strchr(pname,'.') ) {
1256 pname = malloc(strlen(username) + strlen(realm) + 2);
1258 strcpy(pname, username);
1260 /* handle kerberos iv notation */
1261 while ( dot = strchr(pname,'.') ) {
1266 strcat(pname,realm);
1268 if ( IsDebuggerPresent() ) {
1269 OutputDebugString("Realm: ");
1270 OutputDebugString(realm);
1271 OutputDebugString("\n");
1274 code = pkrb5_parse_name(ctx, pname, &principal);
1275 if ( code ) goto cleanup;
1277 code = KFW_get_ccache(ctx, principal, &cc);
1278 if ( code ) goto cleanup;
1280 if ( lifetime == 0 )
1281 lifetime = pLeash_get_default_lifetime();
1283 if ( password && password[0] ) {
1284 code = KFW_kinit( ctx, cc, HWND_DESKTOP,
1288 pLeash_get_default_forwardable(),
1289 pLeash_get_default_proxiable(),
1290 pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
1291 pLeash_get_default_noaddresses(),
1292 pLeash_get_default_publicip());
1293 if ( IsDebuggerPresent() ) {
1295 sprintf(message,"KFW_kinit() returns: %d\n",code);
1296 OutputDebugString(message);
1298 if ( code ) goto cleanup;
1300 KFW_AFS_update_princ_ccache_data(ctx, cc, FALSE);
1303 code = KFW_AFS_klog(ctx, cc, "afs", cell, realm, lifetime,smbname);
1304 if ( IsDebuggerPresent() ) {
1306 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1307 OutputDebugString(message);
1309 if ( code ) goto cleanup;
1311 KFW_AFS_update_cell_princ_map(ctx, cell, pname, TRUE);
1313 // Attempt to obtain new tokens for other cells supported by the same
1315 cell_count = KFW_AFS_find_cells_for_princ(ctx, pname, &cells, TRUE);
1316 if ( cell_count > 1 ) {
1317 while ( cell_count-- ) {
1318 if ( strcmp(cells[cell_count],cell) ) {
1319 if ( IsDebuggerPresent() ) {
1321 sprintf(message,"found another cell for the same principal: %s\n",cell);
1322 OutputDebugString(message);
1324 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1325 if ( code ) continue;
1327 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1328 if ( IsDebuggerPresent() ) {
1329 OutputDebugString("Realm: ");
1330 OutputDebugString(realm);
1331 OutputDebugString("\n");
1334 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], realm, lifetime,smbname);
1335 if ( IsDebuggerPresent() ) {
1337 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1338 OutputDebugString(message);
1341 free(cells[cell_count]);
1344 } else if ( cell_count == 1 ) {
1353 pkrb5_cc_close(ctx, cc);
1355 if ( code && reasonP ) {
1356 *reasonP = (char *)perror_message(code);
1362 KFW_AFS_destroy_tickets_for_cell(char * cell)
1364 krb5_context ctx = 0;
1365 krb5_error_code code;
1367 char ** principals = NULL;
1369 if (!pkrb5_init_context)
1372 if ( IsDebuggerPresent() ) {
1373 OutputDebugString("KFW_AFS_destroy_ticets_for_cell: ");
1374 OutputDebugString(cell);
1375 OutputDebugString("\n");
1378 code = pkrb5_init_context(&ctx);
1381 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, FALSE);
1383 krb5_principal princ = 0;
1387 int cell_count = KFW_AFS_find_cells_for_princ(ctx, principals[count], NULL, TRUE);
1388 if ( cell_count > 1 ) {
1389 // TODO - What we really should do here is verify whether or not any of the
1390 // other cells which use this principal to obtain its credentials actually
1391 // have valid tokens or not. If they are currently using these credentials
1392 // we will skip them. For the time being we assume that if there is an active
1393 // map in the table that they are actively being used.
1397 code = pkrb5_parse_name(ctx, principals[count], &princ);
1398 if (code) goto loop_cleanup;
1400 code = KFW_get_ccache(ctx, princ, &cc);
1401 if (code) goto loop_cleanup;
1403 code = pkrb5_cc_destroy(ctx, cc);
1408 pkrb5_cc_close(ctx, cc);
1412 pkrb5_free_principal(ctx, princ);
1416 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], FALSE);
1417 free(principals[count]);
1421 pkrb5_free_context(ctx);
1426 KFW_AFS_renew_expiring_tokens(void)
1428 krb5_error_code code = 0;
1429 krb5_context ctx = 0;
1432 struct principal_ccache_data * pcc_next = princ_cc_data;
1435 const char * realm = NULL;
1436 char local_cell[MAXCELLCHARS+1]="";
1437 struct afsconf_cell cellconfig;
1439 if (!pkrb5_init_context)
1442 if ( pcc_next == NULL ) // nothing to do
1445 if ( IsDebuggerPresent() ) {
1446 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1449 code = pkrb5_init_context(&ctx);
1450 if (code) goto cleanup;
1452 code = pkrb5_timeofday(ctx, &now);
1453 if (code) goto cleanup;
1455 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1456 if ( pcc_next->expired )
1459 if ( now >= (pcc_next->expiration_time) ) {
1460 if ( !pcc_next->from_lsa ) {
1461 pcc_next->expired = 1;
1466 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1467 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1470 code = KFW_renew(ctx,cc);
1472 if ( code && pcc_next->from_lsa)
1474 #endif /* USE_MS2MIT */
1477 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1478 if (code) goto loop_cleanup;
1480 // Attempt to obtain new tokens for other cells supported by the same
1482 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1483 if ( cell_count > 0 ) {
1484 while ( cell_count-- ) {
1485 if ( IsDebuggerPresent() ) {
1486 OutputDebugString("Cell: ");
1487 OutputDebugString(cells[cell_count]);
1488 OutputDebugString("\n");
1490 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1491 if ( code ) continue;
1492 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1493 if ( IsDebuggerPresent() ) {
1494 OutputDebugString("Realm: ");
1495 OutputDebugString(realm);
1496 OutputDebugString("\n");
1498 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, pLeash_get_default_lifetime(),NULL);
1499 if ( IsDebuggerPresent() ) {
1501 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1502 OutputDebugString(message);
1504 free(cells[cell_count]);
1512 pkrb5_cc_close(ctx,cc);
1519 pkrb5_cc_close(ctx,cc);
1521 pkrb5_free_context(ctx);
1528 KFW_AFS_renew_token_for_cell(char * cell)
1530 krb5_error_code code = 0;
1531 krb5_context ctx = 0;
1533 char ** principals = NULL;
1535 if (!pkrb5_init_context)
1538 if ( IsDebuggerPresent() ) {
1539 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1540 OutputDebugString(cell);
1541 OutputDebugString("\n");
1544 code = pkrb5_init_context(&ctx);
1545 if (code) goto cleanup;
1547 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1549 // We know we must have a credential somewhere since we are
1550 // trying to renew a token
1552 KFW_import_ccache_data();
1553 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1556 krb5_principal princ = 0;
1557 krb5_principal service = 0;
1559 krb5_creds mcreds, creds;
1560 #endif /* COMMENT */
1562 const char * realm = NULL;
1563 struct afsconf_cell cellconfig;
1564 char local_cell[MAXCELLCHARS+1];
1567 code = pkrb5_parse_name(ctx, principals[count], &princ);
1568 if (code) goto loop_cleanup;
1570 code = KFW_get_ccache(ctx, princ, &cc);
1571 if (code) goto loop_cleanup;
1573 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1574 if ( code ) goto loop_cleanup;
1576 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1577 if ( IsDebuggerPresent() ) {
1578 OutputDebugString("Realm: ");
1579 OutputDebugString(realm);
1580 OutputDebugString("\n");
1584 /* krb5_cc_remove_cred() is not implemented
1587 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1588 realm, "afs", cell, NULL);
1590 memset(&mcreds, 0, sizeof(krb5_creds));
1591 mcreds.client = princ;
1592 mcreds.server = service;
1594 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1596 if ( IsDebuggerPresent() ) {
1597 char * cname, *sname;
1598 pkrb5_unparse_name(ctx, creds.client, &cname);
1599 pkrb5_unparse_name(ctx, creds.server, &sname);
1600 OutputDebugString("Removing credential for client \"");
1601 OutputDebugString(cname);
1602 OutputDebugString("\" and service \"");
1603 OutputDebugString(sname);
1604 OutputDebugString("\"\n");
1605 pkrb5_free_unparsed_name(ctx,cname);
1606 pkrb5_free_unparsed_name(ctx,sname);
1609 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1610 pkrb5_free_principal(ctx, creds.client);
1611 pkrb5_free_principal(ctx, creds.server);
1614 #endif /* COMMENT */
1616 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, pLeash_get_default_lifetime(),NULL);
1617 if ( IsDebuggerPresent() ) {
1619 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1620 OutputDebugString(message);
1625 pkrb5_cc_close(ctx, cc);
1629 pkrb5_free_principal(ctx, princ);
1633 pkrb5_free_principal(ctx, service);
1637 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1638 free(principals[count]);
1642 code = -1; // we did not renew the tokens
1645 pkrb5_free_context(ctx);
1646 return (code ? FALSE : TRUE);
1651 KFW_AFS_renew_tokens_for_all_cells(void)
1653 struct cell_principal_map * next = cell_princ_map;
1655 if ( IsDebuggerPresent() )
1656 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1661 for ( ; next ; next = next->next ) {
1663 KFW_AFS_renew_token_for_cell(next->cell);
1669 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1671 krb5_error_code code = 0;
1672 krb5_context ctx = 0;
1674 krb5_principal me = 0;
1675 krb5_principal server = 0;
1676 krb5_creds my_creds;
1677 krb5_data *realm = 0;
1679 if (!pkrb5_init_context)
1682 memset(&my_creds, 0, sizeof(krb5_creds));
1687 code = pkrb5_init_context(&ctx);
1688 if (code) goto cleanup;
1694 code = pkrb5_cc_default(ctx, &cc);
1695 if (code) goto cleanup;
1698 code = pkrb5_cc_get_principal(ctx, cc, &me);
1699 if (code) goto cleanup;
1701 realm = krb5_princ_realm(ctx, me);
1703 code = pkrb5_build_principal_ext(ctx, &server,
1704 realm->length,realm->data,
1705 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1706 realm->length,realm->data,
1711 if ( IsDebuggerPresent() ) {
1712 char * cname, *sname;
1713 pkrb5_unparse_name(ctx, me, &cname);
1714 pkrb5_unparse_name(ctx, server, &sname);
1715 OutputDebugString("Renewing credential for client \"");
1716 OutputDebugString(cname);
1717 OutputDebugString("\" and service \"");
1718 OutputDebugString(sname);
1719 OutputDebugString("\"\n");
1720 pkrb5_free_unparsed_name(ctx,cname);
1721 pkrb5_free_unparsed_name(ctx,sname);
1724 my_creds.client = me;
1725 my_creds.server = server;
1727 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1729 if ( IsDebuggerPresent() ) {
1731 sprintf(message,"krb5_get_renewed_creds() failed: %d\n",code);
1732 OutputDebugString(message);
1737 code = pkrb5_cc_initialize(ctx, cc, me);
1739 if ( IsDebuggerPresent() ) {
1741 sprintf(message,"krb5_cc_initialize() failed: %d\n",code);
1742 OutputDebugString(message);
1747 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1749 if ( IsDebuggerPresent() ) {
1751 sprintf(message,"krb5_cc_store_cred() failed: %d\n",code);
1752 OutputDebugString(message);
1758 if (my_creds.client == me)
1759 my_creds.client = 0;
1760 if (my_creds.server == server)
1761 my_creds.server = 0;
1762 pkrb5_free_cred_contents(ctx, &my_creds);
1764 pkrb5_free_principal(ctx, me);
1766 pkrb5_free_principal(ctx, server);
1767 if (cc && (cc != alt_cc))
1768 pkrb5_cc_close(ctx, cc);
1769 if (ctx && (ctx != alt_ctx))
1770 pkrb5_free_context(ctx);
1775 KFW_kinit( krb5_context alt_ctx,
1778 char *principal_name,
1780 krb5_deltat lifetime,
1783 krb5_deltat renew_life,
1788 krb5_error_code code = 0;
1789 krb5_context ctx = 0;
1791 krb5_principal me = 0;
1793 krb5_creds my_creds;
1794 krb5_get_init_creds_opt options;
1795 krb5_address ** addrs = NULL;
1796 int i = 0, addr_count = 0;
1798 if (!pkrb5_init_context)
1801 pkrb5_get_init_creds_opt_init(&options);
1802 memset(&my_creds, 0, sizeof(my_creds));
1810 code = pkrb5_init_context(&ctx);
1811 if (code) goto cleanup;
1817 code = pkrb5_cc_default(ctx, &cc);
1818 if (code) goto cleanup;
1821 code = pkrb5_parse_name(ctx, principal_name, &me);
1825 code = pkrb5_unparse_name(ctx, me, &name);
1830 lifetime = pLeash_get_default_lifetime();
1838 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
1839 pkrb5_get_init_creds_opt_set_forwardable(&options,
1840 forwardable ? 1 : 0);
1841 pkrb5_get_init_creds_opt_set_proxiable(&options,
1843 pkrb5_get_init_creds_opt_set_renew_life(&options,
1846 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
1850 // we are going to add the public IP address specified by the user
1851 // to the list provided by the operating system
1852 krb5_address ** local_addrs=NULL;
1855 pkrb5_os_localaddr(ctx, &local_addrs);
1856 while ( local_addrs[i++] );
1859 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
1861 pkrb5_free_addresses(ctx, local_addrs);
1864 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
1866 while ( local_addrs[i] ) {
1867 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
1868 if (addrs[i] == NULL) {
1869 pkrb5_free_addresses(ctx, local_addrs);
1873 addrs[i]->magic = local_addrs[i]->magic;
1874 addrs[i]->addrtype = local_addrs[i]->addrtype;
1875 addrs[i]->length = local_addrs[i]->length;
1876 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
1877 if (!addrs[i]->contents) {
1878 pkrb5_free_addresses(ctx, local_addrs);
1882 memcpy(addrs[i]->contents,local_addrs[i]->contents,
1883 local_addrs[i]->length); /* safe */
1886 pkrb5_free_addresses(ctx, local_addrs);
1888 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
1889 if (addrs[i] == NULL)
1892 addrs[i]->magic = KV5M_ADDRESS;
1893 addrs[i]->addrtype = AF_INET;
1894 addrs[i]->length = 4;
1895 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
1896 if (!addrs[i]->contents)
1899 netIPAddr = htonl(publicIP);
1900 memcpy(addrs[i]->contents,&netIPAddr,4);
1902 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
1907 code = pkrb5_get_init_creds_password(ctx,
1910 password, // password
1911 KRB5_prompter, // prompter
1912 hParent, // prompter data
1919 code = pkrb5_cc_initialize(ctx, cc, me);
1923 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1929 for ( i=0;i<addr_count;i++ ) {
1931 if ( addrs[i]->contents )
1932 free(addrs[i]->contents);
1937 if (my_creds.client == me)
1938 my_creds.client = 0;
1939 pkrb5_free_cred_contents(ctx, &my_creds);
1941 pkrb5_free_unparsed_name(ctx, name);
1943 pkrb5_free_principal(ctx, me);
1944 if (cc && (cc != alt_cc))
1945 pkrb5_cc_close(ctx, cc);
1946 if (ctx && (ctx != alt_ctx))
1947 pkrb5_free_context(ctx);
1953 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
1957 krb5_error_code code;
1959 if (!pkrb5_init_context)
1968 code = pkrb5_init_context(&ctx);
1969 if (code) goto cleanup;
1975 code = pkrb5_cc_default(ctx, &cc);
1976 if (code) goto cleanup;
1979 code = pkrb5_cc_destroy(ctx, cc);
1980 if ( !code ) cc = 0;
1983 if (cc && (cc != alt_cc))
1984 pkrb5_cc_close(ctx, cc);
1985 if (ctx && (ctx != alt_ctx))
1986 pkrb5_free_context(ctx);
1994 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
1996 NTSTATUS Status = 0;
1998 TOKEN_STATISTICS Stats;
2004 *ppSessionData = NULL;
2006 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2010 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2011 CloseHandle( TokenHandle );
2015 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2016 if ( FAILED(Status) || !ppSessionData )
2023 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2024 // cache. It validates whether or not it is reasonable to assume that if we
2025 // attempted to retrieve valid tickets we could do so. Microsoft does not
2026 // automatically renew expired tickets. Therefore, the cache could contain
2027 // expired or invalid tickets. Microsoft also caches the user's password
2028 // and will use it to retrieve new TGTs if the cache is empty and tickets
2032 MSLSA_IsKerberosLogon(VOID)
2034 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2035 BOOL Success = FALSE;
2037 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2038 if ( pSessionData->AuthenticationPackage.Buffer ) {
2044 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2045 usLength = (pSessionData->AuthenticationPackage).Length;
2048 lstrcpynW (buffer, usBuffer, usLength);
2049 lstrcatW (buffer,L"");
2050 if ( !lstrcmpW(L"Kerberos",buffer) )
2054 pLsaFreeReturnBuffer(pSessionData);
2058 #endif /* USE_MS2MIT */
2060 static BOOL CALLBACK
2061 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2065 switch ( message ) {
2067 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2069 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2072 for ( i=0; i < mid_cnt ; i++ ) {
2073 if (mid_tb[i].echo == 0)
2074 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2075 else if (mid_tb[i].echo == 2)
2076 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2081 switch ( LOWORD(wParam) ) {
2083 for ( i=0; i < mid_cnt ; i++ ) {
2084 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2085 *mid_tb[i].buf = '\0';
2089 EndDialog(hDialog, LOWORD(wParam));
2097 lpwAlign( LPWORD lpIn )
2105 return (LPWORD) ul;;
2109 * dialog widths are measured in 1/4 character widths
2110 * dialog height are measured in 1/8 character heights
2114 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2115 char * ptext[], int numlines, int width,
2116 int tb_cnt, struct textField * tb)
2120 LPDLGITEMTEMPLATE lpdit;
2126 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2133 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2135 // Define a dialog box.
2137 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2138 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2139 | DS_SETFOREGROUND | DS_3DLOOK
2140 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2141 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2144 lpdt->cx = 20 + width * 4;
2145 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2147 lpw = (LPWORD) (lpdt + 1);
2148 *lpw++ = 0; // no menu
2149 *lpw++ = 0; // predefined dialog box class (by default)
2151 lpwsz = (LPWSTR) lpw;
2152 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2154 *lpw++ = 8; // font size (points)
2155 lpwsz = (LPWSTR) lpw;
2156 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2160 //-----------------------
2161 // Define an OK button.
2162 //-----------------------
2163 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2164 lpdit = (LPDLGITEMTEMPLATE) lpw;
2165 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2166 lpdit->dwExtendedStyle = 0;
2167 lpdit->x = (lpdt->cx - 14)/4 - 20;
2168 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2171 lpdit->id = IDOK; // OK button identifier
2173 lpw = (LPWORD) (lpdit + 1);
2175 *lpw++ = 0x0080; // button class
2177 lpwsz = (LPWSTR) lpw;
2178 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2180 *lpw++ = 0; // no creation data
2182 //-----------------------
2183 // Define an Cancel button.
2184 //-----------------------
2185 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2186 lpdit = (LPDLGITEMTEMPLATE) lpw;
2187 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2188 lpdit->dwExtendedStyle = 0;
2189 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2190 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2193 lpdit->id = IDCANCEL; // CANCEL button identifier
2195 lpw = (LPWORD) (lpdit + 1);
2197 *lpw++ = 0x0080; // button class
2199 lpwsz = (LPWSTR) lpw;
2200 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2202 *lpw++ = 0; // no creation data
2204 /* Add controls for preface data */
2205 for ( i=0; i<numlines; i++) {
2206 /*-----------------------
2207 * Define a static text control.
2208 *-----------------------*/
2209 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2210 lpdit = (LPDLGITEMTEMPLATE) lpw;
2211 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2212 lpdit->dwExtendedStyle = 0;
2214 lpdit->y = 10 + i * 14;
2215 lpdit->cx = strlen(ptext[i]) * 4 + 10;
2217 lpdit->id = ID_TEXT + i; // text identifier
2219 lpw = (LPWORD) (lpdit + 1);
2221 *lpw++ = 0x0082; // static class
2223 lpwsz = (LPWSTR) lpw;
2224 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2225 -1, lpwsz, 2*width);
2227 *lpw++ = 0; // no creation data
2230 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2231 if ( pwid < strlen(tb[i].label) )
2232 pwid = strlen(tb[i].label);
2235 for ( i=0; i<tb_cnt; i++) {
2237 /*-----------------------
2238 * Define a static text control.
2239 *-----------------------*/
2240 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2241 lpdit = (LPDLGITEMTEMPLATE) lpw;
2242 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2243 lpdit->dwExtendedStyle = 0;
2245 lpdit->y = 10 + (numlines + i + 1) * 14;
2246 lpdit->cx = pwid * 4;
2248 lpdit->id = ID_TEXT + numlines + i; // text identifier
2250 lpw = (LPWORD) (lpdit + 1);
2252 *lpw++ = 0x0082; // static class
2254 lpwsz = (LPWSTR) lpw;
2255 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2258 *lpw++ = 0; // no creation data
2260 /*-----------------------
2261 * Define an edit control.
2262 *-----------------------*/
2263 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2264 lpdit = (LPDLGITEMTEMPLATE) lpw;
2265 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2266 lpdit->dwExtendedStyle = 0;
2267 lpdit->x = 10 + (pwid + 1) * 4;
2268 lpdit->y = 10 + (numlines + i + 1) * 14;
2269 lpdit->cx = (width - (pwid + 1)) * 4;
2271 lpdit->id = ID_MID_TEXT + i; // identifier
2273 lpw = (LPWORD) (lpdit + 1);
2275 *lpw++ = 0x0081; // edit class
2277 lpwsz = (LPWSTR) lpw;
2278 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2281 *lpw++ = 0; // no creation data
2285 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2286 hwndOwner, (DLGPROC) MultiInputDialogProc);
2290 case 0: /* Timeout */
2298 sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
2299 MessageBox(hwndOwner,
2302 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2309 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2311 HINSTANCE hInst = 0;
2315 char * plines[16], *p = preface ? preface : "";
2318 for ( i=0; i<16; i++ )
2321 while (*p && numlines < 16) {
2322 plines[numlines++] = p;
2323 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2324 if ( *p == '\r' && *(p+1) == '\n' ) {
2327 } else if ( *p == '\n' ) {
2330 if ( strlen(plines[numlines-1]) > maxwidth )
2331 maxwidth = strlen(plines[numlines-1]);
2334 for ( i=0;i<n;i++ ) {
2335 len = strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2336 if ( maxwidth < len )
2340 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb));
2343 static krb5_error_code KRB5_CALLCONV
2344 KRB5_prompter( krb5_context context,
2349 krb5_prompt prompts[])
2351 krb5_error_code errcode = 0;
2353 struct textField * tb = NULL;
2354 int len = 0, blen=0, nlen=0;
2355 HWND hParent = (HWND)data;
2358 nlen = strlen(name)+2;
2361 blen = strlen(banner)+2;
2363 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2366 memset(tb,0,sizeof(struct textField) * num_prompts);
2367 for ( i=0; i < num_prompts; i++ ) {
2368 tb[i].buf = prompts[i].reply->data;
2369 tb[i].len = prompts[i].reply->length;
2370 tb[i].label = prompts[i].prompt;
2372 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2375 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2377 for ( i=0; i < num_prompts; i++ )
2378 prompts[i].reply->length = strlen(prompts[i].reply->data);
2386 for (i = 0; i < num_prompts; i++) {
2387 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2394 KFW_AFS_wait_for_service_start(void)
2399 CurrentState = SERVICE_START_PENDING;
2400 memset(HostName, '\0', sizeof(HostName));
2401 gethostname(HostName, sizeof(HostName));
2403 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2405 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2407 if ( IsDebuggerPresent() ) {
2408 switch ( CurrentState ) {
2409 case SERVICE_STOPPED:
2410 OutputDebugString("SERVICE_STOPPED\n");
2412 case SERVICE_START_PENDING:
2413 OutputDebugString("SERVICE_START_PENDING\n");
2415 case SERVICE_STOP_PENDING:
2416 OutputDebugString("SERVICE_STOP_PENDING\n");
2418 case SERVICE_RUNNING:
2419 OutputDebugString("SERVICE_RUNNING\n");
2421 case SERVICE_CONTINUE_PENDING:
2422 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2424 case SERVICE_PAUSE_PENDING:
2425 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2427 case SERVICE_PAUSED:
2428 OutputDebugString("SERVICE_PAUSED\n");
2431 OutputDebugString("UNKNOWN Service State\n");
2434 if (CurrentState == SERVICE_STOPPED)
2436 if (CurrentState == SERVICE_RUNNING)
2452 memset(HostName, '\0', sizeof(HostName));
2453 gethostname(HostName, sizeof(HostName));
2454 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2456 if (CurrentState != SERVICE_RUNNING)
2459 rc = ktc_ForgetAllTokens();
2465 #define ALLOW_REGISTER 1
2467 ViceIDToUsername(char *username,
2468 char *realm_of_user,
2469 char *realm_of_cell,
2471 struct ktc_principal *aclient,
2472 struct ktc_principal *aserver,
2473 struct ktc_token *atoken)
2475 static char lastcell[MAXCELLCHARS+1] = { 0 };
2476 static char confname[512] = { 0 };
2477 #ifdef AFS_ID_TO_NAME
2478 char username_copy[BUFSIZ];
2479 #endif /* AFS_ID_TO_NAME */
2480 long viceId; /* AFS uid of user */
2482 #ifdef ALLOW_REGISTER
2484 #endif /* ALLOW_REGISTER */
2486 if (confname[0] == '\0') {
2487 strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname));
2488 confname[sizeof(confname) - 2] = '\0';
2492 * Talk about DUMB! It turns out that there is a bug in
2493 * pr_Initialize -- even if you give a different cell name
2494 * to it, it still uses a connection to a previous AFS server
2495 * if one exists. The way to fix this is to change the
2496 * _filename_ argument to pr_Initialize - that forces it to
2497 * re-initialize the connection. We do this by adding and
2498 * removing a "/" on the end of the configuration directory name.
2501 if (lastcell[0] != '\0' && (strcmp(lastcell, aserver->cell) != 0)) {
2502 int i = strlen(confname);
2503 if (confname[i - 1] == '/') {
2504 confname[i - 1] = '\0';
2507 confname[i + 1] = '\0';
2511 strcpy(lastcell, aserver->cell);
2513 if (!pr_Initialize (0, confname, aserver->cell))
2514 status = pr_SNameToId (username, &viceId);
2517 * This is a crock, but it is Transarc's crock, so
2518 * we have to play along in order to get the
2519 * functionality. The way the afs id is stored is
2520 * as a string in the username field of the token.
2521 * Contrary to what you may think by looking at
2522 * the code for tokens, this hack (AFS ID %d) will
2523 * not work if you change %d to something else.
2527 * This code is taken from cklog -- it lets people
2528 * automatically register with the ptserver in foreign cells
2531 #ifdef ALLOW_REGISTER
2533 if (viceId != ANONYMOUSID) {
2534 #else /* ALLOW_REGISTER */
2535 if ((status == 0) && (viceId != ANONYMOUSID))
2536 #endif /* ALLOW_REGISTER */
2538 #ifdef AFS_ID_TO_NAME
2539 strncpy(username_copy, username, BUFSIZ);
2540 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2541 #endif /* AFS_ID_TO_NAME */
2543 #ifdef ALLOW_REGISTER
2544 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2546 strncpy(aclient->name, username, MAXKTCNAMELEN - 1);
2547 strcpy(aclient->instance, "");
2548 strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
2549 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2553 * In case you're wondering, we don't need to change the
2554 * filename here because we're still connecting to the
2555 * same cell -- we're just using a different authentication
2559 if (status = pr_Initialize(1L, confname, aserver->cell))
2561 if (status = pr_CreateUser(username, &id))
2563 #ifdef AFS_ID_TO_NAME
2564 strncpy(username_copy, username, BUFSIZ);
2565 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2566 #endif /* AFS_ID_TO_NAME */
2569 #endif /* ALLOW_REGISTER */
2576 krb5_context alt_ctx,
2589 #endif /* USE_KRB4 */
2590 struct ktc_principal aserver;
2591 struct ktc_principal aclient;
2592 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2593 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2594 char local_cell[MAXCELLCHARS+1];
2595 char Dmycell[MAXCELLCHARS+1];
2596 struct ktc_token atoken;
2597 struct ktc_token btoken;
2598 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2599 char RealmName[128];
2601 char ServiceName[128];
2605 krb5_context ctx = 0;
2608 krb5_creds * k5creds = 0;
2609 krb5_error_code code;
2610 krb5_principal client_principal = 0;
2615 memset(HostName, '\0', sizeof(HostName));
2616 gethostname(HostName, sizeof(HostName));
2617 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2618 if ( IsDebuggerPresent() )
2619 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2622 if (CurrentState != SERVICE_RUNNING) {
2623 if ( IsDebuggerPresent() )
2624 OutputDebugString("AFSD Service NOT RUNNING\n");
2628 if (!pkrb5_init_context)
2631 memset(RealmName, '\0', sizeof(RealmName));
2632 memset(CellName, '\0', sizeof(CellName));
2633 memset(ServiceName, '\0', sizeof(ServiceName));
2634 memset(realm_of_user, '\0', sizeof(realm_of_user));
2635 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2636 if (cell && cell[0])
2637 strcpy(Dmycell, cell);
2639 memset(Dmycell, '\0', sizeof(Dmycell));
2641 // NULL or empty cell returns information on local cell
2642 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2644 // KFW_AFS_error(rc, "get_cellconfig()");
2651 code = pkrb5_init_context(&ctx);
2652 if (code) goto cleanup;
2658 code = pkrb5_cc_default(ctx, &cc);
2659 if (code) goto skip_krb5_init;
2662 memset((char *)&increds, 0, sizeof(increds));
2664 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2666 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2668 OutputDebugString("Principal Not Found for ccache\n");
2670 goto skip_krb5_init;
2673 /* look for client principals which cannot be distinguished
2674 * from Kerberos 4 multi-component principal names
2676 k5data = krb5_princ_component(ctx,client_principal,0);
2677 for ( i=0; i<k5data->length; i++ ) {
2678 if ( k5data->data[i] == '.' )
2681 if (i != k5data->length)
2683 OutputDebugString("Illegal Principal name contains dot in first component\n");
2684 rc = KRB5KRB_ERR_GENERIC;
2688 i = krb5_princ_realm(ctx, client_principal)->length;
2691 strncpy(realm_of_user,krb5_princ_realm(ctx, client_principal)->data,i);
2692 realm_of_user[i] = 0;
2697 if ( !try_krb5 || !realm_of_user[0] ) {
2698 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2707 strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig));
2709 if (strlen(service) == 0)
2710 strcpy(ServiceName, "afs");
2712 strcpy(ServiceName, service);
2714 if (strlen(cell) == 0)
2715 strcpy(CellName, local_cell);
2717 strcpy(CellName, cell);
2719 if (strlen(realm) == 0)
2720 strcpy(RealmName, realm_of_cell);
2722 strcpy(RealmName, realm);
2724 memset(&creds, '\0', sizeof(creds));
2729 /* First try service/cell@REALM */
2730 if (code = pkrb5_build_principal(ctx, &increds.server,
2740 increds.client = client_principal;
2741 increds.times.endtime = 0;
2742 /* Ask for DES since that is what V4 understands */
2743 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
2746 if ( IsDebuggerPresent() ) {
2747 char * cname, *sname;
2748 pkrb5_unparse_name(ctx, increds.client, &cname);
2749 pkrb5_unparse_name(ctx, increds.server, &sname);
2750 OutputDebugString("Getting tickets for \"");
2751 OutputDebugString(cname);
2752 OutputDebugString("\" and service \"");
2753 OutputDebugString(sname);
2754 OutputDebugString("\"\n");
2755 pkrb5_free_unparsed_name(ctx,cname);
2756 pkrb5_free_unparsed_name(ctx,sname);
2759 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2760 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2761 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2762 code == KRB5KRB_AP_ERR_MSG_TYPE) {
2763 /* Or service@REALM */
2764 pkrb5_free_principal(ctx,increds.server);
2766 code = pkrb5_build_principal(ctx, &increds.server,
2772 if ( IsDebuggerPresent() ) {
2773 char * cname, *sname;
2774 pkrb5_unparse_name(ctx, increds.client, &cname);
2775 pkrb5_unparse_name(ctx, increds.server, &sname);
2776 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2777 OutputDebugString("Trying again: getting tickets for \"");
2778 OutputDebugString(cname);
2779 OutputDebugString("\" and service \"");
2780 OutputDebugString(sname);
2781 OutputDebugString("\"\n");
2782 pkrb5_free_unparsed_name(ctx,cname);
2783 pkrb5_free_unparsed_name(ctx,sname);
2787 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2790 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2791 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2792 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
2793 strcmp(RealmName, realm_of_cell)) {
2794 /* Or service/cell@REALM_OF_CELL */
2795 strcpy(RealmName, realm_of_cell);
2796 pkrb5_free_principal(ctx,increds.server);
2798 code = pkrb5_build_principal(ctx, &increds.server,
2805 if ( IsDebuggerPresent() ) {
2806 char * cname, *sname;
2807 pkrb5_unparse_name(ctx, increds.client, &cname);
2808 pkrb5_unparse_name(ctx, increds.server, &sname);
2809 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2810 OutputDebugString("Trying again: getting tickets for \"");
2811 OutputDebugString(cname);
2812 OutputDebugString("\" and service \"");
2813 OutputDebugString(sname);
2814 OutputDebugString("\"\n");
2815 pkrb5_free_unparsed_name(ctx,cname);
2816 pkrb5_free_unparsed_name(ctx,sname);
2820 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2823 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2824 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2825 code == KRB5KRB_AP_ERR_MSG_TYPE) {
2826 /* Or service@REALM_OF_CELL */
2827 pkrb5_free_principal(ctx,increds.server);
2829 code = pkrb5_build_principal(ctx, &increds.server,
2835 if ( IsDebuggerPresent() ) {
2836 char * cname, *sname;
2837 pkrb5_unparse_name(ctx, increds.client, &cname);
2838 pkrb5_unparse_name(ctx, increds.server, &sname);
2839 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2840 OutputDebugString("Trying again: getting tickets for \"");
2841 OutputDebugString(cname);
2842 OutputDebugString("\" and service \"");
2843 OutputDebugString(sname);
2844 OutputDebugString("\"\n");
2845 pkrb5_free_unparsed_name(ctx,cname);
2846 pkrb5_free_unparsed_name(ctx,sname);
2850 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2855 if ( IsDebuggerPresent() ) {
2857 sprintf(message,"krb5_get_credentials returns: %d\n",code);
2858 OutputDebugString(message);
2864 /* This code inserts the entire K5 ticket into the token
2865 * No need to perform a krb524 translation which is
2866 * commented out in the code below
2868 if (KFW_use_krb524() ||
2869 k5creds->ticket.length > MAXKTCTICKETLEN)
2872 memset(&aserver, '\0', sizeof(aserver));
2873 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
2874 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
2876 memset(&atoken, '\0', sizeof(atoken));
2877 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
2878 atoken.startTime = k5creds->times.starttime;
2879 atoken.endTime = k5creds->times.endtime;
2880 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
2881 atoken.ticketLen = k5creds->ticket.length;
2882 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
2885 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
2886 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
2887 if ( rc == KTC_NOCM && retry < 20 ) {
2890 goto retry_gettoken5;
2895 if (atoken.kvno == btoken.kvno &&
2896 atoken.ticketLen == btoken.ticketLen &&
2897 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
2898 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
2900 /* Success - Nothing to do */
2904 // * Reset the "aclient" structure before we call ktc_SetToken.
2905 // * This structure was first set by the ktc_GetToken call when
2906 // * we were comparing whether identical tokens already existed.
2908 len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
2909 strncpy(aclient.name, k5creds->client->data[0].data, len);
2910 aclient.name[len] = '\0';
2912 if ( k5creds->client->length > 1 ) {
2914 strcat(aclient.name, ".");
2915 p = aclient.name + strlen(aclient.name);
2916 len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
2917 strncpy(p, k5creds->client->data[1].data, len);
2920 aclient.instance[0] = '\0';
2922 strcpy(aclient.cell, realm_of_cell);
2924 len = min(k5creds->client->realm.length,strlen(realm_of_cell));
2925 if ( strncmp(realm_of_cell, k5creds->client->realm.data, len) ) {
2927 strcat(aclient.name, "@");
2928 p = aclient.name + strlen(aclient.name);
2929 len = min(k5creds->client->realm.length,MAXKTCNAMELEN - strlen(aclient.name) - 1);
2930 strncpy(p, k5creds->client->realm.data, len);
2934 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
2935 &aclient, &aserver, &atoken);
2938 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
2939 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
2941 aclient.smbname[0] = '\0';
2944 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
2946 goto cleanup; /* We have successfully inserted the token */
2949 /* Otherwise, the ticket could have been too large so try to
2950 * convert using the krb524d running with the KDC
2952 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
2953 pkrb5_free_creds(ctx, k5creds);
2955 if ( IsDebuggerPresent() ) {
2957 sprintf(message,"krb524_convert_creds_kdc returns: %d\n",code);
2958 OutputDebugString(message);
2966 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
2967 if (code == NO_TKT_FIL) {
2968 // if the problem is that we have no krb4 tickets
2969 // do not attempt to continue
2972 if (code != KSUCCESS)
2973 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
2975 if (code != KSUCCESS)
2977 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
2979 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
2984 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
2986 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3001 memset(&aserver, '\0', sizeof(aserver));
3002 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
3003 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
3005 memset(&atoken, '\0', sizeof(atoken));
3006 atoken.kvno = creds.kvno;
3007 atoken.startTime = creds.issue_date;
3008 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3009 memcpy(&atoken.sessionKey, creds.session, 8);
3010 atoken.ticketLen = creds.ticket_st.length;
3011 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3014 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3015 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3016 if ( rc == KTC_NOCM && retry < 20 ) {
3019 goto retry_gettoken;
3021 KFW_AFS_error(rc, "ktc_GetToken()");
3026 if (atoken.kvno == btoken.kvno &&
3027 atoken.ticketLen == btoken.ticketLen &&
3028 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3029 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3034 // * Reset the "aclient" structure before we call ktc_SetToken.
3035 // * This structure was first set by the ktc_GetToken call when
3036 // * we were comparing whether identical tokens already existed.
3038 strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
3041 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3042 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3044 strcpy(aclient.instance, "");
3046 if ( strcmp(realm_of_cell, creds.realm) )
3048 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3049 strncpy(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3051 aclient.name[MAXKTCREALMLEN-1] = '\0';
3053 strcpy(aclient.cell, CellName);
3055 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3056 &aclient, &aserver, &atoken);
3059 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
3060 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
3062 aclient.smbname[0] = '\0';
3065 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3067 KFW_AFS_error(rc, "ktc_SetToken()");
3073 if (client_principal)
3074 pkrb5_free_principal(ctx,client_principal);
3075 /* increds.client == client_principal */
3077 pkrb5_free_principal(ctx,increds.server);
3078 if (cc && (cc != alt_cc))
3079 pkrb5_cc_close(ctx, cc);
3080 if (ctx && (ctx != alt_ctx))
3081 pkrb5_free_context(ctx);
3083 return(rc? rc : code);
3086 /**************************************/
3087 /* afs_realm_of_cell(): */
3088 /**************************************/
3090 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3092 static char krbrlm[REALM_SZ+1]="";
3093 char ** realmlist=NULL;
3099 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3100 if ( !r && realmlist && realmlist[0] ) {
3101 strcpy(krbrlm, realmlist[0]);
3102 pkrb5_free_host_realm(ctx, realmlist);
3108 char *t = cellconfig->name;
3113 if (islower(c)) c=toupper(c);
3121 /**************************************/
3122 /* KFW_AFS_get_cellconfig(): */
3123 /**************************************/
3125 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3128 char newcell[MAXCELLCHARS+1];
3130 local_cell[0] = (char)0;
3131 memset(cellconfig, 0, sizeof(*cellconfig));
3133 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3134 if (rc = cm_GetRootCellName(local_cell))
3139 if (strlen(cell) == 0)
3140 strcpy(cell, local_cell);
3142 /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
3143 strcpy(cellconfig->name, cell);
3145 rc = cm_SearchCellFile(cell, newcell, get_cellconfig_callback, (void*)cellconfig);
3146 #ifdef AFS_AFSDB_ENV
3149 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3155 /**************************************/
3156 /* get_cellconfig_callback(): */
3157 /**************************************/
3159 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep)
3161 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3163 cc->hostAddr[cc->numServers] = *addrp;
3164 strcpy(cc->hostName[cc->numServers], namep);
3170 /**************************************/
3171 /* KFW_AFS_error(): */
3172 /**************************************/
3174 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3177 const char *errText;
3179 // Using AFS defines as error messages for now, until Transarc
3180 // gets back to me with "string" translations of each of these
3182 if (rc == KTC_ERROR)
3183 errText = "KTC_ERROR";
3184 else if (rc == KTC_TOOBIG)
3185 errText = "KTC_TOOBIG";
3186 else if (rc == KTC_INVAL)
3187 errText = "KTC_INVAL";
3188 else if (rc == KTC_NOENT)
3189 errText = "KTC_NOENT";
3190 else if (rc == KTC_PIOCTLFAIL)
3191 errText = "KTC_PIOCTLFAIL";
3192 else if (rc == KTC_NOPIOCTL)
3193 errText = "KTC_NOPIOCTL";
3194 else if (rc == KTC_NOCELL)
3195 errText = "KTC_NOCELL";
3196 else if (rc == KTC_NOCM)
3197 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3199 errText = "Unknown error!";
3201 sprintf(message, "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3203 if ( IsDebuggerPresent() ) {
3204 OutputDebugString(message);
3205 OutputDebugString("\n");
3207 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3213 LPSTR lpszMachineName,
3214 LPSTR lpszServiceName,
3215 DWORD *lpdwCurrentState)
3218 SC_HANDLE schSCManager = NULL;
3219 SC_HANDLE schService = NULL;
3220 DWORD fdwDesiredAccess = 0;
3221 SERVICE_STATUS ssServiceStatus = {0};
3224 *lpdwCurrentState = 0;
3226 fdwDesiredAccess = GENERIC_READ;
3228 schSCManager = OpenSCManager(lpszMachineName,
3232 if(schSCManager == NULL)
3234 hr = GetLastError();
3238 schService = OpenService(schSCManager,
3242 if(schService == NULL)
3244 hr = GetLastError();
3248 fRet = QueryServiceStatus(schService,
3253 hr = GetLastError();
3257 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3261 CloseServiceHandle(schService);
3262 CloseServiceHandle(schSCManager);
3275 for (n = 0; fi[n].func_ptr_var; n++)
3276 *(fi[n].func_ptr_var) = 0;
3277 if (h) FreeLibrary(h);
3282 const char* dll_name,
3284 HINSTANCE* ph, // [out, optional] - DLL handle
3285 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3286 int cleanup, // cleanup function pointers and unload on error
3287 int go_on, // continue loading even if some functions cannot be loaded
3288 int silent // do not pop-up a system dialog if DLL cannot be loaded
3297 if (pindex) *pindex = -1;
3299 for (n = 0; fi[n].func_ptr_var; n++)
3300 *(fi[n].func_ptr_var) = 0;
3303 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3304 h = LoadLibrary(dll_name);
3312 for (i = 0; (go_on || !error) && (i < n); i++)
3314 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3320 *(fi[i].func_ptr_var) = p;
3323 if (pindex) *pindex = last_i;
3324 if (error && cleanup && !go_on) {
3325 for (i = 0; i < n; i++) {
3326 *(fi[i].func_ptr_var) = 0;
3332 if (error) return 0;
3336 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3338 krb5_context ctx = 0;
3340 krb5_error_code code;
3342 const char * realm = 0;
3343 krb5_principal principal = 0;
3345 char password[PROBE_PASSWORD_LEN+1];
3346 BOOL serverReachable = 0;
3348 if (!pkrb5_init_context)
3351 code = pkrb5_init_context(&ctx);
3352 if (code) goto cleanup;
3355 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3357 code = pkrb5_build_principal(ctx, &principal, strlen(realm),
3358 realm, PROBE_USERNAME, NULL, NULL);
3359 if ( code ) goto cleanup;
3361 code = KFW_get_ccache(ctx, principal, &cc);
3362 if ( code ) goto cleanup;
3364 code = pkrb5_unparse_name(ctx, principal, &pname);
3365 if ( code ) goto cleanup;
3367 pwdata.data = password;
3368 pwdata.length = PROBE_PASSWORD_LEN;
3369 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3372 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3375 password[PROBE_PASSWORD_LEN] = '\0';
3377 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3387 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3388 case KRB5KDC_ERR_CLIENT_REVOKED:
3389 case KRB5KDC_ERR_CLIENT_NOTYET:
3390 case KRB5KDC_ERR_PREAUTH_FAILED:
3391 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3392 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3393 serverReachable = TRUE;
3396 serverReachable = FALSE;
3401 pkrb5_free_unparsed_name(ctx,pname);
3403 pkrb5_free_principal(ctx,principal);
3405 pkrb5_cc_close(ctx,cc);
3407 pkrb5_free_context(ctx);
3409 return serverReachable;