passdb: Do not routinely clear the global memory returned by get_global_sam_sid()
[bbaumbach/samba-autobuild/.git] / source3 / passdb / machine_account_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 "passdb.h"
27 #include "../libcli/auth/libcli_auth.h"
28 #include "secrets.h"
29 #include "dbwrap/dbwrap.h"
30 #include "../librpc/ndr/libndr.h"
31 #include "util_tdb.h"
32 #include "libcli/security/security.h"
33
34 #undef DBGC_CLASS
35 #define DBGC_CLASS DBGC_PASSDB
36
37 /**
38  * Form a key for fetching the domain sid
39  *
40  * @param domain domain name
41  *
42  * @return keystring
43  **/
44 static const char *domain_sid_keystr(const char *domain)
45 {
46         char *keystr;
47
48         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
49                                             SECRETS_DOMAIN_SID, domain);
50         SMB_ASSERT(keystr != NULL);
51         return keystr;
52 }
53
54 static const char *protect_ids_keystr(const char *domain)
55 {
56         char *keystr;
57
58         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
59                                             SECRETS_PROTECT_IDS, domain);
60         SMB_ASSERT(keystr != NULL);
61         return keystr;
62 }
63
64 /* N O T E: never use this outside of passdb modules that store the SID on their own */
65 bool secrets_mark_domain_protected(const char *domain)
66 {
67         bool ret;
68
69         ret = secrets_store(protect_ids_keystr(domain), "TRUE", 5);
70         if (!ret) {
71                 DEBUG(0, ("Failed to protect the Domain IDs\n"));
72         }
73         return ret;
74 }
75
76 bool secrets_clear_domain_protection(const char *domain)
77 {
78         bool ret;
79         void *protection = secrets_fetch(protect_ids_keystr(domain), NULL);
80         
81         if (protection) {
82                 SAFE_FREE(protection);
83                 ret = secrets_delete(protect_ids_keystr(domain));
84                 if (!ret) {
85                         DEBUG(0, ("Failed to remove Domain IDs protection\n"));
86                 }
87                 return ret;
88         }
89         return true;
90 }
91
92 bool secrets_store_domain_sid(const char *domain, const struct dom_sid  *sid)
93 {
94         char *protect_ids;
95         bool ret;
96
97         protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
98         if (protect_ids) {
99                 if (strncmp(protect_ids, "TRUE", 4)) {
100                         DEBUG(0, ("Refusing to store a Domain SID, "
101                                   "it has been marked as protected!\n"));
102                         SAFE_FREE(protect_ids);
103                         return false;
104                 }
105         }
106         SAFE_FREE(protect_ids);
107
108         ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
109
110         /* Force a re-query, in the case where we modified our domain */
111         if (ret) {
112                 if (dom_sid_equal(get_global_sam_sid(), sid) == false) {
113                         reset_global_sam_sid();
114                 }
115         }
116         return ret;
117 }
118
119 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid  *sid)
120 {
121         struct dom_sid  *dyn_sid;
122         size_t size = 0;
123
124         dyn_sid = (struct dom_sid  *)secrets_fetch(domain_sid_keystr(domain), &size);
125
126         if (dyn_sid == NULL)
127                 return False;
128
129         if (size != sizeof(struct dom_sid)) {
130                 SAFE_FREE(dyn_sid);
131                 return False;
132         }
133
134         *sid = *dyn_sid;
135         SAFE_FREE(dyn_sid);
136         return True;
137 }
138
139 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
140 {
141         char *protect_ids;
142         fstring key;
143
144         protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
145         if (protect_ids) {
146                 if (strncmp(protect_ids, "TRUE", 4)) {
147                         DEBUG(0, ("Refusing to store a Domain SID, "
148                                   "it has been marked as protected!\n"));
149                         SAFE_FREE(protect_ids);
150                         return false;
151                 }
152         }
153         SAFE_FREE(protect_ids);
154
155         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
156         if (!strupper_m(key)) {
157                 return false;
158         }
159         return secrets_store(key, guid, sizeof(struct GUID));
160 }
161
162 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
163 {
164         struct GUID *dyn_guid;
165         fstring key;
166         size_t size = 0;
167         struct GUID new_guid;
168
169         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
170         if (!strupper_m(key)) {
171                 return false;
172         }
173         dyn_guid = (struct GUID *)secrets_fetch(key, &size);
174
175         if (!dyn_guid) {
176                 if (lp_server_role() == ROLE_DOMAIN_PDC) {
177                         new_guid = GUID_random();
178                         if (!secrets_store_domain_guid(domain, &new_guid))
179                                 return False;
180                         dyn_guid = (struct GUID *)secrets_fetch(key, &size);
181                 }
182                 if (dyn_guid == NULL) {
183                         return False;
184                 }
185         }
186
187         if (size != sizeof(struct GUID)) {
188                 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
189                 SAFE_FREE(dyn_guid);
190                 return False;
191         }
192
193         *guid = *dyn_guid;
194         SAFE_FREE(dyn_guid);
195         return True;
196 }
197
198 /**
199  * Form a key for fetching the machine trust account sec channel type
200  *
201  * @param domain domain name
202  *
203  * @return keystring
204  **/
205 static const char *machine_sec_channel_type_keystr(const char *domain)
206 {
207         char *keystr;
208
209         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
210                                             SECRETS_MACHINE_SEC_CHANNEL_TYPE,
211                                             domain);
212         SMB_ASSERT(keystr != NULL);
213         return keystr;
214 }
215
216 /**
217  * Form a key for fetching the machine trust account last change time
218  *
219  * @param domain domain name
220  *
221  * @return keystring
222  **/
223 static const char *machine_last_change_time_keystr(const char *domain)
224 {
225         char *keystr;
226
227         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
228                                             SECRETS_MACHINE_LAST_CHANGE_TIME,
229                                             domain);
230         SMB_ASSERT(keystr != NULL);
231         return keystr;
232 }
233
234
235 /**
236  * Form a key for fetching the machine previous trust account password
237  *
238  * @param domain domain name
239  *
240  * @return keystring
241  **/
242 static const char *machine_prev_password_keystr(const char *domain)
243 {
244         char *keystr;
245
246         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
247                                             SECRETS_MACHINE_PASSWORD_PREV, domain);
248         SMB_ASSERT(keystr != NULL);
249         return keystr;
250 }
251
252 /**
253  * Form a key for fetching the machine trust account password
254  *
255  * @param domain domain name
256  *
257  * @return keystring
258  **/
259 static const char *machine_password_keystr(const char *domain)
260 {
261         char *keystr;
262
263         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
264                                             SECRETS_MACHINE_PASSWORD, domain);
265         SMB_ASSERT(keystr != NULL);
266         return keystr;
267 }
268
269 /**
270  * Form a key for fetching the machine trust account password
271  *
272  * @param domain domain name
273  *
274  * @return stored password's key
275  **/
276 static const char *trust_keystr(const char *domain)
277 {
278         char *keystr;
279
280         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
281                                             SECRETS_MACHINE_ACCT_PASS, domain);
282         SMB_ASSERT(keystr != NULL);
283         return keystr;
284 }
285
286 /************************************************************************
287  Lock the trust password entry.
288 ************************************************************************/
289
290 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
291 {
292         struct db_context *db_ctx;
293         if (!secrets_init()) {
294                 return NULL;
295         }
296
297         db_ctx = secrets_db_ctx();
298
299         return dbwrap_fetch_locked(
300                 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
301 }
302
303 /************************************************************************
304  Routine to get the default secure channel type for trust accounts
305 ************************************************************************/
306
307 enum netr_SchannelType get_default_sec_channel(void)
308 {
309         if (lp_server_role() == ROLE_DOMAIN_BDC ||
310             lp_server_role() == ROLE_DOMAIN_PDC ||
311             lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
312                 return SEC_CHAN_BDC;
313         } else {
314                 return SEC_CHAN_WKSTA;
315         }
316 }
317
318 /************************************************************************
319  Routine to get the trust account password for a domain.
320  This only tries to get the legacy hashed version of the password.
321  The user of this function must have locked the trust password file using
322  the above secrets_lock_trust_account_password().
323 ************************************************************************/
324
325 bool secrets_fetch_trust_account_password_legacy(const char *domain,
326                                                  uint8_t ret_pwd[16],
327                                                  time_t *pass_last_set_time,
328                                                  enum netr_SchannelType *channel)
329 {
330         struct machine_acct_pass *pass;
331         size_t size = 0;
332
333         if (!(pass = (struct machine_acct_pass *)secrets_fetch(
334                       trust_keystr(domain), &size))) {
335                 DEBUG(5, ("secrets_fetch failed!\n"));
336                 return False;
337         }
338
339         if (size != sizeof(*pass)) {
340                 DEBUG(0, ("secrets were of incorrect size!\n"));
341                 SAFE_FREE(pass);
342                 return False;
343         }
344
345         if (pass_last_set_time) {
346                 *pass_last_set_time = pass->mod_time;
347         }
348         memcpy(ret_pwd, pass->hash, 16);
349
350         if (channel) {
351                 *channel = get_default_sec_channel();
352         }
353
354         SAFE_FREE(pass);
355         return True;
356 }
357
358 /************************************************************************
359  Routine to get the trust account password for a domain.
360  The user of this function must have locked the trust password file using
361  the above secrets_lock_trust_account_password().
362 ************************************************************************/
363
364 bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16],
365                                           time_t *pass_last_set_time,
366                                           enum netr_SchannelType *channel)
367 {
368         char *plaintext;
369
370         plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
371                                                    channel);
372         if (plaintext) {
373                 DEBUG(4,("Using cleartext machine password\n"));
374                 E_md4hash(plaintext, ret_pwd);
375                 SAFE_FREE(plaintext);
376                 return True;
377         }
378
379         return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
380                                                            pass_last_set_time,
381                                                            channel);
382 }
383
384 /************************************************************************
385  Routine to delete the old plaintext machine account password if any
386 ************************************************************************/
387
388 static bool secrets_delete_prev_machine_password(const char *domain)
389 {
390         char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
391         if (oldpass == NULL) {
392                 return true;
393         }
394         SAFE_FREE(oldpass);
395         return secrets_delete(machine_prev_password_keystr(domain));
396 }
397
398 /************************************************************************
399  Routine to delete the plaintext machine account password, old password,
400  sec channel type and last change time from secrets database
401 ************************************************************************/
402
403 bool secrets_delete_machine_password_ex(const char *domain)
404 {
405         if (!secrets_delete_prev_machine_password(domain)) {
406                 return false;
407         }
408         if (!secrets_delete(machine_password_keystr(domain))) {
409                 return false;
410         }
411         if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
412                 return false;
413         }
414         return secrets_delete(machine_last_change_time_keystr(domain));
415 }
416
417 /************************************************************************
418  Routine to delete the domain sid
419 ************************************************************************/
420
421 bool secrets_delete_domain_sid(const char *domain)
422 {
423         return secrets_delete(domain_sid_keystr(domain));
424 }
425
426 /************************************************************************
427  Routine to store the previous machine password (by storing the current password
428  as the old)
429 ************************************************************************/
430
431 static bool secrets_store_prev_machine_password(const char *domain)
432 {
433         char *oldpass;
434         bool ret;
435
436         oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
437         if (oldpass == NULL) {
438                 return true;
439         }
440         ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
441         SAFE_FREE(oldpass);
442         return ret;
443 }
444
445 /************************************************************************
446  Routine to set the plaintext machine account password for a realm
447  the password is assumed to be a null terminated ascii string.
448  Before storing
449 ************************************************************************/
450
451 bool secrets_store_machine_password(const char *pass, const char *domain,
452                                     enum netr_SchannelType sec_channel)
453 {
454         bool ret;
455         uint32_t last_change_time;
456         uint32_t sec_channel_type;
457
458         if (!secrets_store_prev_machine_password(domain)) {
459                 return false;
460         }
461
462         ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
463         if (!ret)
464                 return ret;
465
466         SIVAL(&last_change_time, 0, time(NULL));
467         ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
468
469         SIVAL(&sec_channel_type, 0, sec_channel);
470         ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
471
472         return ret;
473 }
474
475 /************************************************************************
476  Set the machine trust account password, the old pw and last change
477  time, domain SID and salting principals based on values passed in
478  (added to supprt the secrets_tdb_sync module on secrets.ldb)
479 ************************************************************************/
480
481 bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const char *domain,
482                                    const char *realm,
483                                    const char *salting_principal, uint32_t supported_enc_types,
484                                    const struct dom_sid *domain_sid, uint32_t last_change_time,
485                                    bool delete_join)
486 {
487         bool ret;
488         uint8_t last_change_time_store[4];
489         TALLOC_CTX *frame = talloc_stackframe();
490         void *value;
491
492         if (delete_join) {
493                 secrets_delete_machine_password_ex(domain);
494                 secrets_delete_domain_sid(domain);
495                 TALLOC_FREE(frame);
496                 return true;
497         }
498
499         ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
500         if (!ret) {
501                 TALLOC_FREE(frame);
502                 return ret;
503         }
504
505         if (oldpass) {
506                 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
507         } else {
508                 value = secrets_fetch_prev_machine_password(domain);
509                 if (value) {
510                         SAFE_FREE(value);
511                         ret = secrets_delete_prev_machine_password(domain);
512                 }
513         }
514         if (!ret) {
515                 TALLOC_FREE(frame);
516                 return ret;
517         }
518
519         /* We delete this and instead have the read code fall back to
520          * a default based on server role, as our caller can't specify
521          * this with any more certainty */
522         value = secrets_fetch(machine_sec_channel_type_keystr(domain), NULL);
523         if (value) {
524                 SAFE_FREE(value);
525                 ret = secrets_delete(machine_sec_channel_type_keystr(domain));
526                 if (!ret) {
527                         TALLOC_FREE(frame);
528                         return ret;
529                 }
530         }
531
532         SIVAL(&last_change_time_store, 0, last_change_time);
533         ret = secrets_store(machine_last_change_time_keystr(domain),
534                             &last_change_time_store, sizeof(last_change_time));
535
536         if (!ret) {
537                 TALLOC_FREE(frame);
538                 return ret;
539         }
540
541         ret = secrets_store_domain_sid(domain, domain_sid);
542
543         if (!ret) {
544                 TALLOC_FREE(frame);
545                 return ret;
546         }
547
548         if (realm && salting_principal) {
549                 char *key = talloc_asprintf(frame, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, realm);
550                 if (!key) {
551                         TALLOC_FREE(frame);
552                         return false;
553                 }
554                 ret = secrets_store(key, salting_principal, strlen(salting_principal)+1 );
555         }
556
557         TALLOC_FREE(frame);
558         return ret;
559 }
560
561
562 /************************************************************************
563  Routine to fetch the previous plaintext machine account password for a realm
564  the password is assumed to be a null terminated ascii string.
565 ************************************************************************/
566
567 char *secrets_fetch_prev_machine_password(const char *domain)
568 {
569         return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
570 }
571
572 /************************************************************************
573  Routine to fetch the plaintext machine account password for a realm
574  the password is assumed to be a null terminated ascii string.
575 ************************************************************************/
576
577 char *secrets_fetch_machine_password(const char *domain,
578                                      time_t *pass_last_set_time,
579                                      enum netr_SchannelType *channel)
580 {
581         char *ret;
582         ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
583
584         if (pass_last_set_time) {
585                 size_t size;
586                 uint32_t *last_set_time;
587                 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
588                 if (last_set_time) {
589                         *pass_last_set_time = IVAL(last_set_time,0);
590                         SAFE_FREE(last_set_time);
591                 } else {
592                         *pass_last_set_time = 0;
593                 }
594         }
595
596         if (channel) {
597                 size_t size;
598                 uint32_t *channel_type;
599                 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
600                 if (channel_type) {
601                         *channel = IVAL(channel_type,0);
602                         SAFE_FREE(channel_type);
603                 } else {
604                         *channel = get_default_sec_channel();
605                 }
606         }
607
608         return ret;
609 }