diff options
Diffstat (limited to 'src/windows/leashdll/krb5routines.c')
-rw-r--r-- | src/windows/leashdll/krb5routines.c | 790 |
1 files changed, 369 insertions, 421 deletions
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 ) |