Path: blob/main/crypto/krb5/src/windows/leash/KrbListTickets.cpp
34890 views
#include "stdafx.h"1#include "lglobals.h"2#include "krb5.h"34static void5FreeTicketList(TicketList** ticketList)6{7TicketList* tempList = *ticketList, *killList;89while (tempList) {10killList = tempList;11tempList = tempList->next;12free(killList->service);13if (killList->encTypes)14free(killList->encTypes);15free(killList);16}1718*ticketList = NULL;19}2021void22LeashKRB5FreeTicketInfo(TICKETINFO *ticketinfo)23{24if (ticketinfo->principal) {25free(ticketinfo->principal);26ticketinfo->principal = NULL;27}28if (ticketinfo->ccache_name) {29pkrb5_free_string(NULL, ticketinfo->ccache_name);30ticketinfo->ccache_name = NULL;31}32if (ticketinfo->ticket_list)33FreeTicketList(&ticketinfo->ticket_list);34}3536void37LeashKRB5FreeTickets(TICKETINFO **ticketinfolist)38{39TICKETINFO *ticketinfo = *ticketinfolist, *next;40while (ticketinfo) {41next = ticketinfo->next;42LeashKRB5FreeTicketInfo(ticketinfo);43free(ticketinfo);44ticketinfo = next;45}46*ticketinfolist = NULL;47}4849/*50* LeashKRB5Error()51*/52int53LeashKRB5Error(krb5_error_code rc, LPCSTR FailedFunctionName)54{55#ifdef USE_MESSAGE_BOX56char message[256];57const char *errText;5859errText = perror_message(rc);60_snprintf(message, sizeof(message),61"%s\n(Kerberos error %ld)\n\n%s failed",62errText,63rc,64FailedFunctionName);65message[sizeof(message)-1] = 0;6667MessageBox(NULL, message, "Kerberos Five", MB_OK | MB_ICONERROR |68MB_TASKMODAL |69MB_SETFOREGROUND);70#endif /* USE_MESSAGE_BOX */71return rc;72}737475static void76etype_string(krb5_enctype enctype, char *buf, size_t buflen)77{78krb5_error_code retval;7980if ((retval = pkrb5_enctype_to_name(enctype, FALSE, buf, buflen))) {81/* XXX if there's an error != EINVAL, I should probably report it */82sprintf_s(buf, buflen, "etype %d", enctype);83}84}858687static void88CredToTicketInfo(krb5_creds KRBv5Credentials, TICKETINFO *ticketinfo)89{90ticketinfo->issued = (DWORD)KRBv5Credentials.times.starttime;91ticketinfo->valid_until = (DWORD)KRBv5Credentials.times.endtime;92ticketinfo->renew_until = KRBv5Credentials.ticket_flags & TKT_FLG_RENEWABLE ?93(DWORD)KRBv5Credentials.times.renew_till : (DWORD)0;94_tzset();95if ( ticketinfo->valid_until - time(0) <= 0L )96ticketinfo->btickets = EXPD_TICKETS;97else98ticketinfo->btickets = GOOD_TICKETS;99}100101static int102CredToTicketList(krb5_context ctx, krb5_creds KRBv5Credentials,103char *PrincipalName, TicketList ***ticketListTail)104{105krb5_error_code code = 0;106krb5_ticket *tkt=NULL;107char *sServerName = NULL;108char Buffer[256], sestype[100], tkttype[100];109char *functionName = NULL;110TicketList *list = NULL;111112functionName = "krb5_unparse_name()";113code = (*pkrb5_unparse_name)(ctx, KRBv5Credentials.server, &sServerName);114if (code)115goto cleanup;116117if (!KRBv5Credentials.times.starttime)118KRBv5Credentials.times.starttime = KRBv5Credentials.times.authtime;119120memset(Buffer, '\0', sizeof(Buffer));121122// @fixme: calloc for ptr init123list = (TicketList *)calloc(1, sizeof(TicketList));124if (!list) {125code = ENOMEM;126functionName = "calloc()";127goto cleanup;128}129list->service = strdup(sServerName);130if (!list->service) {131code = ENOMEM;132functionName = "calloc()";133goto cleanup;134}135list->issued = (DWORD)KRBv5Credentials.times.starttime;136list->valid_until = (DWORD)KRBv5Credentials.times.endtime;137if (KRBv5Credentials.ticket_flags & TKT_FLG_RENEWABLE)138list->renew_until = (DWORD)KRBv5Credentials.times.renew_till;139else140list->renew_until = 0;141142etype_string(KRBv5Credentials.keyblock.enctype, sestype, sizeof(sestype));143if (!pkrb5_decode_ticket(&KRBv5Credentials.ticket, &tkt)) {144etype_string(tkt->enc_part.enctype, tkttype, sizeof(tkttype));145wsprintf(Buffer, "Session Key: %s Ticket: %s", sestype, tkttype);146pkrb5_free_ticket(ctx, tkt);147tkt = NULL;148} else {149wsprintf(Buffer, "Session Key: %s", sestype);150}151152list->encTypes = (char *)calloc(1, strlen(Buffer)+1);153if (!list->encTypes) {154functionName = "calloc()";155code = ENOMEM;156goto cleanup;157}158strcpy(list->encTypes, Buffer);159160list->flags = KRBv5Credentials.ticket_flags;161cleanup:162if (code) {163LeashKRB5Error(code, functionName);164if (list)165FreeTicketList(&list);166} else {167**ticketListTail = list;168*ticketListTail = &list->next;169}170171if (sServerName != NULL)172(*pkrb5_free_unparsed_name)(ctx, sServerName);173174return code;175}176177// return 0 if ticketinfo was successfully appended to list, 1 otherwise178int179do_ccache(krb5_context ctx,180krb5_ccache cache,181TICKETINFO **ticketInfoTail)182{183krb5_cc_cursor cur;184krb5_creds creds;185krb5_principal princ = NULL;186krb5_flags flags;187krb5_error_code code;188char *defname = NULL;189char *functionName = NULL;190TicketList **ticketListTail;191TICKETINFO *ticketinfo = NULL;192int retval = 1;193194// Don't need the actual ticket.195flags = KRB5_TC_NOTICKET;196code = pkrb5_cc_set_flags(ctx, cache, flags);197if (code) {198if (code == KRB5_FCC_NOFILE || code == KRB5_CC_NOTFOUND) {199// Normal behavior; skip cache but suppress error message box200code = 0;201} else {202functionName = "krb5_cc_set_flags";203}204goto cleanup;205}206code = pkrb5_cc_get_principal(ctx, cache, &princ);207if (code) {208// Normal behavior; skip cache but suppress error message box209code = 0;210goto cleanup;211}212code = pkrb5_unparse_name(ctx, princ, &defname);213if (code) {214functionName = "krb5_unparse_name";215goto cleanup;216}217code = pkrb5_cc_start_seq_get(ctx, cache, &cur);218if (code) {219// MSLSA errors here if no TGT is found; suppress error message box220code = 0;221goto cleanup;222}223if (*ticketInfoTail)224ticketinfo = *ticketInfoTail;225else226// @fixme: calloc to init pointers227ticketinfo = (TICKETINFO *)calloc(1, sizeof(TICKETINFO));228229if (ticketinfo == NULL) {230functionName = "calloc";231code = ENOMEM;232goto cleanup;233}234ticketinfo->next = NULL;235ticketinfo->ticket_list = NULL;236ticketinfo->principal = strdup(defname);237if (ticketinfo->principal == NULL) {238functionName = "strdup";239code = ENOMEM;240goto cleanup;241}242code = pkrb5_cc_get_full_name(ctx, cache, &ticketinfo->ccache_name);243if (code) {244functionName = "krb5_cc_get_full_name";245goto cleanup;246}247*ticketInfoTail = ticketinfo;248ticketListTail = &ticketinfo->ticket_list;249while (!(code = pkrb5_cc_next_cred(ctx, cache, &cur, &creds))) {250if (!pkrb5_is_config_principal(ctx, creds.server)) {251CredToTicketList(ctx, creds, defname, &ticketListTail);252CredToTicketInfo(creds, ticketinfo);253}254pkrb5_free_cred_contents(ctx, &creds);255}256if (code == KRB5_CC_END) {257code = pkrb5_cc_end_seq_get(ctx, cache, &cur);258if (code) {259functionName = "krb5_cc_end_seq_get";260goto cleanup;261}262flags = 0;263code = pkrb5_cc_set_flags(ctx, cache, flags);264if (code) {265functionName = "krb5_cc_set_flags";266goto cleanup;267}268} else {269functionName = "krb5_cc_next_cred";270goto cleanup;271}272cleanup:273if (code)274LeashKRB5Error(code, functionName);275if (ticketinfo) {276if (ticketinfo == *ticketInfoTail)277retval = 0;278else279LeashKRB5FreeTickets(&ticketinfo);280}281if (defname)282pkrb5_free_unparsed_name(ctx, defname);283if (princ)284pkrb5_free_principal(ctx, princ);285return retval;286}287288289//290// Returns 0 for success, 1 for failure291//292int293do_all_ccaches(krb5_context ctx, TICKETINFO **ticketinfotail)294{295krb5_error_code code;296krb5_ccache cache;297krb5_cccol_cursor cursor;298int retval = 1;299char *functionName = NULL;300301code = pkrb5_cccol_cursor_new(ctx, &cursor);302if (code) {303functionName = "krb5_cccol_cursor_new";304goto cleanup;305}306retval = 0;307while (!(code = pkrb5_cccol_cursor_next(ctx, cursor, &cache)) &&308cache != NULL) {309// Note that ticketinfotail will be updated here to point to the tail310// of the list but the caller of this function will remain with a311// pointer to the head.312if (do_ccache(ctx, cache, ticketinfotail) == 0)313ticketinfotail = &((*ticketinfotail)->next);314pkrb5_cc_close(ctx, cache);315}316if (code)317functionName = "krb5_cccol_cursor_next";318pkrb5_cccol_cursor_free(ctx, &cursor);319cleanup:320if (code)321LeashKRB5Error(code, functionName);322return retval;323}324325void326LeashKRB5ListDefaultTickets(TICKETINFO *ticketinfo)327{328krb5_error_code code;329krb5_context ctx = 0;330krb5_ccache cache = 0;331char *functionName = NULL;332333ticketinfo->btickets = NO_TICKETS;334ticketinfo->principal = NULL;335ticketinfo->ccache_name = NULL;336ticketinfo->next = NULL;337ticketinfo->ticket_list = NULL;338ticketinfo->renew_until = 0;339ticketinfo->valid_until = 0;340ticketinfo->issued = 0;341342code = pkrb5_init_context(&ctx);343if (code) {344functionName = "krb5_init_context";345goto cleanup;346}347348code = pkrb5_cc_default(ctx, &cache);349if (code) {350functionName = "krb5_cc_default";351goto cleanup;352}353if (cache != NULL)354do_ccache(ctx, cache, &ticketinfo);355cleanup:356if (code)357LeashKRB5Error(code, functionName);358if (cache)359pkrb5_cc_close(ctx, cache);360if (ctx)361pkrb5_free_context(ctx);362}363364365/*366* LeashKRB5ListAllTickets()367*/368369void370LeashKRB5ListAllTickets(TICKETINFO **ticketinfo)371{372krb5_error_code code;373krb5_context ctx = 0;374char *functionName = NULL;375376code = pkrb5_init_context(&ctx);377if (code) {378functionName = "krb5_init_context";379goto cleanup;380}381382do_all_ccaches(ctx, ticketinfo);383cleanup:384if (code)385LeashKRB5Error(code, functionName);386if (ctx)387pkrb5_free_context(ctx);388}389390391