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