s3: Fix a potential memleak in secrets_fetch_trusted_domain_password
[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 "../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 bool secrets_store_local_schannel_key(uint8_t schannel_key[16])
173 {
174         return secrets_store(SECRETS_LOCAL_SCHANNEL_KEY, schannel_key, 16);
175 }
176
177 bool secrets_fetch_local_schannel_key(uint8_t schannel_key[16])
178 {
179         size_t size = 0;
180         uint8_t *key;
181
182         key = (uint8_t *)secrets_fetch(SECRETS_LOCAL_SCHANNEL_KEY, &size);
183         if (key == NULL) {
184                 return false;
185         }
186
187         if (size != 16) {
188                 SAFE_FREE(key);
189                 return false;
190         }
191
192         memcpy(schannel_key, key, 16);
193         SAFE_FREE(key);
194         return true;
195 }
196
197 /**
198  * Form a key for fetching a trusted domain password
199  *
200  * @param domain trusted domain name
201  *
202  * @return stored password's key
203  **/
204 static char *trustdom_keystr(const char *domain)
205 {
206         char *keystr;
207
208         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
209                                             SECRETS_DOMTRUST_ACCT_PASS,
210                                             domain);
211         SMB_ASSERT(keystr != NULL);
212         return keystr;
213 }
214
215 /************************************************************************
216  Routine to get account password to trusted domain
217 ************************************************************************/
218
219 bool secrets_fetch_trusted_domain_password(const char *domain, char** pwd,
220                                            struct dom_sid *sid, time_t *pass_last_set_time)
221 {
222         struct TRUSTED_DOM_PASS pass;
223         enum ndr_err_code ndr_err;
224
225         /* unpacking structures */
226         DATA_BLOB blob;
227
228         /* fetching trusted domain password structure */
229         if (!(blob.data = (uint8_t *)secrets_fetch(trustdom_keystr(domain),
230                                                    &blob.length))) {
231                 DEBUG(5, ("secrets_fetch failed!\n"));
232                 return False;
233         }
234
235         /* unpack trusted domain password */
236         ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &pass,
237                         (ndr_pull_flags_fn_t)ndr_pull_TRUSTED_DOM_PASS);
238
239         SAFE_FREE(blob.data);
240
241         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
242                 return false;
243         }
244
245
246         /* the trust's password */
247         if (pwd) {
248                 *pwd = SMB_STRDUP(pass.pass);
249                 if (!*pwd) {
250                         return False;
251                 }
252         }
253
254         /* last change time */
255         if (pass_last_set_time) *pass_last_set_time = pass.mod_time;
256
257         /* domain sid */
258         if (sid != NULL) sid_copy(sid, &pass.domain_sid);
259
260         return True;
261 }
262
263 /**
264  * Routine to store the password for trusted domain
265  *
266  * @param domain remote domain name
267  * @param pwd plain text password of trust relationship
268  * @param sid remote domain sid
269  *
270  * @return true if succeeded
271  **/
272
273 bool secrets_store_trusted_domain_password(const char* domain, const char* pwd,
274                                            const struct dom_sid *sid)
275 {
276         bool ret;
277
278         /* packing structures */
279         DATA_BLOB blob;
280         enum ndr_err_code ndr_err;
281         struct TRUSTED_DOM_PASS pass;
282         ZERO_STRUCT(pass);
283
284         pass.uni_name = domain;
285         pass.uni_name_len = strlen(domain)+1;
286
287         /* last change time */
288         pass.mod_time = time(NULL);
289
290         /* password of the trust */
291         pass.pass_len = strlen(pwd);
292         pass.pass = pwd;
293
294         /* domain sid */
295         sid_copy(&pass.domain_sid, sid);
296
297         ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &pass,
298                         (ndr_push_flags_fn_t)ndr_push_TRUSTED_DOM_PASS);
299         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
300                 return false;
301         }
302
303         ret = secrets_store(trustdom_keystr(domain), blob.data, blob.length);
304
305         data_blob_free(&blob);
306
307         return ret;
308 }
309
310 /************************************************************************
311  Routine to delete the password for trusted domain
312 ************************************************************************/
313
314 bool trusted_domain_password_delete(const char *domain)
315 {
316         return secrets_delete(trustdom_keystr(domain));
317 }
318
319 bool secrets_store_ldap_pw(const char* dn, char* pw)
320 {
321         char *key = NULL;
322         bool ret;
323
324         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, dn) < 0) {
325                 DEBUG(0, ("secrets_store_ldap_pw: asprintf failed!\n"));
326                 return False;
327         }
328
329         ret = secrets_store(key, pw, strlen(pw)+1);
330
331         SAFE_FREE(key);
332         return ret;
333 }
334
335 /*******************************************************************
336  Find the ldap password.
337 ******************************************************************/
338
339 bool fetch_ldap_pw(char **dn, char** pw)
340 {
341         char *key = NULL;
342         size_t size = 0;
343
344         *dn = smb_xstrdup(lp_ldap_admin_dn());
345
346         if (asprintf(&key, "%s/%s", SECRETS_LDAP_BIND_PW, *dn) < 0) {
347                 SAFE_FREE(*dn);
348                 DEBUG(0, ("fetch_ldap_pw: asprintf failed!\n"));
349                 return false;
350         }
351
352         *pw=(char *)secrets_fetch(key, &size);
353         SAFE_FREE(key);
354
355         if (!size) {
356                 /* Upgrade 2.2 style entry */
357                 char *p;
358                 char* old_style_key = SMB_STRDUP(*dn);
359                 char *data;
360                 fstring old_style_pw;
361
362                 if (!old_style_key) {
363                         DEBUG(0, ("fetch_ldap_pw: strdup failed!\n"));
364                         return False;
365                 }
366
367                 for (p=old_style_key; *p; p++)
368                         if (*p == ',') *p = '/';
369
370                 data=(char *)secrets_fetch(old_style_key, &size);
371                 if ((data == NULL) || (size < sizeof(old_style_pw))) {
372                         DEBUG(0,("fetch_ldap_pw: neither ldap secret retrieved!\n"));
373                         SAFE_FREE(old_style_key);
374                         SAFE_FREE(*dn);
375                         SAFE_FREE(data);
376                         return False;
377                 }
378
379                 size = MIN(size, sizeof(fstring)-1);
380                 strncpy(old_style_pw, data, size);
381                 old_style_pw[size] = 0;
382
383                 SAFE_FREE(data);
384
385                 if (!secrets_store_ldap_pw(*dn, old_style_pw)) {
386                         DEBUG(0,("fetch_ldap_pw: ldap secret could not be upgraded!\n"));
387                         SAFE_FREE(old_style_key);
388                         SAFE_FREE(*dn);
389                         return False;
390                 }
391                 if (!secrets_delete(old_style_key)) {
392                         DEBUG(0,("fetch_ldap_pw: old ldap secret could not be deleted!\n"));
393                 }
394
395                 SAFE_FREE(old_style_key);
396
397                 *pw = smb_xstrdup(old_style_pw);
398         }
399
400         return True;
401 }
402
403 /**
404  * Get trusted domains info from secrets.tdb.
405  **/
406
407 struct list_trusted_domains_state {
408         uint32 num_domains;
409         struct trustdom_info **domains;
410 };
411
412 static int list_trusted_domain(struct db_record *rec, void *private_data)
413 {
414         const size_t prefix_len = strlen(SECRETS_DOMTRUST_ACCT_PASS);
415         struct TRUSTED_DOM_PASS pass;
416         enum ndr_err_code ndr_err;
417         DATA_BLOB blob;
418         struct trustdom_info *dom_info;
419
420         struct list_trusted_domains_state *state =
421                 (struct list_trusted_domains_state *)private_data;
422
423         if ((rec->key.dsize < prefix_len)
424             || (strncmp((char *)rec->key.dptr, SECRETS_DOMTRUST_ACCT_PASS,
425                         prefix_len) != 0)) {
426                 return 0;
427         }
428
429         blob = data_blob_const(rec->value.dptr, rec->value.dsize);
430
431         ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), &pass,
432                         (ndr_pull_flags_fn_t)ndr_pull_TRUSTED_DOM_PASS);
433         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
434                 return false;
435         }
436
437         if (pass.domain_sid.num_auths != 4) {
438                 DEBUG(0, ("SID %s is not a domain sid, has %d "
439                           "auths instead of 4\n",
440                           sid_string_dbg(&pass.domain_sid),
441                           pass.domain_sid.num_auths));
442                 return 0;
443         }
444
445         if (!(dom_info = TALLOC_P(state->domains, struct trustdom_info))) {
446                 DEBUG(0, ("talloc failed\n"));
447                 return 0;
448         }
449
450         dom_info->name = talloc_strdup(dom_info, pass.uni_name);
451         if (!dom_info->name) {
452                 TALLOC_FREE(dom_info);
453                 return 0;
454         }
455
456         sid_copy(&dom_info->sid, &pass.domain_sid);
457
458         ADD_TO_ARRAY(state->domains, struct trustdom_info *, dom_info,
459                      &state->domains, &state->num_domains);
460
461         if (state->domains == NULL) {
462                 state->num_domains = 0;
463                 return -1;
464         }
465         return 0;
466 }
467
468 NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
469                                  struct trustdom_info ***domains)
470 {
471         struct list_trusted_domains_state state;
472
473         secrets_init();
474
475         if (db_ctx == NULL) {
476                 return NT_STATUS_ACCESS_DENIED;
477         }
478
479         state.num_domains = 0;
480
481         /*
482          * Make sure that a talloc context for the trustdom_info structs
483          * exists
484          */
485
486         if (!(state.domains = TALLOC_ARRAY(
487                       mem_ctx, struct trustdom_info *, 1))) {
488                 return NT_STATUS_NO_MEMORY;
489         }
490
491         db_ctx->traverse_read(db_ctx, list_trusted_domain, (void *)&state);
492
493         *num_domains = state.num_domains;
494         *domains = state.domains;
495         return NT_STATUS_OK;
496 }
497
498 /*******************************************************************************
499  Store a complete AFS keyfile into secrets.tdb.
500 *******************************************************************************/
501
502 bool secrets_store_afs_keyfile(const char *cell, const struct afs_keyfile *keyfile)
503 {
504         fstring key;
505
506         if ((cell == NULL) || (keyfile == NULL))
507                 return False;
508
509         if (ntohl(keyfile->nkeys) > SECRETS_AFS_MAXKEYS)
510                 return False;
511
512         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
513         return secrets_store(key, keyfile, sizeof(struct afs_keyfile));
514 }
515
516 /*******************************************************************************
517  Fetch the current (highest) AFS key from secrets.tdb
518 *******************************************************************************/
519 bool secrets_fetch_afs_key(const char *cell, struct afs_key *result)
520 {
521         fstring key;
522         struct afs_keyfile *keyfile;
523         size_t size = 0;
524         uint32 i;
525
526         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_AFS_KEYFILE, cell);
527
528         keyfile = (struct afs_keyfile *)secrets_fetch(key, &size);
529
530         if (keyfile == NULL)
531                 return False;
532
533         if (size != sizeof(struct afs_keyfile)) {
534                 SAFE_FREE(keyfile);
535                 return False;
536         }
537
538         i = ntohl(keyfile->nkeys);
539
540         if (i > SECRETS_AFS_MAXKEYS) {
541                 SAFE_FREE(keyfile);
542                 return False;
543         }
544
545         *result = keyfile->entry[i-1];
546
547         result->kvno = ntohl(result->kvno);
548
549         SAFE_FREE(keyfile);
550
551         return True;
552 }
553
554 /******************************************************************************
555   When kerberos is not available, choose between anonymous or
556   authenticated connections.
557
558   We need to use an authenticated connection if DCs have the
559   RestrictAnonymous registry entry set > 0, or the "Additional
560   restrictions for anonymous connections" set in the win2k Local
561   Security Policy.
562
563   Caller to free() result in domain, username, password
564 *******************************************************************************/
565 void secrets_fetch_ipc_userpass(char **username, char **domain, char **password)
566 {
567         *username = (char *)secrets_fetch(SECRETS_AUTH_USER, NULL);
568         *domain = (char *)secrets_fetch(SECRETS_AUTH_DOMAIN, NULL);
569         *password = (char *)secrets_fetch(SECRETS_AUTH_PASSWORD, NULL);
570
571         if (*username && **username) {
572
573                 if (!*domain || !**domain)
574                         *domain = smb_xstrdup(lp_workgroup());
575
576                 if (!*password || !**password)
577                         *password = smb_xstrdup("");
578
579                 DEBUG(3, ("IPC$ connections done by user %s\\%s\n",
580                           *domain, *username));
581
582         } else {
583                 DEBUG(3, ("IPC$ connections done anonymously\n"));
584                 *username = smb_xstrdup("");
585                 *domain = smb_xstrdup("");
586                 *password = smb_xstrdup("");
587         }
588 }
589
590 bool secrets_store_generic(const char *owner, const char *key, const char *secret)
591 {
592         char *tdbkey = NULL;
593         bool ret;
594
595         if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
596                 DEBUG(0, ("asprintf failed!\n"));
597                 return False;
598         }
599
600         ret = secrets_store(tdbkey, secret, strlen(secret)+1);
601
602         SAFE_FREE(tdbkey);
603         return ret;
604 }
605
606 bool secrets_delete_generic(const char *owner, const char *key)
607 {
608         char *tdbkey = NULL;
609         bool ret;
610
611         if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
612                 DEBUG(0, ("asprintf failed!\n"));
613                 return False;
614         }
615
616         ret = secrets_delete(tdbkey);
617
618         SAFE_FREE(tdbkey);
619         return ret;
620 }
621
622 /*******************************************************************
623  Find the ldap password.
624 ******************************************************************/
625
626 char *secrets_fetch_generic(const char *owner, const char *key)
627 {
628         char *secret = NULL;
629         char *tdbkey = NULL;
630
631         if (( ! owner) || ( ! key)) {
632                 DEBUG(1, ("Invalid Parameters"));
633                 return NULL;
634         }
635
636         if (asprintf(&tdbkey, "SECRETS/GENERIC/%s/%s", owner, key) < 0) {
637                 DEBUG(0, ("Out of memory!\n"));
638                 return NULL;
639         }
640
641         secret = (char *)secrets_fetch(tdbkey, NULL);
642         SAFE_FREE(tdbkey);
643
644         return secret;
645 }
646