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