s3-secrets: only include secrets.h when needed.
[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 "../libcli/auth/libcli_auth.h"
27 #include "secrets.h"
28
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_PASSDB
31
32 /* Urrrg. global.... */
33 bool global_machine_password_needs_changing;
34
35 /**
36  * Form a key for fetching the domain sid
37  *
38  * @param domain domain name
39  *
40  * @return keystring
41  **/
42 static const char *domain_sid_keystr(const char *domain)
43 {
44         char *keystr;
45
46         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
47                                             SECRETS_DOMAIN_SID, domain);
48         SMB_ASSERT(keystr != NULL);
49         return keystr;
50 }
51
52 bool secrets_store_domain_sid(const char *domain, const struct dom_sid  *sid)
53 {
54         bool ret;
55
56         ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
57
58         /* Force a re-query, in case we modified our domain */
59         if (ret)
60                 reset_global_sam_sid();
61         return ret;
62 }
63
64 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid  *sid)
65 {
66         struct dom_sid  *dyn_sid;
67         size_t size = 0;
68
69         dyn_sid = (struct dom_sid  *)secrets_fetch(domain_sid_keystr(domain), &size);
70
71         if (dyn_sid == NULL)
72                 return False;
73
74         if (size != sizeof(struct dom_sid)) {
75                 SAFE_FREE(dyn_sid);
76                 return False;
77         }
78
79         *sid = *dyn_sid;
80         SAFE_FREE(dyn_sid);
81         return True;
82 }
83
84 bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
85 {
86         fstring key;
87
88         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
89         strupper_m(key);
90         return secrets_store(key, guid, sizeof(struct GUID));
91 }
92
93 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
94 {
95         struct GUID *dyn_guid;
96         fstring key;
97         size_t size = 0;
98         struct GUID new_guid;
99
100         slprintf(key, sizeof(key)-1, "%s/%s", SECRETS_DOMAIN_GUID, domain);
101         strupper_m(key);
102         dyn_guid = (struct GUID *)secrets_fetch(key, &size);
103
104         if (!dyn_guid) {
105                 if (lp_server_role() == ROLE_DOMAIN_PDC) {
106                         new_guid = GUID_random();
107                         if (!secrets_store_domain_guid(domain, &new_guid))
108                                 return False;
109                         dyn_guid = (struct GUID *)secrets_fetch(key, &size);
110                 }
111                 if (dyn_guid == NULL) {
112                         return False;
113                 }
114         }
115
116         if (size != sizeof(struct GUID)) {
117                 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
118                 SAFE_FREE(dyn_guid);
119                 return False;
120         }
121
122         *guid = *dyn_guid;
123         SAFE_FREE(dyn_guid);
124         return True;
125 }
126
127 /**
128  * Form a key for fetching the machine trust account sec channel type
129  *
130  * @param domain domain name
131  *
132  * @return keystring
133  **/
134 static const char *machine_sec_channel_type_keystr(const char *domain)
135 {
136         char *keystr;
137
138         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
139                                             SECRETS_MACHINE_SEC_CHANNEL_TYPE,
140                                             domain);
141         SMB_ASSERT(keystr != NULL);
142         return keystr;
143 }
144
145 /**
146  * Form a key for fetching the machine trust account last change time
147  *
148  * @param domain domain name
149  *
150  * @return keystring
151  **/
152 static const char *machine_last_change_time_keystr(const char *domain)
153 {
154         char *keystr;
155
156         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
157                                             SECRETS_MACHINE_LAST_CHANGE_TIME,
158                                             domain);
159         SMB_ASSERT(keystr != NULL);
160         return keystr;
161 }
162
163
164 /**
165  * Form a key for fetching the machine previous trust account password
166  *
167  * @param domain domain name
168  *
169  * @return keystring
170  **/
171 static const char *machine_prev_password_keystr(const char *domain)
172 {
173         char *keystr;
174
175         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
176                                             SECRETS_MACHINE_PASSWORD_PREV, domain);
177         SMB_ASSERT(keystr != NULL);
178         return keystr;
179 }
180
181 /**
182  * Form a key for fetching the machine trust account password
183  *
184  * @param domain domain name
185  *
186  * @return keystring
187  **/
188 static const char *machine_password_keystr(const char *domain)
189 {
190         char *keystr;
191
192         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
193                                             SECRETS_MACHINE_PASSWORD, domain);
194         SMB_ASSERT(keystr != NULL);
195         return keystr;
196 }
197
198 /**
199  * Form a key for fetching the machine trust account password
200  *
201  * @param domain domain name
202  *
203  * @return stored password's key
204  **/
205 static const char *trust_keystr(const char *domain)
206 {
207         char *keystr;
208
209         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
210                                             SECRETS_MACHINE_ACCT_PASS, domain);
211         SMB_ASSERT(keystr != NULL);
212         return keystr;
213 }
214
215 /************************************************************************
216  Lock the trust password entry.
217 ************************************************************************/
218
219 void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
220 {
221         struct db_context *db_ctx;
222         if (!secrets_init()) {
223                 return NULL;
224         }
225
226         db_ctx = secrets_db_ctx();
227
228         return db_ctx->fetch_locked(
229                 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
230 }
231
232 /************************************************************************
233  Routine to get the default secure channel type for trust accounts
234 ************************************************************************/
235
236 enum netr_SchannelType get_default_sec_channel(void)
237 {
238         if (lp_server_role() == ROLE_DOMAIN_BDC ||
239             lp_server_role() == ROLE_DOMAIN_PDC) {
240                 return SEC_CHAN_BDC;
241         } else {
242                 return SEC_CHAN_WKSTA;
243         }
244 }
245
246 /************************************************************************
247  Routine to get the trust account password for a domain.
248  This only tries to get the legacy hashed version of the password.
249  The user of this function must have locked the trust password file using
250  the above secrets_lock_trust_account_password().
251 ************************************************************************/
252
253 bool secrets_fetch_trust_account_password_legacy(const char *domain,
254                                                  uint8 ret_pwd[16],
255                                                  time_t *pass_last_set_time,
256                                                  enum netr_SchannelType *channel)
257 {
258         struct machine_acct_pass *pass;
259         size_t size = 0;
260
261         if (!(pass = (struct machine_acct_pass *)secrets_fetch(
262                       trust_keystr(domain), &size))) {
263                 DEBUG(5, ("secrets_fetch failed!\n"));
264                 return False;
265         }
266
267         if (size != sizeof(*pass)) {
268                 DEBUG(0, ("secrets were of incorrect size!\n"));
269                 SAFE_FREE(pass);
270                 return False;
271         }
272
273         if (pass_last_set_time) {
274                 *pass_last_set_time = pass->mod_time;
275         }
276         memcpy(ret_pwd, pass->hash, 16);
277
278         if (channel) {
279                 *channel = get_default_sec_channel();
280         }
281
282         /* Test if machine password has expired and needs to be changed */
283         if (lp_machine_password_timeout()) {
284                 if (pass->mod_time > 0 && time(NULL) > (pass->mod_time +
285                                 (time_t)lp_machine_password_timeout())) {
286                         global_machine_password_needs_changing = True;
287                 }
288         }
289
290         SAFE_FREE(pass);
291         return True;
292 }
293
294 /************************************************************************
295  Routine to get the trust account password for a domain.
296  The user of this function must have locked the trust password file using
297  the above secrets_lock_trust_account_password().
298 ************************************************************************/
299
300 bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
301                                           time_t *pass_last_set_time,
302                                           enum netr_SchannelType *channel)
303 {
304         char *plaintext;
305
306         plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
307                                                    channel);
308         if (plaintext) {
309                 DEBUG(4,("Using cleartext machine password\n"));
310                 E_md4hash(plaintext, ret_pwd);
311                 SAFE_FREE(plaintext);
312                 return True;
313         }
314
315         return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
316                                                            pass_last_set_time,
317                                                            channel);
318 }
319
320 /************************************************************************
321  Routine to delete the old plaintext machine account password if any
322 ************************************************************************/
323
324 static bool secrets_delete_prev_machine_password(const char *domain)
325 {
326         char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
327         if (oldpass == NULL) {
328                 return true;
329         }
330         SAFE_FREE(oldpass);
331         return secrets_delete(machine_prev_password_keystr(domain));
332 }
333
334 /************************************************************************
335  Routine to delete the plaintext machine account password and old
336  password if any
337 ************************************************************************/
338
339 bool secrets_delete_machine_password(const char *domain)
340 {
341         if (!secrets_delete_prev_machine_password(domain)) {
342                 return false;
343         }
344         return secrets_delete(machine_password_keystr(domain));
345 }
346
347 /************************************************************************
348  Routine to delete the plaintext machine account password, old password,
349  sec channel type and last change time from secrets database
350 ************************************************************************/
351
352 bool secrets_delete_machine_password_ex(const char *domain)
353 {
354         if (!secrets_delete_prev_machine_password(domain)) {
355                 return false;
356         }
357         if (!secrets_delete(machine_password_keystr(domain))) {
358                 return false;
359         }
360         if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
361                 return false;
362         }
363         return secrets_delete(machine_last_change_time_keystr(domain));
364 }
365
366 /************************************************************************
367  Routine to delete the domain sid
368 ************************************************************************/
369
370 bool secrets_delete_domain_sid(const char *domain)
371 {
372         return secrets_delete(domain_sid_keystr(domain));
373 }
374
375 /************************************************************************
376  Routine to store the previous machine password (by storing the current password
377  as the old)
378 ************************************************************************/
379
380 static bool secrets_store_prev_machine_password(const char *domain)
381 {
382         char *oldpass;
383         bool ret;
384
385         oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
386         if (oldpass == NULL) {
387                 return true;
388         }
389         ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
390         SAFE_FREE(oldpass);
391         return ret;
392 }
393
394 /************************************************************************
395  Routine to set the plaintext machine account password for a realm
396  the password is assumed to be a null terminated ascii string.
397  Before storing
398 ************************************************************************/
399
400 bool secrets_store_machine_password(const char *pass, const char *domain,
401                                     enum netr_SchannelType sec_channel)
402 {
403         bool ret;
404         uint32 last_change_time;
405         uint32 sec_channel_type;
406
407         if (!secrets_store_prev_machine_password(domain)) {
408                 return false;
409         }
410
411         ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
412         if (!ret)
413                 return ret;
414
415         SIVAL(&last_change_time, 0, time(NULL));
416         ret = secrets_store(machine_last_change_time_keystr(domain), &last_change_time, sizeof(last_change_time));
417
418         SIVAL(&sec_channel_type, 0, sec_channel);
419         ret = secrets_store(machine_sec_channel_type_keystr(domain), &sec_channel_type, sizeof(sec_channel_type));
420
421         return ret;
422 }
423
424
425 /************************************************************************
426  Routine to fetch the previous plaintext machine account password for a realm
427  the password is assumed to be a null terminated ascii string.
428 ************************************************************************/
429
430 char *secrets_fetch_prev_machine_password(const char *domain)
431 {
432         return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
433 }
434
435 /************************************************************************
436  Routine to fetch the plaintext machine account password for a realm
437  the password is assumed to be a null terminated ascii string.
438 ************************************************************************/
439
440 char *secrets_fetch_machine_password(const char *domain,
441                                      time_t *pass_last_set_time,
442                                      enum netr_SchannelType *channel)
443 {
444         char *ret;
445         ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
446
447         if (pass_last_set_time) {
448                 size_t size;
449                 uint32 *last_set_time;
450                 last_set_time = (unsigned int *)secrets_fetch(machine_last_change_time_keystr(domain), &size);
451                 if (last_set_time) {
452                         *pass_last_set_time = IVAL(last_set_time,0);
453                         SAFE_FREE(last_set_time);
454                 } else {
455                         *pass_last_set_time = 0;
456                 }
457         }
458
459         if (channel) {
460                 size_t size;
461                 uint32 *channel_type;
462                 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
463                 if (channel_type) {
464                         *channel = IVAL(channel_type,0);
465                         SAFE_FREE(channel_type);
466                 } else {
467                         *channel = get_default_sec_channel();
468                 }
469         }
470
471         return ret;
472 }