xref: /freebsd/crypto/krb5/src/windows/kfwlogon/kfwcommon.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /*
2 Copyright 2005,2006 by the Massachusetts Institute of Technology
3 Copyright 2007 by Secure Endpoints Inc.
4 
5 All rights reserved.
6 
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the name of the Massachusetts
12 Institute of Technology (M.I.T.) not be used in advertising or publicity
13 pertaining to distribution of the software without specific, written
14 prior permission.
15 
16 M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
18 M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
19 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22 SOFTWARE.
23 
24 */
25 
26 #include "kfwlogon.h"
27 #include <windows.h>
28 #include <Aclapi.h>
29 #include <userenv.h>
30 #include <Sddl.h>
31 
32 #include <io.h>
33 #include <sys/stat.h>
34 #include <sys/types.h>
35 #include <fcntl.h>
36 
37 #include <winsock2.h>
38 #include <lm.h>
39 #include <nb30.h>
40 
41 #include <errno.h>
42 #include <malloc.h>
43 
44 
45 /* Function Pointer Declarations for Delayed Loading */
46 // CCAPI
47 DECL_FUNC_PTR(cc_initialize);
48 DECL_FUNC_PTR(cc_shutdown);
49 DECL_FUNC_PTR(cc_get_NC_info);
50 DECL_FUNC_PTR(cc_free_NC_info);
51 
52 // leash functions
53 DECL_FUNC_PTR(Leash_get_default_lifetime);
54 DECL_FUNC_PTR(Leash_get_default_forwardable);
55 DECL_FUNC_PTR(Leash_get_default_renew_till);
56 DECL_FUNC_PTR(Leash_get_default_noaddresses);
57 DECL_FUNC_PTR(Leash_get_default_proxiable);
58 DECL_FUNC_PTR(Leash_get_default_publicip);
59 DECL_FUNC_PTR(Leash_get_default_life_min);
60 DECL_FUNC_PTR(Leash_get_default_life_max);
61 DECL_FUNC_PTR(Leash_get_default_renew_min);
62 DECL_FUNC_PTR(Leash_get_default_renew_max);
63 DECL_FUNC_PTR(Leash_get_default_renewable);
64 DECL_FUNC_PTR(Leash_get_default_mslsa_import);
65 
66 // krb5 functions
67 DECL_FUNC_PTR(krb5_change_password);
68 DECL_FUNC_PTR(krb5_get_init_creds_opt_init);
69 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);
70 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);
71 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);
72 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);
73 DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);
74 DECL_FUNC_PTR(krb5_get_init_creds_password);
75 DECL_FUNC_PTR(krb5_build_principal_ext);
76 DECL_FUNC_PTR(krb5_cc_get_name);
77 DECL_FUNC_PTR(krb5_cc_resolve);
78 DECL_FUNC_PTR(krb5_cc_default);
79 DECL_FUNC_PTR(krb5_cc_default_name);
80 DECL_FUNC_PTR(krb5_cc_set_default_name);
81 DECL_FUNC_PTR(krb5_cc_initialize);
82 DECL_FUNC_PTR(krb5_cc_destroy);
83 DECL_FUNC_PTR(krb5_cc_close);
84 DECL_FUNC_PTR(krb5_cc_store_cred);
85 DECL_FUNC_PTR(krb5_cc_copy_creds);
86 DECL_FUNC_PTR(krb5_cc_retrieve_cred);
87 DECL_FUNC_PTR(krb5_cc_get_principal);
88 DECL_FUNC_PTR(krb5_cc_start_seq_get);
89 DECL_FUNC_PTR(krb5_cc_next_cred);
90 DECL_FUNC_PTR(krb5_cc_end_seq_get);
91 DECL_FUNC_PTR(krb5_cc_remove_cred);
92 DECL_FUNC_PTR(krb5_cc_set_flags);
93 DECL_FUNC_PTR(krb5_cc_get_type);
94 DECL_FUNC_PTR(krb5_free_context);
95 DECL_FUNC_PTR(krb5_free_cred_contents);
96 DECL_FUNC_PTR(krb5_free_principal);
97 DECL_FUNC_PTR(krb5_get_in_tkt_with_password);
98 DECL_FUNC_PTR(krb5_init_context);
99 DECL_FUNC_PTR(krb5_parse_name);
100 DECL_FUNC_PTR(krb5_timeofday);
101 DECL_FUNC_PTR(krb5_timestamp_to_sfstring);
102 DECL_FUNC_PTR(krb5_unparse_name);
103 DECL_FUNC_PTR(krb5_get_credentials);
104 DECL_FUNC_PTR(krb5_mk_req);
105 DECL_FUNC_PTR(krb5_sname_to_principal);
106 DECL_FUNC_PTR(krb5_get_credentials_renew);
107 DECL_FUNC_PTR(krb5_free_data);
108 DECL_FUNC_PTR(krb5_free_data_contents);
109 DECL_FUNC_PTR(krb5_free_unparsed_name);
110 DECL_FUNC_PTR(krb5_os_localaddr);
111 DECL_FUNC_PTR(krb5_copy_keyblock_contents);
112 DECL_FUNC_PTR(krb5_copy_data);
113 DECL_FUNC_PTR(krb5_free_creds);
114 DECL_FUNC_PTR(krb5_build_principal);
115 DECL_FUNC_PTR(krb5_get_renewed_creds);
116 DECL_FUNC_PTR(krb5_get_default_config_files);
117 DECL_FUNC_PTR(krb5_free_config_files);
118 DECL_FUNC_PTR(krb5_get_default_realm);
119 DECL_FUNC_PTR(krb5_free_default_realm);
120 DECL_FUNC_PTR(krb5_free_ticket);
121 DECL_FUNC_PTR(krb5_decode_ticket);
122 DECL_FUNC_PTR(krb5_get_host_realm);
123 DECL_FUNC_PTR(krb5_free_host_realm);
124 DECL_FUNC_PTR(krb5_free_addresses);
125 DECL_FUNC_PTR(krb5_c_random_make_octets);
126 
127 // ComErr functions
128 DECL_FUNC_PTR(com_err);
129 DECL_FUNC_PTR(error_message);
130 
131 // Profile functions
132 DECL_FUNC_PTR(profile_init);
133 DECL_FUNC_PTR(profile_release);
134 DECL_FUNC_PTR(profile_get_subsection_names);
135 DECL_FUNC_PTR(profile_free_list);
136 DECL_FUNC_PTR(profile_get_string);
137 DECL_FUNC_PTR(profile_release_string);
138 
139 // Service functions
140 DECL_FUNC_PTR(OpenSCManagerA);
141 DECL_FUNC_PTR(OpenServiceA);
142 DECL_FUNC_PTR(QueryServiceStatus);
143 DECL_FUNC_PTR(CloseServiceHandle);
144 DECL_FUNC_PTR(LsaNtStatusToWinError);
145 
146 // LSA Functions
147 DECL_FUNC_PTR(LsaConnectUntrusted);
148 DECL_FUNC_PTR(LsaLookupAuthenticationPackage);
149 DECL_FUNC_PTR(LsaCallAuthenticationPackage);
150 DECL_FUNC_PTR(LsaFreeReturnBuffer);
151 DECL_FUNC_PTR(LsaGetLogonSessionData);
152 
153 // CCAPI
154 FUNC_INFO ccapi_fi[] = {
155     MAKE_FUNC_INFO(cc_initialize),
156     MAKE_FUNC_INFO(cc_shutdown),
157     MAKE_FUNC_INFO(cc_get_NC_info),
158     MAKE_FUNC_INFO(cc_free_NC_info),
159     END_FUNC_INFO
160 };
161 
162 FUNC_INFO leash_fi[] = {
163     MAKE_FUNC_INFO(Leash_get_default_lifetime),
164     MAKE_FUNC_INFO(Leash_get_default_renew_till),
165     MAKE_FUNC_INFO(Leash_get_default_forwardable),
166     MAKE_FUNC_INFO(Leash_get_default_noaddresses),
167     MAKE_FUNC_INFO(Leash_get_default_proxiable),
168     MAKE_FUNC_INFO(Leash_get_default_publicip),
169     MAKE_FUNC_INFO(Leash_get_default_life_min),
170     MAKE_FUNC_INFO(Leash_get_default_life_max),
171     MAKE_FUNC_INFO(Leash_get_default_renew_min),
172     MAKE_FUNC_INFO(Leash_get_default_renew_max),
173     MAKE_FUNC_INFO(Leash_get_default_renewable),
174     END_FUNC_INFO
175 };
176 
177 FUNC_INFO leash_opt_fi[] = {
178     MAKE_FUNC_INFO(Leash_get_default_mslsa_import),
179     END_FUNC_INFO
180 };
181 
182 FUNC_INFO k5_fi[] = {
183     MAKE_FUNC_INFO(krb5_change_password),
184     MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),
185     MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),
186     MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),
187     MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),
188     MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),
189     MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),
190     MAKE_FUNC_INFO(krb5_get_init_creds_password),
191     MAKE_FUNC_INFO(krb5_build_principal_ext),
192     MAKE_FUNC_INFO(krb5_cc_get_name),
193     MAKE_FUNC_INFO(krb5_cc_resolve),
194     MAKE_FUNC_INFO(krb5_cc_default),
195     MAKE_FUNC_INFO(krb5_cc_default_name),
196     MAKE_FUNC_INFO(krb5_cc_set_default_name),
197     MAKE_FUNC_INFO(krb5_cc_initialize),
198     MAKE_FUNC_INFO(krb5_cc_destroy),
199     MAKE_FUNC_INFO(krb5_cc_close),
200     MAKE_FUNC_INFO(krb5_cc_copy_creds),
201     MAKE_FUNC_INFO(krb5_cc_store_cred),
202     MAKE_FUNC_INFO(krb5_cc_retrieve_cred),
203     MAKE_FUNC_INFO(krb5_cc_get_principal),
204     MAKE_FUNC_INFO(krb5_cc_start_seq_get),
205     MAKE_FUNC_INFO(krb5_cc_next_cred),
206     MAKE_FUNC_INFO(krb5_cc_end_seq_get),
207     MAKE_FUNC_INFO(krb5_cc_remove_cred),
208     MAKE_FUNC_INFO(krb5_cc_set_flags),
209     MAKE_FUNC_INFO(krb5_cc_get_type),
210     MAKE_FUNC_INFO(krb5_free_context),
211     MAKE_FUNC_INFO(krb5_free_cred_contents),
212     MAKE_FUNC_INFO(krb5_free_principal),
213     MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),
214     MAKE_FUNC_INFO(krb5_init_context),
215     MAKE_FUNC_INFO(krb5_parse_name),
216     MAKE_FUNC_INFO(krb5_timeofday),
217     MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),
218     MAKE_FUNC_INFO(krb5_unparse_name),
219     MAKE_FUNC_INFO(krb5_get_credentials),
220     MAKE_FUNC_INFO(krb5_mk_req),
221     MAKE_FUNC_INFO(krb5_sname_to_principal),
222     MAKE_FUNC_INFO(krb5_get_credentials_renew),
223     MAKE_FUNC_INFO(krb5_free_data),
224     MAKE_FUNC_INFO(krb5_free_data_contents),
225     MAKE_FUNC_INFO(krb5_free_unparsed_name),
226     MAKE_FUNC_INFO(krb5_os_localaddr),
227     MAKE_FUNC_INFO(krb5_copy_keyblock_contents),
228     MAKE_FUNC_INFO(krb5_copy_data),
229     MAKE_FUNC_INFO(krb5_free_creds),
230     MAKE_FUNC_INFO(krb5_build_principal),
231     MAKE_FUNC_INFO(krb5_get_renewed_creds),
232     MAKE_FUNC_INFO(krb5_free_addresses),
233     MAKE_FUNC_INFO(krb5_get_default_config_files),
234     MAKE_FUNC_INFO(krb5_free_config_files),
235     MAKE_FUNC_INFO(krb5_get_default_realm),
236     MAKE_FUNC_INFO(krb5_free_default_realm),
237     MAKE_FUNC_INFO(krb5_free_ticket),
238     MAKE_FUNC_INFO(krb5_decode_ticket),
239     MAKE_FUNC_INFO(krb5_get_host_realm),
240     MAKE_FUNC_INFO(krb5_free_host_realm),
241     MAKE_FUNC_INFO(krb5_free_addresses),
242     MAKE_FUNC_INFO(krb5_c_random_make_octets),
243     END_FUNC_INFO
244 };
245 
246 FUNC_INFO profile_fi[] = {
247         MAKE_FUNC_INFO(profile_init),
248         MAKE_FUNC_INFO(profile_release),
249         MAKE_FUNC_INFO(profile_get_subsection_names),
250         MAKE_FUNC_INFO(profile_free_list),
251         MAKE_FUNC_INFO(profile_get_string),
252         MAKE_FUNC_INFO(profile_release_string),
253         END_FUNC_INFO
254 };
255 
256 FUNC_INFO ce_fi[] = {
257     MAKE_FUNC_INFO(com_err),
258     MAKE_FUNC_INFO(error_message),
259     END_FUNC_INFO
260 };
261 
262 FUNC_INFO service_fi[] = {
263     MAKE_FUNC_INFO(OpenSCManagerA),
264     MAKE_FUNC_INFO(OpenServiceA),
265     MAKE_FUNC_INFO(QueryServiceStatus),
266     MAKE_FUNC_INFO(CloseServiceHandle),
267     MAKE_FUNC_INFO(LsaNtStatusToWinError),
268     END_FUNC_INFO
269 };
270 
271 FUNC_INFO lsa_fi[] = {
272     MAKE_FUNC_INFO(LsaConnectUntrusted),
273     MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),
274     MAKE_FUNC_INFO(LsaCallAuthenticationPackage),
275     MAKE_FUNC_INFO(LsaFreeReturnBuffer),
276     MAKE_FUNC_INFO(LsaGetLogonSessionData),
277     END_FUNC_INFO
278 };
279 
280 /* Static Declarations */
281 static int       inited = 0;
282 static HINSTANCE hKrb5 = 0;
283 static HINSTANCE hKrb524 = 0;
284 static HINSTANCE hSecur32 = 0;
285 static HINSTANCE hAdvApi32 = 0;
286 static HINSTANCE hComErr = 0;
287 static HINSTANCE hService = 0;
288 static HINSTANCE hProfile = 0;
289 static HINSTANCE hLeash = 0;
290 static HINSTANCE hLeashOpt = 0;
291 static HINSTANCE hCCAPI = 0;
292 
293 static DWORD TraceOption = 0;
294 static HANDLE hDLL;
295 
IsDebugLogging(void)296 BOOL IsDebugLogging(void)
297 {
298     DWORD LSPsize;
299     HKEY NPKey;
300     DWORD dwDebug = FALSE;
301 
302     if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
303 		     "System\\CurrentControlSet\\Services\\MIT Kerberos\\NetworkProvider",
304 		     0, KEY_QUERY_VALUE, &NPKey) == ERROR_SUCCESS)
305     {
306 	LSPsize=sizeof(dwDebug);
307 	if (RegQueryValueEx(NPKey, "Debug", NULL, NULL, (LPBYTE)&dwDebug, &LSPsize) != ERROR_SUCCESS)
308 	{
309 	    dwDebug = FALSE;
310 	}
311 	RegCloseKey (NPKey);
312     }
313 
314     return(dwDebug ? TRUE : FALSE);
315 }
316 
DebugEvent0(char * a)317 void DebugEvent0(char *a)
318 {
319     HANDLE h; char *ptbuf[1];
320 
321     if (IsDebugLogging()) {
322 	h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
323 	if (h) {
324             ptbuf[0] = a;
325             ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
326             DeregisterEventSource(h);
327         }
328     }
329 }
330 
331 #define MAXBUF_ 512
DebugEvent(char * b,...)332 void DebugEvent(char *b,...)
333 {
334     HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
335     va_list marker;
336 
337     if (IsDebugLogging()) {
338 	h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);
339         if (h) {
340             va_start(marker,b);
341             StringCbVPrintf(buf, MAXBUF_+1,b,marker);
342             buf[MAXBUF_] = '\0';
343             ptbuf[0] = buf;
344             ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
345             DeregisterEventSource(h);
346             va_end(marker);
347         }
348     }
349 }
350 
351 static HANDLE hInitMutex = NULL;
352 static BOOL bInit = FALSE;
353 
354 /* KFW_initialize cannot be called from DllEntryPoint */
355 void
KFW_initialize(void)356 KFW_initialize(void)
357 {
358     static int inited = 0;
359 
360     if ( !inited ) {
361         char mutexName[MAX_PATH];
362         HANDLE hMutex = NULL;
363 
364         sprintf(mutexName, "AFS KFW Init pid=%d", getpid());
365 
366         hMutex = CreateMutex( NULL, TRUE, mutexName );
367         if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
368             if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {
369                 return;
370             }
371         }
372         if ( !inited ) {
373             inited = 1;
374             LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);
375             LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);
376             LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);
377             LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);
378             LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);
379             LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);
380             LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);
381             LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);
382         }
383         ReleaseMutex(hMutex);
384         CloseHandle(hMutex);
385     }
386 }
387 
388 void
KFW_cleanup(void)389 KFW_cleanup(void)
390 {
391     if (hLeashOpt)
392         FreeLibrary(hLeashOpt);
393     if (hCCAPI)
394         FreeLibrary(hCCAPI);
395     if (hLeash)
396         FreeLibrary(hLeash);
397     if (hKrb524)
398         FreeLibrary(hKrb524);
399     if (hSecur32)
400         FreeLibrary(hSecur32);
401     if (hService)
402         FreeLibrary(hService);
403     if (hComErr)
404         FreeLibrary(hComErr);
405     if (hProfile)
406         FreeLibrary(hProfile);
407     if (hKrb5)
408         FreeLibrary(hKrb5);
409 }
410 
411 
412 int
KFW_is_available(void)413 KFW_is_available(void)
414 {
415     KFW_initialize();
416     if ( hKrb5 && hComErr && hService &&
417 #ifdef USE_MS2MIT
418          hSecur32 &&
419 #endif /* USE_MS2MIT */
420          hProfile && hLeash && hCCAPI )
421         return TRUE;
422 
423     return FALSE;
424 }
425 
426 /* Given a principal return an existing ccache or create one and return */
427 int
KFW_get_ccache(krb5_context alt_ctx,krb5_principal principal,krb5_ccache * cc)428 KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)
429 {
430     krb5_context ctx;
431     char * pname = 0;
432     char * ccname = 0;
433     krb5_error_code code;
434 
435     if (!pkrb5_init_context)
436         return 0;
437 
438     if ( alt_ctx ) {
439         ctx = alt_ctx;
440     } else {
441         code = pkrb5_init_context(&ctx);
442         if (code) goto cleanup;
443     }
444 
445     if ( principal ) {
446         code = pkrb5_unparse_name(ctx, principal, &pname);
447         if (code) goto cleanup;
448 
449 	ccname = (char *)malloc(strlen(pname) + 5);
450 	sprintf(ccname,"API:%s",pname);
451 
452 	DebugEvent0(ccname);
453 	code = pkrb5_cc_resolve(ctx, ccname, cc);
454     } else {
455         code = pkrb5_cc_default(ctx, cc);
456         if (code) goto cleanup;
457     }
458 
459   cleanup:
460     if (ccname)
461         free(ccname);
462     if (pname)
463         pkrb5_free_unparsed_name(ctx,pname);
464     if (ctx && (ctx != alt_ctx))
465         pkrb5_free_context(ctx);
466     return(code);
467 }
468 
469 
470 int
KFW_kinit(krb5_context alt_ctx,krb5_ccache alt_cc,HWND hParent,char * principal_name,char * password,krb5_deltat lifetime,DWORD forwardable,DWORD proxiable,krb5_deltat renew_life,DWORD addressless,DWORD publicIP)471 KFW_kinit( krb5_context alt_ctx,
472             krb5_ccache  alt_cc,
473             HWND hParent,
474             char *principal_name,
475             char *password,
476             krb5_deltat lifetime,
477             DWORD                       forwardable,
478             DWORD                       proxiable,
479             krb5_deltat                 renew_life,
480             DWORD                       addressless,
481             DWORD                       publicIP
482             )
483 {
484     krb5_error_code		        code = 0;
485     krb5_context		        ctx = 0;
486     krb5_ccache			        cc = 0;
487     krb5_principal		        me = 0;
488     char*                       name = 0;
489     krb5_creds			        my_creds;
490     krb5_get_init_creds_opt     options;
491     krb5_address **             addrs = NULL;
492     int                         i = 0, addr_count = 0;
493 
494     if (!pkrb5_init_context)
495         return 0;
496 
497     pkrb5_get_init_creds_opt_init(&options);
498     memset(&my_creds, 0, sizeof(my_creds));
499 
500     if (alt_ctx)
501     {
502         ctx = alt_ctx;
503     }
504     else
505     {
506         code = pkrb5_init_context(&ctx);
507         if (code) goto cleanup;
508     }
509 
510     if ( alt_cc ) {
511         cc = alt_cc;
512     } else {
513         code = pkrb5_cc_default(ctx, &cc);
514         if (code) goto cleanup;
515     }
516 
517     code = pkrb5_parse_name(ctx, principal_name, &me);
518     if (code)
519 	goto cleanup;
520 
521     code = pkrb5_unparse_name(ctx, me, &name);
522     if (code)
523 	goto cleanup;
524 
525     if (lifetime == 0)
526         lifetime = pLeash_get_default_lifetime();
527     lifetime *= 60;
528 
529     if (renew_life > 0)
530 	renew_life *= 60;
531 
532     if (lifetime)
533         pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);
534 	pkrb5_get_init_creds_opt_set_forwardable(&options,
535                                                  forwardable ? 1 : 0);
536 	pkrb5_get_init_creds_opt_set_proxiable(&options,
537                                                proxiable ? 1 : 0);
538 	pkrb5_get_init_creds_opt_set_renew_life(&options,
539                                                renew_life);
540     if (addressless)
541         pkrb5_get_init_creds_opt_set_address_list(&options,NULL);
542     else {
543 	if (publicIP)
544         {
545             // we are going to add the public IP address specified by the user
546             // to the list provided by the operating system
547             krb5_address ** local_addrs=NULL;
548             DWORD           netIPAddr;
549 
550             pkrb5_os_localaddr(ctx, &local_addrs);
551             while ( local_addrs[i++] );
552             addr_count = i + 1;
553 
554             addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));
555             if ( !addrs ) {
556                 pkrb5_free_addresses(ctx, local_addrs);
557                 goto cleanup;
558             }
559             memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));
560             i = 0;
561             while ( local_addrs[i] ) {
562                 addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
563                 if (addrs[i] == NULL) {
564                     pkrb5_free_addresses(ctx, local_addrs);
565                     goto cleanup;
566                 }
567 
568                 addrs[i]->magic = local_addrs[i]->magic;
569                 addrs[i]->addrtype = local_addrs[i]->addrtype;
570                 addrs[i]->length = local_addrs[i]->length;
571                 addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
572                 if (!addrs[i]->contents) {
573                     pkrb5_free_addresses(ctx, local_addrs);
574                     goto cleanup;
575                 }
576 
577                 memcpy(addrs[i]->contents,local_addrs[i]->contents,
578                         local_addrs[i]->length);        /* safe */
579                 i++;
580             }
581             pkrb5_free_addresses(ctx, local_addrs);
582 
583             addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));
584             if (addrs[i] == NULL)
585                 goto cleanup;
586 
587             addrs[i]->magic = KV5M_ADDRESS;
588             addrs[i]->addrtype = AF_INET;
589             addrs[i]->length = 4;
590             addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);
591             if (!addrs[i]->contents)
592                 goto cleanup;
593 
594             netIPAddr = htonl(publicIP);
595             memcpy(addrs[i]->contents,&netIPAddr,4);
596 
597             pkrb5_get_init_creds_opt_set_address_list(&options,addrs);
598 
599         }
600     }
601 
602     code = pkrb5_get_init_creds_password(ctx,
603                                        &my_creds,
604                                        me,
605                                        password, // password
606                                        NULL,     // no prompter
607                                        hParent, // prompter data
608                                        0, // start time
609                                        0, // service name
610                                        &options);
611     if (code)
612 	goto cleanup;
613 
614     code = pkrb5_cc_initialize(ctx, cc, me);
615     if (code)
616 	goto cleanup;
617 
618     code = pkrb5_cc_store_cred(ctx, cc, &my_creds);
619     if (code)
620 	goto cleanup;
621 
622  cleanup:
623     if ( addrs ) {
624         for ( i=0;i<addr_count;i++ ) {
625             if ( addrs[i] ) {
626                 if ( addrs[i]->contents )
627                     free(addrs[i]->contents);
628                 free(addrs[i]);
629             }
630         }
631     }
632     if (my_creds.client == me)
633 	my_creds.client = 0;
634     pkrb5_free_cred_contents(ctx, &my_creds);
635     if (name)
636         pkrb5_free_unparsed_name(ctx, name);
637     if (me)
638         pkrb5_free_principal(ctx, me);
639     if (cc && (cc != alt_cc))
640         pkrb5_cc_close(ctx, cc);
641     if (ctx && (ctx != alt_ctx))
642         pkrb5_free_context(ctx);
643     return(code);
644 }
645 
646 
647 int
KFW_get_cred(char * username,char * password,int lifetime,char ** reasonP)648 KFW_get_cred( char * username,
649 	      char * password,
650 	      int lifetime,
651 	      char ** reasonP )
652 {
653     krb5_context ctx = 0;
654     krb5_ccache cc = 0;
655     char * realm = 0;
656     krb5_principal principal = 0;
657     char * pname = 0;
658     krb5_error_code code;
659 
660     if (!pkrb5_init_context || !username || !password || !password[0])
661         return 0;
662 
663     DebugEvent0(username);
664 
665     code = pkrb5_init_context(&ctx);
666     if ( code ) goto cleanup;
667 
668     code = pkrb5_get_default_realm(ctx, &realm);
669 
670     if (realm) {
671         pname = malloc(strlen(username) + strlen(realm) + 2);
672 	if (!pname)
673 	    goto cleanup;
674 	strcpy(pname, username);
675 	strcat(pname, "@");
676 	strcat(pname, realm);
677     } else {
678 	goto cleanup;
679     }
680 
681     DebugEvent0(realm);
682     DebugEvent0(pname);
683 
684     code = pkrb5_parse_name(ctx, pname, &principal);
685     if ( code ) goto cleanup;
686 
687     DebugEvent0("parsed name");
688     code = KFW_get_ccache(ctx, principal, &cc);
689     if ( code ) goto cleanup;
690 
691     DebugEvent0("got ccache");
692 
693     if ( lifetime == 0 )
694         lifetime = pLeash_get_default_lifetime();
695 
696     DebugEvent0("got lifetime");
697 
698     code = KFW_kinit( ctx, cc, HWND_DESKTOP,
699 		      pname,
700 		      password,
701 		      lifetime,
702 		      pLeash_get_default_forwardable(),
703 		      pLeash_get_default_proxiable(),
704 		      pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,
705 		      pLeash_get_default_noaddresses(),
706 		      pLeash_get_default_publicip());
707     DebugEvent0("kinit returned");
708     if ( code ) goto cleanup;
709 
710   cleanup:
711     if ( pname )
712         free(pname);
713     if ( realm )
714 	pkrb5_free_default_realm(ctx, realm);
715     if ( cc )
716         pkrb5_cc_close(ctx, cc);
717 
718     if ( code && reasonP ) {
719         *reasonP = (char *)perror_message(code);
720     }
721     return(code);
722 }
723 
KFW_set_ccache_dacl(char * filename,HANDLE hUserToken)724 int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken)
725 {
726     // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
727     PSID pSystemSID = NULL;
728     DWORD SystemSIDlength = 0, UserSIDlength = 0;
729     PACL ccacheACL = NULL;
730     DWORD ccacheACLlength = 0;
731     PTOKEN_USER pTokenUser = NULL;
732     DWORD retLen;
733     DWORD gle;
734     int ret = 0;
735 
736     if (!filename) {
737 	DebugEvent0("KFW_set_ccache_dacl - invalid parms");
738 	return 1;
739     }
740 
741     DebugEvent0("KFW_set_ccache_dacl");
742 
743     /* Get System SID */
744     if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
745 	DebugEvent("KFW_set_ccache_dacl - ConvertStringSidToSid GLE = 0x%x", GetLastError());
746 	ret = 1;
747 	goto cleanup;
748     }
749 
750     /* Create ACL */
751     SystemSIDlength = GetLengthSid(pSystemSID);
752     ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
753         + SystemSIDlength - sizeof(DWORD);
754 
755     if (hUserToken) {
756 	if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))
757 	{
758 	    if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {
759 		pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);
760 
761 		if (!GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen))
762 		{
763 		    DebugEvent("GetTokenInformation failed: GLE = %lX", GetLastError());
764 		}
765 	    }
766 	}
767 
768 	if (pTokenUser) {
769 	    UserSIDlength = GetLengthSid(pTokenUser->User.Sid);
770 
771 	    ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
772 		- sizeof(DWORD);
773 	}
774     }
775 
776     ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
777     if (!ccacheACL) {
778 	DebugEvent("KFW_set_ccache_dacl - LocalAlloc GLE = 0x%x", GetLastError());
779 	ret = 1;
780 	goto cleanup;
781     }
782 
783     InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
784     AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
785                          STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
786                          pSystemSID);
787     if (pTokenUser) {
788 	AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
789 			     STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
790 			     pTokenUser->User.Sid);
791 	if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
792 				   DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
793 				   NULL,
794 				   NULL,
795 				   ccacheACL,
796 				   NULL)) {
797 	    gle = GetLastError();
798 	    DebugEvent("SetNamedSecurityInfo DACL (1) failed: GLE = 0x%lX", gle);
799 	    if (gle != ERROR_NO_TOKEN)
800 		ret = 1;
801 	}
802 	if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
803 				   OWNER_SECURITY_INFORMATION,
804 				   pTokenUser->User.Sid,
805 				   NULL,
806 				   NULL,
807 				   NULL)) {
808 	    gle = GetLastError();
809 	    DebugEvent("SetNamedSecurityInfo OWNER (2) failed: GLE = 0x%lX", gle);
810 	    if (gle != ERROR_NO_TOKEN)
811 		ret = 1;
812 	}
813     } else {
814 	if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
815 				   DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
816 				   NULL,
817 				   NULL,
818 				   ccacheACL,
819 				   NULL)) {
820 	    gle = GetLastError();
821 	    DebugEvent("SetNamedSecurityInfo DACL (3) failed: GLE = 0x%lX", gle);
822 	    if (gle != ERROR_NO_TOKEN)
823 		ret = 1;
824 	}
825     }
826 
827   cleanup:
828     if (pSystemSID)
829 	LocalFree(pSystemSID);
830     if (pTokenUser)
831 	LocalFree(pTokenUser);
832     if (ccacheACL)
833 	LocalFree(ccacheACL);
834     return ret;
835 }
836 
KFW_set_ccache_dacl_with_user_sid(char * filename,PSID pUserSID)837 int KFW_set_ccache_dacl_with_user_sid(char *filename, PSID pUserSID)
838 {
839     // SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;
840     PSID pSystemSID = NULL;
841     DWORD SystemSIDlength = 0, UserSIDlength = 0;
842     PACL ccacheACL = NULL;
843     DWORD ccacheACLlength = 0;
844     DWORD gle;
845     int ret = 0;
846 
847     if (!filename) {
848 	DebugEvent0("KFW_set_ccache_dacl_with_user_sid - invalid parms");
849 	return 1;
850     }
851 
852     DebugEvent0("KFW_set_ccache_dacl_with_user_sid");
853 
854     /* Get System SID */
855     if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {
856 	DebugEvent("KFW_set_ccache_dacl - ConvertStringSidToSid GLE = 0x%x", GetLastError());
857 	ret = 1;
858 	goto cleanup;
859     }
860 
861     /* Create ACL */
862     SystemSIDlength = GetLengthSid(pSystemSID);
863     ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)
864         + SystemSIDlength - sizeof(DWORD);
865 
866     if (pUserSID) {
867 	UserSIDlength = GetLengthSid(pUserSID);
868 
869 	ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength
870 	    - sizeof(DWORD);
871     }
872 
873     ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);
874     if (!ccacheACL) {
875 	DebugEvent("KFW_set_ccache_dacl - LocalAlloc GLE = 0x%x", GetLastError());
876 	ret = 1;
877 	goto cleanup;
878     }
879 
880     InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);
881     AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
882                          STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
883                          pSystemSID);
884     if (pUserSID) {
885 	AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,
886 			     STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,
887 			     pUserSID);
888 	if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
889 				   DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
890 				   NULL,
891 				   NULL,
892 				   ccacheACL,
893 				   NULL)) {
894 	    gle = GetLastError();
895 	    DebugEvent("SetNamedSecurityInfo DACL (4) failed: GLE = 0x%lX", gle);
896 	    if (gle != ERROR_NO_TOKEN)
897 		ret = 1;
898 	}
899 	if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
900 				   OWNER_SECURITY_INFORMATION,
901 				   pUserSID,
902 				   NULL,
903 				   NULL,
904 				   NULL)) {
905 	    gle = GetLastError();
906 	    DebugEvent("SetNamedSecurityInfo OWNER (5) failed: GLE = 0x%lX", gle);
907 	    if (gle != ERROR_NO_TOKEN)
908 		ret = 1;
909 	}
910     } else {
911 	if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,
912 				   DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,
913 				   NULL,
914 				   NULL,
915 				   ccacheACL,
916 				   NULL)) {
917 	    gle = GetLastError();
918 	    DebugEvent("SetNamedSecurityInfo DACL (6) failed: GLE = 0x%lX", gle);
919 	    if (gle != ERROR_NO_TOKEN)
920 		ret = 1;
921 	}
922     }
923 
924   cleanup:
925     if (pSystemSID)
926 	LocalFree(pSystemSID);
927     if (ccacheACL)
928 	LocalFree(ccacheACL);
929     return ret;
930 }
931 
KFW_obtain_user_temp_directory(HANDLE hUserToken,char * newfilename,int size)932 int KFW_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)
933 {
934     int  retval = 0;
935     DWORD dwSize = size-1;	/* leave room for nul */
936     DWORD dwLen  = 0;
937 
938     if (!hUserToken || !newfilename || size <= 0)
939 	return 1;
940 
941     *newfilename = '\0';
942 
943     dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);
944     if ( !dwLen || dwLen > dwSize )
945 	dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);
946     if ( !dwLen || dwLen > dwSize )
947 	return 1;
948 
949     newfilename[dwSize] = '\0';
950     return 0;
951 }
952 
953 void
KFW_copy_cache_to_system_file(const char * user,const char * filename)954 KFW_copy_cache_to_system_file(const char * user, const char * filename)
955 {
956     char cachename[MAX_PATH + 8] = "FILE:";
957     krb5_context		ctx = 0;
958     krb5_error_code		code;
959     krb5_principal              princ = 0;
960     krb5_ccache			cc  = 0;
961     krb5_ccache                 ncc = 0;
962     PSECURITY_ATTRIBUTES        pSA = NULL;
963 
964     if (!pkrb5_init_context || !user || !filename)
965         return;
966 
967     strncat(cachename, filename, sizeof(cachename));
968     cachename[sizeof(cachename)-1] = '\0';
969 
970     DebugEvent("KFW_Logon_Event - ccache %s", cachename);
971 
972     DeleteFile(filename);
973 
974     code = pkrb5_init_context(&ctx);
975     if (code) goto cleanup;
976 
977     code = pkrb5_parse_name(ctx, user, &princ);
978     if (code) goto cleanup;
979 
980     code = KFW_get_ccache(ctx, princ, &cc);
981     if (code) goto cleanup;
982 
983     code = pkrb5_cc_resolve(ctx, cachename, &ncc);
984     if (code) goto cleanup;
985 
986     code = pkrb5_cc_initialize(ctx, ncc, princ);
987     if (code) goto cleanup;
988 
989     code = KFW_set_ccache_dacl(filename, NULL);
990     if (code) goto cleanup;
991 
992     code = pkrb5_cc_copy_creds(ctx,cc,ncc);
993 
994   cleanup:
995     if ( cc ) {
996         pkrb5_cc_close(ctx, cc);
997         cc = 0;
998     }
999     if ( ncc ) {
1000         pkrb5_cc_close(ctx, ncc);
1001         ncc = 0;
1002     }
1003     if ( princ ) {
1004         pkrb5_free_principal(ctx, princ);
1005         princ = 0;
1006     }
1007 
1008     if (ctx)
1009         pkrb5_free_context(ctx);
1010 }
1011 
1012 int
KFW_copy_file_cache_to_default_cache(char * filename)1013 KFW_copy_file_cache_to_default_cache(char * filename)
1014 {
1015     char cachename[MAX_PATH + 8] = "FILE:";
1016     krb5_context		ctx = 0;
1017     krb5_error_code		code;
1018     krb5_principal              princ = 0;
1019     krb5_ccache			cc  = 0;
1020     krb5_ccache                 ncc = 0;
1021     int retval = 1;
1022 
1023     if (!pkrb5_init_context || !filename)
1024         return 1;
1025 
1026     if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
1027         return 1;
1028 
1029     code = pkrb5_init_context(&ctx);
1030     if (code) return 1;
1031 
1032     strcat(cachename, filename);
1033 
1034     code = pkrb5_cc_resolve(ctx, cachename, &cc);
1035     if (code) {
1036 	DebugEvent0("kfwcpcc krb5_cc_resolve failed");
1037 	goto cleanup;
1038     }
1039 
1040     code = pkrb5_cc_get_principal(ctx, cc, &princ);
1041     if (code) {
1042 	DebugEvent0("kfwcpcc krb5_cc_get_principal failed");
1043 	goto cleanup;
1044     }
1045 
1046     code = pkrb5_cc_default(ctx, &ncc);
1047     if (code) {
1048 	DebugEvent0("kfwcpcc krb5_cc_default failed");
1049 	goto cleanup;
1050     }
1051     if (!code) {
1052         code = pkrb5_cc_initialize(ctx, ncc, princ);
1053 
1054         if (!code)
1055             code = pkrb5_cc_copy_creds(ctx,cc,ncc);
1056 	if (code) {
1057 	    DebugEvent0("kfwcpcc krb5_cc_copy_creds failed");
1058 	    goto cleanup;
1059 	}
1060     }
1061     if ( ncc ) {
1062         pkrb5_cc_close(ctx, ncc);
1063         ncc = 0;
1064     }
1065 
1066     retval=0;   /* success */
1067 
1068   cleanup:
1069     if ( cc ) {
1070         pkrb5_cc_close(ctx, cc);
1071         cc = 0;
1072     }
1073 
1074     DeleteFile(filename);
1075 
1076     if ( princ ) {
1077         pkrb5_free_principal(ctx, princ);
1078         princ = 0;
1079     }
1080 
1081     if (ctx)
1082         pkrb5_free_context(ctx);
1083 
1084     return 0;
1085 }
1086 
1087 
1088 int
KFW_copy_file_cache_to_api_cache(char * filename)1089 KFW_copy_file_cache_to_api_cache(char * filename)
1090 {
1091     char cachename[MAX_PATH + 8] = "FILE:";
1092     krb5_context		ctx = 0;
1093     krb5_error_code		code;
1094     krb5_principal              princ = 0;
1095     krb5_ccache			cc  = 0;
1096     krb5_ccache                 ncc = 0;
1097     char 			*name = NULL;
1098     int retval = 1;
1099 
1100     if (!pkrb5_init_context || !filename)
1101         return 1;
1102 
1103     if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )
1104         return 1;
1105 
1106     code = pkrb5_init_context(&ctx);
1107     if (code) return 1;
1108 
1109     strcat(cachename, filename);
1110 
1111     code = pkrb5_cc_resolve(ctx, cachename, &cc);
1112     if (code) {
1113 	DebugEvent0("kfwcpcc krb5_cc_resolve failed");
1114 	goto cleanup;
1115     }
1116 
1117     code = pkrb5_cc_get_principal(ctx, cc, &princ);
1118     if (code) {
1119 	DebugEvent0("kfwcpcc krb5_cc_get_principal failed");
1120 	goto cleanup;
1121     }
1122 
1123     code = pkrb5_unparse_name(ctx, princ, &name);
1124     if (code) {
1125 	DebugEvent0("kfwcpcc krb5_unparse_name failed");
1126 	goto cleanup;
1127     }
1128 
1129     sprintf(cachename, "API:%s", name);
1130 
1131     code = pkrb5_cc_resolve(ctx, cachename, &ncc);
1132     if (code) {
1133 	DebugEvent0("kfwcpcc krb5_cc_default failed");
1134 	goto cleanup;
1135     }
1136     if (!code) {
1137         code = pkrb5_cc_initialize(ctx, ncc, princ);
1138 
1139         if (!code)
1140             code = pkrb5_cc_copy_creds(ctx,cc,ncc);
1141 	if (code) {
1142 	    DebugEvent0("kfwcpcc krb5_cc_copy_creds failed");
1143 	    goto cleanup;
1144 	}
1145     }
1146     if ( ncc ) {
1147         pkrb5_cc_close(ctx, ncc);
1148         ncc = 0;
1149     }
1150 
1151     retval=0;   /* success */
1152 
1153   cleanup:
1154     if (name)
1155 	pkrb5_free_unparsed_name(ctx, name);
1156 
1157     if ( cc ) {
1158         pkrb5_cc_close(ctx, cc);
1159         cc = 0;
1160     }
1161 
1162     DeleteFile(filename);
1163 
1164     if ( princ ) {
1165         pkrb5_free_principal(ctx, princ);
1166         princ = 0;
1167     }
1168 
1169     if (ctx)
1170         pkrb5_free_context(ctx);
1171 
1172     return 0;
1173 }
1174 
1175 
1176 int
KFW_destroy_tickets_for_principal(char * user)1177 KFW_destroy_tickets_for_principal(char * user)
1178 {
1179     krb5_context		ctx = 0;
1180     krb5_error_code		code;
1181     krb5_principal      princ = 0;
1182     krb5_ccache			cc  = 0;
1183 
1184     if (!pkrb5_init_context)
1185         return 0;
1186 
1187     code = pkrb5_init_context(&ctx);
1188     if (code) return 1;
1189 
1190     code = pkrb5_parse_name(ctx, user, &princ);
1191     if (code) goto loop_cleanup;
1192 
1193     code = KFW_get_ccache(ctx, princ, &cc);
1194     if (code) goto loop_cleanup;
1195 
1196     code = pkrb5_cc_destroy(ctx, cc);
1197     if (!code) cc = 0;
1198 
1199   loop_cleanup:
1200     if ( cc ) {
1201         pkrb5_cc_close(ctx, cc);
1202         cc = 0;
1203     }
1204     if ( princ ) {
1205         pkrb5_free_principal(ctx, princ);
1206         princ = 0;
1207     }
1208 
1209     pkrb5_free_context(ctx);
1210     return 0;
1211 }
1212 
1213 
1214 /* There are scenarios in which an interactive logon will not
1215  * result in the LogonScript being executed.  This will result
1216  * in orphaned cache files being left in the Temp directory.
1217  * This function will search for cache files in the Temp
1218  * directory and delete any that are older than five minutes.
1219  */
1220 void
KFW_cleanup_orphaned_caches(void)1221 KFW_cleanup_orphaned_caches(void)
1222 {
1223     char * temppath = NULL;
1224     char * curdir = NULL;
1225     DWORD count, count2;
1226     WIN32_FIND_DATA FindFileData;
1227     HANDLE hFind = INVALID_HANDLE_VALUE;
1228     FILETIME now;
1229     ULARGE_INTEGER uli_now;
1230     FILETIME expired;
1231 
1232     count = GetTempPath(0, NULL);
1233     if (count <= 0)
1234         return;
1235     temppath = (char *) malloc(count);
1236     if (!temppath)
1237         goto cleanup;
1238     count2 = GetTempPath(count, temppath);
1239     if (count2 <= 0 || count2 > count)
1240         goto cleanup;
1241 
1242     count = GetCurrentDirectory(0, NULL);
1243     curdir = (char *)malloc(count);
1244     if (!curdir)
1245         goto cleanup;
1246     count2 = GetCurrentDirectory(count, curdir);
1247     if (count2 <= 0 || count2 > count)
1248         goto cleanup;
1249 
1250     if (!SetCurrentDirectory(temppath))
1251         goto cleanup;
1252 
1253     GetSystemTimeAsFileTime(&now);
1254     uli_now.u.LowPart = now.dwLowDateTime;
1255     uli_now.u.HighPart = now.dwHighDateTime;
1256 
1257     uli_now.QuadPart -= 3000000000;        /* 5 minutes == 3 billion 100 nano seconds */
1258 
1259     expired.dwLowDateTime = uli_now.u.LowPart;
1260     expired.dwHighDateTime = uli_now.u.HighPart;
1261 
1262     hFind = FindFirstFile("kfwlogon-*", &FindFileData);
1263     if (hFind != INVALID_HANDLE_VALUE) {
1264         do {
1265             if (CompareFileTime(&FindFileData.ftCreationTime, &expired) < 0) {
1266                 DebugEvent("Deleting orphaned cache file: \"%s\"", FindFileData.cFileName);
1267                 DeleteFile(FindFileData.cFileName);
1268             }
1269         } while ( FindNextFile(hFind, &FindFileData) );
1270     }
1271 
1272     SetCurrentDirectory(curdir);
1273 
1274   cleanup:
1275     if (temppath)
1276         free(temppath);
1277     if (hFind != INVALID_HANDLE_VALUE)
1278         FindClose(hFind);
1279     if (curdir)
1280         free(curdir);
1281 }
1282