s4-loadparm: 2nd half of lp_ to lpcfg_ conversion
[ira/wip.git] / source4 / auth / credentials / credentials_files.c
index 1bbdf8a5ad67fb0b9bcfdf7e4818f0923a32d107..e0fd052cbc07d15ad3ae18c6651d3900b086ce22 100644 (file)
 */
 
 #include "includes.h"
+#include "lib/events/events.h"
 #include "lib/ldb/include/ldb.h"
 #include "librpc/gen_ndr/samr.h" /* for struct samrPassword */
 #include "param/secrets.h"
 #include "system/filesys.h"
-#include "util/util_ldb.h"
+#include "../lib/util/util_ldb.h"
 #include "auth/credentials/credentials.h"
 #include "auth/credentials/credentials_krb5.h"
+#include "auth/credentials/credentials_proto.h"
 #include "param/param.h"
+#include "lib/events/events.h"
+#include "dsdb/samdb/samdb.h"
+
 
 /**
  * Read a file descriptor, and parse it for a password (eg from a file or stdin)
@@ -116,7 +121,7 @@ _PUBLIC_ bool cli_credentials_parse_file(struct cli_credentials *cred, const cha
        char **lines;
        int i, numlines;
 
-       lines = file_lines_load(file, &numlines, NULL);
+       lines = file_lines_load(file, &numlines, 0, NULL);
 
        if (lines == NULL)
        {
@@ -169,15 +174,17 @@ _PUBLIC_ bool cli_credentials_parse_file(struct cli_credentials *cred, const cha
  * @retval NTSTATUS error detailing any failure
  */
 _PUBLIC_ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, 
