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