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