0753d38b5f68022b16d143dac8856f37c90521dc
[metze/samba/wip.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         *pnum_members = num_members;
1756         if (NT_STATUS_IS_OK(status)) {
1757                 talloc_steal(mem_ctx, pmembers);
1758         }
1759         talloc_free(tmp_ctx);
1760         return status;
1761 }
1762
1763 static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1764                                                TALLOC_CTX *mem_ctx,
1765                                                const struct dom_sid *domain_sid,
1766                                                const struct dom_sid *members,
1767                                                size_t num_members,
1768                                                uint32_t **palias_rids,
1769                                                size_t *pnum_alias_rids)
1770 {
1771         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1772                 m->private_data, struct pdb_samba_dsdb_state);
1773         uint32_t *alias_rids = NULL;
1774         size_t num_alias_rids = 0;
1775         int i;
1776         struct dom_sid *groupSIDs = NULL;
1777         unsigned int num_groupSIDs = 0;
1778         char *filter;
1779         NTSTATUS status;
1780         const char *sid_dn;
1781         DATA_BLOB sid_blob;
1782
1783         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1784         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1785         /*
1786          * TODO: Get the filter right so that we only get the aliases from
1787          * either the SAM or BUILTIN
1788          */
1789
1790         filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
1791                                  GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1792         if (filter == NULL) {
1793                 return NT_STATUS_NO_MEMORY;
1794         }
1795
1796         for (i = 0; i < num_members; i++) {
1797                 struct dom_sid_buf buf;
1798
1799                 sid_dn = talloc_asprintf(
1800                         tmp_ctx,
1801                         "<SID=%s>",
1802                         dom_sid_str_buf(&members[i], &buf));
1803                 if (sid_dn == NULL) {
1804                         TALLOC_FREE(tmp_ctx);
1805                         return NT_STATUS_NO_MEMORY;
1806                 }
1807
1808                 sid_blob = data_blob_string_const(sid_dn);
1809
1810                 status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1811                                                    tmp_ctx, &groupSIDs, &num_groupSIDs);
1812                 if (!NT_STATUS_IS_OK(status)) {
1813                         talloc_free(tmp_ctx);
1814                         return status;
1815                 }
1816         }
1817
1818         alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1819         if (alias_rids == NULL) {
1820                 talloc_free(tmp_ctx);
1821                 return NT_STATUS_NO_MEMORY;
1822         }
1823
1824         for (i=0; i<num_groupSIDs; i++) {
1825                 if (sid_peek_check_rid(domain_sid, &groupSIDs[i],
1826                                        &alias_rids[num_alias_rids])) {
1827                         num_alias_rids++;;
1828                 }
1829         }
1830
1831         *palias_rids = alias_rids;
1832         *pnum_alias_rids = num_alias_rids;
1833         return NT_STATUS_OK;
1834 }
1835
1836 static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1837                                     const struct dom_sid *domain_sid,
1838                                     int num_rids,
1839                                     uint32_t *rids,
1840                                     const char **names,
1841                                     enum lsa_SidType *lsa_attrs)
1842 {
1843         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1844                 m->private_data, struct pdb_samba_dsdb_state);
1845         NTSTATUS status;
1846
1847         TALLOC_CTX *tmp_ctx;
1848
1849         if (num_rids == 0) {
1850                 return NT_STATUS_NONE_MAPPED;
1851         }
1852
1853         tmp_ctx = talloc_stackframe();
1854         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1855
1856         status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1857         talloc_free(tmp_ctx);
1858         return status;
1859 }
1860
1861 static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1862                                      const struct dom_sid *domain_sid,
1863                                      int num_names,
1864                                      const char **pp_names,
1865                                      uint32_t *rids,
1866                                      enum lsa_SidType *attrs)
1867 {
1868         return NT_STATUS_NOT_IMPLEMENTED;
1869 }
1870
1871 static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1872                                            enum pdb_policy_type type,
1873                                            uint32_t *value)
1874 {
1875         return account_policy_get(type, value)
1876                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1877 }
1878
1879 static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1880                                            enum pdb_policy_type type,
1881                                            uint32_t value)
1882 {
1883         return account_policy_set(type, value)
1884                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1885 }
1886
1887 static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1888                                     time_t *seq_num_out)
1889 {
1890         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1891                 m->private_data, struct pdb_samba_dsdb_state);
1892         uint64_t seq_num;
1893         int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1894         if (ret == LDB_SUCCESS) {
1895                 *seq_num_out = seq_num;
1896                 return NT_STATUS_OK;
1897         } else {
1898                 return NT_STATUS_UNSUCCESSFUL;
1899         }
1900 }
1901
1902 struct pdb_samba_dsdb_search_state {
1903         uint32_t acct_flags;
1904         struct samr_displayentry *entries;
1905         uint32_t num_entries;
1906         ssize_t array_size;
1907         uint32_t current;
1908 };
1909
1910 static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1911                                struct samr_displayentry *entry)
1912 {
1913         struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1914                 search->private_data, struct pdb_samba_dsdb_search_state);
1915
1916         if (state->current == state->num_entries) {
1917                 return false;
1918         }
1919
1920         entry->idx = state->entries[state->current].idx;
1921         entry->rid = state->entries[state->current].rid;
1922         entry->acct_flags = state->entries[state->current].acct_flags;
1923
1924         entry->account_name = talloc_strdup(
1925                 search, state->entries[state->current].account_name);
1926         entry->fullname = talloc_strdup(
1927                 search, state->entries[state->current].fullname);
1928         entry->description = talloc_strdup(
1929                 search, state->entries[state->current].description);
1930
1931         state->current += 1;
1932         return true;
1933 }
1934
1935 static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1936 {
1937         struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1938                 search->private_data, struct pdb_samba_dsdb_search_state);
1939         talloc_free(state);
1940 }
1941
1942 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1943                                          struct pdb_search *search,
1944                                          struct pdb_samba_dsdb_search_state **pstate,
1945                                          const char *exp_fmt, ...)
1946                                          PRINTF_ATTRIBUTE(4, 5);
1947
1948 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1949                                      struct pdb_search *search,
1950                                      struct pdb_samba_dsdb_search_state **pstate,
1951                                      const char *exp_fmt, ...)
1952 {
1953         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1954                 m->private_data, struct pdb_samba_dsdb_state);
1955         struct pdb_samba_dsdb_search_state *sstate;
1956         const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1957                                  "userAccountControl", "description", NULL };
1958         struct ldb_result *res;
1959         int i, rc, num_users;
1960
1961         va_list ap;
1962         char *expression = NULL;
1963
1964         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1965         if (!tmp_ctx) {
1966                 return false;
1967         }
1968
1969         va_start(ap, exp_fmt);
1970         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1971         va_end(ap);
1972
1973         if (!expression) {
1974                 talloc_free(tmp_ctx);
1975                 return LDB_ERR_OPERATIONS_ERROR;
1976         }
1977
1978         sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1979         if (sstate == NULL) {
1980                 talloc_free(tmp_ctx);
1981                 return false;
1982         }
1983
1984         rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1985         if (rc != LDB_SUCCESS) {
1986                 talloc_free(tmp_ctx);
1987                 DEBUG(10, ("dsdb_search failed: %s\n",
1988                            ldb_errstring(state->ldb)));
1989                 return false;
1990         }
1991
1992         num_users = res->count;
1993
1994         sstate->entries = talloc_array(sstate, struct samr_displayentry,
1995                                        num_users);
1996         if (sstate->entries == NULL) {
1997                 talloc_free(tmp_ctx);
1998                 DEBUG(10, ("talloc failed\n"));
1999                 return false;
2000         }
2001
2002         sstate->num_entries = 0;
2003
2004         for (i=0; i<num_users; i++) {
2005                 struct samr_displayentry *e;
2006                 struct dom_sid *sid;
2007
2008                 e = &sstate->entries[sstate->num_entries];
2009
2010                 e->idx = sstate->num_entries;
2011                 sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
2012                 if (!sid) {
2013                         talloc_free(tmp_ctx);
2014                         DEBUG(10, ("Could not pull SID\n"));
2015                         return false;
2016                 }
2017                 sid_peek_rid(sid, &e->rid);
2018
2019                 e->acct_flags = samdb_result_acct_flags(res->msgs[i], "userAccountControl");
2020                 e->account_name = ldb_msg_find_attr_as_string(
2021                         res->msgs[i], "samAccountName", NULL);
2022                 if (e->account_name == NULL) {
2023                         talloc_free(tmp_ctx);
2024                         return false;
2025                 }
2026                 e->fullname = ldb_msg_find_attr_as_string(
2027                         res->msgs[i], "displayName", "");
2028                 e->description = ldb_msg_find_attr_as_string(
2029                         res->msgs[i], "description", "");
2030
2031                 sstate->num_entries += 1;
2032                 if (sstate->num_entries >= num_users) {
2033                         break;
2034                 }
2035         }
2036         talloc_steal(sstate->entries, res->msgs);
2037         search->private_data = talloc_steal(search, sstate);
2038         search->next_entry = pdb_samba_dsdb_next_entry;
2039         search->search_end = pdb_samba_dsdb_search_end;
2040         *pstate = sstate;
2041         talloc_free(tmp_ctx);
2042         return true;
2043 }
2044
2045 static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
2046                                  struct pdb_search *search,
2047                                  uint32_t acct_flags)
2048 {
2049         struct pdb_samba_dsdb_search_state *sstate;
2050         bool ret;
2051
2052         ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
2053         if (!ret) {
2054                 return false;
2055         }
2056         sstate->acct_flags = acct_flags;
2057         return true;
2058 }
2059
2060 static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
2061                                   struct pdb_search *search)
2062 {
2063         struct pdb_samba_dsdb_search_state *sstate;
2064         bool ret;
2065
2066         ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2067                                        "(&(grouptype=%d)(objectclass=group))",
2068                                        GTYPE_SECURITY_GLOBAL_GROUP);
2069         if (!ret) {
2070                 return false;
2071         }
2072         sstate->acct_flags = 0;
2073         return true;
2074 }
2075
2076 static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
2077                                    struct pdb_search *search,
2078                                    const struct dom_sid *sid)
2079 {
2080         struct pdb_samba_dsdb_search_state *sstate;
2081         bool ret;
2082
2083         ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2084                                        "(&(grouptype=%d)(objectclass=group))",
2085                                        sid_check_is_builtin(sid)
2086                                        ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2087                                        : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2088         if (!ret) {
2089                 return false;
2090         }
2091         sstate->acct_flags = 0;
2092         return true;
2093 }
2094
2095 /* 
2096  * Instead of taking a gid or uid, this function takes a pointer to a 
2097  * unixid. 
2098  *
2099  * This acts as an in-out variable so that the idmap functions can correctly
2100  * receive ID_TYPE_BOTH, and this function ensures cache details are filled
2101  * correctly rather than forcing the cache to store ID_TYPE_UID or ID_TYPE_GID. 
2102  */
2103 static bool pdb_samba_dsdb_id_to_sid(struct pdb_methods *m, struct unixid *id,
2104                                      struct dom_sid *sid)
2105 {
2106         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2107                 m->private_data, struct pdb_samba_dsdb_state);
2108         NTSTATUS status;
2109         struct id_map id_map;
2110         struct id_map *id_maps[2];
2111         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2112         if (!tmp_ctx) {
2113                 return false;
2114         }
2115
2116         id_map.xid = *id;
2117         id_maps[0] = &id_map;
2118         id_maps[1] = NULL;
2119
2120         status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2121         if (!NT_STATUS_IS_OK(status)) {
2122                 talloc_free(tmp_ctx);
2123                 return false;
2124         }
2125
2126         if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2127                 id->type = id_map.xid.type;
2128         }
2129         *sid = *id_map.sid;
2130         talloc_free(tmp_ctx);
2131         return true;
2132 }
2133
2134 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2135                                  struct unixid *id)
2136 {
2137         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2138                 m->private_data, struct pdb_samba_dsdb_state);
2139         struct id_map id_map;
2140         struct id_map *id_maps[2];
2141         NTSTATUS status;
2142         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2143         if (!tmp_ctx) {
2144                 return false;
2145         }
2146
2147         ZERO_STRUCT(id_map);
2148         id_map.sid = discard_const_p(struct dom_sid, sid);
2149         id_maps[0] = &id_map;
2150         id_maps[1] = NULL;
2151
2152         status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2153         talloc_free(tmp_ctx);
2154         if (!NT_STATUS_IS_OK(status)) {
2155                 return false;
2156         }
2157         if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2158                 *id = id_map.xid;
2159                 return true;
2160         }
2161         return false;
2162 }
2163
2164 static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2165 {
2166         return PDB_CAP_STORE_RIDS | PDB_CAP_ADS | PDB_CAP_TRUSTED_DOMAINS_EX;
2167 }
2168
2169 static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32_t *rid)
2170 {
2171         return false;
2172 }
2173
2174 static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2175                                       const char *domain, char** pwd,
2176                                       struct dom_sid *sid,
2177                                       time_t *pass_last_set_time)
2178 {
2179         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2180                 m->private_data, struct pdb_samba_dsdb_state);
2181         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2182         const char * const attrs[] = {
2183                 "securityIdentifier",
2184                 "flatName",
2185                 "trustPartner",
2186                 "trustAuthOutgoing",
2187                 "whenCreated",
2188                 "msDS-SupportedEncryptionTypes",
2189                 "trustAttributes",
2190                 "trustDirection",
2191                 "trustType",
2192                 NULL
2193         };
2194         struct ldb_message *msg;
2195         const struct ldb_val *password_val;
2196         int trust_direction_flags;
2197         int trust_type;
2198         int i;
2199         DATA_BLOB password_utf16;
2200         struct trustAuthInOutBlob password_blob;
2201         struct AuthenticationInformationArray *auth_array;
2202         char *password_talloc;
2203         size_t password_len;
2204         enum ndr_err_code ndr_err;
2205         NTSTATUS status;
2206         const char *netbios_domain = NULL;
2207         const struct dom_sid *domain_sid = NULL;
2208
2209         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2210                                        attrs, tmp_ctx, &msg);
2211         if (!NT_STATUS_IS_OK(status)) {
2212                 /*
2213                  * This can be called to work out of a domain is
2214                  * trusted, rather than just to get the password
2215                  */
2216                 DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
2217                           "It may not be a trusted domain.\n", domain,
2218                           nt_errstr(status)));
2219                 TALLOC_FREE(tmp_ctx);
2220                 return false;
2221         }
2222
2223         netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2224         if (netbios_domain == NULL) {
2225                 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2226                           domain));
2227                 TALLOC_FREE(tmp_ctx);
2228                 return false;
2229         }
2230
2231         domain_sid = samdb_result_dom_sid(tmp_ctx, msg, "securityIdentifier");
2232         if (domain_sid == NULL) {
2233                 DEBUG(2, ("Trusted domain %s has no securityIdentifier defined.\n",
2234                           domain));
2235                 TALLOC_FREE(tmp_ctx);
2236                 return false;
2237         }
2238
2239         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2240         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2241                 DEBUG(2, ("Trusted domain %s is is not an outbound trust.\n",
2242                           domain));
2243                 TALLOC_FREE(tmp_ctx);
2244                 return false;
2245         }
2246
2247         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2248         if (trust_type == LSA_TRUST_TYPE_MIT) {
2249                 DEBUG(1, ("Trusted domain %s is is not an AD trust "
2250                           "(trustType == LSA_TRUST_TYPE_MIT).\n",
2251                           domain));
2252                 TALLOC_FREE(tmp_ctx);
2253                 return false;
2254         }
2255
2256         password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2257         if (password_val == NULL) {
2258                 DEBUG(2, ("Failed to get trusted domain password for %s, "
2259                           "attribute trustAuthOutgoing not returned.\n", domain));
2260                 TALLOC_FREE(tmp_ctx);
2261                 return false;
2262         }
2263
2264         ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2265                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2266         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2267                 DEBUG(0, ("Failed to get trusted domain password for %s, "
2268                           "attribute trustAuthOutgoing could not be parsed %s.\n",
2269                           domain,
2270                           ndr_map_error2string(ndr_err)));
2271                 TALLOC_FREE(tmp_ctx);
2272                 return false;
2273         }
2274
2275         auth_array = &password_blob.current;
2276
2277         for (i=0; i < auth_array->count; i++) {
2278                 if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
2279                         break;
2280                 }
2281         }
2282
2283         if (i == auth_array->count) {
2284                 DEBUG(0, ("Trusted domain %s does not have a "
2285                           "clear-text password stored\n",
2286                           domain));
2287                 TALLOC_FREE(tmp_ctx);
2288                 return false;
2289         }
2290
2291         password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
2292                                          auth_array->array[i].AuthInfo.clear.size);
2293
2294         /*
2295          * In the future, make this function return a
2296          * cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash()
2297          * but for now convert to UTF8 and fail if the string can not be converted.
2298          *
2299          * We can't safely convert the random strings windows uses into
2300          * utf8.
2301          */
2302         if (!convert_string_talloc(tmp_ctx,
2303                                    CH_UTF16MUNGED, CH_UTF8,
2304                                    password_utf16.data, password_utf16.length,
2305                                    (void *)&password_talloc,
2306                                    &password_len)) {
2307                 DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
2308                           " to UTF8. This may be a password set from Windows.\n",
2309                           domain));
2310                 TALLOC_FREE(tmp_ctx);
2311                 return false;
2312         }
2313         *pwd = SMB_STRNDUP(password_talloc, password_len);
2314         if (pass_last_set_time) {
2315                 *pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
2316         }
2317
2318         if (sid != NULL) {
2319                 sid_copy(sid, domain_sid);
2320         }
2321
2322         TALLOC_FREE(tmp_ctx);
2323         return true;
2324 }
2325
2326 static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
2327                                                     const char *domain,
2328                                                     TALLOC_CTX *mem_ctx,
2329                                                     struct cli_credentials **_creds)
2330 {
2331         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2332                 m->private_data, struct pdb_samba_dsdb_state);
2333         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2334         const char * const attrs[] = {
2335                 "securityIdentifier",
2336                 "flatName",
2337                 "trustPartner",
2338                 "trustAuthOutgoing",
2339                 "whenCreated",
2340                 "msDS-SupportedEncryptionTypes",
2341                 "trustAttributes",
2342                 "trustDirection",
2343                 "trustType",
2344                 NULL
2345         };
2346         struct ldb_message *msg;
2347         const struct ldb_val *password_val;
2348         int trust_direction_flags;
2349         int trust_type;
2350         int i;
2351         DATA_BLOB password_utf16 = {};
2352         struct samr_Password *password_nt = NULL;
2353         uint32_t password_version = 0;
2354         DATA_BLOB old_password_utf16 = {};
2355         struct samr_Password *old_password_nt = NULL;
2356         struct trustAuthInOutBlob password_blob;
2357         enum ndr_err_code ndr_err;
2358         NTSTATUS status;
2359         time_t last_set_time = 0;
2360         struct cli_credentials *creds = NULL;
2361         bool ok;
2362         const char *my_netbios_name = NULL;
2363         const char *my_netbios_domain = NULL;
2364         const char *my_dns_domain = NULL;
2365         const char *netbios_domain = NULL;
2366         char *account_name = NULL;
2367         char *principal_name = NULL;
2368         const char *dns_domain = NULL;
2369
2370         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2371                                        attrs, tmp_ctx, &msg);
2372         if (!NT_STATUS_IS_OK(status)) {
2373                 /*
2374                  * This can be called to work out of a domain is
2375                  * trusted, rather than just to get the password
2376                  */
2377                 DEBUG(2, ("Failed to get trusted domain password for %s - %s "
2378                           "It may not be a trusted domain.\n", domain,
2379                           nt_errstr(status)));
2380                 TALLOC_FREE(tmp_ctx);
2381                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2382         }
2383
2384         netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2385         if (netbios_domain == NULL) {
2386                 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2387                           domain));
2388                 TALLOC_FREE(tmp_ctx);
2389                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2390         }
2391
2392         dns_domain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2393
2394         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2395         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2396                 DEBUG(2, ("Trusted domain %s is is not an outbound trust.\n",
2397                           domain));
2398                 TALLOC_FREE(tmp_ctx);
2399                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2400         }
2401
2402         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2403         if (trust_type == LSA_TRUST_TYPE_MIT) {
2404                 DEBUG(1, ("Trusted domain %s is is not an AD trust "
2405                           "(trustType == LSA_TRUST_TYPE_MIT).\n",
2406                           domain));
2407                 TALLOC_FREE(tmp_ctx);
2408                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2409         }
2410
2411         password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2412         if (password_val == NULL) {
2413                 DEBUG(2, ("Failed to get trusted domain password for %s, "
2414                           "attribute trustAuthOutgoing not returned.\n", domain));
2415                 TALLOC_FREE(tmp_ctx);
2416                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2417         }
2418
2419         ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2420                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2421         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2422                 DEBUG(0, ("Failed to get trusted domain password for %s, "
2423                           "attribute trustAuthOutgoing could not be parsed %s.\n",
2424                           domain,
2425                           ndr_map_error2string(ndr_err)));
2426                 TALLOC_FREE(tmp_ctx);
2427                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2428         }
2429
2430         for (i=0; i < password_blob.current.count; i++) {
2431                 struct AuthenticationInformation *a =
2432                         &password_blob.current.array[i];
2433
2434                 switch (a->AuthType) {
2435                 case TRUST_AUTH_TYPE_NONE:
2436                         break;
2437
2438                 case TRUST_AUTH_TYPE_VERSION:
2439                         password_version = a->AuthInfo.version.version;
2440                         break;
2441
2442                 case TRUST_AUTH_TYPE_CLEAR:
2443                         last_set_time = nt_time_to_unix(a->LastUpdateTime);
2444
2445                         password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2446                                                          a->AuthInfo.clear.size);
2447                         password_nt = NULL;
2448                         break;
2449
2450                 case TRUST_AUTH_TYPE_NT4OWF:
2451                         if (password_utf16.length != 0) {
2452                                 break;
2453                         }
2454
2455                         last_set_time = nt_time_to_unix(a->LastUpdateTime);
2456
2457                         password_nt = &a->AuthInfo.nt4owf.password;
2458                         break;
2459                 }
2460         }
2461
2462         for (i=0; i < password_blob.previous.count; i++) {
2463                 struct AuthenticationInformation *a = &password_blob.previous.array[i];
2464
2465                 switch (a->AuthType) {
2466                 case TRUST_AUTH_TYPE_NONE:
2467                         break;
2468
2469                 case TRUST_AUTH_TYPE_VERSION:
2470                         break;
2471
2472                 case TRUST_AUTH_TYPE_CLEAR:
2473                         old_password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2474                                                          a->AuthInfo.clear.size);
2475                         old_password_nt = NULL;
2476                         break;
2477
2478                 case TRUST_AUTH_TYPE_NT4OWF:
2479                         if (old_password_utf16.length != 0) {
2480                                 break;
2481                         }
2482
2483                         old_password_nt = &a->AuthInfo.nt4owf.password;
2484                         break;
2485                 }
2486         }
2487
2488         if (password_utf16.length == 0 && password_nt == NULL) {
2489                 DEBUG(0, ("Trusted domain %s does not have a "
2490                           "clear-text nor nt password stored\n",
2491                           domain));
2492                 TALLOC_FREE(tmp_ctx);
2493                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2494         }
2495
2496         my_netbios_name = lpcfg_netbios_name(state->lp_ctx);
2497         my_netbios_domain = lpcfg_workgroup(state->lp_ctx);
2498         my_dns_domain = lpcfg_dnsdomain(state->lp_ctx);
2499
2500         creds = cli_credentials_init(tmp_ctx);
2501         if (creds == NULL) {
2502                 TALLOC_FREE(tmp_ctx);
2503                 return NT_STATUS_NO_MEMORY;
2504         }
2505
2506         ok = cli_credentials_set_workstation(creds, my_netbios_name, CRED_SPECIFIED);
2507         if (!ok) {
2508                 TALLOC_FREE(tmp_ctx);
2509                 return NT_STATUS_NO_MEMORY;
2510         }
2511
2512         ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2513         if (!ok) {
2514                 TALLOC_FREE(tmp_ctx);
2515                 return NT_STATUS_NO_MEMORY;
2516         }
2517         ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2518         if (!ok) {
2519                 TALLOC_FREE(tmp_ctx);
2520                 return NT_STATUS_NO_MEMORY;
2521         }
2522
2523         if (my_dns_domain != NULL && dns_domain != NULL) {
2524                 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DNS_DOMAIN);
2525                 account_name = talloc_asprintf(tmp_ctx, "%s.", my_dns_domain);
2526                 if (account_name == NULL) {
2527                         TALLOC_FREE(tmp_ctx);
2528                         return NT_STATUS_NO_MEMORY;
2529                 }
2530                 principal_name = talloc_asprintf(tmp_ctx, "%s$@%s", my_netbios_domain,
2531                                                  cli_credentials_get_realm(creds));
2532                 if (principal_name == NULL) {
2533                         TALLOC_FREE(tmp_ctx);
2534                         return NT_STATUS_NO_MEMORY;
2535                 }
2536         } else {
2537                 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DOMAIN);
2538                 account_name = talloc_asprintf(tmp_ctx, "%s$", my_netbios_domain);
2539                 if (account_name == NULL) {
2540                         TALLOC_FREE(tmp_ctx);
2541                         return NT_STATUS_NO_MEMORY;
2542                 }
2543                 principal_name = NULL;
2544         }
2545
2546         ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2547         if (!ok) {
2548                 TALLOC_FREE(tmp_ctx);
2549                 return NT_STATUS_NO_MEMORY;
2550         }
2551
2552         if (principal_name != NULL) {
2553                 ok = cli_credentials_set_principal(creds, principal_name,
2554                                                    CRED_SPECIFIED);
2555                 if (!ok) {
2556                         TALLOC_FREE(tmp_ctx);
2557                         return NT_STATUS_NO_MEMORY;
2558                 }
2559         }
2560
2561         if (old_password_nt != NULL) {
2562                 ok = cli_credentials_set_old_nt_hash(creds, old_password_nt);
2563                 if (!ok) {
2564                         TALLOC_FREE(tmp_ctx);
2565                         return NT_STATUS_NO_MEMORY;
2566                 }
2567         }
2568
2569         if (old_password_utf16.length > 0) {
2570                 ok = cli_credentials_set_old_utf16_password(creds,
2571                                                             &old_password_utf16);
2572                 if (!ok) {
2573                         TALLOC_FREE(tmp_ctx);
2574                         return NT_STATUS_NO_MEMORY;
2575                 }
2576         }
2577
2578         if (password_nt != NULL) {
2579                 ok = cli_credentials_set_nt_hash(creds, password_nt,
2580                                                  CRED_SPECIFIED);
2581                 if (!ok) {
2582                         TALLOC_FREE(tmp_ctx);
2583                         return NT_STATUS_NO_MEMORY;
2584                 }
2585         }
2586
2587         if (password_utf16.length > 0) {
2588                 ok = cli_credentials_set_utf16_password(creds,
2589                                                         &password_utf16,
2590                                                         CRED_SPECIFIED);
2591                 if (!ok) {
2592                         TALLOC_FREE(tmp_ctx);
2593                         return NT_STATUS_NO_MEMORY;
2594                 }
2595         }
2596
2597         cli_credentials_set_password_last_changed_time(creds, last_set_time);
2598         cli_credentials_set_kvno(creds, password_version);
2599
2600         if (password_utf16.length > 0 && dns_domain != NULL) {
2601                 /*
2602                  * Force kerberos if this is an active directory domain
2603                  */
2604                 cli_credentials_set_kerberos_state(creds,
2605                                                    CRED_MUST_USE_KERBEROS);
2606         } else  {
2607                 /*
2608                  * TODO: we should allow krb5 with the raw nt hash.
2609                  */
2610                 cli_credentials_set_kerberos_state(creds,
2611                                                    CRED_DONT_USE_KERBEROS);
2612         }
2613
2614         *_creds = talloc_move(mem_ctx, &creds);
2615         TALLOC_FREE(tmp_ctx);
2616         return NT_STATUS_OK;
2617 }
2618
2619 static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2620                                       const char* domain, const char* pwd,
2621                                       const struct dom_sid *sid)
2622 {
2623         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2624                 m->private_data, struct pdb_samba_dsdb_state);
2625         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2626         const char * const attrs[] = {
2627                 "trustAuthOutgoing",
2628                 "trustDirection",
2629                 "trustType",
2630                 NULL
2631         };
2632         struct ldb_message *msg = NULL;
2633         int trust_direction_flags;
2634         int trust_type;
2635         uint32_t i; /* The same type as old_blob.current.count */
2636         const struct ldb_val *old_val = NULL;
2637         struct trustAuthInOutBlob old_blob = {};
2638         uint32_t old_version = 0;
2639         uint32_t new_version = 0;
2640         DATA_BLOB new_utf16 = {};
2641         struct trustAuthInOutBlob new_blob = {};
2642         struct ldb_val new_val = {};
2643         struct timeval tv = timeval_current();
2644         NTTIME now = timeval_to_nttime(&tv);
2645         enum ndr_err_code ndr_err;
2646         NTSTATUS status;
2647         bool ok;
2648         int ret;
2649
2650         ret = ldb_transaction_start(state->ldb);
2651         if (ret != LDB_SUCCESS) {
2652                 DEBUG(2, ("Failed to start transaction.\n"));
2653                 TALLOC_FREE(tmp_ctx);
2654                 return false;
2655         }
2656
2657         ok = samdb_is_pdc(state->ldb);
2658         if (!ok) {
2659                 DEBUG(2, ("Password changes for domain %s are only allowed on a PDC.\n",
2660                           domain));
2661                 TALLOC_FREE(tmp_ctx);
2662                 ldb_transaction_cancel(state->ldb);
2663                 return false;
2664         }
2665
2666         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2667                                        attrs, tmp_ctx, &msg);
2668         if (!NT_STATUS_IS_OK(status)) {
2669                 /*
2670                  * This can be called to work out of a domain is
2671                  * trusted, rather than just to get the password
2672                  */
2673                 DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
2674                           "It may not be a trusted domain.\n", domain,
2675                           nt_errstr(status)));
2676                 TALLOC_FREE(tmp_ctx);
2677                 ldb_transaction_cancel(state->ldb);
2678                 return false;
2679         }
2680
2681         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2682         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2683                 DEBUG(2, ("Trusted domain %s is is not an outbound trust, can't set a password.\n",
2684                           domain));
2685                 TALLOC_FREE(tmp_ctx);
2686                 ldb_transaction_cancel(state->ldb);
2687                 return false;
2688         }
2689
2690         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2691         switch (trust_type) {
2692         case LSA_TRUST_TYPE_DOWNLEVEL:
2693         case LSA_TRUST_TYPE_UPLEVEL:
2694                 break;
2695         default:
2696                 DEBUG(0, ("Trusted domain %s is of type 0x%X - "
2697                           "password changes are not supported\n",
2698                           domain, (unsigned)trust_type));
2699                 TALLOC_FREE(tmp_ctx);
2700                 ldb_transaction_cancel(state->ldb);
2701                 return false;
2702         }
2703
2704         old_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2705         if (old_val != NULL) {
2706                 ndr_err = ndr_pull_struct_blob(old_val, tmp_ctx, &old_blob,
2707                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2708                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2709                         DEBUG(0, ("Failed to get trusted domain password for %s, "
2710                                   "attribute trustAuthOutgoing could not be parsed %s.\n",
2711                                   domain,
2712                                   ndr_map_error2string(ndr_err)));
2713                         TALLOC_FREE(tmp_ctx);
2714                         ldb_transaction_cancel(state->ldb);
2715                         return false;
2716                 }
2717         }
2718
2719         for (i=0; i < old_blob.current.count; i++) {
2720                 struct AuthenticationInformation *a =
2721                         &old_blob.current.array[i];
2722
2723                 switch (a->AuthType) {
2724                 case TRUST_AUTH_TYPE_NONE:
2725                         break;
2726
2727                 case TRUST_AUTH_TYPE_VERSION:
2728                         old_version = a->AuthInfo.version.version;
2729                         break;
2730
2731                 case TRUST_AUTH_TYPE_CLEAR:
2732                         break;
2733
2734                 case TRUST_AUTH_TYPE_NT4OWF:
2735                         break;
2736                 }
2737         }
2738
2739         new_version = old_version + 1;
2740         ok = convert_string_talloc(tmp_ctx,
2741                                    CH_UNIX, CH_UTF16,
2742                                    pwd, strlen(pwd),
2743                                    (void *)&new_utf16.data,
2744                                    &new_utf16.length);
2745         if (!ok) {
2746                 DEBUG(0, ("Failed to generate new_utf16 password for  domain %s\n",
2747                           domain));
2748                 TALLOC_FREE(tmp_ctx);
2749                 ldb_transaction_cancel(state->ldb);
2750                 return false;
2751         }
2752
2753         if (new_utf16.length < 28) {
2754                 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to short.\n",
2755                           new_utf16.length,
2756                           (unsigned)new_version,
2757                           domain));
2758                 TALLOC_FREE(tmp_ctx);
2759                 ldb_transaction_cancel(state->ldb);
2760                 return false;
2761         }
2762         if (new_utf16.length > 498) {
2763                 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to long.\n",
2764                           new_utf16.length,
2765                           (unsigned)new_version,
2766                           domain));
2767                 TALLOC_FREE(tmp_ctx);
2768                 ldb_transaction_cancel(state->ldb);
2769                 return false;
2770         }
2771
2772         new_blob.count = MAX(old_blob.current.count, 2);
2773         new_blob.current.array = talloc_zero_array(tmp_ctx,
2774                                         struct AuthenticationInformation,
2775                                         new_blob.count);
2776         if (new_blob.current.array == NULL) {
2777                 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2778                           (unsigned)new_blob.count));
2779                 TALLOC_FREE(tmp_ctx);
2780                 ldb_transaction_cancel(state->ldb);
2781                 return false;
2782         }
2783         new_blob.previous.array = talloc_zero_array(tmp_ctx,
2784                                         struct AuthenticationInformation,
2785                                         new_blob.count);
2786         if (new_blob.current.array == NULL) {
2787                 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2788                           (unsigned)new_blob.count));
2789                 TALLOC_FREE(tmp_ctx);
2790                 ldb_transaction_cancel(state->ldb);
2791                 return false;
2792         }
2793
2794         for (i = 0; i < old_blob.current.count; i++) {
2795                 struct AuthenticationInformation *o =
2796                         &old_blob.current.array[i];
2797                 struct AuthenticationInformation *p =
2798                         &new_blob.previous.array[i];
2799
2800                 *p = *o;
2801                 new_blob.previous.count++;
2802         }
2803         for (; i < new_blob.count; i++) {
2804                 struct AuthenticationInformation *pi =
2805                         &new_blob.previous.array[i];
2806
2807                 if (i == 0) {
2808                         /*
2809                          * new_blob.previous is still empty so
2810                          * we'll do new_blob.previous = new_blob.current
2811                          * below.
2812                          */
2813                         break;
2814                 }
2815
2816                 pi->LastUpdateTime = now;
2817                 pi->AuthType = TRUST_AUTH_TYPE_NONE;
2818                 new_blob.previous.count++;
2819         }
2820
2821         for (i = 0; i < new_blob.count; i++) {
2822                 struct AuthenticationInformation *ci =
2823                         &new_blob.current.array[i];
2824
2825                 ci->LastUpdateTime = now;
2826                 switch (i) {
2827                 case 0:
2828                         ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
2829                         ci->AuthInfo.clear.size = new_utf16.length;
2830                         ci->AuthInfo.clear.password = new_utf16.data;
2831                         break;
2832                 case 1:
2833                         ci->AuthType = TRUST_AUTH_TYPE_VERSION;
2834                         ci->AuthInfo.version.version = new_version;
2835                         break;
2836                 default:
2837                         ci->AuthType = TRUST_AUTH_TYPE_NONE;
2838                         break;
2839                 }
2840
2841                 new_blob.current.count++;
2842         }
2843
2844         if (new_blob.previous.count == 0) {
2845                 TALLOC_FREE(new_blob.previous.array);
2846                 new_blob.previous = new_blob.current;
2847         }
2848
2849         ndr_err = ndr_push_struct_blob(&new_val, tmp_ctx, &new_blob,
2850                         (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
2851         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2852                 DEBUG(0, ("Failed to generate trustAuthOutgoing for "
2853                           "trusted domain password for %s: %s.\n",
2854                           domain, ndr_map_error2string(ndr_err)));
2855                 TALLOC_FREE(tmp_ctx);
2856                 ldb_transaction_cancel(state->ldb);
2857                 return false;
2858         }
2859
2860         msg->num_elements = 0;
2861         ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2862                                 LDB_FLAG_MOD_REPLACE, NULL);
2863         if (ret != LDB_SUCCESS) {
2864                 DEBUG(0, ("ldb_msg_add_empty() failed\n"));
2865                 TALLOC_FREE(tmp_ctx);
2866                 ldb_transaction_cancel(state->ldb);
2867                 return false;
2868         }
2869         ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2870                                 &new_val, NULL);
2871         if (ret != LDB_SUCCESS) {
2872                 DEBUG(0, ("ldb_msg_add_value() failed\n"));
2873                 TALLOC_FREE(tmp_ctx);
2874                 ldb_transaction_cancel(state->ldb);
2875                 return false;
2876         }
2877
2878         ret = ldb_modify(state->ldb, msg);
2879         if (ret != LDB_SUCCESS) {
2880                 DEBUG(0, ("Failed to replace trustAuthOutgoing for "
2881                           "trusted domain password for %s: %s - %s\n",
2882                           domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2883                 TALLOC_FREE(tmp_ctx);
2884                 ldb_transaction_cancel(state->ldb);
2885                 return false;
2886         }
2887
2888         ret = ldb_transaction_commit(state->ldb);
2889         if (ret != LDB_SUCCESS) {
2890                 DEBUG(0, ("Failed to commit trustAuthOutgoing for "
2891                           "trusted domain password for %s: %s - %s\n",
2892                           domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2893                 TALLOC_FREE(tmp_ctx);
2894                 return false;
2895         }
2896
2897         DEBUG(1, ("Added new_version[%u] to trustAuthOutgoing for "
2898                   "trusted domain password for %s.\n",
2899                   (unsigned)new_version, domain));
2900         TALLOC_FREE(tmp_ctx);
2901         return true;
2902 }
2903
2904 static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2905                                       const char *domain)
2906 {
2907         return false;
2908 }
2909
2910 static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2911                                          TALLOC_CTX *mem_ctx,
2912                                          uint32_t *_num_domains,
2913                                          struct trustdom_info ***_domains)
2914 {
2915         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2916                 m->private_data, struct pdb_samba_dsdb_state);
2917         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2918         const char * const attrs[] = {
2919                 "securityIdentifier",
2920                 "flatName",
2921                 "trustDirection",
2922                 NULL
2923         };
2924         struct ldb_result *res = NULL;
2925         unsigned int i;
2926         struct trustdom_info **domains = NULL;
2927         NTSTATUS status;
2928         uint32_t di = 0;
2929
2930         *_num_domains = 0;
2931         *_domains = NULL;
2932
2933         status = dsdb_trust_search_tdos(state->ldb, NULL,
2934                                         attrs, tmp_ctx, &res);
2935         if (!NT_STATUS_IS_OK(status)) {
2936                 DBG_ERR("dsdb_trust_search_tdos() - %s ", nt_errstr(status));
2937                 TALLOC_FREE(tmp_ctx);
2938                 return status;
2939         }
2940
2941         if (res->count == 0) {
2942                 TALLOC_FREE(tmp_ctx);
2943                 return NT_STATUS_OK;
2944         }
2945
2946         domains = talloc_zero_array(tmp_ctx, struct trustdom_info *,
2947                                     res->count);
2948         if (domains == NULL) {
2949                 TALLOC_FREE(tmp_ctx);
2950                 return NT_STATUS_NO_MEMORY;
2951         }
2952
2953         for (i = 0; i < res->count; i++) {
2954                 struct ldb_message *msg = res->msgs[i];
2955                 struct trustdom_info *d = NULL;
2956                 const char *name = NULL;
2957                 struct dom_sid *sid = NULL;
2958                 uint32_t direction;
2959
2960                 d = talloc_zero(domains, struct trustdom_info);
2961                 if (d == NULL) {
2962                         TALLOC_FREE(tmp_ctx);
2963                         return NT_STATUS_NO_MEMORY;
2964                 }
2965
2966                 name = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2967                 if (name == NULL) {
2968                         TALLOC_FREE(tmp_ctx);
2969                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2970                 }
2971                 sid = samdb_result_dom_sid(msg, msg, "securityIdentifier");
2972                 if (sid == NULL) {
2973                         continue;
2974                 }
2975
2976                 direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
2977                 if (!(direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2978                         continue;
2979                 }
2980
2981                 d->name = talloc_strdup(d, name);
2982                 if (d->name == NULL) {
2983                         TALLOC_FREE(tmp_ctx);
2984                         return NT_STATUS_NO_MEMORY;
2985                 }
2986                 d->sid = *sid;
2987
2988                 domains[di++] = d;
2989         }
2990
2991         domains = talloc_realloc(domains, domains, struct trustdom_info *, di);
2992         *_domains = talloc_move(mem_ctx, &domains);
2993         *_num_domains = di;
2994         TALLOC_FREE(tmp_ctx);
2995         return NT_STATUS_OK;
2996 }
2997
2998 static NTSTATUS pdb_samba_dsdb_msg_to_trusted_domain(const struct ldb_message *msg,
2999                                                 TALLOC_CTX *mem_ctx,
3000                                                 struct pdb_trusted_domain **_d)
3001 {
3002         struct pdb_trusted_domain *d = NULL;
3003         const char *str = NULL;
3004         struct dom_sid *sid = NULL;
3005         const struct ldb_val *val = NULL;
3006         uint64_t val64;
3007
3008         *_d = NULL;
3009
3010         d = talloc_zero(mem_ctx, struct pdb_trusted_domain);
3011         if (d == NULL) {
3012                 return NT_STATUS_NO_MEMORY;
3013         }
3014
3015         str = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
3016         if (str == NULL) {
3017                 TALLOC_FREE(d);
3018                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3019         }
3020         d->netbios_name = talloc_strdup(d, str);
3021         if (d->netbios_name == NULL) {
3022                 TALLOC_FREE(d);
3023                 return NT_STATUS_NO_MEMORY;
3024         }
3025
3026         str = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
3027         if (str != NULL) {
3028                 d->domain_name = talloc_strdup(d, str);
3029                 if (d->domain_name == NULL) {
3030                         TALLOC_FREE(d);
3031                         return NT_STATUS_NO_MEMORY;
3032                 }
3033         }
3034
3035         sid = samdb_result_dom_sid(d, msg, "securityIdentifier");
3036         if (sid != NULL) {
3037                 d->security_identifier = *sid;
3038                 TALLOC_FREE(sid);
3039         }
3040
3041         val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
3042         if (val != NULL) {
3043                 d->trust_auth_outgoing = data_blob_dup_talloc(d, *val);
3044                 if (d->trust_auth_outgoing.data == NULL) {
3045                         TALLOC_FREE(d);
3046                         return NT_STATUS_NO_MEMORY;
3047                 }
3048         }
3049         val = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
3050         if (val != NULL) {
3051                 d->trust_auth_incoming = data_blob_dup_talloc(d, *val);
3052                 if (d->trust_auth_incoming.data == NULL) {
3053                         TALLOC_FREE(d);
3054                         return NT_STATUS_NO_MEMORY;
3055                 }
3056         }
3057
3058         d->trust_direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
3059         d->trust_type = ldb_msg_find_attr_as_uint(msg, "trustType", 0);
3060         d->trust_attributes = ldb_msg_find_attr_as_uint(msg, "trustAttributes", 0);
3061
3062         val64 = ldb_msg_find_attr_as_uint64(msg, "trustPosixOffset", UINT64_MAX);
3063         if (val64 != UINT64_MAX) {
3064                 d->trust_posix_offset = talloc(d, uint32_t);
3065                 if (d->trust_posix_offset == NULL) {
3066                         TALLOC_FREE(d);
3067                         return NT_STATUS_NO_MEMORY;
3068                 }
3069                 *d->trust_posix_offset = (uint32_t)val64;
3070         }
3071
3072         val64 = ldb_msg_find_attr_as_uint64(msg, "msDS-SupportedEncryptionTypes", UINT64_MAX);
3073         if (val64 != UINT64_MAX) {
3074                 d->supported_enc_type = talloc(d, uint32_t);
3075                 if (d->supported_enc_type == NULL) {
3076                         TALLOC_FREE(d);
3077                         return NT_STATUS_NO_MEMORY;
3078                 }
3079                 *d->supported_enc_type = (uint32_t)val64;
3080         }
3081
3082         val = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3083         if (val != NULL) {
3084                 d->trust_forest_trust_info = data_blob_dup_talloc(d, *val);
3085                 if (d->trust_forest_trust_info.data == NULL) {
3086                         TALLOC_FREE(d);
3087                         return NT_STATUS_NO_MEMORY;
3088                 }
3089         }
3090
3091         *_d = d;
3092         return NT_STATUS_OK;
3093 }
3094
3095 static NTSTATUS pdb_samba_dsdb_get_trusted_domain(struct pdb_methods *m,
3096                                                   TALLOC_CTX *mem_ctx,
3097                                                   const char *domain,
3098                                                   struct pdb_trusted_domain **td)
3099 {
3100         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3101                 m->private_data, struct pdb_samba_dsdb_state);
3102         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3103         const char * const attrs[] = {
3104                 "securityIdentifier",
3105                 "flatName",
3106                 "trustPartner",
3107                 "trustAuthOutgoing",
3108                 "trustAuthIncoming",
3109                 "trustAttributes",
3110                 "trustDirection",
3111                 "trustType",
3112                 "trustPosixOffset",
3113                 "msDS-SupportedEncryptionTypes",
3114                 "msDS-TrustForestTrustInfo",
3115                 NULL
3116         };
3117         struct ldb_message *msg = NULL;
3118         struct pdb_trusted_domain *d = NULL;
3119         NTSTATUS status;
3120
3121         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
3122                                        attrs, tmp_ctx, &msg);
3123         if (!NT_STATUS_IS_OK(status)) {
3124                 DBG_ERR("dsdb_trust_search_tdo(%s) - %s ",
3125                         domain, nt_errstr(status));
3126                 TALLOC_FREE(tmp_ctx);
3127                 return status;
3128         }
3129
3130         status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3131         if (!NT_STATUS_IS_OK(status)) {
3132                 DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s ",
3133                         domain, nt_errstr(status));
3134                 TALLOC_FREE(tmp_ctx);
3135                 return status;
3136         }
3137
3138         *td = d;
3139         TALLOC_FREE(tmp_ctx);
3140         return NT_STATUS_OK;
3141 }
3142
3143 static NTSTATUS pdb_samba_dsdb_get_trusted_domain_by_sid(struct pdb_methods *m,
3144                                                          TALLOC_CTX *mem_ctx,
3145                                                          struct dom_sid *sid,
3146                                                          struct pdb_trusted_domain **td)
3147 {
3148         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3149                 m->private_data, struct pdb_samba_dsdb_state);
3150         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3151         const char * const attrs[] = {
3152                 "securityIdentifier",
3153                 "flatName",
3154                 "trustPartner",
3155                 "trustAuthOutgoing",
3156                 "trustAuthIncoming",
3157                 "trustAttributes",
3158                 "trustDirection",
3159                 "trustType",
3160                 "trustPosixOffset",
3161                 "msDS-SupportedEncryptionTypes",
3162                 "msDS-TrustForestTrustInfo",
3163                 NULL
3164         };
3165         struct ldb_message *msg = NULL;
3166         struct pdb_trusted_domain *d = NULL;
3167         struct dom_sid_buf buf;
3168         NTSTATUS status;
3169
3170         status = dsdb_trust_search_tdo_by_sid(state->ldb, sid,
3171                                               attrs, tmp_ctx, &msg);
3172         if (!NT_STATUS_IS_OK(status)) {
3173                 DBG_ERR("dsdb_trust_search_tdo_by_sid(%s) - %s ",
3174                         dom_sid_str_buf(sid, &buf),
3175                         nt_errstr(status));
3176                 TALLOC_FREE(tmp_ctx);
3177                 return status;
3178         }
3179
3180         status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3181         if (!NT_STATUS_IS_OK(status)) {
3182                 DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s ",
3183                         dom_sid_str_buf(sid, &buf),
3184                         nt_errstr(status));
3185                 TALLOC_FREE(tmp_ctx);
3186                 return status;
3187         }
3188
3189         *td = d;
3190         TALLOC_FREE(tmp_ctx);
3191         return NT_STATUS_OK;
3192 }
3193
3194 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
3195                                struct ldb_context *sam_ldb,
3196                                struct ldb_dn *base_dn,
3197                                const char *netbios_name,
3198                                struct trustAuthInOutBlob *taiob)
3199 {
3200         struct ldb_request *req = NULL;
3201         struct ldb_message *msg = NULL;
3202         struct ldb_dn *dn = NULL;
3203         uint32_t i;
3204         int ret;
3205         bool ok;
3206
3207         dn = ldb_dn_copy(mem_ctx, base_dn);
3208         if (dn == NULL) {
3209                 return NT_STATUS_NO_MEMORY;
3210         }
3211         ok = ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name);
3212         if (!ok) {
3213                 return NT_STATUS_NO_MEMORY;
3214         }
3215
3216         msg = ldb_msg_new(mem_ctx);
3217         if (msg == NULL) {
3218                 return NT_STATUS_NO_MEMORY;
3219         }
3220         msg->dn = dn;
3221
3222         ret = ldb_msg_add_string(msg, "objectClass", "user");
3223         if (ret != LDB_SUCCESS) {
3224                 return NT_STATUS_NO_MEMORY;
3225         }
3226
3227         ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
3228         if (ret != LDB_SUCCESS) {
3229                 return NT_STATUS_NO_MEMORY;
3230         }
3231
3232         ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
3233                                  UF_INTERDOMAIN_TRUST_ACCOUNT);
3234         if (ret != LDB_SUCCESS) {
3235                 return NT_STATUS_NO_MEMORY;
3236         }
3237
3238         for (i = 0; i < taiob->count; i++) {
3239                 struct AuthenticationInformation *auth_info =
3240                         &taiob->current.array[i];
3241                 const char *attribute = NULL;
3242                 struct ldb_val v;
3243
3244                 switch (taiob->current.array[i].AuthType) {
3245                 case TRUST_AUTH_TYPE_NT4OWF:
3246                         attribute = "unicodePwd";
3247                         v.data = (uint8_t *)&auth_info->AuthInfo.nt4owf.password;
3248                         v.length = 16;
3249                         break;
3250
3251                 case TRUST_AUTH_TYPE_CLEAR:
3252                         attribute = "clearTextPassword";
3253                         v.data = auth_info->AuthInfo.clear.password;
3254                         v.length = auth_info->AuthInfo.clear.size;
3255                         break;
3256
3257                 default:
3258                         continue;
3259                 }
3260
3261                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
3262                 if (ret != LDB_SUCCESS) {
3263                         return NT_STATUS_NO_MEMORY;
3264                 }
3265         }
3266
3267         /* create the trusted_domain user account */
3268         ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
3269                                 ldb_op_default_callback, NULL);
3270         if (ret != LDB_SUCCESS) {
3271                 return NT_STATUS_NO_MEMORY;
3272         }
3273
3274         ret = ldb_request_add_control(
3275                 req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
3276                 false, NULL);
3277         if (ret != LDB_SUCCESS) {
3278                 return NT_STATUS_NO_MEMORY;
3279         }
3280
3281         ret = dsdb_autotransaction_request(sam_ldb, req);
3282         if (ret != LDB_SUCCESS) {
3283                 DEBUG(0,("Failed to create user record %s: %s\n",
3284                          ldb_dn_get_linearized(msg->dn),
3285                          ldb_errstring(sam_ldb)));
3286
3287                 switch (ret) {
3288                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
3289                         return NT_STATUS_DOMAIN_EXISTS;
3290                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3291                         return NT_STATUS_ACCESS_DENIED;
3292                 default:
3293                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3294                 }
3295         }
3296
3297         return NT_STATUS_OK;
3298 }
3299
3300 static NTSTATUS pdb_samba_dsdb_set_trusted_domain(struct pdb_methods *methods,
3301                                                   const char* domain,
3302                                                   const struct pdb_trusted_domain *td)
3303 {
3304         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3305                 methods->private_data, struct pdb_samba_dsdb_state);
3306         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3307         bool in_txn = false;
3308         struct ldb_dn *base_dn = NULL;
3309         struct ldb_message *msg = NULL;
3310         const char *attrs[] = {
3311                 NULL
3312         };
3313         char *netbios_encoded = NULL;
3314         char *dns_encoded = NULL;
3315         char *sid_encoded = NULL;
3316         int ret;
3317         struct trustAuthInOutBlob taiob;
3318         enum ndr_err_code ndr_err;
3319         NTSTATUS status;
3320         bool ok;
3321
3322         base_dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(state->ldb));
3323         if (base_dn == NULL) {
3324                 TALLOC_FREE(tmp_ctx);
3325                 status = NT_STATUS_NO_MEMORY;
3326                 goto out;
3327         }
3328         /*
3329          * We expect S-1-5-21-A-B-C, but we don't
3330          * allow S-1-5-21-0-0-0 as this is used
3331          * for claims and compound identities.
3332          */
3333         ok = dom_sid_is_valid_account_domain(&td->security_identifier);
3334         if (!ok) {
3335                 status = NT_STATUS_INVALID_PARAMETER;
3336                 goto out;
3337         }
3338
3339         if (strequal(td->netbios_name, "BUILTIN")) {
3340                 status = NT_STATUS_INVALID_PARAMETER;
3341                 goto out;
3342         }
3343         if (strequal(td->domain_name, "BUILTIN")) {
3344                 status = NT_STATUS_INVALID_PARAMETER;
3345                 goto out;
3346         }
3347
3348         dns_encoded = ldb_binary_encode_string(tmp_ctx, td->domain_name);
3349         if (dns_encoded == NULL) {
3350                 status = NT_STATUS_NO_MEMORY;
3351                 goto out;
3352         }
3353         netbios_encoded = ldb_binary_encode_string(tmp_ctx, td->netbios_name);
3354         if (netbios_encoded == NULL) {
3355                 status =NT_STATUS_NO_MEMORY;
3356                 goto out;
3357         }
3358         sid_encoded = ldap_encode_ndr_dom_sid(tmp_ctx, &td->security_identifier);
3359         if (sid_encoded == NULL) {
3360                 status = NT_STATUS_NO_MEMORY;
3361                 goto out;
3362         }
3363
3364         ok = samdb_is_pdc(state->ldb);
3365         if (!ok) {
3366                 DBG_ERR("Adding TDO is only allowed on a PDC.\n");
3367                 TALLOC_FREE(tmp_ctx);
3368                 status = NT_STATUS_INVALID_DOMAIN_ROLE;
3369                 goto out;
3370         }
3371
3372         status = dsdb_trust_search_tdo(state->ldb,
3373                                        td->netbios_name,
3374                                        td->domain_name,
3375                                        attrs,
3376                                        tmp_ctx,
3377                                        &msg);
3378         if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3379                 DBG_ERR("dsdb_trust_search_tdo returned %s\n",
3380                         nt_errstr(status));
3381                 status = NT_STATUS_INVALID_DOMAIN_STATE;
3382                 goto out;
3383         }
3384
3385         ret = ldb_transaction_start(state->ldb);
3386         if (ret != LDB_SUCCESS) {
3387                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3388                 goto out;
3389         }
3390         in_txn = true;
3391
3392         msg = ldb_msg_new(tmp_ctx);
3393         if (msg == NULL) {
3394                 status = NT_STATUS_NO_MEMORY;
3395                 goto out;
3396         }
3397
3398         msg->dn = ldb_dn_copy(tmp_ctx, base_dn);
3399
3400         ok = ldb_dn_add_child_fmt(msg->dn, "cn=%s,cn=System", td->domain_name);
3401         if (!ok) {
3402                 status = NT_STATUS_NO_MEMORY;
3403                 goto out;
3404         }
3405
3406         ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
3407         if (ret != LDB_SUCCESS) {
3408                 status = NT_STATUS_NO_MEMORY;
3409                 goto out;
3410         }
3411
3412         ret = ldb_msg_add_string(msg, "flatname", td->netbios_name);
3413         if (ret != LDB_SUCCESS) {
3414                 status = NT_STATUS_NO_MEMORY;
3415                 goto out;
3416         }
3417
3418         ret = ldb_msg_add_string(msg, "trustPartner", td->domain_name);
3419         if (ret != LDB_SUCCESS) {
3420                 status = NT_STATUS_NO_MEMORY;
3421                 goto out;
3422         }
3423
3424         ret = samdb_msg_add_dom_sid(state->ldb,
3425                                     tmp_ctx,
3426                                     msg,
3427                                     "securityIdentifier",
3428                                     &td->security_identifier);
3429         if (ret != LDB_SUCCESS) {
3430                 status = NT_STATUS_NO_MEMORY;
3431                 goto out;
3432         }
3433
3434         ret = samdb_msg_add_int(state->ldb,
3435                                 tmp_ctx,
3436                                 msg,
3437                                 "trustType",
3438                                 td->trust_type);
3439         if (ret != LDB_SUCCESS) {
3440                 status = NT_STATUS_NO_MEMORY;
3441                 goto out;
3442         }
3443
3444         ret = samdb_msg_add_int(state->ldb,
3445                                 tmp_ctx,
3446                                 msg,
3447                                 "trustAttributes",
3448                                 td->trust_attributes);
3449         if (ret != LDB_SUCCESS) {
3450                 status =NT_STATUS_NO_MEMORY;
3451                 goto out;
3452         }
3453
3454         ret = samdb_msg_add_int(state->ldb,
3455                                 tmp_ctx,
3456                                 msg,
3457                                 "trustDirection",
3458                                 td->trust_direction);
3459         if (ret != LDB_SUCCESS) {
3460                 status = NT_STATUS_NO_MEMORY;
3461                 goto out;
3462         }
3463
3464         if (td->trust_auth_incoming.data != NULL) {
3465                 ret = ldb_msg_add_value(msg,
3466                                         "trustAuthIncoming",
3467                                         &td->trust_auth_incoming,
3468                                         NULL);
3469                 if (ret != LDB_SUCCESS) {
3470                         status = NT_STATUS_NO_MEMORY;
3471                         goto out;
3472                 }
3473         }
3474         if (td->trust_auth_outgoing.data != NULL) {
3475                 ret = ldb_msg_add_value(msg,
3476                                         "trustAuthOutgoing",
3477                                         &td->trust_auth_outgoing,
3478                                         NULL);
3479                 if (ret != LDB_SUCCESS) {
3480                         status = NT_STATUS_NO_MEMORY;
3481                         goto out;
3482                 }
3483         }
3484
3485         /* create the trusted_domain */
3486         ret = ldb_add(state->ldb, msg);
3487         switch (ret) {
3488         case  LDB_SUCCESS:
3489                 break;
3490
3491         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
3492                 DBG_ERR("Failed to create trusted domain record %s: %s\n",
3493                         ldb_dn_get_linearized(msg->dn),
3494                         ldb_errstring(state->ldb));
3495                 status = NT_STATUS_DOMAIN_EXISTS;
3496                 goto out;
3497
3498         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3499                 DBG_ERR("Failed to create trusted domain record %s: %s\n",
3500                         ldb_dn_get_linearized(msg->dn),
3501                         ldb_errstring(state->ldb));
3502                 status = NT_STATUS_ACCESS_DENIED;
3503                 goto out;
3504
3505         default:
3506                 DBG_ERR("Failed to create trusted domain record %s: %s\n",
3507                         ldb_dn_get_linearized(msg->dn),
3508                         ldb_errstring(state->ldb));
3509                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3510                 goto out;
3511         }
3512
3513         ndr_err = ndr_pull_struct_blob(
3514                 &td->trust_auth_outgoing,
3515                 tmp_ctx,
3516                 &taiob,
3517                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
3518         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3519                 status = ndr_map_error2ntstatus(ndr_err);
3520                 goto out;
3521         }
3522
3523         if (td->trust_direction == LSA_TRUST_DIRECTION_INBOUND) {
3524                 status = add_trust_user(tmp_ctx,
3525                                         state->ldb,
3526                                         base_dn,
3527                                         td->netbios_name,
3528                                         &taiob);
3529                 if (!NT_STATUS_IS_OK(status)) {
3530                         goto out;
3531                 }
3532         }
3533
3534         ret = ldb_transaction_commit(state->ldb);
3535         if (ret != LDB_SUCCESS) {
3536                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3537         }
3538         in_txn = false;
3539
3540         /*
3541          * TODO: Notify winbindd that we have a new trust
3542          */
3543
3544         status = NT_STATUS_OK;
3545
3546 out:
3547         if (in_txn) {
3548                 ldb_transaction_cancel(state->ldb);
3549         }
3550         TALLOC_FREE(tmp_ctx);
3551         return status;
3552 }
3553
3554 static NTSTATUS delete_trust_user(TALLOC_CTX *mem_ctx,
3555                                   struct pdb_samba_dsdb_state *state,
3556                                   const char *trust_user)
3557 {
3558         const char *attrs[] = { "userAccountControl", NULL };
3559         struct ldb_message **msgs;
3560         uint32_t uac;
3561         int ret;
3562
3563         ret = gendb_search(state->ldb,
3564                            mem_ctx,
3565                            ldb_get_default_basedn(state->ldb),
3566                            &msgs,
3567                            attrs,
3568                            "samAccountName=%s$",
3569                            trust_user);
3570         if (ret > 1) {
3571                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3572         }
3573
3574         if (ret == 0) {
3575                 return NT_STATUS_OK;
3576         }
3577
3578         uac = ldb_msg_find_attr_as_uint(msgs[0],
3579                                         "userAccountControl",
3580                                         0);
3581         if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3582                 return NT_STATUS_OBJECT_NAME_COLLISION;
3583         }
3584
3585         ret = ldb_delete(state->ldb, msgs[0]->dn);
3586         switch (ret) {
3587         case LDB_SUCCESS:
3588                 break;
3589         case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3590                 return NT_STATUS_ACCESS_DENIED;
3591         default:
3592                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3593         }
3594
3595         return NT_STATUS_OK;
3596 }
3597
3598 static NTSTATUS pdb_samba_dsdb_del_trusted_domain(struct pdb_methods *methods,
3599                                                   const char *domain)
3600 {
3601         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3602                 methods->private_data, struct pdb_samba_dsdb_state);
3603         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3604         struct pdb_trusted_domain *td = NULL;
3605         struct ldb_dn *tdo_dn = NULL;
3606         bool in_txn = false;
3607         NTSTATUS status;
3608         int ret;
3609         bool ok;
3610
3611         status = pdb_samba_dsdb_get_trusted_domain(methods,
3612                                                    tmp_ctx,
3613                                                    domain,
3614                                                    &td);
3615         if (!NT_STATUS_IS_OK(status)) {
3616                 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3617                         DBG_ERR("Searching TDO for %s returned %s\n",
3618                                 domain, nt_errstr(status));
3619                         return status;
3620                 }
3621                 DBG_NOTICE("No TDO object for %s\n", domain);
3622                 return NT_STATUS_OK;
3623         }
3624
3625         tdo_dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(state->ldb));
3626         if (tdo_dn == NULL) {
3627                 status = NT_STATUS_NO_MEMORY;
3628                 goto out;
3629         }
3630
3631         ok = ldb_dn_add_child_fmt(tdo_dn, "cn=%s,cn=System", domain);
3632         if (!ok) {
3633                 TALLOC_FREE(tmp_ctx);
3634                 status = NT_STATUS_NO_MEMORY;
3635                 goto out;
3636         }
3637
3638         ret = ldb_transaction_start(state->ldb);
3639         if (ret != LDB_SUCCESS) {
3640                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3641                 goto out;
3642         }
3643         in_txn = true;
3644
3645         ret = ldb_delete(state->ldb, tdo_dn);
3646         if (ret != LDB_SUCCESS) {
3647                 status = NT_STATUS_INVALID_HANDLE;
3648                 goto out;
3649         }
3650
3651         if (td->trust_direction == LSA_TRUST_DIRECTION_INBOUND) {
3652                 status = delete_trust_user(tmp_ctx, state, domain);
3653                 if (!NT_STATUS_IS_OK(status)) {
3654                         goto out;
3655                 }
3656         }
3657
3658         ret = ldb_transaction_commit(state->ldb);
3659         if (ret != LDB_SUCCESS) {
3660                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3661                 goto out;
3662         }
3663         in_txn = false;
3664
3665         status = NT_STATUS_OK;
3666
3667 out:
3668         if (in_txn) {
3669                 ldb_transaction_cancel(state->ldb);
3670         }
3671         TALLOC_FREE(tmp_ctx);
3672
3673         return status;
3674 }
3675
3676 static NTSTATUS pdb_samba_dsdb_enum_trusted_domains(struct pdb_methods *m,
3677                                                     TALLOC_CTX *mem_ctx,
3678                                                     uint32_t *_num_domains,
3679                                                     struct pdb_trusted_domain ***_domains)
3680 {
3681         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3682                 m->private_data, struct pdb_samba_dsdb_state);
3683         TALLOC_CTX *tmp_ctx = talloc_stackframe();
3684         const char * const attrs[] = {
3685                 "securityIdentifier",
3686                 "flatName",
3687                 "trustPartner",
3688                 "trustAuthOutgoing",
3689                 "trustAuthIncoming",
3690                 "trustAttributes",
3691                 "trustDirection",
3692                 "trustType",
3693                 "trustPosixOffset",
3694                 "msDS-SupportedEncryptionTypes",
3695                 "msDS-TrustForestTrustInfo",
3696                 NULL
3697         };
3698         struct ldb_result *res = NULL;
3699         unsigned int i;
3700         struct pdb_trusted_domain **domains = NULL;
3701         NTSTATUS status;
3702         uint32_t di = 0;
3703
3704         *_num_domains = 0;
3705         *_domains = NULL;
3706
3707         status = dsdb_trust_search_tdos(state->ldb, NULL,
3708                                         attrs, tmp_ctx, &res);
3709         if (!NT_STATUS_IS_OK(status)) {
3710                 DBG_ERR("dsdb_trust_search_tdos() - %s ", nt_errstr(status));
3711                 TALLOC_FREE(tmp_ctx);
3712                 return status;
3713         }
3714
3715         if (res->count == 0) {
3716                 TALLOC_FREE(tmp_ctx);
3717                 return NT_STATUS_OK;
3718         }
3719
3720         domains = talloc_zero_array(tmp_ctx, struct pdb_trusted_domain *,
3721                                     res->count);
3722         if (domains == NULL) {
3723                 TALLOC_FREE(tmp_ctx);
3724                 return NT_STATUS_NO_MEMORY;
3725         }
3726
3727         for (i = 0; i < res->count; i++) {
3728                 struct ldb_message *msg = res->msgs[i];
3729                 struct pdb_trusted_domain *d = NULL;
3730
3731                 status = pdb_samba_dsdb_msg_to_trusted_domain(msg, domains, &d);
3732                 if (!NT_STATUS_IS_OK(status)) {
3733                         DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain() - %s ",
3734                                 nt_errstr(status));
3735                         TALLOC_FREE(tmp_ctx);
3736                         return status;
3737                 }
3738
3739                 domains[di++] = d;
3740         }
3741
3742         domains = talloc_realloc(domains, domains, struct pdb_trusted_domain *,
3743                                  di);
3744         *_domains = talloc_move(mem_ctx, &domains);
3745         *_num_domains = di;
3746         TALLOC_FREE(tmp_ctx);
3747         return NT_STATUS_OK;
3748 }
3749
3750 static bool pdb_samba_dsdb_is_responsible_for_wellknown(struct pdb_methods *m)
3751 {
3752         return true;
3753 }
3754
3755 static bool pdb_samba_dsdb_is_responsible_for_everything_else(struct pdb_methods *m)
3756 {
3757         return true;
3758 }
3759
3760 static void pdb_samba_dsdb_init_methods(struct pdb_methods *m)
3761 {
3762         m->name = "samba_dsdb";
3763         m->get_domain_info = pdb_samba_dsdb_get_domain_info;
3764         m->getsampwnam = pdb_samba_dsdb_getsampwnam;
3765         m->getsampwsid = pdb_samba_dsdb_getsampwsid;
3766         m->create_user = pdb_samba_dsdb_create_user;
3767         m->delete_user = pdb_samba_dsdb_delete_user;
3768         m->add_sam_account = pdb_samba_dsdb_add_sam_account;
3769         m->update_sam_account = pdb_samba_dsdb_update_sam_account;
3770         m->delete_sam_account = pdb_samba_dsdb_delete_sam_account;
3771         m->rename_sam_account = pdb_samba_dsdb_rename_sam_account;
3772         m->update_login_attempts = pdb_samba_dsdb_update_login_attempts;
3773         m->getgrsid = pdb_samba_dsdb_getgrsid;
3774         m->getgrgid = pdb_samba_dsdb_getgrgid;
3775         m->getgrnam = pdb_samba_dsdb_getgrnam;
3776         m->create_dom_group = pdb_samba_dsdb_create_dom_group;
3777         m->delete_dom_group = pdb_samba_dsdb_delete_dom_group;
3778         m->add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry;
3779         m->update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry;
3780         m->delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry;
3781         m->enum_group_mapping = pdb_samba_dsdb_enum_group_mapping;
3782         m->enum_group_members = pdb_samba_dsdb_enum_group_members;
3783         m->enum_group_memberships = pdb_samba_dsdb_enum_group_memberships;
3784         m->set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group;
3785         m->add_groupmem = pdb_samba_dsdb_add_groupmem;
3786         m->del_groupmem = pdb_samba_dsdb_del_groupmem;
3787         m->create_alias = pdb_samba_dsdb_create_alias;
3788         m->delete_alias = pdb_samba_dsdb_delete_alias;
3789         m->get_aliasinfo = pdb_default_get_aliasinfo;
3790         m->add_aliasmem = pdb_samba_dsdb_add_aliasmem;
3791         m->del_aliasmem = pdb_samba_dsdb_del_aliasmem;
3792         m->enum_aliasmem = pdb_samba_dsdb_enum_aliasmem;
3793         m->enum_alias_memberships = pdb_samba_dsdb_enum_alias_memberships;
3794         m->lookup_rids = pdb_samba_dsdb_lookup_rids;
3795         m->lookup_names = pdb_samba_dsdb_lookup_names;
3796         m->get_account_policy = pdb_samba_dsdb_get_account_policy;
3797         m->set_account_policy = pdb_samba_dsdb_set_account_policy;
3798         m->get_seq_num = pdb_samba_dsdb_get_seq_num;
3799         m->search_users = pdb_samba_dsdb_search_users;
3800         m->search_groups = pdb_samba_dsdb_search_groups;
3801         m->search_aliases = pdb_samba_dsdb_search_aliases;
3802         m->id_to_sid = pdb_samba_dsdb_id_to_sid;
3803         m->sid_to_id = pdb_samba_dsdb_sid_to_id;
3804         m->capabilities = pdb_samba_dsdb_capabilities;
3805         m->new_rid = pdb_samba_dsdb_new_rid;
3806         m->get_trusteddom_pw = pdb_samba_dsdb_get_trusteddom_pw;
3807         m->get_trusteddom_creds = pdb_samba_dsdb_get_trusteddom_creds;
3808         m->set_trusteddom_pw = pdb_samba_dsdb_set_trusteddom_pw;
3809         m->del_trusteddom_pw = pdb_samba_dsdb_del_trusteddom_pw;
3810         m->enum_trusteddoms = pdb_samba_dsdb_enum_trusteddoms;
3811         m->get_trusted_domain = pdb_samba_dsdb_get_trusted_domain;
3812         m->get_trusted_domain_by_sid = pdb_samba_dsdb_get_trusted_domain_by_sid;
3813         m->set_trusted_domain = pdb_samba_dsdb_set_trusted_domain;
3814         m->del_trusted_domain = pdb_samba_dsdb_del_trusted_domain;
3815         m->enum_trusted_domains = pdb_samba_dsdb_enum_trusted_domains;
3816         m->is_responsible_for_wellknown =
3817                                 pdb_samba_dsdb_is_responsible_for_wellknown;
3818         m->is_responsible_for_everything_else =
3819                                 pdb_samba_dsdb_is_responsible_for_everything_else;
3820 }
3821
3822 static void free_private_data(void **vp)
3823 {
3824         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3825                 *vp, struct pdb_samba_dsdb_state);
3826         talloc_unlink(state, state->ldb);
3827         return;
3828 }
3829
3830 static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m)
3831 {
3832         struct pdb_domain_info *dom_info;
3833         struct dom_sid stored_sid;
3834         struct GUID stored_guid;
3835         bool sid_exists_and_matches = false;
3836         bool guid_exists_and_matches = false;
3837         bool ret;
3838
3839         dom_info = pdb_samba_dsdb_get_domain_info(m, m);
3840         if (!dom_info) {
3841                 return NT_STATUS_UNSUCCESSFUL;
3842         }
3843
3844         ret = secrets_fetch_domain_sid(dom_info->name, &stored_sid);
3845         if (ret) {
3846                 if (dom_sid_equal(&stored_sid, &dom_info->sid)) {
3847                         sid_exists_and_matches = true;
3848                 }
3849         }
3850
3851         if (sid_exists_and_matches == false) {
3852                 secrets_clear_domain_protection(dom_info->name);
3853                 ret = secrets_store_domain_sid(dom_info->name,
3854                                                &dom_info->sid);
3855                 ret &= secrets_mark_domain_protected(dom_info->name);
3856                 if (!ret) {
3857                         goto done;
3858                 }
3859         }
3860
3861         ret = secrets_fetch_domain_guid(dom_info->name, &stored_guid);
3862         if (ret) {
3863                 if (GUID_equal(&stored_guid, &dom_info->guid)) {
3864                         guid_exists_and_matches = true;
3865                 }
3866         }
3867
3868         if (guid_exists_and_matches == false) {
3869                 secrets_clear_domain_protection(dom_info->name);
3870                 ret = secrets_store_domain_guid(dom_info->name,
3871                                                &dom_info->guid);
3872                 ret &= secrets_mark_domain_protected(dom_info->name);
3873                 if (!ret) {
3874                         goto done;
3875                 }
3876         }
3877
3878 done:
3879         TALLOC_FREE(dom_info);
3880         if (!ret) {
3881                 return NT_STATUS_UNSUCCESSFUL;
3882         }
3883         return NT_STATUS_OK;
3884 }
3885
3886 static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
3887                              const char *location)
3888 {
3889         struct pdb_methods *m;
3890         struct pdb_samba_dsdb_state *state;
3891         NTSTATUS status;
3892         char *errstring = NULL;
3893         int ret;
3894
3895         if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
3896                 return status;
3897         }
3898
3899         state = talloc_zero(m, struct pdb_samba_dsdb_state);
3900         if (state == NULL) {
3901                 goto nomem;
3902         }
3903         m->private_data = state;
3904         m->free_private_data = free_private_data;
3905         pdb_samba_dsdb_init_methods(m);
3906
3907         state->ev = s4_event_context_init(state);
3908         if (!state->ev) {
3909                 DEBUG(0, ("s4_event_context_init failed\n"));
3910                 goto nomem;
3911         }
3912
3913         state->lp_ctx = loadparm_init_s3(state, loadparm_s3_helpers());
3914         if (state->lp_ctx == NULL) {
3915                 DEBUG(0, ("loadparm_init_s3 failed\n"));
3916                 goto nomem;
3917         }
3918
3919         if (location == NULL) {
3920                 location = "sam.ldb";
3921         }
3922
3923         ret = samdb_connect_url(state,
3924                                 state->ev,
3925                                 state->lp_ctx,
3926                                 system_session(state->lp_ctx),
3927                                 0,
3928                                 location,
3929                                 NULL,
3930                                 &state->ldb,
3931                                 &errstring);
3932
3933         if (!state->ldb) {
3934                 DEBUG(0, ("samdb_connect failed: %s: %s\n",
3935                           errstring, ldb_strerror(ret)));
3936                 status = NT_STATUS_INTERNAL_ERROR;
3937                 goto fail;
3938         }
3939
3940         state->idmap_ctx = idmap_init(state, state->ev,
3941                                       state->lp_ctx);
3942         if (!state->idmap_ctx) {
3943                 DEBUG(0, ("idmap failed\n"));
3944                 status = NT_STATUS_INTERNAL_ERROR;
3945                 goto fail;
3946         }
3947
3948         status = pdb_samba_dsdb_init_secrets(m);
3949         if (!NT_STATUS_IS_OK(status)) {
3950                 DEBUG(10, ("pdb_samba_dsdb_init_secrets failed!\n"));
3951                 goto fail;
3952         }
3953
3954         *pdb_method = m;
3955         return NT_STATUS_OK;
3956 nomem:
3957         status = NT_STATUS_NO_MEMORY;
3958 fail:
3959         TALLOC_FREE(m);
3960         return status;
3961 }
3962
3963 NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *);
3964 NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *ctx)
3965 {
3966         NTSTATUS status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba_dsdb",
3967                                               pdb_init_samba_dsdb);
3968         if (!NT_STATUS_IS_OK(status)) {
3969                 return status;
3970         }
3971         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4",
3972                                    pdb_init_samba_dsdb);
3973 }