From 32319900d9e707bb5d90e02193757de586eaedba Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sat, 31 Jan 2004 01:40:58 +0000 Subject: [PATCH] 2004-01-30 Jeffrey Altman * cc_mslsa.c: As per extensive conversations with Doug Engert we have concluded that MS is not specifying a complete set of domain information when it comes to service tickets other than the initial TGT. What happens is the client principal domain cannot be derived from the fields they export. Code has now been added to obtain the domain from the initial TGT and use that when constructing the client principals for all tickets. This behavior can be turned off by setting a registry either on a per-user or a system-wide basis: {HKCU,HKLM}\Software\MIT\Kerberos5 PreserveInitialTicketIdentity = 0x0 (DWORD) ticket: 2139 tags: pullup git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@15990 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/krb5/ccache/ChangeLog | 16 ++++++ src/lib/krb5/ccache/cc_mslsa.c | 102 ++++++++++++++++++++++++++------- 2 files changed, 98 insertions(+), 20 deletions(-) diff --git a/src/lib/krb5/ccache/ChangeLog b/src/lib/krb5/ccache/ChangeLog index e6cb33895..cca7ecb01 100644 --- a/src/lib/krb5/ccache/ChangeLog +++ b/src/lib/krb5/ccache/ChangeLog @@ -1,3 +1,19 @@ +2004-01-30 Jeffrey Altman + + * cc_mslsa.c: As per extensive conversations with Doug Engert we have + concluded that MS is not specifying a complete set of domain information + when it comes to service tickets other than the initial TGT. What happens + is the client principal domain cannot be derived from the fields they + export. Code has now been added to obtain the domain from the initial + TGT and use that when constructing the client principals for all tickets. + + This behavior can be turned off by setting a registry either on a per-user + or a system-wide basis: + + {HKCU,HKLM}\Software\MIT\Kerberos5 + PreserveInitialTicketIdentity = 0x0 (DWORD) + + 2004-01-06 Jeffrey Altman * cc_file.c, cc_memory.c: diff --git a/src/lib/krb5/ccache/cc_mslsa.c b/src/lib/krb5/ccache/cc_mslsa.c index d0b7ac34d..243a86ab1 100644 --- a/src/lib/krb5/ccache/cc_mslsa.c +++ b/src/lib/krb5/ccache/cc_mslsa.c @@ -231,25 +231,78 @@ MSTicketToMITTicket(KERB_EXTERNAL_TICKET *msticket, krb5_context context, krb5_d tmpdata.magic=KV5M_DATA; tmpdata.length=msticket->EncodedTicketSize; tmpdata.data=msticket->EncodedTicket; - // todo: fix this up a little. this is ugly and will break krb_free_data() + + // TODO: fix this up a little. this is ugly and will break krb5_free_data() krb5_copy_data(context, &tmpdata, &newdata); memcpy(ticket, newdata, sizeof(krb5_data)); } +/* + * PreserveInitialTicketIdentity() + * + * This will find the "PreserveInitialTicketIdentity" key in the registry. + * Returns 1 to preserve and 0 to not. + */ + +static DWORD +PreserveInitialTicketIdentity(void) +{ + HKEY hKey; + DWORD size = sizeof(DWORD); + const char *key_path = "Software\\MIT\\Kerberos5"; + const char *value_name = "PreserveInitialTicketIdentity"; + DWORD retval = 1; /* default to Preserve */ + + userkey: + if (RegOpenKeyEx(HKEY_CURRENT_USER, key_path, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) + goto syskey; + if (RegQueryValueEx(hKey, value_name, 0, REG_DWORD, &retval, &size) != ERROR_SUCCESS) + { + RegCloseKey(hKey); + goto syskey; + } + RegCloseKey(hKey); + goto done; + + syskey: + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, key_path, 0, KEY_QUERY_VALUE, &hKey) != ERROR_SUCCESS) + goto done; + if (RegQueryValueEx(hKey, value_name, 0, REG_DWORD, &retval, &size) != ERROR_SUCCESS) + { + RegCloseKey(hKey); + goto done; + } + RegCloseKey(hKey); + + done: + return retval; +} + + static void -MSCredToMITCred(KERB_EXTERNAL_TICKET *msticket, krb5_context context, krb5_creds *creds) +MSCredToMITCred(KERB_EXTERNAL_TICKET *msticket, UNICODE_STRING InitialTicketDomain, + krb5_context context, krb5_creds *creds) { - WCHAR wtmp[128]; + WCHAR wrealm[128]; ZeroMemory(creds, sizeof(krb5_creds)); creds->magic=KV5M_CREDS; - wcsncpy(wtmp, msticket->TargetDomainName.Buffer, - msticket->TargetDomainName.Length/sizeof(WCHAR)); - wtmp[msticket->TargetDomainName.Length/sizeof(WCHAR)]=0; - MSPrincToMITPrinc(msticket->ClientName, wtmp, context, &creds->client); - wcsncpy(wtmp, msticket->DomainName.Buffer, + + // construct Client Principal + if ( PreserveInitialTicketIdentity ) { + wcsncpy(wrealm, InitialTicketDomain.Buffer, InitialTicketDomain.Length/sizeof(WCHAR)); + wrealm[InitialTicketDomain.Length/sizeof(WCHAR)]=0; + } else { + wcsncpy(wrealm, msticket->DomainName.Buffer, msticket->DomainName.Length/sizeof(WCHAR)); + wrealm[msticket->DomainName.Length/sizeof(WCHAR)]=0; + } + MSPrincToMITPrinc(msticket->ClientName, wrealm, context, &creds->client); + + // construct Service Principal + wcsncpy(wrealm, msticket->DomainName.Buffer, msticket->DomainName.Length/sizeof(WCHAR)); - wtmp[msticket->DomainName.Length/sizeof(WCHAR)]=0; - MSPrincToMITPrinc(msticket->ServiceName, wtmp, context, &creds->server); + wrealm[msticket->DomainName.Length/sizeof(WCHAR)]=0; + MSPrincToMITPrinc(msticket->ServiceName, wrealm, context, &creds->server); + MSSessionKeyToMITKeyblock(&msticket->SessionKey, context, &creds->keyblock); MSFlagsToMITFlags(msticket->TicketFlags, &creds->ticket_flags); @@ -1015,8 +1068,8 @@ typedef struct _krb5_lcc_cursor { * id * * Effects: - * creates a file-based cred cache that will reside in the file - * residual. The cache is not opened, but the filename is reserved. + * Acccess the MS Kerberos LSA cache in the current logon session + * Ignore the residual. * * Returns: * A filled in krb5_ccache structure "id". @@ -1077,7 +1130,7 @@ krb5_lcc_resolve (krb5_context context, krb5_ccache *id, const char *residual) if (GetMSTGT(data->LogonHandle, data->PackageId, &msticket)) { /* convert the ticket */ krb5_creds creds; - MSCredToMITCred(msticket, context, &creds); + MSCredToMITCred(msticket, msticket->DomainName, context, &creds); LsaFreeReturnBuffer(msticket); krb5_copy_principal(context, creds.client, &data->princ); @@ -1205,7 +1258,7 @@ krb5_lcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor, { krb5_lcc_cursor *lcursor = (krb5_lcc_cursor *) *cursor; krb5_lcc_data *data = (krb5_lcc_data *)id->data; - KERB_EXTERNAL_TICKET *msticket; + KERB_EXTERNAL_TICKET *msticket, * mstgt; if ( lcursor->index >= lcursor->response->CountOfTickets ) return KRB5_CC_END; @@ -1215,10 +1268,15 @@ krb5_lcc_next_cred(krb5_context context, krb5_ccache id, krb5_cc_cursor *cursor, return KRB5_FCC_INTERNAL; /* convert the ticket */ - MSCredToMITCred(msticket, context, creds); - - LsaFreeReturnBuffer(msticket); - return KRB5_OK; + if (GetMSTGT(data->LogonHandle, data->PackageId, &mstgt)) { + MSCredToMITCred(msticket, mstgt->DomainName, context, creds); + LsaFreeReturnBuffer(mstgt); + LsaFreeReturnBuffer(msticket); + return KRB5_OK; + } else { + LsaFreeReturnBuffer(msticket); + return KRB5_FCC_INTERNAL; + } } /* @@ -1297,7 +1355,7 @@ krb5_lcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields, { krb5_error_code kret = KRB5_OK; krb5_lcc_data *data = (krb5_lcc_data *)id->data; - KERB_EXTERNAL_TICKET *msticket = 0; + KERB_EXTERNAL_TICKET *msticket = 0, *mstgt = 0; krb5_creds * mcreds_noflags; krb5_creds fetchcreds; @@ -1337,7 +1395,9 @@ krb5_lcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields, } /* convert the ticket */ - MSCredToMITCred(msticket, context, &fetchcreds); + GetMSTGT(data->LogonHandle, data->PackageId, &mstgt); + + MSCredToMITCred(msticket, mstgt ? mstgt->DomainName : msticket->DomainName, context, &fetchcreds); /* check to see if this ticket matches the request using logic from * krb5_cc_retrieve_cred_default() @@ -1350,6 +1410,8 @@ krb5_lcc_retrieve(krb5_context context, krb5_ccache id, krb5_flags whichfields, } cleanup: + if ( mstgt ) + LsaFreeReturnBuffer(mstgt); if ( msticket ) LsaFreeReturnBuffer(msticket); if ( mcreds_noflags ) -- 2.26.2