docs: fix a typo in history file
[bbaumbach/samba-autobuild/.git] / source3 / passdb / secrets.c
index b673ad12a4984f4a17a4231ce4478a9e3432fb06..10692d6588b76e6d3f293afe73da515d15b22169 100644 (file)
    such as the local SID and machine trust password */
 
 #include "includes.h"
+#include "system/filesys.h"
 #include "../libcli/auth/libcli_auth.h"
 #include "librpc/gen_ndr/ndr_secrets.h"
+#include "secrets.h"
+#include "dbwrap/dbwrap.h"
+#include "dbwrap/dbwrap_open.h"
+#include "../libcli/security/security.h"
+#include "util_tdb.h"
+#include "auth/credentials/credentials.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_PASSDB
 
 static struct db_context *db_ctx;
 
-/**
- * Use a TDB to store an incrementing random seed.
- *
- * Initialised to the current pid, the very first time Samba starts,
- * and incremented by one each time it is needed.
- *
- * @note Not called by systems with a working /dev/urandom.
- */
-static void get_rand_seed(void *userdata, int *new_seed)
-{
-       *new_seed = sys_getpid();
-       if (db_ctx) {
-               dbwrap_trans_change_int32_atomic(db_ctx, "INFO/random_seed",
-                                                new_seed, 1);
-       }
-}
-
-/* open up the secrets database */
-bool secrets_init(void)
+/* open up the secrets database with specified private_dir path */
+bool secrets_init_path(const char *private_dir)
 {
        char *fname = NULL;
-       unsigned char dummy;
+       TALLOC_CTX *frame;
 
-       if (db_ctx != NULL)
+       if (db_ctx != NULL) {
                return True;
+       }
 
-       fname = talloc_asprintf(talloc_tos(), "%s/secrets.tdb",
-                               lp_private_dir());
+       if (private_dir == NULL) {
+               return False;
+       }
+
+       frame = talloc_stackframe();
+       fname = talloc_asprintf(frame, "%s/secrets.tdb", private_dir);
        if (fname == NULL) {
-               return false;
+               TALLOC_FREE(frame);
+               return False;
        }
 
        db_ctx = db_open(NULL, fname, 0,
-                        TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+                        TDB_DEFAULT, O_RDWR|O_CREAT, 0600,
+                        DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
 
        if (db_ctx == NULL) {
                DEBUG(0,("Failed to open %s\n", fname));
-               TALLOC_FREE(fname);
+               TALLOC_FREE(frame);
                return False;
        }
 
-       TALLOC_FREE(fname);
-
-       /**
-        * Set a reseed function for the crypto random generator
-        *
-        * This avoids a problem where systems without /dev/urandom
-        * could send the same challenge to multiple clients
-        */
-       set_rand_reseed_callback(get_rand_seed, NULL);
-
-       /* Ensure that the reseed is done now, while we are root, etc */
-       generate_random_buffer(&dummy, sizeof(dummy));
-
+       TALLOC_FREE(frame);
        return True;
 }
 
+/* open up the secrets database */
+bool secrets_init(void)
+{
+       return secrets_init_path(lp_private_dir());
+}
+
 struct db_context *secrets_db_ctx(void)
 {
        if (!secrets_init()) {
@@ -112,20 +103,32 @@ void *secrets_fetch(const char *key, size_t *size)
 {
        TDB_DATA dbuf;
        void *result;
+       NTSTATUS status;
 
        if (!secrets_init()) {
                return NULL;
        }
 
-       if (db_ctx->fetch(db_ctx, talloc_tos(), string_tdb_data(key),
-                         &dbuf) != 0) {
+       status = dbwrap_fetch(db_ctx, talloc_tos(), string_tdb_data(key),
+                             &dbuf);
+       if (!NT_STATUS_IS_OK(status)) {
                return NULL;
        }
 
-       result = memdup(dbuf.dptr, dbuf.dsize);
+       result = smb_memdup(dbuf.dptr, dbuf.dsize);
        if (result == NULL) {
                return NULL;
        }
+       /*
+        * secrets_fetch() is a generic code and may be used for sensitive data,
+        * so clear the local dbuf.dptr memory via BURN_PTR_SIZE().
+        * The future plan is to convert secrets_fetch() to talloc.
+        * That would improve performance via:
+        * - avoid smb_memdup() above, instead directly return dbuf.dptr
+        * - BURN_PTR_SIZE() will be done not here but in the caller and only
+        *   if the caller asks for sensitive data.
+        */
+       BURN_PTR_SIZE(dbuf.dptr, dbuf.dsize);
        TALLOC_FREE(dbuf.dptr);
 
        if (size) {
@@ -146,15 +149,58 @@ bool secrets_store(const char *key, const void *data, size_t size)
        }
 
        status = dbwrap_trans_store(db_ctx, string_tdb_data(key),
-                                   make_tdb_data((const uint8 *)data, size),
+                                   make_tdb_data((const uint8_t *)data, size),
                                    TDB_REPLACE);
        return NT_STATUS_IS_OK(status);
 }
 
+bool secrets_store_creds(struct cli_credentials *creds)
+{
+       const char *p = NULL;
+       bool ok;
+
+       p = cli_credentials_get_username(creds);
+       if (p == NULL) {
+               return false;
+       }
+
+       ok = secrets_store(SECRETS_AUTH_USER, p, strlen(p) + 1);
+       if (!ok) {
+               DBG_ERR("Failed storing auth user name\n");
+               return false;
+       }
+
+
+       p = cli_credentials_get_domain(creds);
+       if (p == NULL) {
+               return false;
+       }
+
+       ok = secrets_store(SECRETS_AUTH_DOMAIN, p, strlen(p) + 1);
+       if (!ok) {
+               DBG_ERR("Failed storing auth domain name\n");
+               return false;
+       }
+
+
+       p = cli_credentials_get_password(creds);
+       if (p == NULL) {
+               return false;
+       }
+
+       ok = secrets_store(SECRETS_AUTH_PASSWORD, p, strlen(p) + 1);
+       if (!ok) {
+               DBG_ERR("Failed storing auth password\n");
+               return false;
+       }
+
+       return true;
+}
+
 
 /* delete a secets database entry
  */
-bool secrets_delete(const char *key)
+bool secrets_delete_entry(const char *key)
 {
        NTSTATUS status;
        if (!secrets_init()) {
@@ -166,29 +212,23 @@ bool secrets_delete(const char *key)
        return NT_STATUS_IS_OK(status);
 }
 
-bool secrets_store_local_schannel_key(uint8_t schannel_key[16])
-{
-       return secrets_store(SECRETS_LOCAL_SCHANNEL_KEY, schannel_key, 16);
-}
-
-bool secrets_fetch_local_schannel_key(uint8_t schannel_key[16])
+/*
+ * Deletes the key if it exists.
+ */
+bool secrets_delete(const char *key)
 {
-       size_t size = 0;
-       uint8_t *key;
+       bool exists;
 
-       key = (uint8_t *)secrets_fetch(SECRETS_LOCAL_SCHANNEL_KEY, &size);
-       if (key == NULL) {
+       if (!secrets_init()) {
                return false;
        }
 
-       if (size != 16) {
-               SAFE_FREE(key);
-               return false;
+       exists = dbwrap_exists(db_ctx, string_tdb_data(key));
+       if (!exists) {
+               return true;
        }
 
-       memcpy(schannel_key, key, 16);
-       SAFE_FREE(key);
-       return true;
+       return secrets_delete_entry(key);
 }
 
 /**
@@ -232,11 +272,17 @@ bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
        /* unpack trusted domain password */
        ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &pass,
                        (ndr_pull_flags_fn_t)ndr_pull_TRUSTED_DOM_PASS);
+
+       /* This blob is NOT talloc based! */
+       BURN_FREE(blob.data, blob.length);
+
        if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                return false;
        }
 
-       SAFE_FREE(blob.data);
+       if (pass.pass != NULL) {
+               talloc_keep_secret(discard_const_p(char, pass.pass));
+       }
 
        /* the trust's password */
        if (pwd) {
@@ -297,7 +343,8 @@ bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
 
        ret = secrets_store(trustdom_keystr(domain), blob.data, blob.length);
 
-       data_blob_free(&blob);
+       /* This blob is talloc based. */
+       data_blob_clear_free(&blob);
 
        return ret;
 }
@@ -308,7 +355,7 @@ bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
 
 bool trusted_domain_password_delete(const char *domain)
 {
-       return secrets_delete(trustdom_keystr(domain));
+       return secrets_delete_entry(trustdom_keystr(domain));
 }
 
 bool secrets_store_ldap_pw(const char* dn, char* pw)
@@ -347,147 +394,14 @@ bool fetch_ldap_pw(char **dn, char** pw)
        *pw=(char *)secrets_fetch(key, &size);
        SAFE_FREE(key);
 
-       if (!size) {
-               /* Upgrade 2.2 style entry */
-               char *p;
-               char* old_style_key = SMB_STRDUP(*dn);
-               char *data;
-               fstring old_style_pw;
-
-               if (!old_style_key) {
-                       DEBUG(0, ("fetch_ldap_pw: strdup failed!\n"));
-                       return False;
-               }
-
-               for (p=old_style_key; *p; p++)
-                       if (*p == ',') *p = '/';
-
-               data=(char *)secrets_fetch(old_style_key, &size);
-               if ((data == NULL) || (size < sizeof(old_style_pw))) {
-                       DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
-                       SAFE_FREE(old_style_key);
-                       SAFE_FREE(*dn);
-                       SAFE_FREE(data);
-                       return False;
-               }
-
-               size = MIN(size, sizeof(fstring)-1);
-               strncpy(old_style_pw, data, size);
-               old_style_pw[size] = 0;
-
-               SAFE_FREE(data);
-
-               if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
-                       DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
-                       SAFE_FREE(old_style_key);
-                       SAFE_FREE(*dn);
-                       return False;
-               }
-               if (!secrets_delete(old_style_key)) {
-                       DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
-               }
-
-               SAFE_FREE(old_style_key);
-
-               *pw = smb_xstrdup(old_style_pw);
-       }
-
-       return True;
-}
-
-/**
- * Get trusted domains info from secrets.tdb.
- **/
-
-struct list_trusted_domains_state {
-       uint32 num_domains;
-       struct trustdom_info **domains;
-};
-
-static int list_trusted_domain(struct db_record *rec, void *private_data)
-{
-       const size_t prefix_len = strlen(SECRETS_DOMTRUST_ACCT_PASS);
-       struct TRUSTED_DOM_PASS pass;
-       enum ndr_err_code ndr_err;
-       DATA_BLOB blob;
-       struct trustdom_info *dom_info;
-
-       struct list_trusted_domains_state *state =
-               (struct list_trusted_domains_state *)private_data;
-
-       if ((rec->key.dsize < prefix_len)
-           || (strncmp((char *)rec->key.dptr, SECRETS_DOMTRUST_ACCT_PASS,
-                       prefix_len) != 0)) {
-               return 0;
-       }
-
-       blob = data_blob_const(rec->value.dptr, rec->value.dsize);
-
-       ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &pass,
-                       (ndr_pull_flags_fn_t)ndr_pull_TRUSTED_DOM_PASS);
-       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+       if (*pw == NULL || size == 0 || (*pw)[size-1] != '\0') {
+               DBG_ERR("No valid password for %s\n", *dn);
+               BURN_FREE_STR(*pw);
+               SAFE_FREE(*dn);
                return false;
        }
 
-       if (pass.domain_sid.num_auths != 4) {
-               DEBUG(0, ("SID %s is not a domain sid, has %d "
-                         "auths instead of 4\n",
-                         sid_string_dbg(&pass.domain_sid),
-                         pass.domain_sid.num_auths));
-               return 0;
-       }
-
-       if (!(dom_info = TALLOC_P(state->domains, struct trustdom_info))) {
-               DEBUG(0, ("talloc failed\n"));
-               return 0;
-       }
-
-       dom_info->name = talloc_strdup(dom_info, pass.uni_name);
-       if (!dom_info->name) {
-               TALLOC_FREE(dom_info);
-               return 0;
-       }
-
-       sid_copy(&dom_info->sid, &pass.domain_sid);
-
-       ADD_TO_ARRAY(state->domains, struct trustdom_info *, dom_info,
-                    &state->domains, &state->num_domains);
-
-       if (state->domains == NULL) {
-               state->num_domains = 0;
-               return -1;
-       }
-       return 0;
-}
-
-NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
-                                struct trustdom_info ***domains)
-{
-       struct list_trusted_domains_state state;
-
-       secrets_init();
-
-       if (db_ctx == NULL) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
-
-       state.num_domains = 0;
-
-       /*
-        * Make sure that a talloc context for the trustdom_info structs
-        * exists
-        */
-
-       if (!(state.domains = TALLOC_ARRAY(
-                     mem_ctx, struct trustdom_info *, 1))) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       db_ctx->traverse_read(db_ctx, list_trusted_domain, (void *)&state);
-
-       *num_domains = state.num_domains;
-       *domains = state.domains;
-       return NT_STATUS_OK;
+       return true;
 }
 
 /*******************************************************************************
@@ -516,7 +430,7 @@ bool secrets_fetch_afs_key(const char *cell, struct afs_key *result)
        fstring key;
        struct afs_keyfile *keyfile;
        size_t size = 0;
-       uint32 i;
+       uint32_t i;
 
        slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
 
@@ -526,14 +440,14 @@ bool secrets_fetch_afs_key(const char *cell, struct afs_key *result)
                return False;
 
        if (size != sizeof(struct afs_keyfile)) {
-               SAFE_FREE(keyfile);
+               BURN_FREE(keyfile, sizeof(*keyfile));
                return False;
        }
 
        i = ntohl(keyfile->nkeys);
 
        if (i > SECRETS_AFS_MAXKEYS) {
-               SAFE_FREE(keyfile);
+               BURN_FREE(keyfile, sizeof(*keyfile));
                return False;
        }
 
@@ -541,7 +455,7 @@ bool secrets_fetch_afs_key(const char *cell, struct afs_key *result)
 
        result->kvno = ntohl(result->kvno);
 
-       SAFE_FREE(keyfile);
+       BURN_FREE(keyfile, sizeof(*keyfile));
 
        return True;
 }
@@ -565,17 +479,24 @@ void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
 
        if (*username && **username) {
 
-               if (!*domain || !**domain)
+               if (!*domain || !**domain) {
+                       SAFE_FREE(*domain);
                        *domain = smb_xstrdup(lp_workgroup());
+               }
 
-               if (!*password || !**password)
+               if (!*password || !**password) {
+                       BURN_FREE_STR(*password);
                        *password = smb_xstrdup("");
+               }
 
                DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
                          *domain, *username));
 
        } else {
                DEBUG(3, ("IPC$ connections done anonymously\n"));
+               SAFE_FREE(*username);
+               SAFE_FREE(*domain);
+               BURN_FREE_STR(*password);
                *username = smb_xstrdup("");
                *domain = smb_xstrdup("");
                *password = smb_xstrdup("");
@@ -598,22 +519,6 @@ bool secrets_store_generic(const char *owner, const char *key, const char *secre
        return ret;
 }
 
-bool secrets_delete_generic(const char *owner, const char *key)
-{
-       char *tdbkey = NULL;
-       bool ret;
-
-       if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
-               DEBUG(0, ("asprintf failed!\n"));
-               return False;
-       }
-
-       ret = secrets_delete(tdbkey);
-
-       SAFE_FREE(tdbkey);
-       return ret;
-}
-
 /*******************************************************************
  Find the ldap password.
 ******************************************************************/