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
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
);
61 DBG_ERR("Unable to get time of day: (%d) %s\n",
67 tm_info
= localtime(&tv
.tv_sec
);
68 if (tm_info
== NULL
) {
69 DBG_ERR("Unable to determine local time\n");
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
);
77 DBG_ERR("Out of memory formatting time stamp\n");
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
,
125 const char *domain_name
,
126 const char *account_name
,
127 const char *unix_username
,
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
)) {
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
),
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]"
198 ui
->service_description
,
199 ui
->auth_description
,
200 log_escape(frame
, ui
->client
.domain_name
),
201 log_escape(frame
, ui
->client
.account_name
),
205 log_escape(frame
, ui
->workstation_name
),
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
)) {
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]"
263 " local host [%s]\n",
266 log_escape(frame
, session_info
->info
->domain_name
),
267 log_escape(frame
, session_info
->info
->account_name
),