dsdb: When using an LDAP backend, force use of the password from secrets.ldb
authorAndrew Bartlett <abartlet@samba.org>
Mon, 9 Sep 2013 23:38:10 +0000 (11:38 +1200)
committerNadezhda Ivanova <nivanova@samba.org>
Wed, 11 Sep 2013 19:15:50 +0000 (21:15 +0200)
This makes testing from the command line much easier, as ldbsearch -H
sam.ldb will now just work as well as it did with a tdb-based
provision.

This code was removed from it's previous location outside the ldb
module stack in aabda85a2fc9f6763abd56d61ff819012f2225ad.

Andrew Bartlett

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Signed-off-by: Nadezhda Ivanova <nivanova@symas.com>
Autobuild-User(master): Nadezhda Ivanova <nivanova@samba.org>
Autobuild-Date(master): Wed Sep 11 21:15:50 CEST 2013 on sn-devel-104

source4/dsdb/samdb/ldb_modules/samba_dsdb.c

index ee7f694c734e8f319ee89b93189650b19913e254..ac993db4d788372afdb16d795b210a2c330b0937 100644 (file)
@@ -37,6 +37,9 @@
 #include "dsdb/samdb/ldb_modules/util.h"
 #include "dsdb/samdb/samdb.h"
 #include "librpc/ndr/libndr.h"
+#include "auth/credentials/credentials.h"
+#include "param/secrets.h"
+#include "lib/ldb-samba/ldb_wrap.h"
 
 static int read_at_rootdse_record(struct ldb_context *ldb, struct ldb_module *module, TALLOC_CTX *mem_ctx,
                                  struct ldb_message **msg, struct ldb_request *parent)
@@ -129,7 +132,94 @@ static int prepare_modules_line(struct ldb_context *ldb,
        return ret;
 }
 
+/*
+ * Force overwrite of the credentials with those
+ * specified in secrets.ldb, to connect across the
+ * ldapi socket to an LDAP backend
+ */
 
+static int set_ldap_credentials(struct ldb_context *ldb)
+{
+       const char *secrets_ldb_path, *sam_ldb_path;
+       char *private_dir, *p, *error_string;
+       struct ldb_context *secrets_ldb;
+       struct cli_credentials *cred;
+       struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm");
+       TALLOC_CTX *tmp_ctx = talloc_new(ldb);
+
+       if (!tmp_ctx) {
+               return ldb_oom(ldb);
+       }
+
+       cred = cli_credentials_init(ldb);
+       if (!cred) {
+               talloc_free(tmp_ctx);
+               return ldb_oom(ldb);
+       }
+       cli_credentials_set_anonymous(cred);
+
+       /*
+        * We don't want to use krb5 to talk to our samdb - recursion
+        * here would be bad, and this account isn't in the KDC
+        * anyway
+        */
+       cli_credentials_set_kerberos_state(cred, CRED_DONT_USE_KERBEROS);
+
+       /*
+        * Work out where *our* secrets.ldb is.  It must be in
+        * the same directory as sam.ldb
+        */
+       sam_ldb_path = (const char *)ldb_get_opaque(ldb, "ldb_url");
+       if (!sam_ldb_path) {
+               talloc_free(tmp_ctx);
+               return ldb_operr(ldb);
+       }
+       if (strncmp("tdb://", sam_ldb_path, 6) == 0) {
+               sam_ldb_path += 6;
+       }
+       private_dir = talloc_strdup(tmp_ctx, sam_ldb_path);
+       p = strrchr(private_dir, '/');
+       if (p) {
+               *p = '\0';
+       } else {
+               private_dir = talloc_strdup(tmp_ctx, ".");
+       }
+
+       secrets_ldb_path = talloc_asprintf(private_dir, "tdb://%s/secrets.ldb",
+                                          private_dir);
+
+       if (!secrets_ldb_path) {
+               talloc_free(tmp_ctx);
+               return ldb_oom(ldb);
+       }
+
+       /*
+        * Now that we have found the location, connect to
+        * secrets.ldb so we can read the SamDB Credentials
+        * record
+        */
+       secrets_ldb = ldb_wrap_connect(tmp_ctx, NULL, lp_ctx, secrets_ldb_path,
+                                      NULL, NULL, 0);
+
+       if (!NT_STATUS_IS_OK(cli_credentials_set_secrets(cred, NULL, secrets_ldb, NULL,
+                                                        SECRETS_LDAP_FILTER, &error_string))) {
+               ldb_asprintf_errstring(ldb, "Failed to read LDAP backend password from %s", secrets_ldb_path);
+               talloc_free(tmp_ctx);
+               return LDB_ERR_STRONG_AUTH_REQUIRED;
+       }
+
+       /*
+        * Finally overwrite any supplied credentials with
+        * these ones, as only secrets.ldb contains the magic
+        * credentials to talk on the ldapi socket
+        */
+       if (ldb_set_opaque(ldb, "credentials", cred)) {
+               talloc_free(tmp_ctx);
+               return ldb_operr(ldb);
+       }
+       talloc_free(tmp_ctx);
+       return LDB_SUCCESS;
+}
 
 static int samba_dsdb_init(struct ldb_module *module)
 {
@@ -257,6 +347,7 @@ static int samba_dsdb_init(struct ldb_module *module)
                extended_dn_module = extended_dn_module_ldb;
                link_modules = tdb_modules_list;
        } else {
+               struct cli_credentials *cred;
                if (strcasecmp(backendType, "fedora-ds") == 0) {
                        link_modules = fedora_ds_modules;
                        backend_modules = fedora_ds_backend_modules;
@@ -272,6 +363,14 @@ static int samba_dsdb_init(struct ldb_module *module)
                if (ret != LDB_SUCCESS) {
                        ldb_set_errstring(ldb, "Failed to set readOnlySchema opaque");
                }
+
+               cred = ldb_get_opaque(ldb, "credentials");
+               if (!cred || !cli_credentials_authentication_requested(cred)) {
+                       ret = set_ldap_credentials(ldb);
+                       if (ret != LDB_SUCCESS) {
+                               return ret;
+                       }
+               }
        }
 
 #define CHECK_MODULE_LIST \