mirror of
https://github.com/samba-team/samba.git
synced 2025-02-28 01:58:17 +03:00
r9589: Support reading secrets tdb
(This used to be commit dd15131b5219ecf0d09329c0de37c426b9147f45)
This commit is contained in:
parent
b873c1789f
commit
cdf218e270
@ -278,4 +278,5 @@ struct samba3_groupdb;
|
||||
struct samba3_winsdb_entry;
|
||||
struct samba3_policy;
|
||||
struct samba3_regdb;
|
||||
struct samba3_secrets;
|
||||
struct samba3;
|
||||
|
@ -9,8 +9,8 @@ ADD_OBJ_FILES = \
|
||||
lib/samba3/winsdb.o \
|
||||
lib/samba3/samba3.o \
|
||||
lib/samba3/group.o \
|
||||
lib/samba3/registry.o
|
||||
# lib/samba3/secrets.o
|
||||
lib/samba3/registry.o \
|
||||
lib/samba3/secrets.o
|
||||
# End SUBSYSTEM LIBSAMBA3
|
||||
################################################
|
||||
|
||||
|
@ -51,5 +51,9 @@ struct samba3 *samba3_read(const char *libdir, TALLOC_CTX *ctx)
|
||||
samba3_read_regdb(dbfile, ctx, &ret->registry);
|
||||
SAFE_FREE(dbfile);
|
||||
|
||||
asprintf(&dbfile, "%s/secrets.tdb", libdir);
|
||||
samba3_read_secrets(dbfile, ctx, &ret->secrets);
|
||||
SAFE_FREE(dbfile);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -137,6 +137,53 @@ struct samba3_regdb
|
||||
struct samba3_regkey *keys;
|
||||
};
|
||||
|
||||
struct samba3_secrets
|
||||
{
|
||||
struct cli_credentials *ipc_cred;
|
||||
|
||||
uint32_t ldappw_count;
|
||||
struct samba3_ldappw
|
||||
{
|
||||
char *dn;
|
||||
char *password;
|
||||
} *ldappws;
|
||||
|
||||
uint32_t domain_count;
|
||||
struct samba3_domainsecrets
|
||||
{
|
||||
char *name;
|
||||
struct dom_sid sid;
|
||||
struct GUID guid;
|
||||
char *plaintext_pw;
|
||||
time_t last_change_time;
|
||||
struct {
|
||||
uint8_t hash[16];
|
||||
time_t mod_time;
|
||||
} hash_pw;;
|
||||
int sec_channel_type;
|
||||
} *domains;
|
||||
|
||||
uint32_t trusted_domain_count;
|
||||
struct samba3_trusted_dom_pass {
|
||||
uint32_t uni_name_len;
|
||||
const char *uni_name[32]; /* unicode domain name */
|
||||
const char *pass; /* trust relationship's password */
|
||||
time_t mod_time;
|
||||
struct dom_sid domain_sid; /* remote domain's sid */
|
||||
} *trusted_domains;
|
||||
|
||||
uint32_t afs_keyfile_count;
|
||||
|
||||
struct samba3_afs_keyfile {
|
||||
uint32_t nkeys;
|
||||
struct {
|
||||
uint32_t kvno;
|
||||
char key[8];
|
||||
} entry[8];
|
||||
char *cell;
|
||||
} *afs_keyfiles;
|
||||
};
|
||||
|
||||
struct samba3
|
||||
{
|
||||
uint32_t winsdb_count;
|
||||
@ -145,6 +192,7 @@ struct samba3
|
||||
uint32_t samaccount_count;
|
||||
struct samba3_samaccount *samaccounts;
|
||||
|
||||
struct samba3_secrets secrets;
|
||||
struct samba3_groupdb group;
|
||||
struct samba3_idmapdb idmap;
|
||||
struct samba3_policy policy;
|
||||
|
@ -24,52 +24,13 @@
|
||||
/* the Samba secrets database stores any generated, private information
|
||||
such as the local SID and machine trust password */
|
||||
|
||||
#define SECRETS_DOMAIN_SID "SECRETS/SID"
|
||||
#define SECRETS_DOMAIN_GUID "SECRETS/DOMGUID"
|
||||
#define SECRETS_LDAP_BIND_PW "SECRETS/LDAP_BIND_PW"
|
||||
#define SECRETS_MACHINE_ACCT_PASS "SECRETS/$MACHINE.ACC"
|
||||
#define SECRETS_DOMTRUST_ACCT_PASS "SECRETS/$DOMTRUST.ACC"
|
||||
#define SECRETS_MACHINE_PASSWORD "SECRETS/MACHINE_PASSWORD"
|
||||
#define SECRETS_MACHINE_LAST_CHANGE_TIME "SECRETS/MACHINE_LAST_CHANGE_TIME"
|
||||
#define SECRETS_MACHINE_SEC_CHANNEL_TYPE "SECRETS/MACHINE_SEC_CHANNEL_TYPE"
|
||||
#define SECRETS_AFS_KEYFILE "SECRETS/AFS_KEYFILE"
|
||||
#define SECRETS_AUTH_USER "SECRETS/AUTH_USER"
|
||||
#define SECRETS_AUTH_DOMAIN "SECRETS/AUTH_DOMAIN"
|
||||
#define SECRETS_AUTH_PASSWORD "SECRETS/AUTH_PASSWORD"
|
||||
|
||||
|
||||
#include "includes.h"
|
||||
#include "tdb.h"
|
||||
#include "lib/samba3/samba3.h"
|
||||
#include "system/filesys.h"
|
||||
#include "librpc/gen_ndr/ndr_security.h"
|
||||
#include "lib/tdb/include/tdbutil.h"
|
||||
|
||||
/* structure for storing machine account password
|
||||
(ie. when samba server is member of a domain */
|
||||
struct machine_acct_pass {
|
||||
uint8_t hash[16];
|
||||
time_t mod_time;
|
||||
};
|
||||
|
||||
#define SECRETS_AFS_MAXKEYS 8
|
||||
|
||||
struct afs_key {
|
||||
uint32_t kvno;
|
||||
char key[8];
|
||||
};
|
||||
|
||||
/*
|
||||
* storage structure for trusted domain
|
||||
*/
|
||||
typedef struct trusted_dom_pass {
|
||||
size_t uni_name_len;
|
||||
const char *uni_name[32]; /* unicode domain name */
|
||||
size_t pass_len;
|
||||
const char *pass; /* trust relationship's password */
|
||||
time_t mod_time;
|
||||
struct dom_sid domain_sid; /* remote domain's sid */
|
||||
} TRUSTED_DOM_PASS;
|
||||
|
||||
/**
|
||||
* Unpack SID into a pointer
|
||||
*
|
||||
@ -99,492 +60,197 @@ static size_t tdb_sid_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, stru
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpack TRUSTED_DOM_PASS passed by pointer
|
||||
*
|
||||
* @param pack_buf pointer to buffer with packed representation
|
||||
* @param bufsize size of the buffer
|
||||
* @param pass pointer to trusted domain password to be filled with unpacked data
|
||||
*
|
||||
* @return size of structure unpacked from buffer
|
||||
**/
|
||||
static size_t tdb_trusted_dom_pass_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, TRUSTED_DOM_PASS* pass)
|
||||
static struct samba3_domainsecrets *secrets_find_domain(TALLOC_CTX *ctx, struct samba3_secrets *db, const char *key)
|
||||
{
|
||||
int idx, len = 0;
|
||||
|
||||
if (!pack_buf || !pass) return -1;
|
||||
int i;
|
||||
|
||||
/* unpack unicode domain name and plaintext password */
|
||||
len += tdb_unpack(tdb, pack_buf, bufsize - len, "d", &pass->uni_name_len);
|
||||
|
||||
for (idx = 0; idx < 32; idx++)
|
||||
len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "w", &pass->uni_name[idx]);
|
||||
for (i = 0; i < db->domain_count; i++)
|
||||
{
|
||||
if (!StrCaseCmp(db->domains[i].name, key))
|
||||
return &db->domains[i];
|
||||
}
|
||||
|
||||
len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "dPd", &pass->pass_len, &pass->pass,
|
||||
&pass->mod_time);
|
||||
db->domains = talloc_realloc(ctx, db->domains, struct samba3_domainsecrets, db->domain_count+1);
|
||||
ZERO_STRUCT(db->domains[db->domain_count]);
|
||||
db->domains[db->domain_count].name = talloc_strdup(ctx, key);
|
||||
|
||||
db->domain_count++;
|
||||
|
||||
/* unpack domain sid */
|
||||
len += tdb_sid_unpack(tdb, pack_buf + len, bufsize - len, &pass->domain_sid);
|
||||
|
||||
return len;
|
||||
return &db->domains[db->domain_count-1];
|
||||
}
|
||||
|
||||
static NTSTATUS ipc_password (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
cli_credentials_set_password(db->ipc_cred, vbuf.dptr, CRED_SPECIFIED);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static TDB_CONTEXT *secrets_open(const char *fname)
|
||||
static NTSTATUS ipc_username (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
cli_credentials_set_username(db->ipc_cred, vbuf.dptr, CRED_SPECIFIED);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS ipc_domain (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
cli_credentials_set_domain(db->ipc_cred, vbuf.dptr, CRED_SPECIFIED);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS domain_sid (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
|
||||
domainsec->sid.sub_auths = talloc_array(ctx, uint32_t, 15);
|
||||
tdb_sid_unpack(tdb, vbuf.dptr, vbuf.dsize, &domainsec->sid);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS domain_guid (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
|
||||
memcpy(&domainsec->guid, vbuf.dptr, vbuf.dsize);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS ldap_bind_pw (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
struct samba3_ldappw pw;
|
||||
pw.dn = talloc_strdup(ctx, key);
|
||||
pw.password = talloc_strdup(ctx, vbuf.dptr);
|
||||
|
||||
db->ldappws = talloc_realloc(ctx, db->ldappws, struct samba3_ldappw, db->ldappw_count+1);
|
||||
db->ldappws[db->ldappw_count] = pw;
|
||||
db->ldappw_count++;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS afs_keyfile (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
struct samba3_afs_keyfile keyfile;
|
||||
memcpy(&keyfile, vbuf.dptr, vbuf.dsize);
|
||||
keyfile.cell = talloc_strdup(ctx, key);
|
||||
|
||||
db->afs_keyfiles = talloc_realloc(ctx, db->afs_keyfiles, struct samba3_afs_keyfile, db->afs_keyfile_count+1);
|
||||
db->afs_keyfiles[db->afs_keyfile_count] = keyfile;
|
||||
db->afs_keyfile_count++;
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS machine_sec_channel_type (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
|
||||
|
||||
domainsec->sec_channel_type = IVAL(vbuf.dptr, 0);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS machine_last_change_time (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
|
||||
domainsec->last_change_time = IVAL(vbuf.dptr, 0);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS machine_password (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
|
||||
domainsec->plaintext_pw = talloc_strdup(ctx, vbuf.dptr);
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS machine_acc (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
|
||||
|
||||
memcpy(&domainsec->hash_pw, vbuf.dptr, vbuf.dsize);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS domtrust_acc (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
int idx, len = 0;
|
||||
struct samba3_trusted_dom_pass pass;
|
||||
int pass_len;
|
||||
|
||||
if (!vbuf.dptr)
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
|
||||
/* unpack unicode domain name and plaintext password */
|
||||
len += tdb_unpack(tdb, vbuf.dptr, vbuf.dsize - len, "d", &pass.uni_name_len);
|
||||
|
||||
for (idx = 0; idx < 32; idx++)
|
||||
len += tdb_unpack(tdb, vbuf.dptr + len, vbuf.dsize - len, "w", &pass.uni_name[idx]);
|
||||
|
||||
len += tdb_unpack(tdb, vbuf.dptr + len, vbuf.dsize - len, "d", &pass_len);
|
||||
pass.pass = talloc_strdup(ctx, vbuf.dptr+len);
|
||||
len += strlen(vbuf.dptr)+1;
|
||||
len += tdb_unpack(tdb, vbuf.dptr + len, vbuf.dsize - len, "d", &pass.mod_time);
|
||||
|
||||
pass.domain_sid.sub_auths = talloc_array(ctx, uint32_t, 15);
|
||||
/* unpack domain sid */
|
||||
len += tdb_sid_unpack(tdb, vbuf.dptr + len, vbuf.dsize - len, &pass.domain_sid);
|
||||
|
||||
/* FIXME: Add to list */
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
const char *prefix;
|
||||
NTSTATUS (*handler) (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db);
|
||||
} secrets_handlers[] = {
|
||||
{ "SECRETS/AUTH_PASSWORD", ipc_password },
|
||||
{ "SECRETS/AUTH_DOMAIN", ipc_domain },
|
||||
{ "SECRETS/AUTH_USER", ipc_username },
|
||||
{ "SECRETS/SID/", domain_sid },
|
||||
{ "SECRETS/DOMGUID/", domain_guid },
|
||||
{ "SECRETS/LDAP_BIND_PW/", ldap_bind_pw },
|
||||
{ "SECRETS/AFS_KEYFILE/", afs_keyfile },
|
||||
{ "SECRETS/MACHINE_SEC_CHANNEL_TYPE/", machine_sec_channel_type },
|
||||
{ "SECRETS/MACHINE_LAST_CHANGE_TIME/", machine_last_change_time },
|
||||
{ "SECRETS/MACHINE_PASSWORD/", machine_password },
|
||||
{ "SECRETS/$MACHINE.ACC/", machine_acc },
|
||||
{ "SECRETS/$DOMTRUST.ACC/", domtrust_acc },
|
||||
};
|
||||
|
||||
|
||||
NTSTATUS samba3_read_secrets(const char *fname, TALLOC_CTX *ctx, struct samba3_secrets *db)
|
||||
{
|
||||
TDB_CONTEXT *tdb = tdb_open(fname, 0, TDB_DEFAULT, O_RDONLY, 0600);
|
||||
TDB_DATA kbuf, vbuf;
|
||||
|
||||
if (!tdb) {
|
||||
DEBUG(0,("Failed to open %s\n", fname));
|
||||
return NULL;
|
||||
return NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
return tdb;
|
||||
}
|
||||
|
||||
static BOOL secrets_fetch_domain_sid(TDB_CONTEXT *tdb, const char *domain, struct dom_sid *sid)
|
||||
{
|
||||
struct dom_sid *dyn_sid;
|
||||
TDB_DATA val;
|
||||
char *key;
|
||||
size_t size;
|
||||
|
||||
asprintf(&key, "%s/%s", SECRETS_DOMAIN_SID, domain);
|
||||
strupper_m(key);
|
||||
ZERO_STRUCTP(db);
|
||||
|
||||
val = tdb_fetch_bystring(tdb, key);
|
||||
/* FIXME: Convert val to dyn_sid */
|
||||
SAFE_FREE(key);
|
||||
|
||||
if (dyn_sid == NULL)
|
||||
return False;
|
||||
|
||||
if (size != sizeof(struct dom_sid))
|
||||
{
|
||||
SAFE_FREE(dyn_sid);
|
||||
return False;
|
||||
}
|
||||
|
||||
*sid = *dyn_sid;
|
||||
SAFE_FREE(dyn_sid);
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL secrets_fetch_domain_guid(TDB_CONTEXT *tdb, const char *domain, struct GUID *guid)
|
||||
{
|
||||
struct GUID *dyn_guid;
|
||||
char *key;
|
||||
TDB_DATA val;
|
||||
size_t size;
|
||||
|
||||
asprintf(&key, "%s/%s", SECRETS_DOMAIN_GUID, domain);
|
||||
strupper_m(key);
|
||||
val = tdb_fetch_bystring(tdb, key);
|
||||
|
||||
dyn_guid = (struct GUID *)val.dptr;
|
||||
|
||||
if (!dyn_guid) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if (val.dsize != sizeof(struct GUID))
|
||||
{
|
||||
DEBUG(1,("GUID size %d is wrong!\n", (int)size));
|
||||
SAFE_FREE(dyn_guid);
|
||||
return False;
|
||||
}
|
||||
|
||||
*guid = *dyn_guid;
|
||||
SAFE_FREE(dyn_guid);
|
||||
return True;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form a key for fetching the machine trust account password
|
||||
*
|
||||
* @param domain domain name
|
||||
*
|
||||
* @return stored password's key
|
||||
**/
|
||||
static char *trust_keystr(const char *domain)
|
||||
{
|
||||
char *keystr;
|
||||
|
||||
asprintf(&keystr, "%s/%s", SECRETS_MACHINE_ACCT_PASS, domain);
|
||||
strupper_m(keystr);
|
||||
|
||||
return keystr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Form a key for fetching a trusted domain password
|
||||
*
|
||||
* @param domain trusted domain name
|
||||
*
|
||||
* @return stored password's key
|
||||
**/
|
||||
static char *trustdom_keystr(const char *domain)
|
||||
{
|
||||
char *keystr;
|
||||
|
||||
asprintf(&keystr, "%s/%s", SECRETS_DOMTRUST_ACCT_PASS, domain);
|
||||
strupper_m(keystr);
|
||||
|
||||
return keystr;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Routine to get the trust account password for a domain.
|
||||
The user of this function must have locked the trust password file using
|
||||
the above secrets_lock_trust_account_password().
|
||||
************************************************************************/
|
||||
|
||||
static BOOL secrets_fetch_trust_account_password(TDB_CONTEXT *tdb,
|
||||
const char *domain, uint8_t ret_pwd[16],
|
||||
time_t *pass_last_set_time,
|
||||
uint32_t *channel)
|
||||
{
|
||||
struct machine_acct_pass *pass;
|
||||
char *plaintext;
|
||||
TDB_DATA val;
|
||||
|
||||
plaintext = secrets_fetch_machine_password(tdb, domain, pass_last_set_time,
|
||||
channel);
|
||||
if (plaintext) {
|
||||
DEBUG(4,("Using cleartext machine password\n"));
|
||||
E_md4hash(plaintext, ret_pwd);
|
||||
SAFE_FREE(plaintext);
|
||||
return True;
|
||||
}
|
||||
db->ipc_cred = cli_credentials_init(ctx);
|
||||
|
||||
val = tdb_fetch_bystring(tdb, trust_keystr(domain));
|
||||
if (!val.dptr) {
|
||||
DEBUG(5, ("tdb_fetch_bystring failed!\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (val.dsize != sizeof(*pass)) {
|
||||
DEBUG(0, ("secrets were of incorrect size!\n"));
|
||||
return False;
|
||||
}
|
||||
for (kbuf = tdb_firstkey(tdb); kbuf.dptr; kbuf = tdb_nextkey(tdb, kbuf))
|
||||
{
|
||||
int i;
|
||||
char *key;
|
||||
vbuf = tdb_fetch(tdb, kbuf);
|
||||
|
||||
pass = (struct machine_acct_pass *)val.dptr;
|
||||
|
||||
if (pass_last_set_time) *pass_last_set_time = pass->mod_time;
|
||||
memcpy(ret_pwd, pass->hash, 16);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Routine to get account password to trusted domain
|
||||
************************************************************************/
|
||||
|
||||
static BOOL secrets_fetch_trusted_domain_password(TDB_CONTEXT *tdb, const char *domain, char** pwd, struct dom_sid **sid, time_t *pass_last_set_time)
|
||||
{
|
||||
struct trusted_dom_pass pass;
|
||||
|
||||
/* unpacking structures */
|
||||
int pass_len = 0;
|
||||
TDB_DATA val;
|
||||
|
||||
ZERO_STRUCT(pass);
|
||||
|
||||
/* fetching trusted domain password structure */
|
||||
val = tdb_fetch_bystring(tdb, trustdom_keystr(domain));
|
||||
if (!val.dptr) {
|
||||
DEBUG(5, ("secrets_fetch failed!\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* unpack trusted domain password */
|
||||
pass_len = tdb_trusted_dom_pass_unpack(val.dptr, val.dsize, &pass);
|
||||
|
||||
if (pass_len != val.dsize) {
|
||||
DEBUG(5, ("Invalid secrets size. Unpacked data doesn't match trusted_dom_pass structure.\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* the trust's password */
|
||||
if (pwd) {
|
||||
*pwd = strdup(pass.pass);
|
||||
if (!*pwd) {
|
||||
return False;
|
||||
}
|
||||
}
|
||||
|
||||
/* last change time */
|
||||
if (pass_last_set_time) *pass_last_set_time = pass.mod_time;
|
||||
|
||||
/* domain sid */
|
||||
|
||||
*sid = dom_sid_dup(tdb, &pass.domain_sid);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/************************************************************************
|
||||
Routine to fetch the plaintext machine account password for a realm
|
||||
the password is assumed to be a null terminated ascii string
|
||||
************************************************************************/
|
||||
static char *secrets_fetch_machine_password(TDB_CONTEXT *tdb, const char *domain,
|
||||
time_t *pass_last_set_time,
|
||||
uint32_t *channel)
|
||||
{
|
||||
char *key = NULL;
|
||||
char *ret;
|
||||
TDB_DATA val;
|
||||
asprintf(&key, "%s/%s", SECRETS_MACHINE_PASSWORD, domain);
|
||||
strupper_m(key);
|
||||
val = tdb_fetch_bystring(tdb, key);
|
||||
SAFE_FREE(key);
|
||||
|
||||
if (pass_last_set_time) {
|
||||
asprintf(&key, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain);
|
||||
strupper_m(key);
|
||||
tdb_fetch_uint32(tdb, key, (uint32_t *)pass_last_set_time);
|
||||
SAFE_FREE(key);
|
||||
}
|
||||
|
||||
if (channel) {
|
||||
asprintf(&key, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, domain);
|
||||
strupper_m(key);
|
||||
tdb_fetch_uint32(tdb, key, channel);
|
||||
SAFE_FREE(key);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
find the ldap password
|
||||
******************************************************************/
|
||||
static BOOL fetch_ldap_pw(TDB_CONTEXT *tdb, const char *dn, char** pw)
|
||||
{
|
||||
char *key = NULL;
|
||||
size_t size;
|
||||
TDB_DATA val;
|
||||
|
||||
if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
|
||||
DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
|
||||
}
|
||||
|
||||
val = tdb_fetch_bystring(tdb, key);
|
||||
*pw = val.dptr;
|
||||
SAFE_FREE(key);
|
||||
|
||||
if (!size) {
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get trusted domains info from secrets.tdb.
|
||||
*
|
||||
* The linked list is allocated on the supplied talloc context, caller gets to destroy
|
||||
* when done.
|
||||
*
|
||||
* @param ctx Allocation context
|
||||
* @param enum_ctx Starting index, eg. we can start fetching at third
|
||||
* or sixth trusted domain entry. Zero is the first index.
|
||||
* Value it is set to is the enum context for the next enumeration.
|
||||
* @param num_domains Number of domain entries to fetch at one call
|
||||
* @param domains Pointer to array of trusted domain structs to be filled up
|
||||
*
|
||||
* @return nt status code of rpc response
|
||||
**/
|
||||
|
||||
static NTSTATUS secrets_get_trusted_domains(TDB_CONTEXT *tdb, TALLOC_CTX* ctx, int* enum_ctx, unsigned int max_num_domains,
|
||||
int *num_domains, struct samba3_trustdom ***domains)
|
||||
{
|
||||
TDB_LIST_NODE *keys, *k;
|
||||
struct samba3_trustdom *dom = NULL;
|
||||
char *pattern;
|
||||
unsigned int start_idx;
|
||||
uint32_t idx = 0;
|
||||
size_t size, packed_size = 0;
|
||||
fstring dom_name;
|
||||
char *packed_pass;
|
||||
struct trusted_dom_pass *pass = talloc(ctx, struct trusted_dom_pass);
|
||||
NTSTATUS status;
|
||||
|
||||
if (!pass) {
|
||||
DEBUG(0, ("talloc_zero failed!\n"));
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
*num_domains = 0;
|
||||
start_idx = *enum_ctx;
|
||||
|
||||
/* generate searching pattern */
|
||||
if (!(pattern = talloc_asprintf(ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS))) {
|
||||
DEBUG(0, ("secrets_get_trusted_domains: talloc_asprintf() failed!\n"));
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
DEBUG(5, ("secrets_get_trusted_domains: looking for %d domains, starting at index %d\n",
|
||||
max_num_domains, *enum_ctx));
|
||||
|
||||
*domains = talloc_zero_array(ctx, struct samba3_trustdom *, max_num_domains);
|
||||
|
||||
/* fetching trusted domains' data and collecting them in a list */
|
||||
keys = tdb_search_keys(tdb, pattern);
|
||||
|
||||
/*
|
||||
* if there's no keys returned ie. no trusted domain,
|
||||
* return "no more entries" code
|
||||
*/
|
||||
status = NT_STATUS_NO_MORE_ENTRIES;
|
||||
|
||||
/* searching for keys in secrets db -- way to go ... */
|
||||
for (k = keys; k; k = k->next) {
|
||||
char *secrets_key;
|
||||
|
||||
/* important: ensure null-termination of the key string */
|
||||
secrets_key = strndup(k->node_key.dptr, k->node_key.dsize);
|
||||
if (!secrets_key) {
|
||||
DEBUG(0, ("strndup failed!\n"));
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
packed_pass = secrets_fetch(tdb, secrets_key, &size);
|
||||
packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size, pass);
|
||||
/* packed representation isn't needed anymore */
|
||||
SAFE_FREE(packed_pass);
|
||||
|
||||
if (size != packed_size) {
|
||||
DEBUG(2, ("Secrets record %s is invalid!\n", secrets_key));
|
||||
continue;
|
||||
}
|
||||
|
||||
pull_ucs2_fstring(dom_name, pass->uni_name);
|
||||
DEBUG(18, ("Fetched secret record num %d.\nDomain name: %s, SID: %s\n",
|
||||
idx, dom_name, sid_string_static(&pass->domain_sid)));
|
||||
|
||||
SAFE_FREE(secrets_key);
|
||||
|
||||
if (idx >= start_idx && idx < start_idx + max_num_domains) {
|
||||
dom = talloc(ctx, struct samba3_trustdom);
|
||||
if (!dom) {
|
||||
/* free returned tdb record */
|
||||
return NT_STATUS_NO_MEMORY;
|
||||
for (i = 0; secrets_handlers[i].prefix; i++) {
|
||||
if (!strncmp(kbuf.dptr, secrets_handlers[i].prefix, strlen(secrets_handlers[i].prefix))) {
|
||||
key = talloc_strndup(ctx, kbuf.dptr+strlen(secrets_handlers[i].prefix), kbuf.dsize-strlen(secrets_handlers[i].prefix));
|
||||
secrets_handlers[i].handler(tdb, key, vbuf, ctx, db);
|
||||
talloc_free(key);
|
||||
break;
|
||||
}
|
||||
|
||||
/* copy domain sid */
|
||||
SMB_ASSERT(sizeof(dom->sid) == sizeof(pass->domain_sid));
|
||||
memcpy(&(dom->sid), &(pass->domain_sid), sizeof(dom->sid));
|
||||
|
||||
/* copy unicode domain name */
|
||||
dom->name = talloc_memdup(ctx, pass->uni_name,
|
||||
(strlen_w(pass->uni_name) + 1) * sizeof(smb_ucs2_t));
|
||||
|
||||
(*domains)[idx - start_idx] = dom;
|
||||
|
||||
DEBUG(18, ("Secret record is in required range.\n \
|
||||
start_idx = %d, max_num_domains = %d. Added to returned array.\n",
|
||||
start_idx, max_num_domains));
|
||||
|
||||
*enum_ctx = idx + 1;
|
||||
(*num_domains)++;
|
||||
|
||||
/* set proper status code to return */
|
||||
if (k->next) {
|
||||
/* there are yet some entries to enumerate */
|
||||
status = STATUS_MORE_ENTRIES;
|
||||
} else {
|
||||
/* this is the last entry in the whole enumeration */
|
||||
status = NT_STATUS_OK;
|
||||
}
|
||||
} else {
|
||||
DEBUG(18, ("Secret is outside the required range.\n \
|
||||
start_idx = %d, max_num_domains = %d. Not added to returned array\n",
|
||||
start_idx, max_num_domains));
|
||||
}
|
||||
|
||||
idx++;
|
||||
|
||||
if (!secrets_handlers[i].prefix) {
|
||||
DEBUG(0, ("Unable to find handler for string %s", kbuf.dptr));
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n", *num_domains));
|
||||
tdb_close(tdb);
|
||||
|
||||
/* free the results of searching the keys */
|
||||
tdb_search_list_free(keys);
|
||||
|
||||
return status;
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Fetch the current (highest) AFS key from secrets.tdb
|
||||
*******************************************************************************/
|
||||
static BOOL secrets_fetch_afs_key(TDB_CONTEXT *tdb, const char *cell, struct afs_key *result)
|
||||
{
|
||||
fstring key;
|
||||
struct afs_keyfile *keyfile;
|
||||
size_t size;
|
||||
uint32_t i;
|
||||
|
||||
slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
|
||||
|
||||
keyfile = (struct afs_keyfile *)secrets_fetch(tdb, key, &size);
|
||||
|
||||
if (keyfile == NULL)
|
||||
return False;
|
||||
|
||||
if (size != sizeof(struct afs_keyfile)) {
|
||||
SAFE_FREE(keyfile);
|
||||
return False;
|
||||
}
|
||||
|
||||
i = ntohl(keyfile->nkeys);
|
||||
|
||||
if (i > SECRETS_AFS_MAXKEYS) {
|
||||
SAFE_FREE(keyfile);
|
||||
return False;
|
||||
}
|
||||
|
||||
*result = keyfile->entry[i-1];
|
||||
|
||||
result->kvno = ntohl(result->kvno);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
When kerberos is not available, choose between anonymous or
|
||||
authenticated connections.
|
||||
|
||||
We need to use an authenticated connection if DCs have the
|
||||
RestrictAnonymous registry entry set > 0, or the "Additional
|
||||
restrictions for anonymous connections" set in the win2k Local
|
||||
Security Policy.
|
||||
|
||||
Caller to free() result in domain, username, password
|
||||
*******************************************************************************/
|
||||
static void secrets_fetch_ipc_userpass(TDB_CONTEXT *tdb, char **username, char **domain, char **password)
|
||||
{
|
||||
*username = secrets_fetch(tdb, SECRETS_AUTH_USER, NULL);
|
||||
*domain = secrets_fetch(tdb, SECRETS_AUTH_DOMAIN, NULL);
|
||||
*password = secrets_fetch(tdb, SECRETS_AUTH_PASSWORD, NULL);
|
||||
|
||||
if (*username && **username) {
|
||||
|
||||
if (!*domain || !**domain)
|
||||
*domain = smb_xstrdup(lp_workgroup());
|
||||
|
||||
if (!*password || !**password)
|
||||
*password = smb_xstrdup("");
|
||||
|
||||
DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
|
||||
*domain, *username));
|
||||
|
||||
} else {
|
||||
DEBUG(3, ("IPC$ connections done anonymously\n"));
|
||||
*username = smb_xstrdup("");
|
||||
*domain = smb_xstrdup("");
|
||||
*password = smb_xstrdup("");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user