s3-libads: use ldap_init_fd() to initialize a ldap session if possible
[bbaumbach/samba-autobuild/.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 arbitary SIDs (ie, we must ensrue
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 exptected to be used
884  * with auth_samba_dsdb, and this is responible 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", 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", 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         }
1138         rc = ldb_delete(state->ldb, dn);
1139         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1140                 talloc_free(tmp_ctx);
1141                 ldb_transaction_cancel(state->ldb);
1142                 return NT_STATUS_NO_SUCH_GROUP;
1143         } else if (rc != LDB_SUCCESS) {
1144                 DEBUG(10, ("ldb_delete failed %s\n",
1145                            ldb_errstring(state->ldb)));
1146                 ldb_transaction_cancel(state->ldb);
1147                 return NT_STATUS_LDAP(rc);
1148         }
1149
1150         if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1151                 DEBUG(0, ("Unable to commit transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1152                 return NT_STATUS_INTERNAL_ERROR;
1153         }
1154         return NT_STATUS_OK;
1155 }
1156
1157 static NTSTATUS pdb_samba_dsdb_add_group_mapping_entry(struct pdb_methods *m,
1158                                                 GROUP_MAP *map)
1159 {
1160         return NT_STATUS_NOT_IMPLEMENTED;
1161 }
1162
1163 static NTSTATUS pdb_samba_dsdb_update_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_delete_group_mapping_entry(struct pdb_methods *m,
1170                                                    struct dom_sid sid)
1171 {
1172         return NT_STATUS_NOT_IMPLEMENTED;
1173 }
1174
1175 static NTSTATUS pdb_samba_dsdb_enum_group_mapping(struct pdb_methods *m,
1176                                            const struct dom_sid *sid,
1177                                            enum lsa_SidType sid_name_use,
1178                                            GROUP_MAP ***pp_rmap,
1179                                            size_t *p_num_entries,
1180                                            bool unix_only)
1181 {
1182         return NT_STATUS_NOT_IMPLEMENTED;
1183 }
1184
1185 static NTSTATUS pdb_samba_dsdb_enum_group_members(struct pdb_methods *m,
1186                                            TALLOC_CTX *mem_ctx,
1187                                            const struct dom_sid *group,
1188                                            uint32_t **pmembers,
1189                                            size_t *pnum_members)
1190 {
1191         unsigned int i, num_sids, num_members;
1192         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1193                 m->private_data, struct pdb_samba_dsdb_state);
1194         struct dom_sid *members_as_sids;
1195         struct dom_sid *dom_sid;
1196         uint32_t *members;
1197         struct ldb_dn *dn;
1198         NTSTATUS status;
1199         struct dom_sid_buf buf;
1200
1201         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1202         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1203
1204         dn = ldb_dn_new_fmt(
1205                 tmp_ctx,
1206                 state->ldb,
1207                 "<SID=%s>",
1208                 dom_sid_str_buf(group, &buf));
1209         if (!dn || !ldb_dn_validate(dn)) {
1210                 return NT_STATUS_NO_MEMORY;
1211         }
1212
1213         status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
1214         if (!NT_STATUS_IS_OK(status)) {
1215                 talloc_free(tmp_ctx);
1216                 return status;
1217         }
1218         status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
1219         if (!NT_STATUS_IS_OK(status)) {
1220                 talloc_free(tmp_ctx);
1221                 return status;
1222         }
1223
1224         *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
1225         if (*pmembers == NULL) {
1226                 TALLOC_FREE(tmp_ctx);
1227                 return NT_STATUS_NO_MEMORY;
1228         }
1229         num_members = 0;
1230
1231         for (i = 0; i < num_sids; i++) {
1232                 if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
1233                         continue;
1234                 }
1235                 status = dom_sid_split_rid(NULL, &members_as_sids[i],
1236                                            NULL, &members[num_members]);
1237                 if (!NT_STATUS_IS_OK(status)) {
1238                         talloc_free(tmp_ctx);
1239                         return status;
1240                 }
1241                 num_members++;
1242         }
1243         *pnum_members = num_members;
1244         return NT_STATUS_OK;
1245 }
1246
1247 /* Just convert the primary group SID into a group */
1248 static NTSTATUS fake_enum_group_memberships(struct pdb_samba_dsdb_state *state,
1249                                             TALLOC_CTX *mem_ctx,
1250                                             struct samu *user,
1251                                             struct dom_sid **pp_sids,
1252                                             gid_t **pp_gids,
1253                                             uint32_t *p_num_groups)
1254 {
1255         NTSTATUS status;
1256         size_t num_groups = 0;
1257         struct dom_sid *group_sids = NULL;
1258         gid_t *gids = NULL;
1259         TALLOC_CTX *tmp_ctx;
1260
1261         tmp_ctx = talloc_new(mem_ctx);
1262         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1263
1264         if (user->group_sid) {
1265                 struct id_map *id_maps[2];
1266                 struct id_map id_map;
1267
1268                 num_groups = 1;
1269
1270                 group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
1271                 if (group_sids == NULL) {
1272                         talloc_free(tmp_ctx);
1273                         return NT_STATUS_NO_MEMORY;
1274                 }
1275                 gids = talloc_array(tmp_ctx, gid_t, num_groups);
1276                 if (gids == NULL) {
1277                         talloc_free(tmp_ctx);
1278                         return NT_STATUS_NO_MEMORY;
1279                 }
1280
1281                 group_sids[0] = *user->group_sid;
1282
1283                 ZERO_STRUCT(id_map);
1284                 id_map.sid = &group_sids[0];
1285                 id_maps[0] = &id_map;
1286                 id_maps[1] = NULL;
1287
1288                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1289                 if (!NT_STATUS_IS_OK(status)) {
1290                         talloc_free(tmp_ctx);
1291                         return status;
1292                 }
1293                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1294                         gids[0] = id_map.xid.id;
1295                 } else {
1296                         struct dom_sid_buf buf1, buf2;
1297                         DEBUG(1, (__location__
1298                                   "Group %s, of which %s is a member, could not be converted to a GID\n",
1299                                   dom_sid_str_buf(&group_sids[0], &buf1),
1300                                   dom_sid_str_buf(&user->user_sid, &buf2)));
1301                         talloc_free(tmp_ctx);
1302                         /* We must error out, otherwise a user might
1303                          * avoid a DENY acl based on a group they
1304                          * missed out on */
1305                         return NT_STATUS_NO_SUCH_GROUP;
1306                 }
1307         }
1308
1309         *pp_sids = talloc_steal(mem_ctx, group_sids);
1310         *pp_gids = talloc_steal(mem_ctx, gids);
1311         *p_num_groups = num_groups;
1312         talloc_free(tmp_ctx);
1313         return NT_STATUS_OK;
1314 }
1315
1316 static NTSTATUS pdb_samba_dsdb_enum_group_memberships(struct pdb_methods *m,
1317                                                TALLOC_CTX *mem_ctx,
1318                                                struct samu *user,
1319                                                struct dom_sid **pp_sids,
1320                                                gid_t **pp_gids,
1321                                                uint32_t *p_num_groups)
1322 {
1323         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1324                 m->private_data, struct pdb_samba_dsdb_state);
1325         struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
1326                 m, user);
1327         const char *attrs[] = { "tokenGroups", NULL};
1328         struct ldb_message *tokengroups_msg;
1329         struct ldb_message_element *tokengroups;
1330         int i, rc;
1331         NTSTATUS status;
1332         unsigned int count = 0;
1333         size_t num_groups;
1334         struct dom_sid *group_sids;
1335         gid_t *gids;
1336         TALLOC_CTX *tmp_ctx;
1337
1338         if (msg == NULL) {
1339                 /* Fake up some things here */
1340                 return fake_enum_group_memberships(state,
1341                                                    mem_ctx,
1342                                                    user, pp_sids,
1343                                                    pp_gids, p_num_groups);
1344         }
1345
1346         tmp_ctx = talloc_new(mem_ctx);
1347         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1348
1349         rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
1350
1351         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1352                 talloc_free(tmp_ctx);
1353                 return NT_STATUS_NO_SUCH_USER;
1354         } else if (rc != LDB_SUCCESS) {
1355                 DEBUG(10, ("dsdb_search_one failed %s\n",
1356                            ldb_errstring(state->ldb)));
1357                 talloc_free(tmp_ctx);
1358                 return NT_STATUS_LDAP(rc);
1359         }
1360
1361         tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
1362
1363         if (tokengroups) {
1364                 count = tokengroups->num_values;
1365         }
1366
1367         group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
1368         if (group_sids == NULL) {
1369                 talloc_free(tmp_ctx);
1370                 return NT_STATUS_NO_MEMORY;
1371         }
1372         gids = talloc_array(tmp_ctx, gid_t, count);
1373         if (gids == NULL) {
1374                 talloc_free(tmp_ctx);
1375                 return NT_STATUS_NO_MEMORY;
1376         }
1377         num_groups = 0;
1378
1379         for (i=0; i<count; i++) {
1380                 struct id_map *id_maps[2];
1381                 struct id_map id_map;
1382                 struct ldb_val *v = &tokengroups->values[i];
1383                 enum ndr_err_code ndr_err
1384                         = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
1385                                                (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1386                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1387                         talloc_free(tmp_ctx);
1388                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1389                 }
1390
1391                 ZERO_STRUCT(id_map);
1392                 id_map.sid = &group_sids[num_groups];
1393                 id_maps[0] = &id_map;
1394                 id_maps[1] = NULL;
1395
1396                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1397                 if (!NT_STATUS_IS_OK(status)) {
1398                         talloc_free(tmp_ctx);
1399                         return status;
1400                 }
1401                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1402                         gids[num_groups] = id_map.xid.id;
1403                 } else {
1404                         struct dom_sid_buf buf;
1405                         DEBUG(1, (__location__
1406                                   "Group %s, of which %s is a member, could not be converted to a GID\n",
1407                                   dom_sid_str_buf(&group_sids[num_groups],
1408                                                   &buf),
1409                                   ldb_dn_get_linearized(msg->dn)));
1410                         talloc_free(tmp_ctx);
1411                         /* We must error out, otherwise a user might
1412                          * avoid a DENY acl based on a group they
1413                          * missed out on */
1414                         return NT_STATUS_NO_SUCH_GROUP;
1415                 }
1416
1417                 num_groups += 1;
1418                 if (num_groups == count) {
1419                         break;
1420                 }
1421         }
1422
1423         *pp_sids = talloc_steal(mem_ctx, group_sids);
1424         *pp_gids = talloc_steal(mem_ctx, gids);
1425         *p_num_groups = num_groups;
1426         talloc_free(tmp_ctx);
1427         return NT_STATUS_OK;
1428 }
1429
1430 static NTSTATUS pdb_samba_dsdb_set_unix_primary_group(struct pdb_methods *m,
1431                                                TALLOC_CTX *mem_ctx,
1432                                                struct samu *user)
1433 {
1434         return NT_STATUS_NOT_IMPLEMENTED;
1435 }
1436
1437 static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid(struct pdb_methods *m,
1438                                                TALLOC_CTX *mem_ctx,
1439                                                const struct dom_sid *groupsid,
1440                                                const struct dom_sid *membersid,
1441                                                int mod_op)
1442 {
1443         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1444                 m->private_data, struct pdb_samba_dsdb_state);
1445         struct ldb_message *msg;
1446         int ret;
1447         struct ldb_message_element *el;
1448         struct dom_sid_buf buf;
1449         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1450         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1451         msg = ldb_msg_new(tmp_ctx);
1452         if (msg == NULL) {
1453                 TALLOC_FREE(tmp_ctx);
1454                 return NT_STATUS_NO_MEMORY;
1455         }
1456
1457         msg->dn = ldb_dn_new_fmt(
1458                 msg,
1459                 state->ldb,
1460                 "<SID=%s>",
1461                 dom_sid_str_buf(groupsid, &buf));
1462         if (!msg->dn || !ldb_dn_validate(msg->dn)) {
1463                 talloc_free(tmp_ctx);
1464                 return NT_STATUS_NO_MEMORY;
1465         }
1466         ret = ldb_msg_add_fmt(
1467                 msg,
1468                 "member",
1469                 "<SID=%s>",
1470                 dom_sid_str_buf(membersid, &buf));
1471         if (ret != LDB_SUCCESS) {
1472                 talloc_free(tmp_ctx);
1473                 return NT_STATUS_NO_MEMORY;
1474         }
1475         el = ldb_msg_find_element(msg, "member");
1476         el->flags = mod_op;
1477
1478         /* No need for transactions here, the ldb auto-transaction
1479          * code will handle things for the single operation */
1480         ret = ldb_modify(state->ldb, msg);
1481         talloc_free(tmp_ctx);
1482         if (ret != LDB_SUCCESS) {
1483                 DEBUG(10, ("ldb_modify failed: %s\n",
1484                            ldb_errstring(state->ldb)));
1485                 if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
1486                         return NT_STATUS_MEMBER_IN_GROUP;
1487                 }
1488                 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1489                         return NT_STATUS_MEMBER_NOT_IN_GROUP;
1490                 }
1491                 return NT_STATUS_LDAP(ret);
1492         }
1493
1494         return NT_STATUS_OK;
1495 }
1496
1497 static NTSTATUS pdb_samba_dsdb_mod_groupmem(struct pdb_methods *m,
1498                                      TALLOC_CTX *mem_ctx,
1499                                      uint32_t grouprid, uint32_t memberrid,
1500                                      int mod_op)
1501 {
1502         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1503                 m->private_data, struct pdb_samba_dsdb_state);
1504         const struct dom_sid *dom_sid, *groupsid, *membersid;
1505         NTSTATUS status;
1506         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1507         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1508
1509         dom_sid = samdb_domain_sid(state->ldb);
1510
1511         groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
1512         if (groupsid == NULL) {
1513                 TALLOC_FREE(tmp_ctx);
1514                 return NT_STATUS_NO_MEMORY;
1515         }
1516         membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
1517         if (membersid == NULL) {
1518                 TALLOC_FREE(tmp_ctx);
1519                 return NT_STATUS_NO_MEMORY;
1520         }
1521         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
1522         talloc_free(tmp_ctx);
1523         return status;
1524 }
1525
1526 static NTSTATUS pdb_samba_dsdb_add_groupmem(struct pdb_methods *m,
1527                                      TALLOC_CTX *mem_ctx,
1528                                      uint32_t group_rid, uint32_t member_rid)
1529 {
1530         return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1531                                     LDB_FLAG_MOD_ADD);
1532 }
1533
1534 static NTSTATUS pdb_samba_dsdb_del_groupmem(struct pdb_methods *m,
1535                                      TALLOC_CTX *mem_ctx,
1536                                      uint32_t group_rid, uint32_t member_rid)
1537 {
1538         return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1539                                        LDB_FLAG_MOD_DELETE);
1540 }
1541
1542 static NTSTATUS pdb_samba_dsdb_create_alias(struct pdb_methods *m,
1543                                      const char *name, uint32_t *rid)
1544 {
1545         TALLOC_CTX *frame = talloc_stackframe();
1546         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1547                 m->private_data, struct pdb_samba_dsdb_state);
1548         struct dom_sid *sid;
1549
1550         struct ldb_dn *dn;
1551         NTSTATUS status;
1552
1553         /* Internally this uses transactions to ensure all the steps
1554          * happen or fail as one */
1555         status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
1556         if (!NT_STATUS_IS_OK(status)) {
1557                 TALLOC_FREE(frame);
1558         }
1559
1560         sid_peek_rid(sid, rid);
1561         TALLOC_FREE(frame);
1562         return NT_STATUS_OK;
1563 }
1564
1565 static NTSTATUS pdb_samba_dsdb_delete_alias(struct pdb_methods *m,
1566                                      const struct dom_sid *sid)
1567 {
1568         const char *attrs[] = { NULL };
1569         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1570                 m->private_data, struct pdb_samba_dsdb_state);
1571         struct ldb_message *msg;
1572         struct ldb_dn *dn;
1573         int rc;
1574         struct dom_sid_buf buf;
1575         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1576         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1577
1578         dn = ldb_dn_new_fmt(
1579                 tmp_ctx,
1580                 state->ldb,
1581                 "<SID=%s>",
1582                 dom_sid_str_buf(sid, &buf));
1583         if (!dn || !ldb_dn_validate(dn)) {
1584                 talloc_free(tmp_ctx);
1585                 return NT_STATUS_NO_MEMORY;
1586         }
1587
1588         if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1589                 DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(state->ldb)));
1590                 talloc_free(tmp_ctx);
1591                 return NT_STATUS_INTERNAL_ERROR;
1592         }
1593
1594         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
1595                              "(|(grouptype=%d)(grouptype=%d)))",
1596                              GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1597                              GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1598         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1599                 talloc_free(tmp_ctx);
1600                 ldb_transaction_cancel(state->ldb);
1601                 return NT_STATUS_NO_SUCH_ALIAS;
1602         }
1603         rc = ldb_delete(state->ldb, dn);
1604         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1605                 talloc_free(tmp_ctx);
1606                 ldb_transaction_cancel(state->ldb);
1607                 return NT_STATUS_NO_SUCH_ALIAS;
1608         } else if (rc != LDB_SUCCESS) {
1609                 DEBUG(10, ("ldb_delete failed %s\n",
1610                            ldb_errstring(state->ldb)));
1611                 ldb_transaction_cancel(state->ldb);
1612                 talloc_free(tmp_ctx);
1613                 return NT_STATUS_LDAP(rc);
1614         }
1615
1616         if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1617                 DEBUG(0, ("Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s\n",
1618                           ldb_errstring(state->ldb)));
1619                 talloc_free(tmp_ctx);
1620                 return NT_STATUS_INTERNAL_ERROR;
1621         }
1622
1623         talloc_free(tmp_ctx);
1624         return NT_STATUS_OK;
1625 }
1626
1627 #if 0
1628 static NTSTATUS pdb_samba_dsdb_set_aliasinfo(struct pdb_methods *m,
1629                                       const struct dom_sid *sid,
1630                                       struct acct_info *info)
1631 {
1632         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1633                 m->private_data, struct pdb_samba_dsdb_state);
1634         struct tldap_context *ld;
1635         const char *attrs[3] = { "objectSid", "description",
1636                                  "samAccountName" };
1637         struct ldb_message **msg;
1638         char *sidstr, *dn;
1639         int rc;
1640         struct tldap_mod *mods;
1641         int num_mods;
1642         bool ok;
1643
1644         ld = pdb_samba_dsdb_ld(state);
1645         if (ld == NULL) {
1646                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1647         }
1648
1649         sidstr = sid_binstring(talloc_tos(), sid);
1650         NT_STATUS_HAVE_NO_MEMORY(sidstr);
1651
1652         rc = pdb_samba_dsdb_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1653                                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1654                                 &msg, "(&(objectSid=%s)(objectclass=group)"
1655                                 "(|(grouptype=%d)(grouptype=%d)))",
1656                                 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1657                                 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1658         TALLOC_FREE(sidstr)
1659         if (rc != LDB_SUCCESS) {
1660                 DEBUG(10, ("ldap_search failed %s\n",
1661                            ldb_errstring(state->ldb)));
1662                 return NT_STATUS_LDAP(rc);
1663         }
1664         switch talloc_array_length(msg) {
1665         case 0:
1666                 return NT_STATUS_NO_SUCH_ALIAS;
1667         case 1:
1668                 break;
1669         default:
1670                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1671         }
1672
1673         if (!tldap_entry_dn(msg[0], &dn)) {
1674                 TALLOC_FREE(msg);
1675                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1676         }
1677
1678         mods = NULL;
1679         num_mods = 0;
1680         ok = true;
1681
1682         ok &= tldap_make_mod_fmt(
1683                 msg[0], msg, &num_mods, &mods, "description",
1684                 "%s", info->acct_desc);
1685         ok &= tldap_make_mod_fmt(
1686                 msg[0], msg, &num_mods, &mods, "samAccountName",
1687                 "%s", info->acct_name);
1688         if (!ok) {
1689                 TALLOC_FREE(msg);
1690                 return NT_STATUS_NO_MEMORY;
1691         }
1692         if (num_mods == 0) {
1693                 /* no change */
1694                 TALLOC_FREE(msg);
1695                 return NT_STATUS_OK;
1696         }
1697
1698         rc = tldap_modify(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
1699         TALLOC_FREE(msg);
1700         if (rc != LDB_SUCCESS) {
1701                 DEBUG(10, ("ldap_modify failed: %s\n",
1702                            ldb_errstring(state->ldb)));
1703                 return NT_STATUS_LDAP(rc);
1704         }
1705         return NT_STATUS_OK;
1706 }
1707 #endif
1708 static NTSTATUS pdb_samba_dsdb_add_aliasmem(struct pdb_methods *m,
1709                                      const struct dom_sid *alias,
1710                                      const struct dom_sid *member)
1711 {
1712         NTSTATUS status;
1713         TALLOC_CTX *frame = talloc_stackframe();
1714         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_ADD);
1715         talloc_free(frame);
1716         return status;
1717 }
1718
1719 static NTSTATUS pdb_samba_dsdb_del_aliasmem(struct pdb_methods *m,
1720                                      const struct dom_sid *alias,
1721                                      const struct dom_sid *member)
1722 {
1723         NTSTATUS status;
1724         TALLOC_CTX *frame = talloc_stackframe();
1725         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
1726         talloc_free(frame);
1727         return status;
1728 }
1729
1730 static NTSTATUS pdb_samba_dsdb_enum_aliasmem(struct pdb_methods *m,
1731                                       const struct dom_sid *alias,
1732                                       TALLOC_CTX *mem_ctx,
1733                                       struct dom_sid **pmembers,
1734                                       size_t *pnum_members)
1735 {
1736         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1737                 m->private_data, struct pdb_samba_dsdb_state);
1738         struct ldb_dn *dn;
1739         unsigned int num_members;
1740         NTSTATUS status;
1741         struct dom_sid_buf buf;
1742         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1743         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1744
1745         dn = ldb_dn_new_fmt(
1746                 tmp_ctx,
1747                 state->ldb,
1748                 "<SID=%s>",
1749                 dom_sid_str_buf(alias, &buf));
1750         if (!dn || !ldb_dn_validate(dn)) {
1751                 return NT_STATUS_NO_MEMORY;
1752         }
1753
1754         status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
1755         if (NT_STATUS_IS_OK(status)) {
1756                 *pnum_members = num_members;
1757         }
1758         talloc_free(tmp_ctx);
1759         return status;
1760 }
1761
1762 static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1763                                                TALLOC_CTX *mem_ctx,
1764                                                const struct dom_sid *domain_sid,
1765                                                const struct dom_sid *members,
1766                                                size_t num_members,
1767                                                uint32_t **palias_rids,
1768                                                size_t *pnum_alias_rids)
1769 {
1770         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1771                 m->private_data, struct pdb_samba_dsdb_state);
1772         uint32_t *alias_rids = NULL;
1773         size_t num_alias_rids = 0;
1774         int i;
1775         struct dom_sid *groupSIDs = NULL;
1776         unsigned int num_groupSIDs = 0;
1777         char *filter;
1778         NTSTATUS status;
1779         const char *sid_dn;
1780         DATA_BLOB sid_blob;
1781
1782         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1783         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1784         /*
1785          * TODO: Get the filter right so that we only get the aliases from
1786          * either the SAM or BUILTIN
1787          */
1788
1789         filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
1790                                  GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1791         if (filter == NULL) {
1792                 return NT_STATUS_NO_MEMORY;
1793         }
1794
1795         for (i = 0; i < num_members; i++) {
1796                 struct dom_sid_buf buf;
1797
1798                 sid_dn = talloc_asprintf(
1799                         tmp_ctx,
1800                         "<SID=%s>",
1801                         dom_sid_str_buf(&members[i], &buf));
1802                 if (sid_dn == NULL) {
1803                         TALLOC_FREE(tmp_ctx);
1804                         return NT_STATUS_NO_MEMORY;
1805                 }
1806
1807                 sid_blob = data_blob_string_const(sid_dn);
1808
1809                 status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1810                                                    tmp_ctx, &groupSIDs, &num_groupSIDs);
1811                 if (!NT_STATUS_IS_OK(status)) {
1812                         talloc_free(tmp_ctx);
1813                         return status;
1814                 }
1815         }
1816
1817         alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1818         if (alias_rids == NULL) {
1819                 talloc_free(tmp_ctx);
1820                 return NT_STATUS_NO_MEMORY;
1821         }
1822
1823         for (i=0; i<num_groupSIDs; i++) {
1824                 if (sid_peek_check_rid(domain_sid, &groupSIDs[i],
1825                                        &alias_rids[num_alias_rids])) {
1826                         num_alias_rids++;;
1827                 }
1828         }
1829
1830         *palias_rids = alias_rids;
1831         *pnum_alias_rids = num_alias_rids;
1832         return NT_STATUS_OK;
1833 }
1834
1835 static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1836                                     const struct dom_sid *domain_sid,
1837                                     int num_rids,
1838                                     uint32_t *rids,
1839                                     const char **names,
1840                                     enum lsa_SidType *lsa_attrs)
1841 {
1842         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1843                 m->private_data, struct pdb_samba_dsdb_state);
1844         NTSTATUS status;
1845
1846         TALLOC_CTX *tmp_ctx;
1847
1848         if (num_rids == 0) {
1849                 return NT_STATUS_NONE_MAPPED;
1850         }
1851
1852         tmp_ctx = talloc_stackframe();
1853         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1854
1855         status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1856         talloc_free(tmp_ctx);
1857         return status;
1858 }
1859
1860 static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1861                                      const struct dom_sid *domain_sid,
1862                                      int num_names,
1863                                      const char **pp_names,
1864                                      uint32_t *rids,
1865                                      enum lsa_SidType *attrs)
1866 {
1867         return NT_STATUS_NOT_IMPLEMENTED;
1868 }
1869
1870 static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1871                                            enum pdb_policy_type type,
1872                                            uint32_t *value)
1873 {
1874         return account_policy_get(type, value)
1875                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1876 }
1877
1878 static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1879                                            enum pdb_policy_type type,
1880                                            uint32_t value)
1881 {
1882         return account_policy_set(type, value)
1883                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1884 }
1885
1886 static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1887                                     time_t *seq_num_out)
1888 {
1889         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1890                 m->private_data, struct pdb_samba_dsdb_state);
1891         uint64_t seq_num;
1892         int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1893         if (ret == LDB_SUCCESS) {
1894                 *seq_num_out = seq_num;
1895                 return NT_STATUS_OK;
1896         } else {
1897                 return NT_STATUS_UNSUCCESSFUL;
1898         }
1899 }
1900
1901 struct pdb_samba_dsdb_search_state {
1902         uint32_t acct_flags;
1903         struct samr_displayentry *entries;
1904         uint32_t num_entries;
1905         ssize_t array_size;
1906         uint32_t current;
1907 };
1908
1909 static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1910                                struct samr_displayentry *entry)
1911 {
1912         struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1913                 search->private_data, struct pdb_samba_dsdb_search_state);
1914
1915         if (state->current == state->num_entries) {
1916                 return false;
1917         }
1918
1919         entry->idx = state->entries[state->current].idx;
1920         entry->rid = state->entries[state->current].rid;
1921         entry->acct_flags = state->entries[state->current].acct_flags;
1922
1923         entry->account_name = talloc_strdup(
1924                 search, state->entries[state->current].account_name);
1925         entry->fullname = talloc_strdup(
1926                 search, state->entries[state->current].fullname);
1927         entry->description = talloc_strdup(
1928                 search, state->entries[state->current].description);
1929
1930         state->current += 1;
1931         return true;
1932 }
1933
1934 static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1935 {
1936         struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1937                 search->private_data, struct pdb_samba_dsdb_search_state);
1938         talloc_free(state);
1939 }
1940
1941 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1942                                          struct pdb_search *search,
1943                                          struct pdb_samba_dsdb_search_state **pstate,
1944                                          const char *exp_fmt, ...)
1945                                          PRINTF_ATTRIBUTE(4, 5);
1946
1947 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1948                                      struct pdb_search *search,
1949                                      struct pdb_samba_dsdb_search_state **pstate,
1950                                      const char *exp_fmt, ...)
1951 {
1952         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1953                 m->private_data, struct pdb_samba_dsdb_state);
1954         struct pdb_samba_dsdb_search_state *sstate;
1955         const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1956                                  "userAccountControl", "description", NULL };
1957         struct ldb_result *res;
1958         int i, rc, num_users;
1959
1960         va_list ap;
1961         char *expression = NULL;
1962
1963         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1964         if (!tmp_ctx) {
1965                 return false;
1966         }
1967
1968         va_start(ap, exp_fmt);
1969         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1970         va_end(ap);
1971
1972         if (!expression) {
1973                 talloc_free(tmp_ctx);
1974                 return LDB_ERR_OPERATIONS_ERROR;
1975         }
1976
1977         sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1978         if (sstate == NULL) {
1979                 talloc_free(tmp_ctx);
1980                 return false;
1981         }
1982
1983         rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1984         if (rc != LDB_SUCCESS) {
1985                 talloc_free(tmp_ctx);
1986                 DEBUG(10, ("dsdb_search failed: %s\n",
1987                            ldb_errstring(state->ldb)));
1988                 return false;
1989         }
1990
1991         num_users = res->count;
1992
1993         sstate->entries = talloc_array(sstate, struct samr_displayentry,
1994                                        num_users);
1995         if (sstate->entries == NULL) {
1996                 talloc_free(tmp_ctx);
1997                 DEBUG(10, ("talloc failed\n"));
1998                 return false;
1999         }
2000
2001         sstate->num_entries = 0;
2002
2003         for (i=0; i<num_users; i++) {
2004                 struct samr_displayentry *e;
2005                 struct dom_sid *sid;
2006
2007                 e = &sstate->entries[sstate->num_entries];
2008
2009                 e->idx = sstate->num_entries;
2010                 sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
2011                 if (!sid) {
2012                         talloc_free(tmp_ctx);
2013                         DEBUG(10, ("Could not pull SID\n"));
2014                         return false;
2015                 }
2016                 sid_peek_rid(sid, &e->rid);
2017
2018                 e->acct_flags = samdb_result_acct_flags(res->msgs[i], "userAccountControl");
2019                 e->account_name = ldb_msg_find_attr_as_string(
2020                         res->msgs[i], "samAccountName", NULL);
2021                 if (e->account_name == NULL) {
2022                         talloc_free(tmp_ctx);
2023                         return false;
2024                 }
2025                 e->fullname = ldb_msg_find_attr_as_string(
2026                         res->msgs[i], "displayName", "");
2027                 e->description = ldb_msg_find_attr_as_string(
2028                         res->msgs[i], "description", "");
2029
2030                 sstate->num_entries += 1;
2031                 if (sstate->num_entries >= num_users) {
2032                         break;
2033                 }
2034         }
2035         talloc_steal(sstate->entries, res->msgs);
2036         search->private_data = talloc_steal(search, sstate);
2037         search->next_entry = pdb_samba_dsdb_next_entry;
2038         search->search_end = pdb_samba_dsdb_search_end;
2039         *pstate = sstate;
2040         talloc_free(tmp_ctx);
2041         return true;
2042 }
2043
2044 static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
2045                                  struct pdb_search *search,
2046                                  uint32_t acct_flags)
2047 {
2048         struct pdb_samba_dsdb_search_state *sstate;
2049         bool ret;
2050
2051         ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
2052         if (!ret) {
2053                 return false;
2054         }
2055         sstate->acct_flags = acct_flags;
2056         return true;
2057 }
2058
2059 static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
2060                                   struct pdb_search *search)
2061 {
2062         struct pdb_samba_dsdb_search_state *sstate;
2063         bool ret;
2064
2065         ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2066                                        "(&(grouptype=%d)(objectclass=group))",
2067                                        GTYPE_SECURITY_GLOBAL_GROUP);
2068         if (!ret) {
2069                 return false;
2070         }
2071         sstate->acct_flags = 0;
2072         return true;
2073 }
2074
2075 static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
2076                                    struct pdb_search *search,
2077                                    const struct dom_sid *sid)
2078 {
2079         struct pdb_samba_dsdb_search_state *sstate;
2080         bool ret;
2081
2082         ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2083                                        "(&(grouptype=%d)(objectclass=group))",
2084                                        sid_check_is_builtin(sid)
2085                                        ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2086                                        : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2087         if (!ret) {
2088                 return false;
2089         }
2090         sstate->acct_flags = 0;
2091         return true;
2092 }
2093
2094 /* 
2095  * Instead of taking a gid or uid, this function takes a pointer to a 
2096  * unixid. 
2097  *
2098  * This acts as an in-out variable so that the idmap functions can correctly
2099  * receive ID_TYPE_BOTH, and this function ensures cache details are filled
2100  * correctly rather than forcing the cache to store ID_TYPE_UID or ID_TYPE_GID. 
2101  */
2102 static bool pdb_samba_dsdb_id_to_sid(struct pdb_methods *m, struct unixid *id,
2103                                      struct dom_sid *sid)
2104 {
2105         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2106                 m->private_data, struct pdb_samba_dsdb_state);
2107         NTSTATUS status;
2108         struct id_map id_map;
2109         struct id_map *id_maps[2];
2110         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2111         if (!tmp_ctx) {
2112                 return false;
2113         }
2114
2115         id_map.xid = *id;
2116         id_maps[0] = &id_map;
2117         id_maps[1] = NULL;
2118
2119         status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2120         if (!NT_STATUS_IS_OK(status)) {
2121                 talloc_free(tmp_ctx);
2122                 return false;
2123         }
2124
2125         if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2126                 id->type = id_map.xid.type;
2127         }
2128         *sid = *id_map.sid;
2129         talloc_free(tmp_ctx);
2130         return true;
2131 }
2132
2133 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2134                                  struct unixid *id)
2135 {
2136         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2137                 m->private_data, struct pdb_samba_dsdb_state);
2138         struct id_map id_map;
2139         struct id_map *id_maps[2];
2140         NTSTATUS status;
2141         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2142         if (!tmp_ctx) {
2143                 return false;
2144         }
2145
2146         ZERO_STRUCT(id_map);
2147         id_map.sid = discard_const_p(struct dom_sid, sid);
2148         id_maps[0] = &id_map;
2149         id_maps[1] = NULL;
2150
2151         status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2152         talloc_free(tmp_ctx);
2153         if (!NT_STATUS_IS_OK(status)) {
2154                 return false;
2155         }
2156         if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2157                 *id = id_map.xid;
2158                 return true;
2159         }
2160         return false;
2161 }
2162
2163 static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2164 {
2165         return PDB_CAP_STORE_RIDS | PDB_CAP_ADS | PDB_CAP_TRUSTED_DOMAINS_EX;
2166 }
2167
2168 static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32_t *rid)
2169 {
2170         return false;
2171 }
2172
2173 static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2174                                       const char *domain, char** pwd,
2175                                       struct dom_sid *sid,
2176                                       time_t *pass_last_set_time)
2177 {
2178         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2179                 m->private_data, struct pdb_samba_dsdb_state);
2180         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2181         const char * const attrs[] = {
2182                 "securityIdentifier",
2183                 "flatName",
2184                 "trustPartner",
2185                 "trustAuthOutgoing",
2186                 "whenCreated",
2187                 "msDS-SupportedEncryptionTypes",
2188                 "trustAttributes",
2189                 "trustDirection",
2190                 "trustType",
2191                 NULL
2192         };
2193         struct ldb_message *msg;
2194         const struct ldb_val *password_val;
2195         int trust_direction_flags;
2196         int trust_type;
2197         int i;
2198         DATA_BLOB password_utf16;
2199         struct trustAuthInOutBlob password_blob;
2200         struct AuthenticationInformationArray *auth_array;
2201         char *password_talloc;
2202         size_t password_len;
2203         enum ndr_err_code ndr_err;
2204         NTSTATUS status;
2205         const char *netbios_domain = NULL;
2206         const struct dom_sid *domain_sid = NULL;
2207
2208         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2209                                        attrs, tmp_ctx, &msg);
2210         if (!NT_STATUS_IS_OK(status)) {
2211                 /*
2212                  * This can be called to work out of a domain is
2213                  * trusted, rather than just to get the password
2214                  */
2215                 DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
2216                           "It may not be a trusted domain.\n", domain,
2217                           nt_errstr(status)));
2218                 TALLOC_FREE(tmp_ctx);
2219                 return false;
2220         }
2221
2222         netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2223         if (netbios_domain == NULL) {
2224                 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2225                           domain));
2226                 TALLOC_FREE(tmp_ctx);
2227                 return false;
2228         }
2229
2230         domain_sid = samdb_result_dom_sid(tmp_ctx, msg, "securityIdentifier");
2231         if (domain_sid == NULL) {
2232                 DEBUG(2, ("Trusted domain %s has no securityIdentifier defined.\n",
2233                           domain));
2234                 TALLOC_FREE(tmp_ctx);
2235                 return false;
2236         }
2237
2238         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2239         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2240                 DBG_WARNING("Trusted domain %s is not an outbound trust.\n",
2241                             domain);
2242                 TALLOC_FREE(tmp_ctx);
2243                 return false;
2244         }
2245
2246         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2247         if (trust_type == LSA_TRUST_TYPE_MIT) {
2248                 DBG_WARNING("Trusted domain %s is not an AD trust "
2249                             "(trustType == LSA_TRUST_TYPE_MIT).\n", domain);
2250                 TALLOC_FREE(tmp_ctx);
2251                 return false;
2252         }
2253
2254         password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2255         if (password_val == NULL) {
2256                 DEBUG(2, ("Failed to get trusted domain password for %s, "
2257                           "attribute trustAuthOutgoing not returned.\n", domain));
2258                 TALLOC_FREE(tmp_ctx);
2259                 return false;
2260         }
2261
2262         ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2263                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2264         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2265                 DEBUG(0, ("Failed to get trusted domain password for %s, "
2266                           "attribute trustAuthOutgoing could not be parsed %s.\n",
2267                           domain,
2268                           ndr_map_error2string(ndr_err)));
2269                 TALLOC_FREE(tmp_ctx);
2270                 return false;
2271         }
2272
2273         auth_array = &password_blob.current;
2274
2275         for (i=0; i < auth_array->count; i++) {
2276                 if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
2277                         break;
2278                 }
2279         }
2280
2281         if (i == auth_array->count) {
2282                 DEBUG(0, ("Trusted domain %s does not have a "
2283                           "clear-text password stored\n",
2284                           domain));
2285                 TALLOC_FREE(tmp_ctx);
2286                 return false;
2287         }
2288
2289         password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
2290                                          auth_array->array[i].AuthInfo.clear.size);
2291
2292         /*
2293          * In the future, make this function return a
2294          * cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash()
2295          * but for now convert to UTF8 and fail if the string can not be converted.
2296          *
2297          * We can't safely convert the random strings windows uses into
2298          * utf8.
2299          */
2300         if (!convert_string_talloc(tmp_ctx,
2301                                    CH_UTF16MUNGED, CH_UTF8,
2302                                    password_utf16.data, password_utf16.length,
2303                                    (void *)&password_talloc,
2304                                    &password_len)) {
2305                 DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
2306                           " to UTF8. This may be a password set from Windows.\n",
2307                           domain));
2308                 TALLOC_FREE(tmp_ctx);
2309                 return false;
2310         }
2311         *pwd = SMB_STRNDUP(password_talloc, password_len);
2312         if (pass_last_set_time) {
2313                 *pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
2314         }
2315
2316         if (sid != NULL) {
2317                 sid_copy(sid, domain_sid);
2318         }
2319
2320         TALLOC_FREE(tmp_ctx);
2321         return true;
2322 }
2323
2324 static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
2325                                                     const char *domain,
2326                                                     TALLOC_CTX *mem_ctx,
2327                                                     struct cli_credentials **_creds)
2328 {
2329         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2330                 m->private_data, struct pdb_samba_dsdb_state);
2331         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2332         const char * const attrs[] = {
2333                 "securityIdentifier",
2334                 "flatName",
2335                 "trustPartner",
2336                 "trustAuthOutgoing",
2337                 "whenCreated",
2338                 "msDS-SupportedEncryptionTypes",
2339                 "trustAttributes",
2340                 "trustDirection",
2341                 "trustType",
2342                 NULL
2343         };
2344         struct ldb_message *msg;
2345         const struct ldb_val *password_val;
2346         int trust_direction_flags;
2347         int trust_type;
2348         int i;
2349         DATA_BLOB password_utf16 = {};
2350         struct samr_Password *password_nt = NULL;
2351         uint32_t password_version = 0;
2352         DATA_BLOB old_password_utf16 = {};
2353         struct samr_Password *old_password_nt = NULL;
2354         struct trustAuthInOutBlob password_blob;
2355         enum ndr_err_code ndr_err;
2356         NTSTATUS status;
2357         time_t last_set_time = 0;
2358         struct cli_credentials *creds = NULL;
2359         bool ok;
2360         const char *my_netbios_name = NULL;
2361         const char *my_netbios_domain = NULL;
2362         const char *my_dns_domain = NULL;
2363         const char *netbios_domain = NULL;
2364         char *account_name = NULL;
2365         char *principal_name = NULL;
2366         const char *dns_domain = NULL;
2367
2368         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2369                                        attrs, tmp_ctx, &msg);
2370         if (!NT_STATUS_IS_OK(status)) {
2371                 /*
2372                  * This can be called to work out of a domain is
2373                  * trusted, rather than just to get the password
2374                  */
2375                 DEBUG(2, ("Failed to get trusted domain password for %s - %s "
2376                           "It may not be a trusted domain.\n", domain,
2377                           nt_errstr(status)));
2378                 TALLOC_FREE(tmp_ctx);
2379                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2380         }
2381
2382         netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2383         if (netbios_domain == NULL) {
2384                 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2385                           domain));
2386                 TALLOC_FREE(tmp_ctx);
2387                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2388         }
2389
2390         dns_domain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2391
2392         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2393         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2394                 DBG_WARNING("Trusted domain %s is not an outbound trust.\n",
2395                             domain);
2396                 TALLOC_FREE(tmp_ctx);
2397                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2398         }
2399
2400         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2401         if (trust_type == LSA_TRUST_TYPE_MIT) {
2402                 DBG_WARNING("Trusted domain %s is not an AD trust "
2403                             "(trustType == LSA_TRUST_TYPE_MIT).\n", domain);
2404                 TALLOC_FREE(tmp_ctx);
2405                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2406         }
2407
2408         password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2409         if (password_val == NULL) {
2410                 DEBUG(2, ("Failed to get trusted domain password for %s, "
2411                           "attribute trustAuthOutgoing not returned.\n", domain));
2412                 TALLOC_FREE(tmp_ctx);
2413                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2414         }
2415
2416         ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2417                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2418         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2419                 DEBUG(0, ("Failed to get trusted domain password for %s, "
2420                           "attribute trustAuthOutgoing could not be parsed %s.\n",
2421                           domain,
2422                           ndr_map_error2string(ndr_err)));
2423                 TALLOC_FREE(tmp_ctx);
2424                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2425         }
2426
2427         for (i=0; i < password_blob.current.count; i++) {
2428                 struct AuthenticationInformation *a =
2429                         &password_blob.current.array[i];
2430
2431                 switch (a->AuthType) {
2432                 case TRUST_AUTH_TYPE_NONE:
2433                         break;
2434
2435                 case TRUST_AUTH_TYPE_VERSION:
2436                         password_version = a->AuthInfo.version.version;
2437                         break;
2438
2439                 case TRUST_AUTH_TYPE_CLEAR:
2440                         last_set_time = nt_time_to_unix(a->LastUpdateTime);
2441
2442                         password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2443                                                          a->AuthInfo.clear.size);
2444                         password_nt = NULL;
2445                         break;
2446
2447                 case TRUST_AUTH_TYPE_NT4OWF:
2448                         if (password_utf16.length != 0) {
2449                                 break;
2450                         }
2451
2452                         last_set_time = nt_time_to_unix(a->LastUpdateTime);
2453
2454                         password_nt = &a->AuthInfo.nt4owf.password;
2455                         break;
2456                 }
2457         }
2458
2459         for (i=0; i < password_blob.previous.count; i++) {
2460                 struct AuthenticationInformation *a = &password_blob.previous.array[i];
2461
2462                 switch (a->AuthType) {
2463                 case TRUST_AUTH_TYPE_NONE:
2464                         break;
2465
2466                 case TRUST_AUTH_TYPE_VERSION:
2467                         break;
2468
2469                 case TRUST_AUTH_TYPE_CLEAR:
2470                         old_password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2471                                                          a->AuthInfo.clear.size);
2472                         old_password_nt = NULL;
2473                         break;
2474
2475                 case TRUST_AUTH_TYPE_NT4OWF:
2476                         if (old_password_utf16.length != 0) {
2477                                 break;
2478                         }
2479
2480                         old_password_nt = &a->AuthInfo.nt4owf.password;
2481                         break;
2482                 }
2483         }
2484
2485         if (password_utf16.length == 0 && password_nt == NULL) {
2486                 DEBUG(0, ("Trusted domain %s does not have a "
2487                           "clear-text nor nt password stored\n",
2488                           domain));
2489                 TALLOC_FREE(tmp_ctx);
2490                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2491         }
2492
2493         my_netbios_name = lpcfg_netbios_name(state->lp_ctx);
2494         my_netbios_domain = lpcfg_workgroup(state->lp_ctx);
2495         my_dns_domain = lpcfg_dnsdomain(state->lp_ctx);
2496
2497         creds = cli_credentials_init(tmp_ctx);
2498         if (creds == NULL) {
2499                 TALLOC_FREE(tmp_ctx);
2500                 return NT_STATUS_NO_MEMORY;
2501         }
2502
2503         ok = cli_credentials_set_workstation(creds, my_netbios_name, CRED_SPECIFIED);
2504         if (!ok) {
2505                 TALLOC_FREE(tmp_ctx);
2506                 return NT_STATUS_NO_MEMORY;
2507         }
2508
2509         ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2510         if (!ok) {
2511                 TALLOC_FREE(tmp_ctx);
2512                 return NT_STATUS_NO_MEMORY;
2513         }
2514         ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2515         if (!ok) {
2516                 TALLOC_FREE(tmp_ctx);
2517                 return NT_STATUS_NO_MEMORY;
2518         }
2519
2520         if (my_dns_domain != NULL && dns_domain != NULL) {
2521                 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DNS_DOMAIN);
2522                 account_name = talloc_asprintf(tmp_ctx, "%s.", my_dns_domain);
2523                 if (account_name == NULL) {
2524                         TALLOC_FREE(tmp_ctx);
2525                         return NT_STATUS_NO_MEMORY;
2526                 }
2527                 principal_name = talloc_asprintf(tmp_ctx, "%s$@%s", my_netbios_domain,
2528                                                  cli_credentials_get_realm(creds));
2529                 if (principal_name == NULL) {
2530                         TALLOC_FREE(tmp_ctx);
2531                         return NT_STATUS_NO_MEMORY;
2532                 }
2533         } else {
2534                 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DOMAIN);
2535                 account_name = talloc_asprintf(tmp_ctx, "%s$", my_netbios_domain);
2536                 if (account_name == NULL) {
2537                         TALLOC_FREE(tmp_ctx);
2538                         return NT_STATUS_NO_MEMORY;
2539                 }
2540                 principal_name = NULL;
2541         }
2542
2543         ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2544         if (!ok) {
2545                 TALLOC_FREE(tmp_ctx);
2546                 return NT_STATUS_NO_MEMORY;
2547         }
2548
2549         if (principal_name != NULL) {
2550                 ok = cli_credentials_set_principal(creds, principal_name,
2551                                                    CRED_SPECIFIED);
2552                 if (!ok) {
2553                         TALLOC_FREE(tmp_ctx);
2554                         return NT_STATUS_NO_MEMORY;
2555                 }
2556         }
2557
2558         if (old_password_nt != NULL) {
2559                 ok = cli_credentials_set_old_nt_hash(creds, old_password_nt);
2560                 if (!ok) {
2561                         TALLOC_FREE(tmp_ctx);
2562                         return NT_STATUS_NO_MEMORY;
2563                 }
2564         }
2565
2566         if (old_password_utf16.length > 0) {
2567                 ok = cli_credentials_set_old_utf16_password(creds,
2568                                                             &old_password_utf16);
2569                 if (!ok) {
2570                         TALLOC_FREE(tmp_ctx);
2571                         return NT_STATUS_NO_MEMORY;
2572                 }
2573         }
2574
2575         if (password_nt != NULL) {
2576                 ok = cli_credentials_set_nt_hash(creds, password_nt,
2577                                                  CRED_SPECIFIED);
2578                 if (!ok) {
2579                         TALLOC_FREE(tmp_ctx);
2580                         return NT_STATUS_NO_MEMORY;
2581                 }
2582         }
2583
2584         if (password_utf16.length > 0) {
2585                 ok = cli_credentials_set_utf16_password(creds,
2586                                                         &password_utf16,
2587                                                         CRED_SPECIFIED);
2588                 if (!ok) {
2589                         TALLOC_FREE(tmp_ctx);
2590                         return NT_STATUS_NO_MEMORY;
2591                 }
2592         }
2593
2594         cli_credentials_set_password_last_changed_time(creds, last_set_time);
2595         cli_credentials_set_kvno(creds, password_version);
2596
2597         if (password_utf16.length > 0 && dns_domain != NULL) {
2598                 /*
2599                  * Force kerberos if this is an active directory domain
2600                  */
2601                 cli_credentials_set_kerberos_state(creds,
2602                                                    CRED_MUST_USE_KERBEROS);
2603         } else  {
2604                 /*
2605                  * TODO: we should allow krb5 with the raw nt hash.
2606                  */
2607                 cli_credentials_set_kerberos_state(creds,
2608                                                    CRED_DONT_USE_KERBEROS);
2609         }
2610
2611         *_creds = talloc_move(mem_ctx, &creds);
2612         TALLOC_FREE(tmp_ctx);
2613         return NT_STATUS_OK;
2614 }
2615
2616 static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2617                                       const char* domain, const char* pwd,
2618                                       const struct dom_sid *sid)
2619 {
2620         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2621                 m->private_data, struct pdb_samba_dsdb_state);
2622         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2623         const char * const attrs[] = {
2624                 "trustAuthOutgoing",
2625                 "trustDirection",
2626                 "trustType",
2627                 NULL
2628         };
2629         struct ldb_message *msg = NULL;
2630         int trust_direction_flags;
2631         int trust_type;
2632         uint32_t i; /* The same type as old_blob.current.count */
2633         const struct ldb_val *old_val = NULL;
2634         struct trustAuthInOutBlob old_blob = {};
2635         uint32_t old_version = 0;
2636         uint32_t new_version = 0;
2637         DATA_BLOB new_utf16 = {};
2638         struct trustAuthInOutBlob new_blob = {};
2639         struct ldb_val new_val = {};
2640         struct timeval tv = timeval_current();
2641         NTTIME now = timeval_to_nttime(&tv);
2642         enum ndr_err_code ndr_err;
2643         NTSTATUS status;
2644         bool ok;
2645         int ret;
2646
2647         ret = ldb_transaction_start(state->ldb);
2648         if (ret != LDB_SUCCESS) {
2649                 DEBUG(2, ("Failed to start transaction.\n"));
2650                 TALLOC_FREE(tmp_ctx);
2651                 return false;
2652         }
2653
2654         ok = samdb_is_pdc(state->ldb);
2655         if (!ok) {
2656                 DEBUG(2, ("Password changes for domain %s are only allowed on a PDC.\n",
2657                           domain));
2658                 TALLOC_FREE(tmp_ctx);
2659                 ldb_transaction_cancel(state->ldb);
2660                 return false;
2661         }
2662
2663         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2664                                        attrs, tmp_ctx, &msg);
2665         if (!NT_STATUS_IS_OK(status)) {
2666                 /*
2667                  * This can be called to work out of a domain is
2668                  * trusted, rather than just to get the password
2669                  */
2670                 DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
2671                           "It may not be a trusted domain.\n", domain,
2672                           nt_errstr(status)));
2673                 TALLOC_FREE(tmp_ctx);
2674                 ldb_transaction_cancel(state->ldb);
2675                 return false;
2676         }
2677
2678         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2679         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2680                 DBG_WARNING("Trusted domain %s is not an outbound trust, can't set a password.\n",
2681                             domain);
2682                 TALLOC_FREE(tmp_ctx);
2683                 ldb_transaction_cancel(state->ldb);
2684                 return false;
2685         }
2686
2687         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2688         switch (trust_type) {
2689         case LSA_TRUST_TYPE_DOWNLEVEL:
2690         case LSA_TRUST_TYPE_UPLEVEL:
2691                 break;
2692         default:
2693                 DEBUG(0, ("Trusted domain %s is of type 0x%X - "
2694                           "password changes are not supported\n",
2695                           domain, (unsigned)trust_type));
2696                 TALLOC_FREE(tmp_ctx);
2697                 ldb_transaction_cancel(state->ldb);
2698                 return false;
2699         }
2700
2701         old_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2702         if (old_val != NULL) {
2703                 ndr_err = ndr_pull_struct_blob(old_val, tmp_ctx, &old_blob,
2704                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2705                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2706                         DEBUG(0, ("Failed to get trusted domain password for %s, "
2707                                   "attribute trustAuthOutgoing could not be parsed %s.\n",
2708                                   domain,
2709                                   ndr_map_error2string(ndr_err)));
2710                         TALLOC_FREE(tmp_ctx);
2711                         ldb_transaction_cancel(state->ldb);
2712                         return false;
2713                 }
2714         }
2715
2716         for (i=0; i < old_blob.current.count; i++) {
2717                 struct AuthenticationInformation *a =
2718                         &old_blob.current.array[i];
2719
2720                 switch (a->AuthType) {
2721                 case TRUST_AUTH_TYPE_NONE:
2722                         break;
2723
2724                 case TRUST_AUTH_TYPE_VERSION:
2725                         old_version = a->AuthInfo.version.version;
2726                         break;
2727
2728                 case TRUST_AUTH_TYPE_CLEAR:
2729                         break;
2730
2731                 case TRUST_AUTH_TYPE_NT4OWF:
2732                         break;
2733                 }
2734         }
2735
2736         new_version = old_version + 1;
2737         ok = convert_string_talloc(tmp_ctx,
2738                                    CH_UNIX, CH_UTF16,
2739                                    pwd, strlen(pwd),
2740                                    (void *)&new_utf16.data,
2741                                    &new_utf16.length);
2742         if (!ok) {
2743                 DEBUG(0, ("Failed to generate new_utf16 password for  domain %s\n",
2744                           domain));
2745                 TALLOC_FREE(tmp_ctx);
2746                 ldb_transaction_cancel(state->ldb);
2747                 return false;
2748         }
2749
2750         if (new_utf16.length < 28) {
2751                 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to short.\n",
2752                           new_utf16.length,
2753                           (unsigned)new_version,
2754                           domain));
2755                 TALLOC_FREE(tmp_ctx);
2756                 ldb_transaction_cancel(state->ldb);
2757                 return false;
2758         }
2759         if (new_utf16.length > 498) {
2760                 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to long.\n",
2761                           new_utf16.length,
2762                           (unsigned)new_version,
2763                           domain));
2764                 TALLOC_FREE(tmp_ctx);
2765                 ldb_transaction_cancel(state->ldb);
2766                 return false;
2767         }
2768
2769         new_blob.count = MAX(old_blob.current.count, 2);
2770         new_blob.current.array = talloc_zero_array(tmp_ctx,
2771                                         struct AuthenticationInformation,
2772                                         new_blob.count);
2773         if (new_blob.current.array == NULL) {
2774                 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2775                           (unsigned)new_blob.count));
2776                 TALLOC_FREE(tmp_ctx);
2777                 ldb_transaction_cancel(state->ldb);
2778                 return false;
2779         }
2780         new_blob.previous.array = talloc_zero_array(tmp_ctx,
2781                                         struct AuthenticationInformation,
2782                                         new_blob.count);
2783         if (new_blob.current.array == NULL) {
2784                 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2785                           (unsigned)new_blob.count));
2786                 TALLOC_FREE(tmp_ctx);
2787                 ldb_transaction_cancel(state->ldb);
2788                 return false;
2789         }
2790
2791         for (i = 0; i < old_blob.current.count; i++) {
2792                 struct AuthenticationInformation *o =
2793                         &old_blob.current.array[i];
2794                 struct AuthenticationInformation *p =
2795                         &new_blob.previous.array[i];
2796
2797                 *p = *o;
2798                 new_blob.previous.count++;
2799         }
2800         for (; i < new_blob.count; i++) {
2801                 struct AuthenticationInformation *pi =
2802                         &new_blob.previous.array[i];
2803
2804                 if (i == 0) {
2805                         /*
2806                          * new_blob.previous is still empty so
2807                          * we'll do new_blob.previous = new_blob.current
2808                          * below.
2809                          */
2810                         break;
2811                 }
2812
2813                 pi->LastUpdateTime = now;
2814                 pi->AuthType = TRUST_AUTH_TYPE_NONE;
2815                 new_blob.previous.count++;
2816         }
2817
2818         for (i = 0; i < new_blob.count; i++) {
2819                 struct AuthenticationInformation *ci =
2820                         &new_blob.current.array[i];
2821
2822                 ci->LastUpdateTime = now;
2823                 switch (i) {
2824                 case 0:
2825                         ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
2826                         ci->AuthInfo.clear.size = new_utf16.length;
2827                         ci->AuthInfo.clear.password = new_utf16.data;
2828                         break;
2829                 case 1:
2830                         ci->AuthType = TRUST_AUTH_TYPE_VERSION;
2831                         ci->AuthInfo.version.version = new_version;
2832                         break;
2833                 default:
2834                         ci->AuthType = TRUST_AUTH_TYPE_NONE;
2835                         break;
2836                 }
2837
2838                 new_blob.current.count++;
2839         }
2840
2841         if (new_blob.previous.count == 0) {
2842                 TALLOC_FREE(new_blob.previous.array);
2843                 new_blob.previous = new_blob.current;
2844         }
2845
2846         ndr_err = ndr_push_struct_blob(&new_val, tmp_ctx, &new_blob,
2847                         (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
2848         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2849                 DEBUG(0, ("Failed to generate trustAuthOutgoing for "
2850                           "trusted domain password for %s: %s.\n",
2851                           domain, ndr_map_error2string(ndr_err)));
2852                 TALLOC_FREE(tmp_ctx);
2853                 ldb_transaction_cancel(state->ldb);
2854                 return false;
2855         }
2856
2857         msg->num_elements = 0;
2858         ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2859                                 LDB_FLAG_MOD_REPLACE, NULL);
2860         if (ret != LDB_SUCCESS) {
2861                 DEBUG(0, ("ldb_msg_add_empty() failed\n"));
2862                 TALLOC_FREE(tmp_ctx);
2863                 ldb_transaction_cancel(state->ldb);
2864                 return false;
2865         }
2866         ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2867                                 &new_val, NULL);
2868         if (ret != LDB_SUCCESS) {
2869                 DEBUG(0, ("ldb_msg_add_value() failed\n"));
2870                 TALLOC_FREE(tmp_ctx);
2871                 ldb_transaction_cancel(state->ldb);
2872                 return false;
2873         }
2874
2875         ret = ldb_modify(state->ldb, msg);
2876         if (ret != LDB_SUCCESS) {
2877                 DEBUG(0, ("Failed to replace trustAuthOutgoing for "
2878                           "trusted domain password for %s: %s - %s\n",
2879                           domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2880                 TALLOC_FREE(tmp_ctx);
2881                 ldb_transaction_cancel(state->ldb);
2882                 return false;
2883         }
2884
2885         ret = ldb_transaction_commit(state->ldb);
2886         if (ret != LDB_SUCCESS) {
2887                 DEBUG(0, ("Failed to commit trustAuthOutgoing for "
2888                           "trusted domain password for %s: %s - %s\n",
2889                           domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2890                 TALLOC_FREE(tmp_ctx);
2891                 return false;
2892         }
2893
2894         DEBUG(1, ("Added new_version[%u] to trustAuthOutgoing for "
2895                   "trusted domain password for %s.\n",
2896                   (unsigned)new_version, domain));
2897         TALLOC_FREE(tmp_ctx);
2898         return true;
2899 }
2900
2901 static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2902                                       const char *domain)
2903 {
2904         return false;
2905 }
2906
2907 static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2908                                          TALLOC_CTX *mem_ctx,
2909                                          uint32_t *_num_domains,
2910                                          struct trustdom_info ***_domains)
2911 {
2912         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2913                 m->private_data, struct pdb_samba_dsdb_state);
2914         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2915         const char * const attrs[] = {
2916                 "securityIdentifier",
2917                 "flatName",
2918                 "trustDirection",
2919                 NULL
2920         };
2921         struct ldb_result *res = NULL;
2922         unsigned int i;
2923         struct trustdom_info **domains = NULL;
2924         NTSTATUS status;
2925         uint32_t di = 0;
2926
2927         *_num_domains = 0;
2928         *_domains = NULL;
2929
2930         status = dsdb_trust_search_tdos(state->ldb, NULL,
2931                                         attrs, tmp_ctx, &res);
2932         if (!NT_STATUS_IS_OK(status)) {
2933                 DBG_ERR("dsdb_trust_search_tdos() - %s ", nt_errstr(status));
2934                 TALLOC_FREE(tmp_ctx);
2935                 return status;
2936         }
2937
2938         if (res->count == 0) {
2939                 TALLOC_FREE(tmp_ctx);
2940                 return NT_STATUS_OK;
2941         }
2942
2943         domains = talloc_zero_array(tmp_ctx, struct trustdom_info *,
2944                                     res->count);
2945         if (domains == NULL) {
2946                 TALLOC_FREE(tmp_ctx);
2947                 return NT_STATUS_NO_MEMORY;
2948         }
2949
2950         for (i = 0; i < res->count; i++) {
2951                 struct ldb_message *msg = res->msgs[i];
2952                 struct trustdom_info *d = NULL;
2953                 const char *name = NULL;
2954                 struct dom_sid *sid = NULL;
2955                 uint32_t direction;
2956
2957                 d = talloc_zero(domains, struct trustdom_info);
2958                 if (d == NULL) {
2959                         TALLOC_FREE(tmp_ctx);
2960                         return NT_STATUS_NO_MEMORY;
2961                 }
2962
2963                 name = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2964                 if (name == NULL) {
2965                         TALLOC_FREE(tmp_ctx);
2966                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2967                 }
2968                 sid = samdb_result_dom_sid(msg, msg, "securityIdentifier");
2969                 if (sid == NULL) {
2970                         continue;
2971                 }
2972
2973                 direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
2974                 if (!(direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2975                         continue;
2976                 }
2977
2978                 d->name = talloc_strdup(d, name);
2979                 if (d->name == NULL) {
2980                         TALLOC_FREE(tmp_ctx);
2981                         return NT_STATUS_NO_MEMORY;
2982                 }
2983                 d->sid = *sid;
2984
2985                 domains[di++] = d;
2986         }
2987
2988         domains = talloc_realloc(domains, domains, struct trustdom_info *, di);
2989         *_domains = talloc_move(mem_ctx, &domains);
2990         *_num_domains = di;
2991         TALLOC_FREE(tmp_ctx);
2992         return NT_STATUS_OK;
2993 }
2994
2995 static NTSTATUS pdb_samba_dsdb_msg_to_trusted_domain(const struct ldb_message *msg,
2996                                                 TALLOC_CTX *mem_ctx,
2997                                                 struct pdb_trusted_domain **_d)
2998 {
2999         struct pdb_trusted_domain *d = NULL;
3000         const char *str = NULL;
3001         struct dom_sid *sid = NULL;
3002         const struct ldb_val *val = NULL;
3003         uint64_t val64;
3004
3005         *_d = NULL;
3006
3007         d = talloc_zero(mem_ctx, struct pdb_trusted_domain);
3008         if (d == NULL) {
3009                 return NT_STATUS_NO_MEMORY;
3010         }
3011
3012         str = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
3013         if (str == NULL) {
3014                 TALLOC_FREE(d);
3015                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3016         }
3017         d->netbios_name = talloc_strdup(d, str);
3018         if (d->netbios_name == NULL) {
3019                 TALLOC_FREE(d);
3020                 return NT_STATUS_NO_MEMORY;
3021         }
3022
3023         str = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
3024         if (str != NULL) {
3025                 d->domain_name = talloc_strdup(d, str);
3026                 if (d->domain_name == NULL) {
3027                         TALLOC_FREE(d);
3028                         return NT_STATUS_NO_MEMORY;
3029                 }
3030         }
3031
3032         sid = samdb_result_dom_sid(d, msg, "securityIdentifier");
3033         if (sid != NULL) {
3034                 d->security_identifier = *sid;
3035                 TALLOC_FREE(sid);
3036         }
3037
3038         val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
3039         if (val != NULL) {
3040                 d->trust_auth_outgoing = data_blob_dup_talloc(d, *val);
3041                 if (d->trust_auth_outgoing.data == NULL) {
3042                         TALLOC_FREE(d);
3043                         return NT_STATUS_NO_MEMORY;
3044                 }
3045         }
3046         val = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
3047         if (val != NULL) {
3048                 d->trust_auth_incoming = data_blob_dup_talloc(d, *val);
3049                 if (d->trust_auth_incoming.data == NULL) {
3050                         TALLOC_FREE(d);
3051                         return NT_STATUS_NO_MEMORY;
3052                 }
3053         }
3054
3055         d->trust_direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
3056         d->trust_type = ldb_msg_find_attr_as_uint(msg, "trustType", 0);
3057         d->trust_attributes = ldb_msg_find_attr_as_uint(msg, "trustAttributes", 0);
3058
3059         val64 = ldb_msg_find_attr_as_uint64(msg, "trustPosixOffset", UINT64_MAX);
3060         if (val64 != UINT64_MAX) {
3061                 d->trust_posix_offset = talloc(d, uint32_t);
3062                 if (d->trust_posix_offset == NULL) {
3063                         TALLOC_FREE(d);
3064                         return NT_STATUS_NO_MEMORY;
3065                 }
3066                 *d->trust_posix_offset = (uint32_t)val64;
3067         }
3068
3069         val64 = ldb_msg_find_attr_as_uint64(msg, "msDS-SupportedEncryptionTypes", UINT64_MAX);
3070         if (val64 != UINT64_MAX) {
3071                 d->supported_enc_type = talloc(d, uint32_t);
3072                 if (d->supported_enc_type == NULL) {
3073                         TALLOC_FREE(d);
3074                         return NT_STATUS_NO_MEMORY;
3075                 }
3076                 *d->supported_enc_type = (uint32_t)val64;
3077         }
3078
3079         val = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3080         if (val != NULL) {
3081                 d->trust_forest_trust_info = data_blob_dup_talloc(d, *val);
3082                 if (d->trust_forest_trust_info.data == NULL) {
3083                         TALLOC_FREE(d);
3084                         return NT_STATUS_NO_MEMORY;
3085                 }
3086         }
3087
3088         *_d = d;
3089         return NT_STATUS_OK;
3090 }
3091
3092 static NTSTATUS pdb_samba_dsdb_get_trusted_domain(struct pdb_methods *m,
3093                                                   TALLOC_CTX *mem_ctx,
3094                                                   const char *domain,
3095                                                   struct pdb_trusted_domain **td)
3096 {
3097         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3098                 m->private_data, struct pdb_samba_dsdb_state);
3099         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3100         const char * const attrs[] = {
3101                 "securityIdentifier",
3102                 "flatName",
3103                 "trustPartner",
3104                 "trustAuthOutgoing",
3105                 "trustAuthIncoming",
3106                 "trustAttributes",
3107                 "trustDirection",
3108                 "trustType",
3109                 "trustPosixOffset",
3110                 "msDS-SupportedEncryptionTypes",
3111                 "msDS-TrustForestTrustInfo",
3112                 NULL
3113         };
3114         struct ldb_message *msg = NULL;
3115         struct pdb_trusted_domain *d = NULL;
3116         NTSTATUS status;
3117
3118         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
3119                                        attrs, tmp_ctx, &msg);
3120         if (!NT_STATUS_IS_OK(status)) {
3121                 DBG_ERR("dsdb_trust_search_tdo(%s) - %s ",
3122                         domain, nt_errstr(status));
3123                 TALLOC_FREE(tmp_ctx);
3124                 return status;
3125         }
3126
3127         status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3128         if (!NT_STATUS_IS_OK(status)) {
3129                 DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s ",
3130                         domain, nt_errstr(status));
3131                 TALLOC_FREE(tmp_ctx);
3132                 return status;
3133         }
3134
3135         *td = d;
3136         TALLOC_FREE(tmp_ctx);
3137         return NT_STATUS_OK;
3138 }
3139
3140 static NTSTATUS pdb_samba_dsdb_get_trusted_domain_by_sid(struct pdb_methods *m,
3141                                                          TALLOC_CTX *mem_ctx,
3142                                                          struct dom_sid *sid,
3143                                                          struct pdb_trusted_domain **td)
3144 {
3145         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3146                 m->private_data, struct pdb_samba_dsdb_state);
3147         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3148         const char * const attrs[] = {
3149                 "securityIdentifier",
3150                 "flatName",
3151                 "trustPartner",
3152                 "trustAuthOutgoing",
3153                 "trustAuthIncoming",
3154                 "trustAttributes",
3155                 "trustDirection",
3156                 "trustType",
3157                 "trustPosixOffset",
3158                 "msDS-SupportedEncryptionTypes",
3159                 "msDS-TrustForestTrustInfo",
3160                 NULL
3161         };
3162         struct ldb_message *msg = NULL;
3163         struct pdb_trusted_domain *d = NULL;
3164         struct dom_sid_buf buf;
3165         NTSTATUS status;
3166
3167         status = dsdb_trust_search_tdo_by_sid(state->ldb, sid,
3168                                               attrs, tmp_ctx, &msg);
3169         if (!NT_STATUS_IS_OK(status)) {
3170                 DBG_ERR("dsdb_trust_search_tdo_by_sid(%s) - %s ",
3171                         dom_sid_str_buf(sid, &buf),
3172                         nt_errstr(status));
3173                 TALLOC_FREE(tmp_ctx);
3174                 return status;
3175         }
3176
3177         status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3178         if (!NT_STATUS_IS_OK(status)) {
3179                 DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s ",
3180                         dom_sid_str_buf(sid, &buf),
3181                         nt_errstr(status));
3182                 TALLOC_FREE(tmp_ctx);
3183                 return status;
3184         }
3185
3186         *td = d;
3187         TALLOC_FREE(tmp_ctx);
3188         return NT_STATUS_OK;
3189 }
3190
3191 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
3192                                struct ldb_context *sam_ldb,
3193                                struct ldb_dn *base_dn,
3194                                const char *netbios_name,
3195                                struct trustAuthInOutBlob *taiob)
3196 {
3197         struct ldb_request *req = NULL;
3198         struct ldb_message *msg = NULL;
3199         struct ldb_dn *dn = NULL;
3200         uint32_t i;
3201         int ret;
3202         bool ok;
3203
3204         dn = ldb_dn_copy(mem_ctx, base_dn);
3205         if (dn == NULL) {
3206                 return NT_STATUS_NO_MEMORY;
3207         }
3208         ok = ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name);
3209         if (!ok) {
3210                 return NT_STATUS_NO_MEMORY;
3211         }
3212
3213         msg = ldb_msg_new(mem_ctx);
3214         if (msg == NULL) {
3215                 return NT_STATUS_NO_MEMORY;
3216         }
3217         msg->dn = dn;
3218
3219         ret = ldb_msg_add_string(msg, "objectClass", "user");
3220         if (ret != LDB_SUCCESS) {
3221                 return NT_STATUS_NO_MEMORY;
3222         }
3223
3224         ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);