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