source: trunk/server/source3/passdb/machine_account_secrets.c

Last change on this file was 745, checked in by Silvan Scherrer, 13 years ago

Samba Server: updated trunk to 3.6.0

File size: 13.4 KB
Line 
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 "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"
32
33#undef DBGC_CLASS
34#define DBGC_CLASS DBGC_PASSDB
35
36/* Urrrg. global.... */
37bool global_machine_password_needs_changing;
38
39/**
40 * Form a key for fetching the domain sid
41 *
42 * @param domain domain name
43 *
44 * @return keystring
45 **/
46static const char *domain_sid_keystr(const char *domain)
47{
48 char *keystr;
49
50 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
51 SECRETS_DOMAIN_SID, domain);
52 SMB_ASSERT(keystr != NULL);
53 return keystr;
54}
55
56bool secrets_store_domain_sid(const char *domain, const struct dom_sid *sid)
57{
58 bool ret;
59
60 ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
61
62 /* Force a re-query, in case we modified our domain */
63 if (ret)
64 reset_global_sam_sid();
65 return ret;
66}
67
68bool secrets_fetch_domain_sid(const char *domain, struct dom_sid *sid)
69{
70 struct dom_sid *dyn_sid;
71 size_t size = 0;
72
73 dyn_sid = (struct dom_sid *)secrets_fetch(domain_sid_keystr(domain), &size);
74
75 if (dyn_sid == NULL)
76 return False;
77
78 if (size != sizeof(struct dom_sid)) {
79 SAFE_FREE(dyn_sid);
80 return False;
81 }
82
83 *sid = *dyn_sid;
84 SAFE_FREE(dyn_sid);
85 return True;
86}
87
88bool secrets_store_domain_guid(const char *domain, struct GUID *guid)
89{
90 fstring key;
91
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));
95}
96
97bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
98{
99 struct GUID *dyn_guid;
100 fstring key;
101 size_t size = 0;
102 struct GUID new_guid;
103
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);
107
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);
114 }
115 if (dyn_guid == NULL) {
116 return False;
117 }
118 }
119
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;
124 }
125
126 *guid = *dyn_guid;
127 SAFE_FREE(dyn_guid);
128 return True;
129}
130
131/**
132 * Form a key for fetching the machine trust account sec channel type
133 *
134 * @param domain domain name
135 *
136 * @return keystring
137 **/
138static const char *machine_sec_channel_type_keystr(const char *domain)
139{
140 char *keystr;
141
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;
147}
148
149/**
150 * Form a key for fetching the machine trust account last change time
151 *
152 * @param domain domain name
153 *
154 * @return keystring
155 **/
156static const char *machine_last_change_time_keystr(const char *domain)
157{
158 char *keystr;
159
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;
165}
166
167
168/**
169 * Form a key for fetching the machine previous trust account password
170 *
171 * @param domain domain name
172 *
173 * @return keystring
174 **/
175static const char *machine_prev_password_keystr(const char *domain)
176{
177 char *keystr;
178
179 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
180 SECRETS_MACHINE_PASSWORD_PREV, domain);
181 SMB_ASSERT(keystr != NULL);
182 return keystr;
183}
184
185/**
186 * Form a key for fetching the machine trust account password
187 *
188 * @param domain domain name
189 *
190 * @return keystring
191 **/
192static const char *machine_password_keystr(const char *domain)
193{
194 char *keystr;
195
196 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
197 SECRETS_MACHINE_PASSWORD, domain);
198 SMB_ASSERT(keystr != NULL);
199 return keystr;
200}
201
202/**
203 * Form a key for fetching the machine trust account password
204 *
205 * @param domain domain name
206 *
207 * @return stored password's key
208 **/
209static const char *trust_keystr(const char *domain)
210{
211 char *keystr;
212
213 keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
214 SECRETS_MACHINE_ACCT_PASS, domain);
215 SMB_ASSERT(keystr != NULL);
216 return keystr;
217}
218
219/************************************************************************
220 Lock the trust password entry.
221************************************************************************/
222
223void *secrets_get_trust_account_lock(TALLOC_CTX *mem_ctx, const char *domain)
224{
225 struct db_context *db_ctx;
226 if (!secrets_init()) {
227 return NULL;
228 }
229
230 db_ctx = secrets_db_ctx();
231
232 return db_ctx->fetch_locked(
233 db_ctx, mem_ctx, string_term_tdb_data(trust_keystr(domain)));
234}
235
236/************************************************************************
237 Routine to get the default secure channel type for trust accounts
238************************************************************************/
239
240enum netr_SchannelType get_default_sec_channel(void)
241{
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;
247 }
248}
249
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************************************************************************/
256
257bool 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)
261{
262 struct machine_acct_pass *pass;
263 size_t size = 0;
264
265 if (!(pass = (struct machine_acct_pass *)secrets_fetch(
266 trust_keystr(domain), &size))) {
267 DEBUG(5, ("secrets_fetch failed!\n"));
268 return False;
269 }
270
271 if (size != sizeof(*pass)) {
272 DEBUG(0, ("secrets were of incorrect size!\n"));
273 SAFE_FREE(pass);
274 return False;
275 }
276
277 if (pass_last_set_time) {
278 *pass_last_set_time = pass->mod_time;
279 }
280 memcpy(ret_pwd, pass->hash, 16);
281
282 if (channel) {
283 *channel = get_default_sec_channel();
284 }
285
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;
291 }
292 }
293
294 SAFE_FREE(pass);
295 return True;
296}
297
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************************************************************************/
303
304bool secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16],
305 time_t *pass_last_set_time,
306 enum netr_SchannelType *channel)
307{
308 char *plaintext;
309
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;
317 }
318
319 return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
320 pass_last_set_time,
321 channel);
322}
323
324/************************************************************************
325 Routine to delete the old plaintext machine account password if any
326************************************************************************/
327
328static bool secrets_delete_prev_machine_password(const char *domain)
329{
330 char *oldpass = (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
331 if (oldpass == NULL) {
332 return true;
333 }
334 SAFE_FREE(oldpass);
335 return secrets_delete(machine_prev_password_keystr(domain));
336}
337
338/************************************************************************
339 Routine to delete the plaintext machine account password and old
340 password if any
341************************************************************************/
342
343bool secrets_delete_machine_password(const char *domain)
344{
345 if (!secrets_delete_prev_machine_password(domain)) {
346 return false;
347 }
348 return secrets_delete(machine_password_keystr(domain));
349}
350
351/************************************************************************
352 Routine to delete the plaintext machine account password, old password,
353 sec channel type and last change time from secrets database
354************************************************************************/
355
356bool secrets_delete_machine_password_ex(const char *domain)
357{
358 if (!secrets_delete_prev_machine_password(domain)) {
359 return false;
360 }
361 if (!secrets_delete(machine_password_keystr(domain))) {
362 return false;
363 }
364 if (!secrets_delete(machine_sec_channel_type_keystr(domain))) {
365 return false;
366 }
367 return secrets_delete(machine_last_change_time_keystr(domain));
368}
369
370/************************************************************************
371 Routine to delete the domain sid
372************************************************************************/
373
374bool secrets_delete_domain_sid(const char *domain)
375{
376 return secrets_delete(domain_sid_keystr(domain));
377}
378
379/************************************************************************
380 Routine to store the previous machine password (by storing the current password
381 as the old)
382************************************************************************/
383
384static bool secrets_store_prev_machine_password(const char *domain)
385{
386 char *oldpass;
387 bool ret;
388
389 oldpass = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
390 if (oldpass == NULL) {
391 return true;
392 }
393 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
394 SAFE_FREE(oldpass);
395 return ret;
396}
397
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************************************************************************/
403
404bool secrets_store_machine_password(const char *pass, const char *domain,
405 enum netr_SchannelType sec_channel)
406{
407 bool ret;
408 uint32 last_change_time;
409 uint32 sec_channel_type;
410
411 if (!secrets_store_prev_machine_password(domain)) {
412 return false;
413 }
414
415 ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
416 if (!ret)
417 return ret;
418
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));
421
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));
424
425 return ret;
426}
427
428
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************************************************************************/
433
434char *secrets_fetch_prev_machine_password(const char *domain)
435{
436 return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
437}
438
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************************************************************************/
443
444char *secrets_fetch_machine_password(const char *domain,
445 time_t *pass_last_set_time,
446 enum netr_SchannelType *channel)
447{
448 char *ret;
449 ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
450
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;
460 }
461 }
462
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();
472 }
473 }
474
475 return ret;
476}
Note: See TracBrowser for help on using the repository browser.