a4b5709b283e1ca52efa748ddd625b0083800fa8
[vlendec/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
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
79         ret = secrets_delete(protect_ids_keystr(domain));
80         if (!ret) {
81                 DEBUG(0, ("Failed to remove Domain IDs protection\n"));
82         }
83         return ret;
84 }
85
86 bool secrets_store_domain_sid(const char *domain, const struct dom_sid  *sid)
87 {
88 #if _SAMBA_BUILD_ == 4
89         char *protect_ids;
90 #endif
91         bool ret;
92
93 #if _SAMBA_BUILD_ == 4
94         protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
95         if (protect_ids) {
96                 if (strncmp(protect_ids, "TRUE", 4)) {
97                         DEBUG(0, ("Refusing to store a Domain SID, "
98                                   "it has been marked as protected!\n"));
99                         return false;
100                 }
101         }
102 #endif
103
104         ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
105
106         /* Force a re-query, in case we modified our domain */
107         if (ret)
108                 reset_global_sam_sid();
109         return ret;
110 }
111
112 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid  *sid)
113 {
114         struct dom_sid  *dyn_sid;
115         size_t size = 0;
116
117         dyn_sid = (struct dom_sid  *)secrets_fetch(domain_sid_keystr(domain), &size);
118
119         if (dyn_sid == NULL)
120                 return False;
121
122         if (size != sizeof(struct dom_sid)) {
123                 SAFE_FREE(dyn_sid);
124                 return False;
125         }
126
127         *sid = *dyn_sid;
128         SAFE_FREE(dyn_sid);
129         return True;
130 }
131
132 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
133 {
134 #if _SAMBA_BUILD_ == 4
135         char *protect_ids;
136 #endif
137         fstring key;
138
139 #if _SAMBA_BUILD_ == 4
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                         return false;
146                 }
147         }
148 #endif
149
150         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
151         if (!strupper_m(key)) {
152                 return false;
153         }
154         return secrets_store(key, guid, sizeof(struct GUID));
155 }
156
157 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
158 {
159         struct GUID *dyn_guid;
160         fstring key;
161         size_t size = 0;
162         struct GUID new_guid;
163
164         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
165         if (!strupper_m(key)) {
166                 return false;
167         }
168         dyn_guid = (struct GUID *)secrets_fetch(key, &size);
169
170         if (!dyn_guid) {
171                 if (lp_server_role() == ROLE_DOMAIN_PDC) {
172                         new_guid = GUID_random();
173                         if (!secrets_store_domain_guid(domain, &new_guid))
174                                 return False;
175                         dyn_guid = (struct GUID *)secrets_fetch(key, &size);
176                 }
177                 if (dyn_guid == NULL) {
178                         return False;
179                 }
180         }
181
182         if (size != sizeof(struct GUID)) {
183                 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
184                 SAFE_FREE(dyn_guid);
185                 return False;
186         }
187
188         *guid = *dyn_guid;
189         SAFE_FREE(dyn_guid);
190         return True;
191 }
192
193 /**
194  * Form a key for fetching the machine trust account sec channel type
195  *
196  * @param domain domain name
197  *
198  * @return keystring
199  **/
200 static const char *machine_sec_channel_type_keystr(const char *domain)
201 {
202         char *keystr;
203
204         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
205                                             SECRETS_MACHINE_SEC_CHANNEL_TYPE,
206                                             domain);
207         SMB_ASSERT(keystr != NULL);
208         return keystr;
209 }
210
211 /**
212  * Form a key for fetching the machine trust account last change time
213  *
214  * @param domain domain name
215  *
216  * @return keystring
217  **/
218 static const char *machine_last_change_time_keystr(const char *domain)
219 {
220         char *keystr;
221
222         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
223                                             SECRETS_MACHINE_LAST_CHANGE_TIME,
224                                             domain);
225         SMB_ASSERT(keystr != NULL);
226         return keystr;
227 }
228
229
230 /**
231  * Form a key for fetching the machine previous trust account password
232  *
233  * @param domain domain name
234  *
235  * @return keystring
236  **/
237 static const char *machine_prev_password_keystr(const char *domain)
238 {
239         char *keystr;
240
241         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
242                                             SECRETS_MACHINE_PASSWORD_PREV, domain);
243         SMB_ASSERT(keystr != NULL);
244         return keystr;
245 }
246
247 /**
248  * Form a key for fetching the machine trust account password
249  *
250  * @param domain domain name
251  *
252  * @return keystring
253  **/
254 static const char *machine_password_keystr(const char *domain)
255 {
256         char *keystr;
257
258         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
259                                             SECRETS_MACHINE_PASSWORD, domain);
260         SMB_ASSERT(keystr != NULL);
261         return keystr;
262 }
263
264 /**
265  * Form a key for fetching the machine trust account password
266  *
267  * @param domain domain name
268  *
269  * @return stored password's key
270  **/
271 static const char *trust_keystr(const char *domain)
272 {
273         char *keystr;
274
275         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
276                                             SECRETS_MACHINE_ACCT_PASS, domain);
277         SMB_ASSERT(keystr != NULL);
278         return keystr;
279 }
280
281 /************************************************************************
282  Lock the trust password entry.
283 ************************************************************************/
284
285 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
286 {
287         struct db_context *db_ctx;
288         if (!secrets_init()) {
289                 return NULL;
290         }
291
292         db_ctx = secrets_db_ctx();
293
294         return dbwrap_fetch_locked(
295                 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
296 }
297
298 /************************************************************************
299  Routine to get the default secure channel type for trust accounts
300 ************************************************************************/
301
302 enum netr_SchannelType get_default_sec_channel(void)
303 {
304         if (lp_server_role() == ROLE_DOMAIN_BDC ||
305             lp_server_role() == ROLE_DOMAIN_PDC) {
306                 return SEC_CHAN_BDC;
307         } else {
308                 return SEC_CHAN_WKSTA;
309         }
310 }
311
312 /************************************************************************
313  Routine to get the trust account password for a domain.
314  This only tries to get the legacy hashed version of the password.
315  The user of this function must have locked the trust password file using
316  the above secrets_lock_trust_account_password().
317 ************************************************************************/
318
319 bool secrets_fetch_trust_account_password_legacy(const char *domain,
320                                                  uint8_t ret_pwd[16],
321                                                  time_t *pass_last_set_time,
322                                                  enum netr_SchannelType *channel)
323 {
324         struct machine_acct_pass *pass;
325         size_t size = 0;
326
327         if (!(pass = (struct machine_acct_pass *)secrets_fetch(
328                       trust_keystr(domain), &size))) {
329                 DEBUG(5, ("secrets_fetch failed!\n"));
330                 return False;
331         }
332
333         if (size != sizeof(*pass)) {
334                 DEBUG(0, ("secrets were of incorrect size!\n"));
335                 SAFE_FREE(pass);
336                 return False;
337         }
338
339         if (pass_last_set_time) {
340                 *pass_last_set_time = pass->mod_time;
341         }
342         memcpy(ret_pwd, pass->hash, 16);
343
344         if (channel) {
345                 *channel = get_default_sec_channel();
346         }
347
348         SAFE_FREE(pass);
349         return True;
350 }
351
352 /************************************************************************
353  Routine to get the trust account password for a domain.
354  The user of this function must have locked the trust password file using
355  the above secrets_lock_trust_account_password().
356 ************************************************************************/
357
358 bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16],
359                                           time_t *pass_last_set_time,
360                                           enum netr_SchannelType *channel)
361 {
362         char *plaintext;
363
364         plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
365                                                    channel);
366         if (plaintext) {
367                 DEBUG(4,("Using cleartext machine password\n"));
368                 E_md4hash(plaintext, ret_pwd);
369                 SAFE_FREE(plaintext);
370                 return True;
371         }
372
373         return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
374                                                            pass_last_set_time,
375                                                            channel);
376 }
377
378 /************************************************************************
379  Routine to delete the old plaintext machine account password if any
380 ************************************************************************/
381
382 static bool secrets_delete_prev_machine_password(const char *domain)
383 {
384         char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
385         if (oldpass == NULL) {
386                 return true;
387         }
388         SAFE_FREE(oldpass);
389         return secrets_delete(machine_prev_password_keystr(domain));
390 }
391
392 /************************************************************************
393  Routine to delete the plaintext machine account password, old password,
394  sec channel type and last change time from secrets database
395 ************************************************************************/
396
397 bool secrets_delete_machine_password_ex(const char *domain)
398 {
399         if (!secrets_delete_prev_machine_password(domain)) {
400                 return false;
401         }
402         if (!secrets_delete(machine_password_keystr(domain))) {
403                 return false;
404         }
405         if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
406                 return false;
407         }
408         return secrets_delete(machine_last_change_time_keystr(domain));
409 }
410
411 /************************************************************************
412  Routine to delete the domain sid
413 ************************************************************************/
414
415 bool secrets_delete_domain_sid(const char *domain)
416 {
417         return secrets_delete(domain_sid_keystr(domain));
418 }
419
420 /************************************************************************
421  Routine to store the previous machine password (by storing the current password
422  as the old)
423 ************************************************************************/
424
425 static bool secrets_store_prev_machine_password(const char *domain)
426 {
427         char *oldpass;
428         bool ret;
429
430         oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
431         if (oldpass == NULL) {
432                 return true;
433         }
434         ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
435         SAFE_FREE(oldpass);
436         return ret;
437 }
438
439 /************************************************************************
440  Routine to set the plaintext machine account password for a realm
441  the password is assumed to be a null terminated ascii string.
442  Before storing
443 ************************************************************************/
444
445 bool secrets_store_machine_password(const char *pass, const char *domain,
446                                     enum netr_SchannelType sec_channel)
447 {
448         bool ret;
449         uint32_t last_change_time;
450         uint32_t sec_channel_type;
451
452         if (!secrets_store_prev_machine_password(domain)) {
453                 return false;
454         }
455
456         ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
457         if (!ret)
458                 return ret;
459
460         SIVAL(&last_change_time, 0, time(NULL));
461         ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
462
463         SIVAL(&sec_channel_type, 0, sec_channel);
464         ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
465
466         return ret;
467 }
468
469
470 /************************************************************************
471  Routine to fetch the previous plaintext machine account password for a realm
472  the password is assumed to be a null terminated ascii string.
473 ************************************************************************/
474
475 char *secrets_fetch_prev_machine_password(const char *domain)
476 {
477         return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
478 }
479
480 /************************************************************************
481  Routine to fetch the plaintext machine account password for a realm
482  the password is assumed to be a null terminated ascii string.
483 ************************************************************************/
484
485 char *secrets_fetch_machine_password(const char *domain,
486                                      time_t *pass_last_set_time,
487                                      enum netr_SchannelType *channel)
488 {
489         char *ret;
490         ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
491
492         if (pass_last_set_time) {
493                 size_t size;
494                 uint32_t *last_set_time;
495                 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
496                 if (last_set_time) {
497                         *pass_last_set_time = IVAL(last_set_time,0);
498                         SAFE_FREE(last_set_time);
499                 } else {
500                         *pass_last_set_time = 0;
501                 }
502         }
503
504         if (channel) {
505                 size_t size;
506                 uint32_t *channel_type;
507                 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
508                 if (channel_type) {
509                         *channel = IVAL(channel_type,0);
510                         SAFE_FREE(channel_type);
511                 } else {
512                         *channel = get_default_sec_channel();
513                 }
514         }
515
516         return ret;
517 }