s3/packaging: Fix rpm build issues on RHEL.
[Samba.git] / source3 / passdb / machine_account_secrets.c
blob61894d4ee662207d381eee7aff123cd698902210
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.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 bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid)
58 bool ret;
60 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
62 /* Force a re-query, in case we modified our domain */
63 if (ret)
64 reset_global_sam_sid();
65 return ret;
68 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid)
70 struct dom_sid *dyn_sid;
71 size_t size = 0;
73 dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size);
75 if (dyn_sid == NULL)
76 return False;
78 if (size != sizeof(struct dom_sid)) {
79 SAFE_FREE(dyn_sid);
80 return False;
83 *sid = *dyn_sid;
84 SAFE_FREE(dyn_sid);
85 return True;
88 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
90 fstring key;
92 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
93 strupper_m(key);
94 return secrets_store(key, guid, sizeof(struct GUID));
97 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
99 struct GUID *dyn_guid;
100 fstring key;
101 size_t size = 0;
102 struct GUID new_guid;
104 slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
105 strupper_m(key);
106 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
108 if (!dyn_guid) {
109 if (lp_server_role() == ROLE_DOMAIN_PDC) {
110 new_guid = GUID_random();
111 if (!secrets_store_domain_guid(domain, &new_guid))
112 return False;
113 dyn_guid = (struct GUID *)secrets_fetch(key, &size);
115 if (dyn_guid == NULL) {
116 return False;
120 if (size != sizeof(struct GUID)) {
121 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
122 SAFE_FREE(dyn_guid);
123 return False;
126 *guid = *dyn_guid;
127 SAFE_FREE(dyn_guid);
128 return True;
132 * Form a key for fetching the machine trust account sec channel type
134 * @param domain domain name
136 * @return keystring
138 static const char *machine_sec_channel_type_keystr(const char *domain)
140 char *keystr;
142 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
143 SECRETS_MACHINE_SEC_CHANNEL_TYPE,
144 domain);
145 SMB_ASSERT(keystr != NULL);
146 return keystr;
150 * Form a key for fetching the machine trust account last change time
152 * @param domain domain name
154 * @return keystring
156 static const char *machine_last_change_time_keystr(const char *domain)
158 char *keystr;
160 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
161 SECRETS_MACHINE_LAST_CHANGE_TIME,
162 domain);
163 SMB_ASSERT(keystr != NULL);
164 return keystr;
169 * Form a key for fetching the machine previous trust account password
171 * @param domain domain name
173 * @return keystring
175 static const char *machine_prev_password_keystr(const char *domain)
177 char *keystr;
179 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
180 SECRETS_MACHINE_PASSWORD_PREV, domain);
181 SMB_ASSERT(keystr != NULL);
182 return keystr;
186 * Form a key for fetching the machine trust account password
188 * @param domain domain name
190 * @return keystring
192 static const char *machine_password_keystr(const char *domain)
194 char *keystr;
196 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
197 SECRETS_MACHINE_PASSWORD, domain);
198 SMB_ASSERT(keystr != NULL);
199 return keystr;
203 * Form a key for fetching the machine trust account password
205 * @param domain domain name
207 * @return stored password's key
209 static const char *trust_keystr(const char *domain)
211 char *keystr;
213 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
214 SECRETS_MACHINE_ACCT_PASS, domain);
215 SMB_ASSERT(keystr != NULL);
216 return keystr;
219 /************************************************************************
220 Lock the trust password entry.
221 ************************************************************************/
223 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
225 struct db_context *db_ctx;
226 if (!secrets_init()) {
227 return NULL;
230 db_ctx = secrets_db_ctx();
232 return db_ctx->fetch_locked(
233 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
236 /************************************************************************
237 Routine to get the default secure channel type for trust accounts
238 ************************************************************************/
240 enum netr_SchannelType get_default_sec_channel(void)
242 if (lp_server_role() == ROLE_DOMAIN_BDC ||
243 lp_server_role() == ROLE_DOMAIN_PDC) {
244 return SEC_CHAN_BDC;
245 } else {
246 return SEC_CHAN_WKSTA;
250 /************************************************************************
251 Routine to get the trust account password for a domain.
252 This only tries to get the legacy hashed version of the password.
253 The user of this function must have locked the trust password file using
254 the above secrets_lock_trust_account_password().
255 ************************************************************************/
257 bool secrets_fetch_trust_account_password_legacy(const char *domain,
258 uint8 ret_pwd[16],
259 time_t *pass_last_set_time,
260 enum netr_SchannelType *channel)
262 struct machine_acct_pass *pass;
263 size_t size = 0;
265 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
266 trust_keystr(domain), &size))) {
267 DEBUG(5, ("secrets_fetch failed!\n"));
268 return False;
271 if (size != sizeof(*pass)) {
272 DEBUG(0, ("secrets were of incorrect size!\n"));
273 SAFE_FREE(pass);
274 return False;
277 if (pass_last_set_time) {
278 *pass_last_set_time = pass->mod_time;
280 memcpy(ret_pwd, pass->hash, 16);
282 if (channel) {
283 *channel = get_default_sec_channel();
286 /* Test if machine password has expired and needs to be changed */
287 if (lp_machine_password_timeout()) {
288 if (pass->mod_time > 0 && time(NULL) > (pass->mod_time +
289 (time_t)lp_machine_password_timeout())) {
290 global_machine_password_needs_changing = True;
294 SAFE_FREE(pass);
295 return True;
298 /************************************************************************
299 Routine to get the trust account password for a domain.
300 The user of this function must have locked the trust password file using
301 the above secrets_lock_trust_account_password().
302 ************************************************************************/
304 bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
305 time_t *pass_last_set_time,
306 enum netr_SchannelType *channel)
308 char *plaintext;
310 plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
311 channel);
312 if (plaintext) {
313 DEBUG(4,("Using cleartext machine password\n"));
314 E_md4hash(plaintext, ret_pwd);
315 SAFE_FREE(plaintext);
316 return True;
319 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
320 pass_last_set_time,
321 channel);
324 /************************************************************************
325 Routine to delete the old plaintext machine account password if any
326 ************************************************************************/
328 static bool secrets_delete_prev_machine_password(const char *domain)
330 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
331 if (oldpass == NULL) {
332 return true;
334 SAFE_FREE(oldpass);
335 return secrets_delete(machine_prev_password_keystr(domain));
338 /************************************************************************
339 Routine to delete the plaintext machine account password and old
340 password if any
341 ************************************************************************/
343 bool secrets_delete_machine_password(const char *domain)
345 if (!secrets_delete_prev_machine_password(domain)) {
346 return false;
348 return secrets_delete(machine_password_keystr(domain));
351 /************************************************************************
352 Routine to delete the plaintext machine account password, old password,
353 sec channel type and last change time from secrets database
354 ************************************************************************/
356 bool secrets_delete_machine_password_ex(const char *domain)
358 if (!secrets_delete_prev_machine_password(domain)) {
359 return false;
361 if (!secrets_delete(machine_password_keystr(domain))) {
362 return false;
364 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
365 return false;
367 return secrets_delete(machine_last_change_time_keystr(domain));
370 /************************************************************************
371 Routine to delete the domain sid
372 ************************************************************************/
374 bool secrets_delete_domain_sid(const char *domain)
376 return secrets_delete(domain_sid_keystr(domain));
379 /************************************************************************
380 Routine to store the previous machine password (by storing the current password
381 as the old)
382 ************************************************************************/
384 static bool secrets_store_prev_machine_password(const char *domain)
386 char *oldpass;
387 bool ret;
389 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
390 if (oldpass == NULL) {
391 return true;
393 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
394 SAFE_FREE(oldpass);
395 return ret;
398 /************************************************************************
399 Routine to set the plaintext machine account password for a realm
400 the password is assumed to be a null terminated ascii string.
401 Before storing
402 ************************************************************************/
404 bool secrets_store_machine_password(const char *pass, const char *domain,
405 enum netr_SchannelType sec_channel)
407 bool ret;
408 uint32 last_change_time;
409 uint32 sec_channel_type;
411 if (!secrets_store_prev_machine_password(domain)) {
412 return false;
415 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
416 if (!ret)
417 return ret;
419 SIVAL(&last_change_time, 0, time(NULL));
420 ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
422 SIVAL(&sec_channel_type, 0, sec_channel);
423 ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
425 return ret;
429 /************************************************************************
430 Routine to fetch the previous plaintext machine account password for a realm
431 the password is assumed to be a null terminated ascii string.
432 ************************************************************************/
434 char *secrets_fetch_prev_machine_password(const char *domain)
436 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
439 /************************************************************************
440 Routine to fetch the plaintext machine account password for a realm
441 the password is assumed to be a null terminated ascii string.
442 ************************************************************************/
444 char *secrets_fetch_machine_password(const char *domain,
445 time_t *pass_last_set_time,
446 enum netr_SchannelType *channel)
448 char *ret;
449 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
451 if (pass_last_set_time) {
452 size_t size;
453 uint32 *last_set_time;
454 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
455 if (last_set_time) {
456 *pass_last_set_time = IVAL(last_set_time,0);
457 SAFE_FREE(last_set_time);
458 } else {
459 *pass_last_set_time = 0;
463 if (channel) {
464 size_t size;
465 uint32 *channel_type;
466 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
467 if (channel_type) {
468 *channel = IVAL(channel_type,0);
469 SAFE_FREE(channel_type);
470 } else {
471 *channel = get_default_sec_channel();
475 return ret;