1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* kdc/kdc_log.c - Logging functions for KDC requests */ 3 /* 4 * Copyright 2008,2009 by the Massachusetts Institute of Technology. 5 * All Rights Reserved. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of M.I.T. not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original M.I.T. software. 22 * M.I.T. makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 */ 26 27 #include "k5-int.h" 28 #include "kdc_util.h" 29 #include <syslog.h> 30 #include "adm_proto.h" 31 32 /* 33 * A note on KDC-status string format. 34 * 35 * - All letters in the status string should be capitalized; 36 * - the words in the status phrase are separated by underscores; 37 * - abbreviations should be avoided. Some acceptable "standard" acronyms 38 * are AS_REQ, TGS_REP etc. 39 * - since in almost all cases KDC status string is set on error, no need 40 * to state this fact as part of the status string; 41 * - KDC status string should be an imperative phrase. 42 * 43 * Example: "MAKE_RANDOM_KEY" 44 */ 45 46 /* Main logging routines for ticket requests. 47 48 There are a few simple cases -- unparseable requests mainly -- 49 where messages are logged otherwise, but once a ticket request can 50 be decoded in some basic way, these routines are used for logging 51 the details. */ 52 53 /* "status" is null to indicate success. */ 54 /* Someday, pass local address/port as well. */ 55 /* Currently no info about name canonicalization is logged. */ 56 void 57 log_as_req(krb5_context context, 58 const krb5_fulladdr *local_addr, 59 const krb5_fulladdr *remote_addr, 60 krb5_kdc_req *request, krb5_kdc_rep *reply, 61 krb5_db_entry *client, const char *cname, 62 krb5_db_entry *server, const char *sname, 63 krb5_timestamp authtime, 64 const char *status, krb5_error_code errcode, const char *emsg) 65 { 66 const char *fromstring = 0; 67 char fromstringbuf[70]; 68 char *ktypestr = NULL; 69 const char *cname2 = cname ? cname : "<unknown client>"; 70 const char *sname2 = sname ? sname : "<unknown server>"; 71 72 fromstring = inet_ntop(ADDRTYPE2FAMILY(remote_addr->address->addrtype), 73 remote_addr->address->contents, 74 fromstringbuf, sizeof(fromstringbuf)); 75 if (!fromstring) 76 fromstring = "<unknown>"; 77 78 ktypestr = ktypes2str(request->ktype, request->nktypes); 79 80 if (status == NULL) { 81 /* success */ 82 char *rep_etypestr = rep_etypes2str(reply); 83 krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: ISSUE: authtime %u, %s, " 84 "%s for %s"), 85 ktypestr ? ktypestr : "", fromstring, 86 (unsigned int)authtime, 87 rep_etypestr ? rep_etypestr : "", cname2, sname2); 88 free(rep_etypestr); 89 } else { 90 /* fail */ 91 krb5_klog_syslog(LOG_INFO, _("AS_REQ (%s) %s: %s: %s for %s%s%s"), 92 ktypestr ? ktypestr : "", fromstring, status, cname2, 93 sname2, emsg ? ", " : "", emsg ? emsg : ""); 94 } 95 krb5_db_audit_as_req(context, request, 96 local_addr->address, remote_addr->address, 97 client, server, authtime, errcode); 98 99 free(ktypestr); 100 } 101 102 /* 103 * Unparse a principal for logging purposes and limit the string length. 104 * Ignore errors because the most likely errors are memory exhaustion, and many 105 * other things will fail in the logging functions in that case. 106 */ 107 static void 108 unparse_and_limit(krb5_context ctx, krb5_principal princ, char **str) 109 { 110 /* Ignore errors */ 111 krb5_unparse_name(ctx, princ, str); 112 limit_string(*str); 113 } 114 115 /* Here "status" must be non-null. Error code 116 KRB5KDC_ERR_SERVER_NOMATCH is handled specially. 117 118 Currently no info about name canonicalization is logged. */ 119 void 120 log_tgs_req(krb5_context ctx, const krb5_fulladdr *from, 121 krb5_kdc_req *request, krb5_kdc_rep *reply, 122 krb5_principal cprinc, krb5_principal sprinc, 123 krb5_principal altcprinc, 124 krb5_timestamp authtime, 125 unsigned int c_flags, 126 const char *status, krb5_error_code errcode, const char *emsg) 127 { 128 char *ktypestr = NULL, *rep_etypestr = NULL; 129 const char *fromstring = 0; 130 char fromstringbuf[70]; 131 char *cname = NULL, *sname = NULL, *altcname = NULL; 132 char *logcname = NULL, *logsname = NULL, *logaltcname = NULL; 133 134 fromstring = inet_ntop(ADDRTYPE2FAMILY(from->address->addrtype), 135 from->address->contents, 136 fromstringbuf, sizeof(fromstringbuf)); 137 if (!fromstring) 138 fromstring = "<unknown>"; 139 140 unparse_and_limit(ctx, cprinc, &cname); 141 logcname = (cname != NULL) ? cname : "<unknown client>"; 142 unparse_and_limit(ctx, sprinc, &sname); 143 logsname = (sname != NULL) ? sname : "<unknown server>"; 144 unparse_and_limit(ctx, altcprinc, &altcname); 145 logaltcname = (altcname != NULL) ? altcname : "<unknown>"; 146 147 /* Differences: server-nomatch message logs 2nd ticket's client 148 name (useful), and doesn't log ktypestr (probably not 149 important). */ 150 if (errcode != KRB5KDC_ERR_SERVER_NOMATCH) { 151 ktypestr = ktypes2str(request->ktype, request->nktypes); 152 if (reply != NULL) 153 rep_etypestr = rep_etypes2str(reply); 154 krb5_klog_syslog(LOG_INFO, _("TGS_REQ (%s) %s: %s: authtime %u, %s%s " 155 "%s for %s%s%s"), 156 ktypestr ? ktypestr : "", fromstring, status, 157 (unsigned int)authtime, 158 rep_etypestr ? rep_etypestr : "", 159 !errcode ? "," : "", logcname, logsname, 160 errcode ? ", " : "", errcode ? emsg : ""); 161 if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) 162 krb5_klog_syslog(LOG_INFO, 163 _("... PROTOCOL-TRANSITION s4u-client=%s"), 164 logaltcname); 165 else if (isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) 166 krb5_klog_syslog(LOG_INFO, 167 _("... CONSTRAINED-DELEGATION s4u-client=%s"), 168 logaltcname); 169 170 } else 171 krb5_klog_syslog(LOG_INFO, _("TGS_REQ %s: %s: authtime %u, %s for %s, " 172 "2nd tkt client %s"), 173 fromstring, status, (unsigned int)authtime, 174 logcname, logsname, logaltcname); 175 176 free(rep_etypestr); 177 free(ktypestr); 178 krb5_free_unparsed_name(ctx, cname); 179 krb5_free_unparsed_name(ctx, sname); 180 krb5_free_unparsed_name(ctx, altcname); 181 } 182 183 void 184 log_tgs_badtrans(krb5_context ctx, krb5_principal cprinc, 185 krb5_principal sprinc, krb5_data *trcont, 186 krb5_error_code errcode) 187 { 188 unsigned int tlen; 189 char *tdots; 190 const char *emsg = NULL; 191 char *cname = NULL, *sname = NULL; 192 char *logcname = NULL, *logsname = NULL; 193 194 unparse_and_limit(ctx, cprinc, &cname); 195 logcname = (cname != NULL) ? cname : "<unknown client>"; 196 unparse_and_limit(ctx, sprinc, &sname); 197 logsname = (sname != NULL) ? sname : "<unknown server>"; 198 199 tlen = trcont->length; 200 tdots = tlen > 125 ? "..." : ""; 201 tlen = tlen > 125 ? 125 : tlen; 202 203 if (errcode == KRB5KRB_AP_ERR_ILL_CR_TKT) 204 krb5_klog_syslog(LOG_INFO, _("bad realm transit path from '%s' " 205 "to '%s' via '%.*s%s'"), 206 logcname, logsname, tlen, 207 trcont->data, tdots); 208 else { 209 emsg = krb5_get_error_message(ctx, errcode); 210 krb5_klog_syslog(LOG_ERR, _("unexpected error checking transit " 211 "from '%s' to '%s' via '%.*s%s': %s"), 212 logcname, logsname, tlen, 213 trcont->data, tdots, 214 emsg); 215 krb5_free_error_message(ctx, emsg); 216 emsg = NULL; 217 } 218 krb5_free_unparsed_name(ctx, cname); 219 krb5_free_unparsed_name(ctx, sname); 220 } 221 222 void 223 log_tgs_alt_tgt(krb5_context context, krb5_principal p) 224 { 225 char *sname; 226 if (krb5_unparse_name(context, p, &sname)) { 227 krb5_klog_syslog(LOG_INFO, 228 _("TGS_REQ: issuing alternate <un-unparsable> TGT")); 229 } else { 230 limit_string(sname); 231 krb5_klog_syslog(LOG_INFO, _("TGS_REQ: issuing TGT %s"), sname); 232 free(sname); 233 } 234 /* OpenSolaris: audit_krb5kdc_tgs_req_alt_tgt(...) */ 235 } 236