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