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