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