s3:smbspool: Fix cmdline argument handling
[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 0
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
60 /*
61  * Get a human readable timestamp.
62  *
63  * Returns the current time formatted as
64  *  "Tue, 14 Mar 2017 08:38:42.209028 NZDT"
65  *
66  * The returned string is allocated by talloc in the supplied context.
67  * It is the callers responsibility to free it.
68  *
69  */
70 static const char* get_timestamp(TALLOC_CTX *frame)
71 {
72         char buffer[40];        /* formatted time less usec and timezone */
73         char tz[10];            /* formatted time zone                   */
74         struct tm* tm_info;     /* current local time                    */
75         struct timeval tv;      /* current system time                   */
76         int r;                  /* response code from gettimeofday       */
77         const char * ts;        /* formatted time stamp                  */
78
79         r = gettimeofday(&tv, NULL);
80         if (r) {
81                 DBG_ERR("Unable to get time of day: (%d) %s\n",
82                         errno,
83                         strerror(errno));
84                 return NULL;
85         }
86
87         tm_info = localtime(&tv.tv_sec);
88         if (tm_info == NULL) {
89                 DBG_ERR("Unable to determine local time\n");
90                 return NULL;
91         }
92
93         strftime(buffer, sizeof(buffer)-1, "%a, %d %b %Y %H:%M:%S", tm_info);
94         strftime(tz, sizeof(tz)-1, "%Z", tm_info);
95         ts = talloc_asprintf(frame, "%s.%06ld %s", buffer, tv.tv_usec, tz);
96         if (ts == NULL) {
97                 DBG_ERR("Out of memory formatting time stamp\n");
98         }
99         return ts;
100 }
101
102 /*
103  * Determine the type of the password supplied for the
104  * authorisation attempt.
105  *
106  */
107 static const char* get_password_type(const struct auth_usersupplied_info *ui);
108
109 #ifdef HAVE_JANSSON
110
111 #include <jansson.h>
112 #include "system/time.h"
113
114 /*
115  * Context required by the JSON generation
116  *  routines
117  *
118  */
119 struct json_context {
120         json_t *root;
121         bool error;
122 };
123
124 static NTSTATUS get_auth_event_server(struct imessaging_context *msg_ctx,
125                                       struct server_id *auth_event_server)
126 {
127         NTSTATUS status;
128         TALLOC_CTX *frame = talloc_stackframe();
129         unsigned num_servers, i;
130         struct server_id *servers;
131
132         status = irpc_servers_byname(msg_ctx, frame,
133                                      AUTH_EVENT_NAME,
134                                      &num_servers, &servers);
135
136         if (!NT_STATUS_IS_OK(status)) {
137                 DBG_NOTICE("Failed to find 'auth_event' registered on the "
138                            "message bus to send JSON authentication events to: %s\n",
139                            nt_errstr(status));
140                 TALLOC_FREE(frame);
141                 return status;
142         }
143
144         /*
145          * Select the first server that is listening, because
146          * we get connection refused as
147          * NT_STATUS_OBJECT_NAME_NOT_FOUND without waiting
148          */
149         for (i = 0; i < num_servers; i++) {
150                 status = imessaging_send(msg_ctx, servers[i], MSG_PING,
151                                          &data_blob_null);
152                 if (NT_STATUS_IS_OK(status)) {
153                         *auth_event_server = servers[i];
154                         TALLOC_FREE(frame);
155                         return NT_STATUS_OK;
156                 }
157         }
158         DBG_NOTICE("Failed to find a running 'auth_event' server "
159                    "registered on the message bus to send JSON "
160                    "authentication events to\n");
161         TALLOC_FREE(frame);
162         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
163 }
164
165 static void auth_message_send(struct imessaging_context *msg_ctx,
166                               const char *json)
167 {
168         struct server_id auth_event_server;
169         NTSTATUS status;
170         DATA_BLOB json_blob = data_blob_string_const(json);
171         if (msg_ctx == NULL) {
172                 return;
173         }
174
175         /* Need to refetch the address each time as the destination server may
176          * have disconnected and reconnected in the interim, in which case
177          * messages may get lost, manifests in the auth_log tests
178          */
179         status = get_auth_event_server(msg_ctx, &auth_event_server);
180         if (!NT_STATUS_IS_OK(status)) {
181                 return;
182         }
183
184         status = imessaging_send(msg_ctx, auth_event_server, MSG_AUTH_LOG,
185                                  &json_blob);
186
187         /* If the server crashed, try to find it again */
188         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
189                 status = get_auth_event_server(msg_ctx, &auth_event_server);
190                 if (!NT_STATUS_IS_OK(status)) {
191                         return;
192                 }
193                 imessaging_send(msg_ctx, auth_event_server, MSG_AUTH_LOG,
194                                 &json_blob);
195
196         }
197 }
198
199 /*
200  * Write the json object to the debug logs.
201  *
202  */
203 static void log_json(struct imessaging_context *msg_ctx,
204                      struct loadparm_context *lp_ctx,
205                      struct json_context *context,
206                      const char *type, int debug_class, int debug_level)
207 {
208         char* json = NULL;
209
210         if (context->error) {
211                 return;
212         }
213
214         json = json_dumps(context->root, 0);
215         if (json == NULL) {
216                 DBG_ERR("Unable to convert JSON object to string\n");
217                 context->error = true;
218                 return;
219         }
220
221         DEBUGC(debug_class, debug_level, ("JSON %s: %s\n", type, json));
222         if (msg_ctx && lp_ctx && lpcfg_auth_event_notification(lp_ctx)) {
223                 auth_message_send(msg_ctx, json);
224         }
225
226         if (json) {
227                 free(json);
228         }
229
230 }
231
232 /*
233  * Create a new json logging context.
234  *
235  * Free with a call to free_json_context
236  *
237  */
238 static struct json_context get_json_context(void) {
239
240         struct json_context context;
241         context.error = false;
242
243         context.root = json_object();
244         if (context.root == NULL) {
245                 context.error = true;
246                 DBG_ERR("Unable to create json_object\n");
247         }
248         return context;
249 }
250
251 /*
252  * free a previously created json_context
253  *
254  */
255 static void free_json_context(struct json_context *context)
256 {
257         if (context->root) {
258                 json_decref(context->root);
259         }
260 }
261
262 /*
263  * Output a JSON pair with name name and integer value value
264  *
265  */
266 static void add_int(struct json_context *context,
267                     const char* name,
268                     const int value)
269 {
270         int rc = 0;
271
272         if (context->error) {
273                 return;
274         }
275
276         rc = json_object_set_new(context->root, name, json_integer(value));
277         if (rc) {
278                 DBG_ERR("Unable to set name [%s] value [%d]\n", name, value);
279                 context->error = true;
280         }
281
282 }
283
284 /*
285  * Output a JSON pair with name name and string value value
286  *
287  */
288 static void add_string(struct json_context *context,
289                        const char* name,
290                        const char* value)
291 {
292         int rc = 0;
293
294         if (context->error) {
295                 return;
296         }
297
298         if (value) {
299                 rc = json_object_set_new(context->root, name, json_string(value));
300         } else {
301                 rc = json_object_set_new(context->root, name, json_null());
302         }
303         if (rc) {
304                 DBG_ERR("Unable to set name [%s] value [%s]\n", name, value);
305                 context->error = true;
306         }
307 }
308
309
310 /*
311  * Output a JSON pair with name name and object value
312  *
313  */
314 static void add_object(struct json_context *context,
315                        const char* name,
316                        struct json_context *value)
317 {
318         int rc = 0;
319
320         if (value->error) {
321                 context->error = true;
322         }
323         if (context->error) {
324                 return;
325         }
326         rc = json_object_set_new(context->root, name, value->root);
327         if (rc) {
328                 DBG_ERR("Unable to add object [%s]\n", name);
329                 context->error = true;
330         }
331 }
332
333 /*
334  * Output a version object
335  *
336  * "version":{"major":1,"minor":0}
337  *
338  */
339 static void add_version(struct json_context *context, int major, int minor)
340 {
341         struct json_context version = get_json_context();
342         add_int(&version, "major", major);
343         add_int(&version, "minor", minor);
344         add_object(context, "version", &version);
345 }
346
347 /*
348  * Output the current date and time as a timestamp in ISO 8601 format
349  *
350  * "timestamp":"2017-03-06T17:18:04.455081+1300"
351  *
352  */
353 static void add_timestamp(struct json_context *context)
354 {
355         char buffer[40];        /* formatted time less usec and timezone */
356         char timestamp[50];     /* the formatted ISO 8601 time stamp     */
357         char tz[10];            /* formatted time zone                   */
358         struct tm* tm_info;     /* current local time                    */
359         struct timeval tv;      /* current system time                   */
360         int r;                  /* response code from gettimeofday       */
361
362         if (context->error) {
363                 return;
364         }
365
366         r = gettimeofday(&tv, NULL);
367         if (r) {
368                 DBG_ERR("Unable to get time of day: (%d) %s\n",
369                         errno,
370                         strerror(errno));
371                 context->error = true;
372                 return;
373         }
374
375         tm_info = localtime(&tv.tv_sec);
376         if (tm_info == NULL) {
377                 DBG_ERR("Unable to determine local time\n");
378                 context->error = true;
379                 return;
380         }
381
382         strftime(buffer, sizeof(buffer)-1, "%Y-%m-%dT%T", tm_info);
383         strftime(tz, sizeof(tz)-1, "%z", tm_info);
384         snprintf(timestamp, sizeof(timestamp),"%s.%06ld%s",
385                  buffer, tv.tv_usec, tz);
386         add_string(context,"timestamp", timestamp);
387 }
388
389
390 /*
391  * Output an address pair, with name name.
392  *
393  * "localAddress":"ipv6::::0"
394  *
395  */
396 static void add_address(struct json_context *context,
397                         const char *name,
398                         const struct tsocket_address *address)
399 {
400         char *s = NULL;
401         TALLOC_CTX *frame = talloc_stackframe();
402
403         if (context->error) {
404                 return;
405         }
406
407         s = tsocket_address_string(address, frame);
408         add_string(context, name, s);
409         talloc_free(frame);
410
411 }
412
413 /*
414  * Output a SID with name name
415  *
416  * "sid":"S-1-5-18"
417  *
418  */
419 static void add_sid(struct json_context *context,
420                     const char *name,
421                     const struct dom_sid *sid)
422 {
423         char sid_buf[DOM_SID_STR_BUFLEN];
424
425         if (context->error) {
426                 return;
427         }
428
429         dom_sid_string_buf(sid, sid_buf, sizeof(sid_buf));
430         add_string(context, name, sid_buf);
431 }
432
433 /*
434  * Write a machine parsable json formatted authentication log entry.
435  *
436  * IF removing or changing the format/meaning of a field please update the
437  *    major version number AUTH_MAJOR
438  *
439  * IF adding a new field please update the minor version number AUTH_MINOR
440  *
441  *  To process the resulting log lines from the commend line use jq to
442  *  parse the json.
443  *
444  *  grep "JSON Authentication" log file |
445  *  sed 's;^[^{]*;;' |
446  * jq -rc  '"\(.timestamp)\t\(.Authentication.status)\t
447  *           \(.Authentication.clientDomain)\t
448  *           \(.Authentication.clientAccount)
449  *           \t\(.Authentication.workstation)
450  *           \t\(.Authentication.remoteAddress)
451  *           \t\(.Authentication.localAddress)"'
452  */
453 static void log_authentication_event_json(
454                         struct imessaging_context *msg_ctx,
455                         struct loadparm_context *lp_ctx,
456                         const struct auth_usersupplied_info *ui,
457                         NTSTATUS status,
458                         const char *domain_name,
459                         const char *account_name,
460                         const char *unix_username,
461                         struct dom_sid *sid,
462                         int debug_level)
463 {
464         struct json_context context = get_json_context();
465         struct json_context authentication;
466         char negotiate_flags[11];
467
468         add_timestamp(&context);
469         add_string(&context, "type", AUTH_JSON_TYPE);
470
471         authentication = get_json_context();
472         add_version(&authentication, AUTH_MAJOR, AUTH_MINOR);
473         add_string(&authentication, "status", nt_errstr(status));
474         add_address(&authentication, "localAddress", ui->local_host);
475         add_address(&authentication, "remoteAddress", ui->remote_host);
476         add_string(&authentication,
477                    "serviceDescription",
478                    ui->service_description);
479         add_string(&authentication, "authDescription", ui->auth_description);
480         add_string(&authentication, "clientDomain", ui->client.domain_name);
481         add_string(&authentication, "clientAccount", ui->client.account_name);
482         add_string(&authentication, "workstation", ui->workstation_name);
483         add_string(&authentication, "becameAccount", account_name);
484         add_string(&authentication, "becameDomain", domain_name);
485         add_sid(&authentication, "becameSid", sid);
486         add_string(&authentication, "mappedAccount", ui->mapped.account_name);
487         add_string(&authentication, "mappedDomain", ui->mapped.domain_name);
488         add_string(&authentication,
489                    "netlogonComputer",
490                    ui->netlogon_trust_account.computer_name);
491         add_string(&authentication,
492                    "netlogonTrustAccount",
493                    ui->netlogon_trust_account.account_name);
494         snprintf(negotiate_flags,
495                  sizeof( negotiate_flags),
496                  "0x%08X",
497                  ui->netlogon_trust_account.negotiate_flags);
498         add_string(&authentication, "netlogonNegotiateFlags", negotiate_flags);
499         add_int(&authentication,
500                 "netlogonSecureChannelType",
501                 ui->netlogon_trust_account.secure_channel_type);
502         add_sid(&authentication,
503                 "netlogonTrustAccountSid",
504                 ui->netlogon_trust_account.sid);
505         add_string(&authentication, "passwordType", get_password_type(ui));
506         add_object(&context,AUTH_JSON_TYPE, &authentication);
507
508         log_json(msg_ctx,
509                  lp_ctx,
510                  &context,
511                  AUTH_JSON_TYPE,
512                  DBGC_AUTH_AUDIT,
513                  debug_level);
514         free_json_context(&context);
515 }
516
517 /*
518  * Log details of a successful authorization to a service,
519  * in a machine parsable json format
520  *
521  * IF removing or changing the format/meaning of a field please update the
522  *    major version number AUTHZ_MAJOR
523  *
524  * IF adding a new field please update the minor version number AUTHZ_MINOR
525  *
526  *  To process the resulting log lines from the commend line use jq to
527  *  parse the json.
528  *
529  *  grep "JSON Authentication" log_file |\
530  *  sed "s;^[^{]*;;" |\
531  *  jq -rc '"\(.timestamp)\t
532  *           \(.Authorization.domain)\t
533  *           \(.Authorization.account)\t
534  *           \(.Authorization.remoteAddress)"'
535  *
536  */
537 static void log_successful_authz_event_json(
538                                 struct imessaging_context *msg_ctx,
539                                 struct loadparm_context *lp_ctx,
540                                 const struct tsocket_address *remote,
541                                 const struct tsocket_address *local,
542                                 const char *service_description,
543                                 const char *auth_type,
544                                 const char *transport_protection,
545                                 struct auth_session_info *session_info,
546                                 int debug_level)
547 {
548         struct json_context context = get_json_context();
549         struct json_context authorization;
550         char account_flags[11];
551
552         //start_object(&context, NULL);
553         add_timestamp(&context);
554         add_string(&context, "type", AUTHZ_JSON_TYPE);
555         authorization = get_json_context();
556         add_version(&authorization, AUTHZ_MAJOR, AUTHZ_MINOR);
557         add_address(&authorization, "localAddress", local);
558         add_address(&authorization, "remoteAddress", remote);
559         add_string(&authorization, "serviceDescription", service_description);
560         add_string(&authorization, "authType", auth_type);
561         add_string(&authorization, "domain", session_info->info->domain_name);
562         add_string(&authorization, "account", session_info->info->account_name);
563         add_sid(&authorization, "sid", &session_info->security_token->sids[0]);
564         add_string(&authorization,
565                    "logonServer",
566                    session_info->info->logon_server);
567         add_string(&authorization, "transportProtection", transport_protection);
568
569         snprintf(account_flags,
570                  sizeof(account_flags),
571                  "0x%08X",
572                  session_info->info->acct_flags);
573         add_string(&authorization, "accountFlags", account_flags);
574         add_object(&context,AUTHZ_JSON_TYPE, &authorization);
575
576         log_json(msg_ctx,
577                  lp_ctx,
578                  &context,
579                  AUTHZ_JSON_TYPE,
580                  DBGC_AUTH_AUDIT,
581                  debug_level);
582         free_json_context(&context);
583 }
584
585 #else
586
587 static void log_no_json(struct imessaging_context *msg_ctx,
588                         struct loadparm_context *lp_ctx)
589 {
590         if (msg_ctx && lp_ctx && lpcfg_auth_event_notification(lp_ctx)) {
591                 static bool auth_event_logged = false;
592                 if (auth_event_logged == false) {
593                         auth_event_logged = true;
594                         DBG_ERR("auth event notification = true but Samba was not compiled with jansson\n");
595                 }
596         } else {
597                 static bool json_logged = false;
598                 if (json_logged == false) {
599                         json_logged = true;
600                         DBG_NOTICE("JSON auth logs not available unless compiled with jansson\n");
601                 }
602         }
603
604         return;
605 }
606
607 static void log_authentication_event_json(
608                         struct imessaging_context *msg_ctx,
609                         struct loadparm_context *lp_ctx,
610                         const struct auth_usersupplied_info *ui,
611                         NTSTATUS status,
612                         const char *domain_name,
613                         const char *account_name,
614                         const char *unix_username,
615                         struct dom_sid *sid,
616                         int debug_level)
617 {
618         log_no_json(msg_ctx, lp_ctx);
619         return;
620 }
621
622 static void log_successful_authz_event_json(
623                                 struct imessaging_context *msg_ctx,
624                                 struct loadparm_context *lp_ctx,
625                                 const struct tsocket_address *remote,
626                                 const struct tsocket_address *local,
627                                 const char *service_description,
628                                 const char *auth_type,
629                                 const char *transport_protection,
630                                 struct auth_session_info *session_info,
631                                 int debug_level)
632 {
633         log_no_json(msg_ctx, lp_ctx);
634         return;
635 }
636
637 #endif
638
639 /*
640  * Determine the type of the password supplied for the
641  * authorisation attempt.
642  *
643  */
644 static const char* get_password_type(const struct auth_usersupplied_info *ui)
645 {
646
647         const char *password_type = NULL;
648
649         if (ui->password_type != NULL) {
650                 password_type = ui->password_type;
651         } else if (ui->auth_description != NULL &&
652                    strncmp("ServerAuthenticate", ui->auth_description, 18) == 0)
653         {
654                 if (ui->netlogon_trust_account.negotiate_flags
655                     & NETLOGON_NEG_SUPPORTS_AES) {
656                         password_type = "HMAC-SHA256";
657                 } else if (ui->netlogon_trust_account.negotiate_flags
658                            & NETLOGON_NEG_STRONG_KEYS) {
659                         password_type = "HMAC-MD5";
660                 } else {
661                         password_type = "DES";
662                 }
663         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE &&
664                    (ui->logon_parameters & MSV1_0_ALLOW_MSVCHAPV2) &&
665                    ui->password.response.nt.length == 24) {
666                 password_type = "MSCHAPv2";
667         } else if ((ui->logon_parameters & MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED)
668                    || (ui->password_state == AUTH_PASSWORD_PLAIN)) {
669                 password_type = "Plaintext";
670         } else if (ui->password_state == AUTH_PASSWORD_HASH) {
671                 password_type = "Supplied-NT-Hash";
672         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
673                    && ui->password.response.nt.length > 24) {
674                 password_type = "NTLMv2";
675         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
676                    && ui->password.response.nt.length == 24) {
677                 password_type = "NTLMv1";
678         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
679                    && ui->password.response.lanman.length == 24) {
680                 password_type = "LANMan";
681         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
682                    && ui->password.response.nt.length == 0
683                    && ui->password.response.lanman.length == 0) {
684                 password_type = "No-Password";
685         }
686         return password_type;
687 }
688
689 /*
690  * Write a human readable authentication log entry.
691  *
692  */
693 static void log_authentication_event_human_readable(
694                         const struct auth_usersupplied_info *ui,
695                         NTSTATUS status,
696                         const char *domain_name,
697                         const char *account_name,
698                         const char *unix_username,
699                         struct dom_sid *sid,
700                         int debug_level)
701 {
702         TALLOC_CTX *frame = NULL;
703
704         const char *ts = NULL;             /* formatted current time      */
705         char *remote = NULL;               /* formatted remote host       */
706         char *local = NULL;                /* formatted local host        */
707         char *nl = NULL;                   /* NETLOGON details if present */
708         char *trust_computer_name = NULL;
709         char *trust_account_name = NULL;
710         char *logon_line = NULL;
711         const char *password_type = NULL;
712
713         frame = talloc_stackframe();
714
715         password_type = get_password_type(ui);
716         /* Get the current time */
717         ts = get_timestamp(frame);
718
719         /* Only log the NETLOGON details if they are present */
720         if (ui->netlogon_trust_account.computer_name ||
721             ui->netlogon_trust_account.account_name) {
722                 trust_computer_name = log_escape(frame,
723                         ui->netlogon_trust_account.computer_name);
724                 trust_account_name  = log_escape(frame,
725                         ui->netlogon_trust_account.account_name);
726                 nl = talloc_asprintf(frame,
727                         " NETLOGON computer [%s] trust account [%s]",
728                         trust_computer_name, trust_account_name);
729         }
730
731         remote = tsocket_address_string(ui->remote_host, frame);
732         local = tsocket_address_string(ui->local_host, frame);
733
734         if (NT_STATUS_IS_OK(status)) {
735                 char sid_buf[DOM_SID_STR_BUFLEN];
736
737                 dom_sid_string_buf(sid, sid_buf, sizeof(sid_buf));
738                 logon_line = talloc_asprintf(frame,
739                                              " became [%s]\\[%s] [%s].",
740                                              log_escape(frame, domain_name),
741                                              log_escape(frame, account_name),
742                                              sid_buf);
743         } else {
744                 logon_line = talloc_asprintf(
745                                 frame,
746                                 " mapped to [%s]\\[%s].",
747                                 log_escape(frame, ui->mapped.domain_name),
748                                 log_escape(frame, ui->mapped.account_name));
749         }
750
751         DEBUGC(DBGC_AUTH_AUDIT, debug_level,
752                ("Auth: [%s,%s] user [%s]\\[%s]"
753                 " at [%s] with [%s] status [%s]"
754                 " workstation [%s] remote host [%s]"
755                 "%s local host [%s]"
756                 " %s\n",
757                 ui->service_description,
758                 ui->auth_description,
759                 log_escape(frame, ui->client.domain_name),
760                 log_escape(frame, ui->client.account_name),
761                 ts,
762                 password_type,
763                 nt_errstr(status),
764                 log_escape(frame, ui->workstation_name),
765                 remote,
766                 logon_line,
767                 local,
768                 nl ? nl : ""
769                ));
770
771         talloc_free(frame);
772 }
773
774 /*
775  * Log details of an authentication attempt.
776  * Successful and unsuccessful attempts are logged.
777  *
778  * NOTE: msg_ctx and lp_ctx is optional, but when supplied allows streaming the
779  * authentication events over the message bus.
780  */
781 void log_authentication_event(struct imessaging_context *msg_ctx,
782                               struct loadparm_context *lp_ctx,
783                               const struct auth_usersupplied_info *ui,
784                               NTSTATUS status,
785                               const char *domain_name,
786                               const char *account_name,
787                               const char *unix_username,
788                               struct dom_sid *sid)
789 {
790         /* set the log level */
791         int debug_level = AUTH_FAILURE_LEVEL;
792
793         if (NT_STATUS_IS_OK(status)) {
794                 debug_level = AUTH_SUCCESS_LEVEL;
795                 if (dom_sid_equal(sid, &global_sid_Anonymous)) {
796                         debug_level = AUTH_ANONYMOUS_LEVEL;
797                 }
798         }
799
800         if (CHECK_DEBUGLVLC(DBGC_AUTH_AUDIT, debug_level)) {
801                 log_authentication_event_human_readable(ui,
802                                                         status,
803                                                         domain_name,
804                                                         account_name,
805                                                         unix_username,
806                                                         sid,
807                                                         debug_level);
808         }
809         if (CHECK_DEBUGLVLC(DBGC_AUTH_AUDIT_JSON, debug_level) ||
810             (msg_ctx && lp_ctx && lpcfg_auth_event_notification(lp_ctx))) {
811                 log_authentication_event_json(msg_ctx, lp_ctx,
812                                               ui,
813                                               status,
814                                               domain_name,
815                                               account_name,
816                                               unix_username,
817                                               sid,
818                                               debug_level);
819         }
820 }
821
822
823
824 /*
825  * Log details of a successful authorization to a service,
826  * in a human readable format.
827  *
828  */
829 static void log_successful_authz_event_human_readable(
830                                 const struct tsocket_address *remote,
831                                 const struct tsocket_address *local,
832                                 const char *service_description,
833                                 const char *auth_type,
834                                 const char *transport_protection,
835                                 struct auth_session_info *session_info,
836                                 int debug_level)
837 {
838         TALLOC_CTX *frame = NULL;
839
840         const char *ts = NULL;       /* formatted current time      */
841         char *remote_str = NULL;     /* formatted remote host       */
842         char *local_str = NULL;      /* formatted local host        */
843         char sid_buf[DOM_SID_STR_BUFLEN];
844
845         frame = talloc_stackframe();
846
847         /* Get the current time */
848         ts = get_timestamp(frame);
849
850         remote_str = tsocket_address_string(remote, frame);
851         local_str = tsocket_address_string(local, frame);
852
853         dom_sid_string_buf(&session_info->security_token->sids[0],
854                            sid_buf,
855                            sizeof(sid_buf));
856
857         DEBUGC(DBGC_AUTH_AUDIT, debug_level,
858                ("Successful AuthZ: [%s,%s] user [%s]\\[%s] [%s]"
859                 " at [%s]"
860                 " Remote host [%s]"
861                 " local host [%s]\n",
862                 service_description,
863                 auth_type,
864                 log_escape(frame, session_info->info->domain_name),
865                 log_escape(frame, session_info->info->account_name),
866                 sid_buf,
867                 ts,
868                 remote_str,
869                 local_str));
870
871         talloc_free(frame);
872 }
873
874 /*
875  * Log details of a successful authorization to a service.
876  *
877  * Only successful authorizations are logged.  For clarity:
878  * - NTLM bad passwords will be recorded by log_authentication_event
879  * - Kerberos decrypt failures need to be logged in gensec_gssapi et al
880  *
881  * The service may later refuse authorization due to an ACL.
882  *
883  * NOTE: msg_ctx and lp_ctx is optional, but when supplied allows streaming the
884  * authentication events over the message bus.
885  */
886 void log_successful_authz_event(struct imessaging_context *msg_ctx,
887                                 struct loadparm_context *lp_ctx,
888                                 const struct tsocket_address *remote,
889                                 const struct tsocket_address *local,
890                                 const char *service_description,
891                                 const char *auth_type,
892                                 const char *transport_protection,
893                                 struct auth_session_info *session_info)
894 {
895         int debug_level = AUTHZ_SUCCESS_LEVEL;
896
897         /* set the log level */
898         if (security_token_is_anonymous(session_info->security_token)) {
899                 debug_level = AUTH_ANONYMOUS_LEVEL;
900         }
901
902         if (CHECK_DEBUGLVLC(DBGC_AUTH_AUDIT, debug_level)) {
903                 log_successful_authz_event_human_readable(remote,
904                                                           local,
905                                                           service_description,
906                                                           auth_type,
907                                                           transport_protection,
908                                                           session_info,
909                                                           debug_level);
910         }
911         if (CHECK_DEBUGLVLC(DBGC_AUTH_AUDIT_JSON, debug_level) ||
912             (msg_ctx && lp_ctx && lpcfg_auth_event_notification(lp_ctx))) {
913                 log_successful_authz_event_json(msg_ctx, lp_ctx,
914                                                 remote,
915                                                 local,
916                                                 service_description,
917                                                 auth_type,
918                                                 transport_protection,
919                                                 session_info,
920                                                 debug_level);
921         }
922 }