auth_log: Improve comment
[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 json_context *context,
204                      const char *type, int debug_class, int debug_level)
205 {
206         char* json = NULL;
207
208         if( context->error) {
209                 return;
210         }
211
212         json = json_dumps( context->root, 0);
213         if (json == NULL) {
214                 DBG_ERR( "Unable to convert JSON object to string\n");
215                 context->error = true;
216                 return;
217         }
218
219         DEBUGC( debug_class, debug_level, ( "JSON %s: %s\n", type, json));
220
221         if (json) {
222                 free(json);
223         }
224
225 }
226
227 /*
228  * Create a new json logging context.
229  *
230  * Free with a call to free_json_context
231  *
232  */
233 static struct json_context get_json_context( void) {
234
235         struct json_context context;
236         context.error = false;
237
238         context.root = json_object();
239         if (context.root == NULL) {
240                 context.error = true;
241                 DBG_ERR("Unable to create json_object\n");
242         }
243         return context;
244 }
245
246 /*
247  * free a previously created json_context
248  *
249  */
250 static void free_json_context(struct json_context *context)
251 {
252         if (context->root) {
253                 json_decref( context->root);
254         }
255 }
256
257 /*
258  * Output a JSON pair with name name and integer value value
259  *
260  */
261 static void add_int(struct json_context *context,
262                     const char* name,
263                     const int value)
264 {
265         int rc = 0;
266
267         if (context->error) {
268                 return;
269         }
270
271         rc = json_object_set_new( context->root, name, json_integer( value));
272         if (rc) {
273                 DBG_ERR("Unable to set name [%s] value [%d]\n", name, value);
274                 context->error = true;
275         }
276
277 }
278
279 /*
280  * Output a JSON pair with name name and string value value
281  *
282  */
283 static void add_string(struct json_context *context,
284                        const char* name,
285                        const char* value)
286 {
287         int rc = 0;
288
289         if (context->error) {
290                 return;
291         }
292
293         if (value) {
294                 rc = json_object_set_new(context->root, name, json_string(value));
295         } else {
296                 rc = json_object_set_new(context->root, name, json_null());
297         }
298         if (rc) {
299                 DBG_ERR("Unable to set name [%s] value [%s]\n", name, value);
300                 context->error = true;
301         }
302 }
303
304
305 /*
306  * Output a JSON pair with name name and object value
307  *
308  */
309 static void add_object(struct json_context *context,
310                        const char* name,
311                        struct json_context *value)
312 {
313         int rc = 0;
314
315         if (value->error) {
316                 context->error = true;
317         }
318         if (context->error) {
319                 return;
320         }
321         rc = json_object_set_new(context->root, name, value->root);
322         if (rc) {
323                 DBG_ERR("Unable to add object [%s]\n", name);
324                 context->error = true;
325         }
326 }
327
328 /*
329  * Output a version object
330  *
331  * "version":{"major":1,"minor":0}
332  *
333  */
334 static void add_version( struct json_context *context, int major, int minor)
335 {
336         struct json_context version = get_json_context();
337         add_int(&version, "major", major);
338         add_int(&version, "minor", minor);
339         add_object(context, "version", &version);
340 }
341
342 /*
343  * Output the current date and time as a timestamp in ISO 8601 format
344  *
345  * "timestamp":"2017-03-06T17:18:04.455081+1300"
346  *
347  */
348 static void add_timestamp( struct json_context *context)
349 {
350         char buffer[40];        /* formatted time less usec and timezone */
351         char timestamp[50];     /* the formatted ISO 8601 time stamp     */
352         char tz[10];            /* formatted time zone                   */
353         struct tm* tm_info;     /* current local time                    */
354         struct timeval tv;      /* current system time                   */
355         int r;                  /* response code from gettimeofday       */
356
357         if (context->error) {
358                 return;
359         }
360
361         r = gettimeofday(&tv, NULL);
362         if (r) {
363                 DBG_ERR("Unable to get time of day: (%d) %s\n",
364                         errno,
365                         strerror( errno));
366                 context->error = true;
367                 return;
368         }
369
370         tm_info = localtime(&tv.tv_sec);
371         if (tm_info == NULL) {
372                 DBG_ERR("Unable to determine local time\n");
373                 context->error = true;
374                 return;
375         }
376
377         strftime(buffer, sizeof(buffer)-1, "%Y-%m-%dT%T", tm_info);
378         strftime(tz, sizeof(tz)-1, "%z", tm_info);
379         snprintf(timestamp, sizeof(timestamp),"%s.%06ld%s",
380                  buffer, tv.tv_usec, tz);
381         add_string(context,"timestamp", timestamp);
382 }
383
384
385 /*
386  * Output an address pair, with name name.
387  *
388  * "localAddress":"ipv6::::0"
389  *
390  */
391 static void add_address(struct json_context *context,
392                         const char *name,
393                         const struct tsocket_address *address)
394 {
395         char *s = NULL;
396         TALLOC_CTX *frame = talloc_stackframe();
397
398         if (context->error) {
399                 return;
400         }
401
402         s = tsocket_address_string(address, frame);
403         add_string(context, name, s);
404         talloc_free(frame);
405
406 }
407
408 /*
409  * Output a SID with name name
410  *
411  * "sid":"S-1-5-18"
412  *
413  */
414 static void add_sid(struct json_context *context,
415                     const char *name,
416                     const struct dom_sid *sid)
417 {
418         char sid_buf[DOM_SID_STR_BUFLEN];
419
420         if (context->error) {
421                 return;
422         }
423
424         dom_sid_string_buf(sid, sid_buf, sizeof(sid_buf));
425         add_string(context, name, sid_buf);
426 }
427
428 /*
429  * Write a machine parsable json formatted authentication log entry.
430  *
431  * IF removing or changing the format/meaning of a field please update the
432  *    major version number AUTH_MAJOR
433  *
434  * IF adding a new field please update the minor version number AUTH_MINOR
435  *
436  *  To process the resulting log lines from the commend line use jq to
437  *  parse the json.
438  *
439  *  grep "JSON Authentication" log file |
440  *  sed 's;^[^{]*;;' |
441  * jq -rc  '"\(.timestamp)\t\(.Authentication.status)\t
442  *           \(.Authentication.clientDomain)\t
443  *           \(.Authentication.clientAccount)
444  *           \t\(.Authentication.workstation)
445  *           \t\(.Authentication.remoteAddress)
446  *           \t\(.Authentication.localAddress)"'
447  */
448 static void log_authentication_event_json(
449                         const struct auth_usersupplied_info *ui,
450                         NTSTATUS status,
451                         const char *domain_name,
452                         const char *account_name,
453                         const char *unix_username,
454                         struct dom_sid *sid,
455                         int debug_level)
456 {
457         struct json_context context = get_json_context();
458         struct json_context authentication;
459         char negotiate_flags[11];
460
461         add_timestamp(&context);
462         add_string(&context, "type", AUTH_JSON_TYPE);
463
464         authentication = get_json_context();
465         add_version(&authentication, AUTH_MAJOR, AUTH_MINOR);
466         add_string(&authentication, "status", nt_errstr( status));
467         add_address(&authentication, "localAddress", ui->local_host);
468         add_address(&authentication, "remoteAddress", ui->remote_host);
469         add_string(&authentication,
470                    "serviceDescription",
471                    ui->service_description);
472         add_string(&authentication, "authDescription", ui->auth_description);
473         add_string(&authentication, "clientDomain", ui->client.domain_name);
474         add_string(&authentication, "clientAccount", ui->client.account_name);
475         add_string(&authentication, "workstation", ui->workstation_name);
476         add_string(&authentication, "becameAccount", account_name);
477         add_string(&authentication, "becameDomain", domain_name);
478         add_sid(&authentication, "becameSid", sid);
479         add_string(&authentication, "mappedAccount", ui->mapped.account_name);
480         add_string(&authentication, "mappedDomain", ui->mapped.domain_name);
481         add_string(&authentication,
482                    "netlogonComputer",
483                    ui->netlogon_trust_account.computer_name);
484         add_string(&authentication,
485                    "netlogonTrustAccount",
486                    ui->netlogon_trust_account.account_name);
487         snprintf(negotiate_flags,
488                  sizeof( negotiate_flags),
489                  "0x%08X",
490                  ui->netlogon_trust_account.negotiate_flags);
491         add_string(&authentication, "netlogonNegotiateFlags", negotiate_flags);
492         add_int(&authentication,
493                 "netlogonSecureChannelType",
494                 ui->netlogon_trust_account.secure_channel_type);
495         add_sid(&authentication,
496                 "netlogonTrustAccountSid",
497                 ui->netlogon_trust_account.sid);
498         add_string(&authentication, "passwordType", get_password_type( ui));
499         add_object(&context,AUTH_JSON_TYPE, &authentication);
500
501         log_json(&context, AUTH_JSON_TYPE, DBGC_AUTH_AUDIT, debug_level);
502         free_json_context(&context);
503 }
504
505 /*
506  * Log details of a successful authorization to a service,
507  * in a machine parsable json format
508  *
509  * IF removing or changing the format/meaning of a field please update the
510  *    major version number AUTHZ_MAJOR
511  *
512  * IF adding a new field please update the minor version number AUTHZ_MINOR
513  *
514  *  To process the resulting log lines from the commend line use jq to
515  *  parse the json.
516  *
517  *  grep "JSON Authentication" log_file |\
518  *  sed "s;^[^{]*;;" |\
519  *  jq -rc '"\(.timestamp)\t
520  *           \(.Authorization.domain)\t
521  *           \(.Authorization.account)\t
522  *           \(.Authorization.remoteAddress)"'
523  *
524  */
525 static void log_successful_authz_event_json(
526                                 const struct tsocket_address *remote,
527                                 const struct tsocket_address *local,
528                                 const char *service_description,
529                                 const char *auth_type,
530                                 const char *transport_protection,
531                                 struct auth_session_info *session_info,
532                                 int debug_level)
533 {
534         struct json_context context = get_json_context();
535         struct json_context authorization;
536         char account_flags[11];
537
538         //start_object(&context, NULL);
539         add_timestamp(&context);
540         add_string(&context, "type", AUTHZ_JSON_TYPE);
541         authorization = get_json_context();
542         add_version(&authorization, AUTHZ_MAJOR, AUTHZ_MINOR);
543         add_address(&authorization, "localAddress", local);
544         add_address(&authorization, "remoteAddress", remote);
545         add_string(&authorization, "serviceDescription", service_description);
546         add_string(&authorization, "authType", auth_type);
547         add_string(&authorization, "domain", session_info->info->domain_name);
548         add_string(&authorization, "account", session_info->info->account_name);
549         add_sid(&authorization, "sid", &session_info->security_token->sids[0]);
550         add_string(&authorization,
551                    "logonServer",
552                    session_info->info->logon_server);
553         add_string(&authorization, "transportProtection", transport_protection);
554
555         snprintf(account_flags,
556                  sizeof( account_flags),
557                  "0x%08X",
558                  session_info->info->acct_flags);
559         add_string(&authorization, "accountFlags", account_flags);
560         add_object(&context,AUTHZ_JSON_TYPE, &authorization);
561
562         log_json(&context,
563                  AUTHZ_JSON_TYPE,
564                  DBGC_AUTH_AUDIT,
565                  debug_level);
566         free_json_context(&context);
567 }
568
569 #else
570
571 static void log_authentication_event_json(
572                         const struct auth_usersupplied_info *ui,
573                         NTSTATUS status,
574                         const char *domain_name,
575                         const char *account_name,
576                         const char *unix_username,
577                         struct dom_sid *sid,
578                         int debug_level)
579 {
580         return;
581 }
582
583 static void log_successful_authz_event_json(
584                                 const struct tsocket_address *remote,
585                                 const struct tsocket_address *local,
586                                 const char *service_description,
587                                 const char *auth_type,
588                                 const char *transport_protection,
589                                 struct auth_session_info *session_info,
590                                 int debug_level)
591 {
592         return;
593 }
594
595 #endif
596
597 /*
598  * Determine the type of the password supplied for the
599  * authorisation attempt.
600  *
601  */
602 static const char* get_password_type(const struct auth_usersupplied_info *ui)
603 {
604
605         const char *password_type = NULL;
606
607         if (ui->password_state == AUTH_PASSWORD_RESPONSE &&
608             (ui->logon_parameters & MSV1_0_ALLOW_MSVCHAPV2) &&
609             ui->password.response.nt.length == 24) {
610                 password_type = "MSCHAPv2";
611         } else if ((ui->logon_parameters & MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED)
612                    || (ui->password_state == AUTH_PASSWORD_PLAIN)) {
613                 password_type = "Plaintext";
614         } else if (ui->password_state == AUTH_PASSWORD_HASH) {
615                 password_type = "Supplied-NT-Hash";
616         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
617                    && ui->password.response.nt.length > 24) {
618                 password_type = "NTLMv2";
619         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
620                    && ui->password.response.nt.length == 24) {
621                 password_type = "NTLMv1";
622         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
623                    && ui->password.response.lanman.length == 24) {
624                 password_type = "LANMan";
625         } else if (ui->password_state == AUTH_PASSWORD_RESPONSE
626                    && ui->password.response.nt.length == 0
627                    && ui->password.response.lanman.length == 0) {
628                 password_type = "No-Password";
629         }
630         return password_type;
631 }
632
633 /*
634  * Write a human readable authentication log entry.
635  *
636  */
637 static void log_authentication_event_human_readable(
638                         const struct auth_usersupplied_info *ui,
639                         NTSTATUS status,
640                         const char *domain_name,
641                         const char *account_name,
642                         const char *unix_username,
643                         struct dom_sid *sid,
644                         int debug_level)
645 {
646         TALLOC_CTX *frame = NULL;
647
648         const char *ts = NULL;             /* formatted current time      */
649         char *remote = NULL;               /* formatted remote host       */
650         char *local = NULL;                /* formatted local host        */
651         char *nl = NULL;                   /* NETLOGON details if present */
652         char *trust_computer_name = NULL;
653         char *trust_account_name = NULL;
654         char *logon_line = NULL;
655         const char *password_type = NULL;
656
657         frame = talloc_stackframe();
658
659         password_type = get_password_type( ui);
660         /* Get the current time */
661         ts = get_timestamp(frame);
662
663         /* Only log the NETLOGON details if they are present */
664         if (ui->netlogon_trust_account.computer_name ||
665             ui->netlogon_trust_account.account_name) {
666                 trust_computer_name = log_escape(frame,
667                         ui->netlogon_trust_account.computer_name);
668                 trust_account_name  = log_escape(frame,
669                         ui->netlogon_trust_account.account_name);
670                 nl = talloc_asprintf(frame,
671                         " NETLOGON computer [%s] trust account [%s]",
672                         trust_computer_name, trust_account_name);
673         }
674
675         remote = tsocket_address_string(ui->remote_host, frame);
676         local  = tsocket_address_string(ui->local_host, frame);
677
678         if (NT_STATUS_IS_OK(status)) {
679                 char sid_buf[DOM_SID_STR_BUFLEN];
680
681                 dom_sid_string_buf(sid, sid_buf, sizeof(sid_buf));
682                 logon_line = talloc_asprintf(frame,
683                                              " became [%s]\\[%s] [%s].",
684                                              log_escape(frame, domain_name),
685                                              log_escape(frame, account_name),
686                                              sid_buf);
687         } else {
688                 logon_line = talloc_asprintf(
689                                 frame,
690                                 " mapped to [%s]\\[%s].",
691                                 log_escape(frame, ui->mapped.domain_name),
692                                 log_escape(frame, ui->mapped.account_name));
693         }
694
695         DEBUGC( DBGC_AUTH_AUDIT, debug_level, (
696                 "Auth: [%s,%s] user [%s]\\[%s]"
697                 " at [%s] with [%s] status [%s]"
698                 " workstation [%s] remote host [%s]"
699                 "%s local host [%s]"
700                 " %s\n",
701                 ui->service_description,
702                 ui->auth_description,
703                 log_escape(frame, ui->client.domain_name),
704                 log_escape(frame, ui->client.account_name),
705                 ts,
706                 password_type,
707                 nt_errstr( status),
708                 log_escape(frame, ui->workstation_name),
709                 remote,
710                 logon_line,
711                 local,
712                 nl ? nl : ""
713                 ));
714
715         talloc_free(frame);
716 }
717
718 /*
719  * Log details of an authentication attempt.
720  * Successful and unsuccessful attempts are logged.
721  *
722  * NOTE: msg_ctx and lp_ctx is optional, but when supplied allows streaming the
723  * authentication events over the message bus.
724  */
725 void log_authentication_event( const struct auth_usersupplied_info *ui,
726                               NTSTATUS status,
727                               const char *domain_name,
728                               const char *account_name,
729                               const char *unix_username,
730                               struct dom_sid *sid)
731 {
732         /* set the log level */
733         int debug_level = AUTH_FAILURE_LEVEL;
734
735         if (NT_STATUS_IS_OK(status)) {
736                 debug_level = AUTH_SUCCESS_LEVEL;
737                 if (dom_sid_equal(sid, &global_sid_Anonymous)) {
738                         debug_level = AUTH_ANONYMOUS_LEVEL;
739                 }
740         }
741
742         if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, debug_level)) {
743                 log_authentication_event_human_readable(ui,
744                                                         status,
745                                                         domain_name,
746                                                         account_name,
747                                                         unix_username,
748                                                         sid,
749                                                         debug_level);
750         }
751         if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT_JSON, debug_level)) {
752                 log_authentication_event_json(ui,
753                                               status,
754                                               domain_name,
755                                               account_name,
756                                               unix_username,
757                                               sid,
758                                               debug_level);
759         }
760 }
761
762
763
764 /*
765  * Log details of a successful authorization to a service,
766  * in a human readable format.
767  *
768  */
769 static void log_successful_authz_event_human_readable(
770                                 const struct tsocket_address *remote,
771                                 const struct tsocket_address *local,
772                                 const char *service_description,
773                                 const char *auth_type,
774                                 const char *transport_protection,
775                                 struct auth_session_info *session_info,
776                                 int debug_level)
777 {
778         TALLOC_CTX *frame = NULL;
779
780         const char *ts = NULL;       /* formatted current time      */
781         char *remote_str = NULL;     /* formatted remote host       */
782         char *local_str = NULL;      /* formatted local host        */
783         char sid_buf[DOM_SID_STR_BUFLEN];
784
785         frame = talloc_stackframe();
786
787         /* Get the current time */
788         ts = get_timestamp(frame);
789
790         remote_str = tsocket_address_string(remote, frame);
791         local_str  = tsocket_address_string(local, frame);
792
793         dom_sid_string_buf(&session_info->security_token->sids[0],
794                            sid_buf,
795                            sizeof(sid_buf));
796
797         DEBUGC( DBGC_AUTH_AUDIT, debug_level, (
798                 "Successful AuthZ: [%s,%s] user [%s]\\[%s] [%s]"
799                 " at [%s]"
800                 " Remote host [%s]"
801                 " local host [%s]\n",
802                 service_description,
803                 auth_type,
804                 log_escape(frame, session_info->info->domain_name),
805                 log_escape(frame, session_info->info->account_name),
806                 sid_buf,
807                 ts,
808                 remote_str,
809                 local_str));
810
811         talloc_free(frame);
812 }
813
814 /*
815  * Log details of a successful authorization to a service.
816  *
817  * Only successful authorizations are logged.  For clarity:
818  * - NTLM bad passwords will be recorded by log_authentication_event
819  * - Kerberos decrypt failures need to be logged in gensec_gssapi et al
820  *
821  * The service may later refuse authorization due to an ACL.
822  *
823  * NOTE: msg_ctx and lp_ctx is optional, but when supplied allows streaming the
824  * authentication events over the message bus.
825  */
826 void log_successful_authz_event(const struct tsocket_address *remote,
827                                 const struct tsocket_address *local,
828                                 const char *service_description,
829                                 const char *auth_type,
830                                 const char *transport_protection,
831                                 struct auth_session_info *session_info)
832 {
833         int debug_level = AUTHZ_SUCCESS_LEVEL;
834
835         /* set the log level */
836         if (security_token_is_anonymous(session_info->security_token)) {
837                 debug_level = AUTH_ANONYMOUS_LEVEL;
838         }
839
840         if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, debug_level)) {
841                 log_successful_authz_event_human_readable(remote,
842                                                           local,
843                                                           service_description,
844                                                           auth_type,
845                                                           transport_protection,
846                                                           session_info,
847                                                           debug_level);
848         }
849         if (CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT_JSON, debug_level)) {
850                 log_successful_authz_event_json(remote,
851                                                 local,
852                                                 service_description,
853                                                 auth_type,
854                                                 transport_protection,
855                                                 session_info,
856                                                 debug_level);
857         }
858 }