diff options
author | Gary Lockyer <gary@catalyst.net.nz> | 2018-07-13 09:14:09 +1200 |
---|---|---|
committer | Gary Lockyer <gary@samba.org> | 2018-07-25 06:29:50 +0200 |
commit | 79f494e51eabb5176747fcf3b9f2efad10ec7f97 (patch) | |
tree | e0b6cfa42845fa9af5c19113f540f40d1291ae5b /lib/audit_logging | |
parent | e2ebfd8e082fef59791947a24d61bfc50eec8596 (diff) | |
download | samba-79f494e51eabb5176747fcf3b9f2efad10ec7f97.tar.gz |
json: Modify API to use return codes
Modify the auditing JSON API to return a response code, as the consensus
was that the existing error handling was aesthetically displeasing.
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
Reviewed-by: Jeremy Allison <jra@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'lib/audit_logging')
-rw-r--r-- | lib/audit_logging/audit_logging.c | 527 | ||||
-rw-r--r-- | lib/audit_logging/audit_logging.h | 61 | ||||
-rw-r--r-- | lib/audit_logging/tests/audit_logging_test.c | 252 |
3 files changed, 573 insertions, 267 deletions
diff --git a/lib/audit_logging/audit_logging.c b/lib/audit_logging/audit_logging.c index f94f2c2a839..ac08863129a 100644 --- a/lib/audit_logging/audit_logging.c +++ b/lib/audit_logging/audit_logging.c @@ -20,31 +20,6 @@ /* * Error handling: * - * The json_object structure contains a boolean 'error'. This is set whenever - * an error is detected. All the library functions check this flag and return - * immediately if it is set. - * - * if (object->error) { - * return; - * } - * - * This allows the operations to be sequenced naturally with out the clutter - * of error status checks. - * - * audit = json_new_object(); - * json_add_version(&audit, OPERATION_MAJOR, OPERATION_MINOR); - * json_add_int(&audit, "statusCode", ret); - * json_add_string(&audit, "status", ldb_strerror(ret)); - * json_add_string(&audit, "operation", operation); - * json_add_address(&audit, "remoteAddress", remote); - * json_add_sid(&audit, "userSid", sid); - * json_add_string(&audit, "dn", dn); - * json_add_guid(&audit, "transactionId", &ac->transaction_guid); - * json_add_guid(&audit, "sessionId", unique_session_token); - * - * The assumptions are that errors will be rare, and that the audit logging - * code should not cause failures. So errors are logged but processing - * continues on a best effort basis. */ #include "includes.h" @@ -67,7 +42,7 @@ * * @param mem_ctx talloc memory context that owns the returned string. * - * @return a human readable time stamp. + * @return a human readable time stamp, or NULL in the event of an error. * */ char* audit_get_timestamp(TALLOC_CTX *frame) @@ -76,11 +51,11 @@ char* audit_get_timestamp(TALLOC_CTX *frame) char tz[10]; /* formatted time zone */ struct tm* tm_info; /* current local time */ struct timeval tv; /* current system time */ - int r; /* response code from gettimeofday */ + int ret; /* response code */ char * ts; /* formatted time stamp */ - r = gettimeofday(&tv, NULL); - if (r) { + ret = gettimeofday(&tv, NULL); + if (ret != 0) { DBG_ERR("Unable to get time of day: (%d) %s\n", errno, strerror(errno)); @@ -122,6 +97,10 @@ void audit_log_human_text(const char* prefix, #ifdef HAVE_JANSSON /* + * Constant for empty json object initialisation + */ +const struct json_object json_empty_object = {.valid = false, .root = NULL}; +/* * @brief write a json object to the samba audit logs. * * Write the json object to the audit logs as a formatted string @@ -136,8 +115,23 @@ void audit_log_json(const char* prefix, int debug_class, int debug_level) { - TALLOC_CTX *ctx = talloc_new(NULL); - char *s = json_to_string(ctx, message); + TALLOC_CTX *ctx = NULL; + char *s = NULL; + + if (json_is_invalid(message)) { + DBG_ERR("Invalid JSON object, unable to log\n"); + return; + } + + ctx = talloc_new(NULL); + s = json_to_string(ctx, message); + if (s == NULL) { + DBG_ERR("json_to_string for (%s) returned NULL, " + "JSON audit message could not written\n", + prefix); + TALLOC_FREE(ctx); + return; + } DEBUGC(debug_class, debug_level, ("JSON %s: %s\n", prefix, s)); TALLOC_FREE(ctx); } @@ -235,11 +229,14 @@ void audit_message_send( const char *message_string = NULL; DATA_BLOB message_blob = data_blob_null; - TALLOC_CTX *ctx = talloc_new(NULL); + TALLOC_CTX *ctx = NULL; + if (json_is_invalid(message)) { + DBG_ERR("Invalid JSON object, unable to send\n"); + return; + } if (msg_ctx == NULL) { DBG_DEBUG("No messaging context\n"); - TALLOC_FREE(ctx); return; } @@ -288,20 +285,21 @@ void audit_message_send( * Free with a call to json_free_object, note that the jansson inplementation * allocates memory with malloc and not talloc. * - * @return a struct json_object, error will be set to true if the object + * @return a struct json_object, valid will be set to false if the object * could not be created. * */ struct json_object json_new_object(void) { - struct json_object object; - object.error = false; + struct json_object object = json_empty_object; object.root = json_object(); if (object.root == NULL) { - object.error = true; - DBG_ERR("Unable to create json_object\n"); + object.valid = false; + DBG_ERR("Unable to create JSON object\n"); + return object; } + object.valid = true; return object; } @@ -320,14 +318,15 @@ struct json_object json_new_object(void) { */ struct json_object json_new_array(void) { - struct json_object array; - array.error = false; + struct json_object array = json_empty_object; array.root = json_array(); if (array.root == NULL) { - array.error = true; - DBG_ERR("Unable to create json_array\n"); + array.valid = false; + DBG_ERR("Unable to create JSON array\n"); + return array; } + array.valid = true; return array; } @@ -345,7 +344,7 @@ void json_free(struct json_object *object) json_decref(object->root); } object->root = NULL; - object->error = true; + object->valid = false; } /* @@ -358,99 +357,131 @@ void json_free(struct json_object *object) */ bool json_is_invalid(struct json_object *object) { - return object->error; + return !object->valid; } /* * @brief Add an integer value to a JSON object. * * Add an integer value named 'name' to the json object. - * In the event of an error object will be invalidated. * * @param object the JSON object to be updated. * @param name the name of the value. * @param value the value. * + * @return 0 the operation was successful + * -1 the operation failed + * */ -void json_add_int(struct json_object *object, - const char* name, - const int value) +int json_add_int(struct json_object *object, const char *name, const int value) { - int rc = 0; + int ret = 0; + json_t *integer = NULL; - if (object->error) { - return; + if (json_is_invalid(object)) { + DBG_ERR("Unable to add int [%s] value [%d], " + "target object is invalid\n", + name, + value); + return JSON_ERROR; + } + + integer = json_integer(value); + if (integer == NULL) { + DBG_ERR("Unable to create integer value [%s] value [%d]\n", + name, + value); + return JSON_ERROR; } - rc = json_object_set_new(object->root, name, json_integer(value)); - if (rc) { - DBG_ERR("Unable to set name [%s] value [%d]\n", name, value); - object->error = true; + ret = json_object_set_new(object->root, name, integer); + if (ret != 0) { + json_decref(integer); + DBG_ERR("Unable to add int [%s] value [%d]\n", name, value); } + return ret; } /* * @brief Add a boolean value to a JSON object. * * Add a boolean value named 'name' to the json object. - * In the event of an error object will be invalidated. * * @param object the JSON object to be updated. * @param name the name. * @param value the value. * + * @return 0 the operation was successful + * -1 the operation failed + * */ -void json_add_bool(struct json_object *object, - const char* name, - const bool value) +int json_add_bool(struct json_object *object, + const char *name, + const bool value) { - int rc = 0; + int ret = 0; - if (object->error) { - return; + if (json_is_invalid(object)) { + DBG_ERR("Unable to add boolean [%s] value [%d], " + "target object is invalid\n", + name, + value); + return JSON_ERROR; } - rc = json_object_set_new(object->root, name, json_boolean(value)); - if (rc) { - DBG_ERR("Unable to set name [%s] value [%d]\n", name, value); - object->error = true; + ret = json_object_set_new(object->root, name, json_boolean(value)); + if (ret != 0) { + DBG_ERR("Unable to add boolean [%s] value [%d]\n", name, value); } - + return ret; } /* * @brief Add a string value to a JSON object. * * Add a string value named 'name' to the json object. - * In the event of an error object will be invalidated. * * @param object the JSON object to be updated. * @param name the name. * @param value the value. * + * @return 0 the operation was successful + * -1 the operation failed + * */ -void json_add_string(struct json_object *object, - const char* name, - const char* value) +int json_add_string(struct json_object *object, + const char *name, + const char *value) { - int rc = 0; + int ret = 0; - if (object->error) { - return; + if (json_is_invalid(object)) { + DBG_ERR("Unable to add string [%s], target object is invalid\n", + name); + return JSON_ERROR; } - if (value) { - rc = json_object_set_new( - object->root, - name, - json_string(value)); + json_t *string = json_string(value); + if (string == NULL) { + DBG_ERR("Unable to add string [%s], " + "could not create string object\n", + name); + return JSON_ERROR; + } + ret = json_object_set_new(object->root, name, string); + if (ret != 0) { + json_decref(string); + DBG_ERR("Unable to add string [%s]\n", name); + return ret; + } } else { - rc = json_object_set_new(object->root, name, json_null()); - } - if (rc) { - DBG_ERR("Unable to set name [%s] value [%s]\n", name, value); - object->error = true; + ret = json_object_set_new(object->root, name, json_null()); + if (ret != 0) { + DBG_ERR("Unable to add null string [%s]\n", name); + return ret; + } } + return ret; } /* @@ -464,13 +495,13 @@ void json_add_string(struct json_object *object, */ void json_assert_is_array(struct json_object *array) { - if (array->error) { + if (json_is_invalid(array)) { return; } if (json_is_array(array->root) == false) { DBG_ERR("JSON object is not an array\n"); - array->error = true; + array->valid = false; return; } } @@ -479,43 +510,46 @@ void json_assert_is_array(struct json_object *array) { * @brief Add a JSON object to a JSON object. * * Add a JSON object named 'name' to the json object. - * In the event of an error object will be invalidated. * * @param object the JSON object to be updated. * @param name the name. * @param value the value. * + * @return 0 the operation was successful + * -1 the operation failed + * */ -void json_add_object(struct json_object *object, - const char* name, - struct json_object *value) +int json_add_object(struct json_object *object, + const char *name, + struct json_object *value) { - int rc = 0; + int ret = 0; json_t *jv = NULL; - if (object->error) { - return; + if (value != NULL && json_is_invalid(value)) { + DBG_ERR("Invalid JSON object [%s] supplied\n", name); + return JSON_ERROR; } - - if (value != NULL && value->error) { - object->error = true; - return; + if (json_is_invalid(object)) { + DBG_ERR("Unable to add object [%s], target object is invalid\n", + name); + return JSON_ERROR; } jv = value == NULL ? json_null() : value->root; if (json_is_array(object->root)) { - rc = json_array_append_new(object->root, jv); + ret = json_array_append_new(object->root, jv); } else if (json_is_object(object->root)) { - rc = json_object_set_new(object->root, name, jv); + ret = json_object_set_new(object->root, name, jv); } else { DBG_ERR("Invalid JSON object type\n"); - object->error = true; + ret = JSON_ERROR; } - if (rc) { + if (ret != 0) { DBG_ERR("Unable to add object [%s]\n", name); - object->error = true; } + return ret; } /* @@ -526,39 +560,57 @@ void json_add_object(struct json_object *object, * truncated if it is more than len characters long. If len is 0 the value * is encoded as a JSON null. * - * In the event of an error object will be invalidated. * * @param object the JSON object to be updated. * @param name the name. * @param value the value. * @param len the maximum number of characters to be copied. * + * @return 0 the operation was successful + * -1 the operation failed + * */ -void json_add_stringn(struct json_object *object, - const char *name, - const char *value, - const size_t len) +int json_add_stringn(struct json_object *object, + const char *name, + const char *value, + const size_t len) { - int rc = 0; - if (object->error) { - return; + int ret = 0; + if (json_is_invalid(object)) { + DBG_ERR("Unable to add string [%s], target object is invalid\n", + name); + return JSON_ERROR; } if (value != NULL && len > 0) { + json_t *string = NULL; char buffer[len+1]; + strncpy(buffer, value, len); buffer[len] = '\0'; - rc = json_object_set_new(object->root, - name, - json_string(buffer)); + + string = json_string(buffer); + if (string == NULL) { + DBG_ERR("Unable to add string [%s], " + "could not create string object\n", + name); + return JSON_ERROR; + } + ret = json_object_set_new(object->root, name, string); + if (ret != 0) { + json_decref(string); + DBG_ERR("Unable to add string [%s]\n", name); + return ret; + } } else { - rc = json_object_set_new(object->root, name, json_null()); - } - if (rc) { - DBG_ERR("Unable to set name [%s] value [%s]\n", name, value); - object->error = true; + ret = json_object_set_new(object->root, name, json_null()); + if (ret != 0) { + DBG_ERR("Unable to add null string [%s]\n", name); + return ret; + } } + return ret; } /* @@ -576,18 +628,45 @@ void json_add_stringn(struct json_object *object, * The minor version should change whenever a new attribute is added and for * minor bug fixes to an attributes content. * - * In the event of an error object will be invalidated. * * @param object the JSON object to be updated. * @param major the major version number * @param minor the minor version number + * + * @return 0 the operation was successful + * -1 the operation failed */ -void json_add_version(struct json_object *object, int major, int minor) +int json_add_version(struct json_object *object, int major, int minor) { - struct json_object version = json_new_object(); - json_add_int(&version, "major", major); - json_add_int(&version, "minor", minor); - json_add_object(object, "version", &version); + int ret = 0; + struct json_object version; + + if (json_is_invalid(object)) { + DBG_ERR("Unable to add version, target object is invalid\n"); + return JSON_ERROR; + } + + version = json_new_object(); + if (json_is_invalid(&version)) { + DBG_ERR("Unable to add version, failed to create object\n"); + return JSON_ERROR; + } + ret = json_add_int(&version, "major", major); + if (ret != 0) { + json_free(&version); + return ret; + } + ret = json_add_int(&version, "minor", minor); + if (ret != 0) { + json_free(&version); + return ret; + } + ret = json_add_object(object, "version", &version); + if (ret != 0) { + json_free(&version); + return ret; + } + return ret; } /* @@ -598,11 +677,13 @@ void json_add_version(struct json_object *object, int major, int minor) * * "timestamp":"2017-03-06T17:18:04.455081+1300" * - * In the event of an error object will be invalidated. * * @param object the JSON object to be updated. + * + * @return 0 the operation was successful + * -1 the operation failed */ -void json_add_timestamp(struct json_object *object) +int json_add_timestamp(struct json_object *object) { char buffer[40]; /* formatted time less usec and timezone */ char timestamp[65]; /* the formatted ISO 8601 time stamp */ @@ -610,9 +691,11 @@ void json_add_timestamp(struct json_object *object) struct tm* tm_info; /* current local time */ struct timeval tv; /* current system time */ int r; /* response code from gettimeofday */ + int ret; /* return code from json operations */ - if (object->error) { - return; + if (json_is_invalid(object)) { + DBG_ERR("Unable to add time stamp, target object is invalid\n"); + return JSON_ERROR; } r = gettimeofday(&tv, NULL); @@ -620,15 +703,13 @@ void json_add_timestamp(struct json_object *object) DBG_ERR("Unable to get time of day: (%d) %s\n", errno, strerror(errno)); - object->error = true; - return; + return JSON_ERROR; } tm_info = localtime(&tv.tv_sec); if (tm_info == NULL) { DBG_ERR("Unable to determine local time\n"); - object->error = true; - return; + return JSON_ERROR; } strftime(buffer, sizeof(buffer)-1, "%Y-%m-%dT%T", tm_info); @@ -640,10 +721,13 @@ void json_add_timestamp(struct json_object *object) buffer, tv.tv_usec, tz); - json_add_string(object, "timestamp", timestamp); + ret = json_add_string(object, "timestamp", timestamp); + if (ret != 0) { + DBG_ERR("Unable to add time stamp to JSON object\n"); + } + return ret; } - /* *@brief Add a tsocket_address to a JSON object * @@ -651,35 +735,59 @@ void json_add_timestamp(struct json_object *object) * * "localAddress":"ipv6::::0" * - * In the event of an error object will be invalidated. * * @param object the JSON object to be updated. * @param name the name. * @param address the tsocket_address. * + * @return 0 the operation was successful + * -1 the operation failed + * */ -void json_add_address(struct json_object *object, - const char *name, - const struct tsocket_address *address) +int json_add_address(struct json_object *object, + const char *name, + const struct tsocket_address *address) { + int ret = 0; - if (object->error) { - return; + if (json_is_invalid(object)) { + DBG_ERR("Unable to add address [%s], " + "target object is invalid\n", + name); + return JSON_ERROR; } + if (address == NULL) { - int rc = json_object_set_new(object->root, name, json_null()); - if (rc) { - DBG_ERR("Unable to set address [%s] to null\n", name); - object->error = true; + ret = json_object_set_new(object->root, name, json_null()); + if (ret != 0) { + DBG_ERR("Unable to add null address [%s]\n", name); + return JSON_ERROR; } } else { TALLOC_CTX *ctx = talloc_new(NULL); char *s = NULL; + if (ctx == NULL) { + DBG_ERR("Out of memory adding address [%s]\n", name); + return JSON_ERROR; + } + s = tsocket_address_string(address, ctx); - json_add_string(object, name, s); + if (s == NULL) { + DBG_ERR("Out of memory adding address [%s]\n", name); + TALLOC_FREE(ctx); + return JSON_ERROR; + } + ret = json_add_string(object, name, s); + if (ret != 0) { + DBG_ERR( + "Unable to add address [%s] value [%s]\n", name, s); + TALLOC_FREE(ctx); + return JSON_ERROR; + } TALLOC_FREE(ctx); } + return ret; } /* @@ -689,33 +797,47 @@ void json_add_address(struct json_object *object, * * "sid":"S-1-5-18" * - * In the event of an error object will be invalidated. * * @param object the JSON object to be updated. * @param name the name. * @param sid the sid * + * @return 0 the operation was successful + * -1 the operation failed + * */ -void json_add_sid(struct json_object *object, - const char *name, - const struct dom_sid *sid) +int json_add_sid(struct json_object *object, + const char *name, + const struct dom_sid *sid) { + int ret = 0; - if (object->error) { - return; + if (json_is_invalid(object)) { + DBG_ERR("Unable to add SID [%s], " + "target object is invalid\n", + name); + return JSON_ERROR; } + if (sid == NULL) { - int rc = json_object_set_new(object->root, name, json_null()); - if (rc) { - DBG_ERR("Unable to set SID [%s] to null\n", name); - object->error = true; + ret = json_object_set_new(object->root, name, json_null()); + if (ret != 0) { + DBG_ERR("Unable to add null SID [%s]\n", name); + return ret; } } else { char sid_buf[DOM_SID_STR_BUFLEN]; dom_sid_string_buf(sid, sid_buf, sizeof(sid_buf)); - json_add_string(object, name, sid_buf); + ret = json_add_string(object, name, sid_buf); + if (ret != 0) { + DBG_ERR("Unable to add SID [%s] value [%s]\n", + name, + sid_buf); + return ret; + } } + return ret; } /* @@ -725,46 +847,59 @@ void json_add_sid(struct json_object *object, * * "guid":"1fb9f2ee-2a4d-4bf8-af8b-cb9d4529a9ab" * - * In the event of an error object will be invalidated. * * @param object the JSON object to be updated. * @param name the name. * @param guid the guid. * + * @return 0 the operation was successful + * -1 the operation failed + * * */ -void json_add_guid(struct json_object *object, - const char *name, - const struct GUID *guid) +int json_add_guid(struct json_object *object, + const char *name, + const struct GUID *guid) { + int ret = 0; - if (object->error) { - return; + if (json_is_invalid(object)) { + DBG_ERR("Unable to add GUID [%s], " + "target object is invalid\n", + name); + return JSON_ERROR; } + if (guid == NULL) { - int rc = json_object_set_new(object->root, name, json_null()); - if (rc) { - DBG_ERR("Unable to set GUID [%s] to null\n", name); - object->error = true; + ret = json_object_set_new(object->root, name, json_null()); + if (ret != 0) { + DBG_ERR("Unable to add null GUID [%s]\n", name); + return ret; } } else { char *guid_str; struct GUID_txt_buf guid_buff; guid_str = GUID_buf_string(guid, &guid_buff); - json_add_string(object, name, guid_str); + ret = json_add_string(object, name, guid_str); + if (ret != 0) { + DBG_ERR("Unable to guid GUID [%s] value [%s]\n", + name, + guid_str); + return ret; + } } + return ret; } - /* * @brief Convert a JSON object into a string * * Convert the jsom object into a string suitable for printing on a log line, * i.e. with no embedded line breaks. * - * If the object is invalid it returns NULL. + * If the object is invalid it logs an error and returns NULL. * * @param mem_ctx the talloc memory context owning the returned string * @param object the json object. @@ -772,13 +907,17 @@ void json_add_guid(struct json_object *object, * @return A string representation of the object or NULL if the object * is invalid. */ -char *json_to_string(TALLOC_CTX *mem_ctx, - struct json_object *object) +char *json_to_string(TALLOC_CTX *mem_ctx, struct json_object *object) { char *json = NULL; char *json_string = NULL; - if (object->error) { + if (json_is_invalid(object)) { + DBG_ERR("Invalid JSON object, unable to convert to string\n"); + return NULL; + } + + if (object->root == NULL) { return NULL; } @@ -813,15 +952,23 @@ char *json_to_string(TALLOC_CTX *mem_ctx, * * @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 json_get_array(struct json_object *object, const char *name) { - struct json_object array = json_new_array(); + struct json_object array = json_empty_object; json_t *a = NULL; + int ret = 0; + + if (json_is_invalid(object)) { + DBG_ERR("Invalid JSON object, unable to get array [%s]\n", + name); + json_free(&array); + return array; + } - if (object->error) { - array.error = true; + array = json_new_array(); + if (json_is_invalid(&array)) { + DBG_ERR("Unable to create new array for [%s]\n", name); return array; } @@ -829,7 +976,13 @@ struct json_object json_get_array(struct json_object *object, if (a == NULL) { return array; } - json_array_extend(array.root, a); + + ret = json_array_extend(array.root, a); + if (ret != 0) { + DBG_ERR("Unable to get array [%s]\n", name); + json_free(&array); + return array; + } return array; } @@ -844,15 +997,17 @@ struct json_object json_get_array(struct json_object *object, * * @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 json_get_object(struct json_object *object, const char *name) { struct json_object o = json_new_object(); json_t *v = NULL; + int ret = 0; - if (object->error) { - o.error = true; + if (json_is_invalid(object)) { + DBG_ERR("Invalid JSON object, unable to get object [%s]\n", + name); + json_free(&o); return o; } @@ -860,8 +1015,12 @@ struct json_object json_get_object(struct json_object *object, if (v == NULL) { return o; } - json_object_update(o.root, v); - + ret = json_object_update(o.root, v); + if (ret != 0) { + DBG_ERR("Unable to get object [%s]\n", name); + json_free(&o); + return o; + } return o; } #endif diff --git a/lib/audit_logging/audit_logging.h b/lib/audit_logging/audit_logging.h index 4af743a4102..84738d2bb93 100644 --- a/lib/audit_logging/audit_logging.h +++ b/lib/audit_logging/audit_logging.h @@ -16,7 +16,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ - +#ifndef _AUDIT_LOGGING_H_ +#define _AUDIT_LOGGING_H_ #include <talloc.h> #include "lib/messaging/irpc.h" #include "lib/tsocket/tsocket.h" @@ -35,8 +36,11 @@ void audit_log_human_text(const char *prefix, */ struct json_object { json_t *root; - bool error; + bool valid; }; +extern const struct json_object json_empty_object; + +#define JSON_ERROR -1 void audit_log_json(const char *prefix, struct json_object *message, @@ -52,35 +56,31 @@ void json_free(struct json_object *object); void json_assert_is_array(struct json_object *array); bool json_is_invalid(struct json_object *object); -void json_add_int(struct json_object *object, - const char* name, - const int value); -void json_add_bool(struct json_object *object, - const char* name, - const bool value); -void json_add_string(struct json_object *object, - const char* name, - const char* value); -void json_add_object(struct json_object *object, - const char* name, - struct json_object *value); -void json_add_stringn(struct json_object *object, - const char *name, - const char *value, - const size_t len); -void json_add_version(struct json_object *object, - int major, - int minor); -void json_add_timestamp(struct json_object *object); -void json_add_address(struct json_object *object, - const char *name, - const struct tsocket_address *address); -void json_add_sid(struct json_object *object, +int json_add_int(struct json_object *object, const char *name, const int value); +int json_add_bool(struct json_object *object, const char *name, - const struct dom_sid *sid); -void json_add_guid(struct json_object *object, - const char *name, - const struct GUID *guid); + const bool value); +int json_add_string(struct json_object *object, + const char *name, + const char *value); +int json_add_object(struct json_object *object, + const char *name, + struct json_object *value); +int json_add_stringn(struct json_object *object, + const char *name, + const char *value, + const size_t len); +int json_add_version(struct json_object *object, int major, int minor); +int json_add_timestamp(struct json_object *object); +int json_add_address(struct json_object *object, + const char *name, + const struct tsocket_address *address); +int json_add_sid(struct json_object *object, + const char *name, + const struct dom_sid *sid); +int json_add_guid(struct json_object *object, + const char *name, + const struct GUID *guid); struct json_object json_get_array(struct json_object *object, const char* name); @@ -89,3 +89,4 @@ struct json_object json_get_object(struct json_object *object, char *json_to_string(TALLOC_CTX *mem_ctx, struct json_object *object); #endif +#endif diff --git a/lib/audit_logging/tests/audit_logging_test.c b/lib/audit_logging/tests/audit_logging_test.c index 26875c98944..07c52eada39 100644 --- a/lib/audit_logging/tests/audit_logging_test.c +++ b/lib/audit_logging/tests/audit_logging_test.c @@ -64,12 +64,15 @@ static void test_json_add_int(void **state) struct json_object object; struct json_t *value = NULL; double n; + int rc = 0; object = json_new_object(); - json_add_int(&object, "positive_one", 1); - json_add_int(&object, "zero", 0); - json_add_int(&object, "negative_one", -1); - + rc = json_add_int(&object, "positive_one", 1); + assert_int_equal(0, rc); + rc = json_add_int(&object, "zero", 0); + assert_int_equal(0, rc); + rc = json_add_int(&object, "negative_one", -1); + assert_int_equal(0, rc); assert_int_equal(3, json_object_size(object.root)); @@ -88,18 +91,27 @@ static void test_json_add_int(void **state) n = json_number_value(value); assert_true(n == -1.0); + object.valid = false; + rc = json_add_int(&object, "should fail 1", 0xf1); + assert_int_equal(JSON_ERROR, rc); + json_free(&object); + + rc = json_add_int(&object, "should fail 2", 0xf2); + assert_int_equal(JSON_ERROR, rc); } static void test_json_add_bool(void **state) { struct json_object object; struct json_t *value = NULL; + int rc = 0; object = json_new_object(); - json_add_bool(&object, "true", true); - json_add_bool(&object, "false", false); - + rc = json_add_bool(&object, "true", true); + assert_int_equal(0, rc); + rc = json_add_bool(&object, "false", false); + assert_int_equal(0, rc); assert_int_equal(2, json_object_size(object.root)); @@ -111,7 +123,14 @@ static void test_json_add_bool(void **state) assert_true(json_is_boolean(value)); assert_true(value == json_false()); + object.valid = false; + rc = json_add_bool(&object, "should fail 1", true); + assert_int_equal(JSON_ERROR, rc); + json_free(&object); + + rc = json_add_bool(&object, "should fail 2", false); + assert_int_equal(JSON_ERROR, rc); } static void test_json_add_string(void **state) @@ -119,13 +138,15 @@ static void test_json_add_string(void **state) struct json_object object; struct json_t *value = NULL; const char *s = NULL; + int rc = 0; object = json_new_object(); - json_add_string(&object, "null", NULL); - json_add_string(&object, "empty", ""); - json_add_string(&object, "name", "value"); - - + rc = json_add_string(&object, "null", NULL); + assert_int_equal(0, rc); + rc = json_add_string(&object, "empty", ""); + assert_int_equal(0, rc); + rc = json_add_string(&object, "name", "value"); + assert_int_equal(0, rc); assert_int_equal(3, json_object_size(object.root)); @@ -141,21 +162,32 @@ static void test_json_add_string(void **state) assert_true(json_is_string(value)); s = json_string_value(value); assert_string_equal("value", s); + + object.valid = false; + rc = json_add_string(&object, "should fail 1", "A value"); + assert_int_equal(JSON_ERROR, rc); + json_free(&object); + + rc = json_add_string(&object, "should fail 2", "Another value"); + assert_int_equal(JSON_ERROR, rc); } static void test_json_add_object(void **state) { struct json_object object; struct json_object other; + struct json_object after; + struct json_object invalid = json_empty_object; struct json_t *value = NULL; + int rc = 0; object = json_new_object(); other = json_new_object(); - json_add_object(&object, "null", NULL); - json_add_object(&object, "other", &other); - - + rc = json_add_object(&object, "null", NULL); + assert_int_equal(0, rc); + rc = json_add_object(&object, "other", &other); + assert_int_equal(0, rc); assert_int_equal(2, json_object_size(object.root)); @@ -166,7 +198,20 @@ static void test_json_add_object(void **state) assert_true(json_is_object(value)); assert_ptr_equal(other.root, value); + rc = json_add_object(&object, "invalid", &invalid); + assert_int_equal(JSON_ERROR, rc); + + object.valid = false; + after = json_new_object(); + rc = json_add_object(&object, "after", &after); + assert_int_equal(JSON_ERROR, rc); + json_free(&object); + + rc = json_add_object(&object, "after", &after); + assert_int_equal(JSON_ERROR, rc); + + json_free(&after); } static void test_json_add_to_array(void **state) @@ -175,7 +220,10 @@ static void test_json_add_to_array(void **state) struct json_object o1; struct json_object o2; struct json_object o3; + struct json_object after; + struct json_object invalid = json_empty_object; struct json_t *value = NULL; + int rc = 0; array = json_new_array(); assert_true(json_is_array(array.root)); @@ -184,10 +232,14 @@ static void test_json_add_to_array(void **state) o2 = json_new_object(); o3 = json_new_object(); - json_add_object(&array, NULL, &o3); - json_add_object(&array, "", &o2); - json_add_object(&array, "will-be-ignored", &o1); - json_add_object(&array, NULL, NULL); + rc = json_add_object(&array, NULL, &o3); + assert_int_equal(0, rc); + rc = json_add_object(&array, "", &o2); + assert_int_equal(0, rc); + rc = json_add_object(&array, "will-be-ignored", &o1); + assert_int_equal(0, rc); + rc = json_add_object(&array, NULL, NULL); + assert_int_equal(0, rc); assert_int_equal(4, json_array_size(array.root)); @@ -203,8 +255,20 @@ static void test_json_add_to_array(void **state) value = json_array_get(array.root, 3); assert_true(json_is_null(value)); + rc = json_add_object(&array, "invalid", &invalid); + assert_int_equal(JSON_ERROR, rc); + + array.valid = false; + after = json_new_object(); + rc = json_add_object(&array, "after", &after); + assert_int_equal(JSON_ERROR, rc); + json_free(&array); + rc = json_add_object(&array, "after", &after); + assert_int_equal(JSON_ERROR, rc); + + json_free(&after); } static void test_json_add_timestamp(void **state) @@ -224,7 +288,8 @@ static void test_json_add_timestamp(void **state) object = json_new_object(); before = time(NULL); - json_add_timestamp(&object); + rc = json_add_timestamp(&object); + assert_int_equal(0, rc); after = time(NULL); ts = json_object_get(object.root, "timestamp"); @@ -263,7 +328,14 @@ static void test_json_add_timestamp(void **state) assert_true(difftime(actual, before) >= 0); assert_true(difftime(after, actual) >= 0); + object.valid = false; + rc = json_add_timestamp(&object); + assert_int_equal(JSON_ERROR, rc); + json_free(&object); + + rc = json_add_timestamp(&object); + assert_int_equal(JSON_ERROR, rc); } static void test_json_add_stringn(void **state) @@ -271,17 +343,26 @@ static void test_json_add_stringn(void **state) struct json_object object; struct json_t *value = NULL; const char *s = NULL; + int rc = 0; object = json_new_object(); - json_add_stringn(&object, "null", NULL, 10); - json_add_stringn(&object, "null-zero-len", NULL, 0); - json_add_stringn(&object, "empty", "", 1); - json_add_stringn(&object, "empty-zero-len", "", 0); - json_add_stringn(&object, "value-less-than-len", "123456", 7); - json_add_stringn(&object, "value-greater-than-len", "abcd", 3); - json_add_stringn(&object, "value-equal-len", "ZYX", 3); - json_add_stringn(&object, "value-len-is-zero", "this will be null", 0); - + rc = json_add_stringn(&object, "null", NULL, 10); + assert_int_equal(0, rc); + rc = json_add_stringn(&object, "null-zero-len", NULL, 0); + assert_int_equal(0, rc); + rc = json_add_stringn(&object, "empty", "", 1); + assert_int_equal(0, rc); + rc = json_add_stringn(&object, "empty-zero-len", "", 0); + assert_int_equal(0, rc); + rc = json_add_stringn(&object, "value-less-than-len", "123456", 7); + assert_int_equal(0, rc); + rc = json_add_stringn(&object, "value-greater-than-len", "abcd", 3); + assert_int_equal(0, rc); + rc = json_add_stringn(&object, "value-equal-len", "ZYX", 3); + assert_int_equal(0, rc); + rc = json_add_stringn( + &object, "value-len-is-zero", "this will be null", 0); + assert_int_equal(0, rc); assert_int_equal(8, json_object_size(object.root)); @@ -314,7 +395,14 @@ static void test_json_add_stringn(void **state) value = json_object_get(object.root, "value-len-is-zero"); assert_true(json_is_null(value)); + object.valid = false; + rc = json_add_stringn(&object, "fail-01", "xxxxxxx", 1); + assert_int_equal(JSON_ERROR, rc); + json_free(&object); + + rc = json_add_stringn(&object, "fail-02", "xxxxxxx", 1); + assert_int_equal(JSON_ERROR, rc); } static void test_json_add_version(void **state) @@ -323,9 +411,11 @@ static void test_json_add_version(void **state) struct json_t *version = NULL; struct json_t *v = NULL; double n; + int rc; object = json_new_object(); - json_add_version(&object, 3, 1); + rc = json_add_version(&object, 3, 1); + assert_int_equal(0, rc); assert_int_equal(1, json_object_size(object.root)); @@ -343,7 +433,14 @@ static void test_json_add_version(void **state) n = json_number_value(v); assert_true(n == 1.0); + object.valid = false; + rc = json_add_version(&object, 3, 1); + assert_int_equal(JSON_ERROR, rc); + json_free(&object); + + rc = json_add_version(&object, 3, 1); + assert_int_equal(JSON_ERROR, rc); } static void test_json_add_address(void **state) @@ -353,6 +450,8 @@ static void test_json_add_address(void **state) struct tsocket_address *ip4 = NULL; struct tsocket_address *ip6 = NULL; struct tsocket_address *pipe = NULL; + + struct tsocket_address *after = NULL; const char *s = NULL; int rc; @@ -360,7 +459,8 @@ static void test_json_add_address(void **state) object = json_new_object(); - json_add_address(&object, "null", NULL); + rc = json_add_address(&object, "null", NULL); + assert_int_equal(0, rc); rc = tsocket_address_inet_from_strings( ctx, @@ -369,7 +469,8 @@ static void test_json_add_address(void **state) 21, &ip4); assert_int_equal(0, rc); - json_add_address(&object, "ip4", ip4); + rc = json_add_address(&object, "ip4", ip4); + assert_int_equal(0, rc); rc = tsocket_address_inet_from_strings( ctx, @@ -378,11 +479,13 @@ static void test_json_add_address(void **state) 42, &ip6); assert_int_equal(0, rc); - json_add_address(&object, "ip6", ip6); + rc = json_add_address(&object, "ip6", ip6); + assert_int_equal(0, rc); rc = tsocket_address_unix_from_path(ctx, "/samba/pipe", &pipe); assert_int_equal(0, rc); - json_add_address(&object, "pipe", pipe); + rc = json_add_address(&object, "pipe", pipe); + assert_int_equal(0, rc); assert_int_equal(4, json_object_size(object.root)); @@ -404,7 +507,18 @@ static void test_json_add_address(void **state) s = json_string_value(value); assert_string_equal("unix:/samba/pipe", s); + object.valid = false; + rc = tsocket_address_inet_from_strings( + ctx, "ip", "127.0.0.11", 23, &after); + assert_int_equal(0, rc); + rc = json_add_address(&object, "invalid_object", after); + assert_int_equal(JSON_ERROR, rc); + json_free(&object); + + rc = json_add_address(&object, "freed object", after); + assert_int_equal(JSON_ERROR, rc); + TALLOC_FREE(ctx); } @@ -415,14 +529,16 @@ static void test_json_add_sid(void **state) const char *SID = "S-1-5-21-2470180966-3899876309-2637894779"; struct dom_sid sid; const char *s = NULL; - + int rc; object = json_new_object(); - json_add_sid(&object, "null", NULL); + rc = json_add_sid(&object, "null", NULL); + assert_int_equal(0, rc); assert_true(string_to_sid(&sid, SID)); - json_add_sid(&object, "sid", &sid); + rc = json_add_sid(&object, "sid", &sid); + assert_int_equal(0, rc); assert_int_equal(2, json_object_size(object.root)); @@ -433,7 +549,15 @@ static void test_json_add_sid(void **state) assert_true(json_is_string(value)); s = json_string_value(value); assert_string_equal(SID, s); + + object.valid = false; + rc = json_add_sid(&object, "invalid_object", &sid); + assert_int_equal(JSON_ERROR, rc); + json_free(&object); + + rc = json_add_sid(&object, "freed_object", &sid); + assert_int_equal(JSON_ERROR, rc); } static void test_json_add_guid(void **state) @@ -444,15 +568,17 @@ static void test_json_add_guid(void **state) struct GUID guid; const char *s = NULL; NTSTATUS status; - + int rc; object = json_new_object(); - json_add_guid(&object, "null", NULL); + rc = json_add_guid(&object, "null", NULL); + assert_int_equal(0, rc); status = GUID_from_string(GUID, &guid); assert_true(NT_STATUS_IS_OK(status)); - json_add_guid(&object, "guid", &guid); + rc = json_add_guid(&object, "guid", &guid); + assert_int_equal(0, rc); assert_int_equal(2, json_object_size(object.root)); @@ -464,7 +590,14 @@ static void test_json_add_guid(void **state) s = json_string_value(value); assert_string_equal(GUID, s); + object.valid = false; + rc = json_add_guid(&object, "invalid_object", &guid); + assert_int_equal(JSON_ERROR, rc); + json_free(&object); + + rc = json_add_guid(&object, "freed_object", &guid); + assert_int_equal(JSON_ERROR, rc); } static void test_json_to_string(void **state) @@ -475,12 +608,7 @@ static void test_json_to_string(void **state) TALLOC_CTX *ctx = talloc_new(NULL); object = json_new_object(); - object.error = true; - - s = json_to_string(ctx, &object); - assert_null(s); - object.error = false; s = json_to_string(ctx, &object); assert_string_equal("{}", s); TALLOC_FREE(s); @@ -490,7 +618,17 @@ static void test_json_to_string(void **state) assert_string_equal("{\"name\": \"value\"}", s); TALLOC_FREE(s); + object.valid = false; + s = json_to_string(ctx, &object); + assert_null(s); + json_free(&object); + + object.valid = true; + object.root = NULL; + + s = json_to_string(ctx, &object); + assert_null(s); TALLOC_FREE(ctx); } @@ -507,7 +645,7 @@ static void test_json_get_array(void **state) object = json_new_object(); array = json_get_array(&object, "not-there"); - assert_false(array.error); + assert_true(array.valid); assert_non_null(array.root); assert_true(json_is_array(array.root)); json_free(&array); @@ -518,7 +656,7 @@ static void test_json_get_array(void **state) json_add_object(&object, "stored_array", &stored_array); array = json_get_array(&object, "stored_array"); - assert_false(array.error); + assert_true(array.valid); assert_non_null(array.root); assert_true(json_is_array(array.root)); @@ -542,7 +680,7 @@ static void test_json_get_array(void **state) assert_true(json_is_array(array.root)); o2 = json_new_object(); json_add_string(&o2, "value", "value-two"); - assert_false(o2.error); + assert_true(o2.valid); json_add_object(&array, NULL, &o2); assert_true(json_is_array(array.root)); json_add_object(&object, "stored_array", &array); @@ -551,7 +689,7 @@ static void test_json_get_array(void **state) 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(array.valid); assert_true(json_is_array(array.root)); assert_int_equal(2, json_array_size(array.root)); @@ -577,6 +715,10 @@ static void test_json_get_array(void **state) json_free(&array); json_free(&object); + + array = json_get_array(&object, "stored_array"); + assert_false(array.valid); + json_free(&array); } static void test_json_get_object(void **state) @@ -590,7 +732,7 @@ static void test_json_get_object(void **state) object = json_new_object(); o1 = json_get_object(&object, "not-there"); - assert_false(o1.error); + assert_true(o1.valid); assert_non_null(o1.root); assert_true(json_is_object(o1.root)); json_free(&o1); @@ -600,7 +742,7 @@ static void test_json_get_object(void **state) json_add_object(&object, "stored_object", &o1); o2 = json_get_object(&object, "stored_object"); - assert_false(o2.error); + assert_true(o2.valid); assert_non_null(o2.root); assert_true(json_is_object(o2.root)); @@ -615,7 +757,7 @@ static void test_json_get_object(void **state) o3 = json_get_object(&object, "stored_object"); - assert_false(o3.error); + assert_true(o3.valid); assert_non_null(o3.root); assert_true(json_is_object(o3.root)); @@ -627,6 +769,10 @@ static void test_json_get_object(void **state) json_free(&o3); json_free(&object); + + o3 = json_get_object(&object, "stored_object"); + assert_false(o3.valid); + json_free(&o3); } static void test_audit_get_timestamp(void **state) |