Line data Source code
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 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : /* the Samba secrets database stores any generated, private information
23 : such as the local SID and machine trust password */
24 :
25 : #include "includes.h"
26 : #include "system/filesys.h"
27 : #include "../libcli/auth/libcli_auth.h"
28 : #include "librpc/gen_ndr/ndr_secrets.h"
29 : #include "secrets.h"
30 : #include "dbwrap/dbwrap.h"
31 : #include "dbwrap/dbwrap_open.h"
32 : #include "../libcli/security/security.h"
33 : #include "util_tdb.h"
34 : #include "auth/credentials/credentials.h"
35 :
36 : #undef DBGC_CLASS
37 : #define DBGC_CLASS DBGC_PASSDB
38 :
39 : static struct db_context *db_ctx;
40 :
41 : /* open up the secrets database with specified private_dir path */
42 208126 : bool secrets_init_path(const char *private_dir)
43 : {
44 208126 : char *fname = NULL;
45 7417 : TALLOC_CTX *frame;
46 :
47 208126 : if (db_ctx != NULL) {
48 182295 : return True;
49 : }
50 :
51 18478 : if (private_dir == NULL) {
52 0 : return False;
53 : }
54 :
55 18478 : frame = talloc_stackframe();
56 18478 : fname = talloc_asprintf(frame, "%s/secrets.tdb", private_dir);
57 18478 : if (fname == NULL) {
58 0 : TALLOC_FREE(frame);
59 0 : return False;
60 : }
61 :
62 18478 : db_ctx = db_open(NULL, fname, 0,
63 : TDB_DEFAULT, O_RDWR|O_CREAT, 0600,
64 : DBWRAP_LOCK_ORDER_1, DBWRAP_FLAG_NONE);
65 :
66 18478 : if (db_ctx == NULL) {
67 0 : DEBUG(0,("Failed to open %s\n", fname));
68 0 : TALLOC_FREE(frame);
69 0 : return False;
70 : }
71 :
72 18478 : TALLOC_FREE(frame);
73 18414 : return True;
74 : }
75 :
76 : /* open up the secrets database */
77 138492 : bool secrets_init(void)
78 : {
79 138492 : return secrets_init_path(lp_private_dir());
80 : }
81 :
82 71848 : struct db_context *secrets_db_ctx(void)
83 : {
84 71848 : if (!secrets_init()) {
85 0 : return NULL;
86 : }
87 :
88 71848 : return db_ctx;
89 : }
90 :
91 : /*
92 : * close secrets.tdb
93 : */
94 1065 : void secrets_shutdown(void)
95 : {
96 1065 : TALLOC_FREE(db_ctx);
97 1065 : }
98 :
99 : /* read a entry from the secrets database - the caller must free the result
100 : if size is non-null then the size of the entry is put in there
101 : */
102 56712 : void *secrets_fetch(const char *key, size_t *size)
103 : {
104 1810 : TDB_DATA dbuf;
105 1810 : void *result;
106 1810 : NTSTATUS status;
107 :
108 56712 : if (!secrets_init()) {
109 0 : return NULL;
110 : }
111 :
112 56712 : status = dbwrap_fetch(db_ctx, talloc_tos(), string_tdb_data(key),
113 : &dbuf);
114 56712 : if (!NT_STATUS_IS_OK(status)) {
115 13140 : return NULL;
116 : }
117 :
118 43499 : result = smb_memdup(dbuf.dptr, dbuf.dsize);
119 43499 : if (result == NULL) {
120 0 : return NULL;
121 : }
122 : /*
123 : * secrets_fetch() is a generic code and may be used for sensitive data,
124 : * so clear the local dbuf.dptr memory via BURN_PTR_SIZE().
125 : * The future plan is to convert secrets_fetch() to talloc.
126 : * That would improve performance via:
127 : * - avoid smb_memdup() above, instead directly return dbuf.dptr
128 : * - BURN_PTR_SIZE() will be done not here but in the caller and only
129 : * if the caller asks for sensitive data.
130 : */
131 43499 : BURN_PTR_SIZE(dbuf.dptr, dbuf.dsize);
132 43499 : TALLOC_FREE(dbuf.dptr);
133 :
134 43499 : if (size) {
135 38621 : *size = dbuf.dsize;
136 : }
137 :
138 41762 : return result;
139 : }
140 :
141 : /* store a secrets entry
142 : */
143 2414 : bool secrets_store(const char *key, const void *data, size_t size)
144 : {
145 170 : NTSTATUS status;
146 :
147 2414 : if (!secrets_init()) {
148 0 : return false;
149 : }
150 :
151 2414 : status = dbwrap_trans_store(db_ctx, string_tdb_data(key),
152 : make_tdb_data((const uint8_t *)data, size),
153 : TDB_REPLACE);
154 2414 : return NT_STATUS_IS_OK(status);
155 : }
156 :
157 0 : bool secrets_store_creds(struct cli_credentials *creds)
158 : {
159 0 : const char *p = NULL;
160 0 : bool ok;
161 :
162 0 : p = cli_credentials_get_username(creds);
163 0 : if (p == NULL) {
164 0 : return false;
165 : }
166 :
167 0 : ok = secrets_store(SECRETS_AUTH_USER, p, strlen(p) + 1);
168 0 : if (!ok) {
169 0 : DBG_ERR("Failed storing auth user name\n");
170 0 : return false;
171 : }
172 :
173 :
174 0 : p = cli_credentials_get_domain(creds);
175 0 : if (p == NULL) {
176 0 : return false;
177 : }
178 :
179 0 : ok = secrets_store(SECRETS_AUTH_DOMAIN, p, strlen(p) + 1);
180 0 : if (!ok) {
181 0 : DBG_ERR("Failed storing auth domain name\n");
182 0 : return false;
183 : }
184 :
185 :
186 0 : p = cli_credentials_get_password(creds);
187 0 : if (p == NULL) {
188 0 : return false;
189 : }
190 :
191 0 : ok = secrets_store(SECRETS_AUTH_PASSWORD, p, strlen(p) + 1);
192 0 : if (!ok) {
193 0 : DBG_ERR("Failed storing auth password\n");
194 0 : return false;
195 : }
196 :
197 0 : return true;
198 : }
199 :
200 :
201 : /* delete a secets database entry
202 : */
203 492 : bool secrets_delete_entry(const char *key)
204 : {
205 9 : NTSTATUS status;
206 492 : if (!secrets_init()) {
207 0 : return false;
208 : }
209 :
210 492 : status = dbwrap_trans_delete(db_ctx, string_tdb_data(key));
211 :
212 492 : return NT_STATUS_IS_OK(status);
213 : }
214 :
215 : /*
216 : * Deletes the key if it exists.
217 : */
218 1323 : bool secrets_delete(const char *key)
219 : {
220 21 : bool exists;
221 :
222 1323 : if (!secrets_init()) {
223 0 : return false;
224 : }
225 :
226 1323 : exists = dbwrap_exists(db_ctx, string_tdb_data(key));
227 1323 : if (!exists) {
228 926 : return true;
229 : }
230 :
231 376 : return secrets_delete_entry(key);
232 : }
233 :
234 : /**
235 : * Form a key for fetching a trusted domain password
236 : *
237 : * @param domain trusted domain name
238 : *
239 : * @return stored password's key
240 : **/
241 804 : static char *trustdom_keystr(const char *domain)
242 : {
243 0 : char *keystr;
244 :
245 804 : keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
246 : SECRETS_DOMTRUST_ACCT_PASS,
247 : domain);
248 804 : SMB_ASSERT(keystr != NULL);
249 804 : return keystr;
250 : }
251 :
252 : /************************************************************************
253 : Routine to get account password to trusted domain
254 : ************************************************************************/
255 :
256 800 : bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
257 : struct dom_sid *sid, time_t *pass_last_set_time)
258 : {
259 0 : struct TRUSTED_DOM_PASS pass;
260 0 : enum ndr_err_code ndr_err;
261 :
262 : /* unpacking structures */
263 0 : DATA_BLOB blob;
264 :
265 : /* fetching trusted domain password structure */
266 800 : if (!(blob.data = (uint8_t *)secrets_fetch(trustdom_keystr(domain),
267 : &blob.length))) {
268 800 : DEBUG(5, ("secrets_fetch failed!\n"));
269 800 : return False;
270 : }
271 :
272 : /* unpack trusted domain password */
273 0 : ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &pass,
274 : (ndr_pull_flags_fn_t)ndr_pull_TRUSTED_DOM_PASS);
275 :
276 : /* This blob is NOT talloc based! */
277 0 : BURN_FREE(blob.data, blob.length);
278 :
279 0 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
280 0 : return false;
281 : }
282 :
283 0 : if (pass.pass != NULL) {
284 0 : talloc_keep_secret(discard_const_p(char, pass.pass));
285 : }
286 :
287 : /* the trust's password */
288 0 : if (pwd) {
289 0 : *pwd = SMB_STRDUP(pass.pass);
290 0 : if (!*pwd) {
291 0 : return False;
292 : }
293 : }
294 :
295 : /* last change time */
296 0 : if (pass_last_set_time) *pass_last_set_time = pass.mod_time;
297 :
298 : /* domain sid */
299 0 : if (sid != NULL) sid_copy(sid, &pass.domain_sid);
300 :
301 0 : return True;
302 : }
303 :
304 : /**
305 : * Routine to store the password for trusted domain
306 : *
307 : * @param domain remote domain name
308 : * @param pwd plain text password of trust relationship
309 : * @param sid remote domain sid
310 : *
311 : * @return true if succeeded
312 : **/
313 :
314 4 : bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
315 : const struct dom_sid *sid)
316 : {
317 0 : bool ret;
318 :
319 : /* packing structures */
320 0 : DATA_BLOB blob;
321 0 : enum ndr_err_code ndr_err;
322 0 : struct TRUSTED_DOM_PASS pass;
323 4 : ZERO_STRUCT(pass);
324 :
325 4 : pass.uni_name = domain;
326 4 : pass.uni_name_len = strlen(domain)+1;
327 :
328 : /* last change time */
329 4 : pass.mod_time = time(NULL);
330 :
331 : /* password of the trust */
332 4 : pass.pass_len = strlen(pwd);
333 4 : pass.pass = pwd;
334 :
335 : /* domain sid */
336 4 : sid_copy(&pass.domain_sid, sid);
337 :
338 4 : ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &pass,
339 : (ndr_push_flags_fn_t)ndr_push_TRUSTED_DOM_PASS);
340 4 : if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
341 0 : return false;
342 : }
343 :
344 4 : ret = secrets_store(trustdom_keystr(domain), blob.data, blob.length);
345 :
346 : /* This blob is talloc based. */
347 4 : data_blob_clear_free(&blob);
348 :
349 4 : return ret;
350 : }
351 :
352 : /************************************************************************
353 : Routine to delete the password for trusted domain
354 : ************************************************************************/
355 :
356 0 : bool trusted_domain_password_delete(const char *domain)
357 : {
358 0 : return secrets_delete_entry(trustdom_keystr(domain));
359 : }
360 :
361 0 : bool secrets_store_ldap_pw(const char* dn, char* pw)
362 : {
363 0 : char *key = NULL;
364 0 : bool ret;
365 :
366 0 : if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
367 0 : DEBUG(0, ("secrets_store_ldap_pw: asprintf failed!\n"));
368 0 : return False;
369 : }
370 :
371 0 : ret = secrets_store(key, pw, strlen(pw)+1);
372 :
373 0 : SAFE_FREE(key);
374 0 : return ret;
375 : }
376 :
377 : /*******************************************************************
378 : Find the ldap password.
379 : ******************************************************************/
380 :
381 0 : bool fetch_ldap_pw(char **dn, char** pw)
382 : {
383 0 : char *key = NULL;
384 0 : size_t size = 0;
385 :
386 0 : *dn = smb_xstrdup(lp_ldap_admin_dn());
387 :
388 0 : if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
389 0 : SAFE_FREE(*dn);
390 0 : DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
391 0 : return false;
392 : }
393 :
394 0 : *pw=(char *)secrets_fetch(key, &size);
395 0 : SAFE_FREE(key);
396 :
397 0 : if (*pw == NULL || size == 0 || (*pw)[size-1] != '\0') {
398 0 : DBG_ERR("No valid password for %s\n", *dn);
399 0 : BURN_FREE_STR(*pw);
400 0 : SAFE_FREE(*dn);
401 0 : return false;
402 : }
403 :
404 0 : return true;
405 : }
406 :
407 : /*******************************************************************************
408 : Store a complete AFS keyfile into secrets.tdb.
409 : *******************************************************************************/
410 :
411 0 : bool secrets_store_afs_keyfile(const char *cell, const struct afs_keyfile *keyfile)
412 : {
413 0 : fstring key;
414 :
415 0 : if ((cell == NULL) || (keyfile == NULL))
416 0 : return False;
417 :
418 0 : if (ntohl(keyfile->nkeys) > SECRETS_AFS_MAXKEYS)
419 0 : return False;
420 :
421 0 : slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
422 0 : return secrets_store(key, keyfile, sizeof(struct afs_keyfile));
423 : }
424 :
425 : /*******************************************************************************
426 : Fetch the current (highest) AFS key from secrets.tdb
427 : *******************************************************************************/
428 0 : bool secrets_fetch_afs_key(const char *cell, struct afs_key *result)
429 : {
430 0 : fstring key;
431 0 : struct afs_keyfile *keyfile;
432 0 : size_t size = 0;
433 0 : uint32_t i;
434 :
435 0 : slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
436 :
437 0 : keyfile = (struct afs_keyfile *)secrets_fetch(key, &size);
438 :
439 0 : if (keyfile == NULL)
440 0 : return False;
441 :
442 0 : if (size != sizeof(struct afs_keyfile)) {
443 0 : BURN_FREE(keyfile, sizeof(*keyfile));
444 0 : return False;
445 : }
446 :
447 0 : i = ntohl(keyfile->nkeys);
448 :
449 0 : if (i > SECRETS_AFS_MAXKEYS) {
450 0 : BURN_FREE(keyfile, sizeof(*keyfile));
451 0 : return False;
452 : }
453 :
454 0 : *result = keyfile->entry[i-1];
455 :
456 0 : result->kvno = ntohl(result->kvno);
457 :
458 0 : BURN_FREE(keyfile, sizeof(*keyfile));
459 :
460 0 : return True;
461 : }
462 :
463 : /******************************************************************************
464 : When kerberos is not available, choose between anonymous or
465 : authenticated connections.
466 :
467 : We need to use an authenticated connection if DCs have the
468 : RestrictAnonymous registry entry set > 0, or the "Additional
469 : restrictions for anonymous connections" set in the win2k Local
470 : Security Policy.
471 :
472 : Caller to free() result in domain, username, password
473 : *******************************************************************************/
474 0 : void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
475 : {
476 0 : *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
477 0 : *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
478 0 : *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
479 :
480 0 : if (*username && **username) {
481 :
482 0 : if (!*domain || !**domain) {
483 0 : SAFE_FREE(*domain);
484 0 : *domain = smb_xstrdup(lp_workgroup());
485 : }
486 :
487 0 : if (!*password || !**password) {
488 0 : BURN_FREE_STR(*password);
489 0 : *password = smb_xstrdup("");
490 : }
491 :
492 0 : DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
493 : *domain, *username));
494 :
495 : } else {
496 0 : DEBUG(3, ("IPC$ connections done anonymously\n"));
497 0 : SAFE_FREE(*username);
498 0 : SAFE_FREE(*domain);
499 0 : BURN_FREE_STR(*password);
500 0 : *username = smb_xstrdup("");
501 0 : *domain = smb_xstrdup("");
502 0 : *password = smb_xstrdup("");
503 : }
504 0 : }
505 :
506 0 : bool secrets_store_generic(const char *owner, const char *key, const char *secret)
507 : {
508 0 : char *tdbkey = NULL;
509 0 : bool ret;
510 :
511 0 : if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
512 0 : DEBUG(0, ("asprintf failed!\n"));
513 0 : return False;
514 : }
515 :
516 0 : ret = secrets_store(tdbkey, secret, strlen(secret)+1);
517 :
518 0 : SAFE_FREE(tdbkey);
519 0 : return ret;
520 : }
521 :
522 : /*******************************************************************
523 : Find the ldap password.
524 : ******************************************************************/
525 :
526 0 : char *secrets_fetch_generic(const char *owner, const char *key)
527 : {
528 0 : char *secret = NULL;
529 0 : char *tdbkey = NULL;
530 :
531 0 : if (( ! owner) || ( ! key)) {
532 0 : DEBUG(1, ("Invalid Parameters\n"));
533 0 : return NULL;
534 : }
535 :
536 0 : if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
537 0 : DEBUG(0, ("Out of memory!\n"));
538 0 : return NULL;
539 : }
540 :
541 0 : secret = (char *)secrets_fetch(tdbkey, NULL);
542 0 : SAFE_FREE(tdbkey);
543 :
544 0 : return secret;
545 : }
546 :
|