auth: For NTLM and KDC authentication, log the authentication duration
[samba.git] / auth / auth_log.c
1 /*
2
3    Authentication and authorization logging
4
5    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017
6
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.
11
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.
16
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/>.
19 */
20
21 /*
22  * Debug log levels for authentication logging (these both map to
23  * LOG_NOTICE in syslog)
24  */
25 #define AUTH_FAILURE_LEVEL 2
26 #define AUTH_SUCCESS_LEVEL 3
27 #define AUTHZ_SUCCESS_LEVEL 4
28
29 /* 5 is used for both authentication and authorization */
30 #define AUTH_ANONYMOUS_LEVEL 5
31 #define AUTHZ_ANONYMOUS_LEVEL 5
32
33 #define AUTHZ_JSON_TYPE "Authorization"
34 #define AUTH_JSON_TYPE  "Authentication"
35
36 /*
37  * JSON message version numbers
38  *
39  * If adding a field increment the minor version
40  * If removing or changing the format/meaning of a field
41  * increment the major version.
42  */
43 #define AUTH_MAJOR 1
44 #define AUTH_MINOR 0
45 #define AUTHZ_MAJOR 1
46 #define AUTHZ_MINOR 1
47
48 #include "includes.h"
49 #include "../lib/tsocket/tsocket.h"
50 #include "common_auth.h"
51 #include "lib/util/util_str_escape.h"
52 #include "libcli/security/dom_sid.h"
53 #include "libcli/security/security_token.h"
54 #include "librpc/gen_ndr/server_id.h"
55 #include "source4/lib/messaging/messaging.h"
56 #include "source4/lib/messaging/irpc.h"
57 #include "lib/util/server_id_db.h"
58 #include "lib/param/param.h"
59 #include "librpc/ndr/libndr.h"
60 #include "lib/audit_logging/audit_logging.h"
61
62 /*
63  * Determine the type of the password supplied for the
64  * authorisation attempt.
65  *
66  */
67 static const char* get_password_type(const struct auth_usersupplied_info *ui);
68
69 #ifdef HAVE_JANSSON
70
71 #include <jansson.h>
72 #include "system/time.h"
73
74 /*
75  * Write the json object to the debug logs.
76  *
77  */
78 static void log_json(struct imessaging_context *msg_ctx,
79                      struct loadparm_context *lp_ctx,
80                      struct json_object *object,
81                      const char *type,
82                      int debug_class,
83                      int debug_level)
84 {
85         audit_log_json(type, object, debug_class, debug_level);
86         if (msg_ctx && lp_ctx && lpcfg_auth_event_notification(lp_ctx)) {
87                 audit_message_send(msg_ctx,
88                                    AUTH_EVENT_NAME,
89                                    MSG_AUTH_LOG,
90                                    object);
91         }
92 }
93
94 /*
95  * Write a machine parsable json formatted authentication log entry.
96  *
97  * IF removing or changing the format/meaning of a field please update the
98  *    major version number AUTH_MAJOR
99  *
100  * IF adding a new field please update the minor version number AUTH_MINOR
101  *
102  *  To process the resulting log lines from the commend line use jq to
103  *  parse the json.
104  *
105  *  grep "JSON Authentication" log file |
106  *  sed 's;^[^{]*;;' |
107  * jq -rc  '"\(.timestamp)\t\(.Authentication.status)\t
108  *           \(.Authentication.clientDomain)\t
109  *           \(.Authentication.clientAccount)
110  *           \t\(.Authentication.workstation)
111  *           \t\(.Authentication.remoteAddress)
112  *           \t\(.Authentication.localAddress)"'
113  */
114 static void log_authentication_event_json(
115         struct imessaging_context *msg_ctx,
116         struct loadparm_context *lp_ctx,
117         const struct timeval *start_time,
118         const struct auth_usersupplied_info *ui,
119         NTSTATUS status,
120         const char *domain_name,
121         const char *account_name,
122         const char *unix_username,
123         struct dom_sid *sid,
124         int debug_level)
125 {
126         struct json_object wrapper = json_new_object();
127         struct json_object authentication;
128         char negotiate_flags[11];
129
130         json_add_timestamp(&wrapper);
131         json_add_string(&wrapper, "type", AUTH_JSON_TYPE);
132
133         authentication = json_new_object();
134         json_add_version(&authentication, AUTH_MAJOR, AUTH_MINOR);
135         json_add_string(&authentication, "status", nt_errstr(status));
136         json_add_address(&authentication, "localAddress", ui->local_host);
137         json_add_address(&authentication, "remoteAddress", ui->remote_host);
138         json_add_string(&authentication,
139                         "serviceDescription",
140                         ui->service_description);
141         json_add_string(&authentication,
142                         "authDescription",
143                         ui->auth_description);
144         json_add_string(&authentication,
145                         "clientDomain",
146                         ui->client.domain_name);
147         json_add_string(&authentication,
148                         "clientAccount",
149                         ui->client.account_name);
150         json_add_string(&authentication,
151                         "workstation",
152                         ui->workstation_name);
153         json_add_string(&authentication, "becameAccount", account_name);
154         json_add_string(&authentication, "becameDomain", domain_name);
155         json_add_sid(&authentication, "becameSid", sid);
156         json_add_string(&authentication,
157                         "mappedAccount",
158                         ui->mapped.account_name);
159         json_add_string(&authentication,
160                         "mappedDomain",
161                         ui->mapped.domain_name);
162         json_add_string(&authentication,
163                         "netlogonComputer",
164                         ui->netlogon_trust_account.computer_name);
165         json_add_string(&authentication,
166                         "netlogonTrustAccount",
167                         ui->netlogon_trust_account.account_name);
168         snprintf(negotiate_flags,
169                  sizeof( negotiate_flags),
170                  "0x%08X",
171                  ui->netlogon_trust_account.negotiate_flags);
172         json_add_string(&authentication,
173                         "netlogonNegotiateFlags",
174                         negotiate_flags);
175         json_add_int(&authentication,
176                      "netlogonSecureChannelType",
177                      ui->netlogon_trust_account.secure_channel_type);
178         json_add_sid(&authentication,
179                      "netlogonTrustAccountSid",
180                      ui->netlogon_trust_account.sid);
181         json_add_string(&authentication, "passwordType", get_password_type(ui));
182         json_add_object(&wrapper, AUTH_JSON_TYPE, &authentication);
183
184         /*
185          * While not a general-purpose profiling solution this will
186          * assist some to determine how long NTLM and KDC
187          * authentication takes once this process can handle it.  This
188          * covers transactions elsewhere but not (eg) the delay while
189          * this is waiting unread on the input socket.
190          */
191         if (start_time != NULL) {
192                 struct timeval current_time = timeval_current();
193                 uint64_t duration =  usec_time_diff(&current_time,
194                                                     start_time);
195                 json_add_int(&authentication,
196                              "duration",
197                              duration);
198         }
199
200         log_json(msg_ctx,
201                  lp_ctx,
202                  &wrapper,
203                  AUTH_JSON_TYPE,
204                  DBGC_AUTH_AUDIT,
205                  debug_level);
206         json_free(&wrapper);
207 }
208
209 /*
210  * Log details of a successful authorization to a service,
211  * in a machine parsable json format
212  *
213  * IF removing or changing the format/meaning of a field please update the
214  *    major version number AUTHZ_MAJOR
215  *
216  * IF adding a new field please update the minor version number AUTHZ_MINOR
217  *
218  *  To process the resulting log lines from the commend line use jq to
219  *  parse the json.
220  *
221  *  grep "JSON Authentication" log_file |\
222  *  sed "s;^[^{]*;;" |\
223  *  jq -rc '"\(.timestamp)\t
224  *           \(.Authorization.domain)\t
225  *           \(.Authorization.account)\t
226  *           \(.Authorization.remoteAddress)"'
227  *
228  */
229 static void log_successful_authz_event_json(
230         struct imessaging_context *msg_ctx,
231         struct loadparm_context *lp_ctx,
232         const struct tsocket_address *remote,
233         const struct tsocket_address *local,
234         const char *service_description,
235         const char *auth_type,
236         const char *transport_protection,
237         struct auth_session_info *session_info,
238         int debug_level)
239 {
240         struct json_object wrapper = json_new_object();
241         struct json_object authorization;
242         char account_flags[11];
243
244         json_add_timestamp(&wrapper);
245         json_add_string(&wrapper, "type", AUTHZ_JSON_TYPE);
246         authorization = json_new_object();
247         json_add_version(&authorization, AUTHZ_MAJOR, AUTHZ_MINOR);
248         json_add_address(&authorization, "localAddress", local);
249         json_add_address(&authorization, "remoteAddress", remote);
250         json_add_string(&authorization,
251                         "serviceDescription",
252                         service_description);
253         json_add_string(&authorization, "authType", auth_type);
254         json_add_string(&authorization,
255                         "domain",
256                         session_info->info->domain_name);
257         json_add_string(&authorization,
258                         "account",
259                         session_info->info->account_name);
260         json_add_sid(&authorization,
261                      "sid",
262                      &session_info->security_token->sids[0]);
263         json_add_guid(&authorization,
264                       "sessionId",
265                       &session_info->unique_session_token);
266         json_add_string(&authorization,
267                         "logonServer",
268                         session_info->info->logon_server);
269         json_add_string(&authorization,
270                         "transportProtection",
271                         transport_protection);
272
273         snprintf(account_flags,
274                  sizeof(account_flags),
275                  "0x%08X",
276                  session_info->info->acct_flags);
277         json_add_string(&authorization, "accountFlags", account_flags);
278         json_add_object(&wrapper, AUTHZ_JSON_TYPE, &authorization);
279
280         log_json(msg_ctx,
281                  lp_ctx,
282                  &wrapper,
283                  AUTHZ_JSON_TYPE,
284                  DBGC_AUTH_AUDIT,
285                  debug_level);
286         json_free(&wrapper);
287 }
288
289 #else
290
291 static void log_no_json(struct imessaging_context *msg_ctx,
292                         struct loadparm_context *lp_ctx)
293 {
294         if (msg_ctx && lp_ctx && lpcfg_auth_event_notification(lp_ctx)) {
295                 static bool auth_event_logged = false;
296                 if (auth_event_logged == false) {
297                         auth_event_logged = true;
298                         DBG_ERR("auth event notification = true but Samba was "
299                                 "not compiled with jansson\n");
300                 }
301         } else {
302                 static bool json_logged = false;
303                 if (json_logged == false) {
304                         json_logged = true;
305                         DBG_NOTICE("JSON auth logs not available unless "
306                                    "compiled with jansson\n");
307                 }
308         }
309
310         return;
311 }
312
313 static void log_authentication_event_json(
314         struct imessaging_context *msg_ctx,
315         struct loadparm_context *lp_ctx,
316         const struct timeval *start_time,
317         const struct auth_usersupplied_info *ui,
318         NTSTATUS status,
319         const char *domain_name,
320         const char *account_name,
321         const char *unix_username,
322         struct dom_sid *sid,
323         int debug_level)
324 {
325         log_no_json(msg_ctx, lp_ctx);
326         return;
327 }
328
329 static void log_successful_authz_event_json(
330         struct imessaging_context *msg_ctx,
331         struct loadparm_context *lp_ctx,
332         const struct tsocket_address *remote,
333         const struct tsocket_address *local,
334         const char *service_description,
335         const char *auth_type,
336         const char *transport_protection,
337         struct auth_session_info *session_info,
338         int debug_level)
339 {
340         log_no_json(msg_ctx, lp_ctx);
341         return;
342 }
343
344 #endif
345
346 /*
347  * Determine the type of the password supplied for the
348  * authorisation attempt.
349  *
350  */
351 static const char* get_password_type(const struct auth_usersupplied_info *ui)
352 {
353
354         const char *password_type = NULL;
355
356         if (ui->password_type != NULL) {
357                 password_type = ui->password_type;
358         } else if (ui->auth_description != NULL &&
359                    strncmp("ServerAuthenticate", ui->auth_description, 18) == 0)
360         {
361                 if (ui->netlogon_trust_account.negotiate_flags
362                     & NETLOGON_NEG_SUPPORTS_AES) {
363                         password_type = "HMAC-SHA256";
364                 } else if (ui->netlogon_trust_account.negotiate_flags
365                            & NETLOGON_NEG_STRONG_KEYS) {
366                         password_type = "HMAC-MD5";
367                 } else {
368                         password_type = "DES";
369                 }
370         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE &&
371                    (ui->logon_parameters & MSV1_0_ALLOW_MSVCHAPV2) &&
372                    ui->password.response.nt.length == 24) {
373                 password_type = "MSCHAPv2";
374         } else if ((ui->logon_parameters & MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED)
375                    || (ui->password_state == AUTH_PASSWORD_PLAIN)) {
376                 password_type = "Plaintext";
377         } else if (ui->password_state == AUTH_PASSWORD_HASH) {
378                 password_type = "Supplied-NT-Hash";
379         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
380                    && ui->password.response.nt.length > 24) {
381                 password_type = "NTLMv2";
382         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
383                    && ui->password.response.nt.length == 24) {
384                 password_type = "NTLMv1";
385         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
386                    && ui->password.response.lanman.length == 24) {
387                 password_type = "LANMan";
388         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
389                    && ui->password.response.nt.length == 0
390                    && ui->password.response.lanman.length == 0) {
391                 password_type = "No-Password";
392         }
393         return password_type;
394 }
395
396 /*
397  * Write a human readable authentication log entry.
398  *
399  */
400 static void log_authentication_event_human_readable(
401         const struct auth_usersupplied_info *ui,
402         NTSTATUS status,
403         const char *domain_name,
404         const char *account_name,
405         const char *unix_username,
406         struct dom_sid *sid,
407         int debug_level)
408 {
409         TALLOC_CTX *frame = NULL;
410
411         const char *ts = NULL;             /* formatted current time      */
412         char *remote = NULL;               /* formatted remote host       */
413         char *local = NULL;                /* formatted local host        */
414         char *nl = NULL;                   /* NETLOGON details if present */
415         char *trust_computer_name = NULL;
416         char *trust_account_name = NULL;
417         char *logon_line = NULL;
418         const char *password_type = NULL;
419
420         frame = talloc_stackframe();
421
422         password_type = get_password_type(ui);
423         /* Get the current time */
424         ts = audit_get_timestamp(frame);
425
426         /* Only log the NETLOGON details if they are present */
427         if (ui->netlogon_trust_account.computer_name ||
428             ui->netlogon_trust_account.account_name) {
429                 trust_computer_name = log_escape(frame,
430                         ui->netlogon_trust_account.computer_name);
431                 trust_account_name  = log_escape(frame,
432                         ui->netlogon_trust_account.account_name);
433                 nl = talloc_asprintf(frame,
434                         " NETLOGON computer [%s] trust account [%s]",
435                         trust_computer_name, trust_account_name);
436         }
437
438         remote = tsocket_address_string(ui->remote_host, frame);
439         local = tsocket_address_string(ui->local_host, frame);
440
441         if (NT_STATUS_IS_OK(status)) {
442                 char sid_buf[DOM_SID_STR_BUFLEN];
443
444                 dom_sid_string_buf(sid, sid_buf, sizeof(sid_buf));
445                 logon_line = talloc_asprintf(frame,
446                                              " became [%s]\\[%s] [%s].",
447                                              log_escape(frame, domain_name),
448                                              log_escape(frame, account_name),
449                                              sid_buf);
450         } else {
451                 logon_line = talloc_asprintf(
452                                 frame,
453                                 " mapped to [%s]\\[%s].",
454                                 log_escape(frame, ui->mapped.domain_name),
455                                 log_escape(frame, ui->mapped.account_name));
456         }
457
458         DEBUGC(DBGC_AUTH_AUDIT, debug_level,
459                ("Auth: [%s,%s] user [%s]\\[%s]"
460                 " at [%s] with [%s] status [%s]"
461                 " workstation [%s] remote host [%s]"
462                 "%s local host [%s]"
463                 " %s\n",
464                 ui->service_description,
465                 ui->auth_description,
466                 log_escape(frame, ui->client.domain_name),
467                 log_escape(frame, ui->client.account_name),
468                 ts,
469                 password_type,
470                 nt_errstr(status),
471                 log_escape(frame, ui->workstation_name),
472                 remote,
473                 logon_line,
474                 local,
475                 nl ? nl : ""
476         ));
477
478         talloc_free(frame);
479 }
480
481 /*
482  * Log details of an authentication attempt.
483  * Successful and unsuccessful attempts are logged.
484  *
485  * NOTE: msg_ctx and lp_ctx is optional, but when supplied allows streaming the
486  * authentication events over the message bus.
487  */
488 void log_authentication_event(
489         struct imessaging_context *msg_ctx,
490         struct loadparm_context *lp_ctx,
491         const struct timeval *start_time,
492         const struct auth_usersupplied_info *ui,
493         NTSTATUS status,
494         const char *domain_name,
495         const char *account_name,
496         const char *unix_username,
497         struct dom_sid *sid)
498 {
499         /* set the log level */
500         int debug_level = AUTH_FAILURE_LEVEL;
501
502         if (NT_STATUS_IS_OK(status)) {
503                 debug_level = AUTH_SUCCESS_LEVEL;
504                 if (dom_sid_equal(sid, &global_sid_Anonymous)) {
505                         debug_level = AUTH_ANONYMOUS_LEVEL;
506                 }
507         }
508
509         if (CHECK_DEBUGLVLC(DBGC_AUTH_AUDIT, debug_level)) {
510                 log_authentication_event_human_readable(ui,
511                                                         status,
512                                                         domain_name,
513                                                         account_name,
514                                                         unix_username,
515                                                         sid,
516                                                         debug_level);
517         }
518         if (CHECK_DEBUGLVLC(DBGC_AUTH_AUDIT_JSON, debug_level) ||
519             (msg_ctx && lp_ctx && lpcfg_auth_event_notification(lp_ctx))) {
520                 log_authentication_event_json(msg_ctx,
521                                               lp_ctx,
522                                               start_time,
523                                               ui,
524                                               status,
525                                               domain_name,
526                                               account_name,
527                                               unix_username,
528                                               sid,
529                                               debug_level);
530         }
531 }
532
533
534
535 /*
536  * Log details of a successful authorization to a service,
537  * in a human readable format.
538  *
539  */
540 static void log_successful_authz_event_human_readable(
541         const struct tsocket_address *remote,
542         const struct tsocket_address *local,
543         const char *service_description,
544         const char *auth_type,
545         const char *transport_protection,
546         struct auth_session_info *session_info,
547         int debug_level)
548 {
549         TALLOC_CTX *frame = NULL;
550
551         const char *ts = NULL;       /* formatted current time      */
552         char *remote_str = NULL;     /* formatted remote host       */
553         char *local_str = NULL;      /* formatted local host        */
554         char sid_buf[DOM_SID_STR_BUFLEN];
555
556         frame = talloc_stackframe();
557
558         /* Get the current time */
559         ts = audit_get_timestamp(frame);
560
561         remote_str = tsocket_address_string(remote, frame);
562         local_str = tsocket_address_string(local, frame);
563
564         dom_sid_string_buf(&session_info->security_token->sids[0],
565                            sid_buf,
566                            sizeof(sid_buf));
567
568         DEBUGC(DBGC_AUTH_AUDIT, debug_level,
569                ("Successful AuthZ: [%s,%s] user [%s]\\[%s] [%s]"
570                 " at [%s]"
571                 " Remote host [%s]"
572                 " local host [%s]\n",
573                 service_description,
574                 auth_type,
575                 log_escape(frame, session_info->info->domain_name),
576                 log_escape(frame, session_info->info->account_name),
577                 sid_buf,
578                 ts,
579                 remote_str,
580                 local_str));
581
582         talloc_free(frame);
583 }
584
585 /*
586  * Log details of a successful authorization to a service.
587  *
588  * Only successful authorizations are logged.  For clarity:
589  * - NTLM bad passwords will be recorded by log_authentication_event
590  * - Kerberos decrypt failures need to be logged in gensec_gssapi et al
591  *
592  * The service may later refuse authorization due to an ACL.
593  *
594  * NOTE: msg_ctx and lp_ctx is optional, but when supplied allows streaming the
595  * authentication events over the message bus.
596  */
597 void log_successful_authz_event(
598         struct imessaging_context *msg_ctx,
599         struct loadparm_context *lp_ctx,
600         const struct tsocket_address *remote,
601         const struct tsocket_address *local,
602         const char *service_description,
603         const char *auth_type,
604         const char *transport_protection,
605         struct auth_session_info *session_info)
606 {
607         int debug_level = AUTHZ_SUCCESS_LEVEL;
608
609         /* set the log level */
610         if (security_token_is_anonymous(session_info->security_token)) {
611                 debug_level = AUTH_ANONYMOUS_LEVEL;
612         }
613
614         if (CHECK_DEBUGLVLC(DBGC_AUTH_AUDIT, debug_level)) {
615                 log_successful_authz_event_human_readable(remote,
616                                                           local,
617                                                           service_description,
618                                                           auth_type,
619                                                           transport_protection,
620                                                           session_info,
621                                                           debug_level);
622         }
623         if (CHECK_DEBUGLVLC(DBGC_AUTH_AUDIT_JSON, debug_level) ||
624             (msg_ctx && lp_ctx && lpcfg_auth_event_notification(lp_ctx))) {
625                 log_successful_authz_event_json(msg_ctx, lp_ctx,
626                                                 remote,
627                                                 local,
628                                                 service_description,
629                                                 auth_type,
630                                                 transport_protection,
631                                                 session_info,
632                                                 debug_level);
633         }
634 }