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