s3:smb2_server: add SMB3 encryption support
[Samba/gebeck_regimport.git] / source3 / passdb / machine_account_secrets.c
blobebd7b4cc56d594eb0547db0cf778eb47bce6ae8c
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
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.
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.
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/>.
22 /* the Samba secrets database stores any generated, private information
23 such as the local SID and machine trust password */
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"
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_PASSDB
36 /**
37 * Form a key for fetching the domain sid
39 * @param domain domain name
41 * @return keystring
42 **/
43 static const char *domain_sid_keystr(const char *domain)
45 char *keystr;
47 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
48 SECRETS_DOMAIN_SID, domain);
49 SMB_ASSERT(keystr != NULL);
50 return keystr;
53 static const char *protect_ids_keystr(const char *domain)
55 char *keystr;
57 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
58 SECRETS_PROTECT_IDS, domain);
59 SMB_ASSERT(keystr != NULL);
60 return keystr;
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)
66 bool ret;
68 ret = secrets_store(protect_ids_keystr(domain), "TRUE", 5);
69 if (!ret) {
70 DEBUG(0, ("Failed to protect the Domain IDs\n"));
72 return ret;
75 bool secrets_clear_domain_protection(const char *domain)
77 bool ret;
78 void *protection = secrets_fetch(protect_ids_keystr(domain), NULL);
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"));
86 return ret;
88 return true;
91 bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid)
93 #if _SAMBA_BUILD_ == 4
94 char *protect_ids;
95 #endif
96 bool ret;
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 return false;
107 #endif
109 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
111 /* Force a re-query, in case we modified our domain */
112 if (ret)
113 reset_global_sam_sid();
114 return ret;
117 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid)
119 struct dom_sid *dyn_sid;
120 size_t size = 0;
122 dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size);
124 if (dyn_sid == NULL)
125 return False;
127 if (size != sizeof(struct dom_sid)) {
128 SAFE_FREE(dyn_sid);
129 return False;
132 *sid = *dyn_sid;
133 SAFE_FREE(dyn_sid);
134 return True;
137 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
139 #if _SAMBA_BUILD_ == 4
140 char *protect_ids;
141 #endif
142 fstring key;
144 #if _SAMBA_BUILD_ == 4
145 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
146 if (protect_ids) {
147 if (strncmp(protect_ids, "TRUE", 4)) {
148 DEBUG(0, ("Refusing to store a Domain SID, "
149 "it has been marked as protected!\n"));
150 return false;
153 #endif
155 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
156 if (!strupper_m(key)) {
157 return false;
159 return secrets_store(key, guid, sizeof(struct GUID));
162 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
164 struct GUID *dyn_guid;
165 fstring key;
166 size_t size = 0;
167 struct GUID new_guid;
169 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
170 if (!strupper_m(key)) {
171 return false;
173 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
175 if (!dyn_guid) {
176 if (lp_server_role() == ROLE_DOMAIN_PDC) {
177 new_guid = GUID_random();
178 if (!secrets_store_domain_guid(domain, &new_guid))
179 return False;
180 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
182 if (dyn_guid == NULL) {
183 return False;
187 if (size != sizeof(struct GUID)) {
188 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
189 SAFE_FREE(dyn_guid);
190 return False;
193 *guid = *dyn_guid;
194 SAFE_FREE(dyn_guid);
195 return True;
199 * Form a key for fetching the machine trust account sec channel type
201 * @param domain domain name
203 * @return keystring
205 static const char *machine_sec_channel_type_keystr(const char *domain)
207 char *keystr;
209 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
210 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
211 domain);
212 SMB_ASSERT(keystr != NULL);
213 return keystr;
217 * Form a key for fetching the machine trust account last change time
219 * @param domain domain name
221 * @return keystring
223 static const char *machine_last_change_time_keystr(const char *domain)
225 char *keystr;
227 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
228 SECRETS_MACHINE_LAST_CHANGE_TIME,
229 domain);
230 SMB_ASSERT(keystr != NULL);
231 return keystr;
236 * Form a key for fetching the machine previous trust account password
238 * @param domain domain name
240 * @return keystring
242 static const char *machine_prev_password_keystr(const char *domain)
244 char *keystr;
246 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
247 SECRETS_MACHINE_PASSWORD_PREV, domain);
248 SMB_ASSERT(keystr != NULL);
249 return keystr;
253 * Form a key for fetching the machine trust account password
255 * @param domain domain name
257 * @return keystring
259 static const char *machine_password_keystr(const char *domain)
261 char *keystr;
263 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
264 SECRETS_MACHINE_PASSWORD, domain);
265 SMB_ASSERT(keystr != NULL);
266 return keystr;
270 * Form a key for fetching the machine trust account password
272 * @param domain domain name
274 * @return stored password's key
276 static const char *trust_keystr(const char *domain)
278 char *keystr;
280 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
281 SECRETS_MACHINE_ACCT_PASS, domain);
282 SMB_ASSERT(keystr != NULL);
283 return keystr;
286 /************************************************************************
287 Lock the trust password entry.
288 ************************************************************************/
290 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
292 struct db_context *db_ctx;
293 if (!secrets_init()) {
294 return NULL;
297 db_ctx = secrets_db_ctx();
299 return dbwrap_fetch_locked(
300 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
303 /************************************************************************
304 Routine to get the default secure channel type for trust accounts
305 ************************************************************************/
307 enum netr_SchannelType get_default_sec_channel(void)
309 if (lp_server_role() == ROLE_DOMAIN_BDC ||
310 lp_server_role() == ROLE_DOMAIN_PDC) {
311 return SEC_CHAN_BDC;
312 } else {
313 return SEC_CHAN_WKSTA;
317 /************************************************************************
318 Routine to get the trust account password for a domain.
319 This only tries to get the legacy hashed version of the password.
320 The user of this function must have locked the trust password file using
321 the above secrets_lock_trust_account_password().
322 ************************************************************************/
324 bool secrets_fetch_trust_account_password_legacy(const char *domain,
325 uint8_t ret_pwd[16],
326 time_t *pass_last_set_time,
327 enum netr_SchannelType *channel)
329 struct machine_acct_pass *pass;
330 size_t size = 0;
332 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
333 trust_keystr(domain), &size))) {
334 DEBUG(5, ("secrets_fetch failed!\n"));
335 return False;
338 if (size != sizeof(*pass)) {
339 DEBUG(0, ("secrets were of incorrect size!\n"));
340 SAFE_FREE(pass);
341 return False;
344 if (pass_last_set_time) {
345 *pass_last_set_time = pass->mod_time;
347 memcpy(ret_pwd, pass->hash, 16);
349 if (channel) {
350 *channel = get_default_sec_channel();
353 SAFE_FREE(pass);
354 return True;
357 /************************************************************************
358 Routine to get the trust account password for a domain.
359 The user of this function must have locked the trust password file using
360 the above secrets_lock_trust_account_password().
361 ************************************************************************/
363 bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16],
364 time_t *pass_last_set_time,
365 enum netr_SchannelType *channel)
367 char *plaintext;
369 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
370 channel);
371 if (plaintext) {
372 DEBUG(4,("Using cleartext machine password\n"));
373 E_md4hash(plaintext, ret_pwd);
374 SAFE_FREE(plaintext);
375 return True;
378 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
379 pass_last_set_time,
380 channel);
383 /************************************************************************
384 Routine to delete the old plaintext machine account password if any
385 ************************************************************************/
387 static bool secrets_delete_prev_machine_password(const char *domain)
389 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
390 if (oldpass == NULL) {
391 return true;
393 SAFE_FREE(oldpass);
394 return secrets_delete(machine_prev_password_keystr(domain));
397 /************************************************************************
398 Routine to delete the plaintext machine account password, old password,
399 sec channel type and last change time from secrets database
400 ************************************************************************/
402 bool secrets_delete_machine_password_ex(const char *domain)
404 if (!secrets_delete_prev_machine_password(domain)) {
405 return false;
407 if (!secrets_delete(machine_password_keystr(domain))) {
408 return false;
410 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
411 return false;
413 return secrets_delete(machine_last_change_time_keystr(domain));
416 /************************************************************************
417 Routine to delete the domain sid
418 ************************************************************************/
420 bool secrets_delete_domain_sid(const char *domain)
422 return secrets_delete(domain_sid_keystr(domain));
425 /************************************************************************
426 Routine to store the previous machine password (by storing the current password
427 as the old)
428 ************************************************************************/
430 static bool secrets_store_prev_machine_password(const char *domain)
432 char *oldpass;
433 bool ret;
435 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
436 if (oldpass == NULL) {
437 return true;
439 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
440 SAFE_FREE(oldpass);
441 return ret;
444 /************************************************************************
445 Routine to set the plaintext machine account password for a realm
446 the password is assumed to be a null terminated ascii string.
447 Before storing
448 ************************************************************************/
450 bool secrets_store_machine_password(const char *pass, const char *domain,
451 enum netr_SchannelType sec_channel)
453 bool ret;
454 uint32_t last_change_time;
455 uint32_t sec_channel_type;
457 if (!secrets_store_prev_machine_password(domain)) {
458 return false;
461 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
462 if (!ret)
463 return ret;
465 SIVAL(&last_change_time, 0, time(NULL));
466 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
468 SIVAL(&sec_channel_type, 0, sec_channel);
469 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
471 return ret;
475 /************************************************************************
476 Routine to fetch the previous plaintext machine account password for a realm
477 the password is assumed to be a null terminated ascii string.
478 ************************************************************************/
480 char *secrets_fetch_prev_machine_password(const char *domain)
482 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
485 /************************************************************************
486 Routine to fetch the plaintext machine account password for a realm
487 the password is assumed to be a null terminated ascii string.
488 ************************************************************************/
490 char *secrets_fetch_machine_password(const char *domain,
491 time_t *pass_last_set_time,
492 enum netr_SchannelType *channel)
494 char *ret;
495 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
497 if (pass_last_set_time) {
498 size_t size;
499 uint32_t *last_set_time;
500 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
501 if (last_set_time) {
502 *pass_last_set_time = IVAL(last_set_time,0);
503 SAFE_FREE(last_set_time);
504 } else {
505 *pass_last_set_time = 0;
509 if (channel) {
510 size_t size;
511 uint32_t *channel_type;
512 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
513 if (channel_type) {
514 *channel = IVAL(channel_type,0);
515 SAFE_FREE(channel_type);
516 } else {
517 *channel = get_default_sec_channel();
521 return ret;