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_tickets_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_destroy_tickets_for_principal(char * user)
1428 krb5_context ctx = 0;
1429 krb5_error_code code;
1431 char ** cells = NULL;
1432 krb5_principal princ = 0;
1435 if (!pkrb5_init_context)
1438 if ( IsDebuggerPresent() ) {
1439 OutputDebugString("KFW_AFS_destroy_tickets_for_user: ");
1440 OutputDebugString(user);
1441 OutputDebugString("\n");
1444 code = pkrb5_init_context(&ctx);
1447 code = pkrb5_parse_name(ctx, user, &princ);
1448 if (code) goto loop_cleanup;
1450 code = KFW_get_ccache(ctx, princ, &cc);
1451 if (code) goto loop_cleanup;
1453 code = pkrb5_cc_destroy(ctx, cc);
1458 pkrb5_cc_close(ctx, cc);
1462 pkrb5_free_principal(ctx, princ);
1466 count = KFW_AFS_find_cells_for_princ(ctx, user, &cells, TRUE);
1469 KFW_AFS_update_cell_princ_map(ctx, cells[count], user, FALSE);
1475 pkrb5_free_context(ctx);
1480 KFW_AFS_renew_expiring_tokens(void)
1482 krb5_error_code code = 0;
1483 krb5_context ctx = 0;
1486 struct principal_ccache_data * pcc_next = princ_cc_data;
1489 const char * realm = NULL;
1490 char local_cell[MAXCELLCHARS+1]="";
1491 struct afsconf_cell cellconfig;
1493 if (!pkrb5_init_context)
1496 if ( pcc_next == NULL ) // nothing to do
1499 if ( IsDebuggerPresent() ) {
1500 OutputDebugString("KFW_AFS_renew_expiring_tokens\n");
1503 code = pkrb5_init_context(&ctx);
1504 if (code) goto cleanup;
1506 code = pkrb5_timeofday(ctx, &now);
1507 if (code) goto cleanup;
1509 for ( ; pcc_next ; pcc_next = pcc_next->next ) {
1510 if ( pcc_next->expired )
1513 if ( now >= (pcc_next->expiration_time) ) {
1514 if ( !pcc_next->from_lsa ) {
1515 pcc_next->expired = 1;
1520 if ( pcc_next->renew && now >= (pcc_next->expiration_time - cminRENEW * csec1MINUTE) ) {
1521 code = pkrb5_cc_resolve(ctx, pcc_next->ccache_name, &cc);
1524 code = KFW_renew(ctx,cc);
1526 if ( code && pcc_next->from_lsa)
1528 #endif /* USE_MS2MIT */
1531 KFW_AFS_update_princ_ccache_data(ctx, cc, pcc_next->from_lsa);
1532 if (code) goto loop_cleanup;
1534 // Attempt to obtain new tokens for other cells supported by the same
1536 cell_count = KFW_AFS_find_cells_for_princ(ctx, pcc_next->principal, &cells, TRUE);
1537 if ( cell_count > 0 ) {
1538 while ( cell_count-- ) {
1539 if ( IsDebuggerPresent() ) {
1540 OutputDebugString("Cell: ");
1541 OutputDebugString(cells[cell_count]);
1542 OutputDebugString("\n");
1544 code = KFW_AFS_get_cellconfig( cells[cell_count], (void*)&cellconfig, local_cell);
1545 if ( code ) continue;
1546 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1547 if ( IsDebuggerPresent() ) {
1548 OutputDebugString("Realm: ");
1549 OutputDebugString(realm);
1550 OutputDebugString("\n");
1552 code = KFW_AFS_klog(ctx, cc, "afs", cells[cell_count], (char *)realm, 0, NULL);
1553 if ( IsDebuggerPresent() ) {
1555 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1556 OutputDebugString(message);
1558 free(cells[cell_count]);
1566 pkrb5_cc_close(ctx,cc);
1573 pkrb5_cc_close(ctx,cc);
1575 pkrb5_free_context(ctx);
1582 KFW_AFS_renew_token_for_cell(char * cell)
1584 krb5_error_code code = 0;
1585 krb5_context ctx = 0;
1587 char ** principals = NULL;
1589 if (!pkrb5_init_context)
1592 if ( IsDebuggerPresent() ) {
1593 OutputDebugString("KFW_AFS_renew_token_for_cell:");
1594 OutputDebugString(cell);
1595 OutputDebugString("\n");
1598 code = pkrb5_init_context(&ctx);
1599 if (code) goto cleanup;
1601 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1603 // We know we must have a credential somewhere since we are
1604 // trying to renew a token
1606 KFW_import_ccache_data();
1607 count = KFW_AFS_find_principals_for_cell(ctx, cell, &principals, TRUE);
1610 krb5_principal princ = 0;
1611 krb5_principal service = 0;
1613 krb5_creds mcreds, creds;
1614 #endif /* COMMENT */
1616 const char * realm = NULL;
1617 struct afsconf_cell cellconfig;
1618 char local_cell[MAXCELLCHARS+1];
1621 code = pkrb5_parse_name(ctx, principals[count], &princ);
1622 if (code) goto loop_cleanup;
1624 code = KFW_get_ccache(ctx, princ, &cc);
1625 if (code) goto loop_cleanup;
1627 code = KFW_AFS_get_cellconfig( cell, (void*)&cellconfig, local_cell);
1628 if ( code ) goto loop_cleanup;
1630 realm = afs_realm_of_cell(ctx, &cellconfig); // do not free
1631 if ( IsDebuggerPresent() ) {
1632 OutputDebugString("Realm: ");
1633 OutputDebugString(realm);
1634 OutputDebugString("\n");
1638 /* krb5_cc_remove_cred() is not implemented
1641 code = pkrb5_build_principal(ctx, &service, strlen(realm),
1642 realm, "afs", cell, NULL);
1644 memset(&mcreds, 0, sizeof(krb5_creds));
1645 mcreds.client = princ;
1646 mcreds.server = service;
1648 code = pkrb5_cc_retrieve_cred(ctx, cc, 0, &mcreds, &creds);
1650 if ( IsDebuggerPresent() ) {
1651 char * cname, *sname;
1652 pkrb5_unparse_name(ctx, creds.client, &cname);
1653 pkrb5_unparse_name(ctx, creds.server, &sname);
1654 OutputDebugString("Removing credential for client \"");
1655 OutputDebugString(cname);
1656 OutputDebugString("\" and service \"");
1657 OutputDebugString(sname);
1658 OutputDebugString("\"\n");
1659 pkrb5_free_unparsed_name(ctx,cname);
1660 pkrb5_free_unparsed_name(ctx,sname);
1663 code = pkrb5_cc_remove_cred(ctx, cc, 0, &creds);
1664 pkrb5_free_principal(ctx, creds.client);
1665 pkrb5_free_principal(ctx, creds.server);
1668 #endif /* COMMENT */
1670 code = KFW_AFS_klog(ctx, cc, "afs", cell, (char *)realm, 0,NULL);
1671 if ( IsDebuggerPresent() ) {
1673 sprintf(message,"KFW_AFS_klog() returns: %d\n",code);
1674 OutputDebugString(message);
1679 pkrb5_cc_close(ctx, cc);
1683 pkrb5_free_principal(ctx, princ);
1687 pkrb5_free_principal(ctx, service);
1691 KFW_AFS_update_cell_princ_map(ctx, cell, principals[count], code ? FALSE : TRUE);
1692 free(principals[count]);
1696 code = -1; // we did not renew the tokens
1699 pkrb5_free_context(ctx);
1700 return (code ? FALSE : TRUE);
1705 KFW_AFS_renew_tokens_for_all_cells(void)
1707 struct cell_principal_map * next = cell_princ_map;
1709 if ( IsDebuggerPresent() )
1710 OutputDebugString("KFW_AFS_renew_tokens_for_all()\n");
1715 for ( ; next ; next = next->next ) {
1717 KFW_AFS_renew_token_for_cell(next->cell);
1723 KFW_renew(krb5_context alt_ctx, krb5_ccache alt_cc)
1725 krb5_error_code code = 0;
1726 krb5_context ctx = 0;
1728 krb5_principal me = 0;
1729 krb5_principal server = 0;
1730 krb5_creds my_creds;
1731 krb5_data *realm = 0;
1733 if (!pkrb5_init_context)
1736 memset(&my_creds, 0, sizeof(krb5_creds));
1741 code = pkrb5_init_context(&ctx);
1742 if (code) goto cleanup;
1748 code = pkrb5_cc_default(ctx, &cc);
1749 if (code) goto cleanup;
1752 code = pkrb5_cc_get_principal(ctx, cc, &me);
1753 if (code) goto cleanup;
1755 realm = krb5_princ_realm(ctx, me);
1757 code = pkrb5_build_principal_ext(ctx, &server,
1758 realm->length,realm->data,
1759 KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME,
1760 realm->length,realm->data,
1765 if ( IsDebuggerPresent() ) {
1766 char * cname, *sname;
1767 pkrb5_unparse_name(ctx, me, &cname);
1768 pkrb5_unparse_name(ctx, server, &sname);
1769 OutputDebugString("Renewing credential for client \"");
1770 OutputDebugString(cname);
1771 OutputDebugString("\" and service \"");
1772 OutputDebugString(sname);
1773 OutputDebugString("\"\n");
1774 pkrb5_free_unparsed_name(ctx,cname);
1775 pkrb5_free_unparsed_name(ctx,sname);
1778 my_creds.client = me;
1779 my_creds.server = server;
1781 code = pkrb5_get_renewed_creds(ctx, &my_creds, me, cc, NULL);
1783 if ( IsDebuggerPresent() ) {
1785 sprintf(message,"krb5_get_renewed_creds() failed: %d\n",code);
1786 OutputDebugString(message);
1791 code = pkrb5_cc_initialize(ctx, cc, me);
1793 if ( IsDebuggerPresent() ) {
1795 sprintf(message,"krb5_cc_initialize() failed: %d\n",code);
1796 OutputDebugString(message);
1801 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1803 if ( IsDebuggerPresent() ) {
1805 sprintf(message,"krb5_cc_store_cred() failed: %d\n",code);
1806 OutputDebugString(message);
1812 if (my_creds.client == me)
1813 my_creds.client = 0;
1814 if (my_creds.server == server)
1815 my_creds.server = 0;
1816 pkrb5_free_cred_contents(ctx, &my_creds);
1818 pkrb5_free_principal(ctx, me);
1820 pkrb5_free_principal(ctx, server);
1821 if (cc && (cc != alt_cc))
1822 pkrb5_cc_close(ctx, cc);
1823 if (ctx && (ctx != alt_ctx))
1824 pkrb5_free_context(ctx);
1829 KFW_kinit( krb5_context alt_ctx,
1832 char *principal_name,
1834 krb5_deltat lifetime,
1837 krb5_deltat renew_life,
1842 krb5_error_code code = 0;
1843 krb5_context ctx = 0;
1845 krb5_principal me = 0;
1847 krb5_creds my_creds;
1848 krb5_get_init_creds_opt options;
1849 krb5_address ** addrs = NULL;
1850 int i = 0, addr_count = 0;
1852 if (!pkrb5_init_context)
1855 pkrb5_get_init_creds_opt_init(&options);
1856 memset(&my_creds, 0, sizeof(my_creds));
1864 code = pkrb5_init_context(&ctx);
1865 if (code) goto cleanup;
1871 code = pkrb5_cc_default(ctx, &cc);
1872 if (code) goto cleanup;
1875 code = pkrb5_parse_name(ctx, principal_name, &me);
1879 code = pkrb5_unparse_name(ctx, me, &name);
1884 lifetime = pLeash_get_default_lifetime();
1891 pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
1892 pkrb5_get_init_creds_opt_set_forwardable(&options,
1893 forwardable ? 1 : 0);
1894 pkrb5_get_init_creds_opt_set_proxiable(&options,
1896 pkrb5_get_init_creds_opt_set_renew_life(&options,
1899 pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
1903 // we are going to add the public IP address specified by the user
1904 // to the list provided by the operating system
1905 krb5_address ** local_addrs=NULL;
1908 pkrb5_os_localaddr(ctx, &local_addrs);
1909 while ( local_addrs[i++] );
1912 addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
1914 pkrb5_free_addresses(ctx, local_addrs);
1917 memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
1919 while ( local_addrs[i] ) {
1920 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
1921 if (addrs[i] == NULL) {
1922 pkrb5_free_addresses(ctx, local_addrs);
1926 addrs[i]->magic = local_addrs[i]->magic;
1927 addrs[i]->addrtype = local_addrs[i]->addrtype;
1928 addrs[i]->length = local_addrs[i]->length;
1929 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
1930 if (!addrs[i]->contents) {
1931 pkrb5_free_addresses(ctx, local_addrs);
1935 memcpy(addrs[i]->contents,local_addrs[i]->contents,
1936 local_addrs[i]->length); /* safe */
1939 pkrb5_free_addresses(ctx, local_addrs);
1941 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
1942 if (addrs[i] == NULL)
1945 addrs[i]->magic = KV5M_ADDRESS;
1946 addrs[i]->addrtype = AF_INET;
1947 addrs[i]->length = 4;
1948 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
1949 if (!addrs[i]->contents)
1952 netIPAddr = htonl(publicIP);
1953 memcpy(addrs[i]->contents,&netIPAddr,4);
1955 pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
1960 code = pkrb5_get_init_creds_password(ctx,
1963 password, // password
1964 KRB5_prompter, // prompter
1965 hParent, // prompter data
1972 code = pkrb5_cc_initialize(ctx, cc, me);
1976 code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
1982 for ( i=0;i<addr_count;i++ ) {
1984 if ( addrs[i]->contents )
1985 free(addrs[i]->contents);
1990 if (my_creds.client == me)
1991 my_creds.client = 0;
1992 pkrb5_free_cred_contents(ctx, &my_creds);
1994 pkrb5_free_unparsed_name(ctx, name);
1996 pkrb5_free_principal(ctx, me);
1997 if (cc && (cc != alt_cc))
1998 pkrb5_cc_close(ctx, cc);
1999 if (ctx && (ctx != alt_ctx))
2000 pkrb5_free_context(ctx);
2006 KFW_kdestroy(krb5_context alt_ctx, krb5_ccache alt_cc)
2010 krb5_error_code code;
2012 if (!pkrb5_init_context)
2021 code = pkrb5_init_context(&ctx);
2022 if (code) goto cleanup;
2028 code = pkrb5_cc_default(ctx, &cc);
2029 if (code) goto cleanup;
2032 code = pkrb5_cc_destroy(ctx, cc);
2033 if ( !code ) cc = 0;
2036 if (cc && (cc != alt_cc))
2037 pkrb5_cc_close(ctx, cc);
2038 if (ctx && (ctx != alt_ctx))
2039 pkrb5_free_context(ctx);
2047 GetSecurityLogonSessionData(PSECURITY_LOGON_SESSION_DATA * ppSessionData)
2049 NTSTATUS Status = 0;
2051 TOKEN_STATISTICS Stats;
2057 *ppSessionData = NULL;
2059 Success = OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &TokenHandle );
2063 Success = GetTokenInformation( TokenHandle, TokenStatistics, &Stats, sizeof(TOKEN_STATISTICS), &ReqLen );
2064 CloseHandle( TokenHandle );
2068 Status = pLsaGetLogonSessionData( &Stats.AuthenticationId, ppSessionData );
2069 if ( FAILED(Status) || !ppSessionData )
2076 // MSLSA_IsKerberosLogon() does not validate whether or not there are valid tickets in the
2077 // cache. It validates whether or not it is reasonable to assume that if we
2078 // attempted to retrieve valid tickets we could do so. Microsoft does not
2079 // automatically renew expired tickets. Therefore, the cache could contain
2080 // expired or invalid tickets. Microsoft also caches the user's password
2081 // and will use it to retrieve new TGTs if the cache is empty and tickets
2085 MSLSA_IsKerberosLogon(VOID)
2087 PSECURITY_LOGON_SESSION_DATA pSessionData = NULL;
2088 BOOL Success = FALSE;
2090 if ( GetSecurityLogonSessionData(&pSessionData) ) {
2091 if ( pSessionData->AuthenticationPackage.Buffer ) {
2097 usBuffer = (pSessionData->AuthenticationPackage).Buffer;
2098 usLength = (pSessionData->AuthenticationPackage).Length;
2101 lstrcpynW (buffer, usBuffer, usLength);
2102 lstrcatW (buffer,L"");
2103 if ( !lstrcmpW(L"Kerberos",buffer) )
2107 pLsaFreeReturnBuffer(pSessionData);
2111 #endif /* USE_MS2MIT */
2113 static BOOL CALLBACK
2114 MultiInputDialogProc( HWND hDialog, UINT message, WPARAM wParam, LPARAM lParam)
2118 switch ( message ) {
2120 if ( GetDlgCtrlID((HWND) wParam) != ID_MID_TEXT )
2122 SetFocus(GetDlgItem( hDialog, ID_MID_TEXT));
2125 for ( i=0; i < mid_cnt ; i++ ) {
2126 if (mid_tb[i].echo == 0)
2127 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, 32, 0);
2128 else if (mid_tb[i].echo == 2)
2129 SendDlgItemMessage(hDialog, ID_MID_TEXT+i, EM_SETPASSWORDCHAR, '*', 0);
2134 switch ( LOWORD(wParam) ) {
2136 for ( i=0; i < mid_cnt ; i++ ) {
2137 if ( !GetDlgItemText(hDialog, ID_MID_TEXT+i, mid_tb[i].buf, mid_tb[i].len) )
2138 *mid_tb[i].buf = '\0';
2142 EndDialog(hDialog, LOWORD(wParam));
2150 lpwAlign( LPWORD lpIn )
2154 ul = (ULONG_PTR) lpIn;
2158 return (LPWORD) ul;;
2162 * dialog widths are measured in 1/4 character widths
2163 * dialog height are measured in 1/8 character heights
2167 MultiInputDialog( HINSTANCE hinst, HWND hwndOwner,
2168 char * ptext[], int numlines, int width,
2169 int tb_cnt, struct textField * tb)
2173 LPDLGITEMTEMPLATE lpdit;
2179 hgbl = GlobalAlloc(GMEM_ZEROINIT, 4096);
2186 lpdt = (LPDLGTEMPLATE)GlobalLock(hgbl);
2188 // Define a dialog box.
2190 lpdt->style = WS_POPUP | WS_BORDER | WS_SYSMENU
2191 | DS_MODALFRAME | WS_CAPTION | DS_CENTER
2192 | DS_SETFOREGROUND | DS_3DLOOK
2193 | DS_SETFONT | DS_FIXEDSYS | DS_NOFAILCREATE;
2194 lpdt->cdit = numlines + (2 * tb_cnt) + 2; // number of controls
2197 lpdt->cx = 20 + width * 4;
2198 lpdt->cy = 20 + (numlines + tb_cnt + 4) * 14;
2200 lpw = (LPWORD) (lpdt + 1);
2201 *lpw++ = 0; // no menu
2202 *lpw++ = 0; // predefined dialog box class (by default)
2204 lpwsz = (LPWSTR) lpw;
2205 nchar = MultiByteToWideChar (CP_ACP, 0, "", -1, lpwsz, 128);
2207 *lpw++ = 8; // font size (points)
2208 lpwsz = (LPWSTR) lpw;
2209 nchar = MultiByteToWideChar (CP_ACP, 0, "MS Shell Dlg",
2213 //-----------------------
2214 // Define an OK button.
2215 //-----------------------
2216 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2217 lpdit = (LPDLGITEMTEMPLATE) lpw;
2218 lpdit->style = WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_TABSTOP | WS_BORDER;
2219 lpdit->dwExtendedStyle = 0;
2220 lpdit->x = (lpdt->cx - 14)/4 - 20;
2221 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2224 lpdit->id = IDOK; // OK button identifier
2226 lpw = (LPWORD) (lpdit + 1);
2228 *lpw++ = 0x0080; // button class
2230 lpwsz = (LPWSTR) lpw;
2231 nchar = MultiByteToWideChar (CP_ACP, 0, "OK", -1, lpwsz, 50);
2233 *lpw++ = 0; // no creation data
2235 //-----------------------
2236 // Define an Cancel button.
2237 //-----------------------
2238 lpw = lpwAlign (lpw); // align DLGITEMTEMPLATE on DWORD boundary
2239 lpdit = (LPDLGITEMTEMPLATE) lpw;
2240 lpdit->style = WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | WS_TABSTOP | WS_BORDER;
2241 lpdit->dwExtendedStyle = 0;
2242 lpdit->x = (lpdt->cx - 14)*3/4 - 20;
2243 lpdit->y = 10 + (numlines + tb_cnt + 2) * 14;
2246 lpdit->id = IDCANCEL; // CANCEL button identifier
2248 lpw = (LPWORD) (lpdit + 1);
2250 *lpw++ = 0x0080; // button class
2252 lpwsz = (LPWSTR) lpw;
2253 nchar = MultiByteToWideChar (CP_ACP, 0, "Cancel", -1, lpwsz, 50);
2255 *lpw++ = 0; // no creation data
2257 /* Add controls for preface data */
2258 for ( i=0; i<numlines; i++) {
2259 /*-----------------------
2260 * Define a static text control.
2261 *-----------------------*/
2262 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2263 lpdit = (LPDLGITEMTEMPLATE) lpw;
2264 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2265 lpdit->dwExtendedStyle = 0;
2267 lpdit->y = 10 + i * 14;
2268 lpdit->cx = (short)strlen(ptext[i]) * 4 + 10;
2270 lpdit->id = ID_TEXT + i; // text identifier
2272 lpw = (LPWORD) (lpdit + 1);
2274 *lpw++ = 0x0082; // static class
2276 lpwsz = (LPWSTR) lpw;
2277 nchar = MultiByteToWideChar (CP_ACP, 0, ptext[i],
2278 -1, lpwsz, 2*width);
2280 *lpw++ = 0; // no creation data
2283 for ( i=0, pwid = 0; i<tb_cnt; i++) {
2284 int len = (int)strlen(tb[i].label);
2289 for ( i=0; i<tb_cnt; i++) {
2291 /*-----------------------
2292 * Define a static text control.
2293 *-----------------------*/
2294 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2295 lpdit = (LPDLGITEMTEMPLATE) lpw;
2296 lpdit->style = WS_CHILD | WS_VISIBLE | SS_LEFT;
2297 lpdit->dwExtendedStyle = 0;
2299 lpdit->y = 10 + (numlines + i + 1) * 14;
2300 lpdit->cx = pwid * 4;
2302 lpdit->id = ID_TEXT + numlines + i; // text identifier
2304 lpw = (LPWORD) (lpdit + 1);
2306 *lpw++ = 0x0082; // static class
2308 lpwsz = (LPWSTR) lpw;
2309 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].label ? tb[i].label : "",
2312 *lpw++ = 0; // no creation data
2314 /*-----------------------
2315 * Define an edit control.
2316 *-----------------------*/
2317 lpw = lpwAlign (lpw); /* align DLGITEMTEMPLATE on DWORD boundary */
2318 lpdit = (LPDLGITEMTEMPLATE) lpw;
2319 lpdit->style = WS_CHILD | WS_VISIBLE | ES_LEFT | WS_TABSTOP | WS_BORDER | (tb[i].echo == 1 ? 0L : ES_PASSWORD);
2320 lpdit->dwExtendedStyle = 0;
2321 lpdit->x = 10 + (pwid + 1) * 4;
2322 lpdit->y = 10 + (numlines + i + 1) * 14;
2323 lpdit->cx = (width - (pwid + 1)) * 4;
2325 lpdit->id = ID_MID_TEXT + i; // identifier
2327 lpw = (LPWORD) (lpdit + 1);
2329 *lpw++ = 0x0081; // edit class
2331 lpwsz = (LPWSTR) lpw;
2332 nchar = MultiByteToWideChar (CP_ACP, 0, tb[i].def ? tb[i].def : "",
2335 *lpw++ = 0; // no creation data
2339 ret = DialogBoxIndirect(hinst, (LPDLGTEMPLATE) hgbl,
2340 hwndOwner, (DLGPROC) MultiInputDialogProc);
2344 case 0: /* Timeout */
2352 sprintf(buf,"DialogBoxIndirect() failed: %d",GetLastError());
2353 MessageBox(hwndOwner,
2356 MB_OK | MB_ICONINFORMATION | MB_TASKMODAL);
2363 multi_field_dialog(HWND hParent, char * preface, int n, struct textField tb[])
2365 HINSTANCE hInst = 0;
2369 char * plines[16], *p = preface ? preface : "";
2372 for ( i=0; i<16; i++ )
2375 while (*p && numlines < 16) {
2376 plines[numlines++] = p;
2377 for ( ;*p && *p != '\r' && *p != '\n'; p++ );
2378 if ( *p == '\r' && *(p+1) == '\n' ) {
2381 } else if ( *p == '\n' ) {
2384 if ( strlen(plines[numlines-1]) > maxwidth )
2385 maxwidth = (int)strlen(plines[numlines-1]);
2388 for ( i=0;i<n;i++ ) {
2389 len = (int)strlen(tb[i].label) + 1 + (tb[i].len > 40 ? 40 : tb[i].len);
2390 if ( maxwidth < len )
2394 return(MultiInputDialog(hInst, hParent, plines, numlines, maxwidth, n, tb)?1:0);
2397 static krb5_error_code KRB5_CALLCONV
2398 KRB5_prompter( krb5_context context,
2403 krb5_prompt prompts[])
2405 krb5_error_code errcode = 0;
2407 struct textField * tb = NULL;
2408 int len = 0, blen=0, nlen=0;
2409 HWND hParent = (HWND)data;
2412 nlen = (int)strlen(name)+2;
2415 blen = (int)strlen(banner)+2;
2417 tb = (struct textField *) malloc(sizeof(struct textField) * num_prompts);
2420 memset(tb,0,sizeof(struct textField) * num_prompts);
2421 for ( i=0; i < num_prompts; i++ ) {
2422 tb[i].buf = prompts[i].reply->data;
2423 tb[i].len = prompts[i].reply->length;
2424 tb[i].label = prompts[i].prompt;
2426 tb[i].echo = (prompts[i].hidden ? 2 : 1);
2429 ok = multi_field_dialog(hParent,(char *)banner,num_prompts,tb);
2431 for ( i=0; i < num_prompts; i++ )
2432 prompts[i].reply->length = (unsigned int)strlen(prompts[i].reply->data);
2440 for (i = 0; i < num_prompts; i++) {
2441 memset(prompts[i].reply->data, 0, prompts[i].reply->length);
2448 KFW_AFS_wait_for_service_start(void)
2453 CurrentState = SERVICE_START_PENDING;
2454 memset(HostName, '\0', sizeof(HostName));
2455 gethostname(HostName, sizeof(HostName));
2457 while (CurrentState != SERVICE_RUNNING || CurrentState != SERVICE_STOPPED)
2459 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2461 if ( IsDebuggerPresent() ) {
2462 switch ( CurrentState ) {
2463 case SERVICE_STOPPED:
2464 OutputDebugString("SERVICE_STOPPED\n");
2466 case SERVICE_START_PENDING:
2467 OutputDebugString("SERVICE_START_PENDING\n");
2469 case SERVICE_STOP_PENDING:
2470 OutputDebugString("SERVICE_STOP_PENDING\n");
2472 case SERVICE_RUNNING:
2473 OutputDebugString("SERVICE_RUNNING\n");
2475 case SERVICE_CONTINUE_PENDING:
2476 OutputDebugString("SERVICE_CONTINUE_PENDING\n");
2478 case SERVICE_PAUSE_PENDING:
2479 OutputDebugString("SERVICE_PAUSE_PENDING\n");
2481 case SERVICE_PAUSED:
2482 OutputDebugString("SERVICE_PAUSED\n");
2485 OutputDebugString("UNKNOWN Service State\n");
2488 if (CurrentState == SERVICE_STOPPED)
2490 if (CurrentState == SERVICE_RUNNING)
2506 memset(HostName, '\0', sizeof(HostName));
2507 gethostname(HostName, sizeof(HostName));
2508 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR)
2510 if (CurrentState != SERVICE_RUNNING)
2513 rc = ktc_ForgetAllTokens();
2519 #define ALLOW_REGISTER 1
2521 ViceIDToUsername(char *username,
2522 char *realm_of_user,
2523 char *realm_of_cell,
2525 struct ktc_principal *aclient,
2526 struct ktc_principal *aserver,
2527 struct ktc_token *atoken)
2529 static char lastcell[MAXCELLCHARS+1] = { 0 };
2530 static char confname[512] = { 0 };
2531 #ifdef AFS_ID_TO_NAME
2532 char username_copy[BUFSIZ];
2533 #endif /* AFS_ID_TO_NAME */
2534 long viceId; /* AFS uid of user */
2536 #ifdef ALLOW_REGISTER
2538 #endif /* ALLOW_REGISTER */
2540 if (confname[0] == '\0') {
2541 strncpy(confname, AFSDIR_CLIENT_ETC_DIRPATH, sizeof(confname));
2542 confname[sizeof(confname) - 2] = '\0';
2545 strcpy(lastcell, aserver->cell);
2547 if (!pr_Initialize (0, confname, aserver->cell)) {
2548 char sname[PR_MAXNAMELEN];
2549 strncpy(sname, username, PR_MAXNAMELEN);
2550 sname[PR_MAXNAMELEN-1] = '\0';
2551 status = pr_SNameToId (sname, &viceId);
2555 * This is a crock, but it is Transarc's crock, so
2556 * we have to play along in order to get the
2557 * functionality. The way the afs id is stored is
2558 * as a string in the username field of the token.
2559 * Contrary to what you may think by looking at
2560 * the code for tokens, this hack (AFS ID %d) will
2561 * not work if you change %d to something else.
2565 * This code is taken from cklog -- it lets people
2566 * automatically register with the ptserver in foreign cells
2569 #ifdef ALLOW_REGISTER
2571 if (viceId != ANONYMOUSID) {
2572 #else /* ALLOW_REGISTER */
2573 if ((status == 0) && (viceId != ANONYMOUSID))
2574 #endif /* ALLOW_REGISTER */
2576 #ifdef AFS_ID_TO_NAME
2577 strncpy(username_copy, username, BUFSIZ);
2578 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2579 #endif /* AFS_ID_TO_NAME */
2581 #ifdef ALLOW_REGISTER
2582 } else if (strcmp(realm_of_user, realm_of_cell) != 0) {
2584 strncpy(aclient->name, username, MAXKTCNAMELEN - 1);
2585 strcpy(aclient->instance, "");
2586 strncpy(aclient->cell, realm_of_user, MAXKTCREALMLEN - 1);
2587 if (status = ktc_SetToken(aserver, atoken, aclient, 0))
2589 if (status = pr_Initialize(1L, confname, aserver->cell))
2591 if (status = pr_CreateUser(username, &id))
2593 #ifdef AFS_ID_TO_NAME
2594 strncpy(username_copy, username, BUFSIZ);
2595 snprintf (username, BUFSIZ, "%s (AFS ID %d)", username_copy, (int) viceId);
2596 #endif /* AFS_ID_TO_NAME */
2599 #endif /* ALLOW_REGISTER */
2606 krb5_context alt_ctx,
2611 int lifetime, /* unused parameter */
2619 #endif /* USE_KRB4 */
2620 struct ktc_principal aserver;
2621 struct ktc_principal aclient;
2622 char realm_of_user[REALM_SZ]; /* Kerberos realm of user */
2623 char realm_of_cell[REALM_SZ]; /* Kerberos realm of cell */
2624 char local_cell[MAXCELLCHARS+1];
2625 char Dmycell[MAXCELLCHARS+1];
2626 struct ktc_token atoken;
2627 struct ktc_token btoken;
2628 struct afsconf_cell ak_cellconfig; /* General information about the cell */
2629 char RealmName[128];
2631 char ServiceName[128];
2635 krb5_context ctx = 0;
2638 krb5_creds * k5creds = 0;
2639 krb5_error_code code;
2640 krb5_principal client_principal = 0;
2645 memset(HostName, '\0', sizeof(HostName));
2646 gethostname(HostName, sizeof(HostName));
2647 if (GetServiceStatus(HostName, TRANSARCAFSDAEMON, &CurrentState) != NOERROR) {
2648 if ( IsDebuggerPresent() )
2649 OutputDebugString("Unable to retrieve AFSD Service Status\n");
2652 if (CurrentState != SERVICE_RUNNING) {
2653 if ( IsDebuggerPresent() )
2654 OutputDebugString("AFSD Service NOT RUNNING\n");
2658 if (!pkrb5_init_context)
2661 memset(RealmName, '\0', sizeof(RealmName));
2662 memset(CellName, '\0', sizeof(CellName));
2663 memset(ServiceName, '\0', sizeof(ServiceName));
2664 memset(realm_of_user, '\0', sizeof(realm_of_user));
2665 memset(realm_of_cell, '\0', sizeof(realm_of_cell));
2666 if (cell && cell[0])
2667 strcpy(Dmycell, cell);
2669 memset(Dmycell, '\0', sizeof(Dmycell));
2671 // NULL or empty cell returns information on local cell
2672 if (rc = KFW_AFS_get_cellconfig(Dmycell, &ak_cellconfig, local_cell))
2674 // KFW_AFS_error(rc, "get_cellconfig()");
2681 code = pkrb5_init_context(&ctx);
2682 if (code) goto cleanup;
2688 code = pkrb5_cc_default(ctx, &cc);
2689 if (code) goto skip_krb5_init;
2692 memset((char *)&increds, 0, sizeof(increds));
2694 code = pkrb5_cc_get_principal(ctx, cc, &client_principal);
2696 if ( code == KRB5_CC_NOTFOUND && IsDebuggerPresent() )
2698 OutputDebugString("Principal Not Found for ccache\n");
2700 goto skip_krb5_init;
2703 /* look for client principals which cannot be distinguished
2704 * from Kerberos 4 multi-component principal names
2706 k5data = krb5_princ_component(ctx,client_principal,0);
2707 for ( i=0; i<k5data->length; i++ ) {
2708 if ( k5data->data[i] == '.' )
2711 if (i != k5data->length)
2713 OutputDebugString("Illegal Principal name contains dot in first component\n");
2714 rc = KRB5KRB_ERR_GENERIC;
2718 i = krb5_princ_realm(ctx, client_principal)->length;
2721 strncpy(realm_of_user,krb5_princ_realm(ctx, client_principal)->data,i);
2722 realm_of_user[i] = 0;
2727 if ( !try_krb5 || !realm_of_user[0] ) {
2728 if ((rc = (*pkrb_get_tf_realm)((*ptkt_string)(), realm_of_user)) != KSUCCESS)
2737 strcpy(realm_of_cell, afs_realm_of_cell(ctx, &ak_cellconfig));
2739 if (strlen(service) == 0)
2740 strcpy(ServiceName, "afs");
2742 strcpy(ServiceName, service);
2744 if (strlen(cell) == 0)
2745 strcpy(CellName, local_cell);
2747 strcpy(CellName, cell);
2749 if (strlen(realm) == 0)
2750 strcpy(RealmName, realm_of_cell);
2752 strcpy(RealmName, realm);
2754 memset(&creds, '\0', sizeof(creds));
2759 /* First try service/cell@REALM */
2760 if (code = pkrb5_build_principal(ctx, &increds.server,
2761 (int)strlen(RealmName),
2770 increds.client = client_principal;
2771 increds.times.endtime = 0;
2772 /* Ask for DES since that is what V4 understands */
2773 increds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
2776 if ( IsDebuggerPresent() ) {
2777 char * cname, *sname;
2778 pkrb5_unparse_name(ctx, increds.client, &cname);
2779 pkrb5_unparse_name(ctx, increds.server, &sname);
2780 OutputDebugString("Getting tickets for \"");
2781 OutputDebugString(cname);
2782 OutputDebugString("\" and service \"");
2783 OutputDebugString(sname);
2784 OutputDebugString("\"\n");
2785 pkrb5_free_unparsed_name(ctx,cname);
2786 pkrb5_free_unparsed_name(ctx,sname);
2789 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 /* Or service@REALM */
2794 pkrb5_free_principal(ctx,increds.server);
2796 code = pkrb5_build_principal(ctx, &increds.server,
2797 (int)strlen(RealmName),
2802 if ( IsDebuggerPresent() ) {
2803 char * cname, *sname;
2804 pkrb5_unparse_name(ctx, increds.client, &cname);
2805 pkrb5_unparse_name(ctx, increds.server, &sname);
2806 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2807 OutputDebugString("Trying again: getting tickets for \"");
2808 OutputDebugString(cname);
2809 OutputDebugString("\" and service \"");
2810 OutputDebugString(sname);
2811 OutputDebugString("\"\n");
2812 pkrb5_free_unparsed_name(ctx,cname);
2813 pkrb5_free_unparsed_name(ctx,sname);
2817 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2820 if ((code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2821 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2822 code == KRB5KRB_AP_ERR_MSG_TYPE) &&
2823 strcmp(RealmName, realm_of_cell)) {
2824 /* Or service/cell@REALM_OF_CELL */
2825 strcpy(RealmName, realm_of_cell);
2826 pkrb5_free_principal(ctx,increds.server);
2828 code = pkrb5_build_principal(ctx, &increds.server,
2829 (int)strlen(RealmName),
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);
2853 if (code == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN ||
2854 code == KRB5KRB_ERR_GENERIC /* heimdal */ ||
2855 code == KRB5KRB_AP_ERR_MSG_TYPE) {
2856 /* Or service@REALM_OF_CELL */
2857 pkrb5_free_principal(ctx,increds.server);
2859 code = pkrb5_build_principal(ctx, &increds.server,
2860 (int)strlen(RealmName),
2865 if ( IsDebuggerPresent() ) {
2866 char * cname, *sname;
2867 pkrb5_unparse_name(ctx, increds.client, &cname);
2868 pkrb5_unparse_name(ctx, increds.server, &sname);
2869 OutputDebugString("krb5_get_credentials() returned Service Principal Unknown\n");
2870 OutputDebugString("Trying again: getting tickets for \"");
2871 OutputDebugString(cname);
2872 OutputDebugString("\" and service \"");
2873 OutputDebugString(sname);
2874 OutputDebugString("\"\n");
2875 pkrb5_free_unparsed_name(ctx,cname);
2876 pkrb5_free_unparsed_name(ctx,sname);
2880 code = pkrb5_get_credentials(ctx, 0, cc, &increds, &k5creds);
2885 if ( IsDebuggerPresent() ) {
2887 sprintf(message,"krb5_get_credentials returns: %d\n",code);
2888 OutputDebugString(message);
2894 /* This code inserts the entire K5 ticket into the token
2895 * No need to perform a krb524 translation which is
2896 * commented out in the code below
2898 if (KFW_use_krb524() ||
2899 k5creds->ticket.length > MAXKTCTICKETLEN)
2902 memset(&aserver, '\0', sizeof(aserver));
2903 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
2904 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
2906 memset(&atoken, '\0', sizeof(atoken));
2907 atoken.kvno = RXKAD_TKT_TYPE_KERBEROS_V5;
2908 atoken.startTime = k5creds->times.starttime;
2909 atoken.endTime = k5creds->times.endtime;
2910 memcpy(&atoken.sessionKey, k5creds->keyblock.contents, k5creds->keyblock.length);
2911 atoken.ticketLen = k5creds->ticket.length;
2912 memcpy(atoken.ticket, k5creds->ticket.data, atoken.ticketLen);
2915 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
2916 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
2917 if ( rc == KTC_NOCM && retry < 20 ) {
2920 goto retry_gettoken5;
2925 if (atoken.kvno == btoken.kvno &&
2926 atoken.ticketLen == btoken.ticketLen &&
2927 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
2928 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
2930 /* Success - Nothing to do */
2934 // * Reset the "aclient" structure before we call ktc_SetToken.
2935 // * This structure was first set by the ktc_GetToken call when
2936 // * we were comparing whether identical tokens already existed.
2938 len = min(k5creds->client->data[0].length,MAXKTCNAMELEN - 1);
2939 strncpy(aclient.name, k5creds->client->data[0].data, len);
2940 aclient.name[len] = '\0';
2942 if ( k5creds->client->length > 1 ) {
2944 strcat(aclient.name, ".");
2945 p = aclient.name + strlen(aclient.name);
2946 len = min(k5creds->client->data[1].length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
2947 strncpy(p, k5creds->client->data[1].data, len);
2950 aclient.instance[0] = '\0';
2952 strcpy(aclient.cell, realm_of_cell);
2954 len = min(k5creds->client->realm.length,(int)strlen(realm_of_cell));
2955 /* For Khimaira, always append the realm name */
2956 if ( 1 /* strncmp(realm_of_cell, k5creds->client->realm.data, len) */ ) {
2958 strcat(aclient.name, "@");
2959 p = aclient.name + strlen(aclient.name);
2960 len = min(k5creds->client->realm.length,MAXKTCNAMELEN - (int)strlen(aclient.name) - 1);
2961 strncpy(p, k5creds->client->realm.data, len);
2965 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
2966 &aclient, &aserver, &atoken);
2969 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
2970 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
2972 aclient.smbname[0] = '\0';
2975 rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0));
2977 goto cleanup; /* We have successfully inserted the token */
2980 /* Otherwise, the ticket could have been too large so try to
2981 * convert using the krb524d running with the KDC
2983 code = pkrb524_convert_creds_kdc(ctx, k5creds, &creds);
2984 pkrb5_free_creds(ctx, k5creds);
2986 if ( IsDebuggerPresent() ) {
2988 sprintf(message,"krb524_convert_creds_kdc returns: %d\n",code);
2989 OutputDebugString(message);
2997 code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds);
2998 if (code == NO_TKT_FIL) {
2999 // if the problem is that we have no krb4 tickets
3000 // do not attempt to continue
3003 if (code != KSUCCESS)
3004 code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds);
3006 if (code != KSUCCESS)
3008 if ((code = (*pkrb_mk_req)(&ticket, ServiceName, CellName, RealmName, 0)) == KSUCCESS)
3010 if ((code = (*pkrb_get_cred)(ServiceName, CellName, RealmName, &creds)) != KSUCCESS)
3015 else if ((code = (*pkrb_mk_req)(&ticket, ServiceName, "", RealmName, 0)) == KSUCCESS)
3017 if ((code = (*pkrb_get_cred)(ServiceName, "", RealmName, &creds)) != KSUCCESS)
3032 memset(&aserver, '\0', sizeof(aserver));
3033 strncpy(aserver.name, ServiceName, MAXKTCNAMELEN - 1);
3034 strncpy(aserver.cell, CellName, MAXKTCREALMLEN - 1);
3036 memset(&atoken, '\0', sizeof(atoken));
3037 atoken.kvno = creds.kvno;
3038 atoken.startTime = creds.issue_date;
3039 atoken.endTime = creds.issue_date + life_to_time(0,creds.lifetime);
3040 memcpy(&atoken.sessionKey, creds.session, 8);
3041 atoken.ticketLen = creds.ticket_st.length;
3042 memcpy(atoken.ticket, creds.ticket_st.dat, atoken.ticketLen);
3045 rc = ktc_GetToken(&aserver, &btoken, sizeof(btoken), &aclient);
3046 if (rc != 0 && rc != KTC_NOENT && rc != KTC_NOCELL) {
3047 if ( rc == KTC_NOCM && retry < 20 ) {
3050 goto retry_gettoken;
3052 KFW_AFS_error(rc, "ktc_GetToken()");
3057 if (atoken.kvno == btoken.kvno &&
3058 atoken.ticketLen == btoken.ticketLen &&
3059 !memcmp(&atoken.sessionKey, &btoken.sessionKey, sizeof(atoken.sessionKey)) &&
3060 !memcmp(atoken.ticket, btoken.ticket, atoken.ticketLen))
3065 // * Reset the "aclient" structure before we call ktc_SetToken.
3066 // * This structure was first set by the ktc_GetToken call when
3067 // * we were comparing whether identical tokens already existed.
3069 strncpy(aclient.name, creds.pname, MAXKTCNAMELEN - 1);
3072 strncat(aclient.name, ".", MAXKTCNAMELEN - 1);
3073 strncat(aclient.name, creds.pinst, MAXKTCNAMELEN - 1);
3075 strcpy(aclient.instance, "");
3077 if ( strcmp(realm_of_cell, creds.realm) )
3079 strncat(aclient.name, "@", MAXKTCNAMELEN - 1);
3080 strncpy(aclient.name, creds.realm, MAXKTCREALMLEN - 1);
3082 aclient.name[MAXKTCREALMLEN-1] = '\0';
3084 strcpy(aclient.cell, CellName);
3086 ViceIDToUsername(aclient.name, realm_of_user, realm_of_cell, CellName,
3087 &aclient, &aserver, &atoken);
3090 strncpy(aclient.smbname, smbname, sizeof(aclient.smbname));
3091 aclient.smbname[sizeof(aclient.smbname)-1] = '\0';
3093 aclient.smbname[0] = '\0';
3096 if (rc = ktc_SetToken(&aserver, &atoken, &aclient, (aclient.smbname[0]?AFS_SETTOK_LOGON:0)))
3098 KFW_AFS_error(rc, "ktc_SetToken()");
3104 if (client_principal)
3105 pkrb5_free_principal(ctx,client_principal);
3106 /* increds.client == client_principal */
3108 pkrb5_free_principal(ctx,increds.server);
3109 if (cc && (cc != alt_cc))
3110 pkrb5_cc_close(ctx, cc);
3111 if (ctx && (ctx != alt_ctx))
3112 pkrb5_free_context(ctx);
3114 return(rc? rc : code);
3117 /**************************************/
3118 /* afs_realm_of_cell(): */
3119 /**************************************/
3121 afs_realm_of_cell(krb5_context ctx, struct afsconf_cell *cellconfig)
3123 static char krbrlm[REALM_SZ+1]="";
3124 char ** realmlist=NULL;
3130 r = pkrb5_get_host_realm(ctx, cellconfig->hostName[0], &realmlist);
3131 if ( !r && realmlist && realmlist[0] ) {
3132 strcpy(krbrlm, realmlist[0]);
3133 pkrb5_free_host_realm(ctx, realmlist);
3139 char *t = cellconfig->name;
3144 if (islower(c)) c=toupper(c);
3152 /**************************************/
3153 /* KFW_AFS_get_cellconfig(): */
3154 /**************************************/
3156 KFW_AFS_get_cellconfig(char *cell, struct afsconf_cell *cellconfig, char *local_cell)
3159 char newcell[MAXCELLCHARS+1];
3161 local_cell[0] = (char)0;
3162 memset(cellconfig, 0, sizeof(*cellconfig));
3164 /* WIN32: cm_GetRootCellName(local_cell) - NOTE: no way to get max chars */
3165 if (rc = cm_GetRootCellName(local_cell))
3170 if (strlen(cell) == 0)
3171 strcpy(cell, local_cell);
3173 /* WIN32: cm_SearchCellFile(cell, pcallback, pdata) */
3174 strcpy(cellconfig->name, cell);
3176 rc = cm_SearchCellFile(cell, newcell, get_cellconfig_callback, (void*)cellconfig);
3177 #ifdef AFS_AFSDB_ENV
3180 rc = cm_SearchCellByDNS(cell, newcell, &ttl, get_cellconfig_callback, (void*)cellconfig);
3186 /**************************************/
3187 /* get_cellconfig_callback(): */
3188 /**************************************/
3190 get_cellconfig_callback(void *cellconfig, struct sockaddr_in *addrp, char *namep)
3192 struct afsconf_cell *cc = (struct afsconf_cell *)cellconfig;
3194 cc->hostAddr[cc->numServers] = *addrp;
3195 strcpy(cc->hostName[cc->numServers], namep);
3201 /**************************************/
3202 /* KFW_AFS_error(): */
3203 /**************************************/
3205 KFW_AFS_error(LONG rc, LPCSTR FailedFunctionName)
3208 const char *errText;
3210 // Using AFS defines as error messages for now, until Transarc
3211 // gets back to me with "string" translations of each of these
3213 if (rc == KTC_ERROR)
3214 errText = "KTC_ERROR";
3215 else if (rc == KTC_TOOBIG)
3216 errText = "KTC_TOOBIG";
3217 else if (rc == KTC_INVAL)
3218 errText = "KTC_INVAL";
3219 else if (rc == KTC_NOENT)
3220 errText = "KTC_NOENT";
3221 else if (rc == KTC_PIOCTLFAIL)
3222 errText = "KTC_PIOCTLFAIL";
3223 else if (rc == KTC_NOPIOCTL)
3224 errText = "KTC_NOPIOCTL";
3225 else if (rc == KTC_NOCELL)
3226 errText = "KTC_NOCELL";
3227 else if (rc == KTC_NOCM)
3228 errText = "KTC_NOCM: The service, Transarc AFS Daemon, most likely is not started!";
3230 errText = "Unknown error!";
3232 sprintf(message, "%s (0x%x)\n(%s failed)", errText, rc, FailedFunctionName);
3234 if ( IsDebuggerPresent() ) {
3235 OutputDebugString(message);
3236 OutputDebugString("\n");
3238 MessageBox(NULL, message, "AFS", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND);
3244 LPSTR lpszMachineName,
3245 LPSTR lpszServiceName,
3246 DWORD *lpdwCurrentState)
3249 SC_HANDLE schSCManager = NULL;
3250 SC_HANDLE schService = NULL;
3251 DWORD fdwDesiredAccess = 0;
3252 SERVICE_STATUS ssServiceStatus = {0};
3255 *lpdwCurrentState = 0;
3257 fdwDesiredAccess = GENERIC_READ;
3259 schSCManager = OpenSCManager(lpszMachineName,
3263 if(schSCManager == NULL)
3265 hr = GetLastError();
3269 schService = OpenService(schSCManager,
3273 if(schService == NULL)
3275 hr = GetLastError();
3279 fRet = QueryServiceStatus(schService,
3284 hr = GetLastError();
3288 *lpdwCurrentState = ssServiceStatus.dwCurrentState;
3292 CloseServiceHandle(schService);
3293 CloseServiceHandle(schSCManager);
3306 for (n = 0; fi[n].func_ptr_var; n++)
3307 *(fi[n].func_ptr_var) = 0;
3308 if (h) FreeLibrary(h);
3313 const char* dll_name,
3315 HINSTANCE* ph, // [out, optional] - DLL handle
3316 int* pindex, // [out, optional] - index of last func loaded (-1 if none)
3317 int cleanup, // cleanup function pointers and unload on error
3318 int go_on, // continue loading even if some functions cannot be loaded
3319 int silent // do not pop-up a system dialog if DLL cannot be loaded
3328 if (pindex) *pindex = -1;
3330 for (n = 0; fi[n].func_ptr_var; n++)
3331 *(fi[n].func_ptr_var) = 0;
3334 em = SetErrorMode(SEM_FAILCRITICALERRORS);
3335 h = LoadLibrary(dll_name);
3343 for (i = 0; (go_on || !error) && (i < n); i++)
3345 void* p = (void*)GetProcAddress(h, fi[i].func_name);
3351 *(fi[i].func_ptr_var) = p;
3354 if (pindex) *pindex = last_i;
3355 if (error && cleanup && !go_on) {
3356 for (i = 0; i < n; i++) {
3357 *(fi[i].func_ptr_var) = 0;
3363 if (error) return 0;
3367 BOOL KFW_probe_kdc(struct afsconf_cell * cellconfig)
3369 krb5_context ctx = 0;
3371 krb5_error_code code;
3373 const char * realm = 0;
3374 krb5_principal principal = 0;
3376 char password[PROBE_PASSWORD_LEN+1];
3377 BOOL serverReachable = 0;
3379 if (!pkrb5_init_context)
3382 code = pkrb5_init_context(&ctx);
3383 if (code) goto cleanup;
3386 realm = afs_realm_of_cell(ctx, cellconfig); // do not free
3388 code = pkrb5_build_principal(ctx, &principal, (int)strlen(realm),
3389 realm, PROBE_USERNAME, NULL, NULL);
3390 if ( code ) goto cleanup;
3392 code = KFW_get_ccache(ctx, principal, &cc);
3393 if ( code ) goto cleanup;
3395 code = pkrb5_unparse_name(ctx, principal, &pname);
3396 if ( code ) goto cleanup;
3398 pwdata.data = password;
3399 pwdata.length = PROBE_PASSWORD_LEN;
3400 code = pkrb5_c_random_make_octets(ctx, &pwdata);
3403 for ( i=0 ; i<PROBE_PASSWORD_LEN ; i++ )
3406 password[PROBE_PASSWORD_LEN] = '\0';
3408 code = KFW_kinit(NULL, NULL, HWND_DESKTOP,
3418 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
3419 case KRB5KDC_ERR_CLIENT_REVOKED:
3420 case KRB5KDC_ERR_CLIENT_NOTYET:
3421 case KRB5KDC_ERR_PREAUTH_FAILED:
3422 case KRB5KDC_ERR_PREAUTH_REQUIRED:
3423 case KRB5KDC_ERR_PADATA_TYPE_NOSUPP:
3424 serverReachable = TRUE;
3427 serverReachable = FALSE;
3432 pkrb5_free_unparsed_name(ctx,pname);
3434 pkrb5_free_principal(ctx,principal);
3436 pkrb5_cc_close(ctx,cc);
3438 pkrb5_free_context(ctx);
3440 return serverReachable;
3444 KFW_AFS_get_lsa_principal(char * szUser, DWORD *dwSize)
3446 krb5_context ctx = 0;
3447 krb5_error_code code;
3448 krb5_ccache mslsa_ccache=0;
3449 krb5_principal princ = 0;
3453 if (!KFW_is_available())
3456 if (code = pkrb5_init_context(&ctx))
3459 if (code = pkrb5_cc_resolve(ctx, "MSLSA:", &mslsa_ccache))
3462 if (code = pkrb5_cc_get_principal(ctx, mslsa_ccache, &princ))
3465 if (code = pkrb5_unparse_name(ctx, princ, &pname))
3468 if ( strlen(pname) < *dwSize ) {
3469 strncpy(szUser, pname, *dwSize);
3470 szUser[*dwSize-1] = '\0';
3473 *dwSize = (DWORD)strlen(pname);
3477 pkrb5_free_unparsed_name(ctx, pname);
3480 pkrb5_free_principal(ctx, princ);
3483 pkrb5_cc_close(ctx, mslsa_ccache);
3486 pkrb5_free_context(ctx);
3491 KFW_AFS_copy_cache_to_system_file(char * user, char * szLogonId)
3495 char cachename[264] = "FILE:";
3496 krb5_context ctx = 0;
3497 krb5_error_code code;
3498 krb5_principal princ = 0;
3500 krb5_ccache ncc = 0;
3502 if (!pkrb5_init_context)
3505 count = GetEnvironmentVariable("TEMP", filename, sizeof(filename));
3506 if ( count > sizeof(filename) || count == 0 ) {
3507 GetWindowsDirectory(filename, sizeof(filename));
3510 if ( strlen(filename) + strlen(szLogonId) + 2 > sizeof(filename) )
3513 strcat(filename, "\\");
3514 strcat(filename, szLogonId);
3516 strcat(cachename, filename);
3518 DeleteFile(filename);
3520 code = pkrb5_init_context(&ctx);
3523 code = pkrb5_parse_name(ctx, user, &princ);
3524 if (code) goto cleanup;
3526 code = KFW_get_ccache(ctx, princ, &cc);
3527 if (code) goto cleanup;
3529 code = pkrb5_cc_resolve(ctx, cachename, &ncc);
3530 if (code) goto cleanup;
3532 code = pkrb5_cc_initialize(ctx, ncc, princ);
3533 if (code) goto cleanup;
3535 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3539 pkrb5_cc_close(ctx, cc);
3543 pkrb5_cc_close(ctx, ncc);
3547 pkrb5_free_principal(ctx, princ);
3552 pkrb5_free_context(ctx);
3556 KFW_AFS_copy_system_file_to_default_cache(char * filename)
3558 char cachename[264] = "FILE:";
3559 krb5_context ctx = 0;
3560 krb5_error_code code;
3561 krb5_principal princ = 0;
3563 krb5_ccache ncc = 0;
3566 if (!pkrb5_init_context)
3569 if ( strlen(filename) + 6 > sizeof(cachename) )
3572 strcat(cachename, filename);
3574 code = pkrb5_init_context(&ctx);
3577 code = pkrb5_cc_resolve(ctx, cachename, &cc);
3578 if (code) goto cleanup;
3580 code = pkrb5_cc_get_principal(ctx, cc, &princ);
3582 code = pkrb5_cc_default(ctx, &ncc);
3584 code = pkrb5_cc_initialize(ctx, ncc, princ);
3587 code = pkrb5_cc_copy_creds(ctx,cc,ncc);
3590 pkrb5_cc_close(ctx, ncc);
3594 retval=0; /* success */
3598 pkrb5_cc_close(ctx, cc);
3602 DeleteFile(filename);
3605 pkrb5_free_principal(ctx, princ);
3610 pkrb5_free_context(ctx);