s3:smbd: include smbXsrv.h before smbd/proto.h to have the smbXsrv_ structs available
[Samba/gebeck_regimport.git] / source3 / passdb / machine_account_secrets.c
blob8aaea10d8c25482afce87a77858d7529223d2eed
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 /* Urrrg. global.... */
37 bool global_machine_password_needs_changing;
39 /**
40 * Form a key for fetching the domain sid
42 * @param domain domain name
44 * @return keystring
45 **/
46 static const char *domain_sid_keystr(const char *domain)
48 char *keystr;
50 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
51 SECRETS_DOMAIN_SID, domain);
52 SMB_ASSERT(keystr != NULL);
53 return keystr;
56 static const char *protect_ids_keystr(const char *domain)
58 char *keystr;
60 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
61 SECRETS_PROTECT_IDS, domain);
62 SMB_ASSERT(keystr != NULL);
63 return keystr;
66 /* N O T E: never use this outside of passdb modules that store the SID on their own */
67 bool secrets_mark_domain_protected(const char *domain)
69 bool ret;
71 ret = secrets_store(protect_ids_keystr(domain), "TRUE", 5);
72 if (!ret) {
73 DEBUG(0, ("Failed to protect the Domain IDs\n"));
75 return ret;
78 bool secrets_clear_domain_protection(const char *domain)
80 bool ret;
82 ret = secrets_delete(protect_ids_keystr(domain));
83 if (!ret) {
84 DEBUG(0, ("Failed to remove Domain IDs protection\n"));
86 return ret;
89 bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid)
91 #if _SAMBA_BUILD_ == 4
92 char *protect_ids;
93 #endif
94 bool ret;
96 #if _SAMBA_BUILD_ == 4
97 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
98 if (protect_ids) {
99 if (strncmp(protect_ids, "TRUE", 4)) {
100 DEBUG(0, ("Refusing to store a Domain SID, "
101 "it has been marked as protected!\n"));
102 return false;
105 #endif
107 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
109 /* Force a re-query, in case we modified our domain */
110 if (ret)
111 reset_global_sam_sid();
112 return ret;
115 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid)
117 struct dom_sid *dyn_sid;
118 size_t size = 0;
120 dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size);
122 if (dyn_sid == NULL)
123 return False;
125 if (size != sizeof(struct dom_sid)) {
126 SAFE_FREE(dyn_sid);
127 return False;
130 *sid = *dyn_sid;
131 SAFE_FREE(dyn_sid);
132 return True;
135 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
137 #if _SAMBA_BUILD_ == 4
138 char *protect_ids;
139 #endif
140 fstring key;
142 #if _SAMBA_BUILD_ == 4
143 protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
144 if (protect_ids) {
145 if (strncmp(protect_ids, "TRUE", 4)) {
146 DEBUG(0, ("Refusing to store a Domain SID, "
147 "it has been marked as protected!\n"));
148 return false;
151 #endif
153 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
154 strupper_m(key);
155 return secrets_store(key, guid, sizeof(struct GUID));
158 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
160 struct GUID *dyn_guid;
161 fstring key;
162 size_t size = 0;
163 struct GUID new_guid;
165 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
166 strupper_m(key);
167 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
169 if (!dyn_guid) {
170 if (lp_server_role() == ROLE_DOMAIN_PDC) {
171 new_guid = GUID_random();
172 if (!secrets_store_domain_guid(domain, &new_guid))
173 return False;
174 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
176 if (dyn_guid == NULL) {
177 return False;
181 if (size != sizeof(struct GUID)) {
182 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
183 SAFE_FREE(dyn_guid);
184 return False;
187 *guid = *dyn_guid;
188 SAFE_FREE(dyn_guid);
189 return True;
193 * Form a key for fetching the machine trust account sec channel type
195 * @param domain domain name
197 * @return keystring
199 static const char *machine_sec_channel_type_keystr(const char *domain)
201 char *keystr;
203 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
204 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
205 domain);
206 SMB_ASSERT(keystr != NULL);
207 return keystr;
211 * Form a key for fetching the machine trust account last change time
213 * @param domain domain name
215 * @return keystring
217 static const char *machine_last_change_time_keystr(const char *domain)
219 char *keystr;
221 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
222 SECRETS_MACHINE_LAST_CHANGE_TIME,
223 domain);
224 SMB_ASSERT(keystr != NULL);
225 return keystr;
230 * Form a key for fetching the machine previous trust account password
232 * @param domain domain name
234 * @return keystring
236 static const char *machine_prev_password_keystr(const char *domain)
238 char *keystr;
240 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
241 SECRETS_MACHINE_PASSWORD_PREV, domain);
242 SMB_ASSERT(keystr != NULL);
243 return keystr;
247 * Form a key for fetching the machine trust account password
249 * @param domain domain name
251 * @return keystring
253 static const char *machine_password_keystr(const char *domain)
255 char *keystr;
257 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
258 SECRETS_MACHINE_PASSWORD, domain);
259 SMB_ASSERT(keystr != NULL);
260 return keystr;
264 * Form a key for fetching the machine trust account password
266 * @param domain domain name
268 * @return stored password's key
270 static const char *trust_keystr(const char *domain)
272 char *keystr;
274 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
275 SECRETS_MACHINE_ACCT_PASS, domain);
276 SMB_ASSERT(keystr != NULL);
277 return keystr;
280 /************************************************************************
281 Lock the trust password entry.
282 ************************************************************************/
284 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
286 struct db_context *db_ctx;
287 if (!secrets_init()) {
288 return NULL;
291 db_ctx = secrets_db_ctx();
293 return dbwrap_fetch_locked(
294 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
297 /************************************************************************
298 Routine to get the default secure channel type for trust accounts
299 ************************************************************************/
301 enum netr_SchannelType get_default_sec_channel(void)
303 if (lp_server_role() == ROLE_DOMAIN_BDC ||
304 lp_server_role() == ROLE_DOMAIN_PDC) {
305 return SEC_CHAN_BDC;
306 } else {
307 return SEC_CHAN_WKSTA;
311 /************************************************************************
312 Routine to get the trust account password for a domain.
313 This only tries to get the legacy hashed version of the password.
314 The user of this function must have locked the trust password file using
315 the above secrets_lock_trust_account_password().
316 ************************************************************************/
318 bool secrets_fetch_trust_account_password_legacy(const char *domain,
319 uint8 ret_pwd[16],
320 time_t *pass_last_set_time,
321 enum netr_SchannelType *channel)
323 struct machine_acct_pass *pass;
324 size_t size = 0;
326 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
327 trust_keystr(domain), &size))) {
328 DEBUG(5, ("secrets_fetch failed!\n"));
329 return False;
332 if (size != sizeof(*pass)) {
333 DEBUG(0, ("secrets were of incorrect size!\n"));
334 SAFE_FREE(pass);
335 return False;
338 if (pass_last_set_time) {
339 *pass_last_set_time = pass->mod_time;
341 memcpy(ret_pwd, pass->hash, 16);
343 if (channel) {
344 *channel = get_default_sec_channel();
347 /* Test if machine password has expired and needs to be changed */
348 if (lp_machine_password_timeout()) {
349 if (pass->mod_time > 0 && time(NULL) > (pass->mod_time +
350 (time_t)lp_machine_password_timeout())) {
351 global_machine_password_needs_changing = True;
355 SAFE_FREE(pass);
356 return True;
359 /************************************************************************
360 Routine to get the trust account password for a domain.
361 The user of this function must have locked the trust password file using
362 the above secrets_lock_trust_account_password().
363 ************************************************************************/
365 bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
366 time_t *pass_last_set_time,
367 enum netr_SchannelType *channel)
369 char *plaintext;
371 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
372 channel);
373 if (plaintext) {
374 DEBUG(4,("Using cleartext machine password\n"));
375 E_md4hash(plaintext, ret_pwd);
376 SAFE_FREE(plaintext);
377 return True;
380 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
381 pass_last_set_time,
382 channel);
385 /************************************************************************
386 Routine to delete the old plaintext machine account password if any
387 ************************************************************************/
389 static bool secrets_delete_prev_machine_password(const char *domain)
391 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
392 if (oldpass == NULL) {
393 return true;
395 SAFE_FREE(oldpass);
396 return secrets_delete(machine_prev_password_keystr(domain));
399 /************************************************************************
400 Routine to delete the plaintext machine account password, old password,
401 sec channel type and last change time from secrets database
402 ************************************************************************/
404 bool secrets_delete_machine_password_ex(const char *domain)
406 if (!secrets_delete_prev_machine_password(domain)) {
407 return false;
409 if (!secrets_delete(machine_password_keystr(domain))) {
410 return false;
412 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
413 return false;
415 return secrets_delete(machine_last_change_time_keystr(domain));
418 /************************************************************************
419 Routine to delete the domain sid
420 ************************************************************************/
422 bool secrets_delete_domain_sid(const char *domain)
424 return secrets_delete(domain_sid_keystr(domain));
427 /************************************************************************
428 Routine to store the previous machine password (by storing the current password
429 as the old)
430 ************************************************************************/
432 static bool secrets_store_prev_machine_password(const char *domain)
434 char *oldpass;
435 bool ret;
437 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
438 if (oldpass == NULL) {
439 return true;
441 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
442 SAFE_FREE(oldpass);
443 return ret;
446 /************************************************************************
447 Routine to set the plaintext machine account password for a realm
448 the password is assumed to be a null terminated ascii string.
449 Before storing
450 ************************************************************************/
452 bool secrets_store_machine_password(const char *pass, const char *domain,
453 enum netr_SchannelType sec_channel)
455 bool ret;
456 uint32 last_change_time;
457 uint32 sec_channel_type;
459 if (!secrets_store_prev_machine_password(domain)) {
460 return false;
463 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
464 if (!ret)
465 return ret;
467 SIVAL(&last_change_time, 0, time(NULL));
468 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
470 SIVAL(&sec_channel_type, 0, sec_channel);
471 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
473 return ret;
477 /************************************************************************
478 Routine to fetch the previous plaintext machine account password for a realm
479 the password is assumed to be a null terminated ascii string.
480 ************************************************************************/
482 char *secrets_fetch_prev_machine_password(const char *domain)
484 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
487 /************************************************************************
488 Routine to fetch the plaintext machine account password for a realm
489 the password is assumed to be a null terminated ascii string.
490 ************************************************************************/
492 char *secrets_fetch_machine_password(const char *domain,
493 time_t *pass_last_set_time,
494 enum netr_SchannelType *channel)
496 char *ret;
497 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
499 if (pass_last_set_time) {
500 size_t size;
501 uint32 *last_set_time;
502 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
503 if (last_set_time) {
504 *pass_last_set_time = IVAL(last_set_time,0);
505 SAFE_FREE(last_set_time);
506 } else {
507 *pass_last_set_time = 0;
511 if (channel) {
512 size_t size;
513 uint32 *channel_type;
514 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
515 if (channel_type) {
516 *channel = IVAL(channel_type,0);
517 SAFE_FREE(channel_type);
518 } else {
519 *channel = get_default_sec_channel();
523 return ret;