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