libcli/smb: pass smbXcli_tcon to smb2cli_write*()
[Samba/gebeck_regimport.git] / source3 / passdb / machine_account_secrets.c
blob30f5f822ff9dc5f8c0bfd68926cc75e5dd4a4341
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;
79 ret = secrets_delete(protect_ids_keystr(domain));
80 if (!ret) {
81 DEBUG(0, ("Failed to remove Domain IDs protection\n"));
83 return ret;
86 bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid)
88 #if _SAMBA_BUILD_ == 4
89 char *protect_ids;
90 #endif
91 bool ret;
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;
102 #endif
104 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
106 /* Force a re-query, in case we modified our domain */
107 if (ret)
108 reset_global_sam_sid();
109 return ret;
112 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid)
114 struct dom_sid *dyn_sid;
115 size_t size = 0;
117 dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size);
119 if (dyn_sid == NULL)
120 return False;
122 if (size != sizeof(struct dom_sid)) {
123 SAFE_FREE(dyn_sid);
124 return False;
127 *sid = *dyn_sid;
128 SAFE_FREE(dyn_sid);
129 return True;
132 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
134 #if _SAMBA_BUILD_ == 4
135 char *protect_ids;
136 #endif
137 fstring key;
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;
148 #endif
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));
155 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
157 struct GUID *dyn_guid;
158 fstring key;
159 size_t size = 0;
160 struct GUID new_guid;
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);
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);
173 if (dyn_guid == NULL) {
174 return False;
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;
184 *guid = *dyn_guid;
185 SAFE_FREE(dyn_guid);
186 return True;
190 * Form a key for fetching the machine trust account sec channel type
192 * @param domain domain name
194 * @return keystring
196 static const char *machine_sec_channel_type_keystr(const char *domain)
198 char *keystr;
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;
208 * Form a key for fetching the machine trust account last change time
210 * @param domain domain name
212 * @return keystring
214 static const char *machine_last_change_time_keystr(const char *domain)
216 char *keystr;
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;
227 * Form a key for fetching the machine previous trust account password
229 * @param domain domain name
231 * @return keystring
233 static const char *machine_prev_password_keystr(const char *domain)
235 char *keystr;
237 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
238 SECRETS_MACHINE_PASSWORD_PREV, domain);
239 SMB_ASSERT(keystr != NULL);
240 return keystr;
244 * Form a key for fetching the machine trust account password
246 * @param domain domain name
248 * @return keystring
250 static const char *machine_password_keystr(const char *domain)
252 char *keystr;
254 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
255 SECRETS_MACHINE_PASSWORD, domain);
256 SMB_ASSERT(keystr != NULL);
257 return keystr;
261 * Form a key for fetching the machine trust account password
263 * @param domain domain name
265 * @return stored password's key
267 static const char *trust_keystr(const char *domain)
269 char *keystr;
271 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
272 SECRETS_MACHINE_ACCT_PASS, domain);
273 SMB_ASSERT(keystr != NULL);
274 return keystr;
277 /************************************************************************
278 Lock the trust password entry.
279 ************************************************************************/
281 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
283 struct db_context *db_ctx;
284 if (!secrets_init()) {
285 return NULL;
288 db_ctx = secrets_db_ctx();
290 return dbwrap_fetch_locked(
291 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
294 /************************************************************************
295 Routine to get the default secure channel type for trust accounts
296 ************************************************************************/
298 enum netr_SchannelType get_default_sec_channel(void)
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;
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 ************************************************************************/
315 bool secrets_fetch_trust_account_password_legacy(const char *domain,
316 uint8_t ret_pwd[16],
317 time_t *pass_last_set_time,
318 enum netr_SchannelType *channel)
320 struct machine_acct_pass *pass;
321 size_t size = 0;
323 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
324 trust_keystr(domain), &size))) {
325 DEBUG(5, ("secrets_fetch failed!\n"));
326 return False;
329 if (size != sizeof(*pass)) {
330 DEBUG(0, ("secrets were of incorrect size!\n"));
331 SAFE_FREE(pass);
332 return False;
335 if (pass_last_set_time) {
336 *pass_last_set_time = pass->mod_time;
338 memcpy(ret_pwd, pass->hash, 16);
340 if (channel) {
341 *channel = get_default_sec_channel();
344 SAFE_FREE(pass);
345 return True;
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 ************************************************************************/
354 bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16],
355 time_t *pass_last_set_time,
356 enum netr_SchannelType *channel)
358 char *plaintext;
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;
369 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
370 pass_last_set_time,
371 channel);
374 /************************************************************************
375 Routine to delete the old plaintext machine account password if any
376 ************************************************************************/
378 static bool secrets_delete_prev_machine_password(const char *domain)
380 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
381 if (oldpass == NULL) {
382 return true;
384 SAFE_FREE(oldpass);
385 return secrets_delete(machine_prev_password_keystr(domain));
388 /************************************************************************
389 Routine to delete the plaintext machine account password, old password,
390 sec channel type and last change time from secrets database
391 ************************************************************************/
393 bool secrets_delete_machine_password_ex(const char *domain)
395 if (!secrets_delete_prev_machine_password(domain)) {
396 return false;
398 if (!secrets_delete(machine_password_keystr(domain))) {
399 return false;
401 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
402 return false;
404 return secrets_delete(machine_last_change_time_keystr(domain));
407 /************************************************************************
408 Routine to delete the domain sid
409 ************************************************************************/
411 bool secrets_delete_domain_sid(const char *domain)
413 return secrets_delete(domain_sid_keystr(domain));
416 /************************************************************************
417 Routine to store the previous machine password (by storing the current password
418 as the old)
419 ************************************************************************/
421 static bool secrets_store_prev_machine_password(const char *domain)
423 char *oldpass;
424 bool ret;
426 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
427 if (oldpass == NULL) {
428 return true;
430 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
431 SAFE_FREE(oldpass);
432 return ret;
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 ************************************************************************/
441 bool secrets_store_machine_password(const char *pass, const char *domain,
442 enum netr_SchannelType sec_channel)
444 bool ret;
445 uint32_t last_change_time;
446 uint32_t sec_channel_type;
448 if (!secrets_store_prev_machine_password(domain)) {
449 return false;
452 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
453 if (!ret)
454 return ret;
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));
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));
462 return ret;
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 ************************************************************************/
471 char *secrets_fetch_prev_machine_password(const char *domain)
473 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
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 ************************************************************************/
481 char *secrets_fetch_machine_password(const char *domain,
482 time_t *pass_last_set_time,
483 enum netr_SchannelType *channel)
485 char *ret;
486 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
488 if (pass_last_set_time) {
489 size_t size;
490 uint32_t *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;
500 if (channel) {
501 size_t size;
502 uint32_t *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();
512 return ret;