From: Gary Lockyer Date: Wed, 16 May 2018 20:03:00 +0000 (+1200) Subject: lib audit_logging: re-factor and add functions. X-Git-Tag: tevent-0.9.37~441 X-Git-Url: http://git.samba.org/?p=samba.git;a=commitdiff_plain;h=77e66b86db606ff135c8c76a95c5576feec0fa51 lib audit_logging: re-factor and add functions. Re-factor the common calls to json_dumps DEBUGC and audit_message_send into a separate function. Add functions to retrieve json object and json array elements Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett --- diff --git a/auth/auth_log.c b/auth/auth_log.c index 87daf2f110f..369a5c96162 100644 --- a/auth/auth_log.c +++ b/auth/auth_log.c @@ -82,31 +82,13 @@ static void log_json(struct imessaging_context *msg_ctx, int debug_class, int debug_level) { - char* json = NULL; - - if (object->error) { - return; - } - - json = json_dumps(object->root, 0); - if (json == NULL) { - DBG_ERR("Unable to convert JSON object to string\n"); - object->error = true; - return; - } - - DEBUGC(debug_class, debug_level, ("JSON %s: %s\n", type, json)); + audit_log_json(type, object, debug_class, debug_level); if (msg_ctx && lp_ctx && lpcfg_auth_event_notification(lp_ctx)) { audit_message_send(msg_ctx, AUTH_EVENT_NAME, MSG_AUTH_LOG, - json); - } - - if (json) { - free(json); + object); } - } /* diff --git a/lib/audit_logging/audit_logging.c b/lib/audit_logging/audit_logging.c index 5c16806d54e..1f82d576c84 100644 --- a/lib/audit_logging/audit_logging.c +++ b/lib/audit_logging/audit_logging.c @@ -102,9 +102,46 @@ char* audit_get_timestamp(TALLOC_CTX *frame) return ts; } -#ifdef HAVE_JANSSON +/* + * @brief write an audit message to the audit logs. + * + * Write a human readable text audit message to the samba logs. + * + * @param prefix Text to be printed at the start of the log line + * @param message The content of the log line. + * @param debub_class The debug class to log the message with. + * @param debug_level The debug level to log the message with. + */ +void audit_log_human_text(const char* prefix, + const char* message, + int debug_class, + int debug_level) +{ + DEBUGC(debug_class, debug_level, ("%s %s\n", prefix, message)); +} -#include "system/time.h" +#ifdef HAVE_JANSSON +/* + * @brief write a json object to the samba audit logs. + * + * Write the json object to the audit logs as a formatted string + * + * @param prefix Text to be printed at the start of the log line + * @param message The content of the log line. + * @param debub_class The debug class to log the message with. + * @param debug_level The debug level to log the message with. + */ +void audit_log_json( + const char* prefix, + struct json_object* message, + int debug_class, + int debug_level) +{ + TALLOC_CTX *ctx = talloc_new(NULL); + char *s = json_to_string(ctx, message); + DEBUGC(debug_class, debug_level, ("JSON %s: %s\n", prefix, s)); + TALLOC_FREE(ctx); +} /* * @brief get a connection to the messaging event server. @@ -192,14 +229,18 @@ void audit_message_send( struct imessaging_context *msg_ctx, const char *server_name, uint32_t message_type, - const char *message) + struct json_object *message) { struct server_id event_server; NTSTATUS status; - DATA_BLOB message_blob = data_blob_string_const(message); + + const char *message_string = NULL; + DATA_BLOB message_blob = data_blob_null; + TALLOC_CTX *ctx = talloc_new(NULL); if (msg_ctx == NULL) { DBG_DEBUG("No messaging context\n"); + TALLOC_FREE(ctx); return; } @@ -213,9 +254,12 @@ void audit_message_send( DBG_ERR("get_event_server for %s returned (%s)\n", server_name, nt_errstr(status)); + TALLOC_FREE(ctx); return; } + message_string = json_to_string(ctx, message); + message_blob = data_blob_string_const(message_string); status = imessaging_send( msg_ctx, event_server, @@ -232,6 +276,7 @@ void audit_message_send( DBG_ERR("get_event_server for %s returned (%s)\n", server_name, nt_errstr(status)); + TALLOC_FREE(ctx); return; } imessaging_send( @@ -240,6 +285,7 @@ void audit_message_send( message_type, &message_blob); } + TALLOC_FREE(ctx); } /* @@ -768,4 +814,64 @@ char *json_to_string(TALLOC_CTX *mem_ctx, struct json_object *object) return json_string; } + +/* + * @brief get a json array named "name" from the json object. + * + * Get the array attribute named name, creating it if it does not exist. + * + * @param object the json object. + * @param name the name of the array attribute + * + * @return The array object, will be created if it did not exist. + */ +struct json_object json_get_array(struct json_object *object, const char* name) +{ + + struct json_object array = json_new_array(); + json_t *a = NULL; + + if (object->error) { + array.error = true; + return array; + } + + a = json_object_get(object->root, name); + if (a == NULL) { + return array; + } + json_array_extend(array.root, a); + + return array; +} + +/* + * @brief get a json object named "name" from the json object. + * + * Get the object attribute named name, creating it if it does not exist. + * + * @param object the json object. + * @param name the name of the object attribute + * + * @return The object, will be created if it did not exist. + */ +struct json_object json_get_object(struct json_object *object, const char* name) +{ + + struct json_object o = json_new_object(); + json_t *v = NULL; + + if (object->error) { + o.error = true; + return o; + } + + v = json_object_get(object->root, name); + if (v == NULL) { + return o; + } + json_object_update(o.root, v); + + return o; +} #endif diff --git a/lib/audit_logging/audit_logging.h b/lib/audit_logging/audit_logging.h index 763f3ed5d9c..152b22ee916 100644 --- a/lib/audit_logging/audit_logging.h +++ b/lib/audit_logging/audit_logging.h @@ -21,14 +21,12 @@ #include "lib/messaging/irpc.h" #include "lib/tsocket/tsocket.h" -char* audit_get_timestamp( - TALLOC_CTX *frame); +char* audit_get_timestamp(TALLOC_CTX *frame); +void audit_log_human_text(const char *prefix, + const char *message, + int debug_class, + int debug_level); -void audit_message_send( - struct imessaging_context *msg_ctx, - const char *server_name, - uint32_t message_type, - const char *message); #ifdef HAVE_JANSSON #include /* @@ -40,6 +38,14 @@ struct json_object { bool error; }; +void audit_log_json(const char *prefix, + struct json_object *message, + int debug_class, + int debug_level); +void audit_message_send(struct imessaging_context *msg_ctx, + const char *server_name, + uint32_t message_type, + struct json_object *message); struct json_object json_new_object(void); struct json_object json_new_array(void); void json_free(struct json_object *object); @@ -85,5 +91,9 @@ void json_add_guid( const char *name, const struct GUID *guid); +struct json_object json_get_array(struct json_object *object, + const char* name); +struct json_object json_get_object(struct json_object *object, + const char* name); char *json_to_string(TALLOC_CTX *mem_ctx, struct json_object *object); #endif diff --git a/lib/audit_logging/tests/audit_logging_test.c b/lib/audit_logging/tests/audit_logging_test.c index 8385e9ce363..56e8fbcd43e 100644 --- a/lib/audit_logging/tests/audit_logging_test.c +++ b/lib/audit_logging/tests/audit_logging_test.c @@ -492,6 +492,141 @@ static void test_json_to_string(void **state) } #endif +static void test_json_get_array(void **state) +{ + struct json_object object; + struct json_object array; + struct json_object stored_array = json_new_array(); + json_t *value = NULL; + json_t *o = NULL; + struct json_object o1; + struct json_object o2; + + object = json_new_object(); + + array = json_get_array(&object, "not-there"); + assert_false(array.error); + assert_non_null(array.root); + assert_true(json_is_array(array.root)); + json_free(&array); + + o1 = json_new_object(); + json_add_string(&o1, "value", "value-one"); + json_add_object(&stored_array, NULL, &o1); + json_add_object(&object, "stored_array", &stored_array); + + array = json_get_array(&object, "stored_array"); + assert_false(array.error); + assert_non_null(array.root); + assert_true(json_is_array(array.root)); + + assert_int_equal(1, json_array_size(array.root)); + + o = json_array_get(array.root, 0); + assert_non_null(o); + assert_true(json_is_object(o)); + + value = json_object_get(o, "value"); + assert_non_null(value); + assert_true(json_is_string(value)); + + assert_string_equal("value-one", json_string_value(value)); + json_free(&array); + + /* + * Now update the array and add it back to the object + */ + array = json_get_array(&object, "stored_array"); + assert_true(json_is_array(array.root)); + o2 = json_new_object(); + json_add_string(&o2, "value", "value-two"); + assert_false(o2.error); + json_add_object(&array, NULL, &o2); + assert_true(json_is_array(array.root)); + json_add_object(&object, "stored_array", &array); + assert_true(json_is_array(array.root)); + + array = json_get_array(&object, "stored_array"); + assert_non_null(array.root); + assert_true(json_is_array(array.root)); + assert_false(array.error); + assert_true(json_is_array(array.root)); + + assert_int_equal(2, json_array_size(array.root)); + + o = json_array_get(array.root, 0); + assert_non_null(o); + assert_true(json_is_object(o)); + + assert_non_null(value); + assert_true(json_is_string(value)); + + assert_string_equal("value-one", json_string_value(value)); + + o = json_array_get(array.root, 1); + assert_non_null(o); + assert_true(json_is_object(o)); + + value = json_object_get(o, "value"); + assert_non_null(value); + assert_true(json_is_string(value)); + + assert_string_equal("value-two", json_string_value(value)); + + json_free(&array); + json_free(&object); +} + +static void test_json_get_object(void **state) +{ + struct json_object object; + struct json_object o1; + struct json_object o2; + struct json_object o3; + json_t *value = NULL; + + object = json_new_object(); + + o1 = json_get_object(&object, "not-there"); + assert_false(o1.error); + assert_non_null(o1.root); + assert_true(json_is_object(o1.root)); + json_free(&o1); + + o1 = json_new_object(); + json_add_string(&o1, "value", "value-one"); + json_add_object(&object, "stored_object", &o1); + + o2 = json_get_object(&object, "stored_object"); + assert_false(o2.error); + assert_non_null(o2.root); + assert_true(json_is_object(o2.root)); + + value = json_object_get(o2.root, "value"); + assert_non_null(value); + assert_true(json_is_string(value)); + + assert_string_equal("value-one", json_string_value(value)); + + json_add_string(&o2, "value", "value-two"); + json_add_object(&object, "stored_object", &o2); + + + o3 = json_get_object(&object, "stored_object"); + assert_false(o3.error); + assert_non_null(o3.root); + assert_true(json_is_object(o3.root)); + + value = json_object_get(o3.root, "value"); + assert_non_null(value); + assert_true(json_is_string(value)); + + assert_string_equal("value-two", json_string_value(value)); + + json_free(&o3); + json_free(&object); +} + static void test_audit_get_timestamp(void **state) { const char *t = NULL; @@ -549,6 +684,8 @@ int main(int argc, const char **argv) cmocka_unit_test(test_json_add_sid), cmocka_unit_test(test_json_add_guid), cmocka_unit_test(test_json_to_string), + cmocka_unit_test(test_json_get_array), + cmocka_unit_test(test_json_get_object), #endif cmocka_unit_test(test_audit_get_timestamp), };