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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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