auth_log: Split up auth/authz logging levels and handle anonymous better
[Samba.git] / auth / auth_log.c
blob7da47f6b6599f5a167f56bee84a13063ffbfd4e3
1 /*
3 Authentication and authorization logging
5 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 * Debug log levels for authentication logging (these both map to
23 * LOG_NOTICE in syslog)
25 #define AUTH_FAILURE_LEVEL 2
26 #define AUTH_SUCCESS_LEVEL 3
27 #define AUTHZ_SUCCESS_LEVEL 4
29 /* 5 is used for both authentication and authorization */
30 #define AUTH_ANONYMOUS_LEVEL 5
31 #define AUTHZ_ANONYMOUS_LEVEL 5
33 #include "includes.h"
34 #include "../lib/tsocket/tsocket.h"
35 #include "common_auth.h"
36 #include "lib/util/util_str_escape.h"
37 #include "libcli/security/dom_sid.h"
38 #include "libcli/security/security_token.h"
41 * Get a human readable timestamp.
43 * Returns the current time formatted as
44 * "Tue, 14 Mar 2017 08:38:42.209028 NZDT"
46 * The returned string is allocated by talloc in the supplied context.
47 * It is the callers responsibility to free it.
50 static const char* get_timestamp( TALLOC_CTX *frame )
52 char buffer[40]; /* formatted time less usec and timezone */
53 char tz[10]; /* formatted time zone */
54 struct tm* tm_info; /* current local time */
55 struct timeval tv; /* current system time */
56 int r; /* response code from gettimeofday */
57 const char * ts; /* formatted time stamp */
59 r = gettimeofday(&tv, NULL);
60 if (r) {
61 DBG_ERR("Unable to get time of day: (%d) %s\n",
62 errno,
63 strerror( errno));
64 return NULL;
67 tm_info = localtime(&tv.tv_sec);
68 if (tm_info == NULL) {
69 DBG_ERR("Unable to determine local time\n");
70 return NULL;
73 strftime(buffer, sizeof(buffer)-1, "%a, %d %b %Y %H:%M:%S", tm_info);
74 strftime(tz, sizeof(tz)-1, "%Z", tm_info);
75 ts = talloc_asprintf(frame, "%s.%06ld %s", buffer, tv.tv_usec, tz);
76 if (ts == NULL) {
77 DBG_ERR("Out of memory formatting time stamp\n");
79 return ts;
83 * Determine the type of the password supplied for the
84 * authorisation attempt.
87 static const char* get_password_type(const struct auth_usersupplied_info *ui)
90 const char *password_type = NULL;
92 if (ui->password_state == AUTH_PASSWORD_RESPONSE &&
93 (ui->logon_parameters & MSV1_0_ALLOW_MSVCHAPV2) &&
94 ui->password.response.nt.length == 24) {
95 password_type = "MSCHAPv2";
96 } else if ((ui->logon_parameters & MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED)
97 || (ui->password_state == AUTH_PASSWORD_PLAIN)) {
98 password_type = "Plaintext";
99 } else if (ui->password_state == AUTH_PASSWORD_HASH) {
100 password_type = "Supplied-NT-Hash";
101 } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
102 && ui->password.response.nt.length > 24) {
103 password_type = "NTLMv2";
104 } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
105 && ui->password.response.nt.length == 24) {
106 password_type = "NTLMv1";
107 } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
108 && ui->password.response.lanman.length == 24) {
109 password_type = "LANMan";
110 } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
111 && ui->password.response.nt.length == 0
112 && ui->password.response.lanman.length == 0) {
113 password_type = "No-Password";
115 return password_type;
119 * Log details of an authentication attempt.
120 * Successful and unsuccessful attempts are logged.
123 void log_authentication_event(const struct auth_usersupplied_info *ui,
124 NTSTATUS status,
125 const char *domain_name,
126 const char *account_name,
127 const char *unix_username,
128 struct dom_sid *sid)
130 TALLOC_CTX *frame = NULL;
132 const char *ts = NULL; /* formatted current time */
133 char *remote = NULL; /* formatted remote host */
134 char *local = NULL; /* formatted local host */
135 char *nl = NULL; /* NETLOGON details if present */
136 char *trust_computer_name = NULL;
137 char *trust_account_name = NULL;
138 char *logon_line = NULL;
139 const char *password_type = NULL;
141 /* set the log level */
142 int debug_level = AUTH_FAILURE_LEVEL;
144 if (NT_STATUS_IS_OK(status)) {
145 debug_level = AUTH_SUCCESS_LEVEL;
146 if (dom_sid_equal(sid, &global_sid_Anonymous)) {
147 debug_level = AUTH_ANONYMOUS_LEVEL;
151 if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, debug_level)) {
152 return;
155 frame = talloc_stackframe();
157 password_type = get_password_type( ui);
158 /* Get the current time */
159 ts = get_timestamp(frame);
161 /* Only log the NETLOGON details if they are present */
162 if (ui->netlogon_trust_account.computer_name ||
163 ui->netlogon_trust_account.account_name) {
164 trust_computer_name = log_escape(frame,
165 ui->netlogon_trust_account.computer_name);
166 trust_account_name = log_escape(frame,
167 ui->netlogon_trust_account.account_name);
168 nl = talloc_asprintf(frame,
169 " NETLOGON computer [%s] trust account [%s]",
170 trust_computer_name, trust_account_name);
173 remote = tsocket_address_string(ui->remote_host, frame);
174 local = tsocket_address_string(ui->local_host, frame);
176 if (NT_STATUS_IS_OK(status)) {
177 char sid_buf[DOM_SID_STR_BUFLEN];
179 dom_sid_string_buf(sid, sid_buf, sizeof(sid_buf));
180 logon_line = talloc_asprintf(frame,
181 " became [%s]\\[%s] [%s].",
182 log_escape(frame, domain_name),
183 log_escape(frame, account_name),
184 sid_buf);
185 } else {
186 logon_line = talloc_asprintf(frame,
187 " mapped to [%s]\\[%s].",
188 log_escape(frame, ui->mapped.domain_name),
189 log_escape(frame, ui->mapped.account_name));
192 DEBUGC( DBGC_AUTH_AUDIT, debug_level, (
193 "Auth: [%s,%s] user [%s]\\[%s]"
194 " at [%s] with [%s] status [%s]"
195 " workstation [%s] remote host [%s]"
196 "%s local host [%s]"
197 " %s\n",
198 ui->service_description,
199 ui->auth_description,
200 log_escape(frame, ui->client.domain_name),
201 log_escape(frame, ui->client.account_name),
203 password_type,
204 nt_errstr( status),
205 log_escape(frame, ui->workstation_name),
206 remote,
207 logon_line,
208 local,
209 nl ? nl : ""
212 talloc_free(frame);
217 * Log details of a successful authorization to a service.
219 * Only successful authorizations are logged. For clarity:
220 * - NTLM bad passwords will be recorded by the above
221 * - Kerberos decrypt failures need to be logged in gensec_gssapi et al
223 * The service may later refuse authorization due to an ACL.
226 void log_successful_authz_event(const struct tsocket_address *remote,
227 const struct tsocket_address *local,
228 const char *service_description,
229 const char *auth_type,
230 struct auth_session_info *session_info)
232 TALLOC_CTX *frame = NULL;
234 const char *ts = NULL; /* formatted current time */
235 char *remote_str = NULL; /* formatted remote host */
236 char *local_str = NULL; /* formatted local host */
237 char sid_buf[DOM_SID_STR_BUFLEN];
238 int debug_level = AUTHZ_SUCCESS_LEVEL;
240 if (security_token_is_anonymous(session_info->security_token)) {
241 debug_level = AUTH_ANONYMOUS_LEVEL;
244 /* set the log level */
245 if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, debug_level)) {
246 return;
249 frame = talloc_stackframe();
251 /* Get the current time */
252 ts = get_timestamp(frame);
254 remote_str = tsocket_address_string(remote, frame);
255 local_str = tsocket_address_string(local, frame);
257 dom_sid_string_buf(&session_info->security_token->sids[0], sid_buf, sizeof(sid_buf));
259 DEBUGC( DBGC_AUTH_AUDIT, AUTHZ_SUCCESS_LEVEL, (
260 "Successful AuthZ: [%s,%s] user [%s]\\[%s] [%s]"
261 " at [%s]"
262 " Remote host [%s]"
263 " local host [%s]\n",
264 service_description,
265 auth_type,
266 log_escape(frame, session_info->info->domain_name),
267 log_escape(frame, session_info->info->account_name),
268 sid_buf,
270 remote_str,
271 local_str));
273 talloc_free(frame);