s3:dbwrap: move db_open() to a file dbwrap_open.c of its own.
[sfrench/samba-autobuild/.git] / source3 / passdb / secrets.c
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 "passdb.h"
28 #include "../libcli/auth/libcli_auth.h"
29 #include "librpc/gen_ndr/ndr_secrets.h"
30 #include "secrets.h"
31 #include "dbwrap.h"
32 #include "dbwrap/dbwrap_open.h"
33 #include "../libcli/security/security.h"
34 #include "util_tdb.h"
35
36 #undef DBGC_CLASS
37 #define DBGC_CLASS DBGC_PASSDB
38
39 static struct db_context *db_ctx;
40
41 /**
42  * Use a TDB to store an incrementing random seed.
43  *
44  * Initialised to the current pid, the very first time Samba starts,
45  * and incremented by one each time it is needed.
46  *
47  * @note Not called by systems with a working /dev/urandom.
48  */
49 static void get_rand_seed(void *userdata, int *new_seed)
50 {
51         *new_seed = sys_getpid();
52         if (db_ctx) {
53                 dbwrap_trans_change_int32_atomic(db_ctx, "INFO/random_seed",
54                                                  new_seed, 1);
55         }
56 }
57
58 /* open up the secrets database */
59 bool secrets_init(void)
60 {
61         char *fname = NULL;
62         unsigned char dummy;
63
64         if (db_ctx != NULL)
65                 return True;
66
67         fname = talloc_asprintf(talloc_tos(), "%s/secrets.tdb",
68                                 lp_private_dir());
69         if (fname == NULL) {
70                 return false;
71         }
72
73         db_ctx = db_open(NULL, fname, 0,
74                          TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
75
76         if (db_ctx == NULL) {
77                 DEBUG(0,("Failed to open %s\n", fname));
78                 TALLOC_FREE(fname);
79                 return False;
80         }
81
82         TALLOC_FREE(fname);
83
84         /**
85          * Set a reseed function for the crypto random generator
86          *
87          * This avoids a problem where systems without /dev/urandom
88          * could send the same challenge to multiple clients
89          */
90         set_rand_reseed_callback(get_rand_seed, NULL);
91
92         /* Ensure that the reseed is done now, while we are root, etc */
93         generate_random_buffer(&dummy, sizeof(dummy));
94
95         return True;
96 }
97
98 struct db_context *secrets_db_ctx(void)
99 {
100         if (!secrets_init()) {
101                 return NULL;
102         }
103
104         return db_ctx;
105 }
106
107 /*
108  * close secrets.tdb
109  */
110 void secrets_shutdown(void)
111 {
112         TALLOC_FREE(db_ctx);
113 }
114
115 /* read a entry from the secrets database - the caller must free the result
116    if size is non-null then the size of the entry is put in there
117  */
118 void *secrets_fetch(const char *key, size_t *size)
119 {
120         TDB_DATA dbuf;
121         void *result;
122
123         if (!secrets_init()) {
124                 return NULL;
125         }
126
127         if (db_ctx->fetch(db_ctx, talloc_tos(), string_tdb_data(key),
128                           &dbuf) != 0) {
129                 return NULL;
130         }
131
132         result = memdup(dbuf.dptr, dbuf.dsize);
133         if (result == NULL) {
134                 return NULL;
135         }
136         TALLOC_FREE(dbuf.dptr);
137
138         if (size) {
139                 *size = dbuf.dsize;
140         }
141
142         return result;
143 }
144
145 /* store a secrets entry
146  */
147 bool secrets_store(const char *key, const void *data, size_t size)
148 {
149         NTSTATUS status;
150
151         if (!secrets_init()) {
152                 return false;
153         }
154
155         status = dbwrap_trans_store(db_ctx, string_tdb_data(key),
156                                     make_tdb_data((const uint8 *)data, size),
157                                     TDB_REPLACE);
158         return NT_STATUS_IS_OK(status);
159 }
160
161
162 /* delete a secets database entry
163  */
164 bool secrets_delete(const char *key)
165 {
166         NTSTATUS status;
167         if (!secrets_init()) {
168                 return false;
169         }
170
171         status = dbwrap_trans_delete(db_ctx, string_tdb_data(key));
172
173         return NT_STATUS_IS_OK(status);
174 }
175
176 /**
177  * Form a key for fetching a trusted domain password
178  *
179  * @param domain trusted domain name
180  *
181  * @return stored password's key
182  **/
183 static char *trustdom_keystr(const char *domain)
184 {
185         char *keystr;
186
187         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
188                                             SECRETS_DOMTRUST_ACCT_PASS,
189                                             domain);
190         SMB_ASSERT(keystr != NULL);
191         return keystr;
192 }
193
194 /************************************************************************
195  Routine to get account password to trusted domain
196 ************************************************************************/
197
198 bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
199                                            struct dom_sid *sid, time_t *pass_last_set_time)
200 {
201         struct TRUSTED_DOM_PASS pass;
202         enum ndr_err_code ndr_err;
203
204         /* unpacking structures */
205         DATA_BLOB blob;
206
207         /* fetching trusted domain password structure */
208         if (!(blob.data = (uint8_t *)secrets_fetch(trustdom_keystr(domain),
209                                                    &blob.length))) {
210                 DEBUG(5, ("secrets_fetch failed!\n"));
211                 return False;
212         }
213
214         /* unpack trusted domain password */
215         ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &pass,
216                         (ndr_pull_flags_fn_t)ndr_pull_TRUSTED_DOM_PASS);
217
218         SAFE_FREE(blob.data);
219
220         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
221                 return false;
222         }
223
224
225         /* the trust's password */
226         if (pwd) {
227                 *pwd = SMB_STRDUP(pass.pass);
228                 if (!*pwd) {
229                         return False;
230                 }
231         }
232
233         /* last change time */
234         if (pass_last_set_time) *pass_last_set_time = pass.mod_time;
235
236         /* domain sid */
237         if (sid != NULL) sid_copy(sid, &pass.domain_sid);
238
239         return True;
240 }
241
242 /**
243  * Routine to store the password for trusted domain
244  *
245  * @param domain remote domain name
246  * @param pwd plain text password of trust relationship
247  * @param sid remote domain sid
248  *
249  * @return true if succeeded
250  **/
251
252 bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
253                                            const struct dom_sid *sid)
254 {
255         bool ret;
256
257         /* packing structures */
258         DATA_BLOB blob;
259         enum ndr_err_code ndr_err;
260         struct TRUSTED_DOM_PASS pass;
261         ZERO_STRUCT(pass);
262
263         pass.uni_name = domain;
264         pass.uni_name_len = strlen(domain)+1;
265
266         /* last change time */
267         pass.mod_time = time(NULL);
268
269         /* password of the trust */
270         pass.pass_len = strlen(pwd);
271         pass.pass = pwd;
272
273         /* domain sid */
274         sid_copy(&pass.domain_sid, sid);
275
276         ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &pass,
277                         (ndr_push_flags_fn_t)ndr_push_TRUSTED_DOM_PASS);
278         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
279                 return false;
280         }
281
282         ret = secrets_store(trustdom_keystr(domain), blob.data, blob.length);
283
284         data_blob_free(&blob);
285
286         return ret;
287 }
288
289 /************************************************************************
290  Routine to delete the password for trusted domain
291 ************************************************************************/
292
293 bool trusted_domain_password_delete(const char *domain)
294 {
295         return secrets_delete(trustdom_keystr(domain));
296 }
297
298 bool secrets_store_ldap_pw(const char* dn, char* pw)
299 {
300         char *key = NULL;
301         bool ret;
302
303         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
304                 DEBUG(0, ("secrets_store_ldap_pw: asprintf failed!\n"));
305                 return False;
306         }
307
308         ret = secrets_store(key, pw, strlen(pw)+1);
309
310         SAFE_FREE(key);
311         return ret;
312 }
313
314 /*******************************************************************
315  Find the ldap password.
316 ******************************************************************/
317
318 bool fetch_ldap_pw(char **dn, char** pw)
319 {
320         char *key = NULL;
321         size_t size = 0;
322
323         *dn = smb_xstrdup(lp_ldap_admin_dn());
324
325         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
326                 SAFE_FREE(*dn);
327                 DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
328                 return false;
329         }
330
331         *pw=(char *)secrets_fetch(key, &size);
332         SAFE_FREE(key);
333
334         if (!size) {
335                 /* Upgrade 2.2 style entry */
336                 char *p;
337                 char* old_style_key = SMB_STRDUP(*dn);
338                 char *data;
339                 fstring old_style_pw;
340
341                 if (!old_style_key) {
342                         DEBUG(0, ("fetch_ldap_pw: strdup failed!\n"));
343                         return False;
344                 }
345
346                 for (p=old_style_key; *p; p++)
347                         if (*p == ',') *p = '/';
348
349                 data=(char *)secrets_fetch(old_style_key, &size);
350                 if ((data == NULL) || (size < sizeof(old_style_pw))) {
351                         DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
352                         SAFE_FREE(old_style_key);
353                         SAFE_FREE(*dn);
354                         SAFE_FREE(data);
355                         return False;
356                 }
357
358                 size = MIN(size, sizeof(fstring)-1);
359                 strncpy(old_style_pw, data, size);
360                 old_style_pw[size] = 0;
361
362                 SAFE_FREE(data);
363
364                 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
365                         DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
366                         SAFE_FREE(old_style_key);
367                         SAFE_FREE(*dn);
368                         return False;
369                 }
370                 if (!secrets_delete(old_style_key)) {
371                         DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
372                 }
373
374                 SAFE_FREE(old_style_key);
375
376                 *pw = smb_xstrdup(old_style_pw);
377         }
378
379         return True;
380 }
381
382 /**
383  * Get trusted domains info from secrets.tdb.
384  **/
385
386 struct list_trusted_domains_state {
387         uint32 num_domains;
388         struct trustdom_info **domains;
389 };
390
391 static int list_trusted_domain(struct db_record *rec, void *private_data)
392 {
393         const size_t prefix_len = strlen(SECRETS_DOMTRUST_ACCT_PASS);
394         struct TRUSTED_DOM_PASS pass;
395         enum ndr_err_code ndr_err;
396         DATA_BLOB blob;
397         struct trustdom_info *dom_info;
398
399         struct list_trusted_domains_state *state =
400                 (struct list_trusted_domains_state *)private_data;
401
402         if ((rec->key.dsize < prefix_len)
403             || (strncmp((char *)rec->key.dptr, SECRETS_DOMTRUST_ACCT_PASS,
404                         prefix_len) != 0)) {
405                 return 0;
406         }
407
408         blob = data_blob_const(rec->value.dptr, rec->value.dsize);
409
410         ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &pass,
411                         (ndr_pull_flags_fn_t)ndr_pull_TRUSTED_DOM_PASS);
412         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
413                 return false;
414         }
415
416         if (pass.domain_sid.num_auths != 4) {
417                 DEBUG(0, ("SID %s is not a domain sid, has %d "
418                           "auths instead of 4\n",
419                           sid_string_dbg(&pass.domain_sid),
420                           pass.domain_sid.num_auths));
421                 return 0;
422         }
423
424         if (!(dom_info = talloc(state->domains, struct trustdom_info))) {
425                 DEBUG(0, ("talloc failed\n"));
426                 return 0;
427         }
428
429         dom_info->name = talloc_strdup(dom_info, pass.uni_name);
430         if (!dom_info->name) {
431                 TALLOC_FREE(dom_info);
432                 return 0;
433         }
434
435         sid_copy(&dom_info->sid, &pass.domain_sid);
436
437         ADD_TO_ARRAY(state->domains, struct trustdom_info *, dom_info,
438                      &state->domains, &state->num_domains);
439
440         if (state->domains == NULL) {
441                 state->num_domains = 0;
442                 return -1;
443         }
444         return 0;
445 }
446
447 NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
448                                  struct trustdom_info ***domains)
449 {
450         struct list_trusted_domains_state state;
451
452         if (!secrets_init()) {
453                 return NT_STATUS_ACCESS_DENIED;
454         }
455
456         state.num_domains = 0;
457
458         /*
459          * Make sure that a talloc context for the trustdom_info structs
460          * exists
461          */
462
463         if (!(state.domains = talloc_array(
464                       mem_ctx, struct trustdom_info *, 1))) {
465                 return NT_STATUS_NO_MEMORY;
466         }
467
468         db_ctx->traverse_read(db_ctx, list_trusted_domain, (void *)&state);
469
470         *num_domains = state.num_domains;
471         *domains = state.domains;
472         return NT_STATUS_OK;
473 }
474
475 /*******************************************************************************
476  Store a complete AFS keyfile into secrets.tdb.
477 *******************************************************************************/
478
479 bool secrets_store_afs_keyfile(const char *cell, const struct afs_keyfile *keyfile)
480 {
481         fstring key;
482
483         if ((cell == NULL) || (keyfile == NULL))
484                 return False;
485
486         if (ntohl(keyfile->nkeys) > SECRETS_AFS_MAXKEYS)
487                 return False;
488
489         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
490         return secrets_store(key, keyfile, sizeof(struct afs_keyfile));
491 }
492
493 /*******************************************************************************
494  Fetch the current (highest) AFS key from secrets.tdb
495 *******************************************************************************/
496 bool secrets_fetch_afs_key(const char *cell, struct afs_key *result)
497 {
498         fstring key;
499         struct afs_keyfile *keyfile;
500         size_t size = 0;
501         uint32 i;
502
503         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
504
505         keyfile = (struct afs_keyfile *)secrets_fetch(key, &size);
506
507         if (keyfile == NULL)
508                 return False;
509
510         if (size != sizeof(struct afs_keyfile)) {
511                 SAFE_FREE(keyfile);
512                 return False;
513         }
514
515         i = ntohl(keyfile->nkeys);
516
517         if (i > SECRETS_AFS_MAXKEYS) {
518                 SAFE_FREE(keyfile);
519                 return False;
520         }
521
522         *result = keyfile->entry[i-1];
523
524         result->kvno = ntohl(result->kvno);
525
526         SAFE_FREE(keyfile);
527
528         return True;
529 }
530
531 /******************************************************************************
532   When kerberos is not available, choose between anonymous or
533   authenticated connections.
534
535   We need to use an authenticated connection if DCs have the
536   RestrictAnonymous registry entry set > 0, or the "Additional
537   restrictions for anonymous connections" set in the win2k Local
538   Security Policy.
539
540   Caller to free() result in domain, username, password
541 *******************************************************************************/
542 void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
543 {
544         *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
545         *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
546         *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
547
548         if (*username && **username) {
549
550                 if (!*domain || !**domain)
551                         *domain = smb_xstrdup(lp_workgroup());
552
553                 if (!*password || !**password)
554                         *password = smb_xstrdup("");
555
556                 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
557                           *domain, *username));
558
559         } else {
560                 DEBUG(3, ("IPC$ connections done anonymously\n"));
561                 *username = smb_xstrdup("");
562                 *domain = smb_xstrdup("");
563                 *password = smb_xstrdup("");
564         }
565 }
566
567 bool secrets_store_generic(const char *owner, const char *key, const char *secret)
568 {
569         char *tdbkey = NULL;
570         bool ret;
571
572         if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
573                 DEBUG(0, ("asprintf failed!\n"));
574                 return False;
575         }
576
577         ret = secrets_store(tdbkey, secret, strlen(secret)+1);
578
579         SAFE_FREE(tdbkey);
580         return ret;
581 }
582
583 bool secrets_delete_generic(const char *owner, const char *key)
584 {
585         char *tdbkey = NULL;
586         bool ret;
587
588         if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
589                 DEBUG(0, ("asprintf failed!\n"));
590                 return False;
591         }
592
593         ret = secrets_delete(tdbkey);
594
595         SAFE_FREE(tdbkey);
596         return ret;
597 }
598
599 /*******************************************************************
600  Find the ldap password.
601 ******************************************************************/
602
603 char *secrets_fetch_generic(const char *owner, const char *key)
604 {
605         char *secret = NULL;
606         char *tdbkey = NULL;
607
608         if (( ! owner) || ( ! key)) {
609                 DEBUG(1, ("Invalid Parameters"));
610                 return NULL;
611         }
612
613         if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
614                 DEBUG(0, ("Out of memory!\n"));
615                 return NULL;
616         }
617
618         secret = (char *)secrets_fetch(tdbkey, NULL);
619         SAFE_FREE(tdbkey);
620
621         return secret;
622 }
623