Path: blob/main/crypto/krb5/src/windows/kfwlogon/kfwcommon.c
34889 views
/*1Copyright 2005,2006 by the Massachusetts Institute of Technology2Copyright 2007 by Secure Endpoints Inc.34All rights reserved.56Permission to use, copy, modify, and distribute this software and its7documentation for any purpose and without fee is hereby granted,8provided that the above copyright notice appear in all copies and that9both that copyright notice and this permission notice appear in10supporting documentation, and that the name of the Massachusetts11Institute of Technology (M.I.T.) not be used in advertising or publicity12pertaining to distribution of the software without specific, written13prior permission.1415M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING16ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL17M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR18ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,19WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,20ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS21SOFTWARE.2223*/2425#include "kfwlogon.h"26#include <windows.h>27#include <Aclapi.h>28#include <userenv.h>29#include <Sddl.h>3031#include <io.h>32#include <sys/stat.h>33#include <sys/types.h>34#include <fcntl.h>3536#include <winsock2.h>37#include <lm.h>38#include <nb30.h>3940#include <errno.h>41#include <malloc.h>424344/* Function Pointer Declarations for Delayed Loading */45// CCAPI46DECL_FUNC_PTR(cc_initialize);47DECL_FUNC_PTR(cc_shutdown);48DECL_FUNC_PTR(cc_get_NC_info);49DECL_FUNC_PTR(cc_free_NC_info);5051// leash functions52DECL_FUNC_PTR(Leash_get_default_lifetime);53DECL_FUNC_PTR(Leash_get_default_forwardable);54DECL_FUNC_PTR(Leash_get_default_renew_till);55DECL_FUNC_PTR(Leash_get_default_noaddresses);56DECL_FUNC_PTR(Leash_get_default_proxiable);57DECL_FUNC_PTR(Leash_get_default_publicip);58DECL_FUNC_PTR(Leash_get_default_life_min);59DECL_FUNC_PTR(Leash_get_default_life_max);60DECL_FUNC_PTR(Leash_get_default_renew_min);61DECL_FUNC_PTR(Leash_get_default_renew_max);62DECL_FUNC_PTR(Leash_get_default_renewable);63DECL_FUNC_PTR(Leash_get_default_mslsa_import);6465// krb5 functions66DECL_FUNC_PTR(krb5_change_password);67DECL_FUNC_PTR(krb5_get_init_creds_opt_init);68DECL_FUNC_PTR(krb5_get_init_creds_opt_set_tkt_life);69DECL_FUNC_PTR(krb5_get_init_creds_opt_set_renew_life);70DECL_FUNC_PTR(krb5_get_init_creds_opt_set_forwardable);71DECL_FUNC_PTR(krb5_get_init_creds_opt_set_proxiable);72DECL_FUNC_PTR(krb5_get_init_creds_opt_set_address_list);73DECL_FUNC_PTR(krb5_get_init_creds_password);74DECL_FUNC_PTR(krb5_build_principal_ext);75DECL_FUNC_PTR(krb5_cc_get_name);76DECL_FUNC_PTR(krb5_cc_resolve);77DECL_FUNC_PTR(krb5_cc_default);78DECL_FUNC_PTR(krb5_cc_default_name);79DECL_FUNC_PTR(krb5_cc_set_default_name);80DECL_FUNC_PTR(krb5_cc_initialize);81DECL_FUNC_PTR(krb5_cc_destroy);82DECL_FUNC_PTR(krb5_cc_close);83DECL_FUNC_PTR(krb5_cc_store_cred);84DECL_FUNC_PTR(krb5_cc_copy_creds);85DECL_FUNC_PTR(krb5_cc_retrieve_cred);86DECL_FUNC_PTR(krb5_cc_get_principal);87DECL_FUNC_PTR(krb5_cc_start_seq_get);88DECL_FUNC_PTR(krb5_cc_next_cred);89DECL_FUNC_PTR(krb5_cc_end_seq_get);90DECL_FUNC_PTR(krb5_cc_remove_cred);91DECL_FUNC_PTR(krb5_cc_set_flags);92DECL_FUNC_PTR(krb5_cc_get_type);93DECL_FUNC_PTR(krb5_free_context);94DECL_FUNC_PTR(krb5_free_cred_contents);95DECL_FUNC_PTR(krb5_free_principal);96DECL_FUNC_PTR(krb5_get_in_tkt_with_password);97DECL_FUNC_PTR(krb5_init_context);98DECL_FUNC_PTR(krb5_parse_name);99DECL_FUNC_PTR(krb5_timeofday);100DECL_FUNC_PTR(krb5_timestamp_to_sfstring);101DECL_FUNC_PTR(krb5_unparse_name);102DECL_FUNC_PTR(krb5_get_credentials);103DECL_FUNC_PTR(krb5_mk_req);104DECL_FUNC_PTR(krb5_sname_to_principal);105DECL_FUNC_PTR(krb5_get_credentials_renew);106DECL_FUNC_PTR(krb5_free_data);107DECL_FUNC_PTR(krb5_free_data_contents);108DECL_FUNC_PTR(krb5_free_unparsed_name);109DECL_FUNC_PTR(krb5_os_localaddr);110DECL_FUNC_PTR(krb5_copy_keyblock_contents);111DECL_FUNC_PTR(krb5_copy_data);112DECL_FUNC_PTR(krb5_free_creds);113DECL_FUNC_PTR(krb5_build_principal);114DECL_FUNC_PTR(krb5_get_renewed_creds);115DECL_FUNC_PTR(krb5_get_default_config_files);116DECL_FUNC_PTR(krb5_free_config_files);117DECL_FUNC_PTR(krb5_get_default_realm);118DECL_FUNC_PTR(krb5_free_default_realm);119DECL_FUNC_PTR(krb5_free_ticket);120DECL_FUNC_PTR(krb5_decode_ticket);121DECL_FUNC_PTR(krb5_get_host_realm);122DECL_FUNC_PTR(krb5_free_host_realm);123DECL_FUNC_PTR(krb5_free_addresses);124DECL_FUNC_PTR(krb5_c_random_make_octets);125126// ComErr functions127DECL_FUNC_PTR(com_err);128DECL_FUNC_PTR(error_message);129130// Profile functions131DECL_FUNC_PTR(profile_init);132DECL_FUNC_PTR(profile_release);133DECL_FUNC_PTR(profile_get_subsection_names);134DECL_FUNC_PTR(profile_free_list);135DECL_FUNC_PTR(profile_get_string);136DECL_FUNC_PTR(profile_release_string);137138// Service functions139DECL_FUNC_PTR(OpenSCManagerA);140DECL_FUNC_PTR(OpenServiceA);141DECL_FUNC_PTR(QueryServiceStatus);142DECL_FUNC_PTR(CloseServiceHandle);143DECL_FUNC_PTR(LsaNtStatusToWinError);144145// LSA Functions146DECL_FUNC_PTR(LsaConnectUntrusted);147DECL_FUNC_PTR(LsaLookupAuthenticationPackage);148DECL_FUNC_PTR(LsaCallAuthenticationPackage);149DECL_FUNC_PTR(LsaFreeReturnBuffer);150DECL_FUNC_PTR(LsaGetLogonSessionData);151152// CCAPI153FUNC_INFO ccapi_fi[] = {154MAKE_FUNC_INFO(cc_initialize),155MAKE_FUNC_INFO(cc_shutdown),156MAKE_FUNC_INFO(cc_get_NC_info),157MAKE_FUNC_INFO(cc_free_NC_info),158END_FUNC_INFO159};160161FUNC_INFO leash_fi[] = {162MAKE_FUNC_INFO(Leash_get_default_lifetime),163MAKE_FUNC_INFO(Leash_get_default_renew_till),164MAKE_FUNC_INFO(Leash_get_default_forwardable),165MAKE_FUNC_INFO(Leash_get_default_noaddresses),166MAKE_FUNC_INFO(Leash_get_default_proxiable),167MAKE_FUNC_INFO(Leash_get_default_publicip),168MAKE_FUNC_INFO(Leash_get_default_life_min),169MAKE_FUNC_INFO(Leash_get_default_life_max),170MAKE_FUNC_INFO(Leash_get_default_renew_min),171MAKE_FUNC_INFO(Leash_get_default_renew_max),172MAKE_FUNC_INFO(Leash_get_default_renewable),173END_FUNC_INFO174};175176FUNC_INFO leash_opt_fi[] = {177MAKE_FUNC_INFO(Leash_get_default_mslsa_import),178END_FUNC_INFO179};180181FUNC_INFO k5_fi[] = {182MAKE_FUNC_INFO(krb5_change_password),183MAKE_FUNC_INFO(krb5_get_init_creds_opt_init),184MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_tkt_life),185MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_renew_life),186MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_forwardable),187MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_proxiable),188MAKE_FUNC_INFO(krb5_get_init_creds_opt_set_address_list),189MAKE_FUNC_INFO(krb5_get_init_creds_password),190MAKE_FUNC_INFO(krb5_build_principal_ext),191MAKE_FUNC_INFO(krb5_cc_get_name),192MAKE_FUNC_INFO(krb5_cc_resolve),193MAKE_FUNC_INFO(krb5_cc_default),194MAKE_FUNC_INFO(krb5_cc_default_name),195MAKE_FUNC_INFO(krb5_cc_set_default_name),196MAKE_FUNC_INFO(krb5_cc_initialize),197MAKE_FUNC_INFO(krb5_cc_destroy),198MAKE_FUNC_INFO(krb5_cc_close),199MAKE_FUNC_INFO(krb5_cc_copy_creds),200MAKE_FUNC_INFO(krb5_cc_store_cred),201MAKE_FUNC_INFO(krb5_cc_retrieve_cred),202MAKE_FUNC_INFO(krb5_cc_get_principal),203MAKE_FUNC_INFO(krb5_cc_start_seq_get),204MAKE_FUNC_INFO(krb5_cc_next_cred),205MAKE_FUNC_INFO(krb5_cc_end_seq_get),206MAKE_FUNC_INFO(krb5_cc_remove_cred),207MAKE_FUNC_INFO(krb5_cc_set_flags),208MAKE_FUNC_INFO(krb5_cc_get_type),209MAKE_FUNC_INFO(krb5_free_context),210MAKE_FUNC_INFO(krb5_free_cred_contents),211MAKE_FUNC_INFO(krb5_free_principal),212MAKE_FUNC_INFO(krb5_get_in_tkt_with_password),213MAKE_FUNC_INFO(krb5_init_context),214MAKE_FUNC_INFO(krb5_parse_name),215MAKE_FUNC_INFO(krb5_timeofday),216MAKE_FUNC_INFO(krb5_timestamp_to_sfstring),217MAKE_FUNC_INFO(krb5_unparse_name),218MAKE_FUNC_INFO(krb5_get_credentials),219MAKE_FUNC_INFO(krb5_mk_req),220MAKE_FUNC_INFO(krb5_sname_to_principal),221MAKE_FUNC_INFO(krb5_get_credentials_renew),222MAKE_FUNC_INFO(krb5_free_data),223MAKE_FUNC_INFO(krb5_free_data_contents),224MAKE_FUNC_INFO(krb5_free_unparsed_name),225MAKE_FUNC_INFO(krb5_os_localaddr),226MAKE_FUNC_INFO(krb5_copy_keyblock_contents),227MAKE_FUNC_INFO(krb5_copy_data),228MAKE_FUNC_INFO(krb5_free_creds),229MAKE_FUNC_INFO(krb5_build_principal),230MAKE_FUNC_INFO(krb5_get_renewed_creds),231MAKE_FUNC_INFO(krb5_free_addresses),232MAKE_FUNC_INFO(krb5_get_default_config_files),233MAKE_FUNC_INFO(krb5_free_config_files),234MAKE_FUNC_INFO(krb5_get_default_realm),235MAKE_FUNC_INFO(krb5_free_default_realm),236MAKE_FUNC_INFO(krb5_free_ticket),237MAKE_FUNC_INFO(krb5_decode_ticket),238MAKE_FUNC_INFO(krb5_get_host_realm),239MAKE_FUNC_INFO(krb5_free_host_realm),240MAKE_FUNC_INFO(krb5_free_addresses),241MAKE_FUNC_INFO(krb5_c_random_make_octets),242END_FUNC_INFO243};244245FUNC_INFO profile_fi[] = {246MAKE_FUNC_INFO(profile_init),247MAKE_FUNC_INFO(profile_release),248MAKE_FUNC_INFO(profile_get_subsection_names),249MAKE_FUNC_INFO(profile_free_list),250MAKE_FUNC_INFO(profile_get_string),251MAKE_FUNC_INFO(profile_release_string),252END_FUNC_INFO253};254255FUNC_INFO ce_fi[] = {256MAKE_FUNC_INFO(com_err),257MAKE_FUNC_INFO(error_message),258END_FUNC_INFO259};260261FUNC_INFO service_fi[] = {262MAKE_FUNC_INFO(OpenSCManagerA),263MAKE_FUNC_INFO(OpenServiceA),264MAKE_FUNC_INFO(QueryServiceStatus),265MAKE_FUNC_INFO(CloseServiceHandle),266MAKE_FUNC_INFO(LsaNtStatusToWinError),267END_FUNC_INFO268};269270FUNC_INFO lsa_fi[] = {271MAKE_FUNC_INFO(LsaConnectUntrusted),272MAKE_FUNC_INFO(LsaLookupAuthenticationPackage),273MAKE_FUNC_INFO(LsaCallAuthenticationPackage),274MAKE_FUNC_INFO(LsaFreeReturnBuffer),275MAKE_FUNC_INFO(LsaGetLogonSessionData),276END_FUNC_INFO277};278279/* Static Declarations */280static int inited = 0;281static HINSTANCE hKrb5 = 0;282static HINSTANCE hKrb524 = 0;283static HINSTANCE hSecur32 = 0;284static HINSTANCE hAdvApi32 = 0;285static HINSTANCE hComErr = 0;286static HINSTANCE hService = 0;287static HINSTANCE hProfile = 0;288static HINSTANCE hLeash = 0;289static HINSTANCE hLeashOpt = 0;290static HINSTANCE hCCAPI = 0;291292static DWORD TraceOption = 0;293static HANDLE hDLL;294295BOOL IsDebugLogging(void)296{297DWORD LSPsize;298HKEY NPKey;299DWORD dwDebug = FALSE;300301if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,302"System\\CurrentControlSet\\Services\\MIT Kerberos\\NetworkProvider",3030, KEY_QUERY_VALUE, &NPKey) == ERROR_SUCCESS)304{305LSPsize=sizeof(dwDebug);306if (RegQueryValueEx(NPKey, "Debug", NULL, NULL, (LPBYTE)&dwDebug, &LSPsize) != ERROR_SUCCESS)307{308dwDebug = FALSE;309}310RegCloseKey (NPKey);311}312313return(dwDebug ? TRUE : FALSE);314}315316void DebugEvent0(char *a)317{318HANDLE h; char *ptbuf[1];319320if (IsDebugLogging()) {321h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);322if (h) {323ptbuf[0] = a;324ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);325DeregisterEventSource(h);326}327}328}329330#define MAXBUF_ 512331void DebugEvent(char *b,...)332{333HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];334va_list marker;335336if (IsDebugLogging()) {337h = RegisterEventSource(NULL, KFW_LOGON_EVENT_NAME);338if (h) {339va_start(marker,b);340StringCbVPrintf(buf, MAXBUF_+1,b,marker);341buf[MAXBUF_] = '\0';342ptbuf[0] = buf;343ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);344DeregisterEventSource(h);345va_end(marker);346}347}348}349350static HANDLE hInitMutex = NULL;351static BOOL bInit = FALSE;352353/* KFW_initialize cannot be called from DllMain */354void355KFW_initialize(void)356{357static int inited = 0;358359if ( !inited ) {360char mutexName[MAX_PATH];361HANDLE hMutex = NULL;362363sprintf(mutexName, "AFS KFW Init pid=%d", getpid());364365hMutex = CreateMutex( NULL, TRUE, mutexName );366if ( GetLastError() == ERROR_ALREADY_EXISTS ) {367if ( WaitForSingleObject( hMutex, INFINITE ) != WAIT_OBJECT_0 ) {368return;369}370}371if ( !inited ) {372inited = 1;373LoadFuncs(KRB5_DLL, k5_fi, &hKrb5, 0, 1, 0, 0);374LoadFuncs(COMERR_DLL, ce_fi, &hComErr, 0, 0, 1, 0);375LoadFuncs(SERVICE_DLL, service_fi, &hService, 0, 1, 0, 0);376LoadFuncs(SECUR32_DLL, lsa_fi, &hSecur32, 0, 1, 1, 1);377LoadFuncs(PROFILE_DLL, profile_fi, &hProfile, 0, 1, 0, 0);378LoadFuncs(LEASH_DLL, leash_fi, &hLeash, 0, 1, 0, 0);379LoadFuncs(CCAPI_DLL, ccapi_fi, &hCCAPI, 0, 1, 0, 0);380LoadFuncs(LEASH_DLL, leash_opt_fi, &hLeashOpt, 0, 1, 0, 0);381}382ReleaseMutex(hMutex);383CloseHandle(hMutex);384}385}386387void388KFW_cleanup(void)389{390if (hLeashOpt)391FreeLibrary(hLeashOpt);392if (hCCAPI)393FreeLibrary(hCCAPI);394if (hLeash)395FreeLibrary(hLeash);396if (hKrb524)397FreeLibrary(hKrb524);398if (hSecur32)399FreeLibrary(hSecur32);400if (hService)401FreeLibrary(hService);402if (hComErr)403FreeLibrary(hComErr);404if (hProfile)405FreeLibrary(hProfile);406if (hKrb5)407FreeLibrary(hKrb5);408}409410411int412KFW_is_available(void)413{414KFW_initialize();415if ( hKrb5 && hComErr && hService &&416#ifdef USE_MS2MIT417hSecur32 &&418#endif /* USE_MS2MIT */419hProfile && hLeash && hCCAPI )420return TRUE;421422return FALSE;423}424425/* Given a principal return an existing ccache or create one and return */426int427KFW_get_ccache(krb5_context alt_ctx, krb5_principal principal, krb5_ccache * cc)428{429krb5_context ctx;430char * pname = 0;431char * ccname = 0;432krb5_error_code code;433434if (!pkrb5_init_context)435return 0;436437if ( alt_ctx ) {438ctx = alt_ctx;439} else {440code = pkrb5_init_context(&ctx);441if (code) goto cleanup;442}443444if ( principal ) {445code = pkrb5_unparse_name(ctx, principal, &pname);446if (code) goto cleanup;447448ccname = (char *)malloc(strlen(pname) + 5);449sprintf(ccname,"API:%s",pname);450451DebugEvent0(ccname);452code = pkrb5_cc_resolve(ctx, ccname, cc);453} else {454code = pkrb5_cc_default(ctx, cc);455if (code) goto cleanup;456}457458cleanup:459if (ccname)460free(ccname);461if (pname)462pkrb5_free_unparsed_name(ctx,pname);463if (ctx && (ctx != alt_ctx))464pkrb5_free_context(ctx);465return(code);466}467468469int470KFW_kinit( krb5_context alt_ctx,471krb5_ccache alt_cc,472HWND hParent,473char *principal_name,474char *password,475krb5_deltat lifetime,476DWORD forwardable,477DWORD proxiable,478krb5_deltat renew_life,479DWORD addressless,480DWORD publicIP481)482{483krb5_error_code code = 0;484krb5_context ctx = 0;485krb5_ccache cc = 0;486krb5_principal me = 0;487char* name = 0;488krb5_creds my_creds;489krb5_get_init_creds_opt options;490krb5_address ** addrs = NULL;491size_t i = 0, addr_count = 0;492493if (!pkrb5_init_context)494return 0;495496pkrb5_get_init_creds_opt_init(&options);497memset(&my_creds, 0, sizeof(my_creds));498499if (alt_ctx)500{501ctx = alt_ctx;502}503else504{505code = pkrb5_init_context(&ctx);506if (code) goto cleanup;507}508509if ( alt_cc ) {510cc = alt_cc;511} else {512code = pkrb5_cc_default(ctx, &cc);513if (code) goto cleanup;514}515516code = pkrb5_parse_name(ctx, principal_name, &me);517if (code)518goto cleanup;519520code = pkrb5_unparse_name(ctx, me, &name);521if (code)522goto cleanup;523524if (lifetime == 0)525lifetime = pLeash_get_default_lifetime();526lifetime *= 60;527528if (renew_life > 0)529renew_life *= 60;530531if (lifetime)532pkrb5_get_init_creds_opt_set_tkt_life(&options, lifetime);533pkrb5_get_init_creds_opt_set_forwardable(&options,534forwardable ? 1 : 0);535pkrb5_get_init_creds_opt_set_proxiable(&options,536proxiable ? 1 : 0);537pkrb5_get_init_creds_opt_set_renew_life(&options,538renew_life);539if (addressless)540pkrb5_get_init_creds_opt_set_address_list(&options,NULL);541else {542if (publicIP)543{544// we are going to add the public IP address specified by the user545// to the list provided by the operating system546krb5_address ** local_addrs=NULL;547DWORD netIPAddr;548549pkrb5_os_localaddr(ctx, &local_addrs);550while ( local_addrs[i++] );551addr_count = i + 1;552553addrs = (krb5_address **) malloc((addr_count+1) * sizeof(krb5_address *));554if ( !addrs ) {555pkrb5_free_addresses(ctx, local_addrs);556goto cleanup;557}558memset(addrs, 0, sizeof(krb5_address *) * (addr_count+1));559i = 0;560while ( local_addrs[i] ) {561addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));562if (addrs[i] == NULL) {563pkrb5_free_addresses(ctx, local_addrs);564goto cleanup;565}566567addrs[i]->magic = local_addrs[i]->magic;568addrs[i]->addrtype = local_addrs[i]->addrtype;569addrs[i]->length = local_addrs[i]->length;570addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);571if (!addrs[i]->contents) {572pkrb5_free_addresses(ctx, local_addrs);573goto cleanup;574}575576memcpy(addrs[i]->contents,local_addrs[i]->contents,577local_addrs[i]->length); /* safe */578i++;579}580pkrb5_free_addresses(ctx, local_addrs);581582addrs[i] = (krb5_address *)malloc(sizeof(krb5_address));583if (addrs[i] == NULL)584goto cleanup;585586addrs[i]->magic = KV5M_ADDRESS;587addrs[i]->addrtype = AF_INET;588addrs[i]->length = 4;589addrs[i]->contents = (unsigned char *)malloc(addrs[i]->length);590if (!addrs[i]->contents)591goto cleanup;592593netIPAddr = htonl(publicIP);594memcpy(addrs[i]->contents,&netIPAddr,4);595596pkrb5_get_init_creds_opt_set_address_list(&options,addrs);597598}599}600601code = pkrb5_get_init_creds_password(ctx,602&my_creds,603me,604password, // password605NULL, // no prompter606hParent, // prompter data6070, // start time6080, // service name609&options);610if (code)611goto cleanup;612613code = pkrb5_cc_initialize(ctx, cc, me);614if (code)615goto cleanup;616617code = pkrb5_cc_store_cred(ctx, cc, &my_creds);618if (code)619goto cleanup;620621cleanup:622if ( addrs ) {623for ( i=0;i<addr_count;i++ ) {624if ( addrs[i] ) {625if ( addrs[i]->contents )626free(addrs[i]->contents);627free(addrs[i]);628}629}630}631if (my_creds.client == me)632my_creds.client = 0;633pkrb5_free_cred_contents(ctx, &my_creds);634if (name)635pkrb5_free_unparsed_name(ctx, name);636if (me)637pkrb5_free_principal(ctx, me);638if (cc && (cc != alt_cc))639pkrb5_cc_close(ctx, cc);640if (ctx && (ctx != alt_ctx))641pkrb5_free_context(ctx);642return(code);643}644645646int647KFW_get_cred( char * username,648char * password,649int lifetime,650char ** reasonP )651{652krb5_context ctx = 0;653krb5_ccache cc = 0;654char * realm = 0;655krb5_principal principal = 0;656char * pname = 0;657krb5_error_code code;658659if (!pkrb5_init_context || !username || !password || !password[0])660return 0;661662DebugEvent0(username);663664code = pkrb5_init_context(&ctx);665if ( code ) goto cleanup;666667code = pkrb5_get_default_realm(ctx, &realm);668669if (realm) {670pname = malloc(strlen(username) + strlen(realm) + 2);671if (!pname)672goto cleanup;673strcpy(pname, username);674strcat(pname, "@");675strcat(pname, realm);676} else {677goto cleanup;678}679680DebugEvent0(realm);681DebugEvent0(pname);682683code = pkrb5_parse_name(ctx, pname, &principal);684if ( code ) goto cleanup;685686DebugEvent0("parsed name");687code = KFW_get_ccache(ctx, principal, &cc);688if ( code ) goto cleanup;689690DebugEvent0("got ccache");691692if ( lifetime == 0 )693lifetime = pLeash_get_default_lifetime();694695DebugEvent0("got lifetime");696697code = KFW_kinit( ctx, cc, HWND_DESKTOP,698pname,699password,700lifetime,701pLeash_get_default_forwardable(),702pLeash_get_default_proxiable(),703pLeash_get_default_renewable() ? pLeash_get_default_renew_till() : 0,704pLeash_get_default_noaddresses(),705pLeash_get_default_publicip());706DebugEvent0("kinit returned");707if ( code ) goto cleanup;708709cleanup:710if ( pname )711free(pname);712if ( realm )713pkrb5_free_default_realm(ctx, realm);714if ( cc )715pkrb5_cc_close(ctx, cc);716717if ( code && reasonP ) {718*reasonP = (char *)perror_message(code);719}720return(code);721}722723int KFW_set_ccache_dacl(char *filename, HANDLE hUserToken)724{725// SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;726PSID pSystemSID = NULL;727DWORD SystemSIDlength = 0, UserSIDlength = 0;728PACL ccacheACL = NULL;729DWORD ccacheACLlength = 0;730PTOKEN_USER pTokenUser = NULL;731DWORD retLen;732DWORD gle;733int ret = 0;734735if (!filename) {736DebugEvent0("KFW_set_ccache_dacl - invalid parms");737return 1;738}739740DebugEvent0("KFW_set_ccache_dacl");741742/* Get System SID */743if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {744DebugEvent("KFW_set_ccache_dacl - ConvertStringSidToSid GLE = 0x%x", GetLastError());745ret = 1;746goto cleanup;747}748749/* Create ACL */750SystemSIDlength = GetLengthSid(pSystemSID);751ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)752+ SystemSIDlength - sizeof(DWORD);753754if (hUserToken) {755if (!GetTokenInformation(hUserToken, TokenUser, NULL, 0, &retLen))756{757if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) {758pTokenUser = (PTOKEN_USER) LocalAlloc(LPTR, retLen);759760if (!GetTokenInformation(hUserToken, TokenUser, pTokenUser, retLen, &retLen))761{762DebugEvent("GetTokenInformation failed: GLE = %lX", GetLastError());763}764}765}766767if (pTokenUser) {768UserSIDlength = GetLengthSid(pTokenUser->User.Sid);769770ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength771- sizeof(DWORD);772}773}774775ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);776if (!ccacheACL) {777DebugEvent("KFW_set_ccache_dacl - LocalAlloc GLE = 0x%x", GetLastError());778ret = 1;779goto cleanup;780}781782InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);783AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,784STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,785pSystemSID);786if (pTokenUser) {787AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,788STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,789pTokenUser->User.Sid);790if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,791DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,792NULL,793NULL,794ccacheACL,795NULL)) {796gle = GetLastError();797DebugEvent("SetNamedSecurityInfo DACL (1) failed: GLE = 0x%lX", gle);798if (gle != ERROR_NO_TOKEN)799ret = 1;800}801if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,802OWNER_SECURITY_INFORMATION,803pTokenUser->User.Sid,804NULL,805NULL,806NULL)) {807gle = GetLastError();808DebugEvent("SetNamedSecurityInfo OWNER (2) failed: GLE = 0x%lX", gle);809if (gle != ERROR_NO_TOKEN)810ret = 1;811}812} else {813if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,814DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,815NULL,816NULL,817ccacheACL,818NULL)) {819gle = GetLastError();820DebugEvent("SetNamedSecurityInfo DACL (3) failed: GLE = 0x%lX", gle);821if (gle != ERROR_NO_TOKEN)822ret = 1;823}824}825826cleanup:827if (pSystemSID)828LocalFree(pSystemSID);829if (pTokenUser)830LocalFree(pTokenUser);831if (ccacheACL)832LocalFree(ccacheACL);833return ret;834}835836int KFW_set_ccache_dacl_with_user_sid(char *filename, PSID pUserSID)837{838// SID_IDENTIFIER_AUTHORITY authority = SECURITY_NT_SID_AUTHORITY;839PSID pSystemSID = NULL;840DWORD SystemSIDlength = 0, UserSIDlength = 0;841PACL ccacheACL = NULL;842DWORD ccacheACLlength = 0;843DWORD gle;844int ret = 0;845846if (!filename) {847DebugEvent0("KFW_set_ccache_dacl_with_user_sid - invalid parms");848return 1;849}850851DebugEvent0("KFW_set_ccache_dacl_with_user_sid");852853/* Get System SID */854if (!ConvertStringSidToSid("S-1-5-18", &pSystemSID)) {855DebugEvent("KFW_set_ccache_dacl - ConvertStringSidToSid GLE = 0x%x", GetLastError());856ret = 1;857goto cleanup;858}859860/* Create ACL */861SystemSIDlength = GetLengthSid(pSystemSID);862ccacheACLlength = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE)863+ SystemSIDlength - sizeof(DWORD);864865if (pUserSID) {866UserSIDlength = GetLengthSid(pUserSID);867868ccacheACLlength += sizeof(ACCESS_ALLOWED_ACE) + UserSIDlength869- sizeof(DWORD);870}871872ccacheACL = (PACL) LocalAlloc(LPTR, ccacheACLlength);873if (!ccacheACL) {874DebugEvent("KFW_set_ccache_dacl - LocalAlloc GLE = 0x%x", GetLastError());875ret = 1;876goto cleanup;877}878879InitializeAcl(ccacheACL, ccacheACLlength, ACL_REVISION);880AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,881STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,882pSystemSID);883if (pUserSID) {884AddAccessAllowedAceEx(ccacheACL, ACL_REVISION, 0,885STANDARD_RIGHTS_ALL | SPECIFIC_RIGHTS_ALL,886pUserSID);887if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,888DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,889NULL,890NULL,891ccacheACL,892NULL)) {893gle = GetLastError();894DebugEvent("SetNamedSecurityInfo DACL (4) failed: GLE = 0x%lX", gle);895if (gle != ERROR_NO_TOKEN)896ret = 1;897}898if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,899OWNER_SECURITY_INFORMATION,900pUserSID,901NULL,902NULL,903NULL)) {904gle = GetLastError();905DebugEvent("SetNamedSecurityInfo OWNER (5) failed: GLE = 0x%lX", gle);906if (gle != ERROR_NO_TOKEN)907ret = 1;908}909} else {910if (!SetNamedSecurityInfo( filename, SE_FILE_OBJECT,911DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION,912NULL,913NULL,914ccacheACL,915NULL)) {916gle = GetLastError();917DebugEvent("SetNamedSecurityInfo DACL (6) failed: GLE = 0x%lX", gle);918if (gle != ERROR_NO_TOKEN)919ret = 1;920}921}922923cleanup:924if (pSystemSID)925LocalFree(pSystemSID);926if (ccacheACL)927LocalFree(ccacheACL);928return ret;929}930931int KFW_obtain_user_temp_directory(HANDLE hUserToken, char *newfilename, int size)932{933int retval = 0;934DWORD dwSize = size-1; /* leave room for nul */935DWORD dwLen = 0;936937if (!hUserToken || !newfilename || size <= 0)938return 1;939940*newfilename = '\0';941942dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TEMP%", newfilename, dwSize);943if ( !dwLen || dwLen > dwSize )944dwLen = ExpandEnvironmentStringsForUser(hUserToken, "%TMP%", newfilename, dwSize);945if ( !dwLen || dwLen > dwSize )946return 1;947948newfilename[dwSize] = '\0';949return 0;950}951952void953KFW_copy_cache_to_system_file(const char * user, const char * filename)954{955char cachename[MAX_PATH + 8] = "FILE:";956krb5_context ctx = 0;957krb5_error_code code;958krb5_principal princ = 0;959krb5_ccache cc = 0;960krb5_ccache ncc = 0;961PSECURITY_ATTRIBUTES pSA = NULL;962963if (!pkrb5_init_context || !user || !filename)964return;965966strncat(cachename, filename, sizeof(cachename));967cachename[sizeof(cachename)-1] = '\0';968969DebugEvent("KFW_Logon_Event - ccache %s", cachename);970971DeleteFile(filename);972973code = pkrb5_init_context(&ctx);974if (code) goto cleanup;975976code = pkrb5_parse_name(ctx, user, &princ);977if (code) goto cleanup;978979code = KFW_get_ccache(ctx, princ, &cc);980if (code) goto cleanup;981982code = pkrb5_cc_resolve(ctx, cachename, &ncc);983if (code) goto cleanup;984985code = pkrb5_cc_initialize(ctx, ncc, princ);986if (code) goto cleanup;987988code = KFW_set_ccache_dacl(filename, NULL);989if (code) goto cleanup;990991code = pkrb5_cc_copy_creds(ctx,cc,ncc);992993cleanup:994if ( cc ) {995pkrb5_cc_close(ctx, cc);996cc = 0;997}998if ( ncc ) {999pkrb5_cc_close(ctx, ncc);1000ncc = 0;1001}1002if ( princ ) {1003pkrb5_free_principal(ctx, princ);1004princ = 0;1005}10061007if (ctx)1008pkrb5_free_context(ctx);1009}10101011int1012KFW_copy_file_cache_to_default_cache(char * filename)1013{1014char cachename[MAX_PATH + 8] = "FILE:";1015krb5_context ctx = 0;1016krb5_error_code code;1017krb5_principal princ = 0;1018krb5_ccache cc = 0;1019krb5_ccache ncc = 0;1020int retval = 1;10211022if (!pkrb5_init_context || !filename)1023return 1;10241025if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )1026return 1;10271028code = pkrb5_init_context(&ctx);1029if (code) return 1;10301031strcat(cachename, filename);10321033code = pkrb5_cc_resolve(ctx, cachename, &cc);1034if (code) {1035DebugEvent0("kfwcpcc krb5_cc_resolve failed");1036goto cleanup;1037}10381039code = pkrb5_cc_get_principal(ctx, cc, &princ);1040if (code) {1041DebugEvent0("kfwcpcc krb5_cc_get_principal failed");1042goto cleanup;1043}10441045code = pkrb5_cc_default(ctx, &ncc);1046if (code) {1047DebugEvent0("kfwcpcc krb5_cc_default failed");1048goto cleanup;1049}1050if (!code) {1051code = pkrb5_cc_initialize(ctx, ncc, princ);10521053if (!code)1054code = pkrb5_cc_copy_creds(ctx,cc,ncc);1055if (code) {1056DebugEvent0("kfwcpcc krb5_cc_copy_creds failed");1057goto cleanup;1058}1059}1060if ( ncc ) {1061pkrb5_cc_close(ctx, ncc);1062ncc = 0;1063}10641065retval=0; /* success */10661067cleanup:1068if ( cc ) {1069pkrb5_cc_close(ctx, cc);1070cc = 0;1071}10721073DeleteFile(filename);10741075if ( princ ) {1076pkrb5_free_principal(ctx, princ);1077princ = 0;1078}10791080if (ctx)1081pkrb5_free_context(ctx);10821083return 0;1084}108510861087int1088KFW_copy_file_cache_to_api_cache(char * filename)1089{1090char cachename[MAX_PATH + 8] = "FILE:";1091krb5_context ctx = 0;1092krb5_error_code code;1093krb5_principal princ = 0;1094krb5_ccache cc = 0;1095krb5_ccache ncc = 0;1096char *name = NULL;1097int retval = 1;10981099if (!pkrb5_init_context || !filename)1100return 1;11011102if ( strlen(filename) + sizeof("FILE:") > sizeof(cachename) )1103return 1;11041105code = pkrb5_init_context(&ctx);1106if (code) return 1;11071108strcat(cachename, filename);11091110code = pkrb5_cc_resolve(ctx, cachename, &cc);1111if (code) {1112DebugEvent0("kfwcpcc krb5_cc_resolve failed");1113goto cleanup;1114}11151116code = pkrb5_cc_get_principal(ctx, cc, &princ);1117if (code) {1118DebugEvent0("kfwcpcc krb5_cc_get_principal failed");1119goto cleanup;1120}11211122code = pkrb5_unparse_name(ctx, princ, &name);1123if (code) {1124DebugEvent0("kfwcpcc krb5_unparse_name failed");1125goto cleanup;1126}11271128sprintf(cachename, "API:%s", name);11291130code = pkrb5_cc_resolve(ctx, cachename, &ncc);1131if (code) {1132DebugEvent0("kfwcpcc krb5_cc_default failed");1133goto cleanup;1134}1135if (!code) {1136code = pkrb5_cc_initialize(ctx, ncc, princ);11371138if (!code)1139code = pkrb5_cc_copy_creds(ctx,cc,ncc);1140if (code) {1141DebugEvent0("kfwcpcc krb5_cc_copy_creds failed");1142goto cleanup;1143}1144}1145if ( ncc ) {1146pkrb5_cc_close(ctx, ncc);1147ncc = 0;1148}11491150retval=0; /* success */11511152cleanup:1153if (name)1154pkrb5_free_unparsed_name(ctx, name);11551156if ( cc ) {1157pkrb5_cc_close(ctx, cc);1158cc = 0;1159}11601161DeleteFile(filename);11621163if ( princ ) {1164pkrb5_free_principal(ctx, princ);1165princ = 0;1166}11671168if (ctx)1169pkrb5_free_context(ctx);11701171return 0;1172}117311741175int1176KFW_destroy_tickets_for_principal(char * user)1177{1178krb5_context ctx = 0;1179krb5_error_code code;1180krb5_principal princ = 0;1181krb5_ccache cc = 0;11821183if (!pkrb5_init_context)1184return 0;11851186code = pkrb5_init_context(&ctx);1187if (code) return 1;11881189code = pkrb5_parse_name(ctx, user, &princ);1190if (code) goto loop_cleanup;11911192code = KFW_get_ccache(ctx, princ, &cc);1193if (code) goto loop_cleanup;11941195code = pkrb5_cc_destroy(ctx, cc);1196if (!code) cc = 0;11971198loop_cleanup:1199if ( cc ) {1200pkrb5_cc_close(ctx, cc);1201cc = 0;1202}1203if ( princ ) {1204pkrb5_free_principal(ctx, princ);1205princ = 0;1206}12071208pkrb5_free_context(ctx);1209return 0;1210}121112121213/* There are scenarios in which an interactive logon will not1214* result in the LogonScript being executed. This will result1215* in orphaned cache files being left in the Temp directory.1216* This function will search for cache files in the Temp1217* directory and delete any that are older than five minutes.1218*/1219void1220KFW_cleanup_orphaned_caches(void)1221{1222char * temppath = NULL;1223char * curdir = NULL;1224DWORD count, count2;1225WIN32_FIND_DATA FindFileData;1226HANDLE hFind = INVALID_HANDLE_VALUE;1227FILETIME now;1228ULARGE_INTEGER uli_now;1229FILETIME expired;12301231count = GetTempPath(0, NULL);1232if (count <= 0)1233return;1234temppath = (char *) malloc(count);1235if (!temppath)1236goto cleanup;1237count2 = GetTempPath(count, temppath);1238if (count2 <= 0 || count2 > count)1239goto cleanup;12401241count = GetCurrentDirectory(0, NULL);1242curdir = (char *)malloc(count);1243if (!curdir)1244goto cleanup;1245count2 = GetCurrentDirectory(count, curdir);1246if (count2 <= 0 || count2 > count)1247goto cleanup;12481249if (!SetCurrentDirectory(temppath))1250goto cleanup;12511252GetSystemTimeAsFileTime(&now);1253uli_now.u.LowPart = now.dwLowDateTime;1254uli_now.u.HighPart = now.dwHighDateTime;12551256uli_now.QuadPart -= 3000000000; /* 5 minutes == 3 billion 100 nano seconds */12571258expired.dwLowDateTime = uli_now.u.LowPart;1259expired.dwHighDateTime = uli_now.u.HighPart;12601261hFind = FindFirstFile("kfwlogon-*", &FindFileData);1262if (hFind != INVALID_HANDLE_VALUE) {1263do {1264if (CompareFileTime(&FindFileData.ftCreationTime, &expired) < 0) {1265DebugEvent("Deleting orphaned cache file: \"%s\"", FindFileData.cFileName);1266DeleteFile(FindFileData.cFileName);1267}1268} while ( FindNextFile(hFind, &FindFileData) );1269}12701271SetCurrentDirectory(curdir);12721273cleanup:1274if (temppath)1275free(temppath);1276if (hFind != INVALID_HANDLE_VALUE)1277FindClose(hFind);1278if (curdir)1279free(curdir);1280}128112821283