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