diff options
author | Kevin Wasserman <kevin.wasserman@painless-security.com> | 2012-07-23 04:30:27 -0400 |
---|---|---|
committer | Ben Kaduk <kaduk@mit.edu> | 2012-08-24 12:22:58 -0400 |
commit | 9bc411e72fce5bed3ed00ae5b09f8c239309bae0 (patch) | |
tree | 0b457e8c5e0d1201f2bc4a58e2540ca3eba44ca4 /src/windows/leashdll | |
parent | dbfd93ea15b12472e4612af928f8baabb2cda611 (diff) | |
download | krb5-9bc411e72fce5bed3ed00ae5b09f8c239309bae0.tar.gz krb5-9bc411e72fce5bed3ed00ae5b09f8c239309bae0.tar.xz krb5-9bc411e72fce5bed3ed00ae5b09f8c239309bae0.zip |
kfw support for multiple identities
We need a sense of what the default identity is, then, with a way
to set it and list it.
The memory management model changes some, as well.
Use a bold font to indicate the current default identity in the
GUI; while here use an italic font for expired credentials.
In the process, rip out some krb4 remenants, and remove ancient
code conditional on the lack of KRB5_TC_NOTICKET.
Define USE_MESSAGE_BOX when building leash and use MessageBox().
[kaduk@mit.edu: adjust for style, flesh out commit message.]
ticket: 7253 (new)
queue: kfw
target_version: 1.10.4
tags: pullup
Diffstat (limited to 'src/windows/leashdll')
-rw-r--r-- | src/windows/leashdll/AFSroutines.c | 3 | ||||
-rw-r--r-- | src/windows/leashdll/krb5routines.c | 790 | ||||
-rw-r--r-- | src/windows/leashdll/leash-int.h | 4 | ||||
-rw-r--r-- | src/windows/leashdll/leashdll.h | 15 | ||||
-rw-r--r-- | src/windows/leashdll/leashw32.def | 1 | ||||
-rw-r--r-- | src/windows/leashdll/lshfunc.c | 45 |
6 files changed, 389 insertions, 469 deletions
diff --git a/src/windows/leashdll/AFSroutines.c b/src/windows/leashdll/AFSroutines.c index 3c1dbc02d3..f04ab29792 100644 --- a/src/windows/leashdll/AFSroutines.c +++ b/src/windows/leashdll/AFSroutines.c @@ -207,8 +207,7 @@ not_an_API_LeashAFSGetToken( list->name = strdup(aclient.name); list->inst = aclient.instance[0] ? strdup(aclient.instance) : NULL; list->realm = strdup(aclient.cell); - list->tktEncType = NULL; - list->keyEncType = NULL; + list->encTypes = NULL; list->addrCount = 0; list->addrList = NULL; diff --git a/src/windows/leashdll/krb5routines.c b/src/windows/leashdll/krb5routines.c index 48240bfc97..8de3179004 100644 --- a/src/windows/leashdll/krb5routines.c +++ b/src/windows/leashdll/krb5routines.c @@ -315,412 +315,326 @@ one_addr(krb5_address *a) return(retstr); } -/* - * LeashKRB5GetTickets() treats krbv5Context as an in/out variable. - * If the caller does not provide a krb5_context, one will be allocated. - * It is up to the caller to ensure that the context is eventually freed. - * A context can be returned even if the function returns an error. - */ +static void +CredToTicketInfo(krb5_creds KRBv5Credentials, TICKETINFO *ticketinfo) +{ + ticketinfo->issued = KRBv5Credentials.times.starttime; + ticketinfo->valid_until = KRBv5Credentials.times.endtime; + ticketinfo->renew_until = + KRBv5Credentials.ticket_flags & TKT_FLG_RENEWABLE ? + KRBv5Credentials.times.renew_till : 0; + _tzset(); + if (ticketinfo->valid_until - time(0) <= 0L) + ticketinfo->btickets = EXPD_TICKETS; + else + ticketinfo->btickets = GOOD_TICKETS; +} -long -not_an_API_LeashKRB5GetTickets( - TICKETINFO * ticketinfo, - TicketList** ticketList, - krb5_context *krbv5Context - ) +static int +CredToTicketList(krb5_context ctx, krb5_creds KRBv5Credentials, + char *PrincipalName, TicketList ***ticketListTail) { -#ifdef NO_KRB5 - return(0); -#else - krb5_context ctx = 0; - krb5_ccache cache = 0; - krb5_error_code code; - krb5_principal KRBv5Principal; - krb5_flags flags = 0; - krb5_cc_cursor KRBv5Cursor; - krb5_creds KRBv5Credentials; - krb5_ticket *tkt=NULL; - int StartMonth; - int EndMonth; - int RenewMonth; - int StartDay; - int EndDay; - int RenewDay; - char StartTimeString[256]; - char EndTimeString[256]; - char RenewTimeString[256]; - char fill; - char *ClientName; - char *PrincipalName; - char *sServerName; - char Buffer[256]; - char Months[12][4] = {"Jan\0", "Feb\0", "Mar\0", "Apr\0", "May\0", "Jun\0", "Jul\0", "Aug\0", "Sep\0", "Oct\0", "Nov\0", "Dec\0"}; - char StartTime[16]; - char EndTime[16]; - char RenewTime[16]; - char temp[128]; - char *sPtr; - char *ticketFlag; - LPCSTR functionName; - TicketList *list = NULL; - - if ( ticketinfo ) { - ticketinfo->btickets = NO_TICKETS; - ticketinfo->principal[0] = '\0'; - } + krb5_error_code code = 0; + krb5_ticket *tkt=NULL; + char *sServerName = NULL; + char Buffer[256]; + char *ticketFlag; + char *functionName = NULL; + TicketList *list = NULL; + + functionName = "krb5_unparse_name()"; + code = (*pkrb5_unparse_name)(ctx, KRBv5Credentials.server, &sServerName); + if (code) + goto cleanup; - if ((code = Leash_krb5_initialize(&(*krbv5Context), &cache))) - return(code); + if (!KRBv5Credentials.times.starttime) + KRBv5Credentials.times.starttime = KRBv5Credentials.times.authtime; - ctx = (*krbv5Context); + memset(Buffer, '\0', sizeof(Buffer)); -#ifdef KRB5_TC_NOTICKET - flags = KRB5_TC_NOTICKET; -#endif - if ((code = pkrb5_cc_set_flags(ctx, cache, flags))) - { - if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND) - Leash_krb5_error(code, "krb5_cc_set_flags()", 0, &ctx, - &cache); - else if ((code == KRB5_FCC_NOFILE || code == KRB5_CC_NOTFOUND)) - { - if (cache != NULL) - pkrb5_cc_close(ctx, cache); - } - return code; - } + ticketFlag = GetTicketFlag(&KRBv5Credentials); - if ((code = pkrb5_cc_get_principal(ctx, cache, &KRBv5Principal))) - { - if (code != KRB5_FCC_NOFILE && code != KRB5_CC_NOTFOUND) - Leash_krb5_error(code, "krb5_cc_get_principal()", 0, &ctx, &cache); - else if ((code == KRB5_FCC_NOFILE || code == KRB5_CC_NOTFOUND)) - { - if (cache != NULL) - pkrb5_cc_close(ctx, cache); - } - return code; + // @fixme: calloc for ptr init + list = calloc(1, sizeof(TicketList)); + if (list == NULL) { + code = ENOMEM; + functionName = "calloc()"; + goto cleanup; } - - PrincipalName = NULL; - ClientName = NULL; - sServerName = NULL; - if ((code = (*pkrb5_unparse_name)(ctx, KRBv5Principal, - (char **)&PrincipalName))) - { - if (PrincipalName != NULL) - (*pkrb5_free_unparsed_name)(ctx, PrincipalName); - - (*pkrb5_free_principal)(ctx, KRBv5Principal); - if (ctx != NULL) - { - if (cache != NULL) - pkrb5_cc_close(ctx, cache); - } - - return(code); + list->service = strdup(sServerName); + if (!list->service) { + code = ENOMEM; + functionName = "calloc()"; + goto cleanup; } - - if (!strcspn(PrincipalName, "@" )) - { - if (PrincipalName != NULL) - (*pkrb5_free_unparsed_name)(ctx, PrincipalName); - - (*pkrb5_free_principal)(ctx, KRBv5Principal); - if (ctx != NULL) - { - if (cache != NULL) - pkrb5_cc_close(ctx, cache); - } - - return(code); + list->issued = KRBv5Credentials.times.starttime; + list->valid_until = KRBv5Credentials.times.endtime; + if (KRBv5Credentials.ticket_flags & TKT_FLG_RENEWABLE) + list->renew_until = KRBv5Credentials.times.renew_till; + else + list->renew_until = 0; + + if (!pkrb5_decode_ticket(&KRBv5Credentials.ticket, &tkt)) { + wsprintf(Buffer, "Session Key: %s Ticket: %s", + etype_string(KRBv5Credentials.keyblock.enctype), + etype_string(tkt->enc_part.enctype)); + pkrb5_free_ticket(ctx, tkt); + tkt = NULL; + } else { + wsprintf(Buffer, "Session Key: %s", + etype_string(KRBv5Credentials.keyblock.enctype)); } - if ( strcmp(ticketinfo->principal, PrincipalName) ) - wsprintf(ticketinfo->principal, "%s", PrincipalName); - - (*pkrb5_free_principal)(ctx, KRBv5Principal); - if ((code = pkrb5_cc_start_seq_get(ctx, cache, &KRBv5Cursor))) - { - functionName = "krb5_cc_start_seq_get()"; - goto on_error; + list->encTypes = calloc(1, strlen(Buffer)+1); + if (list->encTypes == NULL) { + functionName = "calloc()"; + code = ENOMEM; + goto cleanup; } + strcpy(list->encTypes, Buffer); - memset(&KRBv5Credentials, '\0', sizeof(KRBv5Credentials)); - - while (!(code = pkrb5_cc_next_cred(ctx, cache, &KRBv5Cursor, &KRBv5Credentials))) - { - if ((*pkrb5_is_config_principal)(ctx, KRBv5Credentials.server)) - { /* skip configuration credentials */ - (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials); - continue; - } - if (!list) - { - list = (TicketList*) calloc(1, sizeof(TicketList)); - (*ticketList) = list; - } - else - { - list->next = (struct TicketList*) calloc(1, sizeof(TicketList)); - list = (TicketList*) list->next; +cleanup: + if (code) { + Leash_krb5_error(code, functionName, 0, &ctx, NULL); + if (list != NULL) { + not_an_API_LeashFreeTicketList(&list); } + } else { + **ticketListTail = list; + *ticketListTail = &list->next; + } - if ((*pkrb5_unparse_name)(ctx, KRBv5Credentials.client, &ClientName)) - { - (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials); - Leash_krb5_error(code, "krb5_free_cred_contents()", 0, &ctx, &cache); - - if (ClientName != NULL) - (*pkrb5_free_unparsed_name)(ctx, ClientName); + if (sServerName != NULL) + (*pkrb5_free_unparsed_name)(ctx, sServerName); - ClientName = NULL; - sServerName = NULL; - continue; - } + return code; +} - if ((*pkrb5_unparse_name)(ctx, KRBv5Credentials.server, &sServerName)) - { - (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials); - Leash_krb5_error(code, "krb5_free_cred_contents()", 0, &ctx, &cache); +int +do_ccache(krb5_context ctx, + krb5_ccache cache, + TICKETINFO ***ticketInfoTail) +{ + krb5_cc_cursor cur; + krb5_creds creds; + krb5_principal princ = NULL; + krb5_flags flags; + krb5_error_code code; + char *defname = NULL; + char *functionName = NULL; + TicketList **ticketListTail; + TICKETINFO *ticketinfo; - if (ClientName != NULL) - (*pkrb5_free_unparsed_name)(ctx, ClientName); + flags = 0; /* turns off OPENCLOSE mode */ + code = pkrb5_cc_set_flags(ctx, cache, flags); + if (code) { + functionName = "krb5_cc_set_flags"; + goto cleanup; + } + code = pkrb5_cc_get_principal(ctx, cache, &princ); + if (code) { + functionName = "krb5_cc_get_principal"; + goto cleanup; + } + code = pkrb5_unparse_name(ctx, princ, &defname); + if (code) { + functionName = "krb5_unparse_name"; + goto cleanup; + } + code = pkrb5_cc_start_seq_get(ctx, cache, &cur); + if (code) { + functionName = "krb5_cc_start_seq_get"; + goto cleanup; + } - ClientName = NULL; - sServerName = NULL; + ticketinfo = calloc(1, sizeof(TICKETINFO)); + if (ticketinfo == NULL) { + functionName = "calloc"; + code = ENOMEM; + goto cleanup; + } + ticketinfo->next = NULL; + ticketinfo->ticket_list = NULL; + ticketinfo->principal = strdup(defname); + if (ticketinfo->principal == NULL) { + functionName = "strdup"; + code = ENOMEM; + goto cleanup; + } + ticketinfo->ccache_name = strdup(pkrb5_cc_get_name(ctx, cache)); + if (ticketinfo->ccache_name == NULL) { + functionName = "strdup"; + code = ENOMEM; + goto cleanup; + } + **ticketInfoTail = ticketinfo; + *ticketInfoTail = &ticketinfo->next; + ticketListTail = &ticketinfo->ticket_list; + while (!(code = pkrb5_cc_next_cred(ctx, cache, &cur, &creds))) { + if (pkrb5_is_config_principal(ctx, creds.server)) continue; + CredToTicketList(ctx, creds, defname, &ticketListTail); + CredToTicketInfo(creds, ticketinfo); + pkrb5_free_cred_contents(ctx, &creds); + } + if (code == KRB5_CC_END) { + code = pkrb5_cc_end_seq_get(ctx, cache, &cur); + if (code) { + functionName = "krb5_cc_end_seq_get"; + goto cleanup; } - - if (!KRBv5Credentials.times.starttime) - KRBv5Credentials.times.starttime = KRBv5Credentials.times.authtime; - - fill = ' '; - memset(StartTimeString, '\0', sizeof(StartTimeString)); - memset(EndTimeString, '\0', sizeof(EndTimeString)); - memset(RenewTimeString, '\0', sizeof(RenewTimeString)); - (*pkrb5_timestamp_to_sfstring)((krb5_timestamp)KRBv5Credentials.times.starttime, StartTimeString, 17, &fill); - (*pkrb5_timestamp_to_sfstring)((krb5_timestamp)KRBv5Credentials.times.endtime, EndTimeString, 17, &fill); - if (KRBv5Credentials.times.renew_till >= 0) - (*pkrb5_timestamp_to_sfstring)((krb5_timestamp)KRBv5Credentials.times.renew_till, RenewTimeString, 17, &fill); - memset(temp, '\0', sizeof(temp)); - memcpy(temp, StartTimeString, 2); - StartDay = atoi(temp); - memset(temp, (int)'\0', (size_t)sizeof(temp)); - memcpy(temp, EndTimeString, 2); - EndDay = atoi(temp); - memset(temp, (int)'\0', (size_t)sizeof(temp)); - memcpy(temp, RenewTimeString, 2); - RenewDay = atoi(temp); - - memset(temp, '\0', sizeof(temp)); - memcpy(temp, &StartTimeString[3], 2); - StartMonth = atoi(temp); - memset(temp, '\0', sizeof(temp)); - memcpy(temp, &EndTimeString[3], 2); - EndMonth = atoi(temp); - memset(temp, '\0', sizeof(temp)); - memcpy(temp, &RenewTimeString[3], 2); - RenewMonth = atoi(temp); - - while (1) - { - if ((sPtr = strrchr(StartTimeString, ' ')) == NULL) - break; - - if (strlen(sPtr) != 1) - break; - - (*sPtr) = 0; + flags = KRB5_TC_OPENCLOSE; /* turns on OPENCLOSE mode */ + code = pkrb5_cc_set_flags(ctx, cache, flags); + if (code) { + functionName = "krb5_cc_set_flags"; + goto cleanup; } + } else { + functionName = "krb5_cc_next_cred"; + goto cleanup; + } +cleanup: + if (code) { + Leash_krb5_error(code, functionName, 0, NULL, NULL); + } + if (princ) + pkrb5_free_principal(ctx, princ); + if (defname) + pkrb5_free_unparsed_name(ctx, defname); + return code ? 1 : 0; +} - while (1) - { - if ((sPtr = strrchr(EndTimeString, ' ')) == NULL) - break; - - if (strlen(sPtr) != 1) - break; - (*sPtr) = 0; - } +// +// Returns 0 for success, 1 for failure +// +int +do_all_ccaches(krb5_context ctx, TICKETINFO **ticketinfotail) +{ + krb5_error_code code; + krb5_ccache cache; + krb5_cccol_cursor cursor; + int retval = 0; + char *functionName = NULL; - while (1) - { - if ((sPtr = strrchr(RenewTimeString, ' ')) == NULL) - break; + code = pkrb5_cccol_cursor_new(ctx, &cursor); + if (code) { + functionName = "krb5_cccol_cursor_new"; + goto cleanup; + } + retval = 0; + while (!(code = pkrb5_cccol_cursor_next(ctx, cursor, &cache)) && + cache != NULL) { + // Note that ticketList will be updated here to point to the tail + // of the list but the caller of this function will remain with a + // pointer to the head. + do_ccache(ctx, cache, &ticketinfotail); + pkrb5_cc_close(ctx, cache); + } + if (code) + functionName = "krb5_cccol_cursor_next"; + pkrb5_cccol_cursor_free(ctx, &cursor); +cleanup: + if (code) { + Leash_krb5_error(code, functionName, 0, NULL, NULL); + } + return retval; +} - if (strlen(sPtr) != 1) - break; +static void FreeTicketInfo(TICKETINFO *ticketinfo) +{ + if (ticketinfo->principal) { + free(ticketinfo->principal); + ticketinfo->principal = NULL; + } + if (ticketinfo->ccache_name) { + free(ticketinfo->ccache_name); + ticketinfo->ccache_name = NULL; + } + if (ticketinfo->ticket_list) + not_an_API_LeashFreeTicketList(&ticketinfo->ticket_list); +} - (*sPtr) = 0; +long +not_an_API_LeashKRB5FreeTickets(TICKETINFO *ticketinfo) +{ + TICKETINFO *initial = ticketinfo; // @TEMP fixme + TICKETINFO *next; + while (ticketinfo != NULL) { + next = ticketinfo->next; + FreeTicketInfo(ticketinfo); + // @TEMP fixme + if (ticketinfo != initial) { + free(ticketinfo); } + ticketinfo = next; + } + return 0; +} - memset(StartTime, '\0', sizeof(StartTime)); - memcpy(StartTime, &StartTimeString[strlen(StartTimeString) - 5], 5); - memset(EndTime, '\0', sizeof(EndTime)); - memcpy(EndTime, &EndTimeString[strlen(EndTimeString) - 5], 5); - memset(RenewTime, '\0', sizeof(RenewTime)); - memcpy(RenewTime, &RenewTimeString[strlen(RenewTimeString) - 5], 5); - - memset(temp, '\0', sizeof(temp)); - strcpy(temp, ClientName); - if (!strcmp(ClientName, PrincipalName)) - memset(temp, '\0', sizeof(temp)); +/* + * LeashKRB5GetTickets() treats krbv5Context as an in/out variable. + * If the caller does not provide a krb5_context, one will be allocated. + * It is up to the caller to ensure that the context is eventually freed. + * A context can be returned even if the function returns an error. + */ - memset(Buffer, '\0', sizeof(Buffer)); +long +not_an_API_LeashKRB5GetTickets(TICKETINFO *ticketinfo, + krb5_context *krbv5Context) +{ + krb5_error_code code; + krb5_principal me = 0; + krb5_context ctx = 0; + krb5_ccache cache = 0; + char *PrincipalName = NULL; - ticketFlag = GetTicketFlag(&KRBv5Credentials); + code = Leash_krb5_initialize(krbv5Context); + if (code) + return code; - if (KRBv5Credentials.ticket_flags & TKT_FLG_RENEWABLE) { - wsprintf(Buffer,"%s %02d %s %s %02d %s [%s %02d %s] %s %s %s", - Months[StartMonth - 1], StartDay, StartTime, - Months[EndMonth - 1], EndDay, EndTime, - Months[RenewMonth - 1], RenewDay, RenewTime, - sServerName, - temp, ticketFlag); - } else { - wsprintf(Buffer,"%s %02d %s %s %02d %s %s %s %s", - Months[StartMonth - 1], StartDay, StartTime, - Months[EndMonth - 1], EndDay, EndTime, - sServerName, - temp, ticketFlag); - } - list->theTicket = (char*) calloc(1, strlen(Buffer)+1); - if (!list->theTicket) - { -#ifdef USE_MESSAGE_BOX - MessageBox(NULL, "Memory Error", "Error", MB_OK); -#endif /* USE_MESSAGE_BOX */ - return ENOMEM; - } - strcpy(list->theTicket, Buffer); - list->name = NULL; - list->inst = NULL; - list->realm = NULL; - - if ( !pkrb5_decode_ticket(&KRBv5Credentials.ticket, &tkt)) { - wsprintf(Buffer, "Ticket Encryption Type: %s", etype_string(tkt->enc_part.enctype)); - list->tktEncType = (char*) calloc(1, strlen(Buffer)+1); - if (!list->tktEncType) - { -#ifdef USE_MESSAGE_BOX - MessageBox(NULL, "Memory Error", "Error", MB_OK); -#endif /* USE_MESSAGE_BOX */ - return ENOMEM; - } - strcpy(list->tktEncType, Buffer); + ctx = *krbv5Context; - pkrb5_free_ticket(ctx, tkt); - tkt = NULL; - } else { - list->tktEncType = NULL; - } + // @TEMP fixme; shouldn't be necessary + // save default principal name in ticketinfo + if (ticketinfo != NULL) { + ticketinfo->btickets = NO_TICKETS; + ticketinfo->principal = NULL; + ticketinfo->ccache_name = NULL; + ticketinfo->next = NULL; + ticketinfo->ticket_list = NULL; - wsprintf(Buffer, "Session Key Type: %s", etype_string(KRBv5Credentials.keyblock.enctype)); - list->keyEncType = (char*) calloc(1, strlen(Buffer)+1); - if (!list->keyEncType) - { -#ifdef USE_MESSAGE_BOX - MessageBox(NULL, "Memory Error", "Error", MB_OK); -#endif /* USE_MESSAGE_BOX */ - return ENOMEM; + code = pkrb5_cc_default(ctx, &cache); + if (code) + goto cleanup; + ticketinfo->ccache_name = strdup(pkrb5_cc_get_name(ctx, cache)); + if (ticketinfo->ccache_name == NULL) { + code = ENOMEM; + goto cleanup; } - strcpy(list->keyEncType, Buffer); - - if ( KRBv5Credentials.addresses && KRBv5Credentials.addresses[0] ) { - int n = 0; - while ( KRBv5Credentials.addresses[n] ) - n++; - list->addrList = calloc(1, n * sizeof(char *)); - if (!list->addrList) { -#ifdef USE_MESSAGE_BOX - MessageBox(NULL, "Memory Error", "Error", MB_OK); -#endif /* USE_MESSAGE_BOX */ - return ENOMEM; + if (!pkrb5_cc_get_principal(ctx, cache, &me)) { + code = (*pkrb5_unparse_name)(ctx, me, &PrincipalName); + if (code) + goto cleanup; + if (PrincipalName) { + ticketinfo->principal = strdup(PrincipalName); + pkrb5_free_unparsed_name(ctx, PrincipalName); } - list->addrCount = n; - for ( n=0; n<list->addrCount; n++ ) { - wsprintf(Buffer, "Address: %s", one_addr(KRBv5Credentials.addresses[n])); - list->addrList[n] = (char*) calloc(1, strlen(Buffer)+1); - if (!list->addrList[n]) - { -#ifdef USE_MESSAGE_BOX - MessageBox(NULL, "Memory Error", "Error", MB_OK); -#endif /* USE_MESSAGE_BOX */ - return ENOMEM; - } - strcpy(list->addrList[n], Buffer); - } - } - - ticketinfo->issue_date = KRBv5Credentials.times.starttime; - ticketinfo->lifetime = KRBv5Credentials.times.endtime - KRBv5Credentials.times.starttime; - ticketinfo->renew_till = KRBv5Credentials.ticket_flags & TKT_FLG_RENEWABLE ? - KRBv5Credentials.times.renew_till : 0; - _tzset(); - if ( ticketinfo->issue_date + ticketinfo->lifetime - time(0) <= 0L ) - ticketinfo->btickets = EXPD_TICKETS; - else - ticketinfo->btickets = GOOD_TICKETS; - - if (ClientName != NULL) - (*pkrb5_free_unparsed_name)(ctx, ClientName); - - if (sServerName != NULL) - (*pkrb5_free_unparsed_name)(ctx, sServerName); - - ClientName = NULL; - sServerName = NULL; - (*pkrb5_free_cred_contents)(ctx, &KRBv5Credentials); - } - - if (PrincipalName != NULL) - (*pkrb5_free_unparsed_name)(ctx, PrincipalName); - - if (ClientName != NULL) - (*pkrb5_free_unparsed_name)(ctx, ClientName); - - if (sServerName != NULL) - (*pkrb5_free_unparsed_name)(ctx, sServerName); - - if ((code == KRB5_CC_END) || (code == KRB5_CC_NOTFOUND)) - { - if ((code = pkrb5_cc_end_seq_get(ctx, cache, &KRBv5Cursor))) - { - functionName = "krb5_cc_end_seq_get()"; - goto on_error; } - - flags = KRB5_TC_OPENCLOSE; -#ifdef KRB5_TC_NOTICKET - flags |= KRB5_TC_NOTICKET; -#endif - if ((code = pkrb5_cc_set_flags(ctx, cache, flags))) - { - functionName = "krb5_cc_set_flags()"; - goto on_error; - } - } - else - { - functionName = "krb5_cc_next_cred()"; - goto on_error; - } - - if (ctx != NULL) - { - if (cache != NULL) - pkrb5_cc_close(ctx, cache); } - return(code); + do_all_ccaches(*krbv5Context, &ticketinfo->next); + // @TEMP aggregate ticket info here? - on_error: - Leash_krb5_error(code, functionName, 0, &(*krbv5Context), &cache); - return(code); -#endif //!NO_KER5 +cleanup: + if (code) + not_an_API_LeashKRB5FreeTickets(ticketinfo); + if (cache) + pkrb5_cc_close(ctx, cache); + if (me) + pkrb5_free_principal(ctx, me); + return code; } @@ -831,13 +745,15 @@ DWORD publicIP #else krb5_error_code code = 0; krb5_context ctx = 0; - krb5_ccache cc = 0; + krb5_ccache cc = 0, defcache = 0; krb5_principal me = 0; char* name = 0; krb5_creds my_creds; krb5_get_init_creds_opt * options = NULL; krb5_address ** addrs = NULL; int i = 0, addr_count = 0; + int cc_new = 0; + const char * deftype = NULL; if (!pkrb5_init_context) return 0; @@ -857,12 +773,29 @@ DWORD publicIP code = pkrb5_get_init_creds_opt_alloc(ctx, &options); if (code) goto cleanup; - code = pkrb5_cc_default(ctx, &cc); + code = pkrb5_cc_default(ctx, &defcache); if (code) goto cleanup; code = pkrb5_parse_name(ctx, principal_name, &me); if (code) goto cleanup; + deftype = pkrb5_cc_get_type(ctx, defcache); + if (me != NULL && pkrb5_cc_support_switch(ctx, deftype)) { + /* Use an existing cache for the specified principal if we can. */ + code = pkrb5_cc_cache_match(ctx, me, &cc); + if (code != 0 && code != KRB5_CC_NOTFOUND) + goto cleanup; + if (code == KRB5_CC_NOTFOUND) { + code = pkrb5_cc_new_unique(ctx, deftype, NULL, &cc); + if (code) + goto cleanup; + cc_new = 1; + } + pkrb5_cc_close(ctx, defcache); + } else { + cc = defcache; + } + code = pkrb5_unparse_name(ctx, me, &name); if (code) goto cleanup; @@ -957,7 +890,24 @@ DWORD publicIP 0, // start time 0, // service name options); + // @TODO: make this an option + if ((!code) && (cc != defcache)) { + code = pkrb5_cc_switch(ctx, cc); + if (!code) { + const char *cctype = pkrb5_cc_get_type(ctx, cc); + if (cctype != NULL) { + char defname[20]; + sprintf_s(defname, sizeof(defname), "%s:", cctype); + pkrb5int_cc_user_set_default_name(ctx, defname); + } + } + } cleanup: + if (code && cc_new) { + // don't leave newly-generated empty ccache lying around on failure + pkrb5_cc_destroy(ctx, cc); + cc = NULL; + } if ( addrs ) { for ( i=0;i<addr_count;i++ ) { if ( addrs[i] ) { @@ -1002,7 +952,11 @@ Leash_krb5_kdestroy( ctx = NULL; cache = NULL; - if (rc = Leash_krb5_initialize(&ctx, &cache)) + rc = Leash_krb5_initialize(&ctx); + if (rc) + return(rc); + + if (rc = pkrb5_cc_default(ctx, &cache)) return(rc); rc = pkrb5_cc_destroy(ctx, cache); @@ -1015,56 +969,62 @@ Leash_krb5_kdestroy( #endif //!NO_KRB5 } +krb5_error_code +Leash_krb5_cc_default(krb5_context *ctx, krb5_ccache *cache) +{ + krb5_error_code rc; + krb5_flags flags; + + char *functionName = NULL; + if (*cache == 0) { + rc = pkrb5_cc_default(*ctx, cache); + if (rc) { + functionName = "krb5_cc_default()"; + goto on_error; + } + } +#ifdef KRB5_TC_NOTICKET + flags = KRB5_TC_NOTICKET; +#endif + rc = pkrb5_cc_set_flags(*ctx, *cache, flags); + if (rc) { + if (rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) { + if (*cache != NULL && *ctx != NULL) + pkrb5_cc_close(*ctx, *cache); + } else { + functionName = "krb5_cc_set_flags()"; + goto on_error; + } + } +on_error: + if (rc && functionName) { + Leash_krb5_error(rc, functionName, 0, ctx, cache); + } + return rc; +} + /**************************************/ /* Leash_krb5_initialize(): */ /**************************************/ -int Leash_krb5_initialize(krb5_context *ctx, krb5_ccache *cache) +int Leash_krb5_initialize(krb5_context *ctx) { #ifdef NO_KRB5 return(0); #else LPCSTR functionName = NULL; - int freeContextFlag = 0; krb5_error_code rc; - krb5_flags flags; if (pkrb5_init_context == NULL) return 1; if (*ctx == 0) { - if (rc = (*pkrb5_init_context)(ctx)) - { - functionName = "krb5_init_context()"; - goto on_error; - } - freeContextFlag = 1; - } - - if (*cache == 0 && (rc = pkrb5_cc_default(*ctx, cache))) - { - functionName = "krb5_cc_default()"; - goto on_error; - } -#ifdef KRB5_TC_NOTICKET - flags = KRB5_TC_NOTICKET; -#endif - if ((rc = pkrb5_cc_set_flags(*ctx, *cache, flags))) - { - if (rc != KRB5_FCC_NOFILE && rc != KRB5_CC_NOTFOUND) - Leash_krb5_error(rc, "krb5_cc_set_flags()", 0, ctx, - cache); - else if ((rc == KRB5_FCC_NOFILE || rc == KRB5_CC_NOTFOUND) && *ctx != NULL) - { - if (*cache != NULL) - pkrb5_cc_close(*ctx, *cache); + if (rc = (*pkrb5_init_context)(ctx)) { + functionName = "krb5_init_context()"; + return Leash_krb5_error(rc, functionName, 0, ctx, NULL); } - return rc; } - return 0; - - on_error: - return Leash_krb5_error(rc, functionName, freeContextFlag, ctx, cache); + return 0; #endif //!NO_KRB5 } @@ -1083,36 +1043,25 @@ Leash_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName, #ifdef USE_MESSAGE_BOX char message[256]; const char *errText; - int krb5Error = ((int)(rc & 255)); - - /* - switch (krb5Error) - { - // Wrong password - case 31: - case 8: - return; - } - */ errText = perror_message(rc); _snprintf(message, sizeof(message), "%s\n(Kerberos error %ld)\n\n%s failed", errText, - krb5Error, + rc, FailedFunctionName); + message[sizeof(message)-1] = 0; MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR | MB_TASKMODAL | MB_SETFOREGROUND); #endif /* USE_MESSAGE_BOX */ - if (*ctx != NULL) - { - if (*cache != NULL) { - pkrb5_cc_close(*ctx, *cache); - *cache = NULL; - } + if (ctx != NULL && *ctx != NULL) { + if (cache != NULL && *cache != NULL) { + pkrb5_cc_close(*ctx, *cache); + *cache = NULL; + } if (FreeContextFlag) { pkrb5_free_context(*ctx); @@ -1139,7 +1088,6 @@ Leash_ms2mit(BOOL save_creds) krb5_creds creds; krb5_cc_cursor cursor=0; krb5_principal princ = 0; - char *cache_name=NULL; BOOL rc = FALSE; if ( !pkrb5_init_context ) diff --git a/src/windows/leashdll/leash-int.h b/src/windows/leashdll/leash-int.h index fb7617ed34..b5c0b2738b 100644 --- a/src/windows/leashdll/leash-int.h +++ b/src/windows/leashdll/leash-int.h @@ -162,7 +162,9 @@ BOOL IsKerberosLogon(VOID); int Leash_krb5_error(krb5_error_code rc, LPCSTR FailedFunctionName, int FreeContextFlag, krb5_context *ctx, krb5_ccache *cache); -int Leash_krb5_initialize(krb5_context *, krb5_ccache *); +int Leash_krb5_initialize(krb5_context *); +krb5_error_code +Leash_krb5_cc_default(krb5_context *ctx, krb5_ccache *cache); #endif /* NO_KRB5 */ LPSTR err_describe(LPSTR buf, long code); diff --git a/src/windows/leashdll/leashdll.h b/src/windows/leashdll/leashdll.h index a045583da2..63cfe234f8 100644 --- a/src/windows/leashdll/leashdll.h +++ b/src/windows/leashdll/leashdll.h @@ -58,6 +58,8 @@ void FAR Leash_load_com_err_callback(FARPROC,FARPROC,FARPROC); #endif #include <ntsecapi.h> +#include <krb5.h> + #ifndef NO_KRB4 extern HINSTANCE hKrb4; #endif @@ -73,19 +75,6 @@ extern HINSTANCE hProfile; #define LEASH_PRIORITY_LOW 0 #define LEASH_PRIORITY_HIGH 1 -typedef struct TicketList -{ - char* theTicket; - struct TicketList* next; - char* tktEncType; - char* keyEncType; - int addrCount; - char ** addrList; - char * name; - char * inst; - char * realm; -} TicketList; - /////////////////////////////////////////////////////////////////////////////// #ifdef _WIN64 diff --git a/src/windows/leashdll/leashw32.def b/src/windows/leashdll/leashw32.def index 25af0e2ea8..5df8309ae4 100644 --- a/src/windows/leashdll/leashw32.def +++ b/src/windows/leashdll/leashw32.def @@ -106,3 +106,4 @@ EXPORTS not_an_API_LeashKRB4GetTickets not_an_API_LeashGetTimeServerName not_an_API_Leash_AcquireInitialTicketsIfNeeded + not_an_API_LeashKRB5FreeTickets diff --git a/src/windows/leashdll/lshfunc.c b/src/windows/leashdll/lshfunc.c index 1a0bf14305..614bb799eb 100644 --- a/src/windows/leashdll/lshfunc.c +++ b/src/windows/leashdll/lshfunc.c @@ -867,26 +867,9 @@ not_an_API_LeashFreeTicketList(TicketList** ticketList) killList = tempList; tempList = (TicketList*)tempList->next; - free(killList->theTicket); - if (killList->tktEncType) - free(killList->tktEncType); - if (killList->keyEncType) - free(killList->keyEncType); - if (killList->addrCount) { - int n; - for ( n=0; n<killList->addrCount; n++) { - if (killList->addrList[n]) - free(killList->addrList[n]); - } - } - if (killList->addrList) - free(killList->addrList); - if (killList->name) - free(killList->name); - if (killList->inst) - free(killList->inst); - if (killList->realm) - free(killList->realm); + free(killList->service); + if (killList->encTypes) + free(killList->encTypes); free(killList); } @@ -2873,8 +2856,7 @@ acquire_tkt_no_princ(krb5_context context, char * ccname, int cclen) GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename)); } - not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx); - not_an_API_LeashFreeTicketList(&list); + not_an_API_LeashKRB5GetTickets(&ticketinfo,&ctx); if ( ticketinfo.btickets != GOOD_TICKETS && dwMsLsaImport && Leash_importable() ) { @@ -2939,8 +2921,8 @@ acquire_tkt_no_princ(krb5_context context, char * ccname, int cclen) if ( import ) { Leash_import(); - not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx); - not_an_API_LeashFreeTicketList(&list); + not_an_API_LeashKRB5FreeTickets(&ticketinfo); + not_an_API_LeashKRB5GetTickets(&ticketinfo,&ctx); } } @@ -2958,7 +2940,7 @@ acquire_tkt_no_princ(krb5_context context, char * ccname, int cclen) strncpy(ccname, ccachename, cclen); ccname[cclen-1] = '\0'; } - + not_an_API_LeashKRB5FreeTickets(&ticketinfo); if ( !context ) pkrb5_free_context(ctx); } @@ -2968,7 +2950,6 @@ static void acquire_tkt_for_princ(krb5_context context, krb5_principal desiredPrincipal, char * ccname, int cclen) { - TicketList *list = NULL; TICKETINFO ticketinfo; krb5_context ctx; DWORD dwMsLsaImport = Leash_get_default_mslsa_import(); @@ -2992,8 +2973,7 @@ acquire_tkt_for_princ(krb5_context context, krb5_principal desiredPrincipal, GetEnvironmentVariable("KRB5CCNAME", ccachename, sizeof(ccachename)); } - not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx); - not_an_API_LeashFreeTicketList(&list); + not_an_API_LeashKRB5GetTickets(&ticketinfo,&ctx); pkrb5_unparse_name(ctx, desiredPrincipal, &name); @@ -3032,14 +3012,14 @@ acquire_tkt_for_princ(krb5_context context, krb5_principal desiredPrincipal, SetEnvironmentVariable("KRB5CCNAME", ccachename); - not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx); - not_an_API_LeashFreeTicketList(&list); + not_an_API_LeashKRB5FreeTickets(&ticketinfo); + not_an_API_LeashKRB5GetTickets(&ticketinfo,&ctx); if (ticketinfo.btickets != GOOD_TICKETS) { Leash_import(); - not_an_API_LeashKRB5GetTickets(&ticketinfo,&list,&ctx); - not_an_API_LeashFreeTicketList(&list); + not_an_API_LeashKRB5FreeTickets(&ticketinfo); + not_an_API_LeashKRB5GetTickets(&ticketinfo,&ctx); } } } @@ -3059,6 +3039,7 @@ acquire_tkt_for_princ(krb5_context context, krb5_principal desiredPrincipal, ccname[cclen-1] = '\0'; } } + not_an_API_LeashKRB5FreeTickets(&ticketinfo); if (name) pkrb5_free_unparsed_name(ctx, name); |