-                                    struct loadparm_context *lp_ctx,
-                                    struct ldb_context *ldb,
-                                    const char *base,
-                                    const char *filter)
+                                             struct tevent_context *event_ctx,
+                                             struct loadparm_context *lp_ctx,
+                                             struct ldb_context *ldb,
+                                             const char *base,
+                                             const char *filter, 
+                                             char **error_string)
 {
        TALLOC_CTX *mem_ctx;
        
        int ldb_ret;
-       struct ldb_message **msgs;
+       struct ldb_message *msg;
        const char *attrs[] = {
                "secret",
                "priorSecret",
@@ -191,6 +198,7 @@ _PUBLIC_ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
                "privateKeytab",
                "krb5Keytab",
                "servicePrincipalName",
+               "ldapBindDn",
                NULL
        };
        
@@ -202,7 +210,8 @@ _PUBLIC_ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
        enum netr_SchannelType sct;
        const char *salt_principal;
        const char *keytab;
-       
+       const struct ldb_val *whenChanged;
+
        /* ok, we are going to get it now, don't recurse back here */
        cred->machine_account_pending = false;
 
@@ -213,64 +222,68 @@ _PUBLIC_ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
 
        if (!ldb) {
                /* Local secrets are stored in secrets.ldb */
-               ldb = secrets_db_connect(mem_ctx, lp_ctx);
+               ldb = secrets_db_connect(mem_ctx, event_ctx, lp_ctx);
                if (!ldb) {
                        /* set anonymous as the fallback, if the machine account won't work */
                        cli_credentials_set_anonymous(cred);
-                       DEBUG(1, ("Could not open secrets.ldb\n"));
+                       *error_string = talloc_strdup(cred, "Could not open secrets.ldb");
+                       talloc_free(mem_ctx);
                        return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
                }
        }
 
-       /* search for the secret record */
-       ldb_ret = gendb_search(ldb,
-                              mem_ctx, ldb_dn_new(mem_ctx, ldb, base), 
-                              &msgs, attrs,
-                              "%s", filter);
-       if (ldb_ret == 0) {
-               DEBUG(1, ("Could not find entry to match filter: '%s' base: '%s'\n",
-                         filter, base));
-               /* set anonymous as the fallback, if the machine account won't work */
-               cli_credentials_set_anonymous(cred);
-               talloc_free(mem_ctx);
-               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
-       } else if (ldb_ret != 1) {
-               DEBUG(1, ("Found more than one (%d) entry to match filter: '%s' base: '%s'\n",
-                         ldb_ret, filter, base));
+       ldb_ret = dsdb_search_one(ldb, ldb, &msg,
+                                 ldb_dn_new(mem_ctx, ldb, base),
+                                 LDB_SCOPE_SUBTREE,
+                                 attrs, 0, "%s", filter);
+
+       if (ldb_ret != LDB_SUCCESS) {
+               *error_string = talloc_asprintf(cred, "Could not find entry to match filter: '%s' base: '%s': %s: %s\n",
+                                               filter, base ? base : "",
+                                               ldb_strerror(ldb_ret), ldb_errstring(ldb));
                /* set anonymous as the fallback, if the machine account won't work */
                cli_credentials_set_anonymous(cred);
                talloc_free(mem_ctx);
                return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
        }
-       
-       password = ldb_msg_find_attr_as_string(msgs[0], "secret", NULL);
-       old_password = ldb_msg_find_attr_as_string(msgs[0], "priorSecret", NULL);
 
-       machine_account = ldb_msg_find_attr_as_string(msgs[0], "samAccountName", NULL);
+       password = ldb_msg_find_attr_as_string(msg, "secret", NULL);
+       old_password = ldb_msg_find_attr_as_string(msg, "priorSecret", NULL);
+
+       machine_account = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
 
        if (!machine_account) {
-               machine_account = ldb_msg_find_attr_as_string(msgs[0], "servicePrincipalName", NULL);
+               machine_account = ldb_msg_find_attr_as_string(msg, "servicePrincipalName", NULL);
                
                if (!machine_account) {
-                       DEBUG(1, ("Could not find 'samAccountName' in join record to domain: %s: filter: '%s' base: '%s'\n",
-                                 cli_credentials_get_domain(cred), filter, base));
-                       /* set anonymous as the fallback, if the machine account won't work */
-                       cli_credentials_set_anonymous(cred);
-                       talloc_free(mem_ctx);
-                       return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+                       const char *ldap_bind_dn = ldb_msg_find_attr_as_string(msg, "ldapBindDn", NULL);
+                       if (!ldap_bind_dn) {
+                               *error_string = talloc_asprintf(cred, 
+                                                               "Could not find 'samAccountName', "
+                                                               "'servicePrincipalName' or "
+                                                               "'ldapBindDn' in secrets record: %s",
+                                                               ldb_dn_get_linearized(msg->dn));
+                               /* set anonymous as the fallback, if the machine account won't work */
+                               cli_credentials_set_anonymous(cred);
+                               talloc_free(mem_ctx);
+                               return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
+                       } else {
+                               /* store bind dn in credentials */
+                               cli_credentials_set_bind_dn(cred, ldap_bind_dn);
+                       }
                }
        }
 
-       salt_principal = ldb_msg_find_attr_as_string(msgs[0], "saltPrincipal", NULL);
+       salt_principal = ldb_msg_find_attr_as_string(msg, "saltPrincipal", NULL);
        cli_credentials_set_salt_principal(cred, salt_principal);
        
-       sct = ldb_msg_find_attr_as_int(msgs[0], "secureChannelType", 0);
+       sct = ldb_msg_find_attr_as_int(msg, "secureChannelType", 0);
        if (sct) { 
                cli_credentials_set_secure_channel_type(cred, sct);
        }
        
        if (!password) {
-               const struct ldb_val *nt_password_hash = ldb_msg_find_ldb_val(msgs[0], "unicodePwd");
+               const struct ldb_val *nt_password_hash = ldb_msg_find_ldb_val(msg, "unicodePwd");
                struct samr_Password hash;
                ZERO_STRUCT(hash);
                if (nt_password_hash) {
@@ -286,32 +299,42 @@ _PUBLIC_ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
        }
 
        
-       domain = ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL);
+       domain = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
        if (domain) {
                cli_credentials_set_domain(cred, domain, CRED_SPECIFIED);
        }
 
-       realm = ldb_msg_find_attr_as_string(msgs[0], "realm", NULL);
+       realm = ldb_msg_find_attr_as_string(msg, "realm", NULL);
        if (realm) {
                cli_credentials_set_realm(cred, realm, CRED_SPECIFIED);
        }
 
-       cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED);
+       if (machine_account) {
+               cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED);
+       }
 
-       cli_credentials_set_kvno(cred, ldb_msg_find_attr_as_int(msgs[0], "msDS-KeyVersionNumber", 0));
+       cli_credentials_set_kvno(cred, ldb_msg_find_attr_as_int(msg, "msDS-KeyVersionNumber", 0));
 
+       whenChanged = ldb_msg_find_ldb_val(msg, "whenChanged");
+       if (whenChanged) {
+               time_t lct;
+               if (ldb_val_to_time(whenChanged, &lct) == LDB_SUCCESS) {
+                       cli_credentials_set_password_last_changed_time(cred, lct);
+               }
+       }
+       
        /* If there was an external keytab specified by reference in
         * the LDB, then use this.  Otherwise we will make one up
         * (chewing CPU time) from the password */
