Update 4.2 Roadmap file
[mat/samba.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  Routine to get the default secure channel type for trust accounts
288 ************************************************************************/
289
290 enum netr_SchannelType get_default_sec_channel(void)
291 {
292         if (lp_server_role() == ROLE_DOMAIN_BDC ||
293             lp_server_role() == ROLE_DOMAIN_PDC ||
294             lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
295                 return SEC_CHAN_BDC;
296         } else {
297                 return SEC_CHAN_WKSTA;
298         }
299 }
300
301 /************************************************************************
302  Routine to get the trust account password for a domain.
303  This only tries to get the legacy hashed version of the password.
304  The user of this function must have locked the trust password file using
305  the above secrets_lock_trust_account_password().
306 ************************************************************************/
307
308 bool secrets_fetch_trust_account_password_legacy(const char *domain,
309                                                  uint8_t ret_pwd[16],
310                                                  time_t *pass_last_set_time,
311                                                  enum netr_SchannelType *channel)
312 {
313         struct machine_acct_pass *pass;
314         size_t size = 0;
315
316         if (!(pass = (struct machine_acct_pass *)secrets_fetch(
317                       trust_keystr(domain), &size))) {
318                 DEBUG(5, ("secrets_fetch failed!\n"));
319                 return False;
320         }
321
322         if (size != sizeof(*pass)) {
323                 DEBUG(0, ("secrets were of incorrect size!\n"));
324                 SAFE_FREE(pass);
325                 return False;
326         }
327
328         if (pass_last_set_time) {
329                 *pass_last_set_time = pass->mod_time;
330         }
331         memcpy(ret_pwd, pass->hash, 16);
332
333         if (channel) {
334                 *channel = get_default_sec_channel();
335         }
336
337         SAFE_FREE(pass);
338         return True;
339 }
340
341 /************************************************************************
342  Routine to get the trust account password for a domain.
343  The user of this function must have locked the trust password file using
344  the above secrets_lock_trust_account_password().
345 ************************************************************************/
346
347 bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16],
348                                           time_t *pass_last_set_time,
349                                           enum netr_SchannelType *channel)
350 {
351         char *plaintext;
352
353         plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
354                                                    channel);
355         if (plaintext) {
356                 DEBUG(4,("Using cleartext machine password\n"));
357                 E_md4hash(plaintext, ret_pwd);
358                 SAFE_FREE(plaintext);
359                 return True;
360         }
361
362         return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
363                                                            pass_last_set_time,
364                                                            channel);
365 }
366
367 /************************************************************************
368  Routine to delete the old plaintext machine account password if any
369 ************************************************************************/
370
371 static bool secrets_delete_prev_machine_password(const char *domain)
372 {
373         char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
374         if (oldpass == NULL) {
375                 return true;
376         }
377         SAFE_FREE(oldpass);
378         return secrets_delete(machine_prev_password_keystr(domain));
379 }
380
381 /************************************************************************
382  Routine to delete the plaintext machine account password, old password,
383  sec channel type and last change time from secrets database
384 ************************************************************************/
385
386 bool secrets_delete_machine_password_ex(const char *domain)
387 {
388         if (!secrets_delete_prev_machine_password(domain)) {
389                 return false;
390         }
391         if (!secrets_delete(machine_password_keystr(domain))) {
392                 return false;
393         }
394         if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
395                 return false;
396         }
397         return secrets_delete(machine_last_change_time_keystr(domain));
398 }
399
400 /************************************************************************
401  Routine to delete the domain sid
402 ************************************************************************/
403
404 bool secrets_delete_domain_sid(const char *domain)
405 {
406         return secrets_delete(domain_sid_keystr(domain));
407 }
408
409 /************************************************************************
410  Routine to store the previous machine password (by storing the current password
411  as the old)
412 ************************************************************************/
413
414 static bool secrets_store_prev_machine_password(const char *domain)
415 {
416         char *oldpass;
417         bool ret;
418
419         oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
420         if (oldpass == NULL) {
421                 return true;
422         }
423         ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
424         SAFE_FREE(oldpass);
425         return ret;
426 }
427
428 /************************************************************************
429  Routine to set the plaintext machine account password for a realm
430  the password is assumed to be a null terminated ascii string.
431  Before storing
432 ************************************************************************/
433
434 bool secrets_store_machine_password(const char *pass, const char *domain,
435                                     enum netr_SchannelType sec_channel)
436 {
437         bool ret;
438         uint32_t last_change_time;
439         uint32_t sec_channel_type;
440
441         if (!secrets_store_prev_machine_password(domain)) {
442                 return false;
443         }
444
445         ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
446         if (!ret)
447                 return ret;
448
449         SIVAL(&last_change_time, 0, time(NULL));
450         ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
451
452         SIVAL(&sec_channel_type, 0, sec_channel);
453         ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
454
455         return ret;
456 }
457
458 /************************************************************************
459  Set the machine trust account password, the old pw and last change
460  time, domain SID and salting principals based on values passed in
461  (added to supprt the secrets_tdb_sync module on secrets.ldb)
462 ************************************************************************/
463
464 bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const char *domain,
465                                    const char *realm,
466                                    const char *salting_principal, uint32_t supported_enc_types,
467                                    const struct dom_sid *domain_sid, uint32_t last_change_time,
468                                    uint32_t secure_channel_type,
469                                    bool delete_join)
470 {
471         bool ret;
472         uint8_t last_change_time_store[4];
473         TALLOC_CTX *frame = talloc_stackframe();
474         uint8_t sec_channel_bytes[4];
475         void *value;
476
477         if (delete_join) {
478                 secrets_delete_machine_password_ex(domain);
479                 secrets_delete_domain_sid(domain);
480                 TALLOC_FREE(frame);
481                 return true;
482         }
483
484         ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
485         if (!ret) {
486                 TALLOC_FREE(frame);
487                 return ret;
488         }
489
490         if (oldpass) {
491                 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
492         } else {
493                 value = secrets_fetch_prev_machine_password(domain);
494                 if (value) {
495                         SAFE_FREE(value);
496                         ret = secrets_delete_prev_machine_password(domain);
497                 }
498         }
499         if (!ret) {
500                 TALLOC_FREE(frame);
501                 return ret;
502         }
503
504         if (secure_channel_type == 0) {
505                 /* We delete this and instead have the read code fall back to
506                  * a default based on server role, as our caller can't specify
507                  * this with any more certainty */
508                 value = secrets_fetch(machine_sec_channel_type_keystr(domain), NULL);
509                 if (value) {
510                         SAFE_FREE(value);
511                         ret = secrets_delete(machine_sec_channel_type_keystr(domain));
512                         if (!ret) {
513                                 TALLOC_FREE(frame);
514                                 return ret;
515                         }
516                 }
517         } else {
518                 SIVAL(&sec_channel_bytes, 0, secure_channel_type);
519                 ret = secrets_store(machine_sec_channel_type_keystr(domain), 
520                                     &sec_channel_bytes, sizeof(sec_channel_bytes));
521                 if (!ret) {
522                         TALLOC_FREE(frame);
523                         return ret;
524                 }
525         }
526
527         SIVAL(&last_change_time_store, 0, last_change_time);
528         ret = secrets_store(machine_last_change_time_keystr(domain),
529                             &last_change_time_store, sizeof(last_change_time));
530
531         if (!ret) {
532                 TALLOC_FREE(frame);
533                 return ret;
534         }
535
536         ret = secrets_store_domain_sid(domain, domain_sid);
537
538         if (!ret) {
539                 TALLOC_FREE(frame);
540                 return ret;
541         }
542
543         if (realm && salting_principal) {
544                 char *key = talloc_asprintf(frame, "%s/DES/%s", SECRETS_SALTING_PRINCIPAL, realm);
545                 if (!key) {
546                         TALLOC_FREE(frame);
547                         return false;
548                 }
549                 ret = secrets_store(key, salting_principal, strlen(salting_principal)+1 );
550         }
551
552         TALLOC_FREE(frame);
553         return ret;
554 }
555
556
557 /************************************************************************
558  Routine to fetch the previous plaintext machine account password for a realm
559  the password is assumed to be a null terminated ascii string.
560 ************************************************************************/
561
562 char *secrets_fetch_prev_machine_password(const char *domain)
563 {
564         return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
565 }
566
567 /************************************************************************
568  Routine to fetch the plaintext machine account password for a realm
569  the password is assumed to be a null terminated ascii string.
570 ************************************************************************/
571
572 char *secrets_fetch_machine_password(const char *domain,
573                                      time_t *pass_last_set_time,
574                                      enum netr_SchannelType *channel)
575 {
576         char *ret;
577         ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
578
579         if (pass_last_set_time) {
580                 size_t size;
581                 uint32_t *last_set_time;
582                 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
583                 if (last_set_time) {
584                         *pass_last_set_time = IVAL(last_set_time,0);
585                         SAFE_FREE(last_set_time);
586                 } else {
587                         *pass_last_set_time = 0;
588                 }
589         }
590
591         if (channel) {
592                 size_t size;
593                 uint32_t *channel_type;
594                 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
595                 if (channel_type) {
596                         *channel = IVAL(channel_type,0);
597                         SAFE_FREE(channel_type);
598                 } else {
599                         *channel = get_default_sec_channel();
600                 }
601         }
602
603         return ret;
604 }