lib: Fix array size in audit_logging
[samba.git] / lib / audit_logging / audit_logging.c
1 /*
2    common routines for audit logging
3
4    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2018
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /*
21  * Error handling:
22  *
23  * The json_object structure contains a boolean 'error'.  This is set whenever
24  * an error is detected. All the library functions check this flag and return
25  * immediately if it is set.
26  *
27  *      if (object->error) {
28  *              return;
29  *      }
30  *
31  * This allows the operations to be sequenced naturally with out the clutter
32  * of error status checks.
33  *
34  *      audit = json_new_object();
35  *      json_add_version(&audit, OPERATION_MAJOR, OPERATION_MINOR);
36  *      json_add_int(&audit, "statusCode", ret);
37  *      json_add_string(&audit, "status", ldb_strerror(ret));
38  *      json_add_string(&audit, "operation", operation);
39  *      json_add_address(&audit, "remoteAddress", remote);
40  *      json_add_sid(&audit, "userSid", sid);
41  *      json_add_string(&audit, "dn", dn);
42  *      json_add_guid(&audit, "transactionId", &ac->transaction_guid);
43  *      json_add_guid(&audit, "sessionId", unique_session_token);
44  *
45  * The assumptions are that errors will be rare, and that the audit logging
46  * code should not cause failures. So errors are logged but processing
47  * continues on a best effort basis.
48  */
49
50 #include "includes.h"
51
52 #include "librpc/ndr/libndr.h"
53 #include "lib/tsocket/tsocket.h"
54 #include "libcli/security/dom_sid.h"
55 #include "lib/messaging/messaging.h"
56 #include "auth/common_auth.h"
57 #include "audit_logging.h"
58
59 /*
60  * @brief Get a human readable timestamp.
61  *
62  * Returns the current time formatted as
63  *  "Tue, 14 Mar 2017 08:38:42.209028 NZDT"
64  *
65  * The returned string is allocated by talloc in the supplied context.
66  * It is the callers responsibility to free it.
67  *
68  * @param mem_ctx talloc memory context that owns the returned string.
69  *
70  * @return a human readable time stamp.
71  *
72  */
73 char* audit_get_timestamp(TALLOC_CTX *frame)
74 {
75         char buffer[40];        /* formatted time less usec and timezone */
76         char tz[10];            /* formatted time zone                   */
77         struct tm* tm_info;     /* current local time                    */
78         struct timeval tv;      /* current system time                   */
79         int r;                  /* response code from gettimeofday       */
80         char * ts;              /* formatted time stamp                  */
81
82         r = gettimeofday(&tv, NULL);
83         if (r) {
84                 DBG_ERR("Unable to get time of day: (%d) %s\n",
85                         errno,
86                         strerror(errno));
87                 return NULL;
88         }
89
90         tm_info = localtime(&tv.tv_sec);
91         if (tm_info == NULL) {
92                 DBG_ERR("Unable to determine local time\n");
93                 return NULL;
94         }
95
96         strftime(buffer, sizeof(buffer)-1, "%a, %d %b %Y %H:%M:%S", tm_info);
97         strftime(tz, sizeof(tz)-1, "%Z", tm_info);
98         ts = talloc_asprintf(frame, "%s.%06ld %s", buffer, tv.tv_usec, tz);
99         if (ts == NULL) {
100                 DBG_ERR("Out of memory formatting time stamp\n");
101         }
102         return ts;
103 }
104
105 #ifdef HAVE_JANSSON
106
107 #include "system/time.h"
108
109 /*
110  * @brief get a connection to the messaging event server.
111  *
112  * Get a connection to the messaging event server registered by server_name.
113  *
114  * @param msg_ctx a valid imessaging_context.
115  * @param server_name name of messaging event server to connect to.
116  * @param server_id The event server details to populate
117  *
118  * @return NTSTATUS
119  */
120 static NTSTATUS get_event_server(
121         struct imessaging_context *msg_ctx,
122         const char *server_name,
123         struct server_id *event_server)
124 {
125         NTSTATUS status;
126         TALLOC_CTX *frame = talloc_stackframe();
127         unsigned num_servers, i;
128         struct server_id *servers;
129
130         status = irpc_servers_byname(
131                 msg_ctx,
132                 frame,
133                 server_name,
134                 &num_servers,
135                 &servers);
136
137         if (!NT_STATUS_IS_OK(status)) {
138                 DBG_NOTICE(
139                         "Failed to find '%s' registered on the message bus to "
140                         "send audit events to: %s\n",
141                         server_name,
142                         nt_errstr(status));
143                 TALLOC_FREE(frame);
144                 return status;
145         }
146
147         /*
148          * Select the first server that is listening, because we get
149          * connection refused as NT_STATUS_OBJECT_NAME_NOT_FOUND
150          * without waiting
151          */
152         for (i = 0; i < num_servers; i++) {
153                 status = imessaging_send(
154                         msg_ctx,
155                         servers[i],
156                         MSG_PING,
157                         &data_blob_null);
158                 if (NT_STATUS_IS_OK(status)) {
159                         *event_server = servers[i];
160                         TALLOC_FREE(frame);
161                         return NT_STATUS_OK;
162                 }
163         }
164         DBG_NOTICE(
165                 "Failed to find '%s' registered on the message bus to "
166                 "send audit events to: %s\n",
167                 server_name,
168                 nt_errstr(status));
169         TALLOC_FREE(frame);
170         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
171 }
172
173 /*
174  * @brief send an audit message to a messaging event server.
175  *
176  * Send the message to a registered and listening event server.
177  * Note: Any errors are logged, and the message is not sent.  This is to ensure
178  *       that a poorly behaved event server does not impact Samba.
179  *
180  *       As it is possible to lose messages, especially during server
181  *       shut down, currently this function is primarily intended for use
182  *       in integration tests.
183  *
184  * @param msg_ctx an imessaging_context, can be NULL in which case no message
185  *                will be sent.
186  * @param server_name the naname of the event server to send the message to.
187  * @param messag_type A message type defined in librpc/idl/messaging.idl
188  * @param message The message to send.
189  *
190  */
191 void audit_message_send(
192         struct imessaging_context *msg_ctx,
193         const char *server_name,
194         uint32_t message_type,
195         const char *message)
196 {
197         struct server_id event_server;
198         NTSTATUS status;
199         DATA_BLOB message_blob = data_blob_string_const(message);
200
201         if (msg_ctx == NULL) {
202                 DBG_DEBUG("No messaging context\n");
203                 return;
204         }
205
206         /* Need to refetch the address each time as the destination server may
207          * have disconnected and reconnected in the interim, in which case
208          * messages may get lost
209          */
210         status = get_event_server(msg_ctx, server_name, &event_server);
211         if (!NT_STATUS_IS_OK(status) &&
212             !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
213                 DBG_ERR("get_event_server for %s returned (%s)\n",
214                         server_name,
215                         nt_errstr(status));
216                 return;
217         }
218
219         status = imessaging_send(
220                 msg_ctx,
221                 event_server,
222                 message_type,
223                 &message_blob);
224
225         /*
226          * If the server crashed, try to find it again
227          */
228         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
229                 status = get_event_server(msg_ctx, server_name, &event_server);
230                 if (!NT_STATUS_IS_OK(status) &&
231                     !NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
232                         DBG_ERR("get_event_server for %s returned (%s)\n",
233                                 server_name,
234                                 nt_errstr(status));
235                         return;
236                 }
237                 imessaging_send(
238                         msg_ctx,
239                         event_server,
240                         message_type,
241                         &message_blob);
242         }
243 }
244
245 /*
246  * @brief Create a new struct json_object, wrapping a JSON Object.
247  *
248  * Create a new json object, the json_object wraps the underlying json
249  * implementations JSON Object representation.
250  *
251  * Free with a call to json_free_object, note that the jansson inplementation
252  * allocates memory with malloc and not talloc.
253  *
254  * @return a struct json_object, error will be set to true if the object
255  *         could not be created.
256  *
257  */
258 struct json_object json_new_object(void) {
259
260         struct json_object object;
261         object.error = false;
262
263         object.root = json_object();
264         if (object.root == NULL) {
265                 object.error = true;
266                 DBG_ERR("Unable to create json_object\n");
267         }
268         return object;
269 }
270
271 /*
272  * @brief Create a new struct json_object wrapping a JSON Array.
273  *
274  * Create a new json object, the json_object wraps the underlying json
275  * implementations JSON Array representation.
276  *
277  * Free with a call to json_free_object, note that the jansson inplementation
278  * allocates memory with malloc and not talloc.
279  *
280  * @return a struct json_object, error will be set to true if the array
281  *         could not be created.
282  *
283  */
284 struct json_object json_new_array(void) {
285
286         struct json_object array;
287         array.error = false;
288
289         array.root = json_array();
290         if (array.root == NULL) {
291                 array.error = true;
292                 DBG_ERR("Unable to create json_array\n");
293         }
294         return array;
295 }
296
297
298 /*
299  * @brief free and invalidate a previously created JSON object.
300  *
301  * Release any resources owned by a json_object, and then mark the structure
302  * as invalid.  It is safe to call this multiple times on an object.
303  *
304  */
305 void json_free(struct json_object *object)
306 {
307         if (object->root != NULL) {
308                 json_decref(object->root);
309         }
310         object->root = NULL;
311         object->error = true;
312 }
313
314 /*
315  * @brief is the current JSON object invalid?
316  *
317  * Check the state of the object to determine if it is invalid.
318  *
319  * @return is the object valid?
320  *
321  */
322 bool json_is_invalid(struct json_object *object)
323 {
324         return object->error;
325 }
326
327 /*
328  * @brief Add an integer value to a JSON object.
329  *
330  * Add an integer value named 'name' to the json object.
331  * In the event of an error object will be invalidated.
332  *
333  * @param object the JSON object to be updated.
334  * @param name the name of the value.
335  * @param value the value.
336  *
337  */
338 void json_add_int(struct json_object *object,
339                   const char* name,
340                   const int value)
341 {
342         int rc = 0;
343
344         if (object->error) {
345                 return;
346         }
347
348         rc = json_object_set_new(object->root, name, json_integer(value));
349         if (rc) {
350                 DBG_ERR("Unable to set name [%s] value [%d]\n", name, value);
351                 object->error = true;
352         }
353 }
354
355 /*
356  * @brief Add a boolean value to a JSON object.
357  *
358  * Add a boolean value named 'name' to the json object.
359  * In the event of an error object will be invalidated.
360  *
361  * @param object the JSON object to be updated.
362  * @param name the name.
363  * @param value the value.
364  *
365  */
366 void json_add_bool(struct json_object *object,
367                    const char* name,
368                    const bool value)
369 {
370         int rc = 0;
371
372         if (object->error) {
373                 return;
374         }
375
376         rc = json_object_set_new(object->root, name, json_boolean(value));
377         if (rc) {
378                 DBG_ERR("Unable to set name [%s] value [%d]\n", name, value);
379                 object->error = true;
380         }
381
382 }
383
384 /*
385  * @brief Add a string value to a JSON object.
386  *
387  * Add a string value named 'name' to the json object.
388  * In the event of an error object will be invalidated.
389  *
390  * @param object the JSON object to be updated.
391  * @param name the name.
392  * @param value the value.
393  *
394  */
395 void json_add_string(struct json_object *object,
396                      const char* name,
397                      const char* value)
398 {
399         int rc = 0;
400
401         if (object->error) {
402                 return;
403         }
404
405         if (value) {
406                 rc = json_object_set_new(
407                         object->root,
408                         name,
409                         json_string(value));
410         } else {
411                 rc = json_object_set_new(object->root, name, json_null());
412         }
413         if (rc) {
414                 DBG_ERR("Unable to set name [%s] value [%s]\n", name, value);
415                 object->error = true;
416         }
417 }
418
419 /*
420  * @brief Assert that the current JSON object is an array.
421  *
422  * Check that the current object is a JSON array, and if not
423  * invalidate the object. We also log an error message as this indicates
424  * bug in the calling code.
425  *
426  * @param object the JSON object to be validated.
427  */
428 void json_assert_is_array(struct json_object *array) {
429
430         if (array->error) {
431                 return;
432         }
433
434         if (json_is_array(array->root) == false) {
435                 DBG_ERR("JSON object is not an array\n");
436                 array->error = true;
437                 return;
438         }
439 }
440
441 /*
442  * @brief Add a JSON object to a JSON object.
443  *
444  * Add a JSON object named 'name' to the json object.
445  * In the event of an error object will be invalidated.
446  *
447  * @param object the JSON object to be updated.
448  * @param name the name.
449  * @param value the value.
450  *
451  */
452 void json_add_object(struct json_object *object,
453                 const char* name,
454                 struct json_object *value)
455 {
456         int rc = 0;
457         json_t *jv = NULL;
458
459         if (object->error) {
460                 return;
461         }
462
463         if (value != NULL && value->error) {
464                 object->error = true;
465                 return;
466         }
467
468         jv = value == NULL ? json_null() : value->root;
469
470         if (json_is_array(object->root)) {
471                 rc = json_array_append_new(object->root, jv);
472         } else if (json_is_object(object->root)) {
473                 rc = json_object_set_new(object->root, name,  jv);
474         } else {
475                 DBG_ERR("Invalid JSON object type\n");
476                 object->error = true;
477         }
478         if (rc) {
479                 DBG_ERR("Unable to add object [%s]\n", name);
480                 object->error = true;
481         }
482 }
483
484 /*
485  * @brief Add a string to a JSON object, truncating if necessary.
486  *
487  *
488  * Add a string value named 'name' to the json object, the string will be
489  * truncated if it is more than len characters long. If len is 0 the value
490  * is encoded as a JSON null.
491  *
492  * In the event of an error object will be invalidated.
493  *
494  * @param object the JSON object to be updated.
495  * @param name the name.
496  * @param value the value.
497  * @param len the maximum number of characters to be copied.
498  *
499  */
500 void json_add_stringn(
501         struct json_object *object,
502         const char *name,
503         const char *value,
504         const size_t len)
505 {
506
507         int rc = 0;
508         if (object->error) {
509                 return;
510         }
511
512         if (value != NULL && len > 0) {
513                 char buffer[len+1];
514                 strncpy(buffer, value, len);
515                 buffer[len] = '\0';
516                 rc = json_object_set_new(object->root,
517                                          name,
518                                          json_string(buffer));
519         } else {
520                 rc = json_object_set_new(object->root, name, json_null());
521         }
522         if (rc) {
523                 DBG_ERR("Unable to set name [%s] value [%s]\n", name, value);
524                 object->error = true;
525         }
526 }
527
528 /*
529  * @brief Add a version object to a JSON object
530  *
531  * Add a version object to the JSON object
532  *      "version":{"major":1, "minor":0}
533  *
534  * The version tag is intended to aid the processing of the JSON messages
535  * The major version number should change when an attribute is:
536  *  - renamed
537  *  - removed
538  *  - its meaning changes
539  *  - its contents change format
540  * The minor version should change whenever a new attribute is added and for
541  * minor bug fixes to an attributes content.
542  *
543  * In the event of an error object will be invalidated.
544  *
545  * @param object the JSON object to be updated.
546  * @param major the major version number
547  * @param minor the minor version number
548  */
549 void json_add_version(struct json_object *object, int major, int minor)
550 {
551         struct json_object version = json_new_object();
552         json_add_int(&version, "major", major);
553         json_add_int(&version, "minor", minor);
554         json_add_object(object, "version", &version);
555 }
556
557 /*
558  * @brief add an ISO 8601 timestamp to the object.
559  *
560  * Add the current date and time as a timestamp in ISO 8601 format
561  * to a JSON object
562  *
563  * "timestamp":"2017-03-06T17:18:04.455081+1300"
564  *
565  * In the event of an error object will be invalidated.
566  *
567  * @param object the JSON object to be updated.
568  */
569 void json_add_timestamp(struct json_object *object)
570 {
571         char buffer[40];        /* formatted time less usec and timezone */
572         char timestamp[65];     /* the formatted ISO 8601 time stamp     */
573         char tz[10];            /* formatted time zone                   */
574         struct tm* tm_info;     /* current local time                    */
575         struct timeval tv;      /* current system time                   */
576         int r;                  /* response code from gettimeofday       */
577
578         if (object->error) {
579                 return;
580         }
581
582         r = gettimeofday(&tv, NULL);
583         if (r) {
584                 DBG_ERR("Unable to get time of day: (%d) %s\n",
585                         errno,
586                         strerror(errno));
587                 object->error = true;
588                 return;
589         }
590
591         tm_info = localtime(&tv.tv_sec);
592         if (tm_info == NULL) {
593                 DBG_ERR("Unable to determine local time\n");
594                 object->error = true;
595                 return;
596         }
597
598         strftime(buffer, sizeof(buffer)-1, "%Y-%m-%dT%T", tm_info);
599         strftime(tz, sizeof(tz)-1, "%z", tm_info);
600         snprintf(
601                 timestamp,
602                 sizeof(timestamp),
603                 "%s.%06ld%s",
604                 buffer,
605                 tv.tv_usec,
606                 tz);
607         json_add_string(object, "timestamp", timestamp);
608 }
609
610
611 /*
612  *@brief Add a tsocket_address to a JSON object
613  *
614  * Add the string representation of a Samba tsocket_address to the object.
615  *
616  * "localAddress":"ipv6::::0"
617  *
618  * In the event of an error object will be invalidated.
619  *
620  * @param object the JSON object to be updated.
621  * @param name the name.
622  * @param address the tsocket_address.
623  *
624  */
625 void json_add_address(
626         struct json_object *object,
627         const char *name,
628         const struct tsocket_address *address)
629 {
630
631         if (object->error) {
632                 return;
633         }
634         if (address == NULL) {
635                 int rc = json_object_set_new(object->root, name, json_null());
636                 if (rc) {
637                         DBG_ERR("Unable to set address [%s] to null\n", name);
638                         object->error = true;
639                 }
640         } else {
641                 TALLOC_CTX *ctx = talloc_new(NULL);
642                 char *s = NULL;
643
644                 s = tsocket_address_string(address, ctx);
645                 json_add_string(object, name, s);
646                 TALLOC_FREE(ctx);
647         }
648 }
649
650 /*
651  * @brief Add a formatted string representation of a sid to a json object.
652  *
653  * Add the string representation of a Samba sid to the object.
654  *
655  * "sid":"S-1-5-18"
656  *
657  * In the event of an error object will be invalidated.
658  *
659  * @param object the JSON object to be updated.
660  * @param name the name.
661  * @param sid the sid
662  *
663  */
664 void json_add_sid(
665         struct json_object *object,
666         const char *name,
667         const struct dom_sid *sid)
668 {
669
670         if (object->error) {
671                 return;
672         }
673         if (sid == NULL) {
674                 int rc = json_object_set_new(object->root, name, json_null());
675                 if (rc) {
676                         DBG_ERR("Unable to set SID [%s] to null\n", name);
677                         object->error = true;
678                 }
679         } else {
680                 char sid_buf[DOM_SID_STR_BUFLEN];
681
682                 dom_sid_string_buf(sid, sid_buf, sizeof(sid_buf));
683                 json_add_string(object, name, sid_buf);
684         }
685 }
686
687 /*
688  * @brief Add a formatted string representation of a guid to a json object.
689  *
690  * Add the string representation of a Samba GUID to the object.
691  *
692  * "guid":"1fb9f2ee-2a4d-4bf8-af8b-cb9d4529a9ab"
693  *
694  * In the event of an error object will be invalidated.
695  *
696  * @param object the JSON object to be updated.
697  * @param name the name.
698  * @param guid the guid.
699  *
700  *
701  */
702 void json_add_guid(
703         struct json_object *object,
704         const char *name,
705         const struct GUID *guid)
706 {
707
708
709         if (object->error) {
710                 return;
711         }
712         if (guid == NULL) {
713                 int rc = json_object_set_new(object->root, name, json_null());
714                 if (rc) {
715                         DBG_ERR("Unable to set GUID [%s] to null\n", name);
716                         object->error = true;
717                 }
718         } else {
719                 char *guid_str;
720                 struct GUID_txt_buf guid_buff;
721
722                 guid_str = GUID_buf_string(guid, &guid_buff);
723                 json_add_string(object, name, guid_str);
724         }
725 }
726
727
728 /*
729  * @brief Convert a JSON object into a string
730  *
731  * Convert the jsom object into a string suitable for printing on a log line,
732  * i.e. with no embedded line breaks.
733  *
734  * If the object is invalid it returns NULL.
735  *
736  * @param mem_ctx the talloc memory context owning the returned string
737  * @param object the json object.
738  *
739  * @return A string representation of the object or NULL if the object
740  *         is invalid.
741  */
742 char *json_to_string(TALLOC_CTX *mem_ctx, struct json_object *object)
743 {
744         char *json = NULL;
745         char *json_string = NULL;
746
747         if (object->error) {
748                 return NULL;
749         }
750
751         /*
752          * json_dumps uses malloc, so need to call free(json) to release
753          * the memory
754          */
755         json = json_dumps(object->root, 0);
756         if (json == NULL) {
757                 DBG_ERR("Unable to convert JSON object to string\n");
758                 return NULL;
759         }
760
761         json_string = talloc_strdup(mem_ctx, json);
762         if (json_string == NULL) {
763                 free(json);
764                 DBG_ERR("Unable to copy JSON object string to talloc string\n");
765                 return NULL;
766         }
767         free(json);
768
769         return json_string;
770 }
771 #endif