xref: /freebsd/crypto/krb5/src/kdc/kdc_log.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
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
log_as_req(krb5_context context,const krb5_fulladdr * local_addr,const krb5_fulladdr * remote_addr,krb5_kdc_req * request,krb5_kdc_rep * reply,krb5_db_entry * client,const char * cname,krb5_db_entry * server,const char * sname,krb5_timestamp authtime,const char * status,krb5_error_code errcode,const char * emsg)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
unparse_and_limit(krb5_context ctx,krb5_principal princ,char ** str)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
log_tgs_req(krb5_context ctx,const krb5_fulladdr * from,krb5_kdc_req * request,krb5_kdc_rep * reply,krb5_principal cprinc,krb5_principal sprinc,krb5_principal altcprinc,krb5_timestamp authtime,unsigned int c_flags,const char * status,krb5_error_code errcode,const char * emsg)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
log_tgs_badtrans(krb5_context ctx,krb5_principal cprinc,krb5_principal sprinc,krb5_data * trcont,krb5_error_code errcode)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
log_tgs_alt_tgt(krb5_context context,krb5_principal p)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