From: Sarah Day Date: Thu, 18 Feb 2016 21:54:27 +0000 (-0500) Subject: Default to LSA when TGT in LSA is inaccessible X-Git-Tag: krb5-1.15-beta1~229 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=33b862799efa65b16e2acd1510c84d9f1ded2cbb;p=thirdparty%2Fkrb5.git Default to LSA when TGT in LSA is inaccessible When UAC is enabled and a domain user with Administrator privileges logs in, the TGT is inaccessible. Access to the TGT in a UAC-restricted session may allow a non-elevated user to bypass the UAC. In a UAC-restricted session, ms2mit copies the current tickets from the LSA ccache to the API ccache except the TGT, effectively preventing a user session from getting additional service tickets while appearing, for some purposes, to have a usable ccache. Another bug is that ms2mit always copies from the LSA ccache to the default ccache, even if the default ccache is itself the LSA ccache. New behavior: * If the TGT is accessible in the LSA ccache, copy the LSA ccache to the API ccache. * Set the registry key for the default ccname to "API:" if the copy occurred, or to "MSLSA:" if it didn't occur. [tlyu@mit.edu: edit commit message] ticket: 8390 --- diff --git a/src/windows/ms2mit/ms2mit.c b/src/windows/ms2mit/ms2mit.c index 9018707f04..ebc9abd2e7 100644 --- a/src/windows/ms2mit/ms2mit.c +++ b/src/windows/ms2mit/ms2mit.c @@ -23,9 +23,11 @@ * or implied warranty. */ +#include "k5-int.h" #include "krb5.h" #include #include +#include extern int optind; extern char *optarg; @@ -39,6 +41,52 @@ xusage(void) exit(1); } +/* Return true if princ is a local (not cross-realm) krbtgt principal. */ +krb5_boolean +is_local_tgt(krb5_principal princ) +{ + return princ->length == 2 && + data_eq_string(princ->data[0], KRB5_TGS_NAME) && + data_eq(princ->realm, princ->data[1]); +} + +/* + * Check if a ccache has any tickets. + */ +static krb5_error_code +cc_has_tickets(krb5_context kcontext, krb5_ccache ccache, int *has_tickets) +{ + krb5_error_code code; + krb5_cc_cursor cursor; + krb5_creds creds; + krb5_timestamp now = time(0); + + *has_tickets = 0; + + code = krb5_cc_set_flags(kcontext, ccache, KRB5_TC_NOTICKET); + if (code) + return code; + + code = krb5_cc_start_seq_get(kcontext, ccache, &cursor); + if (code) + return code; + + while (!*has_tickets) { + code = krb5_cc_next_cred(kcontext, ccache, &cursor, &creds); + if (code) + break; + + if (!krb5_is_config_principal(kcontext, creds.server) && + creds.times.endtime > now) + *has_tickets = 1; + + krb5_free_cred_contents(kcontext, &creds); + } + krb5_cc_end_seq_get(kcontext, ccache, &cursor); + + return 0; +} + int main(int argc, char *argv[]) { @@ -49,7 +97,8 @@ main(int argc, char *argv[]) krb5_cc_cursor cursor; krb5_creds creds; krb5_principal princ = NULL; - int initial_ticket = 0; + int found_tgt = 0; + int has_tickets; int option; char * ccachestr = 0; @@ -78,36 +127,36 @@ main(int argc, char *argv[]) goto cleanup; } - if (code = krb5_cc_set_flags(kcontext, mslsa_ccache, KRB5_TC_NOTICKET)) { - com_err(argv[0], code, "while setting KRB5_TC_NOTICKET flag"); - goto cleanup; - } - - /* Enumerate tickets from cache looking for an initial ticket */ + /* Enumerate tickets from cache looking for a TGT */ if ((code = krb5_cc_start_seq_get(kcontext, mslsa_ccache, &cursor))) { com_err(argv[0], code, "while initiating the cred sequence of MS LSA ccache"); goto cleanup; } - while (!(code = krb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds))) - { - if ( creds.ticket_flags & TKT_FLG_INITIAL ) { - krb5_free_cred_contents(kcontext, &creds); - initial_ticket = 1; + while (!found_tgt) { + code = krb5_cc_next_cred(kcontext, mslsa_ccache, &cursor, &creds); + if (code) break; - } + + /* Check if the ticket is a TGT */ + if (is_local_tgt(creds.server)) + found_tgt = 1; + krb5_free_cred_contents(kcontext, &creds); } krb5_cc_end_seq_get(kcontext, mslsa_ccache, &cursor); - if (code = krb5_cc_set_flags(kcontext, mslsa_ccache, 0)) { - com_err(argv[0], code, "while clearing flags"); - goto cleanup; - } - - if ( !initial_ticket ) { + if (!found_tgt) { fprintf(stderr, "%s: Initial Ticket Getting Tickets are not available from the MS LSA\n", argv[0]); + /* Only set the LSA cache as the default if it actually has tickets. */ + code = cc_has_tickets(kcontext, mslsa_ccache, &has_tickets); + if (code) + goto cleanup; + + if (has_tickets) + code = krb5int_cc_user_set_default_name(kcontext, "MSLSA:"); + goto cleanup; } @@ -119,7 +168,7 @@ main(int argc, char *argv[]) if (ccachestr) code = krb5_cc_resolve(kcontext, ccachestr, &ccache); else - code = krb5_cc_default(kcontext, &ccache); + code = krb5_cc_resolve(kcontext, "API:", &ccache); if (code) { com_err(argv[0], code, "while getting default ccache"); goto cleanup; @@ -134,6 +183,16 @@ main(int argc, char *argv[]) goto cleanup; } + /* Don't try and set the default cache if the cache name was specified. */ + if (ccachestr == NULL) { + /* On success set the default cache to API. */ + code = krb5int_cc_user_set_default_name(kcontext, "API:"); + if (code) { + com_err(argv[0], code, "when setting default to API"); + goto cleanup; + } + } + cleanup: krb5_free_principal(kcontext, princ); if (ccache != NULL)