-       keytab = ldb_msg_find_attr_as_string(msgs[0], "krb5Keytab", NULL);
+       keytab = ldb_msg_find_attr_as_string(msg, "krb5Keytab", NULL);
        if (keytab) {
-               cli_credentials_set_keytab_name(cred, lp_ctx, keytab, CRED_SPECIFIED);
+               cli_credentials_set_keytab_name(cred, event_ctx, lp_ctx, keytab, CRED_SPECIFIED);
        } else {
-               keytab = ldb_msg_find_attr_as_string(msgs[0], "privateKeytab", NULL);
+               keytab = ldb_msg_find_attr_as_string(msg, "privateKeytab", NULL);
                if (keytab) {
-                       keytab = talloc_asprintf(mem_ctx, "FILE:%s", private_path(mem_ctx, lp_ctx, keytab));
+                       keytab = talloc_asprintf(mem_ctx, "FILE:%s", samdb_relative_path(ldb, mem_ctx, keytab));
                        if (keytab) {
-                               cli_credentials_set_keytab_name(cred, lp_ctx, keytab, CRED_SPECIFIED);
+                               cli_credentials_set_keytab_name(cred, event_ctx, lp_ctx, keytab, CRED_SPECIFIED);
                        }
                }
        }
@@ -329,16 +352,23 @@ _PUBLIC_ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
 _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred,
                                                      struct loadparm_context *lp_ctx)
 {
+       NTSTATUS status;
        char *filter;
+       char *error_string;
        /* Bleh, nasty recursion issues: We are setting a machine
         * account here, so we don't want the 'pending' flag around
         * any more */
        cred->machine_account_pending = false;
        filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER, 
                                       cli_credentials_get_domain(cred));
-       return cli_credentials_set_secrets(cred, lp_ctx, NULL, 
+       status = cli_credentials_set_secrets(cred, event_context_find(cred), lp_ctx, NULL,
                                           SECRETS_PRIMARY_DOMAIN_DN,
-                                          filter);
+                                            filter, &error_string);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(1, ("Could not find machine account in secrets database: %s: %s", nt_errstr(status), error_string));
+               talloc_free(error_string);
+       }
+       return status;
 }
 
 /**
@@ -348,9 +378,12 @@ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cr
  * @retval NTSTATUS error detailing any failure
  */
 NTSTATUS cli_credentials_set_krbtgt(struct cli_credentials *cred,
+                                   struct tevent_context *event_ctx,
                                    struct loadparm_context *lp_ctx)
 {
+       NTSTATUS status;
        char *filter;
+       char *error_string;
        /* Bleh, nasty recursion issues: We are setting a machine
         * account here, so we don't want the 'pending' flag around
         * any more */
@@ -358,22 +391,30 @@ NTSTATUS cli_credentials_set_krbtgt(struct cli_credentials *cred,
        filter = talloc_asprintf(cred, SECRETS_KRBTGT_SEARCH,
                                       cli_credentials_get_realm(cred),
                                       cli_credentials_get_domain(cred));
-       return cli_credentials_set_secrets(cred, lp_ctx, NULL, 
-                                          SECRETS_PRINCIPALS_DN,
-                                          filter);
+       status = cli_credentials_set_secrets(cred, event_ctx, lp_ctx, NULL,
+                                            SECRETS_PRINCIPALS_DN,
+                                            filter, &error_string);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(1, ("Could not find krbtgt (master Kerberos) account in secrets database: %s: %s", nt_errstr(status), error_string));
+               talloc_free(error_string);
+       }
+       return status;
 }
 
 /**
- * Fill in credentials for the machine trust account, from the secrets database.
+ * Fill in credentials for a particular prinicpal, from the secrets database.
  * 
  * @param cred Credentials structure to fill in
  * @retval NTSTATUS error detailing any failure
  */
 _PUBLIC_ NTSTATUS cli_credentials_set_stored_principal(struct cli_credentials *cred,
+                                                      struct tevent_context *event_ctx,
                                              struct loadparm_context *lp_ctx,
                                              const char *serviceprincipal)
 {
+       NTSTATUS status;
        char *filter;
+       char *error_string;
        /* Bleh, nasty recursion issues: We are setting a machine
         * account here, so we don't want the 'pending' flag around
         * any more */
@@ -382,8 +423,13 @@ _PUBLIC_ NTSTATUS cli_credentials_set_stored_principal(struct cli_credentials *c
                                 cli_credentials_get_realm(cred),
                                 cli_credentials_get_domain(cred),
                                 serviceprincipal);
-       return cli_credentials_set_secrets(cred, lp_ctx, NULL, 
-                                          SECRETS_PRINCIPALS_DN, filter);
+       status = cli_credentials_set_secrets(cred, event_ctx, lp_ctx, NULL,
+                                            SECRETS_PRINCIPALS_DN, filter,
+                                            &error_string);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(1, ("Could not find %s principal in secrets database: %s: %s", serviceprincipal, nt_errstr(status), error_string));
+       }
+       return status;
 }
 
 /**