ldb: Add new ldb_ldif_message_redacted_string() with tests
authorAndrew Bartlett <abartlet@samba.org>
Tue, 5 Sep 2017 02:05:43 +0000 (14:05 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 7 Sep 2017 04:56:27 +0000 (06:56 +0200)
This is designed to be a drop in replacement for
ldb_ldif_message_string() while better protecting privacy.

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13017

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
lib/ldb/common/ldb_ldif.c
lib/ldb/include/ldb.h
lib/ldb/tests/ldb_mod_op_test.c

index 0aeda94beac64a568d4345ee5d824b44c7f14385..b90d27eea59d6d597c383b275744682570c67b52 100644 (file)
@@ -1080,3 +1080,24 @@ char *ldb_ldif_message_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
 
        return ldb_ldif_write_string(ldb, mem_ctx, &ldif);
 }
+
+/*
+ * convenient function to turn a ldb_message into a string. Useful for
+ * debugging but also safer if some of the LDIF could be sensitive.
+ *
+ * The secret attributes are specified in a 'const char * const *' within
+ * the LDB_SECRET_ATTRIBUTE_LIST opaque set on the ldb
+ *
+ */
+char *ldb_ldif_message_redacted_string(struct ldb_context *ldb,
+                                      TALLOC_CTX *mem_ctx,
+                                      enum ldb_changetype changetype,
+                                      const struct ldb_message *msg)
+{
+       struct ldb_ldif ldif;
+
+       ldif.changetype = changetype;
+       ldif.msg = discard_const_p(struct ldb_message, msg);
+
+       return ldb_ldif_write_redacted_trace_string(ldb, mem_ctx, &ldif);
+}
index 14cec0e0b93a9867185960c859940f733b355b2e..9918b4e69d9820e2471ceccd424076de052ccbe7 100644 (file)
@@ -1724,16 +1724,46 @@ char * ldb_ldif_write_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
                          const struct ldb_ldif *msg);
 
 
-/*
-   Produce a string form of an ldb message
+/**
+   Write an LDB message to a string
 
-   convenient function to turn a ldb_message into a string. Useful for
-   debugging
- */
+   \param ldb the ldb context (from ldb_init())
+   \param mem_ctx the talloc context on which to attach the string)
+   \param changetype LDB_CHANGETYPE_ADD or LDB_CHANGETYPE_MODIFY
+   \param msg the message to write out
+
+   \return the string containing the LDIF, or NULL on error
+
+   \sa ldb_ldif_message_redacted_string for a safer version of this 
+       function
+*/
 char *ldb_ldif_message_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
                              enum ldb_changetype changetype,
                              const struct ldb_message *msg);
 
