krb5-samba: interdomain trust uses different salt principal
[vlendec/samba-autobuild/.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 "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"
32 #include "libcli/security/security.h"
33
34 #include "librpc/gen_ndr/libnet_join.h"
35 #include "librpc/gen_ndr/ndr_secrets.h"
36 #include "lib/crypto/crypto.h"
37 #include "lib/krb5_wrap/krb5_samba.h"
38 #include "lib/util/time_basic.h"
39 #include "../libds/common/flags.h"
40
41 #undef DBGC_CLASS
42 #define DBGC_CLASS DBGC_PASSDB
43
44 static char *domain_info_keystr(const char *domain);
45
46 static char *des_salt_key(const char *realm);
47
48 /**
49  * Form a key for fetching the domain sid
50  *
51  * @param domain domain name
52  *
53  * @return keystring
54  **/
55 static const char *domain_sid_keystr(const char *domain)
56 {
57         char *keystr;
58
59         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
60                                             SECRETS_DOMAIN_SID, domain);
61         SMB_ASSERT(keystr != NULL);
62         return keystr;
63 }
64
65 static const char *domain_guid_keystr(const char *domain)
66 {
67         char *keystr;
68
69         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
70                                             SECRETS_DOMAIN_GUID, domain);
71         SMB_ASSERT(keystr != NULL);
72         return keystr;
73 }
74
75 static const char *protect_ids_keystr(const char *domain)
76 {
77         char *keystr;
78
79         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
80                                             SECRETS_PROTECT_IDS, domain);
81         SMB_ASSERT(keystr != NULL);
82         return keystr;
83 }
84
85 /* N O T E: never use this outside of passdb modules that store the SID on their own */
86 bool secrets_mark_domain_protected(const char *domain)
87 {
88         bool ret;
89
90         ret = secrets_store(protect_ids_keystr(domain), "TRUE", 5);
91         if (!ret) {
92                 DEBUG(0, ("Failed to protect the Domain IDs\n"));
93         }
94         return ret;
95 }
96
97 bool secrets_clear_domain_protection(const char *domain)
98 {
99         bool ret;
100         void *protection = secrets_fetch(protect_ids_keystr(domain), NULL);
101         
102         if (protection) {
103                 SAFE_FREE(protection);
104                 ret = secrets_delete_entry(protect_ids_keystr(domain));
105                 if (!ret) {
106                         DEBUG(0, ("Failed to remove Domain IDs protection\n"));
107                 }
108                 return ret;
109         }
110         return true;
111 }
112
113 bool secrets_store_domain_sid(const char *domain, const struct dom_sid  *sid)
114 {
115         char *protect_ids;
116         bool ret;
117
118         protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
119         if (protect_ids) {
120                 if (strncmp(protect_ids, "TRUE", 4)) {
121                         DEBUG(0, ("Refusing to store a Domain SID, "
122                                   "it has been marked as protected!\n"));
123                         SAFE_FREE(protect_ids);
124                         return false;
125                 }
126         }
127         SAFE_FREE(protect_ids);
128
129         ret = secrets_store(domain_sid_keystr(domain), sid, sizeof(struct dom_sid ));
130
131         /* Force a re-query, in the case where we modified our domain */
132         if (ret) {
133                 if (dom_sid_equal(get_global_sam_sid(), sid) == false) {
134                         reset_global_sam_sid();
135                 }
136         }
137         return ret;
138 }
139
140 bool secrets_fetch_domain_sid(const char *domain, struct dom_sid  *sid)
141 {
142         struct dom_sid  *dyn_sid;
143         size_t size = 0;
144
145         dyn_sid = (struct dom_sid  *)secrets_fetch(domain_sid_keystr(domain), &size);
146
147         if (dyn_sid == NULL)
148                 return False;
149
150         if (size != sizeof(struct dom_sid)) {
151                 SAFE_FREE(dyn_sid);
152                 return False;
153         }
154
155         *sid = *dyn_sid;
156         SAFE_FREE(dyn_sid);
157         return True;
158 }
159
160 bool secrets_store_domain_guid(const char *domain, const struct GUID *guid)
161 {
162         char *protect_ids;
163         const char *key;
164
165         protect_ids = secrets_fetch(protect_ids_keystr(domain), NULL);
166         if (protect_ids) {
167                 if (strncmp(protect_ids, "TRUE", 4)) {
168                         DEBUG(0, ("Refusing to store a Domain SID, "
169                                   "it has been marked as protected!\n"));
170                         SAFE_FREE(protect_ids);
171                         return false;
172                 }
173         }
174         SAFE_FREE(protect_ids);
175
176         key = domain_guid_keystr(domain);
177         return secrets_store(key, guid, sizeof(struct GUID));
178 }
179
180 bool secrets_fetch_domain_guid(const char *domain, struct GUID *guid)
181 {
182         struct GUID *dyn_guid;
183         const char *key;
184         size_t size = 0;
185         struct GUID new_guid;
186
187         key = domain_guid_keystr(domain);
188         dyn_guid = (struct GUID *)secrets_fetch(key, &size);
189
190         if (!dyn_guid) {
191                 if (lp_server_role() == ROLE_DOMAIN_PDC) {
192                         new_guid = GUID_random();
193                         if (!secrets_store_domain_guid(domain, &new_guid))
194                                 return False;
195                         dyn_guid = (struct GUID *)secrets_fetch(key, &size);
196                 }
197                 if (dyn_guid == NULL) {
198                         return False;
199                 }
200         }
201
202         if (size != sizeof(struct GUID)) {
203                 DEBUG(1,("UUID size %d is wrong!\n", (int)size));
204                 SAFE_FREE(dyn_guid);
205                 return False;
206         }
207
208         *guid = *dyn_guid;
209         SAFE_FREE(dyn_guid);
210         return True;
211 }
212
213 /**
214  * Form a key for fetching the machine trust account sec channel type
215  *
216  * @param domain domain name
217  *
218  * @return keystring
219  **/
220 static const char *machine_sec_channel_type_keystr(const char *domain)
221 {
222         char *keystr;
223
224         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
225                                             SECRETS_MACHINE_SEC_CHANNEL_TYPE,
226                                             domain);
227         SMB_ASSERT(keystr != NULL);
228         return keystr;
229 }
230
231 /**
232  * Form a key for fetching the machine trust account last change time
233  *
234  * @param domain domain name
235  *
236  * @return keystring
237  **/
238 static const char *machine_last_change_time_keystr(const char *domain)
239 {
240         char *keystr;
241
242         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
243                                             SECRETS_MACHINE_LAST_CHANGE_TIME,
244                                             domain);
245         SMB_ASSERT(keystr != NULL);
246         return keystr;
247 }
248
249
250 /**
251  * Form a key for fetching the machine previous trust account password
252  *
253  * @param domain domain name
254  *
255  * @return keystring
256  **/
257 static const char *machine_prev_password_keystr(const char *domain)
258 {
259         char *keystr;
260
261         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
262                                             SECRETS_MACHINE_PASSWORD_PREV, domain);
263         SMB_ASSERT(keystr != NULL);
264         return keystr;
265 }
266
267 /**
268  * Form a key for fetching the machine trust account password
269  *
270  * @param domain domain name
271  *
272  * @return keystring
273  **/
274 static const char *machine_password_keystr(const char *domain)
275 {
276         char *keystr;
277
278         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
279                                             SECRETS_MACHINE_PASSWORD, domain);
280         SMB_ASSERT(keystr != NULL);
281         return keystr;
282 }
283
284 /**
285  * Form a key for fetching the machine trust account password
286  *
287  * @param domain domain name
288  *
289  * @return stored password's key
290  **/
291 static const char *trust_keystr(const char *domain)
292 {
293         char *keystr;
294
295         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
296                                             SECRETS_MACHINE_ACCT_PASS, domain);
297         SMB_ASSERT(keystr != NULL);
298         return keystr;
299 }
300
301 /************************************************************************
302  Routine to get the default secure channel type for trust accounts
303 ************************************************************************/
304
305 enum netr_SchannelType get_default_sec_channel(void)
306 {
307         if (lp_server_role() == ROLE_DOMAIN_BDC ||
308             lp_server_role() == ROLE_DOMAIN_PDC ||
309             lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
310                 return SEC_CHAN_BDC;
311         } else {
312                 return SEC_CHAN_WKSTA;
313         }
314 }
315
316 /************************************************************************
317  Routine to get the trust account password for a domain.
318  This only tries to get the legacy hashed version of the password.
319  The user of this function must have locked the trust password file using
320  the above secrets_lock_trust_account_password().
321 ************************************************************************/
322
323 bool secrets_fetch_trust_account_password_legacy(const char *domain,
324                                                  uint8_t ret_pwd[16],
325                                                  time_t *pass_last_set_time,
326                                                  enum netr_SchannelType *channel)
327 {
328         struct machine_acct_pass *pass;
329         size_t size = 0;
330
331         if (!(pass = (struct machine_acct_pass *)secrets_fetch(
332                       trust_keystr(domain), &size))) {
333                 DEBUG(5, ("secrets_fetch failed!\n"));
334                 return False;
335         }
336
337         if (size != sizeof(*pass)) {
338                 DEBUG(0, ("secrets were of incorrect size!\n"));
339                 SAFE_FREE(pass);
340                 return False;
341         }
342
343         if (pass_last_set_time) {
344                 *pass_last_set_time = pass->mod_time;
345         }
346         memcpy(ret_pwd, pass->hash, 16);
347
348         if (channel) {
349                 *channel = get_default_sec_channel();
350         }
351
352         SAFE_FREE(pass);
353         return True;
354 }
355
356 /************************************************************************
357  Routine to get the trust account password for a domain.
358  The user of this function must have locked the trust password file using
359  the above secrets_lock_trust_account_password().
360 ************************************************************************/
361
362 bool secrets_fetch_trust_account_password(const char *domain, uint8_t ret_pwd[16],
363                                           time_t *pass_last_set_time,
364                                           enum netr_SchannelType *channel)
365 {
366         char *plaintext;
367
368         plaintext = secrets_fetch_machine_password(domain, pass_last_set_time,
369                                                    channel);
370         if (plaintext) {
371                 DEBUG(4,("Using cleartext machine password\n"));
372                 E_md4hash(plaintext, ret_pwd);
373                 SAFE_FREE(plaintext);
374                 return True;
375         }
376
377         return secrets_fetch_trust_account_password_legacy(domain, ret_pwd,
378                                                            pass_last_set_time,
379                                                            channel);
380 }
381
382 /************************************************************************
383  Routine to delete all information related to the domain joined machine.
384 ************************************************************************/
385
386 bool secrets_delete_machine_password_ex(const char *domain, const char *realm)
387 {
388         const char *tmpkey = NULL;
389         bool ok;
390
391         tmpkey = domain_info_keystr(domain);
392         ok = secrets_delete(tmpkey);
393         if (!ok) {
394                 return false;
395         }
396
397         if (realm != NULL) {
398                 tmpkey = des_salt_key(domain);
399                 ok = secrets_delete(tmpkey);
400                 if (!ok) {
401                         return false;
402                 }
403         }
404
405         tmpkey = domain_guid_keystr(domain);
406         ok = secrets_delete(tmpkey);
407         if (!ok) {
408                 return false;
409         }
410
411         tmpkey = machine_prev_password_keystr(domain);
412         ok = secrets_delete(tmpkey);
413         if (!ok) {
414                 return false;
415         }
416
417         tmpkey = machine_password_keystr(domain);
418         ok = secrets_delete(tmpkey);
419         if (!ok) {
420                 return false;
421         }
422
423         tmpkey = machine_sec_channel_type_keystr(domain);
424         ok = secrets_delete(tmpkey);
425         if (!ok) {
426                 return false;
427         }
428
429         tmpkey = machine_last_change_time_keystr(domain);
430         ok = secrets_delete(tmpkey);
431         if (!ok) {
432                 return false;
433         }
434
435         tmpkey = domain_sid_keystr(domain);
436         ok = secrets_delete(tmpkey);
437         if (!ok) {
438                 return false;
439         }
440
441         return true;
442 }
443
444 /************************************************************************
445  Routine to delete the domain sid
446 ************************************************************************/
447
448 bool secrets_delete_domain_sid(const char *domain)
449 {
450         return secrets_delete_entry(domain_sid_keystr(domain));
451 }
452
453 /************************************************************************
454  Set the machine trust account password, the old pw and last change
455  time, domain SID and salting principals based on values passed in
456  (added to supprt the secrets_tdb_sync module on secrets.ldb)
457 ************************************************************************/
458
459 bool secrets_store_machine_pw_sync(const char *pass, const char *oldpass, const char *domain,
460                                    const char *realm,
461                                    const char *salting_principal, uint32_t supported_enc_types,
462                                    const struct dom_sid *domain_sid, uint32_t last_change_time,
463                                    uint32_t secure_channel_type,
464                                    bool delete_join)
465 {
466         bool ret;
467         uint8_t last_change_time_store[4];
468         TALLOC_CTX *frame = talloc_stackframe();
469         uint8_t sec_channel_bytes[4];
470
471         if (delete_join) {
472                 secrets_delete_machine_password_ex(domain, realm);
473                 TALLOC_FREE(frame);
474                 return true;
475         }
476
477         ret = secrets_store(machine_password_keystr(domain), pass, strlen(pass)+1);
478         if (!ret) {
479                 TALLOC_FREE(frame);
480                 return ret;
481         }
482
483         if (oldpass) {
484                 ret = secrets_store(machine_prev_password_keystr(domain), oldpass, strlen(oldpass)+1);
485         } else {
486                 ret = secrets_delete(machine_prev_password_keystr(domain));
487         }
488         if (!ret) {
489                 TALLOC_FREE(frame);
490                 return ret;
491         }
492
493         if (secure_channel_type == 0) {
494                 /* We delete this and instead have the read code fall back to
495                  * a default based on server role, as our caller can't specify
496                  * this with any more certainty */
497                 ret = secrets_delete(machine_sec_channel_type_keystr(domain));
498                 if (!ret) {
499                         TALLOC_FREE(frame);
500                         return ret;
501                 }
502         } else {
503                 SIVAL(&sec_channel_bytes, 0, secure_channel_type);
504                 ret = secrets_store(machine_sec_channel_type_keystr(domain), 
505                                     &sec_channel_bytes, sizeof(sec_channel_bytes));
506                 if (!ret) {
507                         TALLOC_FREE(frame);
508                         return ret;
509                 }
510         }
511
512         SIVAL(&last_change_time_store, 0, last_change_time);
513         ret = secrets_store(machine_last_change_time_keystr(domain),
514                             &last_change_time_store, sizeof(last_change_time));
515
516         if (!ret) {
517                 TALLOC_FREE(frame);
518                 return ret;
519         }
520
521         ret = secrets_store_domain_sid(domain, domain_sid);
522
523         if (!ret) {
524                 TALLOC_FREE(frame);
525                 return ret;
526         }
527
528         if (realm != NULL) {
529                 char *key = des_salt_key(realm);
530
531                 if (salting_principal != NULL) {
532                         ret = secrets_store(key,
533                                             salting_principal,
534                                             strlen(salting_principal)+1);
535                 } else {
536                         ret = secrets_delete(key);
537                 }
538         }
539
540         TALLOC_FREE(frame);
541         return ret;
542 }
543
544 /************************************************************************
545  Return the standard DES salt key
546 ************************************************************************/
547
548 char* kerberos_standard_des_salt( void )
549 {
550         fstring salt;
551
552         fstr_sprintf( salt, "host/%s.%s@", lp_netbios_name(), lp_realm() );
553         (void)strlower_m( salt );
554         fstrcat( salt, lp_realm() );
555
556         return SMB_STRDUP( salt );
557 }
558
559 /************************************************************************
560 ************************************************************************/
561
562 static char *des_salt_key(const char *realm)
563 {
564         char *keystr;
565
566         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/DES/%s",
567                                             SECRETS_SALTING_PRINCIPAL,
568                                             realm);
569         SMB_ASSERT(keystr != NULL);
570         return keystr;
571 }
572
573 /************************************************************************
574 ************************************************************************/
575
576 bool kerberos_secrets_store_des_salt( const char* salt )
577 {
578         char* key;
579         bool ret;
580
581         key = des_salt_key(lp_realm());
582         if (key == NULL) {
583                 DEBUG(0,("kerberos_secrets_store_des_salt: failed to generate key!\n"));
584                 return False;
585         }
586
587         if ( !salt ) {
588                 DEBUG(8,("kerberos_secrets_store_des_salt: deleting salt\n"));
589                 secrets_delete_entry( key );
590                 return True;
591         }
592
593         DEBUG(3,("kerberos_secrets_store_des_salt: Storing salt \"%s\"\n", salt));
594
595         ret = secrets_store( key, salt, strlen(salt)+1 );
596
597         TALLOC_FREE(key);
598
599         return ret;
600 }
601
602 /************************************************************************
603 ************************************************************************/
604
605 static
606 char* kerberos_secrets_fetch_des_salt( void )
607 {
608         char *salt, *key;
609
610         key = des_salt_key(lp_realm());
611         if (key == NULL) {
612                 DEBUG(0,("kerberos_secrets_fetch_des_salt: failed to generate key!\n"));
613                 return NULL;
614         }
615
616         salt = (char*)secrets_fetch( key, NULL );
617
618         TALLOC_FREE(key);
619
620         return salt;
621 }
622
623 /************************************************************************
624  Routine to get the salting principal for this service.
625  Caller must free if return is not null.
626  ************************************************************************/
627
628 char *kerberos_secrets_fetch_salt_princ(void)
629 {
630         char *salt_princ_s;
631         /* lookup new key first */
632
633         salt_princ_s = kerberos_secrets_fetch_des_salt();
634         if (salt_princ_s == NULL) {
635                 /* fall back to host/machine.realm@REALM */
636                 salt_princ_s = kerberos_standard_des_salt();
637         }
638
639         return salt_princ_s;
640 }
641
642 /************************************************************************
643  Routine to fetch the previous plaintext machine account password for a realm
644  the password is assumed to be a null terminated ascii string.
645 ************************************************************************/
646
647 char *secrets_fetch_prev_machine_password(const char *domain)
648 {
649         return (char *)secrets_fetch(machine_prev_password_keystr(domain), NULL);
650 }
651
652 /************************************************************************
653  Routine to fetch the last change time of the machine account password
654   for a realm
655 ************************************************************************/
656
657 time_t secrets_fetch_pass_last_set_time(const char *domain)
658 {
659         uint32_t *last_set_time;
660         time_t pass_last_set_time;
661
662         last_set_time = secrets_fetch(machine_last_change_time_keystr(domain),
663                                       NULL);
664         if (last_set_time) {
665                 pass_last_set_time = IVAL(last_set_time,0);
666                 SAFE_FREE(last_set_time);
667         } else {
668                 pass_last_set_time = 0;
669         }
670
671         return pass_last_set_time;
672 }
673
674 /************************************************************************
675  Routine to fetch the plaintext machine account password for a realm
676  the password is assumed to be a null terminated ascii string.
677 ************************************************************************/
678
679 char *secrets_fetch_machine_password(const char *domain,
680                                      time_t *pass_last_set_time,
681                                      enum netr_SchannelType *channel)
682 {
683         char *ret;
684         ret = (char *)secrets_fetch(machine_password_keystr(domain), NULL);
685
686         if (pass_last_set_time) {
687                 *pass_last_set_time = secrets_fetch_pass_last_set_time(domain);
688         }
689
690         if (channel) {
691                 size_t size;
692                 uint32_t *channel_type;
693                 channel_type = (unsigned int *)secrets_fetch(machine_sec_channel_type_keystr(domain), &size);
694                 if (channel_type) {
695                         *channel = IVAL(channel_type,0);
696                         SAFE_FREE(channel_type);
697                 } else {
698                         *channel = get_default_sec_channel();
699                 }
700         }
701
702         return ret;
703 }
704
705 static char *domain_info_keystr(const char *domain)
706 {
707         char *keystr;
708
709         keystr = talloc_asprintf_strupper_m(talloc_tos(), "%s/%s",
710                                             SECRETS_MACHINE_DOMAIN_INFO,
711                                             domain);
712         SMB_ASSERT(keystr != NULL);
713         return keystr;
714 }
715
716 /************************************************************************
717  Routine to get account password to trusted domain
718 ************************************************************************/
719
720 static NTSTATUS secrets_fetch_domain_info1_by_key(const char *key,
721                                 TALLOC_CTX *mem_ctx,
722                                 struct secrets_domain_info1 **_info1)
723 {
724         struct secrets_domain_infoB sdib = { .version = 0, };
725         enum ndr_err_code ndr_err;
726         /* unpacking structures */
727         DATA_BLOB blob;
728
729         /* fetching trusted domain password structure */
730         blob.data = (uint8_t *)secrets_fetch(key, &blob.length);
731         if (blob.data == NULL) {
732                 DBG_NOTICE("secrets_fetch failed!\n");
733                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
734         }
735
736         /* unpack trusted domain password */
737         ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &sdib,
738                         (ndr_pull_flags_fn_t)ndr_pull_secrets_domain_infoB);
739         SAFE_FREE(blob.data);
740         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
741                 DBG_ERR("ndr_pull_struct_blob failed - %s!\n",
742                         ndr_errstr(ndr_err));
743                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
744         }
745
746         if (sdib.version != SECRETS_DOMAIN_INFO_VERSION_1) {
747                 DBG_ERR("sdib.version = %u\n", (unsigned)sdib.version);
748                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
749         }
750
751         *_info1 = sdib.info.info1;
752         return NT_STATUS_OK;;
753 }
754
755 static NTSTATUS secrets_fetch_domain_info(const char *domain,
756                                           TALLOC_CTX *mem_ctx,
757                                           struct secrets_domain_info1 **pinfo)
758 {
759         char *key = domain_info_keystr(domain);
760         return secrets_fetch_domain_info1_by_key(key, mem_ctx, pinfo);
761 }
762
763 void secrets_debug_domain_info(int lvl, const struct secrets_domain_info1 *info1,
764                                const char *name)
765 {
766         struct secrets_domain_infoB sdib = {
767                 .version = SECRETS_DOMAIN_INFO_VERSION_1,
768         };
769
770         sdib.info.info1 = discard_const_p(struct secrets_domain_info1, info1);
771
772         ndr_print_debug((ndr_print_fn_t)ndr_print_secrets_domain_infoB,
773                         name, &sdib);
774 }
775
776 char *secrets_domain_info_string(TALLOC_CTX *mem_ctx, const struct secrets_domain_info1 *info1,
777                                  const char *name, bool include_secrets)
778 {
779         TALLOC_CTX *frame = talloc_stackframe();
780         struct secrets_domain_infoB sdib = {
781                 .version = SECRETS_DOMAIN_INFO_VERSION_1,
782         };
783         struct ndr_print *ndr = NULL;
784         char *ret = NULL;
785
786         sdib.info.info1 = discard_const_p(struct secrets_domain_info1, info1);
787
788         ndr = talloc_zero(frame, struct ndr_print);
789         if (ndr == NULL) {
790                 TALLOC_FREE(frame);
791                 return NULL;
792         }
793         ndr->private_data = talloc_strdup(ndr, "");
794         if (ndr->private_data == NULL) {
795                 TALLOC_FREE(frame);
796                 return NULL;
797         }
798         ndr->print = ndr_print_string_helper;
799         ndr->depth = 1;
800         ndr->print_secrets = include_secrets;
801
802         ndr_print_secrets_domain_infoB(ndr, name, &sdib);
803         ret = talloc_steal(mem_ctx, (char *)ndr->private_data);
804         TALLOC_FREE(frame);
805         return ret;
806 }
807
808 static NTSTATUS secrets_store_domain_info1_by_key(const char *key,
809                                         const struct secrets_domain_info1 *info1)
810 {
811         struct secrets_domain_infoB sdib = {
812                 .version = SECRETS_DOMAIN_INFO_VERSION_1,
813         };
814         /* packing structures */
815         DATA_BLOB blob;
816         enum ndr_err_code ndr_err;
817         bool ok;
818
819         sdib.info.info1 = discard_const_p(struct secrets_domain_info1, info1);
820
821         ndr_err = ndr_push_struct_blob(&blob, talloc_tos(), &sdib,
822                         (ndr_push_flags_fn_t)ndr_push_secrets_domain_infoB);
823         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
824                 return ndr_map_error2ntstatus(ndr_err);
825         }
826
827         ok = secrets_store(key, blob.data, blob.length);
828         data_blob_clear_free(&blob);
829         if (!ok) {
830                 return NT_STATUS_INTERNAL_DB_ERROR;
831         }
832
833         return NT_STATUS_OK;
834 }
835
836 static NTSTATUS secrets_store_domain_info(const struct secrets_domain_info1 *info,
837                                           bool upgrade)
838 {
839         TALLOC_CTX *frame = talloc_stackframe();
840         const char *domain = info->domain_info.name.string;
841         const char *realm = info->domain_info.dns_domain.string;
842         char *key = domain_info_keystr(domain);
843         struct db_context *db = NULL;
844         struct timeval last_change_tv;
845         const DATA_BLOB *cleartext_blob = NULL;
846         DATA_BLOB pw_blob = data_blob_null;
847         DATA_BLOB old_pw_blob = data_blob_null;
848         const char *pw = NULL;
849         const char *old_pw = NULL;
850         bool ok;
851         NTSTATUS status;
852         int ret;
853         int role = lp_server_role();
854
855         switch (info->secure_channel_type) {
856         case SEC_CHAN_WKSTA:
857         case SEC_CHAN_BDC:
858                 if (!upgrade && role >= ROLE_ACTIVE_DIRECTORY_DC) {
859                         DBG_ERR("AD_DC not supported for %s\n",
860                                 domain);
861                         TALLOC_FREE(frame);
862                         return NT_STATUS_INTERNAL_ERROR;
863                 }
864
865                 break;
866         default:
867                 DBG_ERR("SEC_CHAN_* not supported for %s\n",
868                         domain);
869                 TALLOC_FREE(frame);
870                 return NT_STATUS_INTERNAL_ERROR;
871         }
872
873         db = secrets_db_ctx();
874
875         ret = dbwrap_transaction_start(db);
876         if (ret != 0) {
877                 DBG_ERR("dbwrap_transaction_start() failed for %s\n",
878                         domain);
879                 TALLOC_FREE(frame);
880                 return NT_STATUS_INTERNAL_DB_ERROR;
881         }
882
883         ok = secrets_clear_domain_protection(domain);
884         if (!ok) {
885                 DBG_ERR("secrets_clear_domain_protection(%s) failed\n",
886                         domain);
887                 dbwrap_transaction_cancel(db);
888                 TALLOC_FREE(frame);
889                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
890         }
891
892         ok = secrets_delete_machine_password_ex(domain, realm);
893         if (!ok) {
894                 DBG_ERR("secrets_delete_machine_password_ex(%s) failed\n",
895                         domain);
896                 dbwrap_transaction_cancel(db);
897                 TALLOC_FREE(frame);
898                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
899         }
900
901         status = secrets_store_domain_info1_by_key(key, info);
902         if (!NT_STATUS_IS_OK(status)) {
903                 DBG_ERR("secrets_store_domain_info1_by_key() failed "
904                         "for %s - %s\n", domain, nt_errstr(status));
905                 dbwrap_transaction_cancel(db);
906                 TALLOC_FREE(frame);
907                 return status;
908         }
909
910         /*
911          * We use info->password_last_change instead
912          * of info->password.change_time because
913          * we may want to defer the next change approach
914          * if the server rejected the change the last time,
915          * e.g. due to RefusePasswordChange=1.
916          */
917         nttime_to_timeval(&last_change_tv, info->password_last_change);
918
919         cleartext_blob = &info->password->cleartext_blob;
920         ok = convert_string_talloc(frame, CH_UTF16MUNGED, CH_UNIX,
921                                    cleartext_blob->data,
922                                    cleartext_blob->length,
923                                    (void **)&pw_blob.data,
924                                    &pw_blob.length);
925         if (!ok) {
926                 status = NT_STATUS_UNMAPPABLE_CHARACTER;
927                 if (errno == ENOMEM) {
928                         status = NT_STATUS_NO_MEMORY;
929                 }
930                 DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) "
931                         "failed for pw of %s - %s\n",
932                         domain, nt_errstr(status));
933                 dbwrap_transaction_cancel(db);
934                 TALLOC_FREE(frame);
935                 return status;
936         }
937         pw = (const char *)pw_blob.data;
938         if (info->old_password != NULL) {
939                 cleartext_blob = &info->old_password->cleartext_blob;
940                 ok = convert_string_talloc(frame, CH_UTF16MUNGED, CH_UNIX,
941                                            cleartext_blob->data,
942                                            cleartext_blob->length,
943                                            (void **)&old_pw_blob.data,
944                                            &old_pw_blob.length);
945                 if (!ok) {
946                         status = NT_STATUS_UNMAPPABLE_CHARACTER;
947                         if (errno == ENOMEM) {
948                                 status = NT_STATUS_NO_MEMORY;
949                         }
950                         DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) "
951                                 "failed for old_pw of %s - %s\n",
952                                 domain, nt_errstr(status));
953                         dbwrap_transaction_cancel(db);
954                         data_blob_clear_free(&pw_blob);
955                         TALLOC_FREE(frame);
956                         return status;
957                 }
958                 old_pw = (const char *)old_pw_blob.data;
959         }
960
961         ok = secrets_store_machine_pw_sync(pw, old_pw,
962                                            domain, realm,
963                                            info->salt_principal,
964                                            info->supported_enc_types,
965                                            info->domain_info.sid,
966                                            last_change_tv.tv_sec,
967                                            info->secure_channel_type,
968                                            false); /* delete_join */
969         data_blob_clear_free(&pw_blob);
970         data_blob_clear_free(&old_pw_blob);
971         if (!ok) {
972                 DBG_ERR("secrets_store_machine_pw_sync(%s) failed\n",
973                         domain);
974                 dbwrap_transaction_cancel(db);
975                 TALLOC_FREE(frame);
976                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
977         }
978
979         if (!GUID_all_zero(&info->domain_info.domain_guid)) {
980                 ok = secrets_store_domain_guid(domain,
981                                 &info->domain_info.domain_guid);
982                 if (!ok) {
983                         DBG_ERR("secrets_store_domain_guid(%s) failed\n",
984                                 domain);
985                         dbwrap_transaction_cancel(db);
986                         TALLOC_FREE(frame);
987                         return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
988                 }
989         }
990
991         ok = secrets_mark_domain_protected(domain);
992         if (!ok) {
993                 DBG_ERR("secrets_mark_domain_protected(%s) failed\n",
994                         domain);
995                 dbwrap_transaction_cancel(db);
996                 TALLOC_FREE(frame);
997                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
998         }
999
1000         ret = dbwrap_transaction_commit(db);
1001         if (ret != 0) {
1002                 DBG_ERR("dbwrap_transaction_commit() failed for %s\n",
1003                         domain);
1004                 TALLOC_FREE(frame);
1005                 return NT_STATUS_INTERNAL_DB_ERROR;
1006         }
1007
1008         TALLOC_FREE(frame);
1009         return NT_STATUS_OK;
1010 }
1011
1012 static int secrets_domain_info_kerberos_keys(struct secrets_domain_info1_password *p,
1013                                              const char *salt_principal)
1014 {
1015 #ifdef HAVE_ADS
1016         krb5_error_code krb5_ret;
1017         krb5_context krb5_ctx = NULL;
1018         DATA_BLOB cleartext_utf8_b = data_blob_null;
1019         krb5_data cleartext_utf8;
1020         krb5_data salt;
1021         krb5_keyblock key;
1022         DATA_BLOB aes_256_b = data_blob_null;
1023         DATA_BLOB aes_128_b = data_blob_null;
1024         DATA_BLOB des_md5_b = data_blob_null;
1025         bool ok;
1026 #endif /* HAVE_ADS */
1027         DATA_BLOB arc4_b = data_blob_null;
1028         const uint16_t max_keys = 4;
1029         struct secrets_domain_info1_kerberos_key *keys = NULL;
1030         uint16_t idx = 0;
1031         char *salt_data = NULL;
1032
1033         /*
1034          * We calculate:
1035          * ENCTYPE_AES256_CTS_HMAC_SHA1_96
1036          * ENCTYPE_AES128_CTS_HMAC_SHA1_96
1037          * ENCTYPE_ARCFOUR_HMAC
1038          * ENCTYPE_DES_CBC_MD5
1039          *
1040          * We don't include ENCTYPE_DES_CBC_CRC
1041          * as W2008R2 also doesn't store it anymore.
1042          *
1043          * Note we store all enctypes we support,
1044          * including the weak encryption types,
1045          * but that's no problem as we also
1046          * store the cleartext password anyway.
1047          *
1048          * Which values are then used to construct
1049          * a keytab is configured at runtime and the
1050          * configuration of msDS-SupportedEncryptionTypes.
1051          *
1052          * If we don't have kerberos support or no
1053          * salt, we only generate an entry for arcfour-hmac-md5.
1054          */
1055         keys = talloc_zero_array(p,
1056                                  struct secrets_domain_info1_kerberos_key,
1057                                  max_keys);
1058         if (keys == NULL) {
1059                 return ENOMEM;
1060         }
1061
1062         arc4_b = data_blob_talloc(keys,
1063                                   p->nt_hash.hash,
1064                                   sizeof(p->nt_hash.hash));
1065         if (arc4_b.data == NULL) {
1066                 DBG_ERR("data_blob_talloc failed for arcfour-hmac-md5.\n");
1067                 TALLOC_FREE(keys);
1068                 return ENOMEM;
1069         }
1070
1071 #ifdef HAVE_ADS
1072         if (salt_principal == NULL) {
1073                 goto no_kerberos;
1074         }
1075
1076         initialize_krb5_error_table();
1077         krb5_ret = krb5_init_context(&krb5_ctx);
1078         if (krb5_ret != 0) {
1079                 TALLOC_FREE(keys);
1080                 return krb5_ret;
1081         }
1082
1083         krb5_ret = smb_krb5_salt_principal2data(krb5_ctx, salt_principal,
1084                                                 p, &salt_data);
1085         if (krb5_ret != 0) {
1086                 DBG_ERR("smb_krb5_salt_principal2data(%s) failed: %s\n",
1087                         salt_principal,
1088                         smb_get_krb5_error_message(krb5_ctx, krb5_ret, keys));
1089                 krb5_free_context(krb5_ctx);
1090                 TALLOC_FREE(keys);
1091                 return krb5_ret;
1092         }
1093
1094         salt = (krb5_data) {
1095                 .data = discard_const(salt_data),
1096                 .length = strlen(salt_data),
1097         };
1098
1099         ok = convert_string_talloc(keys, CH_UTF16MUNGED, CH_UTF8,
1100                                    p->cleartext_blob.data,
1101                                    p->cleartext_blob.length,
1102                                    (void **)&cleartext_utf8_b.data,
1103                                    &cleartext_utf8_b.length);
1104         if (!ok) {
1105                 if (errno != 0) {
1106                         krb5_ret = errno;
1107                 } else {
1108                         krb5_ret = EINVAL;
1109                 }
1110                 krb5_free_context(krb5_ctx);
1111                 TALLOC_FREE(keys);
1112                 return krb5_ret;
1113         }
1114         cleartext_utf8.data = (void *)cleartext_utf8_b.data;
1115         cleartext_utf8.length = cleartext_utf8_b.length;
1116
1117         krb5_ret = smb_krb5_create_key_from_string(krb5_ctx,
1118                                                    NULL,
1119                                                    &salt,
1120                                                    &cleartext_utf8,
1121                                                    ENCTYPE_AES256_CTS_HMAC_SHA1_96,
1122                                                    &key);
1123         if (krb5_ret != 0) {
1124                 DBG_ERR("generation of a aes256-cts-hmac-sha1-96 key failed: %s\n",
1125                         smb_get_krb5_error_message(krb5_ctx, krb5_ret, keys));
1126                 krb5_free_context(krb5_ctx);
1127                 TALLOC_FREE(keys);
1128                 TALLOC_FREE(salt_data);
1129                 return krb5_ret;
1130         }
1131         aes_256_b = data_blob_talloc(keys,
1132                                      KRB5_KEY_DATA(&key),
1133                                      KRB5_KEY_LENGTH(&key));
1134         krb5_free_keyblock_contents(krb5_ctx, &key);
1135         if (aes_256_b.data == NULL) {
1136                 DBG_ERR("data_blob_talloc failed for aes-256.\n");
1137                 krb5_free_context(krb5_ctx);
1138                 TALLOC_FREE(keys);
1139                 TALLOC_FREE(salt_data);
1140                 return ENOMEM;
1141         }
1142
1143         krb5_ret = smb_krb5_create_key_from_string(krb5_ctx,
1144                                                    NULL,
1145                                                    &salt,
1146                                                    &cleartext_utf8,
1147                                                    ENCTYPE_AES128_CTS_HMAC_SHA1_96,
1148                                                    &key);
1149         if (krb5_ret != 0) {
1150                 DBG_ERR("generation of a aes128-cts-hmac-sha1-96 key failed: %s\n",
1151                         smb_get_krb5_error_message(krb5_ctx, krb5_ret, keys));
1152                 krb5_free_context(krb5_ctx);
1153                 TALLOC_FREE(keys);
1154                 TALLOC_FREE(salt_data);
1155                 return krb5_ret;
1156         }
1157         aes_128_b = data_blob_talloc(keys,
1158                                      KRB5_KEY_DATA(&key),
1159                                      KRB5_KEY_LENGTH(&key));
1160         krb5_free_keyblock_contents(krb5_ctx, &key);
1161         if (aes_128_b.data == NULL) {
1162                 DBG_ERR("data_blob_talloc failed for aes-128.\n");
1163                 krb5_free_context(krb5_ctx);
1164                 TALLOC_FREE(keys);
1165                 TALLOC_FREE(salt_data);
1166                 return ENOMEM;
1167         }
1168
1169         krb5_ret = smb_krb5_create_key_from_string(krb5_ctx,
1170                                                    NULL,
1171                                                    &salt,
1172                                                    &cleartext_utf8,
1173                                                    ENCTYPE_DES_CBC_MD5,
1174                                                    &key);
1175         if (krb5_ret != 0) {
1176                 DBG_ERR("generation of a des-cbc-md5 key failed: %s\n",
1177                         smb_get_krb5_error_message(krb5_ctx, krb5_ret, keys));
1178                 krb5_free_context(krb5_ctx);
1179                 TALLOC_FREE(keys);
1180                 TALLOC_FREE(salt_data);
1181                 return krb5_ret;
1182         }
1183         des_md5_b = data_blob_talloc(keys,
1184                                      KRB5_KEY_DATA(&key),
1185                                      KRB5_KEY_LENGTH(&key));
1186         krb5_free_keyblock_contents(krb5_ctx, &key);
1187         if (des_md5_b.data == NULL) {
1188                 DBG_ERR("data_blob_talloc failed for des-cbc-md5.\n");
1189                 krb5_free_context(krb5_ctx);
1190                 TALLOC_FREE(keys);
1191                 TALLOC_FREE(salt_data);
1192                 return ENOMEM;
1193         }
1194
1195         krb5_free_context(krb5_ctx);
1196 no_kerberos:
1197
1198         if (aes_256_b.length != 0) {
1199                 keys[idx].keytype               = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
1200                 keys[idx].iteration_count       = 4096;
1201                 keys[idx].value                 = aes_256_b;
1202                 idx += 1;
1203         }
1204
1205         if (aes_128_b.length != 0) {
1206                 keys[idx].keytype               = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
1207                 keys[idx].iteration_count       = 4096;
1208                 keys[idx].value                 = aes_128_b;
1209                 idx += 1;
1210         }
1211
1212 #endif /* HAVE_ADS */
1213
1214         keys[idx].keytype               = ENCTYPE_ARCFOUR_HMAC;
1215         keys[idx].iteration_count       = 4096;
1216         keys[idx].value                 = arc4_b;
1217         idx += 1;
1218
1219 #ifdef HAVE_ADS
1220         if (des_md5_b.length != 0) {
1221                 keys[idx].keytype               = ENCTYPE_DES_CBC_MD5;
1222                 keys[idx].iteration_count       = 4096;
1223                 keys[idx].value                 = des_md5_b;
1224                 idx += 1;
1225         }
1226 #endif /* HAVE_ADS */
1227
1228         p->salt_data = salt_data;
1229         p->default_iteration_count = 4096;
1230         p->num_keys = idx;
1231         p->keys = keys;
1232         return 0;
1233 }
1234
1235 static NTSTATUS secrets_domain_info_password_create(TALLOC_CTX *mem_ctx,
1236                                 const char *cleartext_unix,
1237                                 const char *salt_principal,
1238                                 NTTIME change_time,
1239                                 const char *change_server,
1240                                 struct secrets_domain_info1_password **_p)
1241 {
1242         struct secrets_domain_info1_password *p = NULL;
1243         bool ok;
1244         size_t len;
1245         int ret;
1246
1247         if (change_server == NULL) {
1248                 return NT_STATUS_INVALID_PARAMETER_MIX;
1249         }
1250
1251         p = talloc_zero(mem_ctx, struct secrets_domain_info1_password);
1252         if (p == NULL) {
1253                 return NT_STATUS_NO_MEMORY;
1254         }
1255         p->change_time = change_time;
1256         p->change_server = talloc_strdup(p, change_server);
1257         if (p->change_server == NULL) {
1258                 TALLOC_FREE(p);
1259                 return NT_STATUS_NO_MEMORY;
1260         }
1261         len = strlen(cleartext_unix);
1262         ok = convert_string_talloc(p, CH_UNIX, CH_UTF16,
1263                                    cleartext_unix, len,
1264                                    (void **)&p->cleartext_blob.data,
1265                                    &p->cleartext_blob.length);
1266         if (!ok) {
1267                 NTSTATUS status = NT_STATUS_UNMAPPABLE_CHARACTER;
1268                 if (errno == ENOMEM) {
1269                         status = NT_STATUS_NO_MEMORY;
1270                 }
1271                 TALLOC_FREE(p);
1272                 return status;
1273         }
1274         mdfour(p->nt_hash.hash,
1275                p->cleartext_blob.data,
1276                p->cleartext_blob.length);
1277
1278         ret = secrets_domain_info_kerberos_keys(p, salt_principal);
1279         if (ret != 0) {
1280                 NTSTATUS status = krb5_to_nt_status(ret);
1281                 TALLOC_FREE(p);
1282                 return status;
1283         }
1284
1285         *_p = p;
1286         return NT_STATUS_OK;
1287 }
1288
1289 NTSTATUS secrets_fetch_or_upgrade_domain_info(const char *domain,
1290                                         TALLOC_CTX *mem_ctx,
1291                                         struct secrets_domain_info1 **pinfo)
1292 {
1293         TALLOC_CTX *frame = NULL;
1294         struct secrets_domain_info1 *old = NULL;
1295         struct secrets_domain_info1 *info = NULL;
1296         const char *dns_domain = NULL;
1297         const char *server = NULL;
1298         struct db_context *db = NULL;
1299         time_t last_set_time;
1300         NTTIME last_set_nt;
1301         enum netr_SchannelType channel;
1302         char *pw = NULL;
1303         char *old_pw = NULL;
1304         struct dom_sid domain_sid;
1305         struct GUID domain_guid;
1306         bool ok;
1307         NTSTATUS status;
1308         int ret;
1309
1310         ok = strequal(domain, lp_workgroup());
1311         if (ok) {
1312                 dns_domain = lp_dnsdomain();
1313
1314                 if (dns_domain != NULL && dns_domain[0] == '\0') {
1315                         dns_domain = NULL;
1316                 }
1317         }
1318
1319         last_set_time = secrets_fetch_pass_last_set_time(domain);
1320         if (last_set_time == 0) {
1321                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1322         }
1323         unix_to_nt_time(&last_set_nt, last_set_time);
1324
1325         frame = talloc_stackframe();
1326
1327         status = secrets_fetch_domain_info(domain, frame, &old);
1328         if (NT_STATUS_IS_OK(status)) {
1329                 if (old->password_last_change >= last_set_nt) {
1330                         *pinfo = talloc_move(mem_ctx, &old);
1331                         TALLOC_FREE(frame);
1332                         return NT_STATUS_OK;
1333                 }
1334                 TALLOC_FREE(old);
1335         }
1336
1337         info = talloc_zero(frame, struct secrets_domain_info1);
1338         if (info == NULL) {
1339                 DBG_ERR("talloc_zero failed\n");
1340                 TALLOC_FREE(frame);
1341                 return NT_STATUS_NO_MEMORY;
1342         }
1343
1344         db = secrets_db_ctx();
1345
1346         ret = dbwrap_transaction_start(db);
1347         if (ret != 0) {
1348                 DBG_ERR("dbwrap_transaction_start() failed for %s\n",
1349                         domain);
1350                 TALLOC_FREE(frame);
1351                 return NT_STATUS_INTERNAL_DB_ERROR;
1352         }
1353
1354         pw = secrets_fetch_machine_password(domain,
1355                                             &last_set_time,
1356                                             &channel);
1357         if (pw == NULL) {
1358                 DBG_ERR("secrets_fetch_machine_password(%s) failed\n",
1359                         domain);
1360                 dbwrap_transaction_cancel(db);
1361                 TALLOC_FREE(frame);
1362                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1363         }
1364         unix_to_nt_time(&last_set_nt, last_set_time);
1365
1366         old_pw = secrets_fetch_prev_machine_password(domain);
1367
1368         ok = secrets_fetch_domain_sid(domain, &domain_sid);
1369         if (!ok) {
1370                 DBG_ERR("secrets_fetch_domain_sid(%s) failed\n",
1371                         domain);
1372                 dbwrap_transaction_cancel(db);
1373                 SAFE_FREE(old_pw);
1374                 SAFE_FREE(pw);
1375                 TALLOC_FREE(frame);
1376                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
1377         }
1378
1379         ok = secrets_fetch_domain_guid(domain, &domain_guid);
1380         if (!ok) {
1381                 domain_guid = GUID_zero();
1382         }
1383
1384         info->computer_name = lp_netbios_name();
1385         info->account_name = talloc_asprintf(frame, "%s$", info->computer_name);
1386         if (info->account_name == NULL) {
1387                 DBG_ERR("talloc_asprintf(%s$) failed\n", info->computer_name);
1388                 dbwrap_transaction_cancel(db);
1389                 SAFE_FREE(old_pw);
1390                 SAFE_FREE(pw);
1391                 TALLOC_FREE(frame);
1392                 return NT_STATUS_NO_MEMORY;
1393         }
1394         info->secure_channel_type = channel;
1395
1396         info->domain_info.name.string = domain;
1397         info->domain_info.dns_domain.string = dns_domain;
1398         info->domain_info.dns_forest.string = dns_domain;
1399         info->domain_info.domain_guid = domain_guid;
1400         info->domain_info.sid = &domain_sid;
1401
1402         info->trust_flags = NETR_TRUST_FLAG_PRIMARY;
1403         info->trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1404
1405         if (dns_domain != NULL) {
1406                 /*
1407                  * We just assume all AD domains are
1408                  * NETR_TRUST_FLAG_NATIVE these days.
1409                  *
1410                  * This isn't used anyway for now.
1411                  */
1412                 info->trust_flags |= NETR_TRUST_FLAG_NATIVE;
1413
1414                 info->trust_type = LSA_TRUST_TYPE_UPLEVEL;
1415
1416                 server = info->domain_info.dns_domain.string;
1417         } else {
1418                 info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1419
1420                 server = talloc_asprintf(info,
1421                                          "%s#%02X",
1422                                          domain,
1423                                          NBT_NAME_PDC);
1424                 if (server == NULL) {
1425                         DBG_ERR("talloc_asprintf(%s#%02X) failed\n",
1426                                 domain, NBT_NAME_PDC);
1427                         dbwrap_transaction_cancel(db);
1428                         SAFE_FREE(pw);
1429                         SAFE_FREE(old_pw);
1430                         TALLOC_FREE(frame);
1431                         return NT_STATUS_NO_MEMORY;
1432                 }
1433         }
1434         info->trust_attributes = LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL;
1435
1436         info->join_time = 0;
1437
1438         /*
1439          * We don't have enough information about the configured
1440          * enctypes.
1441          */
1442         info->supported_enc_types = 0;
1443         info->salt_principal = NULL;
1444         if (info->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
1445                 char *p = NULL;
1446
1447                 p = kerberos_secrets_fetch_salt_princ();
1448                 if (p == NULL) {
1449                         dbwrap_transaction_cancel(db);
1450                         SAFE_FREE(old_pw);
1451                         SAFE_FREE(pw);
1452                         TALLOC_FREE(frame);
1453                         return NT_STATUS_INTERNAL_ERROR;
1454                 }
1455                 info->salt_principal = talloc_strdup(info, p);
1456                 SAFE_FREE(p);
1457                 if (info->salt_principal == NULL) {
1458                         dbwrap_transaction_cancel(db);
1459                         SAFE_FREE(pw);
1460                         SAFE_FREE(old_pw);
1461                         TALLOC_FREE(frame);
1462                         return NT_STATUS_NO_MEMORY;
1463                 }
1464         }
1465
1466         info->password_last_change = last_set_nt;
1467         info->password_changes = 1;
1468         info->next_change = NULL;
1469
1470         status = secrets_domain_info_password_create(info,
1471                                                      pw,
1472                                                      info->salt_principal,
1473                                                      last_set_nt, server,
1474                                                      &info->password);
1475         SAFE_FREE(pw);
1476         if (!NT_STATUS_IS_OK(status)) {
1477                 DBG_ERR("secrets_domain_info_password_create(pw) failed "
1478                         "for %s - %s\n", domain, nt_errstr(status));
1479                 dbwrap_transaction_cancel(db);
1480                 SAFE_FREE(old_pw);
1481                 TALLOC_FREE(frame);
1482                 return status;
1483         }
1484
1485         /*
1486          * After a join we don't have old passwords.
1487          */
1488         if (old_pw != NULL) {
1489                 status = secrets_domain_info_password_create(info,
1490                                                              old_pw,
1491                                                              info->salt_principal,
1492                                                              0, server,
1493                                                              &info->old_password);
1494                 SAFE_FREE(old_pw);
1495                 if (!NT_STATUS_IS_OK(status)) {
1496                         DBG_ERR("secrets_domain_info_password_create(old) failed "
1497                                 "for %s - %s\n", domain, nt_errstr(status));
1498                         dbwrap_transaction_cancel(db);
1499                         TALLOC_FREE(frame);
1500                         return status;
1501                 }
1502                 info->password_changes += 1;
1503         } else {
1504                 info->old_password = NULL;
1505         }
1506         info->older_password = NULL;
1507
1508         secrets_debug_domain_info(DBGLVL_INFO, info, "upgrade");
1509
1510         status = secrets_store_domain_info(info, true /* upgrade */);
1511         if (!NT_STATUS_IS_OK(status)) {
1512                 DBG_ERR("secrets_store_domain_info() failed "
1513                         "for %s - %s\n", domain, nt_errstr(status));
1514                 dbwrap_transaction_cancel(db);
1515                 TALLOC_FREE(frame);
1516                 return status;
1517         }
1518
1519         /*
1520          * We now reparse it.
1521          */
1522         status = secrets_fetch_domain_info(domain, frame, &info);
1523         if (!NT_STATUS_IS_OK(status)) {
1524                 DBG_ERR("secrets_fetch_domain_info() failed "
1525                         "for %s - %s\n", domain, nt_errstr(status));
1526                 dbwrap_transaction_cancel(db);
1527                 TALLOC_FREE(frame);
1528                 return status;
1529         }
1530
1531         ret = dbwrap_transaction_commit(db);
1532         if (ret != 0) {
1533                 DBG_ERR("dbwrap_transaction_commit() failed for %s\n",
1534                         domain);
1535                 dbwrap_transaction_cancel(db);
1536                 TALLOC_FREE(frame);
1537                 return NT_STATUS_INTERNAL_DB_ERROR;
1538         }
1539
1540         *pinfo = talloc_move(mem_ctx, &info);
1541         TALLOC_FREE(frame);
1542         return NT_STATUS_OK;
1543 }
1544
1545 NTSTATUS secrets_store_JoinCtx(const struct libnet_JoinCtx *r)
1546 {
1547         TALLOC_CTX *frame = talloc_stackframe();
1548         struct secrets_domain_info1 *old = NULL;
1549         struct secrets_domain_info1 *info = NULL;
1550         struct db_context *db = NULL;
1551         struct timeval tv = timeval_current();
1552         NTTIME now = timeval_to_nttime(&tv);
1553         const char *domain = r->out.netbios_domain_name;
1554         NTSTATUS status;
1555         int ret;
1556
1557         info = talloc_zero(frame, struct secrets_domain_info1);
1558         if (info == NULL) {
1559                 DBG_ERR("talloc_zero failed\n");
1560                 TALLOC_FREE(frame);
1561                 return NT_STATUS_NO_MEMORY;
1562         }
1563
1564         info->computer_name = r->in.machine_name;
1565         info->account_name = r->out.account_name;
1566         info->secure_channel_type = r->in.secure_channel_type;
1567
1568         info->domain_info.name.string =
1569                 r->out.netbios_domain_name;
1570         info->domain_info.dns_domain.string =
1571                 r->out.dns_domain_name;
1572         info->domain_info.dns_forest.string =
1573                 r->out.forest_name;
1574         info->domain_info.domain_guid = r->out.domain_guid;
1575         info->domain_info.sid = r->out.domain_sid;
1576
1577         info->trust_flags = NETR_TRUST_FLAG_PRIMARY;
1578         info->trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1579         if (r->out.domain_is_ad) {
1580                 /*
1581                  * We just assume all AD domains are
1582                  * NETR_TRUST_FLAG_NATIVE these days.
1583                  *
1584                  * This isn't used anyway for now.
1585                  */
1586                 info->trust_flags |= NETR_TRUST_FLAG_NATIVE;
1587
1588                 info->trust_type = LSA_TRUST_TYPE_UPLEVEL;
1589         } else {
1590                 info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1591         }
1592         info->trust_attributes = LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL;
1593
1594         info->join_time = now;
1595
1596         info->supported_enc_types = r->out.set_encryption_types;
1597         info->salt_principal = r->out.krb5_salt;
1598
1599         if (info->salt_principal == NULL && r->out.domain_is_ad) {
1600                 char *p = NULL;
1601
1602                 ret = smb_krb5_salt_principal(info->domain_info.dns_domain.string,
1603                                               info->account_name,
1604                                               NULL /* userPrincipalName */,
1605                                               UF_WORKSTATION_TRUST_ACCOUNT,
1606                                               info, &p);
1607                 if (ret != 0) {
1608                         status = krb5_to_nt_status(ret);
1609                         DBG_ERR("smb_krb5_salt_principal() failed "
1610                                 "for %s - %s\n", domain, nt_errstr(status));
1611                         TALLOC_FREE(frame);
1612                         return status;
1613                 }
1614                 info->salt_principal = p;
1615         }
1616
1617         info->password_last_change = now;
1618         info->password_changes = 1;
1619         info->next_change = NULL;
1620
1621         status = secrets_domain_info_password_create(info,
1622                                                      r->in.machine_password,
1623                                                      info->salt_principal,
1624                                                      now, r->in.dc_name,
1625                                                      &info->password);
1626         if (!NT_STATUS_IS_OK(status)) {
1627                 DBG_ERR("secrets_domain_info_password_create(pw) failed "
1628                         "for %s - %s\n", domain, nt_errstr(status));
1629                 TALLOC_FREE(frame);
1630                 return status;
1631         }
1632
1633         db = secrets_db_ctx();
1634
1635         ret = dbwrap_transaction_start(db);
1636         if (ret != 0) {
1637                 DBG_ERR("dbwrap_transaction_start() failed for %s\n",
1638                         domain);
1639                 TALLOC_FREE(frame);
1640                 return NT_STATUS_INTERNAL_DB_ERROR;
1641         }
1642
1643         status = secrets_fetch_or_upgrade_domain_info(domain, frame, &old);
1644         if (NT_STATUS_EQUAL(status, NT_STATUS_CANT_ACCESS_DOMAIN_INFO)) {
1645                 DBG_DEBUG("no old join for domain(%s) available\n",
1646                           domain);
1647                 old = NULL;
1648         } else if (!NT_STATUS_IS_OK(status)) {
1649                 DBG_ERR("secrets_fetch_or_upgrade_domain_info(%s) failed\n",
1650                         domain);
1651                 dbwrap_transaction_cancel(db);
1652                 TALLOC_FREE(frame);
1653                 return status;
1654         }
1655
1656         /*
1657          * We reuse values from an old join, so that
1658          * we still accept already granted kerberos tickets.
1659          */
1660         if (old != NULL) {
1661                 info->old_password = old->password;
1662                 info->older_password = old->old_password;
1663         }
1664
1665         secrets_debug_domain_info(DBGLVL_INFO, info, "join");
1666
1667         status = secrets_store_domain_info(info, false /* upgrade */);
1668         if (!NT_STATUS_IS_OK(status)) {
1669                 DBG_ERR("secrets_store_domain_info() failed "
1670                         "for %s - %s\n", domain, nt_errstr(status));
1671                 dbwrap_transaction_cancel(db);
1672                 TALLOC_FREE(frame);
1673                 return status;
1674         }
1675
1676         ret = dbwrap_transaction_commit(db);
1677         if (ret != 0) {
1678                 DBG_ERR("dbwrap_transaction_commit() failed for %s\n",
1679                         domain);
1680                 TALLOC_FREE(frame);
1681                 return NT_STATUS_INTERNAL_DB_ERROR;
1682         }
1683
1684         TALLOC_FREE(frame);
1685         return NT_STATUS_OK;
1686 }
1687
1688 NTSTATUS secrets_prepare_password_change(const char *domain, const char *dcname,
1689                                          const char *cleartext_unix,
1690                                          TALLOC_CTX *mem_ctx,
1691                                          struct secrets_domain_info1 **pinfo,
1692                                          struct secrets_domain_info1_change **pprev)
1693 {
1694         TALLOC_CTX *frame = talloc_stackframe();
1695         struct db_context *db = NULL;
1696         struct secrets_domain_info1 *info = NULL;
1697         struct secrets_domain_info1_change *prev = NULL;
1698         struct secrets_domain_info1_change *next = NULL;
1699         struct timeval tv = timeval_current();
1700         NTTIME now = timeval_to_nttime(&tv);
1701         NTSTATUS status;
1702         int ret;
1703
1704         db = secrets_db_ctx();
1705
1706         ret = dbwrap_transaction_start(db);
1707         if (ret != 0) {
1708                 DBG_ERR("dbwrap_transaction_start() failed for %s\n",
1709                         domain);
1710                 TALLOC_FREE(frame);
1711                 return NT_STATUS_INTERNAL_DB_ERROR;
1712         }
1713
1714         status = secrets_fetch_or_upgrade_domain_info(domain, frame, &info);
1715         if (!NT_STATUS_IS_OK(status)) {
1716                 DBG_ERR("secrets_fetch_or_upgrade_domain_info(%s) failed\n",
1717                         domain);
1718                 dbwrap_transaction_cancel(db);
1719                 TALLOC_FREE(frame);
1720                 return status;
1721         }
1722
1723         prev = info->next_change;
1724         info->next_change = NULL;
1725
1726         next = talloc_zero(frame, struct secrets_domain_info1_change);
1727         if (next == NULL) {
1728                 DBG_ERR("talloc_zero failed\n");
1729                 TALLOC_FREE(frame);
1730                 return NT_STATUS_NO_MEMORY;
1731         }
1732
1733         if (prev != NULL) {
1734                 *next = *prev;
1735         } else {
1736                 status = secrets_domain_info_password_create(next,
1737                                                              cleartext_unix,
1738                                                              info->salt_principal,
1739                                                              now, dcname,
1740                                                              &next->password);
1741                 if (!NT_STATUS_IS_OK(status)) {
1742                         DBG_ERR("secrets_domain_info_password_create(next) failed "
1743                                 "for %s - %s\n", domain, nt_errstr(status));
1744                         dbwrap_transaction_cancel(db);
1745                         TALLOC_FREE(frame);
1746                         return status;
1747                 }
1748         }
1749
1750         next->local_status = NT_STATUS_OK;
1751         next->remote_status = NT_STATUS_NOT_COMMITTED;
1752         next->change_time = now;
1753         next->change_server = dcname;
1754
1755         info->next_change = next;
1756
1757         secrets_debug_domain_info(DBGLVL_INFO, info, "prepare_change");
1758
1759         status = secrets_store_domain_info(info, false /* upgrade */);
1760         if (!NT_STATUS_IS_OK(status)) {
1761                 DBG_ERR("secrets_store_domain_info() failed "
1762                         "for %s - %s\n", domain, nt_errstr(status));
1763                 dbwrap_transaction_cancel(db);
1764                 TALLOC_FREE(frame);
1765                 return status;
1766         }
1767
1768         /*
1769          * We now reparse it.
1770          */
1771         status = secrets_fetch_domain_info(domain, frame, &info);
1772         if (!NT_STATUS_IS_OK(status)) {
1773                 DBG_ERR("secrets_fetch_domain_info(%s) failed\n", domain);
1774                 dbwrap_transaction_cancel(db);
1775                 TALLOC_FREE(frame);
1776                 return status;
1777         }
1778
1779         ret = dbwrap_transaction_commit(db);
1780         if (ret != 0) {
1781                 DBG_ERR("dbwrap_transaction_commit() failed for %s\n",
1782                         domain);
1783                 TALLOC_FREE(frame);
1784                 return NT_STATUS_INTERNAL_DB_ERROR;
1785         }
1786
1787         *pinfo = talloc_move(mem_ctx, &info);
1788         if (prev != NULL) {
1789                 *pprev = talloc_move(mem_ctx, &prev);
1790         } else {
1791                 *pprev = NULL;
1792         }
1793
1794         TALLOC_FREE(frame);
1795         return NT_STATUS_OK;
1796 }
1797
1798 static NTSTATUS secrets_check_password_change(const struct secrets_domain_info1 *cookie,
1799                                               TALLOC_CTX *mem_ctx,
1800                                               struct secrets_domain_info1 **pstored)
1801 {
1802         const char *domain = cookie->domain_info.name.string;
1803         struct secrets_domain_info1 *stored = NULL;
1804         struct secrets_domain_info1_change *sn = NULL;
1805         struct secrets_domain_info1_change *cn = NULL;
1806         NTSTATUS status;
1807         int cmp;
1808
1809         if (cookie->next_change == NULL) {
1810                 DBG_ERR("cookie->next_change == NULL for %s.\n", domain);
1811                 return NT_STATUS_INTERNAL_ERROR;
1812         }
1813
1814         if (cookie->next_change->password == NULL) {
1815                 DBG_ERR("cookie->next_change->password == NULL for %s.\n", domain);
1816                 return NT_STATUS_INTERNAL_ERROR;
1817         }
1818
1819         if (cookie->password == NULL) {
1820                 DBG_ERR("cookie->password == NULL for %s.\n", domain);
1821                 return NT_STATUS_INTERNAL_ERROR;
1822         }
1823
1824         /*
1825          * Here we check that the given strucure still contains the
1826          * same secrets_domain_info1_change as currently stored.
1827          *
1828          * There's always a gap between secrets_prepare_password_change()
1829          * and the callers of secrets_check_password_change().
1830          */
1831
1832         status = secrets_fetch_domain_info(domain, mem_ctx, &stored);
1833         if (!NT_STATUS_IS_OK(status)) {
1834                 DBG_ERR("secrets_fetch_domain_info(%s) failed\n", domain);
1835                 return status;
1836         }
1837
1838         if (stored->next_change == NULL) {
1839                 /*
1840                  * We hit a race..., the administrator
1841                  * rejoined or something similar happened.
1842                  */
1843                 DBG_ERR("stored->next_change == NULL for %s.\n", domain);
1844                 TALLOC_FREE(stored);
1845                 return NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
1846         }
1847
1848         if (stored->password_last_change != cookie->password_last_change) {
1849                 struct timeval store_tv;
1850                 struct timeval_buf store_buf;
1851                 struct timeval cookie_tv;
1852                 struct timeval_buf cookie_buf;
1853
1854                 nttime_to_timeval(&store_tv, stored->password_last_change);
1855                 nttime_to_timeval(&cookie_tv, cookie->password_last_change);
1856
1857                 DBG_ERR("password_last_change differs %s != %s for %s.\n",
1858                         timeval_str_buf(&store_tv, false, false, &store_buf),
1859                         timeval_str_buf(&cookie_tv, false, false, &cookie_buf),
1860                         domain);
1861                 TALLOC_FREE(stored);
1862                 return NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
1863         }
1864
1865         sn = stored->next_change;
1866         cn = cookie->next_change;
1867
1868         if (sn->change_time != cn->change_time) {
1869                 struct timeval store_tv;
1870                 struct timeval_buf store_buf;
1871                 struct timeval cookie_tv;
1872                 struct timeval_buf cookie_buf;
1873
1874                 nttime_to_timeval(&store_tv, sn->change_time);
1875                 nttime_to_timeval(&cookie_tv, cn->change_time);
1876
1877                 DBG_ERR("next change_time differs %s != %s for %s.\n",
1878                         timeval_str_buf(&store_tv, false, false, &store_buf),
1879                         timeval_str_buf(&cookie_tv, false, false, &cookie_buf),
1880                         domain);
1881                 TALLOC_FREE(stored);
1882                 return NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
1883         }
1884
1885         if (sn->password->change_time != cn->password->change_time) {
1886                 struct timeval store_tv;
1887                 struct timeval_buf store_buf;
1888                 struct timeval cookie_tv;
1889                 struct timeval_buf cookie_buf;
1890
1891                 nttime_to_timeval(&store_tv, sn->password->change_time);
1892                 nttime_to_timeval(&cookie_tv, cn->password->change_time);
1893
1894                 DBG_ERR("next password.change_time differs %s != %s for %s.\n",
1895                         timeval_str_buf(&store_tv, false, false, &store_buf),
1896                         timeval_str_buf(&cookie_tv, false, false, &cookie_buf),
1897                         domain);
1898                 TALLOC_FREE(stored);
1899                 return NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
1900         }
1901
1902         cmp = memcmp(sn->password->nt_hash.hash,
1903                      cn->password->nt_hash.hash,
1904                      16);
1905         if (cmp != 0) {
1906                 DBG_ERR("next password.nt_hash differs for %s.\n",
1907                         domain);
1908                 TALLOC_FREE(stored);
1909                 return NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
1910         }
1911
1912         cmp = memcmp(stored->password->nt_hash.hash,
1913                      cookie->password->nt_hash.hash,
1914                      16);
1915         if (cmp != 0) {
1916                 DBG_ERR("password.nt_hash differs for %s.\n",
1917                         domain);
1918                 TALLOC_FREE(stored);
1919                 return NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
1920         }
1921
1922         *pstored = stored;
1923         return NT_STATUS_OK;
1924 }
1925
1926 static NTSTATUS secrets_abort_password_change(const char *change_server,
1927                                 NTSTATUS local_status,
1928                                 NTSTATUS remote_status,
1929                                 const struct secrets_domain_info1 *cookie,
1930                                 bool defer)
1931 {
1932         const char *domain = cookie->domain_info.name.string;
1933         TALLOC_CTX *frame = talloc_stackframe();
1934         struct db_context *db = NULL;
1935         struct secrets_domain_info1 *info = NULL;
1936         const char *reason = defer ? "defer_change" : "failed_change";
1937         struct timeval tv = timeval_current();
1938         NTTIME now = timeval_to_nttime(&tv);
1939         NTSTATUS status;
1940         int ret;
1941
1942         db = secrets_db_ctx();
1943
1944         ret = dbwrap_transaction_start(db);
1945         if (ret != 0) {
1946                 DBG_ERR("dbwrap_transaction_start() failed for %s\n",
1947                         domain);
1948                 TALLOC_FREE(frame);
1949                 return NT_STATUS_INTERNAL_DB_ERROR;
1950         }
1951
1952         /*
1953          * secrets_check_password_change()
1954          * checks that cookie->next_change
1955          * is valid and the same as store
1956          * in the database.
1957          */
1958         status = secrets_check_password_change(cookie, frame, &info);
1959         if (!NT_STATUS_IS_OK(status)) {
1960                 DBG_ERR("secrets_check_password_change(%s) failed\n", domain);
1961                 dbwrap_transaction_cancel(db);
1962                 TALLOC_FREE(frame);
1963                 return status;
1964         }
1965
1966         /*
1967          * Remember the last server and error.
1968          */
1969         info->next_change->change_server = change_server;
1970         info->next_change->change_time = now;
1971         info->next_change->local_status = local_status;
1972         info->next_change->remote_status = remote_status;
1973
1974         /*
1975          * Make sure the next automatic change is deferred.
1976          */
1977         if (defer) {
1978                 info->password_last_change = now;
1979         }
1980
1981         secrets_debug_domain_info(DBGLVL_WARNING, info, reason);
1982
1983         status = secrets_store_domain_info(info, false /* upgrade */);
1984         if (!NT_STATUS_IS_OK(status)) {
1985                 DBG_ERR("secrets_store_domain_info() failed "
1986                         "for %s - %s\n", domain, nt_errstr(status));
1987                 dbwrap_transaction_cancel(db);
1988                 TALLOC_FREE(frame);
1989                 return status;
1990         }
1991
1992         ret = dbwrap_transaction_commit(db);
1993         if (ret != 0) {
1994                 DBG_ERR("dbwrap_transaction_commit() failed for %s\n",
1995                         domain);
1996                 TALLOC_FREE(frame);
1997                 return NT_STATUS_INTERNAL_DB_ERROR;
1998         }
1999
2000         TALLOC_FREE(frame);
2001         return NT_STATUS_OK;
2002 }
2003
2004 NTSTATUS secrets_failed_password_change(const char *change_server,
2005                                         NTSTATUS local_status,
2006                                         NTSTATUS remote_status,
2007                                         const struct secrets_domain_info1 *cookie)
2008 {
2009         static const bool defer = false;
2010         return secrets_abort_password_change(change_server,
2011                                              local_status,
2012                                              remote_status,
2013                                              cookie, defer);
2014 }
2015
2016 NTSTATUS secrets_defer_password_change(const char *change_server,
2017                                        NTSTATUS local_status,
2018                                        NTSTATUS remote_status,
2019                                        const struct secrets_domain_info1 *cookie)
2020 {
2021         static const bool defer = true;
2022         return secrets_abort_password_change(change_server,
2023                                              local_status,
2024                                              remote_status,
2025                                              cookie, defer);
2026 }
2027
2028 NTSTATUS secrets_finish_password_change(const char *change_server,
2029                                         NTTIME change_time,
2030                                         const struct secrets_domain_info1 *cookie)
2031 {
2032         const char *domain = cookie->domain_info.name.string;
2033         TALLOC_CTX *frame = talloc_stackframe();
2034         struct db_context *db = NULL;
2035         struct secrets_domain_info1 *info = NULL;
2036         struct secrets_domain_info1_change *nc = NULL;
2037         NTSTATUS status;
2038         int ret;
2039
2040         db = secrets_db_ctx();
2041
2042         ret = dbwrap_transaction_start(db);
2043         if (ret != 0) {
2044                 DBG_ERR("dbwrap_transaction_start() failed for %s\n",
2045                         domain);
2046                 TALLOC_FREE(frame);
2047                 return NT_STATUS_INTERNAL_DB_ERROR;
2048         }
2049
2050         /*
2051          * secrets_check_password_change() checks that cookie->next_change is
2052          * valid and the same as store in the database.
2053          */
2054         status = secrets_check_password_change(cookie, frame, &info);
2055         if (!NT_STATUS_IS_OK(status)) {
2056                 DBG_ERR("secrets_check_password_change(%s) failed\n", domain);
2057                 dbwrap_transaction_cancel(db);
2058                 TALLOC_FREE(frame);
2059                 return status;
2060         }
2061
2062         nc = info->next_change;
2063
2064         nc->password->change_server = change_server;
2065         nc->password->change_time = change_time;
2066
2067         info->password_last_change = change_time;
2068         info->password_changes += 1;
2069         info->next_change = NULL;
2070
2071         info->older_password = info->old_password;
2072         info->old_password = info->password;
2073         info->password = nc->password;
2074
2075         secrets_debug_domain_info(DBGLVL_WARNING, info, "finish_change");
2076
2077         status = secrets_store_domain_info(info, false /* upgrade */);
2078         if (!NT_STATUS_IS_OK(status)) {
2079                 DBG_ERR("secrets_store_domain_info() failed "
2080                         "for %s - %s\n", domain, nt_errstr(status));
2081                 dbwrap_transaction_cancel(db);
2082                 TALLOC_FREE(frame);
2083                 return status;
2084         }
2085
2086         ret = dbwrap_transaction_commit(db);
2087         if (ret != 0) {
2088                 DBG_ERR("dbwrap_transaction_commit() failed for %s\n",
2089                         domain);
2090                 TALLOC_FREE(frame);
2091                 return NT_STATUS_INTERNAL_DB_ERROR;
2092         }
2093
2094         TALLOC_FREE(frame);
2095         return NT_STATUS_OK;
2096 }