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