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()) {
{
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) {
}
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()) {
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);
}
/**
/* 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) {
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;
}
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)
*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;
}
/*******************************************************************************
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);
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;
}
result->kvno = ntohl(result->kvno);
- SAFE_FREE(keyfile);
+ BURN_FREE(keyfile, sizeof(*keyfile));
return True;
}
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("");
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.
******************************************************************/