565c7c4c2022f20d75a9f12aace4d9c6e2b564d2
[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 /* Urrrg. global.... */
37 bool global_machine_password_needs_changing;
38
39 /**
40  * Form a key for fetching the domain sid
41  *
42  * @param domain domain name
43  *
44  * @return keystring
45  **/
46 static const char *domain_sid_keystr(const char *domain)
47 {
48         char *keystr;
49
50         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
51                                             SECRETS_DOMAIN_SID, domain);
52         SMB_ASSERT(keystr != NULL);
53         return keystr;
54 }
55
56 bool secrets_store_domain_sid(const char *domain, const struct dom_sid  *sid)
57 {
58         bool ret;
59
60 #if _SAMBA_BUILD_ == 4
61         if (strequal(domain, get_global_sam_name()) &&
62             (pdb_capabilities() & PDB_CAP_ADS)) {
63                 /* If we have a ADS-capable passdb backend, we
64                  * must never make up our own SID, it will
65                  * already be in the directory */
66                 DEBUG(0, ("Refusing to store a Domain SID, this should be read from the directory not stored here\n"));
67                 return false;
68         }
69 #endif
70
71         ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
72
73         /* Force a re-query, in case we modified our domain */
74         if (ret)
75                 reset_global_sam_sid();
76         return ret;
77 }
78
79 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid  *sid)
80 {
81         struct dom_sid  *dyn_sid;
82         size_t size = 0;
83
84 #if _SAMBA_BUILD_ == 4
85         if (strequal(domain, get_global_sam_name()) &&
86             (pdb_capabilities() & PDB_CAP_ADS)) {
87                 struct pdb_domain_info *domain_info;
88                 domain_info = pdb_get_domain_info(talloc_tos());
89                 if (!domain_info) {
90                         /* If we have a ADS-capable passdb backend, we
91                          * must never make up our own SID, it will
92                          * already be in the directory */
93                         DEBUG(0, ("Unable to fetch a Domain SID from the directory!\n"));
94                         return false;
95                 }
96
97                 *sid = domain_info->sid;
98                 return true;
99         }
100 #endif
101
102         dyn_sid = (struct dom_sid  *)secrets_fetch(domain_sid_keystr(domain), &size);
103
104         if (dyn_sid == NULL)
105                 return False;
106
107         if (size != sizeof(struct dom_sid)) {
108                 SAFE_FREE(dyn_sid);
109                 return False;
110         }
111
112         *sid = *dyn_sid;
113         SAFE_FREE(dyn_sid);
114         return True;
115 }
116
117 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
118 {
119         fstring key;
120
121 #if _SAMBA_BUILD_ == 4
122         if (strequal(domain, get_global_sam_name()) &&
123             (pdb_capabilities() & PDB_CAP_ADS)) {
124                 /* If we have a ADS-capable passdb backend, we
125                  * must never make up our own GUID, it will
126                  * already be in the directory */
127                 DEBUG(0, ("Refusing to store a Domain GUID, this should be read from the directory not stored here\n"));
128                 return false;
129         }
130 #endif
131
132         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
133         strupper_m(key);
134         return secrets_store(key, guid, sizeof(struct GUID));
135 }
136
137 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
138 {
139         struct GUID *dyn_guid;
140         fstring key;
141         size_t size = 0;
142         struct GUID new_guid;
143
144 #if _SAMBA_BUILD_ == 4
145         if (strequal(domain, get_global_sam_name()) &&
146             (pdb_capabilities() & PDB_CAP_ADS)) {
147                 struct pdb_domain_info *domain_info;
148                 domain_info = pdb_get_domain_info(talloc_tos());
149                 if (!domain_info) {
150                         /* If we have a ADS-capable passdb backend, we
151                          * must never make up our own SID, it will
152                          * already be in the directory */
153                         DEBUG(0, ("Unable to fetch a Domain GUID from the directory!\n"));
154                         return false;
155                 }
156
157                 *guid = domain_info->guid;
158                 return true;
159         }
160 #endif
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         /* Test if machine password has expired and needs to be changed */
345         if (lp_machine_password_timeout()) {
346                 if (pass->mod_time > 0 && time(NULL) > (pass->mod_time +
347                                 (time_t)lp_machine_password_timeout())) {
348                         global_machine_password_needs_changing = True;
349                 }
350         }
351
352         SAFE_FREE(pass);
353         return True;
354 }
355
356 /************************************************************************
357  Routine to get the trust account password for a domain.
358  The user of this function must have locked the trust password file using
359  the above secrets_lock_trust_account_password().
360 ************************************************************************/
361
362 bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
363                                           time_t *pass_last_set_time,
364                                           enum netr_SchannelType *channel)
365 {
366         char *plaintext;
367
368         plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
369                                                    channel);
370         if (plaintext) {
371                 DEBUG(4,("Using cleartext machine password\n"));
372                 E_md4hash(plaintext, ret_pwd);
373                 SAFE_FREE(plaintext);
374                 return True;
375         }
376
377         return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
378                                                            pass_last_set_time,
379                                                            channel);
380 }
381
382 /************************************************************************
383  Routine to delete the old plaintext machine account password if any
384 ************************************************************************/
385
386 static bool secrets_delete_prev_machine_password(const char *domain)
387 {
388         char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
389         if (oldpass == NULL) {
390                 return true;
391         }
392         SAFE_FREE(oldpass);
393         return secrets_delete(machine_prev_password_keystr(domain));
394 }
395
396 /************************************************************************
397  Routine to delete the plaintext machine account password and old
398  password if any
399 ************************************************************************/
400
401 bool secrets_delete_machine_password(const char *domain)
402 {
403         if (!secrets_delete_prev_machine_password(domain)) {
404                 return false;
405         }
406         return secrets_delete(machine_password_keystr(domain));
407 }
408
409 /************************************************************************
410  Routine to delete the plaintext machine account password, old password,
411  sec channel type and last change time from secrets database
412 ************************************************************************/
413
414 bool secrets_delete_machine_password_ex(const char *domain)
415 {
416         if (!secrets_delete_prev_machine_password(domain)) {
417                 return false;
418         }
419         if (!secrets_delete(machine_password_keystr(domain))) {
420                 return false;
421         }
422         if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
423                 return false;
424         }
425         return secrets_delete(machine_last_change_time_keystr(domain));
426 }
427
428 /************************************************************************
429  Routine to delete the domain sid
430 ************************************************************************/
431
432 bool secrets_delete_domain_sid(const char *domain)
433 {
434         return secrets_delete(domain_sid_keystr(domain));
435 }
436
437 /************************************************************************
438  Routine to store the previous machine password (by storing the current password
439  as the old)
440 ************************************************************************/
441
442 static bool secrets_store_prev_machine_password(const char *domain)
443 {
444         char *oldpass;
445         bool ret;
446
447         oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
448         if (oldpass == NULL) {
449                 return true;
450         }
451         ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
452         SAFE_FREE(oldpass);
453         return ret;
454 }
455
456 /************************************************************************
457  Routine to set the plaintext machine account password for a realm
458  the password is assumed to be a null terminated ascii string.
459  Before storing
460 ************************************************************************/
461
462 bool secrets_store_machine_password(const char *pass, const char *domain,
463                                     enum netr_SchannelType sec_channel)
464 {
465         bool ret;
466         uint32 last_change_time;
467         uint32 sec_channel_type;
468
469         if (!secrets_store_prev_machine_password(domain)) {
470                 return false;
471         }
472
473         ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
474         if (!ret)
475                 return ret;
476
477         SIVAL(&last_change_time, 0, time(NULL));
478         ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
479
480         SIVAL(&sec_channel_type, 0, sec_channel);
481         ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
482
483         return ret;
484 }
485
486
487 /************************************************************************
488  Routine to fetch the previous plaintext machine account password for a realm
489  the password is assumed to be a null terminated ascii string.
490 ************************************************************************/
491
492 char *secrets_fetch_prev_machine_password(const char *domain)
493 {
494         return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
495 }
496
497 /************************************************************************
498  Routine to fetch the plaintext machine account password for a realm
499  the password is assumed to be a null terminated ascii string.
500 ************************************************************************/
501
502 char *secrets_fetch_machine_password(const char *domain,
503                                      time_t *pass_last_set_time,
504                                      enum netr_SchannelType *channel)
505 {
506         char *ret;
507         ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
508
509         if (pass_last_set_time) {
510                 size_t size;
511                 uint32 *last_set_time;
512                 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
513                 if (last_set_time) {
514                         *pass_last_set_time = IVAL(last_set_time,0);
515                         SAFE_FREE(last_set_time);
516                 } else {
517                         *pass_last_set_time = 0;
518                 }
519         }
520
521         if (channel) {
522                 size_t size;
523                 uint32 *channel_type;
524                 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
525                 if (channel_type) {
526                         *channel = IVAL(channel_type,0);
527                         SAFE_FREE(channel_type);
528                 } else {
529                         *channel = get_default_sec_channel();
530                 }
531         }
532
533         return ret;
534 }