1 /*
2    Unix SMB/CIFS implementation.
3    Copyright (C) Andrew Tridgell 1992-2001
4    Copyright (C) Andrew Bartlett      2002
5    Copyright (C) Rafal Szczesniak     2002
6    Copyright (C) Tim Potter           2001
7    Copyright (C) Jelmer Vernooij	  2005
8 
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23 
24 /* the Samba secrets database stores any generated, private information
25    such as the local SID and machine trust password */
26 
27 #include "includes.h"
28 #include "lib/tdb/include/tdb.h"
29 #include "lib/util/util_tdb.h"
30 #include "lib/samba3/samba3.h"
31 #include "system/filesys.h"
32 #include "librpc/gen_ndr/security.h"
33 #include "auth/credentials/credentials.h"
34 
35 /**
36  * Unpack SID into a pointer
37  *
38  * @param pack_buf pointer to buffer with packed representation
39  * @param bufsize size of the buffer
40  * @param sid pointer to sid structure to be filled with unpacked data
41  *
42  * @return size of structure unpacked from buffer
43  **/
tdb_sid_unpack(TDB_CONTEXT * tdb,char * pack_buf,int bufsize,struct dom_sid * sid)44 static size_t tdb_sid_unpack(TDB_CONTEXT *tdb, char* pack_buf, int bufsize, struct dom_sid* sid)
45 {
46 	int idx, len = 0;
47 
48 	if (!sid || !pack_buf) return -1;
49 
50 	len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "bb",
51 	                  &sid->sid_rev_num, &sid->num_auths);
52 
53 	for (idx = 0; idx < 6; idx++) {
54 		len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "b", &sid->id_auth[idx]);
55 	}
56 
57 	for (idx = 0; idx < 15; idx++) {
58 		len += tdb_unpack(tdb, pack_buf + len, bufsize - len, "d", &sid->sub_auths[idx]);
59 	}
60 
61 	return len;
62 }
63 
secrets_find_domain(TALLOC_CTX * ctx,struct samba3_secrets * db,const char * key)64 static struct samba3_domainsecrets *secrets_find_domain(TALLOC_CTX *ctx, struct samba3_secrets *db, const char *key)
65 {
66 	int i;
67 
68 	for (i = 0; i < db->domain_count; i++)
69 	{
70 		if (!strcasecmp_m(db->domains[i].name, key))
71 			return &db->domains[i];
72 	}
73 
74 	db->domains = talloc_realloc(ctx, db->domains, struct samba3_domainsecrets, db->domain_count+1);
75 	ZERO_STRUCT(db->domains[db->domain_count]);
76 	db->domains[db->domain_count].name = talloc_strdup(db->domains, key);
77 
78 	db->domain_count++;
79 
80 	return &db->domains[db->domain_count-1];
81 }
82 
ipc_password(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)83 static NTSTATUS ipc_password (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
84 {
85 	cli_credentials_set_password(db->ipc_cred, (const char *)vbuf.dptr, CRED_SPECIFIED);
86 	return NT_STATUS_OK;
87 }
88 
ipc_username(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)89 static NTSTATUS ipc_username (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
90 {
91 	cli_credentials_set_username(db->ipc_cred, (const char *)vbuf.dptr, CRED_SPECIFIED);
92 	return NT_STATUS_OK;
93 }
94 
ipc_domain(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)95 static NTSTATUS ipc_domain (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
96 {
97 	cli_credentials_set_domain(db->ipc_cred, (const char *)vbuf.dptr, CRED_SPECIFIED);
98 	return NT_STATUS_OK;
99 }
100 
domain_sid(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)101 static NTSTATUS domain_sid (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
102 {
103 	struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
104 	domainsec->sid.sub_auths = talloc_array(ctx, uint32_t, 15);
105 	tdb_sid_unpack(tdb, (char *)vbuf.dptr, vbuf.dsize, &domainsec->sid);
106 	return NT_STATUS_OK;
107 }
108 
domain_guid(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)109 static NTSTATUS domain_guid (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
110 {
111 	struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
112 	memcpy(&domainsec->guid, vbuf.dptr, vbuf.dsize);
113 	return NT_STATUS_OK;
114 }
115 
ldap_bind_pw(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)116 static NTSTATUS ldap_bind_pw (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
117 {
118 	struct samba3_ldappw pw;
119 	pw.dn = talloc_strdup(ctx, key);
120 	pw.password = talloc_strdup(ctx, (const char *)vbuf.dptr);
121 
122 	db->ldappws = talloc_realloc(ctx, db->ldappws, struct samba3_ldappw, db->ldappw_count+1);
123 	db->ldappws[db->ldappw_count] = pw;
124 	db->ldappw_count++;
125 	return NT_STATUS_OK;
126 }
127 
afs_keyfile(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)128 static NTSTATUS afs_keyfile (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
129 {
130 	struct samba3_afs_keyfile keyfile;
131 	memcpy(&keyfile, vbuf.dptr, vbuf.dsize);
132 	keyfile.cell = talloc_strdup(ctx, key);
133 
134 	db->afs_keyfiles = talloc_realloc(ctx, db->afs_keyfiles, struct samba3_afs_keyfile, db->afs_keyfile_count+1);
135 	db->afs_keyfiles[db->afs_keyfile_count] = keyfile;
136 	db->afs_keyfile_count++;
137 
138 	return NT_STATUS_OK;
139 }
140 
machine_sec_channel_type(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)141 static NTSTATUS machine_sec_channel_type (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
142 {
143 	struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
144 
145 	domainsec->sec_channel_type = IVAL(vbuf.dptr, 0);
146 	return NT_STATUS_OK;
147 }
148 
machine_last_change_time(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)149 static NTSTATUS machine_last_change_time (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
150 {
151 	struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
152 	domainsec->last_change_time = IVAL(vbuf.dptr, 0);
153 	return NT_STATUS_OK;
154 }
155 
machine_password(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)156 static NTSTATUS machine_password (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
157 {
158 	struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
159 	domainsec->plaintext_pw = talloc_strdup(ctx, (const char *)vbuf.dptr);
160 	return NT_STATUS_OK;
161 }
162 
machine_acc(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)163 static NTSTATUS machine_acc (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
164 {
165 	struct samba3_domainsecrets *domainsec = secrets_find_domain(ctx, db, key);
166 
167 	memcpy(&domainsec->hash_pw, vbuf.dptr, vbuf.dsize);
168 
169 	return NT_STATUS_OK;
170 }
171 
random_seed(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)172 static NTSTATUS random_seed (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
173 {
174 	/* Ignore */
175 	return NT_STATUS_OK;
176 }
177 
domtrust_acc(TDB_CONTEXT * tdb,const char * key,TDB_DATA vbuf,TALLOC_CTX * ctx,struct samba3_secrets * db)178 static NTSTATUS domtrust_acc (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db)
179 {
180 	int idx, len = 0;
181 	struct samba3_trusted_dom_pass pass;
182 	int pass_len;
183 
184 	if (!vbuf.dptr)
185 		return NT_STATUS_UNSUCCESSFUL;
186 
187 	/* unpack unicode domain name and plaintext password */
188 	len += tdb_unpack(tdb, (char *)vbuf.dptr, vbuf.dsize - len, "d", &pass.uni_name_len);
189 
190 	for (idx = 0; idx < 32; idx++)
191 		len +=  tdb_unpack(tdb, (char *)(vbuf.dptr + len), vbuf.dsize - len, "w", &pass.uni_name[idx]);
192 
193 	len += tdb_unpack(tdb, (char *)(vbuf.dptr + len), vbuf.dsize - len, "d", &pass_len);
194 	pass.pass = talloc_strdup(ctx, (char *)(vbuf.dptr+len));
195 	len += strlen((const char *)vbuf.dptr)+1;
196 	len += tdb_unpack(tdb, (char *)(vbuf.dptr + len), vbuf.dsize - len, "d", &pass.mod_time);
197 
198 	pass.domain_sid.sub_auths = talloc_array(ctx, uint32_t, 15);
199 	/* unpack domain sid */
200 	len += tdb_sid_unpack(tdb, (char *)(vbuf.dptr + len), vbuf.dsize - len, &pass.domain_sid);
201 
202 	/* FIXME: Add to list */
203 
204 	return NT_STATUS_OK;
205 }
206 
207 static const struct {
208 	const char *prefix;
209 	NTSTATUS (*handler) (TDB_CONTEXT *tdb, const char *key, TDB_DATA vbuf, TALLOC_CTX *ctx, struct samba3_secrets *db);
210 } secrets_handlers[] = {
211 	{ "SECRETS/AUTH_PASSWORD", ipc_password },
212 	{ "SECRETS/AUTH_DOMAIN", ipc_domain },
213 	{ "SECRETS/AUTH_USER", ipc_username },
214 	{ "SECRETS/SID/", domain_sid },
215 	{ "SECRETS/DOMGUID/", domain_guid },
216 	{ "SECRETS/LDAP_BIND_PW/", ldap_bind_pw },
217 	{ "SECRETS/AFS_KEYFILE/", afs_keyfile },
218 	{ "SECRETS/MACHINE_SEC_CHANNEL_TYPE/", machine_sec_channel_type },
219 	{ "SECRETS/MACHINE_LAST_CHANGE_TIME/", machine_last_change_time },
220 	{ "SECRETS/MACHINE_PASSWORD/", machine_password },
221 	{ "SECRETS/$MACHINE.ACC/", machine_acc },
222 	{ "SECRETS/$DOMTRUST.ACC/", domtrust_acc },
223 	{ "INFO/random_seed", random_seed },
224 };
225 
226 
samba3_read_secrets(const char * fname,TALLOC_CTX * ctx,struct samba3_secrets * db)227 NTSTATUS samba3_read_secrets(const char *fname, TALLOC_CTX *ctx, struct samba3_secrets *db)
228 {
229 	TDB_CONTEXT *tdb = tdb_open(fname, 0, TDB_DEFAULT, O_RDONLY, 0600);
230 	TDB_DATA kbuf, vbuf;
231 
232 	if (!tdb) {
233 		DEBUG(0,("Failed to open %s\n", fname));
234 		return NT_STATUS_UNSUCCESSFUL;
235 	}
236 
237 	ZERO_STRUCTP(db);
238 
239 	db->ipc_cred = cli_credentials_init(ctx);
240 
241 	for (kbuf = tdb_firstkey(tdb); kbuf.dptr; kbuf = tdb_nextkey(tdb, kbuf))
242 	{
243 		int i;
244 		char *key;
245 		vbuf = tdb_fetch(tdb, kbuf);
246 
247 		for (i = 0; secrets_handlers[i].prefix; i++) {
248 			if (!strncmp((const char *)kbuf.dptr, secrets_handlers[i].prefix, strlen(secrets_handlers[i].prefix))) {
249 				key = talloc_strndup(ctx, (const char *)(kbuf.dptr+strlen(secrets_handlers[i].prefix)), kbuf.dsize-strlen(secrets_handlers[i].prefix));
250 				secrets_handlers[i].handler(tdb, key, vbuf, ctx, db);
251 				talloc_free(key);
252 				break;
253 			}
254 		}
255 
256 		if (!secrets_handlers[i].prefix) {
257 			DEBUG(0, ("Unable to find handler for string %s\n", kbuf.dptr));
258 		}
259 	}
260 
261 	tdb_close(tdb);
262 
263 	return NT_STATUS_OK;
264 }
265