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