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