ef90ab7342b7f05bb27313dcd085f73f3dcd023f
[samba.git] / source3 / passdb / pdb_samba_dsdb.c
1 /*
2    Unix SMB/CIFS implementation.
3    pdb glue module for direct access to the dsdb via LDB APIs
4    Copyright (C) Volker Lendecke 2009-2011
5    Copyright (C) Andrew Bartlett 2010-2012
6    Copyright (C) Matthias Dieter Wallnöfer                 2009
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 /* This module, is a port of Volker's pdb_ads to ldb and DSDB APIs */
23
24 #include "includes.h"
25 #include "source3/include/passdb.h"
26 #include "source4/dsdb/samdb/samdb.h"
27 #include "ldb_errors.h"
28 #include "libcli/security/dom_sid.h"
29 #include "source4/winbind/idmap.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "librpc/gen_ndr/ndr_drsblobs.h"
32 #include "librpc/gen_ndr/ndr_lsa.h"
33 #include "libds/common/flag_mapping.h"
34 #include "source4/lib/events/events.h"
35 #include "source4/auth/session.h"
36 #include "source4/auth/system_session_proto.h"
37 #include "lib/param/param.h"
38 #include "source4/dsdb/common/util.h"
39 #include "source3/include/secrets.h"
40 #include "source4/auth/auth_sam.h"
41 #include "auth/credentials/credentials.h"
42 #include "lib/util/base64.h"
43 #include "libcli/ldap/ldap_ndr.h"
44 #include "lib/util/util_ldb.h"
45
46 struct pdb_samba_dsdb_state {
47         struct tevent_context *ev;
48         struct ldb_context *ldb;
49         struct idmap_context *idmap_ctx;
50         struct loadparm_context *lp_ctx;
51 };
52
53 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
54                                     struct samu *sam_acct,
55                                     const struct dom_sid *sid);
56 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
57                                     const char *filter,
58                                     TALLOC_CTX *mem_ctx,
59                                     struct ldb_message **pmsg);
60 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
61                                  struct unixid *id);
62
63 static bool pdb_samba_dsdb_pull_time(struct ldb_message *msg, const char *attr,
64                               time_t *ptime)
65 {
66         uint64_t tmp;
67         if (! ldb_msg_find_element(msg, attr)) {
68                 return false;
69         }
70         tmp = ldb_msg_find_attr_as_uint64(msg, attr, 0);
71         *ptime = nt_time_to_unix(tmp);
72         return true;
73 }
74
75 static struct pdb_domain_info *pdb_samba_dsdb_get_domain_info(
76         struct pdb_methods *m, TALLOC_CTX *mem_ctx)
77 {
78         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
79                 m->private_data, struct pdb_samba_dsdb_state);
80         struct pdb_domain_info *info;
81         struct dom_sid *domain_sid;
82         struct ldb_dn *forest_dn, *domain_dn;
83         struct ldb_result *dom_res = NULL;
84         const char *dom_attrs[] = {
85                 "objectSid",
86                 "objectGUID",
87                 "fSMORoleOwner",
88                 NULL
89         };
90         char *p;
91         int ret;
92
93         info = talloc(mem_ctx, struct pdb_domain_info);
94         if (info == NULL) {
95                 return NULL;
96         }
97
98         domain_dn = ldb_get_default_basedn(state->ldb);
99
100         ret = ldb_search(state->ldb, info, &dom_res,
101                          domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
102         if (ret != LDB_SUCCESS) {
103                 goto fail;
104         }
105         if (dom_res->count != 1) {
106                 goto fail;
107         }
108
109         info->guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
110
111         domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
112         if (!domain_sid) {
113                 goto fail;
114         }
115         info->sid = *domain_sid;
116
117         TALLOC_FREE(dom_res);
118
119         info->name = talloc_strdup(info, lpcfg_sam_name(state->lp_ctx));
120         info->dns_domain = ldb_dn_canonical_string(info, domain_dn);
121
122         if (!info->dns_domain) {
123                 goto fail;
124         }
125         p = strchr(info->dns_domain, '/');
126         if (p) {
127                 *p = '\0';
128         }
129
130         forest_dn = ldb_get_root_basedn(state->ldb);
131         if (!forest_dn) {
132                 goto fail;
133         }
134
135         info->dns_forest = ldb_dn_canonical_string(info, forest_dn);
136         if (!info->dns_forest) {
137                 goto fail;
138         }
139         p = strchr(info->dns_forest, '/');
140         if (p) {
141                 *p = '\0';
142         }
143
144         return info;
145
146 fail:
147         TALLOC_FREE(dom_res);
148         TALLOC_FREE(info);
149         return NULL;
150 }
151
152 static struct ldb_message *pdb_samba_dsdb_get_samu_private(
153         struct pdb_methods *m, struct samu *sam)
154 {
155         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
156                 m->private_data, struct pdb_samba_dsdb_state);
157         struct ldb_message *msg;
158         struct dom_sid_buf sidstr;
159         char *filter;
160         NTSTATUS status;
161
162         msg = (struct ldb_message *)
163                 pdb_get_backend_private_data(sam, m);
164
165         if (msg != NULL) {
166                 return talloc_get_type_abort(msg, struct ldb_message);
167         }
168
169         filter = talloc_asprintf(
170                 talloc_tos(),
171                 "(&(objectsid=%s)(objectclass=user))",
172                 dom_sid_str_buf(pdb_get_user_sid(sam), &sidstr));
173         if (filter == NULL) {
174                 return NULL;
175         }
176
177         status = pdb_samba_dsdb_getsamupriv(state, filter, sam, &msg);
178         TALLOC_FREE(filter);
179         if (!NT_STATUS_IS_OK(status)) {
180                 return NULL;
181         }
182
183         return msg;
184 }
185
186 static NTSTATUS pdb_samba_dsdb_init_sam_from_priv(struct pdb_methods *m,
187                                            struct samu *sam,
188                                            struct ldb_message *msg)
189 {
190         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
191                 m->private_data, struct pdb_samba_dsdb_state);
192         TALLOC_CTX *frame = talloc_stackframe();
193         NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
194         const char *str;
195         time_t tmp_time;
196         struct dom_sid *sid, group_sid;
197         uint64_t n;
198         const DATA_BLOB *blob;
199
200         str = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
201         if (str == NULL) {
202                 DEBUG(10, ("no samAccountName\n"));
203                 goto fail;
204         }
205         pdb_set_username(sam, str, PDB_SET);
206
207         if (pdb_samba_dsdb_pull_time(msg, "lastLogon", &tmp_time)) {
208                 pdb_set_logon_time(sam, tmp_time, PDB_SET);
209         }
210         if (pdb_samba_dsdb_pull_time(msg, "lastLogoff", &tmp_time)) {
211                 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
212         }
213         if (pdb_samba_dsdb_pull_time(msg, "pwdLastSet", &tmp_time)) {
214                 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
215         }
216         if (pdb_samba_dsdb_pull_time(msg, "accountExpires", &tmp_time)) {
217                 pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
218         }
219
220         str = ldb_msg_find_attr_as_string(msg, "displayName",
221                                             NULL);
222         if (str != NULL) {
223                 pdb_set_fullname(sam, str, PDB_SET);
224         }
225
226         str = ldb_msg_find_attr_as_string(msg, "homeDirectory",
227                                             NULL);
228         if (str != NULL) {
229                 pdb_set_homedir(sam, str, PDB_SET);
230         }
231
232         str = ldb_msg_find_attr_as_string(msg, "homeDrive", NULL);
233         if (str != NULL) {
234                 pdb_set_dir_drive(sam, str, PDB_SET);
235         }
236
237         str = ldb_msg_find_attr_as_string(msg, "scriptPath", NULL);
238         if (str != NULL) {
239                 pdb_set_logon_script(sam, str, PDB_SET);
240         }
241
242         str = ldb_msg_find_attr_as_string(msg, "profilePath",
243                                             NULL);
244         if (str != NULL) {
245                 pdb_set_profile_path(sam, str, PDB_SET);
246         }
247
248         str = ldb_msg_find_attr_as_string(msg, "comment",
249                                             NULL);
250         if (str != NULL) {
251                 pdb_set_comment(sam, str, PDB_SET);
252         }
253
254         str = ldb_msg_find_attr_as_string(msg, "description",
255                                             NULL);
256         if (str != NULL) {
257                 pdb_set_acct_desc(sam, str, PDB_SET);
258         }
259
260         str = ldb_msg_find_attr_as_string(msg, "userWorkstations",
261                                             NULL);
262         if (str != NULL) {
263                 pdb_set_workstations(sam, str, PDB_SET);
264         }
265
266         blob = ldb_msg_find_ldb_val(msg, "userParameters");
267         if (blob != NULL) {
268                 str = base64_encode_data_blob(frame, *blob);
269                 if (str == NULL) {
270                         DEBUG(0, ("base64_encode_data_blob() failed\n"));
271                         goto fail;
272                 }
273                 pdb_set_munged_dial(sam, str, PDB_SET);
274         }
275
276         sid = samdb_result_dom_sid(talloc_tos(), msg, "objectSid");
277         if (!sid) {
278                 DEBUG(10, ("Could not pull SID\n"));
279                 goto fail;
280         }
281         pdb_set_user_sid(sam, sid, PDB_SET);
282
283         n = samdb_result_acct_flags(msg, "msDS-User-Account-Control-Computed");
284         if (n == 0) {
285                 DEBUG(10, ("Could not pull userAccountControl\n"));
286                 goto fail;
287         }
288         pdb_set_acct_ctrl(sam, n, PDB_SET);
289
290         blob = ldb_msg_find_ldb_val(msg, "unicodePwd");
291         if (blob) {
292                 if (blob->length != NT_HASH_LEN) {
293                         DEBUG(0, ("Got NT hash of length %d, expected %d\n",
294                                   (int)blob->length, NT_HASH_LEN));
295                         goto fail;
296                 }
297                 pdb_set_nt_passwd(sam, blob->data, PDB_SET);
298         }
299
300         blob = ldb_msg_find_ldb_val(msg, "dBCSPwd");
301         if (blob) {
302                 if (blob->length != LM_HASH_LEN) {
303                         DEBUG(0, ("Got LM hash of length %d, expected %d\n",
304                                   (int)blob->length, LM_HASH_LEN));
305                         goto fail;
306                 }
307                 pdb_set_lanman_passwd(sam, blob->data, PDB_SET);
308         }
309
310         n = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", 0);
311         if (n == 0) {
312                 DEBUG(10, ("Could not pull primaryGroupID\n"));
313                 goto fail;
314         }
315         sid_compose(&group_sid, samdb_domain_sid(state->ldb), n);
316         pdb_set_group_sid(sam, &group_sid, PDB_SET);
317
318         status = NT_STATUS_OK;
319 fail:
320         TALLOC_FREE(frame);
321         return status;
322 }
323
324 static bool pdb_samba_dsdb_add_time(struct ldb_message *msg,
325                                 const char *attrib, time_t t)
326 {
327         uint64_t nt_time;
328
329         unix_to_nt_time(&nt_time, t);
330
331         return ldb_msg_add_fmt(msg, attrib, "%llu", (unsigned long long) nt_time);
332 }
333
334 static int pdb_samba_dsdb_replace_by_sam(struct pdb_samba_dsdb_state *state,
335                                      bool (*need_update)(const struct samu *,
336                                                          enum pdb_elements),
337                                      struct ldb_dn *dn,
338                                      struct samu *sam)
339 {
340         TALLOC_CTX *frame = talloc_stackframe();
341         int ret = LDB_SUCCESS;
342         const char *pw;
343         struct ldb_message *msg;
344         struct ldb_request *req;
345         uint32_t dsdb_flags = 0;
346         /* TODO: All fields :-) */
347
348         msg = ldb_msg_new(frame);
349         if (!msg) {
350                 talloc_free(frame);
351                 return false;
352         }
353
354         msg->dn = dn;
355
356         /* build modify request */
357         ret = ldb_build_mod_req(&req, state->ldb, frame, msg, NULL, NULL,
358                                 ldb_op_default_callback,
359                                 NULL);
360         if (ret != LDB_SUCCESS) {
361                 talloc_free(frame);
362                 return ret;
363         }
364
365         /* If we set a plaintext password, the system will
366          * force the pwdLastSet to now() */
367         if (need_update(sam, PDB_PASSLASTSET)) {
368                 dsdb_flags |= DSDB_PASSWORD_BYPASS_LAST_SET;
369
370                 ret |= pdb_samba_dsdb_add_time(msg, "pwdLastSet",
371                                            pdb_get_pass_last_set_time(sam));
372         }
373
374         pw = pdb_get_plaintext_passwd(sam);
375         if (need_update(sam, PDB_PLAINTEXT_PW)) {
376                 struct ldb_val pw_utf16;
377                 if (pw == NULL) {
378                         talloc_free(frame);
379                         return LDB_ERR_OPERATIONS_ERROR;
380                 }
381
382                 if (!convert_string_talloc(msg,
383                                            CH_UNIX, CH_UTF16,
384                                            pw, strlen(pw),
385                                            (void *)&pw_utf16.data,
386                                            &pw_utf16.length)) {
387                         talloc_free(frame);
388                         return LDB_ERR_OPERATIONS_ERROR;
389                 }
390                 ret |= ldb_msg_add_value(msg, "clearTextPassword", &pw_utf16, NULL);
391         } else {
392                 bool changed_lm_pw = false;
393                 bool changed_nt_pw = false;
394                 bool changed_history = false;
395                 if (need_update(sam, PDB_LMPASSWD)) {
396                         struct ldb_val val;
397                         val.data = discard_const_p(uint8_t, pdb_get_lanman_passwd(sam));
398                         if (!val.data) {
399                                 samdb_msg_add_delete(state->ldb, msg, msg,
400                                                      "dBCSPwd");
401                         } else {
402                                 val.length = LM_HASH_LEN;
403                                 ret |= ldb_msg_add_value(msg, "dBCSPwd", &val, NULL);
404                         }
405                         changed_lm_pw = true;
406                 }
407                 if (need_update(sam, PDB_NTPASSWD)) {
408                         struct ldb_val val;
409                         val.data = discard_const_p(uint8_t, pdb_get_nt_passwd(sam));
410                         if (!val.data) {
411                                 samdb_msg_add_delete(state->ldb, msg, msg,
412                                                      "unicodePwd");
413                         } else {
414                                 val.length = NT_HASH_LEN;
415                                 ret |= ldb_msg_add_value(msg, "unicodePwd", &val, NULL);
416                         }
417                         changed_nt_pw = true;
418                 }
419
420                 /* Try to ensure we don't get out of sync */
421                 if (changed_lm_pw && !changed_nt_pw) {
422                         samdb_msg_add_delete(state->ldb, msg, msg,
423                                              "unicodePwd");
424                 } else if (changed_nt_pw && !changed_lm_pw) {
425                         samdb_msg_add_delete(state->ldb, msg, msg,
426                                              "dBCSPwd");
427                 }
428                 if (changed_lm_pw || changed_nt_pw) {
429                         samdb_msg_add_delete(state->ldb, msg, msg,
430                                              "supplementalCredentials");
431
432                 }
433
434                 if (need_update(sam, PDB_PWHISTORY)) {
435                         uint32_t current_hist_len;
436                         const uint8_t *history = pdb_get_pw_history(sam, &current_hist_len);
437
438                         bool invalid_history = false;
439                         struct samr_Password *history_hashes = talloc_array(talloc_tos(), struct samr_Password,
440                                                                             current_hist_len);
441                         if (!history) {
442                                 invalid_history = true;
443                         } else {
444                                 unsigned int i;
445                                 /* Parse the history into the correct format */
446                                 for (i = 0; i < current_hist_len; i++) {
447                                         if (!all_zero(&history[i*PW_HISTORY_ENTRY_LEN],
448                                                       16)) {
449                                                 /* If the history is in the old format, with a salted hash, then we can't migrate it to AD format */
450                                                 invalid_history = true;
451                                                 break;
452                                         }
453                                         /* Copy out the 2nd 16 bytes of the 32 byte password history, containing the NT hash */
454                                         memcpy(history_hashes[i].hash,
455                                                &history[(i*PW_HISTORY_ENTRY_LEN) + PW_HISTORY_SALT_LEN],
456                                                sizeof(history_hashes[i].hash));
457                                 }
458                         }
459                         if (invalid_history) {
460                                 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
461                                                      "ntPwdHistory");
462
463                                 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
464                                                      "lmPwdHistory");
465                         } else {
466                                 ret |= samdb_msg_add_hashes(state->ldb, msg, msg,
467                                                             "ntPwdHistory",
468                                                             history_hashes,
469                                                             current_hist_len);
470                         }
471                         changed_history = true;
472                 }
473                 if (changed_lm_pw || changed_nt_pw || changed_history) {
474                         /* These attributes can only be modified directly by using a special control */
475                         dsdb_flags |= DSDB_BYPASS_PASSWORD_HASH;
476                 }
477         }
478
479         /* PDB_USERSID is only allowed on ADD, handled in caller */
480         if (need_update(sam, PDB_GROUPSID)) {
481                 const struct dom_sid *sid = pdb_get_group_sid(sam);
482                 uint32_t rid;
483                 NTSTATUS status = dom_sid_split_rid(NULL, sid, NULL, &rid);
484                 if (!NT_STATUS_IS_OK(status)) {
485                         talloc_free(frame);
486                         return LDB_ERR_OPERATIONS_ERROR;
487                 }
488                 if (!dom_sid_in_domain(samdb_domain_sid(state->ldb), sid)) {
489                         talloc_free(frame);
490                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
491                 }
492                 ret |= samdb_msg_add_uint(state->ldb, msg, msg, "primaryGroupID", rid);
493         }
494         if (need_update(sam, PDB_FULLNAME)) {
495                 ret |= ldb_msg_add_string(msg, "displayName", pdb_get_fullname(sam));
496         }
497
498         if (need_update(sam, PDB_SMBHOME)) {
499                 ret |= ldb_msg_add_string(msg, "homeDirectory",
500                                           pdb_get_homedir(sam));
501         }
502
503         if (need_update(sam, PDB_PROFILE)) {
504                 ret |= ldb_msg_add_string(msg, "profilePath",
505                                           pdb_get_profile_path(sam));
506         }
507
508         if (need_update(sam, PDB_DRIVE)) {
509                 ret |= ldb_msg_add_string(msg, "homeDrive",
510                                           pdb_get_dir_drive(sam));
511         }
512
513         if (need_update(sam, PDB_LOGONSCRIPT)) {
514                 ret |= ldb_msg_add_string(msg, "scriptPath",
515                                           pdb_get_logon_script(sam));
516         }
517
518         if (need_update(sam, PDB_KICKOFFTIME)) {
519                 ret |= pdb_samba_dsdb_add_time(msg, "accountExpires",
520                                         pdb_get_kickoff_time(sam));
521         }
522
523         if (need_update(sam, PDB_LOGONTIME)) {
524                 ret |= pdb_samba_dsdb_add_time(msg, "lastLogon",
525                                         pdb_get_logon_time(sam));
526         }
527
528         if (need_update(sam, PDB_LOGOFFTIME)) {
529                 ret |= pdb_samba_dsdb_add_time(msg, "lastLogoff",
530                                         pdb_get_logoff_time(sam));
531         }
532
533         if (need_update(sam, PDB_USERNAME)) {
534                 ret |= ldb_msg_add_string(msg, "samAccountName",
535                                           pdb_get_username(sam));
536         }
537
538         if (need_update(sam, PDB_HOURSLEN) || need_update(sam, PDB_HOURS)) {
539                 struct ldb_val hours = data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam));
540                 ret |= ldb_msg_add_value(msg, "logonHours",
541                                          &hours, NULL);
542         }
543
544         if (need_update(sam, PDB_ACCTCTRL)) {
545                 ret |= samdb_msg_add_acct_flags(state->ldb, msg, msg,
546                                                 "userAccountControl", pdb_get_acct_ctrl(sam));
547         }
548
549         if (need_update(sam, PDB_COMMENT)) {
550                 ret |= ldb_msg_add_string(msg, "comment",
551                                           pdb_get_comment(sam));
552         }
553
554         if (need_update(sam, PDB_ACCTDESC)) {
555                 ret |= ldb_msg_add_string(msg, "description",
556                                           pdb_get_acct_desc(sam));
557         }
558
559         if (need_update(sam, PDB_WORKSTATIONS)) {
560                 ret |= ldb_msg_add_string(msg, "userWorkstations",
561                                           pdb_get_workstations(sam));
562         }
563
564         /* This will need work, it is actually a UTF8 'string' with internal NULLs, to handle TS parameters */
565         if (need_update(sam, PDB_MUNGEDDIAL)) {
566                 const char *base64_munged_dial = NULL;
567
568                 base64_munged_dial = pdb_get_munged_dial(sam);
569                 if (base64_munged_dial != NULL && strlen(base64_munged_dial) > 0) {
570                         struct ldb_val blob;
571
572                         blob = base64_decode_data_blob_talloc(msg,
573                                                         base64_munged_dial);
574                         if (blob.data == NULL) {
575                                 DEBUG(0, ("Failed to decode userParameters from "
576                                           "munged dialback string[%s] for %s\n",
577                                           base64_munged_dial,
578                                           ldb_dn_get_linearized(msg->dn)));
579                                 talloc_free(frame);
580                                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
581                         }
582                         ret |= ldb_msg_add_steal_value(msg, "userParameters",
583                                                        &blob);
584                 }
585         }
586
587         if (need_update(sam, PDB_COUNTRY_CODE)) {
588                 ret |= ldb_msg_add_fmt(msg, "countryCode",
589                                        "%i", (int)pdb_get_country_code(sam));
590         }
591
592         if (need_update(sam, PDB_CODE_PAGE)) {
593                 ret |= ldb_msg_add_fmt(msg, "codePage",
594                                        "%i", (int)pdb_get_code_page(sam));
595         }
596
597         /* Not yet handled here or not meaningful for modifies on a Samba_Dsdb backend:
598         PDB_BAD_PASSWORD_TIME,
599         PDB_CANCHANGETIME, - these are calculated per policy, not stored
600         PDB_DOMAIN,
601         PDB_NTUSERNAME, - this makes no sense, and never really did
602         PDB_LOGONDIVS,
603         PDB_USERSID, - Handled in pdb_samba_dsdb_add_sam_account()
604         PDB_FIELDS_PRESENT,
605         PDB_BAD_PASSWORD_COUNT,
606         PDB_LOGON_COUNT,
607         PDB_UNKNOWN6,
608         PDB_BACKEND_PRIVATE_DATA,
609
610  */
611         if (ret != LDB_SUCCESS) {
612                 talloc_free(frame);
613                 return LDB_ERR_OPERATIONS_ERROR;
614         }
615
616         if (msg->num_elements == 0) {
617                 talloc_free(frame);
618                 /* Nothing to do, just return success */
619                 return LDB_SUCCESS;
620         }
621
622         ret = dsdb_replace(state->ldb, msg, dsdb_flags);
623
624         if (ret != LDB_SUCCESS) {
625                 DEBUG(0,("Failed to modify account record %s to set user attributes: %s\n",
626                          ldb_dn_get_linearized(msg->dn),
627                          ldb_errstring(state->ldb)));
628         }
629
630         talloc_free(frame);
631         return ret;
632 }
633
634 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
635                                     const char *filter,
636                                     TALLOC_CTX *mem_ctx,
637                                     struct ldb_message **msg)
638 {
639         const char * attrs[] = {
640                 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
641                 "sAMAccountName", "displayName", "homeDirectory",
642                 "homeDrive", "scriptPath", "profilePath", "description",
643                 "userWorkstations", "comment", "userParameters", "objectSid",
644                 "primaryGroupID", "userAccountControl",
645                 "msDS-User-Account-Control-Computed", "logonHours",
646                 "badPwdCount", "logonCount", "countryCode", "codePage",
647                 "unicodePwd", "dBCSPwd", NULL };
648
649         int rc = dsdb_search_one(state->ldb, mem_ctx, msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter);
650         if (rc != LDB_SUCCESS) {
651                 DEBUG(10, ("ldap_search failed %s\n",
652                            ldb_errstring(state->ldb)));
653                 return NT_STATUS_LDAP(rc);
654         }
655
656         return NT_STATUS_OK;
657 }
658
659 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
660                                           struct pdb_samba_dsdb_state *state,
661                                           struct samu *sam_acct,
662                                           const char *exp_fmt, ...)
663                                           PRINTF_ATTRIBUTE(4,5);
664
665 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
666                                           struct pdb_samba_dsdb_state *state,
667                                           struct samu *sam_acct,
668                                           const char *exp_fmt, ...)
669 {
670         struct ldb_message *priv;
671         NTSTATUS status;
672         va_list ap;
673         char *expression = NULL;
674         TALLOC_CTX *tmp_ctx = talloc_new(state);
675         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
676
677         va_start(ap, exp_fmt);
678         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
679         va_end(ap);
680
681         if (!expression) {
682                 talloc_free(tmp_ctx);
683                 return NT_STATUS_NO_MEMORY;
684         }
685
686         status = pdb_samba_dsdb_getsamupriv(state, expression, sam_acct, &priv);
687         talloc_free(tmp_ctx);
688         if (!NT_STATUS_IS_OK(status)) {
689                 DEBUG(10, ("pdb_samba_dsdb_getsamupriv failed: %s\n",
690                            nt_errstr(status)));
691                 return status;
692         }
693
694         status = pdb_samba_dsdb_init_sam_from_priv(m, sam_acct, priv);
695         if (!NT_STATUS_IS_OK(status)) {
696                 DEBUG(10, ("pdb_samba_dsdb_init_sam_from_priv failed: %s\n",
697                            nt_errstr(status)));
698                 TALLOC_FREE(priv);
699                 return status;
700         }
701
702         pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
703         return NT_STATUS_OK;
704 }
705
706 static NTSTATUS pdb_samba_dsdb_getsampwnam(struct pdb_methods *m,
707                                     struct samu *sam_acct,
708                                     const char *username)
709 {
710         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
711                 m->private_data, struct pdb_samba_dsdb_state);
712
713         return pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
714                                          "(&(samaccountname=%s)(objectclass=user))",
715                                          username);
716 }
717
718 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
719                                     struct samu *sam_acct,
720                                     const struct dom_sid *sid)
721 {
722         NTSTATUS status;
723         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
724                 m->private_data, struct pdb_samba_dsdb_state);
725         struct dom_sid_buf buf;
726
727         status = pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
728                                            "(&(objectsid=%s)(objectclass=user))",
729                                            dom_sid_str_buf(sid, &buf));
730         return status;
731 }
732
733 static NTSTATUS pdb_samba_dsdb_create_user(struct pdb_methods *m,
734                                     TALLOC_CTX *mem_ctx,
735                                     const char *name, uint32_t acct_flags,
736                                     uint32_t *rid)
737 {
738         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
739                 m->private_data, struct pdb_samba_dsdb_state);
740         struct dom_sid *sid;
741         struct ldb_dn *dn;
742         NTSTATUS status;
743         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
744         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
745
746         /* Internally this uses transactions to ensure all the steps
747          * happen or fail as one */
748         status = dsdb_add_user(state->ldb, tmp_ctx, name, acct_flags, NULL,
749                                &sid, &dn);
750         if (!NT_STATUS_IS_OK(status)) {
751                 talloc_free(tmp_ctx);
752                 return status;
753         }
754         sid_peek_rid(sid, rid);
755         talloc_free(tmp_ctx);
756         return NT_STATUS_OK;
757 }
758
759 static NTSTATUS pdb_samba_dsdb_delete_user(struct pdb_methods *m,
760                                        TALLOC_CTX *mem_ctx,
761                                        struct samu *sam)
762 {
763         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
764                 m->private_data, struct pdb_samba_dsdb_state);
765         struct ldb_dn *dn;
766         int rc;
767         struct dom_sid_buf buf;
768         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
769         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
770
771         dn = ldb_dn_new_fmt(
772                 tmp_ctx,
773                 state->ldb,
774                 "<SID=%s>",
775                 dom_sid_str_buf(pdb_get_user_sid(sam), &buf));
776         if (!dn || !ldb_dn_validate(dn)) {
777                 talloc_free(tmp_ctx);
778                 return NT_STATUS_NO_MEMORY;
779         }
780         rc = ldb_delete(state->ldb, dn);
781
782         if (rc != LDB_SUCCESS) {
783                 DEBUG(10, ("ldb_delete for %s failed: %s\n", ldb_dn_get_linearized(dn),
784                            ldb_errstring(state->ldb)));
785                 talloc_free(tmp_ctx);
786                 return NT_STATUS_LDAP(rc);
787         }
788         talloc_free(tmp_ctx);
789         return NT_STATUS_OK;
790 }
791
792 /* This interface takes a fully populated struct samu and places it in
793  * the database.  This is not implemented at this time as we need to
794  * be careful around the creation of arbitrary SIDs (ie, we must ensure
795  * they are not left in a RID pool */
796 static NTSTATUS pdb_samba_dsdb_add_sam_account(struct pdb_methods *m,
797                                         struct samu *sampass)
798 {
799         int ret;
800         NTSTATUS status;
801         struct ldb_dn *dn;
802         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
803                 m->private_data, struct pdb_samba_dsdb_state);
804         uint32_t acb_flags = pdb_get_acct_ctrl(sampass);
805         const char *username = pdb_get_username(sampass);
806         const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
807         TALLOC_CTX *tframe = talloc_stackframe();
808
809         acb_flags &= (ACB_NORMAL|ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST);
810
811         ret = ldb_transaction_start(state->ldb);
812         if (ret != LDB_SUCCESS) {
813                 talloc_free(tframe);
814                 return NT_STATUS_LOCK_NOT_GRANTED;
815         }
816
817         status = dsdb_add_user(state->ldb, talloc_tos(), username,
818                                acb_flags, user_sid, NULL, &dn);
819         if (!NT_STATUS_IS_OK(status)) {
820                 ldb_transaction_cancel(state->ldb);
821                 talloc_free(tframe);
822                 return status;
823         }
824
825         ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_set_or_changed,
826                                         dn, sampass);
827         if (ret != LDB_SUCCESS) {
828                 ldb_transaction_cancel(state->ldb);
829                 talloc_free(tframe);
830                 return dsdb_ldb_err_to_ntstatus(ret);
831         }
832
833         ret = ldb_transaction_commit(state->ldb);
834         if (ret != LDB_SUCCESS) {
835                 DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
836                          ldb_dn_get_linearized(dn),
837                          ldb_errstring(state->ldb)));
838                 talloc_free(tframe);
839                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
840         }
841         talloc_free(tframe);
842         return NT_STATUS_OK;
843 }
844
845 /*
846  * Update the Samba_Dsdb LDB with the changes from a struct samu.
847  *
848  * This takes care not to update elements that have not been changed
849  * by the caller
850  */
851 static NTSTATUS pdb_samba_dsdb_update_sam_account(struct pdb_methods *m,
852                                            struct samu *sam)
853 {
854         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
855                 m->private_data, struct pdb_samba_dsdb_state);
856         struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
857                 m, sam);
858         int ret;
859
860         ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_changed, msg->dn,
861                                         sam);
862         return dsdb_ldb_err_to_ntstatus(ret);
863 }
864
865 static NTSTATUS pdb_samba_dsdb_delete_sam_account(struct pdb_methods *m,
866                                            struct samu *username)
867 {
868         NTSTATUS status;
869         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
870         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
871         status = pdb_samba_dsdb_delete_user(m, tmp_ctx, username);
872         talloc_free(tmp_ctx);
873         return status;
874 }
875
876 static NTSTATUS pdb_samba_dsdb_rename_sam_account(struct pdb_methods *m,
877                                            struct samu *oldname,
878                                            const char *newname)
879 {
880         return NT_STATUS_NOT_IMPLEMENTED;
881 }
882
883 /* This is not implemented, as this module is expected to be used
884  * with auth_samba_dsdb, and this is responsible for login counters etc
885  *
886  */
887 static NTSTATUS pdb_samba_dsdb_update_login_attempts(struct pdb_methods *m,
888                                               struct samu *sam_acct,
889                                               bool success)
890 {
891         return NT_STATUS_NOT_IMPLEMENTED;
892 }
893
894 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m,
895                                            GROUP_MAP *map,
896                                            const char *exp_fmt, ...)
897                                            PRINTF_ATTRIBUTE(3,4);
898
899 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
900                                     const char *exp_fmt, ...)
901 {
902         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
903                 m->private_data, struct pdb_samba_dsdb_state);
904         const char *attrs[] = { "objectClass", "objectSid", "description", "samAccountName", "groupType",
905                                 NULL };
906         struct ldb_message *msg;
907         va_list ap;
908         char *expression = NULL;
909         struct dom_sid *sid;
910         const char *str;
911         int rc;
912         struct id_map id_map;
913         struct id_map *id_maps[2];
914         TALLOC_CTX *tmp_ctx = talloc_stackframe();
915         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
916
917         va_start(ap, exp_fmt);
918         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
919         va_end(ap);
920
921         if (!expression) {
922                 talloc_free(tmp_ctx);
923                 return NT_STATUS_NO_MEMORY;
924         }
925
926         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
927         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
928                 talloc_free(tmp_ctx);
929                 return NT_STATUS_NO_SUCH_GROUP;
930         } else if (rc != LDB_SUCCESS) {
931                 talloc_free(tmp_ctx);
932                 DEBUG(10, ("dsdb_search_one failed %s\n",
933                            ldb_errstring(state->ldb)));
934                 return NT_STATUS_LDAP(rc);
935         }
936
937         sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
938         if (!sid) {
939                 talloc_free(tmp_ctx);
940                 DEBUG(10, ("Could not pull SID\n"));
941                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
942         }
943
944         map->sid = *sid;
945
946         if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) {
947                 NTSTATUS status;
948                 uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0);
949                 switch (grouptype) {
950                 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
951                 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
952                         map->sid_name_use = SID_NAME_ALIAS;
953                         break;
954                 case GTYPE_SECURITY_GLOBAL_GROUP:
955                         map->sid_name_use = SID_NAME_DOM_GRP;
956                         break;
957                 default:
958                         talloc_free(tmp_ctx);
959                         DEBUG(10, ("Could not pull groupType\n"));
960                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
961                 }
962
963                 ZERO_STRUCT(id_map);
964                 id_map.sid = sid;
965                 id_maps[0] = &id_map;
966                 id_maps[1] = NULL;
967
968                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
969
970                 if (!NT_STATUS_IS_OK(status)) {
971                         talloc_free(tmp_ctx);
972                         return status;
973                 }
974                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
975                         map->gid = id_map.xid.id;
976                 } else {
977                         DEBUG(1, (__location__ "Did not get GUID when mapping SID for %s\n", expression));
978                         talloc_free(tmp_ctx);
979                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
980                 }
981         } else if (samdb_find_attribute(state->ldb, msg, "objectClass", "user")) {
982                 DEBUG(1, (__location__ "Got SID_NAME_USER when searching for a group with %s\n", expression));
983                 talloc_free(tmp_ctx);
984                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
985         }
986
987         str = ldb_msg_find_attr_as_string(msg, "samAccountName",
988                                           NULL);
989         if (str == NULL) {
990                 talloc_free(tmp_ctx);
991                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
992         }
993         map->nt_name = talloc_strdup(map, str);
994         if (!map->nt_name) {
995                 talloc_free(tmp_ctx);
996                 return NT_STATUS_NO_MEMORY;
997         }
998
999         str = ldb_msg_find_attr_as_string(msg, "description",
1000                                             NULL);
1001         if (str != NULL) {
1002                 map->comment = talloc_strdup(map, str);
1003         } else {
1004                 map->comment = talloc_strdup(map, "");
1005         }
1006         if (!map->comment) {
1007                 talloc_free(tmp_ctx);
1008                 return NT_STATUS_NO_MEMORY;
1009         }
1010
1011         talloc_free(tmp_ctx);
1012         return NT_STATUS_OK;
1013 }
1014
1015 static NTSTATUS pdb_samba_dsdb_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
1016                                  struct dom_sid sid)
1017 {
1018         char *filter;
1019         NTSTATUS status;
1020         struct dom_sid_buf buf;
1021
1022         filter = talloc_asprintf(talloc_tos(),
1023                                  "(&(objectsid=%s)(objectclass=group))",
1024                                  dom_sid_str_buf(&sid, &buf));
1025         if (filter == NULL) {
1026                 return NT_STATUS_NO_MEMORY;
1027         }
1028
1029         status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
1030         TALLOC_FREE(filter);
1031         return status;
1032 }
1033
1034 static NTSTATUS pdb_samba_dsdb_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
1035                                  gid_t gid)
1036 {
1037         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1038                 m->private_data, struct pdb_samba_dsdb_state);
1039         NTSTATUS status;
1040         struct id_map id_map;
1041         struct id_map *id_maps[2];
1042         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1043         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1044
1045         id_map.xid.id = gid;
1046         id_map.xid.type = ID_TYPE_GID;
1047         id_maps[0] = &id_map;
1048         id_maps[1] = NULL;
1049
1050         status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
1051         if (!NT_STATUS_IS_OK(status)) {
1052                 talloc_free(tmp_ctx);
1053                 return status;
1054         }
1055         status = pdb_samba_dsdb_getgrsid(m, map, *id_map.sid);
1056         talloc_free(tmp_ctx);
1057         return status;
1058 }
1059
1060 static NTSTATUS pdb_samba_dsdb_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
1061                                  const char *name)
1062 {
1063         char *filter;
1064         NTSTATUS status;
1065
1066         filter = talloc_asprintf(talloc_tos(),
1067                                  "(&(samaccountname=%s)(objectclass=group))",
1068                                  name);
1069         if (filter == NULL) {
1070                 return NT_STATUS_NO_MEMORY;
1071         }
1072
1073         status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
1074         TALLOC_FREE(filter);
1075         return status;
1076 }
1077
1078 static NTSTATUS pdb_samba_dsdb_create_dom_group(struct pdb_methods *m,
1079                                          TALLOC_CTX *mem_ctx, const char *name,
1080                                          uint32_t *rid)
1081 {
1082         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1083                 m->private_data, struct pdb_samba_dsdb_state);
1084         NTSTATUS status;
1085         struct dom_sid *sid;
1086         struct ldb_dn *dn;
1087         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1088         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1089
1090         status = dsdb_add_domain_group(state->ldb, tmp_ctx, name, &sid, &dn);
1091         if (!NT_STATUS_IS_OK(status)) {
1092                 talloc_free(tmp_ctx);
1093                 return status;
1094         }
1095
1096         sid_peek_rid(sid, rid);
1097         talloc_free(tmp_ctx);
1098         return NT_STATUS_OK;
1099 }
1100
1101 static NTSTATUS pdb_samba_dsdb_delete_dom_group(struct pdb_methods *m,
1102                                          TALLOC_CTX *mem_ctx, uint32_t rid)
1103 {
1104         const char *attrs[] = { NULL };
1105         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1106                 m->private_data, struct pdb_samba_dsdb_state);
1107         struct dom_sid sid;
1108         struct ldb_message *msg;
1109         struct ldb_dn *dn;
1110         int rc;
1111         struct dom_sid_buf buf;
1112         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1113         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1114
1115         sid_compose(&sid, samdb_domain_sid(state->ldb), rid);
1116
1117         if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1118                 DEBUG(0, ("Unable to start transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1119                 return NT_STATUS_INTERNAL_ERROR;
1120         }
1121
1122         dn = ldb_dn_new_fmt(
1123                 tmp_ctx,
1124                 state->ldb,
1125                 "<SID=%s>",
1126                 dom_sid_str_buf(&sid, &buf));
1127         if (!dn || !ldb_dn_validate(dn)) {
1128                 talloc_free(tmp_ctx);
1129                 ldb_transaction_cancel(state->ldb);
1130                 return NT_STATUS_NO_MEMORY;
1131         }
1132         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "objectclass=group");
1133         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1134                 talloc_free(tmp_ctx);
1135                 ldb_transaction_cancel(state->ldb);
1136                 return NT_STATUS_NO_SUCH_GROUP;
1137         } else if (rc != LDB_SUCCESS) {
1138                 talloc_free(tmp_ctx);
1139                 DEBUG(10, ("dsdb_search_one failed %s\n",
1140                            ldb_errstring(state->ldb)));
1141                 ldb_transaction_cancel(state->ldb);
1142                 return NT_STATUS_LDAP(rc);
1143         }
1144         rc = ldb_delete(state->ldb, dn);
1145         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1146                 talloc_free(tmp_ctx);
1147                 ldb_transaction_cancel(state->ldb);
1148                 return NT_STATUS_NO_SUCH_GROUP;
1149         } else if (rc != LDB_SUCCESS) {
1150                 DEBUG(10, ("ldb_delete failed %s\n",
1151                            ldb_errstring(state->ldb)));
1152                 ldb_transaction_cancel(state->ldb);
1153                 return NT_STATUS_LDAP(rc);
1154         }
1155
1156         if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1157                 DEBUG(0, ("Unable to commit transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1158                 return NT_STATUS_INTERNAL_ERROR;
1159         }
1160         return NT_STATUS_OK;
1161 }
1162
1163 static NTSTATUS pdb_samba_dsdb_add_group_mapping_entry(struct pdb_methods *m,
1164                                                 GROUP_MAP *map)
1165 {
1166         return NT_STATUS_NOT_IMPLEMENTED;
1167 }
1168
1169 static NTSTATUS pdb_samba_dsdb_update_group_mapping_entry(struct pdb_methods *m,
1170                                                    GROUP_MAP *map)
1171 {
1172         return NT_STATUS_NOT_IMPLEMENTED;
1173 }
1174
1175 static NTSTATUS pdb_samba_dsdb_delete_group_mapping_entry(struct pdb_methods *m,
1176                                                    struct dom_sid sid)
1177 {
1178         return NT_STATUS_NOT_IMPLEMENTED;
1179 }
1180
1181 static NTSTATUS pdb_samba_dsdb_enum_group_mapping(struct pdb_methods *m,
1182                                            const struct dom_sid *sid,
1183                                            enum lsa_SidType sid_name_use,
1184                                            GROUP_MAP ***pp_rmap,
1185                                            size_t *p_num_entries,
1186                                            bool unix_only)
1187 {
1188         return NT_STATUS_NOT_IMPLEMENTED;
1189 }
1190
1191 static NTSTATUS pdb_samba_dsdb_enum_group_members(struct pdb_methods *m,
1192                                            TALLOC_CTX *mem_ctx,
1193                                            const struct dom_sid *group,
1194                                            uint32_t **pmembers,
1195                                            size_t *pnum_members)
1196 {
1197         unsigned int i, num_sids, num_members;
1198         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1199                 m->private_data, struct pdb_samba_dsdb_state);
1200         struct dom_sid *members_as_sids;
1201         struct dom_sid *dom_sid;
1202         uint32_t *members;
1203         struct ldb_dn *dn;
1204         NTSTATUS status;
1205         struct dom_sid_buf buf;
1206
1207         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1208         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1209
1210         dn = ldb_dn_new_fmt(
1211                 tmp_ctx,
1212                 state->ldb,
1213                 "<SID=%s>",
1214                 dom_sid_str_buf(group, &buf));
1215         if (!dn || !ldb_dn_validate(dn)) {
1216                 return NT_STATUS_NO_MEMORY;
1217         }
1218
1219         status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
1220         if (!NT_STATUS_IS_OK(status)) {
1221                 talloc_free(tmp_ctx);
1222                 return status;
1223         }
1224         status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
1225         if (!NT_STATUS_IS_OK(status)) {
1226                 talloc_free(tmp_ctx);
1227                 return status;
1228         }
1229
1230         *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
1231         if (*pmembers == NULL) {
1232                 TALLOC_FREE(tmp_ctx);
1233                 return NT_STATUS_NO_MEMORY;
1234         }
1235         num_members = 0;
1236
1237         for (i = 0; i < num_sids; i++) {
1238                 if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
1239                         continue;
1240                 }
1241                 status = dom_sid_split_rid(NULL, &members_as_sids[i],
1242                                            NULL, &members[num_members]);
1243                 if (!NT_STATUS_IS_OK(status)) {
1244                         talloc_free(tmp_ctx);
1245                         return status;
1246                 }
1247                 num_members++;
1248         }
1249         *pnum_members = num_members;
1250         return NT_STATUS_OK;
1251 }
1252
1253 /* Just convert the primary group SID into a group */
1254 static NTSTATUS fake_enum_group_memberships(struct pdb_samba_dsdb_state *state,
1255                                             TALLOC_CTX *mem_ctx,
1256                                             struct samu *user,
1257                                             struct dom_sid **pp_sids,
1258                                             gid_t **pp_gids,
1259                                             uint32_t *p_num_groups)
1260 {
1261         NTSTATUS status;
1262         size_t num_groups = 0;
1263         struct dom_sid *group_sids = NULL;
1264         gid_t *gids = NULL;
1265         TALLOC_CTX *tmp_ctx;
1266
1267         tmp_ctx = talloc_new(mem_ctx);
1268         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1269
1270         if (user->group_sid) {
1271                 struct id_map *id_maps[2];
1272                 struct id_map id_map;
1273
1274                 num_groups = 1;
1275
1276                 group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
1277                 if (group_sids == NULL) {
1278                         talloc_free(tmp_ctx);
1279                         return NT_STATUS_NO_MEMORY;
1280                 }
1281                 gids = talloc_array(tmp_ctx, gid_t, num_groups);
1282                 if (gids == NULL) {
1283                         talloc_free(tmp_ctx);
1284                         return NT_STATUS_NO_MEMORY;
1285                 }
1286
1287                 group_sids[0] = *user->group_sid;
1288
1289                 ZERO_STRUCT(id_map);
1290                 id_map.sid = &group_sids[0];
1291                 id_maps[0] = &id_map;
1292                 id_maps[1] = NULL;
1293
1294                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1295                 if (!NT_STATUS_IS_OK(status)) {
1296                         talloc_free(tmp_ctx);
1297                         return status;
1298                 }
1299                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1300                         gids[0] = id_map.xid.id;
1301                 } else {
1302                         struct dom_sid_buf buf1, buf2;
1303                         DEBUG(1, (__location__
1304                                   "Group %s, of which %s is a member, could not be converted to a GID\n",
1305                                   dom_sid_str_buf(&group_sids[0], &buf1),
1306                                   dom_sid_str_buf(&user->user_sid, &buf2)));
1307                         talloc_free(tmp_ctx);
1308                         /* We must error out, otherwise a user might
1309                          * avoid a DENY acl based on a group they
1310                          * missed out on */
1311                         return NT_STATUS_NO_SUCH_GROUP;
1312                 }
1313         }
1314
1315         *pp_sids = talloc_steal(mem_ctx, group_sids);
1316         *pp_gids = talloc_steal(mem_ctx, gids);
1317         *p_num_groups = num_groups;
1318         talloc_free(tmp_ctx);
1319         return NT_STATUS_OK;
1320 }
1321
1322 static NTSTATUS pdb_samba_dsdb_enum_group_memberships(struct pdb_methods *m,
1323                                                TALLOC_CTX *mem_ctx,
1324                                                struct samu *user,
1325                                                struct dom_sid **pp_sids,
1326                                                gid_t **pp_gids,
1327                                                uint32_t *p_num_groups)
1328 {
1329         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1330                 m->private_data, struct pdb_samba_dsdb_state);
1331         struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
1332                 m, user);
1333         const char *attrs[] = { "tokenGroups", NULL};
1334         struct ldb_message *tokengroups_msg;
1335         struct ldb_message_element *tokengroups;
1336         int i, rc;
1337         NTSTATUS status;
1338         unsigned int count = 0;
1339         size_t num_groups;
1340         struct dom_sid *group_sids;
1341         gid_t *gids;
1342         TALLOC_CTX *tmp_ctx;
1343
1344         if (msg == NULL) {
1345                 /* Fake up some things here */
1346                 return fake_enum_group_memberships(state,
1347                                                    mem_ctx,
1348                                                    user, pp_sids,
1349                                                    pp_gids, p_num_groups);
1350         }
1351
1352         tmp_ctx = talloc_new(mem_ctx);
1353         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1354
1355         rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
1356
1357         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1358                 talloc_free(tmp_ctx);
1359                 return NT_STATUS_NO_SUCH_USER;
1360         } else if (rc != LDB_SUCCESS) {
1361                 DEBUG(10, ("dsdb_search_one failed %s\n",
1362                            ldb_errstring(state->ldb)));
1363                 talloc_free(tmp_ctx);
1364                 return NT_STATUS_LDAP(rc);
1365         }
1366
1367         tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
1368
1369         if (tokengroups) {
1370                 count = tokengroups->num_values;
1371         }
1372
1373         group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
1374         if (group_sids == NULL) {
1375                 talloc_free(tmp_ctx);
1376                 return NT_STATUS_NO_MEMORY;
1377         }
1378         gids = talloc_array(tmp_ctx, gid_t, count);
1379         if (gids == NULL) {
1380                 talloc_free(tmp_ctx);
1381                 return NT_STATUS_NO_MEMORY;
1382         }
1383         num_groups = 0;
1384
1385         for (i=0; i<count; i++) {
1386                 struct id_map *id_maps[2];
1387                 struct id_map id_map;
1388                 struct ldb_val *v = &tokengroups->values[i];
1389                 enum ndr_err_code ndr_err
1390                         = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
1391                                                (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1392                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1393                         talloc_free(tmp_ctx);
1394                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1395                 }
1396
1397                 ZERO_STRUCT(id_map);
1398                 id_map.sid = &group_sids[num_groups];
1399                 id_maps[0] = &id_map;
1400                 id_maps[1] = NULL;
1401
1402                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1403                 if (!NT_STATUS_IS_OK(status)) {
1404                         talloc_free(tmp_ctx);
1405                         return status;
1406                 }
1407                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1408                         gids[num_groups] = id_map.xid.id;
1409                 } else {
1410                         struct dom_sid_buf buf;
1411                         DEBUG(1, (__location__
1412                                   "Group %s, of which %s is a member, could not be converted to a GID\n",
1413                                   dom_sid_str_buf(&group_sids[num_groups],
1414                                                   &buf),
1415                                   ldb_dn_get_linearized(msg->dn)));
1416                         talloc_free(tmp_ctx);
1417                         /* We must error out, otherwise a user might
1418                          * avoid a DENY acl based on a group they
1419                          * missed out on */
1420                         return NT_STATUS_NO_SUCH_GROUP;
1421                 }
1422
1423                 num_groups += 1;
1424                 if (num_groups == count) {
1425                         break;
1426                 }
1427         }
1428
1429         *pp_sids = talloc_steal(mem_ctx, group_sids);
1430         *pp_gids = talloc_steal(mem_ctx, gids);
1431         *p_num_groups = num_groups;
1432         talloc_free(tmp_ctx);
1433         return NT_STATUS_OK;
1434 }
1435
1436 static NTSTATUS pdb_samba_dsdb_set_unix_primary_group(struct pdb_methods *m,
1437                                                TALLOC_CTX *mem_ctx,
1438                                                struct samu *user)
1439 {
1440         return NT_STATUS_NOT_IMPLEMENTED;
1441 }
1442
1443 static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid(struct pdb_methods *m,
1444                                                TALLOC_CTX *mem_ctx,
1445                                                const struct dom_sid *groupsid,
1446                                                const struct dom_sid *membersid,
1447                                                int mod_op)
1448 {
1449         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1450                 m->private_data, struct pdb_samba_dsdb_state);
1451         struct ldb_message *msg;
1452         int ret;
1453         struct ldb_message_element *el;
1454         struct dom_sid_buf buf;
1455         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1456         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1457         msg = ldb_msg_new(tmp_ctx);
1458         if (msg == NULL) {
1459                 TALLOC_FREE(tmp_ctx);
1460                 return NT_STATUS_NO_MEMORY;
1461         }
1462
1463         msg->dn = ldb_dn_new_fmt(
1464                 msg,
1465                 state->ldb,
1466                 "<SID=%s>",
1467                 dom_sid_str_buf(groupsid, &buf));
1468         if (!msg->dn || !ldb_dn_validate(msg->dn)) {
1469                 talloc_free(tmp_ctx);
1470                 return NT_STATUS_NO_MEMORY;
1471         }
1472         ret = ldb_msg_add_fmt(
1473                 msg,
1474                 "member",
1475                 "<SID=%s>",
1476                 dom_sid_str_buf(membersid, &buf));
1477         if (ret != LDB_SUCCESS) {
1478                 talloc_free(tmp_ctx);
1479                 return NT_STATUS_NO_MEMORY;
1480         }
1481         el = ldb_msg_find_element(msg, "member");
1482         el->flags = mod_op;
1483
1484         /* No need for transactions here, the ldb auto-transaction
1485          * code will handle things for the single operation */
1486         ret = ldb_modify(state->ldb, msg);
1487         talloc_free(tmp_ctx);
1488         if (ret != LDB_SUCCESS) {
1489                 DEBUG(10, ("ldb_modify failed: %s\n",
1490                            ldb_errstring(state->ldb)));
1491                 if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
1492                         return NT_STATUS_MEMBER_IN_GROUP;
1493                 }
1494                 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1495                         return NT_STATUS_MEMBER_NOT_IN_GROUP;
1496                 }
1497                 return NT_STATUS_LDAP(ret);
1498         }
1499
1500         return NT_STATUS_OK;
1501 }
1502
1503 static NTSTATUS pdb_samba_dsdb_mod_groupmem(struct pdb_methods *m,
1504                                      TALLOC_CTX *mem_ctx,
1505                                      uint32_t grouprid, uint32_t memberrid,
1506                                      int mod_op)
1507 {
1508         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1509                 m->private_data, struct pdb_samba_dsdb_state);
1510         const struct dom_sid *dom_sid, *groupsid, *membersid;
1511         NTSTATUS status;
1512         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1513         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1514
1515         dom_sid = samdb_domain_sid(state->ldb);
1516
1517         groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
1518         if (groupsid == NULL) {
1519                 TALLOC_FREE(tmp_ctx);
1520                 return NT_STATUS_NO_MEMORY;
1521         }
1522         membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
1523         if (membersid == NULL) {
1524                 TALLOC_FREE(tmp_ctx);
1525                 return NT_STATUS_NO_MEMORY;
1526         }
1527         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
1528         talloc_free(tmp_ctx);
1529         return status;
1530 }
1531
1532 static NTSTATUS pdb_samba_dsdb_add_groupmem(struct pdb_methods *m,
1533                                      TALLOC_CTX *mem_ctx,
1534                                      uint32_t group_rid, uint32_t member_rid)
1535 {
1536         return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1537                                     LDB_FLAG_MOD_ADD);
1538 }
1539
1540 static NTSTATUS pdb_samba_dsdb_del_groupmem(struct pdb_methods *m,
1541                                      TALLOC_CTX *mem_ctx,
1542                                      uint32_t group_rid, uint32_t member_rid)
1543 {
1544         return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1545                                        LDB_FLAG_MOD_DELETE);
1546 }
1547
1548 static NTSTATUS pdb_samba_dsdb_create_alias(struct pdb_methods *m,
1549                                      const char *name, uint32_t *rid)
1550 {
1551         TALLOC_CTX *frame = talloc_stackframe();
1552         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1553                 m->private_data, struct pdb_samba_dsdb_state);
1554         struct dom_sid *sid;
1555
1556         struct ldb_dn *dn;
1557         NTSTATUS status;
1558
1559         /* Internally this uses transactions to ensure all the steps
1560          * happen or fail as one */
1561         status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
1562         if (!NT_STATUS_IS_OK(status)) {
1563                 TALLOC_FREE(frame);
1564         }
1565
1566         sid_peek_rid(sid, rid);
1567         TALLOC_FREE(frame);
1568         return NT_STATUS_OK;
1569 }
1570
1571 static NTSTATUS pdb_samba_dsdb_delete_alias(struct pdb_methods *m,
1572                                      const struct dom_sid *sid)
1573 {
1574         const char *attrs[] = { NULL };
1575         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1576                 m->private_data, struct pdb_samba_dsdb_state);
1577         struct ldb_message *msg;
1578         struct ldb_dn *dn;
1579         int rc;
1580         struct dom_sid_buf buf;
1581         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1582         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1583
1584         dn = ldb_dn_new_fmt(
1585                 tmp_ctx,
1586                 state->ldb,
1587                 "<SID=%s>",
1588                 dom_sid_str_buf(sid, &buf));
1589         if (!dn || !ldb_dn_validate(dn)) {
1590                 talloc_free(tmp_ctx);
1591                 return NT_STATUS_NO_MEMORY;
1592         }
1593
1594         if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1595                 DBG_ERR("Failed to start transaction: %s\n",
1596                         ldb_errstring(state->ldb));
1597                 talloc_free(tmp_ctx);
1598                 return NT_STATUS_INTERNAL_ERROR;
1599         }
1600
1601         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
1602                              "(|(grouptype=%d)(grouptype=%d)))",
1603                              GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1604                              GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1605         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1606                 talloc_free(tmp_ctx);
1607                 ldb_transaction_cancel(state->ldb);
1608                 return NT_STATUS_NO_SUCH_ALIAS;
1609         } else if (rc != LDB_SUCCESS) {
1610                 talloc_free(tmp_ctx);
1611                 DEBUG(10, ("dsdb_search_one failed %s\n",
1612                            ldb_errstring(state->ldb)));
1613                 ldb_transaction_cancel(state->ldb);
1614                 return NT_STATUS_LDAP(rc);
1615         }
1616         rc = ldb_delete(state->ldb, dn);
1617         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1618                 talloc_free(tmp_ctx);
1619                 ldb_transaction_cancel(state->ldb);
1620                 return NT_STATUS_NO_SUCH_ALIAS;
1621         } else if (rc != LDB_SUCCESS) {
1622                 DEBUG(10, ("ldb_delete failed %s\n",
1623                            ldb_errstring(state->ldb)));
1624                 ldb_transaction_cancel(state->ldb);
1625                 talloc_free(tmp_ctx);
1626                 return NT_STATUS_LDAP(rc);
1627         }
1628
1629         if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1630                 DEBUG(0, ("Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s\n",
1631                           ldb_errstring(state->ldb)));
1632                 talloc_free(tmp_ctx);
1633                 return NT_STATUS_INTERNAL_ERROR;
1634         }
1635
1636         talloc_free(tmp_ctx);
1637         return NT_STATUS_OK;
1638 }
1639
1640 static NTSTATUS pdb_samba_dsdb_add_aliasmem(struct pdb_methods *m,
1641                                      const struct dom_sid *alias,
1642                                      const struct dom_sid *member)
1643 {
1644         NTSTATUS status;
1645         TALLOC_CTX *frame = talloc_stackframe();
1646         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_ADD);
1647         talloc_free(frame);
1648         return status;
1649 }
1650
1651 static NTSTATUS pdb_samba_dsdb_del_aliasmem(struct pdb_methods *m,
1652                                      const struct dom_sid *alias,
1653                                      const struct dom_sid *member)
1654 {
1655         NTSTATUS status;
1656         TALLOC_CTX *frame = talloc_stackframe();
1657         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
1658         talloc_free(frame);
1659         return status;
1660 }
1661
1662 static NTSTATUS pdb_samba_dsdb_enum_aliasmem(struct pdb_methods *m,
1663                                       const struct dom_sid *alias,
1664                                       TALLOC_CTX *mem_ctx,
1665                                       struct dom_sid **pmembers,
1666                                       size_t *pnum_members)
1667 {
1668         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1669                 m->private_data, struct pdb_samba_dsdb_state);
1670         struct ldb_dn *dn;
1671         unsigned int num_members;
1672         NTSTATUS status;
1673         struct dom_sid_buf buf;
1674         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1675         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1676
1677         dn = ldb_dn_new_fmt(
1678                 tmp_ctx,
1679                 state->ldb,
1680                 "<SID=%s>",
1681                 dom_sid_str_buf(alias, &buf));
1682         if (!dn || !ldb_dn_validate(dn)) {
1683                 return NT_STATUS_NO_MEMORY;
1684         }
1685
1686         status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
1687         if (NT_STATUS_IS_OK(status)) {
1688                 *pnum_members = num_members;
1689         }
1690         talloc_free(tmp_ctx);
1691         return status;
1692 }
1693
1694 static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1695                                                TALLOC_CTX *mem_ctx,
1696                                                const struct dom_sid *domain_sid,
1697                                                const struct dom_sid *members,
1698                                                size_t num_members,
1699                                                uint32_t **palias_rids,
1700                                                size_t *pnum_alias_rids)
1701 {
1702         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1703                 m->private_data, struct pdb_samba_dsdb_state);
1704         uint32_t *alias_rids = NULL;
1705         size_t num_alias_rids = 0;
1706         int i;
1707         struct auth_SidAttr *groupSIDs = NULL;
1708         uint32_t num_groupSIDs = 0;
1709         char *filter;
1710         NTSTATUS status;
1711         const char *sid_dn;
1712         DATA_BLOB sid_blob;
1713
1714         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1715         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1716         /*
1717          * TODO: Get the filter right so that we only get the aliases from
1718          * either the SAM or BUILTIN
1719          */
1720
1721         filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:"LDB_OID_COMPARATOR_AND":=%u))",
1722                                  GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1723         if (filter == NULL) {
1724                 return NT_STATUS_NO_MEMORY;
1725         }
1726
1727         for (i = 0; i < num_members; i++) {
1728                 struct dom_sid_buf buf;
1729
1730                 sid_dn = talloc_asprintf(
1731                         tmp_ctx,
1732                         "<SID=%s>",
1733                         dom_sid_str_buf(&members[i], &buf));
1734                 if (sid_dn == NULL) {
1735                         TALLOC_FREE(tmp_ctx);
1736                         return NT_STATUS_NO_MEMORY;
1737                 }
1738
1739                 sid_blob = data_blob_string_const(sid_dn);
1740
1741                 status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1742                                                    tmp_ctx, &groupSIDs, &num_groupSIDs);
1743                 if (!NT_STATUS_IS_OK(status)) {
1744                         talloc_free(tmp_ctx);
1745                         return status;
1746                 }
1747         }
1748
1749         alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1750         if (alias_rids == NULL) {
1751                 talloc_free(tmp_ctx);
1752                 return NT_STATUS_NO_MEMORY;
1753         }
1754
1755         for (i=0; i<num_groupSIDs; i++) {
1756                 if (sid_peek_check_rid(domain_sid, &groupSIDs[i].sid,
1757                                        &alias_rids[num_alias_rids])) {
1758                         num_alias_rids++;;
1759                 }
1760         }
1761
1762         *palias_rids = alias_rids;
1763         *pnum_alias_rids = num_alias_rids;
1764         return NT_STATUS_OK;
1765 }
1766
1767 static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1768                                     const struct dom_sid *domain_sid,
1769                                     int num_rids,
1770                                     uint32_t *rids,
1771                                     const char **names,
1772                                     enum lsa_SidType *lsa_attrs)
1773 {
1774         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1775                 m->private_data, struct pdb_samba_dsdb_state);
1776         NTSTATUS status;
1777
1778         TALLOC_CTX *tmp_ctx;
1779
1780         if (num_rids == 0) {
1781                 return NT_STATUS_NONE_MAPPED;
1782         }
1783
1784         tmp_ctx = talloc_stackframe();
1785         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1786
1787         status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1788         talloc_free(tmp_ctx);
1789         return status;
1790 }
1791
1792 static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1793                                      const struct dom_sid *domain_sid,
1794                                      int num_names,
1795                                      const char **pp_names,
1796                                      uint32_t *rids,
1797                                      enum lsa_SidType *attrs)
1798 {
1799         return NT_STATUS_NOT_IMPLEMENTED;
1800 }
1801
1802 static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1803                                            enum pdb_policy_type type,
1804                                            uint32_t *value)
1805 {
1806         return account_policy_get(type, value)
1807                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1808 }
1809
1810 static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1811                                            enum pdb_policy_type type,
1812                                            uint32_t value)
1813 {
1814         return account_policy_set(type, value)
1815                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1816 }
1817
1818 static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1819                                     time_t *seq_num_out)
1820 {
1821         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1822                 m->private_data, struct pdb_samba_dsdb_state);
1823         uint64_t seq_num;
1824         int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1825         if (ret == LDB_SUCCESS) {
1826                 *seq_num_out = seq_num;
1827                 return NT_STATUS_OK;
1828         } else {
1829                 return NT_STATUS_UNSUCCESSFUL;
1830         }
1831 }
1832
1833 struct pdb_samba_dsdb_search_state {
1834         uint32_t acct_flags;
1835         struct samr_displayentry *entries;
1836         uint32_t num_entries;
1837         ssize_t array_size;
1838         uint32_t current;
1839 };
1840
1841 static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1842                                struct samr_displayentry *entry)
1843 {
1844         struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1845                 search->private_data, struct pdb_samba_dsdb_search_state);
1846
1847         if (state->current == state->num_entries) {
1848                 return false;
1849         }
1850
1851         entry->idx = state->entries[state->current].idx;
1852         entry->rid = state->entries[state->current].rid;
1853         entry->acct_flags = state->entries[state->current].acct_flags;
1854
1855         entry->account_name = talloc_strdup(
1856                 search, state->entries[state->current].account_name);
1857         entry->fullname = talloc_strdup(
1858                 search, state->entries[state->current].fullname);
1859         entry->description = talloc_strdup(
1860                 search, state->entries[state->current].description);
1861
1862         state->current += 1;
1863         return true;
1864 }
1865
1866 static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1867 {
1868         struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1869                 search->private_data, struct pdb_samba_dsdb_search_state);
1870         talloc_free(state);
1871 }
1872
1873 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1874                                          struct pdb_search *search,
1875                                          struct pdb_samba_dsdb_search_state **pstate,
1876                                          const char *exp_fmt, ...)
1877                                          PRINTF_ATTRIBUTE(4, 5);
1878
1879 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1880                                      struct pdb_search *search,
1881                                      struct pdb_samba_dsdb_search_state **pstate,
1882                                      const char *exp_fmt, ...)
1883 {
1884         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1885                 m->private_data, struct pdb_samba_dsdb_state);
1886         struct pdb_samba_dsdb_search_state *sstate;
1887         const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1888                                  "userAccountControl", "description", NULL };
1889         struct ldb_result *res;
1890         int i, rc, num_users;
1891
1892         va_list ap;
1893         char *expression = NULL;
1894
1895         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1896         if (!tmp_ctx) {
1897                 return false;
1898         }
1899
1900         va_start(ap, exp_fmt);
1901         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1902         va_end(ap);
1903
1904         if (!expression) {
1905                 talloc_free(tmp_ctx);
1906                 return LDB_ERR_OPERATIONS_ERROR;
1907         }
1908
1909         sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1910         if (sstate == NULL) {
1911                 talloc_free(tmp_ctx);
1912                 return false;
1913         }
1914
1915         rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1916         if (rc != LDB_SUCCESS) {
1917                 talloc_free(tmp_ctx);
1918                 DEBUG(10, ("dsdb_search failed: %s\n",
1919                            ldb_errstring(state->ldb)));
1920                 return false;
1921         }
1922
1923         num_users = res->count;
1924
1925         sstate->entries = talloc_array(sstate, struct samr_displayentry,
1926                                        num_users);
1927         if (sstate->entries == NULL) {
1928                 talloc_free(tmp_ctx);
1929                 DEBUG(10, ("talloc failed\n"));
1930                 return false;
1931         }
1932
1933         sstate->num_entries = 0;
1934
1935         for (i=0; i<num_users; i++) {
1936                 struct samr_displayentry *e;
1937                 struct dom_sid *sid;
1938
1939                 e = &sstate->entries[sstate->num_entries];
1940
1941                 e->idx = sstate->num_entries;
1942                 sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
1943                 if (!sid) {
1944                         talloc_free(tmp_ctx);
1945                         DEBUG(10, ("Could not pull SID\n"));
1946                         return false;
1947                 }
1948                 sid_peek_rid(sid, &e->rid);
1949
1950                 e->acct_flags = samdb_result_acct_flags(res->msgs[i], "userAccountControl");
1951                 e->account_name = ldb_msg_find_attr_as_string(
1952                         res->msgs[i], "samAccountName", NULL);
1953                 if (e->account_name == NULL) {
1954                         talloc_free(tmp_ctx);
1955                         return false;
1956                 }
1957                 e->fullname = ldb_msg_find_attr_as_string(
1958                         res->msgs[i], "displayName", "");
1959                 e->description = ldb_msg_find_attr_as_string(
1960                         res->msgs[i], "description", "");
1961
1962                 sstate->num_entries += 1;
1963                 if (sstate->num_entries >= num_users) {
1964                         break;
1965                 }
1966         }
1967         talloc_steal(sstate->entries, res->msgs);
1968         search->private_data = talloc_steal(search, sstate);
1969         search->next_entry = pdb_samba_dsdb_next_entry;
1970         search->search_end = pdb_samba_dsdb_search_end;
1971         *pstate = sstate;
1972         talloc_free(tmp_ctx);
1973         return true;
1974 }
1975
1976 static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
1977                                  struct pdb_search *search,
1978                                  uint32_t acct_flags)
1979 {
1980         struct pdb_samba_dsdb_search_state *sstate;
1981         bool ret;
1982
1983         ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
1984         if (!ret) {
1985                 return false;
1986         }
1987         sstate->acct_flags = acct_flags;
1988         return true;
1989 }
1990
1991 static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
1992                                   struct pdb_search *search)
1993 {
1994         struct pdb_samba_dsdb_search_state *sstate;
1995         bool ret;
1996
1997         ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
1998                                        "(&(grouptype=%d)(objectclass=group))",
1999                                        GTYPE_SECURITY_GLOBAL_GROUP);
2000         if (!ret) {
2001                 return false;
2002         }
2003         sstate->acct_flags = 0;
2004         return true;
2005 }
2006
2007 static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
2008                                    struct pdb_search *search,
2009                                    const struct dom_sid *sid)
2010 {
2011         struct pdb_samba_dsdb_search_state *sstate;
2012         bool ret;
2013
2014         ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2015                                        "(&(grouptype=%d)(objectclass=group))",
2016                                        sid_check_is_builtin(sid)
2017                                        ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2018                                        : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2019         if (!ret) {
2020                 return false;
2021         }
2022         sstate->acct_flags = 0;
2023         return true;
2024 }
2025
2026 /* 
2027  * Instead of taking a gid or uid, this function takes a pointer to a 
2028  * unixid. 
2029  *
2030  * This acts as an in-out variable so that the idmap functions can correctly
2031  * receive ID_TYPE_BOTH, and this function ensures cache details are filled
2032  * correctly rather than forcing the cache to store ID_TYPE_UID or ID_TYPE_GID. 
2033  */
2034 static bool pdb_samba_dsdb_id_to_sid(struct pdb_methods *m, struct unixid *id,
2035                                      struct dom_sid *sid)
2036 {
2037         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2038                 m->private_data, struct pdb_samba_dsdb_state);
2039         NTSTATUS status;
2040         struct id_map id_map;
2041         struct id_map *id_maps[2];
2042         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2043         if (!tmp_ctx) {
2044                 return false;
2045         }
2046
2047         id_map.xid = *id;
2048         id_maps[0] = &id_map;
2049         id_maps[1] = NULL;
2050
2051         status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2052         if (!NT_STATUS_IS_OK(status)) {
2053                 talloc_free(tmp_ctx);
2054                 return false;
2055         }
2056
2057         if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2058                 id->type = id_map.xid.type;
2059         }
2060         *sid = *id_map.sid;
2061         talloc_free(tmp_ctx);
2062         return true;
2063 }
2064
2065 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2066                                  struct unixid *id)
2067 {
2068         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2069                 m->private_data, struct pdb_samba_dsdb_state);
2070         struct id_map id_map;
2071         struct id_map *id_maps[2];
2072         NTSTATUS status;
2073         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2074         if (!tmp_ctx) {
2075                 return false;
2076         }
2077
2078         ZERO_STRUCT(id_map);
2079         id_map.sid = discard_const_p(struct dom_sid, sid);
2080         id_maps[0] = &id_map;
2081         id_maps[1] = NULL;
2082
2083         status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2084         talloc_free(tmp_ctx);
2085         if (!NT_STATUS_IS_OK(status)) {
2086                 return false;
2087         }
2088         if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2089                 *id = id_map.xid;
2090                 return true;
2091         }
2092         return false;
2093 }
2094
2095 static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2096 {
2097         return PDB_CAP_STORE_RIDS | PDB_CAP_ADS | PDB_CAP_TRUSTED_DOMAINS_EX;
2098 }
2099
2100 static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32_t *rid)
2101 {
2102         return false;
2103 }
2104
2105 static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2106                                       const char *domain, char** pwd,
2107                                       struct dom_sid *sid,
2108                                       time_t *pass_last_set_time)
2109 {
2110         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2111                 m->private_data, struct pdb_samba_dsdb_state);
2112         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2113         const char * const attrs[] = {
2114                 "securityIdentifier",
2115                 "flatName",
2116                 "trustPartner",
2117                 "trustAuthOutgoing",
2118                 "whenCreated",
2119                 "msDS-SupportedEncryptionTypes",
2120                 "trustAttributes",
2121                 "trustDirection",
2122                 "trustType",
2123                 NULL
2124         };
2125         struct ldb_message *msg;
2126         const struct ldb_val *password_val;
2127         int trust_direction_flags;
2128         int trust_type;
2129         int i;
2130         DATA_BLOB password_utf16;
2131         struct trustAuthInOutBlob password_blob;
2132         struct AuthenticationInformationArray *auth_array;
2133         char *password_talloc;
2134         size_t password_len;
2135         enum ndr_err_code ndr_err;
2136         NTSTATUS status;
2137         const char *netbios_domain = NULL;
2138         const struct dom_sid *domain_sid = NULL;
2139
2140         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2141                                        attrs, tmp_ctx, &msg);
2142         if (!NT_STATUS_IS_OK(status)) {
2143                 /*
2144                  * This can be called to work out of a domain is
2145                  * trusted, rather than just to get the password
2146                  */
2147                 DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
2148                           "It may not be a trusted domain.\n", domain,
2149                           nt_errstr(status)));
2150                 TALLOC_FREE(tmp_ctx);
2151                 return false;
2152         }
2153
2154         netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2155         if (netbios_domain == NULL) {
2156                 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2157                           domain));
2158                 TALLOC_FREE(tmp_ctx);
2159                 return false;
2160         }
2161
2162         domain_sid = samdb_result_dom_sid(tmp_ctx, msg, "securityIdentifier");
2163         if (domain_sid == NULL) {
2164                 DEBUG(2, ("Trusted domain %s has no securityIdentifier defined.\n",
2165                           domain));
2166                 TALLOC_FREE(tmp_ctx);
2167                 return false;
2168         }
2169
2170         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2171         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2172                 DBG_WARNING("Trusted domain %s is not an outbound trust.\n",
2173                             domain);
2174                 TALLOC_FREE(tmp_ctx);
2175                 return false;
2176         }
2177
2178         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2179         if (trust_type == LSA_TRUST_TYPE_MIT) {
2180                 DBG_WARNING("Trusted domain %s is not an AD trust "
2181                             "(trustType == LSA_TRUST_TYPE_MIT).\n", domain);
2182                 TALLOC_FREE(tmp_ctx);
2183                 return false;
2184         }
2185
2186         password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2187         if (password_val == NULL) {
2188                 DEBUG(2, ("Failed to get trusted domain password for %s, "
2189                           "attribute trustAuthOutgoing not returned.\n", domain));
2190                 TALLOC_FREE(tmp_ctx);
2191                 return false;
2192         }
2193
2194         ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2195                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2196         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2197                 DEBUG(0, ("Failed to get trusted domain password for %s, "
2198                           "attribute trustAuthOutgoing could not be parsed %s.\n",
2199                           domain,
2200                           ndr_map_error2string(ndr_err)));
2201                 TALLOC_FREE(tmp_ctx);
2202                 return false;
2203         }
2204
2205         auth_array = &password_blob.current;
2206
2207         for (i=0; i < auth_array->count; i++) {
2208                 if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
2209                         break;
2210                 }
2211         }
2212
2213         if (i == auth_array->count) {
2214                 DEBUG(0, ("Trusted domain %s does not have a "
2215                           "clear-text password stored\n",
2216                           domain));
2217                 TALLOC_FREE(tmp_ctx);
2218                 return false;
2219         }
2220
2221         password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
2222                                          auth_array->array[i].AuthInfo.clear.size);
2223
2224         /*
2225          * In the future, make this function return a
2226          * cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash()
2227          * but for now convert to UTF8 and fail if the string can not be converted.
2228          *
2229          * We can't safely convert the random strings windows uses into
2230          * utf8.
2231          */
2232         if (!convert_string_talloc(tmp_ctx,
2233                                    CH_UTF16MUNGED, CH_UTF8,
2234                                    password_utf16.data, password_utf16.length,
2235                                    (void *)&password_talloc,
2236                                    &password_len)) {
2237                 DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
2238                           " to UTF8. This may be a password set from Windows.\n",
2239                           domain));
2240                 TALLOC_FREE(tmp_ctx);
2241                 return false;
2242         }
2243         *pwd = SMB_STRNDUP(password_talloc, password_len);
2244         if (pass_last_set_time) {
2245                 *pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
2246         }
2247
2248         if (sid != NULL) {
2249                 sid_copy(sid, domain_sid);
2250         }
2251
2252         TALLOC_FREE(tmp_ctx);
2253         return true;
2254 }
2255
2256 static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
2257                                                     const char *domain,
2258                                                     TALLOC_CTX *mem_ctx,
2259                                                     struct cli_credentials **_creds)
2260 {
2261         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2262                 m->private_data, struct pdb_samba_dsdb_state);
2263         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2264         const char * const attrs[] = {
2265                 "securityIdentifier",
2266                 "flatName",
2267                 "trustPartner",
2268                 "trustAuthOutgoing",
2269                 "whenCreated",
2270                 "msDS-SupportedEncryptionTypes",
2271                 "trustAttributes",
2272                 "trustDirection",
2273                 "trustType",
2274                 NULL
2275         };
2276         struct ldb_message *msg;
2277         const struct ldb_val *password_val;
2278         int trust_direction_flags;
2279         int trust_type;
2280         int i;
2281         DATA_BLOB password_utf16 = {};
2282         struct samr_Password *password_nt = NULL;
2283         uint32_t password_version = 0;
2284         DATA_BLOB old_password_utf16 = {};
2285         struct samr_Password *old_password_nt = NULL;
2286         struct trustAuthInOutBlob password_blob;
2287         enum ndr_err_code ndr_err;
2288         NTSTATUS status;
2289         time_t last_set_time = 0;
2290         struct cli_credentials *creds = NULL;
2291         bool ok;
2292         const char *my_netbios_name = NULL;
2293         const char *my_netbios_domain = NULL;
2294         const char *my_dns_domain = NULL;
2295         const char *netbios_domain = NULL;
2296         char *account_name = NULL;
2297         char *principal_name = NULL;
2298         const char *dns_domain = NULL;
2299
2300         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2301                                        attrs, tmp_ctx, &msg);
2302         if (!NT_STATUS_IS_OK(status)) {
2303                 /*
2304                  * This can be called to work out of a domain is
2305                  * trusted, rather than just to get the password
2306                  */
2307                 DEBUG(2, ("Failed to get trusted domain password for %s - %s "
2308                           "It may not be a trusted domain.\n", domain,
2309                           nt_errstr(status)));
2310                 TALLOC_FREE(tmp_ctx);
2311                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2312         }
2313
2314         netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2315         if (netbios_domain == NULL) {
2316                 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2317                           domain));
2318                 TALLOC_FREE(tmp_ctx);
2319                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2320         }
2321
2322         dns_domain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2323
2324         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2325         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2326                 DBG_WARNING("Trusted domain %s is not an outbound trust.\n",
2327                             domain);
2328                 TALLOC_FREE(tmp_ctx);
2329                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2330         }
2331
2332         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2333         if (trust_type == LSA_TRUST_TYPE_MIT) {
2334                 DBG_WARNING("Trusted domain %s is not an AD trust "
2335                             "(trustType == LSA_TRUST_TYPE_MIT).\n", domain);
2336                 TALLOC_FREE(tmp_ctx);
2337                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2338         }
2339
2340         password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2341         if (password_val == NULL) {
2342                 DEBUG(2, ("Failed to get trusted domain password for %s, "
2343                           "attribute trustAuthOutgoing not returned.\n", domain));
2344                 TALLOC_FREE(tmp_ctx);
2345                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2346         }
2347
2348         ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2349                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2350         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2351                 DEBUG(0, ("Failed to get trusted domain password for %s, "
2352                           "attribute trustAuthOutgoing could not be parsed %s.\n",
2353                           domain,
2354                           ndr_map_error2string(ndr_err)));
2355                 TALLOC_FREE(tmp_ctx);
2356                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2357         }
2358
2359         for (i=0; i < password_blob.current.count; i++) {
2360                 struct AuthenticationInformation *a =
2361                         &password_blob.current.array[i];
2362
2363                 switch (a->AuthType) {
2364                 case TRUST_AUTH_TYPE_NONE:
2365                         break;
2366
2367                 case TRUST_AUTH_TYPE_VERSION:
2368                         password_version = a->AuthInfo.version.version;
2369                         break;
2370
2371                 case TRUST_AUTH_TYPE_CLEAR:
2372                         last_set_time = nt_time_to_unix(a->LastUpdateTime);
2373
2374                         password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2375                                                          a->AuthInfo.clear.size);
2376                         password_nt = NULL;
2377                         break;
2378
2379                 case TRUST_AUTH_TYPE_NT4OWF:
2380                         if (password_utf16.length != 0) {
2381                                 break;
2382                         }
2383
2384                         last_set_time = nt_time_to_unix(a->LastUpdateTime);
2385
2386                         password_nt = &a->AuthInfo.nt4owf.password;
2387                         break;
2388                 }
2389         }
2390
2391         for (i=0; i < password_blob.previous.count; i++) {
2392                 struct AuthenticationInformation *a = &password_blob.previous.array[i];
2393
2394                 switch (a->AuthType) {
2395                 case TRUST_AUTH_TYPE_NONE:
2396                         break;
2397
2398                 case TRUST_AUTH_TYPE_VERSION:
2399                         break;
2400
2401                 case TRUST_AUTH_TYPE_CLEAR:
2402                         old_password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2403                                                          a->AuthInfo.clear.size);
2404                         old_password_nt = NULL;
2405                         break;
2406
2407                 case TRUST_AUTH_TYPE_NT4OWF:
2408                         if (old_password_utf16.length != 0) {
2409                                 break;
2410                         }
2411
2412                         old_password_nt = &a->AuthInfo.nt4owf.password;
2413                         break;
2414                 }
2415         }
2416
2417         if (password_utf16.length == 0 && password_nt == NULL) {
2418                 DEBUG(0, ("Trusted domain %s does not have a "
2419                           "clear-text nor nt password stored\n",
2420                           domain));
2421                 TALLOC_FREE(tmp_ctx);
2422                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2423         }
2424
2425         my_netbios_name = lpcfg_netbios_name(state->lp_ctx);
2426         my_netbios_domain = lpcfg_workgroup(state->lp_ctx);
2427         my_dns_domain = lpcfg_dnsdomain(state->lp_ctx);
2428
2429         creds = cli_credentials_init(tmp_ctx);
2430         if (creds == NULL) {
2431                 TALLOC_FREE(tmp_ctx);
2432                 return NT_STATUS_NO_MEMORY;
2433         }
2434
2435         ok = cli_credentials_set_workstation(creds, my_netbios_name, CRED_SPECIFIED);
2436         if (!ok) {
2437                 TALLOC_FREE(tmp_ctx);
2438                 return NT_STATUS_NO_MEMORY;
2439         }
2440
2441         ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2442         if (!ok) {
2443                 TALLOC_FREE(tmp_ctx);
2444                 return NT_STATUS_NO_MEMORY;
2445         }
2446         ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2447         if (!ok) {
2448                 TALLOC_FREE(tmp_ctx);
2449                 return NT_STATUS_NO_MEMORY;
2450         }
2451
2452         if (my_dns_domain != NULL && dns_domain != NULL) {
2453                 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DNS_DOMAIN);
2454                 account_name = talloc_asprintf(tmp_ctx, "%s.", my_dns_domain);
2455                 if (account_name == NULL) {
2456                         TALLOC_FREE(tmp_ctx);
2457                         return NT_STATUS_NO_MEMORY;
2458                 }
2459                 principal_name = talloc_asprintf(tmp_ctx, "%s$@%s", my_netbios_domain,
2460                                                  cli_credentials_get_realm(creds));
2461                 if (principal_name == NULL) {
2462                         TALLOC_FREE(tmp_ctx);
2463                         return NT_STATUS_NO_MEMORY;
2464                 }
2465         } else {
2466                 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DOMAIN);
2467                 account_name = talloc_asprintf(tmp_ctx, "%s$", my_netbios_domain);
2468                 if (account_name == NULL) {
2469                         TALLOC_FREE(tmp_ctx);
2470                         return NT_STATUS_NO_MEMORY;
2471                 }
2472                 principal_name = NULL;
2473         }
2474
2475         ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2476         if (!ok) {
2477                 TALLOC_FREE(tmp_ctx);
2478                 return NT_STATUS_NO_MEMORY;
2479         }
2480
2481         if (principal_name != NULL) {
2482                 ok = cli_credentials_set_principal(creds, principal_name,
2483                                                    CRED_SPECIFIED);
2484                 if (!ok) {
2485                         TALLOC_FREE(tmp_ctx);
2486                         return NT_STATUS_NO_MEMORY;
2487                 }
2488         }
2489
2490         if (old_password_nt != NULL) {
2491                 ok = cli_credentials_set_old_nt_hash(creds, old_password_nt);
2492                 if (!ok) {
2493                         TALLOC_FREE(tmp_ctx);
2494                         return NT_STATUS_NO_MEMORY;
2495                 }
2496         }
2497
2498         if (old_password_utf16.length > 0) {
2499                 ok = cli_credentials_set_old_utf16_password(creds,
2500                                                             &old_password_utf16);
2501                 if (!ok) {
2502                         TALLOC_FREE(tmp_ctx);
2503                         return NT_STATUS_NO_MEMORY;
2504                 }
2505         }
2506
2507         if (password_nt != NULL) {
2508                 ok = cli_credentials_set_nt_hash(creds, password_nt,
2509                                                  CRED_SPECIFIED);
2510                 if (!ok) {
2511                         TALLOC_FREE(tmp_ctx);
2512                         return NT_STATUS_NO_MEMORY;
2513                 }
2514         }
2515
2516         if (password_utf16.length > 0) {
2517                 ok = cli_credentials_set_utf16_password(creds,
2518                                                         &password_utf16,
2519                                                         CRED_SPECIFIED);
2520                 if (!ok) {
2521                         TALLOC_FREE(tmp_ctx);
2522                         return NT_STATUS_NO_MEMORY;
2523                 }
2524         }
2525
2526         cli_credentials_set_password_last_changed_time(creds, last_set_time);
2527         cli_credentials_set_kvno(creds, password_version);
2528
2529         if (password_utf16.length > 0 && dns_domain != NULL) {
2530                 /*
2531                  * Force kerberos if this is an active directory domain
2532                  */
2533                 cli_credentials_set_kerberos_state(creds,
2534                                                    CRED_USE_KERBEROS_REQUIRED,
2535                                                    CRED_SPECIFIED);
2536         } else  {
2537                 /*
2538                  * TODO: we should allow krb5 with the raw nt hash.
2539                  */
2540                 cli_credentials_set_kerberos_state(creds,
2541                                                    CRED_USE_KERBEROS_DISABLED,
2542                                                    CRED_SPECIFIED);
2543         }
2544
2545         *_creds = talloc_move(mem_ctx, &creds);
2546         TALLOC_FREE(tmp_ctx);
2547         return NT_STATUS_OK;
2548 }
2549
2550 static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2551                                       const char* domain, const char* pwd,
2552                                       const struct dom_sid *sid)
2553 {
2554         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2555                 m->private_data, struct pdb_samba_dsdb_state);
2556         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2557         const char * const attrs[] = {
2558                 "trustAuthOutgoing",
2559                 "trustDirection",
2560                 "trustType",
2561                 NULL
2562         };
2563         struct ldb_message *msg = NULL;
2564         int trust_direction_flags;
2565         int trust_type;
2566         uint32_t i; /* The same type as old_blob.current.count */
2567         const struct ldb_val *old_val = NULL;
2568         struct trustAuthInOutBlob old_blob = {};
2569         uint32_t old_version = 0;
2570         uint32_t new_version = 0;
2571         DATA_BLOB new_utf16 = {};
2572         struct trustAuthInOutBlob new_blob = {};
2573         struct ldb_val new_val = {};
2574         struct timeval tv = timeval_current();
2575         NTTIME now = timeval_to_nttime(&tv);
2576         enum ndr_err_code ndr_err;
2577         NTSTATUS status;
2578         bool ok;
2579         int ret;
2580
2581         ret = ldb_transaction_start(state->ldb);
2582         if (ret != LDB_SUCCESS) {
2583                 DEBUG(2, ("Failed to start transaction.\n"));
2584                 TALLOC_FREE(tmp_ctx);
2585                 return false;
2586         }
2587
2588         ok = samdb_is_pdc(state->ldb);
2589         if (!ok) {
2590                 DEBUG(2, ("Password changes for domain %s are only allowed on a PDC.\n",
2591                           domain));
2592                 TALLOC_FREE(tmp_ctx);
2593                 ldb_transaction_cancel(state->ldb);
2594                 return false;
2595         }
2596
2597         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2598                                        attrs, tmp_ctx, &msg);
2599         if (!NT_STATUS_IS_OK(status)) {
2600                 /*
2601                  * This can be called to work out of a domain is
2602                  * trusted, rather than just to get the password
2603                  */
2604                 DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
2605                           "It may not be a trusted domain.\n", domain,
2606                           nt_errstr(status)));
2607                 TALLOC_FREE(tmp_ctx);
2608                 ldb_transaction_cancel(state->ldb);
2609                 return false;
2610         }
2611
2612         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2613         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2614                 DBG_WARNING("Trusted domain %s is not an outbound trust, can't set a password.\n",
2615                             domain);
2616                 TALLOC_FREE(tmp_ctx);
2617                 ldb_transaction_cancel(state->ldb);
2618                 return false;
2619         }
2620
2621         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2622         switch (trust_type) {
2623         case LSA_TRUST_TYPE_DOWNLEVEL:
2624         case LSA_TRUST_TYPE_UPLEVEL:
2625                 break;
2626         default:
2627                 DEBUG(0, ("Trusted domain %s is of type 0x%X - "
2628                           "password changes are not supported\n",
2629                           domain, (unsigned)trust_type));
2630                 TALLOC_FREE(tmp_ctx);
2631                 ldb_transaction_cancel(state->ldb);
2632                 return false;
2633         }
2634
2635         old_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2636         if (old_val != NULL) {
2637                 ndr_err = ndr_pull_struct_blob(old_val, tmp_ctx, &old_blob,
2638                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2639                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2640                         DEBUG(0, ("Failed to get trusted domain password for %s, "
2641                                   "attribute trustAuthOutgoing could not be parsed %s.\n",
2642                                   domain,
2643                                   ndr_map_error2string(ndr_err)));
2644                         TALLOC_FREE(tmp_ctx);
2645                         ldb_transaction_cancel(state->ldb);
2646                         return false;
2647                 }
2648         }
2649
2650         for (i=0; i < old_blob.current.count; i++) {
2651                 struct AuthenticationInformation *a =
2652                         &old_blob.current.array[i];
2653
2654                 switch (a->AuthType) {
2655                 case TRUST_AUTH_TYPE_NONE:
2656                         break;
2657
2658                 case TRUST_AUTH_TYPE_VERSION:
2659                         old_version = a->AuthInfo.version.version;
2660                         break;
2661
2662                 case TRUST_AUTH_TYPE_CLEAR:
2663                         break;
2664
2665                 case TRUST_AUTH_TYPE_NT4OWF:
2666                         break;
2667                 }
2668         }
2669
2670         new_version = old_version + 1;
2671         ok = convert_string_talloc(tmp_ctx,
2672                                    CH_UNIX, CH_UTF16,
2673                                    pwd, strlen(pwd),
2674                                    (void *)&new_utf16.data,
2675                                    &new_utf16.length);
2676         if (!ok) {
2677                 DEBUG(0, ("Failed to generate new_utf16 password for  domain %s\n",
2678                           domain));
2679                 TALLOC_FREE(tmp_ctx);
2680                 ldb_transaction_cancel(state->ldb);
2681                 return false;
2682         }
2683
2684         if (new_utf16.length < 28) {
2685                 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to short.\n",
2686                           new_utf16.length,
2687                           (unsigned)new_version,
2688                           domain));
2689                 TALLOC_FREE(tmp_ctx);
2690                 ldb_transaction_cancel(state->ldb);
2691                 return false;
2692         }
2693         if (new_utf16.length > 498) {
2694                 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to long.\n",
2695                           new_utf16.length,
2696                           (unsigned)new_version,
2697                           domain));
2698                 TALLOC_FREE(tmp_ctx);
2699                 ldb_transaction_cancel(state->ldb);
2700                 return false;
2701         }
2702
2703         new_blob.count = MAX(old_blob.current.count, 2);
2704         new_blob.current.array = talloc_zero_array(tmp_ctx,
2705                                         struct AuthenticationInformation,
2706                                         new_blob.count);
2707         if (new_blob.current.array == NULL) {
2708                 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2709                           (unsigned)new_blob.count));
2710                 TALLOC_FREE(tmp_ctx);
2711                 ldb_transaction_cancel(state->ldb);
2712                 return false;
2713         }
2714         new_blob.previous.array = talloc_zero_array(tmp_ctx,
2715                                         struct AuthenticationInformation,
2716                                         new_blob.count);
2717         if (new_blob.current.array == NULL) {
2718                 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2719                           (unsigned)new_blob.count));
2720                 TALLOC_FREE(tmp_ctx);
2721                 ldb_transaction_cancel(state->ldb);
2722                 return false;
2723         }
2724
2725         for (i = 0; i < old_blob.current.count; i++) {
2726                 new_blob.previous.array[i] = old_blob.current.array[i];
2727                 new_blob.previous.count++;
2728         }
2729         for (; i < new_blob.count; i++) {
2730                 struct AuthenticationInformation *pi =
2731                         &new_blob.previous.array[i];
2732
2733                 if (i == 0) {
2734                         /*
2735                          * new_blob.previous is still empty so
2736                          * we'll do new_blob.previous = new_blob.current
2737                          * below.
2738                          */
2739                         break;
2740                 }
2741
2742                 pi->LastUpdateTime = now;
2743                 pi->AuthType = TRUST_AUTH_TYPE_NONE;
2744                 new_blob.previous.count++;
2745         }
2746
2747         for (i = 0; i < new_blob.count; i++) {
2748                 struct AuthenticationInformation *ci =
2749                         &new_blob.current.array[i];
2750
2751                 ci->LastUpdateTime = now;
2752                 switch (i) {
2753                 case 0:
2754                         ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
2755                         ci->AuthInfo.clear.size = new_utf16.length;
2756                         ci->AuthInfo.clear.password = new_utf16.data;
2757                         break;
2758                 case 1:
2759                         ci->AuthType = TRUST_AUTH_TYPE_VERSION;
2760                         ci->AuthInfo.version.version = new_version;
2761                         break;
2762                 default:
2763                         ci->AuthType = TRUST_AUTH_TYPE_NONE;
2764                         break;
2765                 }
2766
2767                 new_blob.current.count++;
2768         }
2769
2770         if (new_blob.previous.count == 0) {
2771                 TALLOC_FREE(new_blob.previous.array);
2772                 new_blob.previous = new_blob.current;
2773         }
2774
2775         ndr_err = ndr_push_struct_blob(&new_val, tmp_ctx, &new_blob,
2776                         (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
2777         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2778                 DEBUG(0, ("Failed to generate trustAuthOutgoing for "
2779                           "trusted domain password for %s: %s.\n",
2780                           domain, ndr_map_error2string(ndr_err)));
2781                 TALLOC_FREE(tmp_ctx);
2782                 ldb_transaction_cancel(state->ldb);
2783                 return false;
2784         }
2785
2786         msg->num_elements = 0;
2787         ret = ldb_msg_append_value(msg, "trustAuthOutgoing",
2788                                    &new_val, LDB_FLAG_MOD_REPLACE);
2789         if (ret != LDB_SUCCESS) {
2790                 DEBUG(0, ("ldb_msg_append_value() failed\n"));
2791                 TALLOC_FREE(tmp_ctx);
2792                 ldb_transaction_cancel(state->ldb);
2793                 return false;
2794         }
2795
2796         ret = ldb_modify(state->ldb, msg);
2797         if (ret != LDB_SUCCESS) {
2798                 DEBUG(0, ("Failed to replace trustAuthOutgoing for "
2799                           "trusted domain password for %s: %s - %s\n",
2800                           domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2801                 TALLOC_FREE(tmp_ctx);
2802                 ldb_transaction_cancel(state->ldb);
2803                 return false;
2804         }
2805
2806         ret = ldb_transaction_commit(state->ldb);
2807         if (ret != LDB_SUCCESS) {
2808                 DEBUG(0, ("Failed to commit trustAuthOutgoing for "
2809                           "trusted domain password for %s: %s - %s\n",
2810                           domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2811                 TALLOC_FREE(tmp_ctx);
2812                 return false;
2813         }
2814
2815         DEBUG(1, ("Added new_version[%u] to trustAuthOutgoing for "
2816                   "trusted domain password for %s.\n",
2817                   (unsigned)new_version, domain));
2818         TALLOC_FREE(tmp_ctx);
2819         return true;
2820 }
2821
2822 static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2823                                       const char *domain)
2824 {
2825         return false;
2826 }
2827
2828 static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2829                                          TALLOC_CTX *mem_ctx,
2830                                          uint32_t *_num_domains,
2831                                          struct trustdom_info ***_domains)
2832 {
2833         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2834                 m->private_data, struct pdb_samba_dsdb_state);
2835         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2836         const char * const attrs[] = {
2837                 "securityIdentifier",
2838                 "flatName",
2839                 "trustDirection",
2840                 NULL
2841         };
2842         struct ldb_result *res = NULL;
2843         unsigned int i;
2844         struct trustdom_info **domains = NULL;
2845         NTSTATUS status;
2846         uint32_t di = 0;
2847
2848         *_num_domains = 0;
2849         *_domains = NULL;
2850
2851         status = dsdb_trust_search_tdos(state->ldb, NULL,
2852                                         attrs, tmp_ctx, &res);
2853         if (!NT_STATUS_IS_OK(status)) {
2854                 DBG_ERR("dsdb_trust_search_tdos() - %s\n", nt_errstr(status));
2855                 TALLOC_FREE(tmp_ctx);
2856                 return status;
2857         }
2858
2859         if (res->count == 0) {
2860                 TALLOC_FREE(tmp_ctx);
2861                 return NT_STATUS_OK;
2862         }
2863
2864         domains = talloc_zero_array(tmp_ctx, struct trustdom_info *,
2865                                     res->count);
2866         if (domains == NULL) {
2867                 TALLOC_FREE(tmp_ctx);
2868                 return NT_STATUS_NO_MEMORY;
2869         }
2870
2871         for (i = 0; i < res->count; i++) {
2872                 struct ldb_message *msg = res->msgs[i];
2873                 struct trustdom_info *d = NULL;
2874                 const char *name = NULL;
2875                 struct dom_sid *sid = NULL;
2876                 uint32_t direction;
2877
2878                 d = talloc_zero(domains, struct trustdom_info);
2879                 if (d == NULL) {
2880                         TALLOC_FREE(tmp_ctx);
2881                         return NT_STATUS_NO_MEMORY;
2882                 }
2883
2884                 name = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2885                 if (name == NULL) {
2886                         TALLOC_FREE(tmp_ctx);
2887                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2888                 }
2889                 sid = samdb_result_dom_sid(msg, msg, "securityIdentifier");
2890                 if (sid == NULL) {
2891                         continue;
2892                 }
2893
2894                 direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
2895                 if (!(direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2896                         continue;
2897                 }
2898
2899                 d->name = talloc_strdup(d, name);
2900                 if (d->name == NULL) {
2901                         TALLOC_FREE(tmp_ctx);
2902                         return NT_STATUS_NO_MEMORY;
2903                 }
2904                 d->sid = *sid;
2905
2906                 domains[di++] = d;
2907         }
2908
2909         domains = talloc_realloc(domains, domains, struct trustdom_info *, di);
2910         *_domains = talloc_move(mem_ctx, &domains);
2911         *_num_domains = di;
2912         TALLOC_FREE(tmp_ctx);
2913         return NT_STATUS_OK;
2914 }
2915
2916 static NTSTATUS pdb_samba_dsdb_msg_to_trusted_domain(const struct ldb_message *msg,
2917                                                 TALLOC_CTX *mem_ctx,
2918                                                 struct pdb_trusted_domain **_d)
2919 {
2920         struct pdb_trusted_domain *d = NULL;
2921         const char *str = NULL;
2922         struct dom_sid *sid = NULL;
2923         const struct ldb_val *val = NULL;
2924         uint64_t val64;
2925
2926         *_d = NULL;
2927
2928         d = talloc_zero(mem_ctx, struct pdb_trusted_domain);
2929         if (d == NULL) {
2930                 return NT_STATUS_NO_MEMORY;
2931         }
2932
2933         str = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2934         if (str == NULL) {
2935                 TALLOC_FREE(d);
2936                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2937         }
2938         d->netbios_name = talloc_strdup(d, str);
2939         if (d->netbios_name == NULL) {
2940                 TALLOC_FREE(d);
2941                 return NT_STATUS_NO_MEMORY;
2942         }
2943
2944         str = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2945         if (str != NULL) {
2946                 d->domain_name = talloc_strdup(d, str);
2947                 if (d->domain_name == NULL) {
2948                         TALLOC_FREE(d);
2949                         return NT_STATUS_NO_MEMORY;
2950                 }
2951         }
2952
2953         sid = samdb_result_dom_sid(d, msg, "securityIdentifier");
2954         if (sid != NULL) {
2955                 d->security_identifier = *sid;
2956                 TALLOC_FREE(sid);
2957         }
2958
2959         val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2960         if (val != NULL) {
2961                 d->trust_auth_outgoing = data_blob_dup_talloc(d, *val);
2962                 if (d->trust_auth_outgoing.data == NULL) {
2963                         TALLOC_FREE(d);
2964                         return NT_STATUS_NO_MEMORY;
2965                 }
2966         }
2967         val = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
2968         if (val != NULL) {
2969                 d->trust_auth_incoming = data_blob_dup_talloc(d, *val);
2970                 if (d->trust_auth_incoming.data == NULL) {
2971                         TALLOC_FREE(d);
2972                         return NT_STATUS_NO_MEMORY;
2973                 }
2974         }
2975
2976         d->trust_direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
2977         d->trust_type = ldb_msg_find_attr_as_uint(msg, "trustType", 0);
2978         d->trust_attributes = ldb_msg_find_attr_as_uint(msg, "trustAttributes", 0);
2979
2980         val64 = ldb_msg_find_attr_as_uint64(msg, "trustPosixOffset", UINT64_MAX);
2981         if (val64 != UINT64_MAX) {
2982                 d->trust_posix_offset = talloc(d, uint32_t);
2983                 if (d->trust_posix_offset == NULL) {
2984                         TALLOC_FREE(d);
2985                         return NT_STATUS_NO_MEMORY;
2986                 }
2987                 *d->trust_posix_offset = (uint32_t)val64;
2988         }
2989
2990         val64 = ldb_msg_find_attr_as_uint64(msg, "msDS-SupportedEncryptionTypes", UINT64_MAX);
2991         if (val64 != UINT64_MAX) {
2992                 d->supported_enc_type = talloc(d, uint32_t);
2993                 if (d->supported_enc_type == NULL) {
2994                         TALLOC_FREE(d);
2995                         return NT_STATUS_NO_MEMORY;
2996                 }
2997                 *d->supported_enc_type = (uint32_t)val64;
2998         }
2999
3000         val = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3001         if (val != NULL) {
3002                 d->trust_forest_trust_info = data_blob_dup_talloc(d, *val);
3003                 if (d->trust_forest_trust_info.data == NULL) {
3004                         TALLOC_FREE(d);
3005                         return NT_STATUS_NO_MEMORY;
3006                 }
3007         }
3008
3009         *_d = d;
3010         return NT_STATUS_OK;
3011 }
3012
3013 static NTSTATUS pdb_samba_dsdb_get_trusted_domain(struct pdb_methods *m,
3014                                                   TALLOC_CTX *mem_ctx,
3015                                                   const char *domain,
3016                                                   struct pdb_trusted_domain **td)
3017 {
3018         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3019                 m->private_data, struct pdb_samba_dsdb_state);
3020         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3021         const char * const attrs[] = {
3022                 "securityIdentifier",
3023                 "flatName",
3024                 "trustPartner",
3025                 "trustAuthOutgoing",
3026                 "trustAuthIncoming",
3027                 "trustAttributes",
3028                 "trustDirection",
3029                 "trustType",
3030                 "trustPosixOffset",
3031                 "msDS-SupportedEncryptionTypes",
3032                 "msDS-TrustForestTrustInfo",
3033                 NULL
3034         };
3035         struct ldb_message *msg = NULL;
3036         struct pdb_trusted_domain *d = NULL;
3037         NTSTATUS status;
3038
3039         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
3040                                        attrs, tmp_ctx, &msg);
3041         if (!NT_STATUS_IS_OK(status)) {
3042                 DBG_ERR("dsdb_trust_search_tdo(%s) - %s\n",
3043                         domain, nt_errstr(status));
3044                 TALLOC_FREE(tmp_ctx);
3045                 return status;
3046         }
3047
3048         status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3049         if (!NT_STATUS_IS_OK(status)) {
3050                 DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s\n",
3051                         domain, nt_errstr(status));
3052                 TALLOC_FREE(tmp_ctx);
3053                 return status;
3054         }
3055
3056         *td = d;
3057         TALLOC_FREE(tmp_ctx);
3058         return NT_STATUS_OK;
3059 }
3060
3061 static NTSTATUS pdb_samba_dsdb_get_trusted_domain_by_sid(struct pdb_methods *m,
3062                                                          TALLOC_CTX *mem_ctx,
3063                                                          struct dom_sid *sid,
3064                                                          struct pdb_trusted_domain **td)
3065 {
3066         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3067                 m->private_data, struct pdb_samba_dsdb_state);
3068         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3069         const char * const attrs[] = {
3070                 "securityIdentifier",
3071                 "flatName",
3072                 "trustPartner",
3073                 "trustAuthOutgoing",
3074                 "trustAuthIncoming",
3075                 "trustAttributes",
3076                 "trustDirection",
3077                 "trustType",
3078                 "trustPosixOffset",
3079                 "msDS-SupportedEncryptionTypes",
3080                 "msDS-TrustForestTrustInfo",
3081                 NULL
3082         };
3083         struct ldb_message *msg = NULL;
3084         struct pdb_trusted_domain *d = NULL;
3085         struct dom_sid_buf buf;
3086         NTSTATUS status;
3087
3088         status = dsdb_trust_search_tdo_by_sid(state->ldb, sid,
3089                                               attrs, tmp_ctx, &msg);
3090         if (!NT_STATUS_IS_OK(status)) {
3091                 DBG_ERR("dsdb_trust_search_tdo_by_sid(%s) - %s\n",
3092                         dom_sid_str_buf(sid, &buf),
3093                         nt_errstr(status));
3094                 TALLOC_FREE(tmp_ctx);
3095                 return status;
3096         }
3097
3098         status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3099         if (!NT_STATUS_IS_OK(status)) {
3100                 DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s\n",
3101                         dom_sid_str_buf(sid, &buf),
3102                         nt_errstr(status));
3103                 TALLOC_FREE(tmp_ctx);
3104                 return status;
3105         }
3106
3107         *td = d;
3108         TALLOC_FREE(tmp_ctx);
3109         return NT_STATUS_OK;
3110 }
3111
3112 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
3113                                struct ldb_context *sam_ldb,
3114                                struct ldb_dn *base_dn,
3115                                const char *netbios_name,
3116                                struct trustAuthInOutBlob *taiob)
3117 {
3118         struct ldb_request *req = NULL;
3119         struct ldb_message *msg = NULL;
3120         struct ldb_dn *dn = NULL;
3121         uint32_t i;
3122         int ret;
3123         bool ok;
3124
3125         dn = ldb_dn_copy(mem_ctx, base_dn);
3126         if (dn == NULL) {
3127                 return NT_STATUS_NO_MEMORY;
3128         }
3129         ok = ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name);
3130         if (!ok) {
3131                 return NT_STATUS_NO_MEMORY;
3132         }
3133
3134         msg = ldb_msg_new(mem_ctx);
3135         if (msg == NULL) {
3136                 return NT_STATUS_NO_MEMORY;
3137         }
3138         msg->dn = dn;
3139
3140         ret = ldb_msg_add_string(msg, "objectClass", "user");
3141         if (ret != LDB_SUCCESS) {
3142                 return NT_STATUS_NO_MEMORY;
3143         }
3144
3145         ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
3146         if (ret != LDB_SUCCESS) {
3147                 return NT_STATUS_NO_MEMORY;
3148         }
3149
3150         ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
3151                                  UF_INTERDOMAIN_TRUST_ACCOUNT);
3152         if (ret != LDB_SUCCESS) {
3153                 return NT_STATUS_NO_MEMORY;
3154         }
3155
3156         for (i = 0; i < taiob->count; i++) {
3157                 struct AuthenticationInformation *auth_info =
3158                         &taiob->current.array[i];
3159                 const char *attribute = NULL;
3160                 struct ldb_val v;
3161
3162                 switch (taiob->current.array[i].AuthType) {
3163                 case TRUST_AUTH_TYPE_NT4OWF:
3164                         attribute = "unicodePwd";
3165                         v.data = (uint8_t *)&auth_info->AuthInfo.nt4owf.password;
3166                         v.length = 16;
3167                         break;
3168
3169                 case TRUST_AUTH_TYPE_CLEAR:
3170                         attribute = "clearTextPassword";
3171                         v.data = auth_info->AuthInfo.clear.password;
3172                         v.length = auth_info->AuthInfo.clear.size;
3173                         break;
3174
3175                 default:
3176                         continue;
3177                 }
3178
3179                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
3180                 if (ret != LDB_SUCCESS) {
3181                         return NT_STATUS_NO_MEMORY;
3182                 }
3183         }
3184
3185         /* create the trusted_domain user account */
3186         ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
3187                                 ldb_op_default_callback, NULL);
3188         if (ret != LDB_SUCCESS) {
3189                 return NT_STATUS_NO_MEMORY;
3190         }
3191
3192         ret = ldb_request_add_control(
3193                 req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
3194                 false, NULL);
3195         if (ret != LDB_SUCCESS) {
3196                 return NT_STATUS_NO_MEMORY;
3197         }
3198
3199         ret = dsdb_autotransaction_request(sam_ldb, req);
3200         if (ret != LDB_SUCCESS) {
3201                 DEBUG(0,("Failed to create user record %s: %s\n",
3202                          ldb_dn_get_linearized(msg->dn),
3203                          ldb_errstring(sam_ldb)));
3204
3205                 switch (ret) {
3206                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
3207                         return NT_STATUS_DOMAIN_EXISTS;
3208                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3209                         return NT_STATUS_ACCESS_DENIED;
3210                 default:
3211                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3212                 }
3213         }
3214
3215         return NT_STATUS_OK;
3216 }
3217
3218 static NTSTATUS pdb_samba_dsdb_set_trusted_domain(struct pdb_methods *methods,
3219                                                   const char* domain,
3220                                                   const struct pdb_trusted_domain *td)
3221 {
3222         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3223                 methods->private_data, struct pdb_samba_dsdb_state);
3224         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3225         bool in_txn = false;
3226         struct ldb_dn *base_dn = NULL;
3227         struct ldb_message *msg = NULL;
3228         const char *attrs[] = {
3229                 NULL
3230         };
3231         char *netbios_encoded = NULL;
3232         char *dns_encoded = NULL;
3233         char *sid_encoded = NULL;
3234         int ret;
3235         struct trustAuthInOutBlob taiob;
3236         enum ndr_err_code ndr_err;
3237         NTSTATUS status;
3238         bool ok;
3239
3240         base_dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(state->ldb));
3241         if (base_dn == NULL) {
3242                 TALLOC_FREE(tmp_ctx);
3243                 status = NT_STATUS_NO_MEMORY;
3244                 goto out;
3245         }
3246         /*
3247          * We expect S-1-5-21-A-B-C, but we don't
3248          * allow S-1-5-21-0-0-0 as this is used
3249          * for claims and compound identities.
3250          */
3251         ok = dom_sid_is_valid_account_domain(&td->security_identifier);
3252         if (!ok) {
3253                 status = NT_STATUS_INVALID_PARAMETER;
3254                 goto out;
3255         }
3256
3257         if (strequal(td->netbios_name, "BUILTIN")) {
3258                 status = NT_STATUS_INVALID_PARAMETER;
3259                 goto out;
3260         }
3261         if (strequal(td->domain_name, "BUILTIN")) {
3262                 status = NT_STATUS_INVALID_PARAMETER;
3263                 goto out;
3264         }
3265
3266         dns_encoded = ldb_binary_encode_string(tmp_ctx, td->domain_name);
3267         if (dns_encoded == NULL) {
3268                 status = NT_STATUS_NO_MEMORY;
3269                 goto out;
3270         }
3271         netbios_encoded = ldb_binary_encode_string(tmp_ctx, td->netbios_name);
3272         if (netbios_encoded == NULL) {
3273                 status =NT_STATUS_NO_MEMORY;
3274                 goto out;
3275         }
3276         sid_encoded = ldap_encode_ndr_dom_sid(tmp_ctx, &td->security_identifier);
3277         if (sid_encoded == NULL) {
3278                 status = NT_STATUS_NO_MEMORY;
3279                 goto out;
3280         }
3281
3282         ok = samdb_is_pdc(state->ldb);
3283         if (!ok) {
3284                 DBG_ERR("Adding TDO is only allowed on a PDC.\n");
3285                 TALLOC_FREE(tmp_ctx);
3286                 status = NT_STATUS_INVALID_DOMAIN_ROLE;
3287                 goto out;
3288         }
3289
3290         status = dsdb_trust_search_tdo(state->ldb,
3291                                        td->netbios_name,
3292                                        td->domain_name,
3293                                        attrs,
3294                                        tmp_ctx,
3295                                        &msg);
3296         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3297                 DBG_ERR("dsdb_trust_search_tdo returned %s\n",
3298                         nt_errstr(status));
3299                 status = NT_STATUS_INVALID_DOMAIN_STATE;
3300                 goto out;
3301         }
3302
3303         ret = ldb_transaction_start(state->ldb);
3304         if (ret != LDB_SUCCESS) {
3305                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3306                 goto out;
3307         }
3308         in_txn = true;
3309
3310         msg = ldb_msg_new(tmp_ctx);
3311         if (msg == NULL) {
3312                 status = NT_STATUS_NO_MEMORY;
3313                 goto out;
3314         }
3315
3316         msg->dn = samdb_system_container_dn(state->ldb, tmp_ctx);
3317         if (msg->dn == NULL) {
3318                 status = NT_STATUS_NO_MEMORY;
3319                 goto out;
3320         }
3321
3322         ok = ldb_dn_add_child_fmt(msg->dn, "cn=%s", td->domain_name);
3323         if (!ok) {
3324                 status = NT_STATUS_NO_MEMORY;
3325                 goto out;
3326         }
3327
3328         ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
3329         if (ret != LDB_SUCCESS) {
3330                 status = NT_STATUS_NO_MEMORY;
3331                 goto out;
3332         }
3333
3334         ret = ldb_msg_add_string(msg, "flatname", td->netbios_name);
3335         if (ret != LDB_SUCCESS) {
3336                 status = NT_STATUS_NO_MEMORY;
3337                 goto out;
3338         }
3339
3340         ret = ldb_msg_add_string(msg, "trustPartner", td->domain_name);
3341         if (ret != LDB_SUCCESS) {
3342                 status = NT_STATUS_NO_MEMORY;
3343                 goto out;
3344         }
3345
3346         ret = samdb_msg_add_dom_sid(state->ldb,
3347                                     tmp_ctx,
3348                                     msg,
3349                                     "securityIdentifier",
3350                                     &td->security_identifier);
3351         if (ret != LDB_SUCCESS) {
3352                 status = NT_STATUS_NO_MEMORY;
3353                 goto out;
3354         }
3355
3356         ret = samdb_msg_add_int(state->ldb,
3357                                 tmp_ctx,
3358                                 msg,
3359                                 "trustType",
3360                                 td->trust_type);
3361         if (ret != LDB_SUCCESS) {
3362                 status = NT_STATUS_NO_MEMORY;
3363                 goto out;
3364         }
3365
3366         ret = samdb_msg_add_int(state->ldb,
3367                                 tmp_ctx,
3368                                 msg,
3369                                 "trustAttributes",
3370                                 td->trust_attributes);
3371         if (ret != LDB_SUCCESS) {
3372                 status =NT_STATUS_NO_MEMORY;
3373                 goto out;
3374         }
3375
3376         ret = samdb_msg_add_int(state->ldb,
3377                                 tmp_ctx,
3378                                 msg,
3379                                 "trustDirection",
3380                                 td->trust_direction);
3381         if (ret != LDB_SUCCESS) {
3382                 status = NT_STATUS_NO_MEMORY;
3383                 goto out;
3384         }
3385
3386         if (td->trust_auth_incoming.data != NULL) {
3387                 ret = ldb_msg_add_value(msg,
3388                                         "trustAuthIncoming",
3389                                         &td->trust_auth_incoming,
3390                                         NULL);
3391                 if (ret != LDB_SUCCESS) {
3392                         status = NT_STATUS_NO_MEMORY;
3393                         goto out;
3394                 }
3395         }
3396         if (td->trust_auth_outgoing.data != NULL) {
3397                 ret = ldb_msg_add_value(msg,
3398                                         "trustAuthOutgoing",
3399                                         &td->trust_auth_outgoing,
3400                                         NULL);
3401                 if (ret != LDB_SUCCESS) {
3402                         status = NT_STATUS_NO_MEMORY;
3403                         goto out;
3404                 }
3405         }
3406
3407         /* create the trusted_domain */
3408         ret = ldb_add(state->ldb, msg);
3409         switch (ret) {
3410         case  LDB_SUCCESS:
3411                 break;
3412
3413         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
3414                 DBG_ERR("Failed to create trusted domain record %s: %s\n",
3415                         ldb_dn_get_linearized(msg->dn),
3416                         ldb_errstring(state->ldb));
3417                 status = NT_STATUS_DOMAIN_EXISTS;
3418                 goto out;
3419
3420         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3421                 DBG_ERR("Failed to create trusted domain record %s: %s\n",
3422                         ldb_dn_get_linearized(msg->dn),
3423                         ldb_errstring(state->ldb));
3424                 status = NT_STATUS_ACCESS_DENIED;
3425                 goto out;
3426
3427         default:
3428                 DBG_ERR("Failed to create trusted domain record %s: %s\n",
3429                         ldb_dn_get_linearized(msg->dn),
3430                         ldb_errstring(state->ldb));
3431                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3432                 goto out;
3433         }
3434
3435         ndr_err = ndr_pull_struct_blob(
3436                 &td->trust_auth_outgoing,
3437                 tmp_ctx,
3438                 &taiob,
3439                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
3440         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3441                 status = ndr_map_error2ntstatus(ndr_err);
3442                 goto out;
3443         }
3444
3445         if (td->trust_direction == LSA_TRUST_DIRECTION_INBOUND) {
3446                 status = add_trust_user(tmp_ctx,
3447                                         state->ldb,
3448                                         base_dn,
3449                                         td->netbios_name,
3450                                         &taiob);
3451                 if (!NT_STATUS_IS_OK(status)) {
3452                         goto out;
3453                 }
3454         }
3455
3456         ret = ldb_transaction_commit(state->ldb);
3457         if (ret != LDB_SUCCESS) {
3458                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3459         }
3460         in_txn = false;
3461
3462         /*
3463          * TODO: Notify winbindd that we have a new trust
3464          */
3465
3466         status = NT_STATUS_OK;
3467
3468 out:
3469         if (in_txn) {
3470                 ldb_transaction_cancel(state->ldb);
3471         }
3472         TALLOC_FREE(tmp_ctx);
3473         return status;
3474 }
3475
3476 static NTSTATUS delete_trust_user(TALLOC_CTX *mem_ctx,
3477                                   struct pdb_samba_dsdb_state *state,
3478                                   const char *trust_user)
3479 {
3480         const char *attrs[] = { "userAccountControl", NULL };
3481         struct ldb_message **msgs;
3482         uint32_t uac;
3483         int ret;
3484
3485         ret = gendb_search(state->ldb,
3486                            mem_ctx,
3487                            ldb_get_default_basedn(state->ldb),
3488                            &msgs,
3489                            attrs,
3490                            "samAccountName=%s$",
3491                            trust_user);
3492         if (ret > 1) {
3493                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3494         }
3495
3496         if (ret == 0) {
3497                 return NT_STATUS_OK;
3498         }
3499
3500         uac = ldb_msg_find_attr_as_uint(msgs[0],
3501                                         "userAccountControl",
3502                                         0);
3503         if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3504                 return NT_STATUS_OBJECT_NAME_COLLISION;
3505         }
3506
3507         ret = ldb_delete(state->ldb, msgs[0]->dn);
3508         switch (ret) {
3509         case LDB_SUCCESS:
3510                 break;
3511         case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3512                 return NT_STATUS_ACCESS_DENIED;
3513         default:
3514                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3515         }
3516
3517         return NT_STATUS_OK;
3518 }
3519
3520 static NTSTATUS pdb_samba_dsdb_del_trusted_domain(struct pdb_methods *methods,
3521                                                   const char *domain)
3522 {
3523         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3524                 methods->private_data, struct pdb_samba_dsdb_state);
3525         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3526         struct pdb_trusted_domain *td = NULL;
3527         struct ldb_dn *tdo_dn = NULL;
3528         bool in_txn = false;
3529         NTSTATUS status;
3530         int ret;
3531         bool ok;
3532
3533         status = pdb_samba_dsdb_get_trusted_domain(methods,
3534                                                    tmp_ctx,
3535                                                    domain,
3536                                                    &td);
3537         if (!NT_STATUS_IS_OK(status)) {
3538                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3539                         DBG_ERR("Searching TDO for %s returned %s\n",
3540                                 domain, nt_errstr(status));
3541                         return status;
3542                 }
3543                 DBG_NOTICE("No TDO object for %s\n", domain);
3544                 return NT_STATUS_OK;
3545         }
3546
3547         tdo_dn = samdb_system_container_dn(state->ldb, tmp_ctx);
3548         if (tdo_dn == NULL) {
3549                 status = NT_STATUS_NO_MEMORY;
3550                 goto out;
3551         }
3552
3553         ok = ldb_dn_add_child_fmt(tdo_dn, "cn=%s", domain);
3554         if (!ok) {
3555                 TALLOC_FREE(tmp_ctx);
3556                 status = NT_STATUS_NO_MEMORY;
3557                 goto out;
3558         }
3559
3560         ret = ldb_transaction_start(state->ldb);
3561         if (ret != LDB_SUCCESS) {
3562                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3563                 goto out;
3564         }
3565         in_txn = true;
3566
3567         ret = ldb_delete(state->ldb, tdo_dn);
3568         if (ret != LDB_SUCCESS) {
3569                 status = NT_STATUS_INVALID_HANDLE;
3570                 goto out;
3571         }
3572
3573         if (td->trust_direction == LSA_TRUST_DIRECTION_INBOUND) {
3574                 status = delete_trust_user(tmp_ctx, state, domain);
3575                 if (!NT_STATUS_IS_OK(status)) {
3576                         goto out;
3577                 }
3578         }
3579
3580         ret = ldb_transaction_commit(state->ldb);
3581         if (ret != LDB_SUCCESS) {
3582                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3583                 goto out;
3584         }
3585         in_txn = false;
3586
3587         status = NT_STATUS_OK;
3588
3589 out:
3590         if (in_txn) {
3591                 ldb_transaction_cancel(state->ldb);
3592         }
3593         TALLOC_FREE(tmp_ctx);
3594
3595         return status;
3596 }
3597
3598 static NTSTATUS pdb_samba_dsdb_enum_trusted_domains(struct pdb_methods *m,
3599                                                     TALLOC_CTX *mem_ctx,
3600                                                     uint32_t *_num_domains,
3601                                                     struct pdb_trusted_domain ***_domains)
3602 {
3603         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3604                 m->private_data, struct pdb_samba_dsdb_state);
3605         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3606         const char * const attrs[] = {
3607                 "securityIdentifier",
3608                 "flatName",
3609                 "trustPartner",
3610                 "trustAuthOutgoing",
3611                 "trustAuthIncoming",
3612                 "trustAttributes",
3613                 "trustDirection",
3614                 "trustType",
3615                 "trustPosixOffset",
3616                 "msDS-SupportedEncryptionTypes",
3617                 "msDS-TrustForestTrustInfo",
3618                 NULL
3619         };
3620         struct ldb_result *res = NULL;
3621         unsigned int i;
3622         struct pdb_trusted_domain **domains = NULL;
3623         NTSTATUS status;
3624         uint32_t di = 0;
3625
3626         *_num_domains = 0;
3627         *_domains = NULL;
3628
3629         status = dsdb_trust_search_tdos(state->ldb, NULL,
3630                                         attrs, tmp_ctx, &res);
3631         if (!NT_STATUS_IS_OK(status)) {
3632                 DBG_ERR("dsdb_trust_search_tdos() - %s\n", nt_errstr(status));
3633                 TALLOC_FREE(tmp_ctx);
3634                 return status;
3635         }
3636
3637         if (res->count == 0) {
3638                 TALLOC_FREE(tmp_ctx);
3639                 return NT_STATUS_OK;
3640         }
3641
3642         domains = talloc_zero_array(tmp_ctx, struct pdb_trusted_domain *,
3643                                     res->count);
3644         if (domains == NULL) {
3645                 TALLOC_FREE(tmp_ctx);
3646                 return NT_STATUS_NO_MEMORY;
3647         }
3648
3649         for (i = 0; i < res->count; i++) {
3650                 struct ldb_message *msg = res->msgs[i];
3651                 struct pdb_trusted_domain *d = NULL;
3652
3653                 status = pdb_samba_dsdb_msg_to_trusted_domain(msg, domains, &d);
3654                 if (!NT_STATUS_IS_OK(status)) {
3655                         DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain() - %s\n",
3656                                 nt_errstr(status));
3657                         TALLOC_FREE(tmp_ctx);
3658                         return status;
3659                 }
3660
3661                 domains[di++] = d;
3662         }
3663
3664         domains = talloc_realloc(domains, domains, struct pdb_trusted_domain *,
3665                                  di);
3666         *_domains = talloc_move(mem_ctx, &domains);
3667         *_num_domains = di;
3668         TALLOC_FREE(tmp_ctx);
3669         return NT_STATUS_OK;
3670 }
3671
3672 static bool pdb_samba_dsdb_is_responsible_for_wellknown(struct pdb_methods *m)
3673 {
3674         return true;
3675 }
3676
3677 static bool pdb_samba_dsdb_is_responsible_for_everything_else(struct pdb_methods *m)
3678 {
3679         return true;
3680 }
3681
3682 static void pdb_samba_dsdb_init_methods(struct pdb_methods *m)
3683 {
3684         m->name = "samba_dsdb";
3685         m->get_domain_info = pdb_samba_dsdb_get_domain_info;
3686         m->getsampwnam = pdb_samba_dsdb_getsampwnam;
3687         m->getsampwsid = pdb_samba_dsdb_getsampwsid;
3688         m->create_user = pdb_samba_dsdb_create_user;
3689         m->delete_user = pdb_samba_dsdb_delete_user;
3690         m->add_sam_account = pdb_samba_dsdb_add_sam_account;
3691         m->update_sam_account = pdb_samba_dsdb_update_sam_account;
3692         m->delete_sam_account = pdb_samba_dsdb_delete_sam_account;
3693         m->rename_sam_account = pdb_samba_dsdb_rename_sam_account;
3694         m->update_login_attempts = pdb_samba_dsdb_update_login_attempts;
3695         m->getgrsid = pdb_samba_dsdb_getgrsid;
3696         m->getgrgid = pdb_samba_dsdb_getgrgid;
3697         m->getgrnam = pdb_samba_dsdb_getgrnam;
3698         m->create_dom_group = pdb_samba_dsdb_create_dom_group;
3699         m->delete_dom_group = pdb_samba_dsdb_delete_dom_group;
3700         m->add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry;
3701         m->update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry;
3702         m->delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry;
3703         m->enum_group_mapping = pdb_samba_dsdb_enum_group_mapping;
3704         m->enum_group_members = pdb_samba_dsdb_enum_group_members;
3705         m->enum_group_memberships = pdb_samba_dsdb_enum_group_memberships;
3706         m->set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group;
3707         m->add_groupmem = pdb_samba_dsdb_add_groupmem;
3708         m->del_groupmem = pdb_samba_dsdb_del_groupmem;
3709         m->create_alias = pdb_samba_dsdb_create_alias;
3710         m->delete_alias = pdb_samba_dsdb_delete_alias;
3711         m->get_aliasinfo = pdb_default_get_aliasinfo;
3712         m->add_aliasmem = pdb_samba_dsdb_add_aliasmem;
3713         m->del_aliasmem = pdb_samba_dsdb_del_aliasmem;
3714         m->enum_aliasmem = pdb_samba_dsdb_enum_aliasmem;
3715         m->enum_alias_memberships = pdb_samba_dsdb_enum_alias_memberships;
3716         m->lookup_rids = pdb_samba_dsdb_lookup_rids;
3717         m->lookup_names = pdb_samba_dsdb_lookup_names;
3718         m->get_account_policy = pdb_samba_dsdb_get_account_policy;
3719         m->set_account_policy = pdb_samba_dsdb_set_account_policy;
3720         m->get_seq_num = pdb_samba_dsdb_get_seq_num;
3721         m->search_users = pdb_samba_dsdb_search_users;
3722         m->search_groups = pdb_samba_dsdb_search_groups;
3723         m->search_aliases = pdb_samba_dsdb_search_aliases;
3724         m->id_to_sid = pdb_samba_dsdb_id_to_sid;
3725         m->sid_to_id = pdb_samba_dsdb_sid_to_id;
3726         m->capabilities = pdb_samba_dsdb_capabilities;
3727         m->new_rid = pdb_samba_dsdb_new_rid;
3728         m->get_trusteddom_pw = pdb_samba_dsdb_get_trusteddom_pw;
3729         m->get_trusteddom_creds = pdb_samba_dsdb_get_trusteddom_creds;
3730         m->set_trusteddom_pw = pdb_samba_dsdb_set_trusteddom_pw;
3731         m->del_trusteddom_pw = pdb_samba_dsdb_del_trusteddom_pw;
3732         m->enum_trusteddoms = pdb_samba_dsdb_enum_trusteddoms;
3733         m->get_trusted_domain = pdb_samba_dsdb_get_trusted_domain;
3734         m->get_trusted_domain_by_sid = pdb_samba_dsdb_get_trusted_domain_by_sid;
3735         m->set_trusted_domain = pdb_samba_dsdb_set_trusted_domain;
3736         m->del_trusted_domain = pdb_samba_dsdb_del_trusted_domain;
3737         m->enum_trusted_domains = pdb_samba_dsdb_enum_trusted_domains;
3738         m->is_responsible_for_wellknown =
3739                                 pdb_samba_dsdb_is_responsible_for_wellknown;
3740         m->is_responsible_for_everything_else =
3741                                 pdb_samba_dsdb_is_responsible_for_everything_else;
3742 }
3743
3744 static void free_private_data(void **vp)
3745 {
3746         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3747                 *vp, struct pdb_samba_dsdb_state);
3748         talloc_unlink(state, state->ldb);
3749         return;
3750 }
3751
3752 static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m)
3753 {
3754         struct pdb_domain_info *dom_info;
3755         struct dom_sid stored_sid;
3756         struct GUID stored_guid;
3757         bool sid_exists_and_matches = false;
3758         bool guid_exists_and_matches = false;
3759         bool ret;
3760
3761         dom_info = pdb_samba_dsdb_get_domain_info(m, m);
3762         if (!dom_info) {
3763                 return NT_STATUS_UNSUCCESSFUL;
3764         }
3765
3766         ret = secrets_fetch_domain_sid(dom_info->name, &stored_sid);
3767         if (ret) {
3768                 if (dom_sid_equal(&stored_sid, &dom_info->sid)) {
3769                         sid_exists_and_matches = true;
3770                 }
3771         }
3772
3773         if (sid_exists_and_matches == false) {
3774                 secrets_clear_domain_protection(dom_info->name);
3775                 ret = secrets_store_domain_sid(dom_info->name,
3776                                                &dom_info->sid);
3777                 ret &= secrets_mark_domain_protected(dom_info->name);
3778                 if (!ret) {
3779                         goto done;
3780                 }
3781         }
3782
3783         ret = secrets_fetch_domain_guid(dom_info->name, &stored_guid);
3784         if (ret) {
3785                 if (GUID_equal(&stored_guid, &dom_info->guid)) {
3786                         guid_exists_and_matches = true;
3787                 }
3788         }
3789
3790         if (guid_exists_and_matches == false) {
3791                 secrets_clear_domain_protection(dom_info->name);
3792                 ret = secrets_store_domain_guid(dom_info->name,
3793                                                &dom_info->guid);
3794                 ret &= secrets_mark_domain_protected(dom_info->name);
3795                 if (!ret) {
3796                         goto done;
3797                 }
3798         }
3799
3800 done:
3801         TALLOC_FREE(dom_info);
3802         if (!ret) {
3803                 return NT_STATUS_UNSUCCESSFUL;
3804         }
3805         return NT_STATUS_OK;
3806 }
3807
3808 static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
3809                              const char *location)
3810 {
3811         struct pdb_methods *m;
3812         struct pdb_samba_dsdb_state *state;
3813         NTSTATUS status;
3814         char *errstring = NULL;
3815         int ret;
3816
3817         if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
3818                 return status;
3819         }
3820
3821         state = talloc_zero(m, struct pdb_samba_dsdb_state);
3822         if (state == NULL) {
3823                 goto nomem;
3824         }
3825         m->private_data = state;
3826         m->free_private_data = free_private_data;
3827         pdb_samba_dsdb_init_methods(m);
3828
3829         state->ev = s4_event_context_init(state);
3830         if (!state->ev) {
3831                 DEBUG(0, ("s4_event_context_init failed\n"));
3832                 goto nomem;
3833         }
3834
3835         state->lp_ctx = loadparm_init_s3(state, loadparm_s3_helpers());
3836         if (state->lp_ctx == NULL) {
3837                 DEBUG(0, ("loadparm_init_s3 failed\n"));
3838                 goto nomem;
3839         }
3840
3841         if (location == NULL) {
3842                 location = "sam.ldb";
3843         }
3844
3845         ret = samdb_connect_url(state,
3846                                 state->ev,
3847                                 state->lp_ctx,
3848                                 system_session(state->lp_ctx),
3849                                 0,
3850                                 location,
3851                                 NULL,
3852                                 &state->ldb,
3853                                 &errstring);
3854
3855         if (!state->ldb) {
3856                 DEBUG(0, ("samdb_connect failed: %s: %s\n",
3857                           errstring, ldb_strerror(ret)));
3858                 status = NT_STATUS_INTERNAL_ERROR;
3859                 goto fail;
3860         }
3861
3862         state->idmap_ctx = idmap_init(state, state->ev,
3863                                       state->lp_ctx);
3864         if (!state->idmap_ctx) {
3865                 DEBUG(0, ("idmap failed\n"));
3866                 status = NT_STATUS_INTERNAL_ERROR;
3867                 goto fail;
3868         }
3869
3870         status = pdb_samba_dsdb_init_secrets(m);
3871         if (!NT_STATUS_IS_OK(status)) {
3872                 DEBUG(10, ("pdb_samba_dsdb_init_secrets failed!\n"));
3873                 goto fail;
3874         }
3875
3876         *pdb_method = m;
3877         return NT_STATUS_OK;
3878 nomem:
3879         status = NT_STATUS_NO_MEMORY;
3880 fail:
3881         TALLOC_FREE(m);
3882         return status;
3883 }
3884
3885 NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *);
3886 NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *ctx)
3887 {
3888         NTSTATUS status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba_dsdb",
3889                                               pdb_init_samba_dsdb);
3890         if (!NT_STATUS_IS_OK(status)) {
3891                 return status;
3892         }
3893         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4",
3894                                    pdb_init_samba_dsdb);
3895 }