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