+/**
+   Write an LDB message to a string
+
+   \param ldb the ldb context (from ldb_init())
+   \param mem_ctx the talloc context on which to attach the string)
+   \param changetype LDB_CHANGETYPE_ADD or LDB_CHANGETYPE_MODIFY
+   \param msg the message to write out
+
+   \return the string containing the LDIF, or NULL on error, but
+           with secret attributes redacted
+
+   \note The secret attributes are specified in a 
+         'const char * const *' within the LDB_SECRET_ATTRIBUTE_LIST
+         opaque set on the ldb
+
+   \sa ldb_ldif_message_string for an exact representiation of the
+       message as LDIF
+*/
+char *ldb_ldif_message_redacted_string(struct ldb_context *ldb,
+                                      TALLOC_CTX *mem_ctx,
+                                      enum ldb_changetype changetype,
+                                      const struct ldb_message *msg);
+
 
 /**
    Base64 encode a buffer
index 96d2dd27df25ea7d2851aed0dbd0dcb8b1f0b784..5e439f8d151b2c82530ef9a424ec58218f013775 100644 (file)
@@ -114,6 +114,91 @@ static void test_connect(void **state)
        assert_int_equal(ret, 0);
 }
 
+static struct ldb_message *get_test_ldb_message(TALLOC_CTX *mem_ctx,
+                                               struct ldb_context *ldb)
+{
+       struct ldb_message *msg = ldb_msg_new(mem_ctx);
+       int ret;
+       assert_non_null(msg);
+
+       msg->dn = ldb_dn_new(msg, ldb, "dc=samba,dc=org");
+       assert_non_null(msg->dn);
+       ret = ldb_msg_add_string(msg, "public", "key");
+       assert_int_equal(ret, LDB_SUCCESS);
+       ret = ldb_msg_add_string(msg, "supersecret", "password");
+       assert_int_equal(ret, LDB_SUCCESS);
+       ret = ldb_msg_add_string(msg, "binary", "\xff\xff\0");
+       assert_int_equal(ret, LDB_SUCCESS);
+       return msg;
+}
+
+static void test_ldif_message(void **state)
+{
+       struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
+                                                       struct ldbtest_ctx);
+       char *got_ldif;
+       const char *expected_ldif =
+               "dn: dc=samba,dc=org\n"
+               "changetype: add\n"
+               "public: key\n"
+               "supersecret: password\n"
+               "binary:: //8=\n"
+               "\n";
+       
+       struct ldb_message *msg = get_test_ldb_message(test_ctx,
+                                                      test_ctx->ldb);
+
+       got_ldif = ldb_ldif_message_string(test_ctx->ldb,
+                                          test_ctx,
+                                          LDB_CHANGETYPE_ADD,
+                                          msg);
+       assert_string_equal(got_ldif, expected_ldif);
+       TALLOC_FREE(got_ldif);
+}
+
+static void test_ldif_message_redacted(void **state)
+{
+       struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
+                                                       struct ldbtest_ctx);
+       int ret;
+       char *got_ldif;
+       const char *expected_ldif =
+               "dn: dc=samba,dc=org\n"
+               "changetype: add\n"
+               "public: key\n"
+               "# supersecret::: REDACTED SECRET ATTRIBUTE\n"
+               "binary:: //8=\n"
+               "\n";
+
+       const char *secret_attrs[] = {
+               "supersecret",
+               NULL
+       };
+       
+       struct ldb_message *msg = ldb_msg_new(test_ctx);
+
+       ldb_set_opaque(test_ctx->ldb,
+                      LDB_SECRET_ATTRIBUTE_LIST_OPAQUE,
+                      secret_attrs);
+       
+       assert_non_null(msg);
+
+       msg->dn = ldb_dn_new(msg, test_ctx->ldb, "dc=samba,dc=org");
+       ret = ldb_msg_add_string(msg, "public", "key");
+       assert_int_equal(ret, LDB_SUCCESS);
+       ret = ldb_msg_add_string(msg, "supersecret", "password");
+       assert_int_equal(ret, LDB_SUCCESS);
+       ret = ldb_msg_add_string(msg, "binary", "\xff\xff\0");
+       assert_int_equal(ret, LDB_SUCCESS);
+       got_ldif = ldb_ldif_message_redacted_string(test_ctx->ldb,
+                                                   test_ctx,
+                                                   LDB_CHANGETYPE_ADD,
+                                                   msg);
+       assert_string_equal(got_ldif, expected_ldif);
+       TALLOC_FREE(got_ldif);
+       assert_int_equal(ret, 0);
+}
+
 static int ldbtest_setup(void **state)
 {
        struct ldbtest_ctx *test_ctx;
@@ -2782,6 +2867,12 @@ int main(int argc, const char **argv)
                cmocka_unit_test_setup_teardown(test_connect,
                                                ldbtest_noconn_setup,
                                                ldbtest_noconn_teardown),
+               cmocka_unit_test_setup_teardown(test_ldif_message,
+                                               ldbtest_noconn_setup,
+                                               ldbtest_noconn_teardown),
+               cmocka_unit_test_setup_teardown(test_ldif_message_redacted,
+                                               ldbtest_noconn_setup,
+                                               ldbtest_noconn_teardown),
                cmocka_unit_test_setup_teardown(test_ldb_add,
                                                ldbtest_setup,
                                                ldbtest_teardown),