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