From 2a8005296c3da39f6d0c6ecd48b950447897af91 Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Tue, 8 Jan 2019 17:42:35 -0500 Subject: [PATCH] Make etype names in KDC logs human-readable Introduce enctype_name() as a wrapper over krb5_enctype_to_name for converting between registered constants and names. Adjust signatures and rewrite ktypes2str() and rep_etypes2str() to operate on dynamic buffers. ticket: 8772 (new) (cherry picked from commit a649279727490687d54becad91fde8cf7429d951) --- src/kdc/kdc_log.c | 42 +++++++-------- src/kdc/kdc_util.c | 131 +++++++++++++++++++++++---------------------- src/kdc/kdc_util.h | 6 +-- 3 files changed, 90 insertions(+), 89 deletions(-) diff --git a/src/kdc/kdc_log.c b/src/kdc/kdc_log.c index 4eec50373..b160ba21a 100644 --- a/src/kdc/kdc_log.c +++ b/src/kdc/kdc_log.c @@ -65,7 +65,7 @@ log_as_req(krb5_context context, { const char *fromstring = 0; char fromstringbuf[70]; - char ktypestr[128]; + char *ktypestr = NULL; const char *cname2 = cname ? cname : ""; const char *sname2 = sname ? sname : ""; @@ -74,26 +74,29 @@ log_as_req(krb5_context context, fromstringbuf, sizeof(fromstringbuf)); if (!fromstring) fromstring = ""; - ktypes2str(ktypestr, sizeof(ktypestr), - request->nktypes, request->ktype); + + ktypestr = ktypes2str(request->ktype, request->nktypes); if (status == NULL) { /* success */ - char rep_etypestr[128]; - rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply); + char *rep_etypestr = rep_etypes2str(reply); krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: ISSUE: authtime %u, %s, " "%s for %s"), - ktypestr, fromstring, (unsigned int)authtime, - rep_etypestr, cname2, sname2); + ktypestr ? ktypestr : "", fromstring, + (unsigned int)authtime, + rep_etypestr ? rep_etypestr : "", cname2, sname2); + free(rep_etypestr); } else { /* fail */ krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: %s: %s for %s%s%s"), - ktypestr, fromstring, status, - cname2, sname2, emsg ? ", " : "", emsg ? emsg : ""); + ktypestr ? ktypestr : "", fromstring, status, cname2, + sname2, emsg ? ", " : "", emsg ? emsg : ""); } krb5_db_audit_as_req(context, request, local_addr->address, remote_addr->address, client, server, authtime, errcode); + + free(ktypestr); } /* @@ -122,10 +125,9 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, unsigned int c_flags, const char *status, krb5_error_code errcode, const char *emsg) { - char ktypestr[128]; + char *ktypestr = NULL, *rep_etypestr = NULL; const char *fromstring = 0; char fromstringbuf[70]; - char rep_etypestr[128]; char *cname = NULL, *sname = NULL, *altcname = NULL; char *logcname = NULL, *logsname = NULL, *logaltcname = NULL; @@ -134,11 +136,6 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, fromstringbuf, sizeof(fromstringbuf)); if (!fromstring) fromstring = ""; - ktypes2str(ktypestr, sizeof(ktypestr), request->nktypes, request->ktype); - if (!errcode) - rep_etypes2str(rep_etypestr, sizeof(rep_etypestr), reply); - else - rep_etypestr[0] = 0; unparse_and_limit(ctx, cprinc, &cname); logcname = (cname != NULL) ? cname : ""; @@ -151,10 +148,14 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, name (useful), and doesn't log ktypestr (probably not important). */ if (errcode != KRB5KDC_ERR_SERVER_NOMATCH) { + ktypestr = ktypes2str(request->ktype, request->nktypes); + rep_etypestr = rep_etypes2str(reply); krb5_klog_syslog(LOG_INFO, _("TGS_REQ (%s) %s: %s: authtime %u, %s%s " "%s for %s%s%s"), - ktypestr, fromstring, status, (unsigned int)authtime, - rep_etypestr, !errcode ? "," : "", logcname, logsname, + ktypestr ? ktypestr : "", fromstring, status, + (unsigned int)authtime, + rep_etypestr ? rep_etypestr : "", + !errcode ? "," : "", logcname, logsname, errcode ? ", " : "", errcode ? emsg : ""); if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) krb5_klog_syslog(LOG_INFO, @@ -171,9 +172,8 @@ log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, fromstring, status, (unsigned int)authtime, logcname, logsname, logaltcname); - /* OpenSolaris: audit_krb5kdc_tgs_req(...) or - audit_krb5kdc_tgs_req_2ndtktmm(...) */ - + free(rep_etypestr); + free(ktypestr); krb5_free_unparsed_name(ctx, cname); krb5_free_unparsed_name(ctx, sname); krb5_free_unparsed_name(ctx, altcname); diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c index 0155c28c6..f5c581c82 100644 --- a/src/kdc/kdc_util.c +++ b/src/kdc/kdc_util.c @@ -1043,84 +1043,87 @@ void limit_string(char *name) return; } -/* - * L10_2 = log10(2**x), rounded up; log10(2) ~= 0.301. - */ -#define L10_2(x) ((int)(((x * 301) + 999) / 1000)) - -/* - * Max length of sprintf("%ld") for an int of type T; includes leading - * minus sign and terminating NUL. - */ -#define D_LEN(t) (L10_2(sizeof(t) * CHAR_BIT) + 2) - -void -ktypes2str(char *s, size_t len, int nktypes, krb5_enctype *ktype) +/* Wrapper of krb5_enctype_to_name() to include the PKINIT types. */ +static krb5_error_code +enctype_name(krb5_enctype ktype, char *buf, size_t buflen) { - int i; - char stmp[D_LEN(krb5_enctype) + 1]; - char *p; + char *name; - if (nktypes < 0 - || len < (sizeof(" etypes {...}") + D_LEN(int))) { - *s = '\0'; - return; - } + if (buflen == 0) + return EINVAL; + *buf = '\0'; /* ensure these are always valid C-strings */ - snprintf(s, len, "%d etypes {", nktypes); - for (i = 0; i < nktypes; i++) { - snprintf(stmp, sizeof(stmp), "%s%ld", i ? " " : "", (long)ktype[i]); - if (strlen(s) + strlen(stmp) + sizeof("}") > len) - break; - strlcat(s, stmp, len); - } - if (i < nktypes) { - /* - * We broke out of the loop. Try to truncate the list. - */ - p = s + strlen(s); - while (p - s + sizeof("...}") > len) { - while (p > s && *p != ' ' && *p != '{') - *p-- = '\0'; - if (p > s && *p == ' ') { - *p-- = '\0'; - continue; - } - } - strlcat(s, "...", len); - } - strlcat(s, "}", len); - return; + /* rfc4556 recommends that clients wishing to indicate support for these + * pkinit algorithms include them in the etype field of the AS-REQ. */ + if (ktype == ENCTYPE_DSA_SHA1_CMS) + name = "id-dsa-with-sha1-CmsOID"; + else if (ktype == ENCTYPE_MD5_RSA_CMS) + name = "md5WithRSAEncryption-CmsOID"; + else if (ktype == ENCTYPE_SHA1_RSA_CMS) + name = "sha-1WithRSAEncryption-CmsOID"; + else if (ktype == ENCTYPE_RC2_CBC_ENV) + name = "rc2-cbc-EnvOID"; + else if (ktype == ENCTYPE_RSA_ENV) + name = "rsaEncryption-EnvOID"; + else if (ktype == ENCTYPE_RSA_ES_OAEP_ENV) + name = "id-RSAES-OAEP-EnvOID"; + else if (ktype == ENCTYPE_DES3_CBC_ENV) + name = "des-ede3-cbc-EnvOID"; + else + return krb5_enctype_to_name(ktype, FALSE, buf, buflen); + + if (strlcpy(name, buf, buflen) >= buflen) + return ENOMEM; + return 0; } -void -rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep) +char * +ktypes2str(krb5_enctype *ktype, int nktypes) { - char stmp[sizeof("ses=") + D_LEN(krb5_enctype)]; + struct k5buf buf; + int i; + char name[64]; - if (len < (3 * D_LEN(krb5_enctype) - + sizeof("etypes {rep= tkt= ses=}"))) { - *s = '\0'; - return; + if (nktypes < 0) + return NULL; + + k5_buf_init_dynamic(&buf); + k5_buf_add_fmt(&buf, "%d etypes {", nktypes); + for (i = 0; i < nktypes; i++) { + enctype_name(ktype[i], name, sizeof(name)); + k5_buf_add_fmt(&buf, "%s%s(%ld)", i ? ", " : "", name, (long)ktype[i]); } + k5_buf_add(&buf, "}"); + return buf.data; +} - snprintf(s, len, "etypes {rep=%ld", (long)rep->enc_part.enctype); +char * +rep_etypes2str(krb5_kdc_rep *rep) +{ + struct k5buf buf; + char name[64]; + krb5_enctype etype; + + k5_buf_init_dynamic(&buf); + k5_buf_add(&buf, "etypes {rep="); + enctype_name(rep->enc_part.enctype, name, sizeof(name)); + k5_buf_add_fmt(&buf, "%s(%ld)", name, (long)rep->enc_part.enctype); if (rep->ticket != NULL) { - snprintf(stmp, sizeof(stmp), - " tkt=%ld", (long)rep->ticket->enc_part.enctype); - strlcat(s, stmp, len); + etype = rep->ticket->enc_part.enctype; + enctype_name(etype, name, sizeof(name)); + k5_buf_add_fmt(&buf, ", tkt=%s(%ld)", name, (long)etype); } - if (rep->ticket != NULL - && rep->ticket->enc_part2 != NULL - && rep->ticket->enc_part2->session != NULL) { - snprintf(stmp, sizeof(stmp), " ses=%ld", - (long)rep->ticket->enc_part2->session->enctype); - strlcat(s, stmp, len); + if (rep->ticket != NULL && rep->ticket->enc_part2 != NULL && + rep->ticket->enc_part2->session != NULL) { + etype = rep->ticket->enc_part2->session->enctype; + enctype_name(etype, name, sizeof(name)); + k5_buf_add_fmt(&buf, ", ses=%s(%ld)", name, (long)etype); } - strlcat(s, "}", len); - return; + + k5_buf_add(&buf, "}"); + return buf.data; } static krb5_error_code diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index 6ec645fc3..25077cbf5 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -110,11 +110,9 @@ select_session_keytype (kdc_realm_t *kdc_active_realm, void limit_string (char *name); -void -ktypes2str(char *s, size_t len, int nktypes, krb5_enctype *ktype); +char *ktypes2str(krb5_enctype *ktype, int nktypes); -void -rep_etypes2str(char *s, size_t len, krb5_kdc_rep *rep); +char *rep_etypes2str(krb5_kdc_rep *rep); /* authind.c */ krb5_boolean