idmap: unify passdb *id_to_sid methods
[bbaumbach/samba-autobuild/.git] / source3 / passdb / pdb_samba_dsdb.c
1 /*
2    Unix SMB/CIFS implementation.
3    pdb glue module for direct access to the dsdb via LDB APIs
4    Copyright (C) Volker Lendecke 2009-2011
5    Copyright (C) Andrew Bartlett 2010-2012
6    Copyright (C) Matthias Dieter Wallnöfer                 2009
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 /* This module, is a port of Volker's pdb_ads to ldb and DSDB APIs */
23
24 #include "includes.h"
25 #include "source3/include/passdb.h"
26 #include "source4/dsdb/samdb/samdb.h"
27 #include "ldb_errors.h"
28 #include "libcli/security/dom_sid.h"
29 #include "source4/winbind/idmap.h"
30 #include "librpc/gen_ndr/ndr_security.h"
31 #include "librpc/gen_ndr/ndr_drsblobs.h"
32 #include "librpc/gen_ndr/ndr_lsa.h"
33 #include "libds/common/flag_mapping.h"
34 #include "source4/lib/events/events.h"
35 #include "source4/auth/session.h"
36 #include "source4/auth/system_session_proto.h"
37 #include "lib/param/param.h"
38 #include "source4/dsdb/common/util.h"
39 #include "source3/include/secrets.h"
40 #include "source4/auth/auth_sam.h"
41
42 struct pdb_samba_dsdb_state {
43         struct tevent_context *ev;
44         struct ldb_context *ldb;
45         struct idmap_context *idmap_ctx;
46         struct loadparm_context *lp_ctx;
47 };
48
49 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
50                                     struct samu *sam_acct,
51                                     const struct dom_sid *sid);
52 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
53                                     const char *filter,
54                                     TALLOC_CTX *mem_ctx,
55                                     struct ldb_message **pmsg);
56 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
57                                  struct unixid *id);
58
59 static bool pdb_samba_dsdb_pull_time(struct ldb_message *msg, const char *attr,
60                               time_t *ptime)
61 {
62         uint64_t tmp;
63         if (! ldb_msg_find_element(msg, attr)) {
64                 return false;
65         }
66         tmp = ldb_msg_find_attr_as_uint64(msg, attr, 0);
67         *ptime = nt_time_to_unix(tmp);
68         return true;
69 }
70
71 static struct pdb_domain_info *pdb_samba_dsdb_get_domain_info(
72         struct pdb_methods *m, TALLOC_CTX *mem_ctx)
73 {
74         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
75                 m->private_data, struct pdb_samba_dsdb_state);
76         struct pdb_domain_info *info;
77         struct dom_sid *domain_sid;
78         struct ldb_dn *forest_dn, *domain_dn;
79         struct ldb_result *dom_res = NULL;
80         const char *dom_attrs[] = {
81                 "objectSid",
82                 "objectGUID",
83                 "fSMORoleOwner",
84                 NULL
85         };
86         char *p;
87         int ret;
88
89         info = talloc(mem_ctx, struct pdb_domain_info);
90         if (info == NULL) {
91                 return NULL;
92         }
93
94         domain_dn = ldb_get_default_basedn(state->ldb);
95
96         ret = ldb_search(state->ldb, info, &dom_res,
97                          domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
98         if (ret != LDB_SUCCESS) {
99                 goto fail;
100         }
101         if (dom_res->count != 1) {
102                 goto fail;
103         }
104
105         info->guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
106
107         domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
108         if (!domain_sid) {
109                 goto fail;
110         }
111         info->sid = *domain_sid;
112
113         TALLOC_FREE(dom_res);
114
115         info->name = talloc_strdup(info, lpcfg_sam_name(state->lp_ctx));
116         info->dns_domain = ldb_dn_canonical_string(info, domain_dn);
117
118         if (!info->dns_domain) {
119                 goto fail;
120         }
121         p = strchr(info->dns_domain, '/');
122         if (p) {
123                 *p = '\0';
124         }
125
126         forest_dn = ldb_get_root_basedn(state->ldb);
127         if (!forest_dn) {
128                 goto fail;
129         }
130
131         info->dns_forest = ldb_dn_canonical_string(info, forest_dn);
132         if (!info->dns_forest) {
133                 goto fail;
134         }
135         p = strchr(info->dns_forest, '/');
136         if (p) {
137                 *p = '\0';
138         }
139
140         return info;
141
142 fail:
143         TALLOC_FREE(dom_res);
144         TALLOC_FREE(info);
145         return NULL;
146 }
147
148 static struct ldb_message *pdb_samba_dsdb_get_samu_private(
149         struct pdb_methods *m, struct samu *sam)
150 {
151         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
152                 m->private_data, struct pdb_samba_dsdb_state);
153         struct ldb_message *msg;
154         char *sidstr, *filter;
155         NTSTATUS status;
156
157         msg = (struct ldb_message *)
158                 pdb_get_backend_private_data(sam, m);
159
160         if (msg != NULL) {
161                 return talloc_get_type_abort(msg, struct ldb_message);
162         }
163
164         sidstr = dom_sid_string(talloc_tos(), pdb_get_user_sid(sam));
165         if (sidstr == NULL) {
166                 return NULL;
167         }
168
169         filter = talloc_asprintf(
170                 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
171         TALLOC_FREE(sidstr);
172         if (filter == NULL) {
173                 return NULL;
174         }
175
176         status = pdb_samba_dsdb_getsamupriv(state, filter, sam, &msg);
177         TALLOC_FREE(filter);
178         if (!NT_STATUS_IS_OK(status)) {
179                 return NULL;
180         }
181
182         return msg;
183 }
184
185 static NTSTATUS pdb_samba_dsdb_init_sam_from_priv(struct pdb_methods *m,
186                                            struct samu *sam,
187                                            struct ldb_message *msg)
188 {
189         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
190                 m->private_data, struct pdb_samba_dsdb_state);
191         TALLOC_CTX *frame = talloc_stackframe();
192         NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
193         const char *str;
194         time_t tmp_time;
195         struct dom_sid *sid, group_sid;
196         uint64_t n;
197         const DATA_BLOB *blob;
198
199         str = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
200         if (str == NULL) {
201                 DEBUG(10, ("no samAccountName\n"));
202                 goto fail;
203         }
204         pdb_set_username(sam, str, PDB_SET);
205
206         if (pdb_samba_dsdb_pull_time(msg, "lastLogon", &tmp_time)) {
207                 pdb_set_logon_time(sam, tmp_time, PDB_SET);
208         }
209         if (pdb_samba_dsdb_pull_time(msg, "lastLogoff", &tmp_time)) {
210                 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
211         }
212         if (pdb_samba_dsdb_pull_time(msg, "pwdLastSet", &tmp_time)) {
213                 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
214         }
215         if (pdb_samba_dsdb_pull_time(msg, "accountExpires", &tmp_time)) {
216                 pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
217         }
218
219         str = ldb_msg_find_attr_as_string(msg, "displayName",
220                                             NULL);
221         if (str != NULL) {
222                 pdb_set_fullname(sam, str, PDB_SET);
223         }
224
225         str = ldb_msg_find_attr_as_string(msg, "homeDirectory",
226                                             NULL);
227         if (str != NULL) {
228                 pdb_set_homedir(sam, str, PDB_SET);
229         }
230
231         str = ldb_msg_find_attr_as_string(msg, "homeDrive", NULL);
232         if (str != NULL) {
233                 pdb_set_dir_drive(sam, str, PDB_SET);
234         }
235
236         str = ldb_msg_find_attr_as_string(msg, "scriptPath", NULL);
237         if (str != NULL) {
238                 pdb_set_logon_script(sam, str, PDB_SET);
239         }
240
241         str = ldb_msg_find_attr_as_string(msg, "profilePath",
242                                             NULL);
243         if (str != NULL) {
244                 pdb_set_profile_path(sam, str, PDB_SET);
245         }
246
247         str = ldb_msg_find_attr_as_string(msg, "comment",
248                                             NULL);
249         if (str != NULL) {
250                 pdb_set_comment(sam, str, PDB_SET);
251         }
252
253         str = ldb_msg_find_attr_as_string(msg, "description",
254                                             NULL);
255         if (str != NULL) {
256                 pdb_set_acct_desc(sam, str, PDB_SET);
257         }
258
259         str = ldb_msg_find_attr_as_string(msg, "userWorkstations",
260                                             NULL);
261         if (str != NULL) {
262                 pdb_set_workstations(sam, str, PDB_SET);
263         }
264
265         blob = ldb_msg_find_ldb_val(msg, "userParameters");
266         if (blob != NULL) {
267                 str = base64_encode_data_blob(frame, *blob);
268                 if (str == NULL) {
269                         DEBUG(0, ("base64_encode_data_blob() failed\n"));
270                         goto fail;
271                 }
272                 pdb_set_munged_dial(sam, str, PDB_SET);
273         }
274
275         sid = samdb_result_dom_sid(talloc_tos(), msg, "objectSid");
276         if (!sid) {
277                 DEBUG(10, ("Could not pull SID\n"));
278                 goto fail;
279         }
280         pdb_set_user_sid(sam, sid, PDB_SET);
281
282         n = samdb_result_acct_flags(msg, "msDS-User-Account-Control-Computed");
283         if (n == 0) {
284                 DEBUG(10, ("Could not pull userAccountControl\n"));
285                 goto fail;
286         }
287         pdb_set_acct_ctrl(sam, n, PDB_SET);
288
289         blob = ldb_msg_find_ldb_val(msg, "unicodePwd");
290         if (blob) {
291                 if (blob->length != NT_HASH_LEN) {
292                         DEBUG(0, ("Got NT hash of length %d, expected %d\n",
293                                   (int)blob->length, NT_HASH_LEN));
294                         goto fail;
295                 }
296                 pdb_set_nt_passwd(sam, blob->data, PDB_SET);
297         }
298
299         blob = ldb_msg_find_ldb_val(msg, "dBCSPwd");
300         if (blob) {
301                 if (blob->length != LM_HASH_LEN) {
302                         DEBUG(0, ("Got LM hash of length %d, expected %d\n",
303                                   (int)blob->length, LM_HASH_LEN));
304                         goto fail;
305                 }
306                 pdb_set_lanman_passwd(sam, blob->data, PDB_SET);
307         }
308
309         n = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", 0);
310         if (n == 0) {
311                 DEBUG(10, ("Could not pull primaryGroupID\n"));
312                 goto fail;
313         }
314         sid_compose(&group_sid, samdb_domain_sid(state->ldb), n);
315         pdb_set_group_sid(sam, &group_sid, PDB_SET);
316
317         status = NT_STATUS_OK;
318 fail:
319         TALLOC_FREE(frame);
320         return status;
321 }
322
323 static bool pdb_samba_dsdb_add_time(struct ldb_message *msg,
324                                 const char *attrib, time_t t)
325 {
326         uint64_t nt_time;
327
328         unix_to_nt_time(&nt_time, t);
329
330         return ldb_msg_add_fmt(msg, attrib, "%llu", (unsigned long long) nt_time);
331 }
332
333 static int pdb_samba_dsdb_replace_by_sam(struct pdb_samba_dsdb_state *state,
334                                      bool (*need_update)(const struct samu *,
335                                                          enum pdb_elements),
336                                      struct ldb_dn *dn,
337                                      struct samu *sam)
338 {
339         TALLOC_CTX *frame = talloc_stackframe();
340         int ret = LDB_SUCCESS;
341         const char *pw;
342         struct ldb_message *msg;
343         struct ldb_request *req;
344         uint32_t dsdb_flags = 0;
345         /* TODO: All fields :-) */
346
347         msg = ldb_msg_new(frame);
348         if (!msg) {
349                 talloc_free(frame);
350                 return false;
351         }
352
353         msg->dn = dn;
354
355         /* build modify request */
356         ret = ldb_build_mod_req(&req, state->ldb, frame, msg, NULL, NULL,
357                                 ldb_op_default_callback,
358                                 NULL);
359         if (ret != LDB_SUCCESS) {
360                 talloc_free(frame);
361                 return ret;
362         }
363
364         /* If we set a plaintext password, the system will
365          * force the pwdLastSet to now() */
366         if (need_update(sam, PDB_PASSLASTSET)) {
367                 dsdb_flags = DSDB_PASSWORD_BYPASS_LAST_SET;
368
369                 ret |= pdb_samba_dsdb_add_time(msg, "pwdLastSet",
370                                            pdb_get_pass_last_set_time(sam));
371         }
372
373         pw = pdb_get_plaintext_passwd(sam);
374         if (need_update(sam, PDB_PLAINTEXT_PW)) {
375                 struct ldb_val pw_utf16;
376                 if (pw == NULL) {
377                         talloc_free(frame);
378                         return LDB_ERR_OPERATIONS_ERROR;
379                 }
380
381                 if (!convert_string_talloc(msg,
382                                            CH_UNIX, CH_UTF16,
383                                            pw, strlen(pw),
384                                            (void *)&pw_utf16.data,
385                                            &pw_utf16.length)) {
386                         talloc_free(frame);
387                         return LDB_ERR_OPERATIONS_ERROR;
388                 }
389                 ret |= ldb_msg_add_value(msg, "clearTextPassword", &pw_utf16, NULL);
390         } else {
391                 bool changed_lm_pw = false;
392                 bool changed_nt_pw = false;
393                 bool changed_history = false;
394                 if (need_update(sam, PDB_LMPASSWD)) {
395                         struct ldb_val val;
396                         val.data = discard_const_p(uint8_t, pdb_get_lanman_passwd(sam));
397                         if (!val.data) {
398                                 samdb_msg_add_delete(state->ldb, msg, msg,
399                                                      "dBCSPwd");
400                         } else {
401                                 val.length = LM_HASH_LEN;
402                                 ret |= ldb_msg_add_value(msg, "dBCSPwd", &val, NULL);
403                         }
404                         changed_lm_pw = true;
405                 }
406                 if (need_update(sam, PDB_NTPASSWD)) {
407                         struct ldb_val val;
408                         val.data = discard_const_p(uint8_t, pdb_get_nt_passwd(sam));
409                         if (!val.data) {
410                                 samdb_msg_add_delete(state->ldb, msg, msg,
411                                                      "unicodePwd");
412                         } else {
413                                 val.length = NT_HASH_LEN;
414                                 ret |= ldb_msg_add_value(msg, "unicodePwd", &val, NULL);
415                         }
416                         changed_nt_pw = true;
417                 }
418
419                 /* Try to ensure we don't get out of sync */
420                 if (changed_lm_pw && !changed_nt_pw) {
421                         samdb_msg_add_delete(state->ldb, msg, msg,
422                                              "unicodePwd");
423                 } else if (changed_nt_pw && !changed_lm_pw) {
424                         samdb_msg_add_delete(state->ldb, msg, msg,
425                                              "dBCSPwd");
426                 }
427                 if (changed_lm_pw || changed_nt_pw) {
428                         samdb_msg_add_delete(state->ldb, msg, msg,
429                                              "supplementalCredentials");
430
431                 }
432
433                 if (need_update(sam, PDB_PWHISTORY)) {
434                         uint32_t current_hist_len;
435                         const uint8_t *history = pdb_get_pw_history(sam, &current_hist_len);
436
437                         bool invalid_history = false;
438                         struct samr_Password *history_hashes = talloc_array(talloc_tos(), struct samr_Password,
439                                                                             current_hist_len);
440                         if (!history) {
441                                 invalid_history = true;
442                         } else {
443                                 unsigned int i;
444                                 static const uint8_t zeros[16];
445                                 /* Parse the history into the correct format */
446                                 for (i = 0; i < current_hist_len; i++) {
447                                         if (memcmp(&history[i*PW_HISTORY_ENTRY_LEN], zeros, 16) != 0) {
448                                                 /* If the history is in the old format, with a salted hash, then we can't migrate it to AD format */
449                                                 invalid_history = true;
450                                                 break;
451                                         }
452                                         /* Copy out the 2nd 16 bytes of the 32 byte password history, containing the NT hash */
453                                         memcpy(history_hashes[i].hash,
454                                                &history[(i*PW_HISTORY_ENTRY_LEN) + PW_HISTORY_SALT_LEN],
455                                                sizeof(history_hashes[i].hash));
456                                 }
457                         }
458                         if (invalid_history) {
459                                 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
460                                                      "ntPwdHistory");
461
462                                 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
463                                                      "lmPwdHistory");
464                         } else {
465                                 ret |= samdb_msg_add_hashes(state->ldb, msg, msg,
466                                                             "ntPwdHistory",
467                                                             history_hashes,
468                                                             current_hist_len);
469                         }
470                         changed_history = true;
471                 }
472                 if (changed_lm_pw || changed_nt_pw || changed_history) {
473                         /* These attributes can only be modified directly by using a special control */
474                         dsdb_flags = DSDB_BYPASS_PASSWORD_HASH;
475                 }
476         }
477
478         /* PDB_USERSID is only allowed on ADD, handled in caller */
479         if (need_update(sam, PDB_GROUPSID)) {
480                 const struct dom_sid *sid = pdb_get_group_sid(sam);
481                 uint32_t rid;
482                 NTSTATUS status = dom_sid_split_rid(NULL, sid, NULL, &rid);
483                 if (!NT_STATUS_IS_OK(status)) {
484                         talloc_free(frame);
485                         return LDB_ERR_OPERATIONS_ERROR;
486                 }
487                 if (!dom_sid_in_domain(samdb_domain_sid(state->ldb), sid)) {
488                         talloc_free(frame);
489                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
490                 }
491                 ret |= samdb_msg_add_uint(state->ldb, msg, msg, "primaryGroupID", rid);
492         }
493         if (need_update(sam, PDB_FULLNAME)) {
494                 ret |= ldb_msg_add_string(msg, "displayName", pdb_get_fullname(sam));
495         }
496
497         if (need_update(sam, PDB_SMBHOME)) {
498                 ret |= ldb_msg_add_string(msg, "homeDirectory",
499                                           pdb_get_homedir(sam));
500         }
501
502         if (need_update(sam, PDB_PROFILE)) {
503                 ret |= ldb_msg_add_string(msg, "profilePath",
504                                           pdb_get_profile_path(sam));
505         }
506
507         if (need_update(sam, PDB_DRIVE)) {
508                 ret |= ldb_msg_add_string(msg, "homeDrive",
509                                           pdb_get_dir_drive(sam));
510         }
511
512         if (need_update(sam, PDB_LOGONSCRIPT)) {
513                 ret |= ldb_msg_add_string(msg, "scriptPath",
514                                           pdb_get_logon_script(sam));
515         }
516
517         if (need_update(sam, PDB_KICKOFFTIME)) {
518                 ret |= pdb_samba_dsdb_add_time(msg, "accountExpires",
519                                         pdb_get_kickoff_time(sam));
520         }
521
522         if (need_update(sam, PDB_LOGONTIME)) {
523                 ret |= pdb_samba_dsdb_add_time(msg, "lastLogon",
524                                         pdb_get_logon_time(sam));
525         }
526
527         if (need_update(sam, PDB_LOGOFFTIME)) {
528                 ret |= pdb_samba_dsdb_add_time(msg, "lastLogoff",
529                                         pdb_get_logoff_time(sam));
530         }
531
532         if (need_update(sam, PDB_USERNAME)) {
533                 ret |= ldb_msg_add_string(msg, "samAccountName",
534                                           pdb_get_username(sam));
535         }
536
537         if (need_update(sam, PDB_HOURSLEN) || need_update(sam, PDB_HOURS)) {
538                 struct ldb_val hours = data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam));
539                 ret |= ldb_msg_add_value(msg, "logonHours",
540                                          &hours, NULL);
541         }
542
543         if (need_update(sam, PDB_ACCTCTRL)) {
544                 ret |= samdb_msg_add_acct_flags(state->ldb, msg, msg,
545                                                 "userAccountControl", pdb_get_acct_ctrl(sam));
546         }
547
548         if (need_update(sam, PDB_COMMENT)) {
549                 ret |= ldb_msg_add_string(msg, "comment",
550                                           pdb_get_comment(sam));
551         }
552
553         if (need_update(sam, PDB_ACCTDESC)) {
554                 ret |= ldb_msg_add_string(msg, "description",
555                                           pdb_get_acct_desc(sam));
556         }
557
558         if (need_update(sam, PDB_WORKSTATIONS)) {
559                 ret |= ldb_msg_add_string(msg, "userWorkstations",
560                                           pdb_get_workstations(sam));
561         }
562
563         /* This will need work, it is actually a UTF8 'string' with internal NULLs, to handle TS parameters */
564         if (need_update(sam, PDB_MUNGEDDIAL)) {
565                 const char *base64_munged_dial = NULL;
566
567                 base64_munged_dial = pdb_get_munged_dial(sam);
568                 if (base64_munged_dial != NULL && strlen(base64_munged_dial) > 0) {
569                         struct ldb_val blob;
570
571                         blob = base64_decode_data_blob_talloc(msg,
572                                                         base64_munged_dial);
573                         if (blob.data == NULL) {
574                                 DEBUG(0, ("Failed to decode userParameters from "
575                                           "munged dialback string[%s] for %s\n",
576                                           base64_munged_dial,
577                                           ldb_dn_get_linearized(msg->dn)));
578                                 talloc_free(frame);
579                                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
580                         }
581                         ret |= ldb_msg_add_steal_value(msg, "userParameters",
582                                                        &blob);
583                 }
584         }
585
586         if (need_update(sam, PDB_COUNTRY_CODE)) {
587                 ret |= ldb_msg_add_fmt(msg, "countryCode",
588                                        "%i", (int)pdb_get_country_code(sam));
589         }
590
591         if (need_update(sam, PDB_CODE_PAGE)) {
592                 ret |= ldb_msg_add_fmt(msg, "codePage",
593                                        "%i", (int)pdb_get_code_page(sam));
594         }
595
596         /* Not yet handled here or not meaningful for modifies on a Samba_Dsdb backend:
597         PDB_BAD_PASSWORD_TIME,
598         PDB_CANCHANGETIME, - these are calculated per policy, not stored
599         PDB_DOMAIN,
600         PDB_NTUSERNAME, - this makes no sense, and never really did
601         PDB_LOGONDIVS,
602         PDB_USERSID, - Handled in pdb_samba_dsdb_add_sam_account()
603         PDB_FIELDS_PRESENT,
604         PDB_BAD_PASSWORD_COUNT,
605         PDB_LOGON_COUNT,
606         PDB_UNKNOWN6,
607         PDB_BACKEND_PRIVATE_DATA,
608
609  */
610         if (ret != LDB_SUCCESS) {
611                 talloc_free(frame);
612                 return LDB_ERR_OPERATIONS_ERROR;
613         }
614
615         if (msg->num_elements == 0) {
616                 talloc_free(frame);
617                 /* Nothing to do, just return success */
618                 return LDB_SUCCESS;
619         }
620
621         ret = dsdb_replace(state->ldb, msg, dsdb_flags);
622
623         if (ret != LDB_SUCCESS) {
624                 DEBUG(0,("Failed to modify account record %s to set user attributes: %s\n",
625                          ldb_dn_get_linearized(msg->dn),
626                          ldb_errstring(state->ldb)));
627         }
628
629         talloc_free(frame);
630         return ret;
631 }
632
633 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
634                                     const char *filter,
635                                     TALLOC_CTX *mem_ctx,
636                                     struct ldb_message **msg)
637 {
638         const char * attrs[] = {
639                 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
640                 "sAMAccountName", "displayName", "homeDirectory",
641                 "homeDrive", "scriptPath", "profilePath", "description",
642                 "userWorkstations", "comment", "userParameters", "objectSid",
643                 "primaryGroupID", "userAccountControl",
644                 "msDS-User-Account-Control-Computed", "logonHours",
645                 "badPwdCount", "logonCount", "countryCode", "codePage",
646                 "unicodePwd", "dBCSPwd", NULL };
647
648         int rc = dsdb_search_one(state->ldb, mem_ctx, msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter);
649         if (rc != LDB_SUCCESS) {
650                 DEBUG(10, ("ldap_search failed %s\n",
651                            ldb_errstring(state->ldb)));
652                 return NT_STATUS_LDAP(rc);
653         }
654
655         return NT_STATUS_OK;
656 }
657
658 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
659                                           struct pdb_samba_dsdb_state *state,
660                                           struct samu *sam_acct,
661                                           const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
662 {
663         struct ldb_message *priv;
664         NTSTATUS status;
665         va_list ap;
666         char *expression = NULL;
667         TALLOC_CTX *tmp_ctx = talloc_new(state);
668         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
669
670         va_start(ap, exp_fmt);
671         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
672         va_end(ap);
673
674         if (!expression) {
675                 talloc_free(tmp_ctx);
676                 return NT_STATUS_NO_MEMORY;
677         }
678
679         status = pdb_samba_dsdb_getsamupriv(state, expression, sam_acct, &priv);
680         talloc_free(tmp_ctx);
681         if (!NT_STATUS_IS_OK(status)) {
682                 DEBUG(10, ("pdb_samba_dsdb_getsamupriv failed: %s\n",
683                            nt_errstr(status)));
684                 return status;
685         }
686
687         status = pdb_samba_dsdb_init_sam_from_priv(m, sam_acct, priv);
688         if (!NT_STATUS_IS_OK(status)) {
689                 DEBUG(10, ("pdb_samba_dsdb_init_sam_from_priv failed: %s\n",
690                            nt_errstr(status)));
691                 TALLOC_FREE(priv);
692                 return status;
693         }
694
695         pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
696         return NT_STATUS_OK;
697 }
698
699 static NTSTATUS pdb_samba_dsdb_getsampwnam(struct pdb_methods *m,
700                                     struct samu *sam_acct,
701                                     const char *username)
702 {
703         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
704                 m->private_data, struct pdb_samba_dsdb_state);
705
706         return pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
707                                          "(&(samaccountname=%s)(objectclass=user))",
708                                          username);
709 }
710
711 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
712                                     struct samu *sam_acct,
713                                     const struct dom_sid *sid)
714 {
715         NTSTATUS status;
716         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
717                 m->private_data, struct pdb_samba_dsdb_state);
718         char *sidstr;
719
720         sidstr = dom_sid_string(talloc_tos(), sid);
721         NT_STATUS_HAVE_NO_MEMORY(sidstr);
722
723         status = pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
724                                            "(&(objectsid=%s)(objectclass=user))",
725                                            sidstr);
726         talloc_free(sidstr);
727         return status;
728 }
729
730 static NTSTATUS pdb_samba_dsdb_create_user(struct pdb_methods *m,
731                                     TALLOC_CTX *mem_ctx,
732                                     const char *name, uint32 acct_flags,
733                                     uint32 *rid)
734 {
735         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
736                 m->private_data, struct pdb_samba_dsdb_state);
737         struct dom_sid *sid;
738         struct ldb_dn *dn;
739         NTSTATUS status;
740         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
741         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
742
743         /* Internally this uses transactions to ensure all the steps
744          * happen or fail as one */
745         status = dsdb_add_user(state->ldb, tmp_ctx, name, acct_flags, NULL,
746                                &sid, &dn);
747         if (!NT_STATUS_IS_OK(status)) {
748                 talloc_free(tmp_ctx);
749                 return status;
750         }
751         sid_peek_rid(sid, rid);
752         talloc_free(tmp_ctx);
753         return NT_STATUS_OK;
754 }
755
756 static NTSTATUS pdb_samba_dsdb_delete_user(struct pdb_methods *m,
757                                        TALLOC_CTX *mem_ctx,
758                                        struct samu *sam)
759 {
760         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
761                 m->private_data, struct pdb_samba_dsdb_state);
762         struct ldb_dn *dn;
763         int rc;
764         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
765         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
766
767         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, pdb_get_user_sid(sam)));
768         if (!dn || !ldb_dn_validate(dn)) {
769                 talloc_free(tmp_ctx);
770                 return NT_STATUS_NO_MEMORY;
771         }
772         rc = ldb_delete(state->ldb, dn);
773
774         if (rc != LDB_SUCCESS) {
775                 DEBUG(10, ("ldb_delete for %s failed: %s\n", ldb_dn_get_linearized(dn),
776                            ldb_errstring(state->ldb)));
777                 talloc_free(tmp_ctx);
778                 return NT_STATUS_LDAP(rc);
779         }
780         talloc_free(tmp_ctx);
781         return NT_STATUS_OK;
782 }
783
784 /* This interface takes a fully populated struct samu and places it in
785  * the database.  This is not implemented at this time as we need to
786  * be careful around the creation of arbitary SIDs (ie, we must ensrue
787  * they are not left in a RID pool */
788 static NTSTATUS pdb_samba_dsdb_add_sam_account(struct pdb_methods *m,
789                                         struct samu *sampass)
790 {
791         int ret;
792         NTSTATUS status;
793         struct ldb_dn *dn;
794         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
795                 m->private_data, struct pdb_samba_dsdb_state);
796         uint32_t acb_flags = pdb_get_acct_ctrl(sampass);
797         const char *username = pdb_get_username(sampass);
798         const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
799         TALLOC_CTX *tframe = talloc_stackframe();
800
801         acb_flags &= (ACB_NORMAL|ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST);
802
803         ret = ldb_transaction_start(state->ldb);
804         if (ret != LDB_SUCCESS) {
805                 talloc_free(tframe);
806                 return NT_STATUS_LOCK_NOT_GRANTED;
807         }
808
809         status = dsdb_add_user(state->ldb, talloc_tos(), username,
810                                acb_flags, user_sid, NULL, &dn);
811         if (!NT_STATUS_IS_OK(status)) {
812                 ldb_transaction_cancel(state->ldb);
813                 talloc_free(tframe);
814                 return status;
815         }
816
817         ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_set_or_changed,
818                                         dn, sampass);
819         if (ret != LDB_SUCCESS) {
820                 ldb_transaction_cancel(state->ldb);
821                 talloc_free(tframe);
822                 return dsdb_ldb_err_to_ntstatus(ret);
823         }
824
825         ret = ldb_transaction_commit(state->ldb);
826         if (ret != LDB_SUCCESS) {
827                 DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
828                          ldb_dn_get_linearized(dn),
829                          ldb_errstring(state->ldb)));
830                 talloc_free(tframe);
831                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
832         }
833         talloc_free(tframe);
834         return NT_STATUS_OK;
835 }
836
837 /*
838  * Update the Samba_Dsdb LDB with the changes from a struct samu.
839  *
840  * This takes care not to update elements that have not been changed
841  * by the caller
842  */
843 static NTSTATUS pdb_samba_dsdb_update_sam_account(struct pdb_methods *m,
844                                            struct samu *sam)
845 {
846         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
847                 m->private_data, struct pdb_samba_dsdb_state);
848         struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
849                 m, sam);
850         int ret;
851
852         ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_changed, msg->dn,
853                                         sam);
854         return dsdb_ldb_err_to_ntstatus(ret);
855 }
856
857 static NTSTATUS pdb_samba_dsdb_delete_sam_account(struct pdb_methods *m,
858                                            struct samu *username)
859 {
860         NTSTATUS status;
861         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
862         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
863         status = pdb_samba_dsdb_delete_user(m, tmp_ctx, username);
864         talloc_free(tmp_ctx);
865         return status;
866 }
867
868 static NTSTATUS pdb_samba_dsdb_rename_sam_account(struct pdb_methods *m,
869                                            struct samu *oldname,
870                                            const char *newname)
871 {
872         return NT_STATUS_NOT_IMPLEMENTED;
873 }
874
875 /* This is not implemented, as this module is exptected to be used
876  * with auth_samba_dsdb, and this is responible for login counters etc
877  *
878  */
879 static NTSTATUS pdb_samba_dsdb_update_login_attempts(struct pdb_methods *m,
880                                               struct samu *sam_acct,
881                                               bool success)
882 {
883         return NT_STATUS_NOT_IMPLEMENTED;
884 }
885
886 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
887                                     const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
888 {
889         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
890                 m->private_data, struct pdb_samba_dsdb_state);
891         const char *attrs[] = { "objectClass", "objectSid", "description", "samAccountName", "groupType",
892                                 NULL };
893         struct ldb_message *msg;
894         va_list ap;
895         char *expression = NULL;
896         struct dom_sid *sid;
897         const char *str;
898         int rc;
899         struct id_map id_map;
900         struct id_map *id_maps[2];
901         TALLOC_CTX *tmp_ctx = talloc_stackframe();
902         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
903
904         va_start(ap, exp_fmt);
905         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
906         va_end(ap);
907
908         if (!expression) {
909                 talloc_free(tmp_ctx);
910                 return NT_STATUS_NO_MEMORY;
911         }
912
913         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
914         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
915                 talloc_free(tmp_ctx);
916                 return NT_STATUS_NO_SUCH_GROUP;
917         } else if (rc != LDB_SUCCESS) {
918                 talloc_free(tmp_ctx);
919                 DEBUG(10, ("dsdb_search_one failed %s\n",
920                            ldb_errstring(state->ldb)));
921                 return NT_STATUS_LDAP(rc);
922         }
923
924         sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
925         if (!sid) {
926                 talloc_free(tmp_ctx);
927                 DEBUG(10, ("Could not pull SID\n"));
928                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
929         }
930
931         map->sid = *sid;
932
933         if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) {
934                 NTSTATUS status;
935                 uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0);
936                 switch (grouptype) {
937                 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
938                 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
939                         map->sid_name_use = SID_NAME_ALIAS;
940                         break;
941                 case GTYPE_SECURITY_GLOBAL_GROUP:
942                         map->sid_name_use = SID_NAME_DOM_GRP;
943                         break;
944                 default:
945                         talloc_free(tmp_ctx);
946                         DEBUG(10, ("Could not pull groupType\n"));
947                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
948                 }
949
950                 ZERO_STRUCT(id_map);
951                 id_map.sid = sid;
952                 id_maps[0] = &id_map;
953                 id_maps[1] = NULL;
954
955                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
956
957                 if (!NT_STATUS_IS_OK(status)) {
958                         talloc_free(tmp_ctx);
959                         return status;
960                 }
961                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
962                         map->gid = id_map.xid.id;
963                 } else {
964                         DEBUG(1, (__location__ "Did not get GUID when mapping SID for %s", expression));
965                         talloc_free(tmp_ctx);
966                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
967                 }
968         } else if (samdb_find_attribute(state->ldb, msg, "objectClass", "user")) {
969                 DEBUG(1, (__location__ "Got SID_NAME_USER when searching for a group with %s", expression));
970                 talloc_free(tmp_ctx);
971                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
972         }
973
974         str = ldb_msg_find_attr_as_string(msg, "samAccountName",
975                                           NULL);
976         if (str == NULL) {
977                 talloc_free(tmp_ctx);
978                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
979         }
980         map->nt_name = talloc_strdup(map, str);
981         if (!map->nt_name) {
982                 talloc_free(tmp_ctx);
983                 return NT_STATUS_NO_MEMORY;
984         }
985
986         str = ldb_msg_find_attr_as_string(msg, "description",
987                                             NULL);
988         if (str != NULL) {
989                 map->comment = talloc_strdup(map, str);
990         } else {
991                 map->comment = talloc_strdup(map, "");
992         }
993         if (!map->comment) {
994                 talloc_free(tmp_ctx);
995                 return NT_STATUS_NO_MEMORY;
996         }
997
998         talloc_free(tmp_ctx);
999         return NT_STATUS_OK;
1000 }
1001
1002 static NTSTATUS pdb_samba_dsdb_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
1003                                  struct dom_sid sid)
1004 {
1005         char *filter;
1006         NTSTATUS status;
1007
1008         filter = talloc_asprintf(talloc_tos(),
1009                                  "(&(objectsid=%s)(objectclass=group))",
1010                                  sid_string_talloc(talloc_tos(), &sid));
1011         if (filter == NULL) {
1012                 return NT_STATUS_NO_MEMORY;
1013         }
1014
1015         status = pdb_samba_dsdb_getgrfilter(m, map, filter);
1016         TALLOC_FREE(filter);
1017         return status;
1018 }
1019
1020 static NTSTATUS pdb_samba_dsdb_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
1021                                  gid_t gid)
1022 {
1023         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1024                 m->private_data, struct pdb_samba_dsdb_state);
1025         NTSTATUS status;
1026         struct id_map id_map;
1027         struct id_map *id_maps[2];
1028         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1029         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1030
1031         id_map.xid.id = gid;
1032         id_map.xid.type = ID_TYPE_GID;
1033         id_maps[0] = &id_map;
1034         id_maps[1] = NULL;
1035
1036         status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
1037         if (!NT_STATUS_IS_OK(status)) {
1038                 talloc_free(tmp_ctx);
1039                 return status;
1040         }
1041         status = pdb_samba_dsdb_getgrsid(m, map, *id_map.sid);
1042         talloc_free(tmp_ctx);
1043         return status;
1044 }
1045
1046 static NTSTATUS pdb_samba_dsdb_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
1047                                  const char *name)
1048 {
1049         char *filter;
1050         NTSTATUS status;
1051
1052         filter = talloc_asprintf(talloc_tos(),
1053                                  "(&(samaccountname=%s)(objectclass=group))",
1054                                  name);
1055         if (filter == NULL) {
1056                 return NT_STATUS_NO_MEMORY;
1057         }
1058
1059         status = pdb_samba_dsdb_getgrfilter(m, map, filter);
1060         TALLOC_FREE(filter);
1061         return status;
1062 }
1063
1064 static NTSTATUS pdb_samba_dsdb_create_dom_group(struct pdb_methods *m,
1065                                          TALLOC_CTX *mem_ctx, const char *name,
1066                                          uint32 *rid)
1067 {
1068         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1069                 m->private_data, struct pdb_samba_dsdb_state);
1070         NTSTATUS status;
1071         struct dom_sid *sid;
1072         struct ldb_dn *dn;
1073         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1074         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1075
1076         status = dsdb_add_domain_group(state->ldb, tmp_ctx, name, &sid, &dn);
1077         if (!NT_STATUS_IS_OK(status)) {
1078                 talloc_free(tmp_ctx);
1079                 return status;
1080         }
1081
1082         sid_peek_rid(sid, rid);
1083         talloc_free(tmp_ctx);
1084         return NT_STATUS_OK;
1085 }
1086
1087 static NTSTATUS pdb_samba_dsdb_delete_dom_group(struct pdb_methods *m,
1088                                          TALLOC_CTX *mem_ctx, uint32 rid)
1089 {
1090         const char *attrs[] = { NULL };
1091         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1092                 m->private_data, struct pdb_samba_dsdb_state);
1093         struct dom_sid sid;
1094         struct ldb_message *msg;
1095         struct ldb_dn *dn;
1096         int rc;
1097         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1098         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1099
1100         sid_compose(&sid, samdb_domain_sid(state->ldb), rid);
1101
1102         if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1103                 DEBUG(0, ("Unable to start transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1104                 return NT_STATUS_INTERNAL_ERROR;
1105         }
1106
1107         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, &sid));
1108         if (!dn || !ldb_dn_validate(dn)) {
1109                 talloc_free(tmp_ctx);
1110                 ldb_transaction_cancel(state->ldb);
1111                 return NT_STATUS_NO_MEMORY;
1112         }
1113         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "objectclass=group");
1114         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1115                 talloc_free(tmp_ctx);
1116                 ldb_transaction_cancel(state->ldb);
1117                 return NT_STATUS_NO_SUCH_GROUP;
1118         }
1119         rc = ldb_delete(state->ldb, dn);
1120         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1121                 talloc_free(tmp_ctx);
1122                 ldb_transaction_cancel(state->ldb);
1123                 return NT_STATUS_NO_SUCH_GROUP;
1124         } else if (rc != LDB_SUCCESS) {
1125                 DEBUG(10, ("ldb_delete failed %s\n",
1126                            ldb_errstring(state->ldb)));
1127                 ldb_transaction_cancel(state->ldb);
1128                 return NT_STATUS_LDAP(rc);
1129         }
1130
1131         if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1132                 DEBUG(0, ("Unable to commit transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1133                 return NT_STATUS_INTERNAL_ERROR;
1134         }
1135         return NT_STATUS_OK;
1136 }
1137
1138 static NTSTATUS pdb_samba_dsdb_add_group_mapping_entry(struct pdb_methods *m,
1139                                                 GROUP_MAP *map)
1140 {
1141         return NT_STATUS_NOT_IMPLEMENTED;
1142 }
1143
1144 static NTSTATUS pdb_samba_dsdb_update_group_mapping_entry(struct pdb_methods *m,
1145                                                    GROUP_MAP *map)
1146 {
1147         return NT_STATUS_NOT_IMPLEMENTED;
1148 }
1149
1150 static NTSTATUS pdb_samba_dsdb_delete_group_mapping_entry(struct pdb_methods *m,
1151                                                    struct dom_sid sid)
1152 {
1153         return NT_STATUS_NOT_IMPLEMENTED;
1154 }
1155
1156 static NTSTATUS pdb_samba_dsdb_enum_group_mapping(struct pdb_methods *m,
1157                                            const struct dom_sid *sid,
1158                                            enum lsa_SidType sid_name_use,
1159                                            GROUP_MAP ***pp_rmap,
1160                                            size_t *p_num_entries,
1161                                            bool unix_only)
1162 {
1163         return NT_STATUS_NOT_IMPLEMENTED;
1164 }
1165
1166 static NTSTATUS pdb_samba_dsdb_enum_group_members(struct pdb_methods *m,
1167                                            TALLOC_CTX *mem_ctx,
1168                                            const struct dom_sid *group,
1169                                            uint32_t **pmembers,
1170                                            size_t *pnum_members)
1171 {
1172         unsigned int i, num_sids, num_members;
1173         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1174                 m->private_data, struct pdb_samba_dsdb_state);
1175         struct dom_sid *members_as_sids;
1176         struct dom_sid *dom_sid;
1177         uint32_t *members;
1178         struct ldb_dn *dn;
1179         NTSTATUS status;
1180
1181         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1182         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1183
1184         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, group));
1185         if (!dn || !ldb_dn_validate(dn)) {
1186                 return NT_STATUS_NO_MEMORY;
1187         }
1188
1189         status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
1190         if (!NT_STATUS_IS_OK(status)) {
1191                 talloc_free(tmp_ctx);
1192                 return status;
1193         }
1194         status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
1195         if (!NT_STATUS_IS_OK(status)) {
1196                 talloc_free(tmp_ctx);
1197                 return status;
1198         }
1199
1200         *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
1201         if (*pmembers == NULL) {
1202                 TALLOC_FREE(tmp_ctx);
1203                 return NT_STATUS_NO_MEMORY;
1204         }
1205         num_members = 0;
1206
1207         for (i = 0; i < num_sids; i++) {
1208                 if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
1209                         continue;
1210                 }
1211                 status = dom_sid_split_rid(NULL, &members_as_sids[i],
1212                                            NULL, &members[num_members]);
1213                 if (!NT_STATUS_IS_OK(status)) {
1214                         talloc_free(tmp_ctx);
1215                         return status;
1216                 }
1217                 num_members++;
1218         }
1219         *pnum_members = num_members;
1220         return NT_STATUS_OK;
1221 }
1222
1223 /* Just convert the primary group SID into a group */
1224 static NTSTATUS fake_enum_group_memberships(struct pdb_samba_dsdb_state *state,
1225                                             TALLOC_CTX *mem_ctx,
1226                                             struct samu *user,
1227                                             struct dom_sid **pp_sids,
1228                                             gid_t **pp_gids,
1229                                             uint32_t *p_num_groups)
1230 {
1231         NTSTATUS status;
1232         size_t num_groups = 0;
1233         struct dom_sid *group_sids = NULL;
1234         gid_t *gids = NULL;
1235         TALLOC_CTX *tmp_ctx;
1236
1237         tmp_ctx = talloc_new(mem_ctx);
1238         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1239
1240         if (user->group_sid) {
1241                 struct id_map *id_maps[2];
1242                 struct id_map id_map;
1243
1244                 num_groups = 1;
1245
1246                 group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
1247                 if (group_sids == NULL) {
1248                         talloc_free(tmp_ctx);
1249                         return NT_STATUS_NO_MEMORY;
1250                 }
1251                 gids = talloc_array(tmp_ctx, gid_t, num_groups);
1252                 if (gids == NULL) {
1253                         talloc_free(tmp_ctx);
1254                         return NT_STATUS_NO_MEMORY;
1255                 }
1256
1257                 group_sids[0] = *user->group_sid;
1258
1259                 ZERO_STRUCT(id_map);
1260                 id_map.sid = &group_sids[0];
1261                 id_maps[0] = &id_map;
1262                 id_maps[1] = NULL;
1263
1264                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1265                 if (!NT_STATUS_IS_OK(status)) {
1266                         talloc_free(tmp_ctx);
1267                         return status;
1268                 }
1269                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1270                         gids[0] = id_map.xid.id;
1271                 } else {
1272                         DEBUG(1, (__location__
1273                                   "Group %s, of which %s is a member, could not be converted to a GID\n",
1274                                   dom_sid_string(tmp_ctx, &group_sids[0]),
1275                                   dom_sid_string(tmp_ctx, &user->user_sid)));
1276                         talloc_free(tmp_ctx);
1277                         /* We must error out, otherwise a user might
1278                          * avoid a DENY acl based on a group they
1279                          * missed out on */
1280                         return NT_STATUS_NO_SUCH_GROUP;
1281                 }
1282         }
1283
1284         *pp_sids = talloc_steal(mem_ctx, group_sids);
1285         *pp_gids = talloc_steal(mem_ctx, gids);
1286         *p_num_groups = num_groups;
1287         talloc_free(tmp_ctx);
1288         return NT_STATUS_OK;
1289 }
1290
1291 static NTSTATUS pdb_samba_dsdb_enum_group_memberships(struct pdb_methods *m,
1292                                                TALLOC_CTX *mem_ctx,
1293                                                struct samu *user,
1294                                                struct dom_sid **pp_sids,
1295                                                gid_t **pp_gids,
1296                                                uint32_t *p_num_groups)
1297 {
1298         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1299                 m->private_data, struct pdb_samba_dsdb_state);
1300         struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
1301                 m, user);
1302         const char *attrs[] = { "tokenGroups", NULL};
1303         struct ldb_message *tokengroups_msg;
1304         struct ldb_message_element *tokengroups;
1305         int i, rc;
1306         NTSTATUS status;
1307         unsigned int count = 0;
1308         size_t num_groups;
1309         struct dom_sid *group_sids;
1310         gid_t *gids;
1311         TALLOC_CTX *tmp_ctx;
1312
1313         if (msg == NULL) {
1314                 /* Fake up some things here */
1315                 return fake_enum_group_memberships(state,
1316                                                    mem_ctx,
1317                                                    user, pp_sids,
1318                                                    pp_gids, p_num_groups);
1319         }
1320
1321         tmp_ctx = talloc_new(mem_ctx);
1322         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1323
1324         rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
1325
1326         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1327                 talloc_free(tmp_ctx);
1328                 return NT_STATUS_NO_SUCH_USER;
1329         } else if (rc != LDB_SUCCESS) {
1330                 DEBUG(10, ("dsdb_search_one failed %s\n",
1331                            ldb_errstring(state->ldb)));
1332                 talloc_free(tmp_ctx);
1333                 return NT_STATUS_LDAP(rc);
1334         }
1335
1336         tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
1337
1338         if (tokengroups) {
1339                 count = tokengroups->num_values;
1340         }
1341
1342         group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
1343         if (group_sids == NULL) {
1344                 talloc_free(tmp_ctx);
1345                 return NT_STATUS_NO_MEMORY;
1346         }
1347         gids = talloc_array(tmp_ctx, gid_t, count);
1348         if (gids == NULL) {
1349                 talloc_free(tmp_ctx);
1350                 return NT_STATUS_NO_MEMORY;
1351         }
1352         num_groups = 0;
1353
1354         for (i=0; i<count; i++) {
1355                 struct id_map *id_maps[2];
1356                 struct id_map id_map;
1357                 struct ldb_val *v = &tokengroups->values[i];
1358                 enum ndr_err_code ndr_err
1359                         = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
1360                                                (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1361                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1362                         talloc_free(tmp_ctx);
1363                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1364                 }
1365
1366                 ZERO_STRUCT(id_map);
1367                 id_map.sid = &group_sids[num_groups];
1368                 id_maps[0] = &id_map;
1369                 id_maps[1] = NULL;
1370
1371                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1372                 if (!NT_STATUS_IS_OK(status)) {
1373                         talloc_free(tmp_ctx);
1374                         return status;
1375                 }
1376                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1377                         gids[num_groups] = id_map.xid.id;
1378                 } else {
1379                         DEBUG(1, (__location__
1380                                   "Group %s, of which %s is a member, could not be converted to a GID\n",
1381                                   dom_sid_string(tmp_ctx, &group_sids[num_groups]),
1382                                   ldb_dn_get_linearized(msg->dn)));
1383                         talloc_free(tmp_ctx);
1384                         /* We must error out, otherwise a user might
1385                          * avoid a DENY acl based on a group they
1386                          * missed out on */
1387                         return NT_STATUS_NO_SUCH_GROUP;
1388                 }
1389
1390                 num_groups += 1;
1391                 if (num_groups == count) {
1392                         break;
1393                 }
1394         }
1395
1396         *pp_sids = talloc_steal(mem_ctx, group_sids);
1397         *pp_gids = talloc_steal(mem_ctx, gids);
1398         *p_num_groups = num_groups;
1399         talloc_free(tmp_ctx);
1400         return NT_STATUS_OK;
1401 }
1402
1403 static NTSTATUS pdb_samba_dsdb_set_unix_primary_group(struct pdb_methods *m,
1404                                                TALLOC_CTX *mem_ctx,
1405                                                struct samu *user)
1406 {
1407         return NT_STATUS_NOT_IMPLEMENTED;
1408 }
1409
1410 static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid(struct pdb_methods *m,
1411                                                TALLOC_CTX *mem_ctx,
1412                                                const struct dom_sid *groupsid,
1413                                                const struct dom_sid *membersid,
1414                                                int mod_op)
1415 {
1416         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1417                 m->private_data, struct pdb_samba_dsdb_state);
1418         struct ldb_message *msg;
1419         int ret;
1420         struct ldb_message_element *el;
1421         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1422         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1423         msg = ldb_msg_new(tmp_ctx);
1424         if (msg == NULL) {
1425                 TALLOC_FREE(tmp_ctx);
1426                 return NT_STATUS_NO_MEMORY;
1427         }
1428
1429         msg->dn = ldb_dn_new_fmt(msg, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, groupsid));
1430         if (!msg->dn || !ldb_dn_validate(msg->dn)) {
1431                 talloc_free(tmp_ctx);
1432                 return NT_STATUS_NO_MEMORY;
1433         }
1434         ret = ldb_msg_add_fmt(msg, "member", "<SID=%s>", dom_sid_string(tmp_ctx, membersid));
1435         if (ret != LDB_SUCCESS) {
1436                 talloc_free(tmp_ctx);
1437                 return NT_STATUS_NO_MEMORY;
1438         }
1439         el = ldb_msg_find_element(msg, "member");
1440         el->flags = mod_op;
1441
1442         /* No need for transactions here, the ldb auto-transaction
1443          * code will handle things for the single operation */
1444         ret = ldb_modify(state->ldb, msg);
1445         talloc_free(tmp_ctx);
1446         if (ret != LDB_SUCCESS) {
1447                 DEBUG(10, ("ldb_modify failed: %s\n",
1448                            ldb_errstring(state->ldb)));
1449                 if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
1450                         return NT_STATUS_MEMBER_IN_GROUP;
1451                 }
1452                 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1453                         return NT_STATUS_MEMBER_NOT_IN_GROUP;
1454                 }
1455                 return NT_STATUS_LDAP(ret);
1456         }
1457
1458         return NT_STATUS_OK;
1459 }
1460
1461 static NTSTATUS pdb_samba_dsdb_mod_groupmem(struct pdb_methods *m,
1462                                      TALLOC_CTX *mem_ctx,
1463                                      uint32 grouprid, uint32 memberrid,
1464                                      int mod_op)
1465 {
1466         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1467                 m->private_data, struct pdb_samba_dsdb_state);
1468         const struct dom_sid *dom_sid, *groupsid, *membersid;
1469         NTSTATUS status;
1470         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1471         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1472
1473         dom_sid = samdb_domain_sid(state->ldb);
1474
1475         groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
1476         if (groupsid == NULL) {
1477                 TALLOC_FREE(tmp_ctx);
1478                 return NT_STATUS_NO_MEMORY;
1479         }
1480         membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
1481         if (membersid == NULL) {
1482                 TALLOC_FREE(tmp_ctx);
1483                 return NT_STATUS_NO_MEMORY;
1484         }
1485         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
1486         talloc_free(tmp_ctx);
1487         return status;
1488 }
1489
1490 static NTSTATUS pdb_samba_dsdb_add_groupmem(struct pdb_methods *m,
1491                                      TALLOC_CTX *mem_ctx,
1492                                      uint32 group_rid, uint32 member_rid)
1493 {
1494         return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1495                                     LDB_FLAG_MOD_ADD);
1496 }
1497
1498 static NTSTATUS pdb_samba_dsdb_del_groupmem(struct pdb_methods *m,
1499                                      TALLOC_CTX *mem_ctx,
1500                                      uint32 group_rid, uint32 member_rid)
1501 {
1502         return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1503                                        LDB_FLAG_MOD_DELETE);
1504 }
1505
1506 static NTSTATUS pdb_samba_dsdb_create_alias(struct pdb_methods *m,
1507                                      const char *name, uint32 *rid)
1508 {
1509         TALLOC_CTX *frame = talloc_stackframe();
1510         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1511                 m->private_data, struct pdb_samba_dsdb_state);
1512         struct dom_sid *sid;
1513
1514         struct ldb_dn *dn;
1515         NTSTATUS status;
1516
1517         /* Internally this uses transactions to ensure all the steps
1518          * happen or fail as one */
1519         status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
1520         if (!NT_STATUS_IS_OK(status)) {
1521                 TALLOC_FREE(frame);
1522         }
1523
1524         sid_peek_rid(sid, rid);
1525         TALLOC_FREE(frame);
1526         return NT_STATUS_OK;
1527 }
1528
1529 static NTSTATUS pdb_samba_dsdb_delete_alias(struct pdb_methods *m,
1530                                      const struct dom_sid *sid)
1531 {
1532         const char *attrs[] = { NULL };
1533         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1534                 m->private_data, struct pdb_samba_dsdb_state);
1535         struct ldb_message *msg;
1536         struct ldb_dn *dn;
1537         int rc;
1538         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1539         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1540
1541         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, sid));
1542         if (!dn || !ldb_dn_validate(dn)) {
1543                 talloc_free(tmp_ctx);
1544                 return NT_STATUS_NO_MEMORY;
1545         }
1546
1547         if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1548                 DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(state->ldb)));
1549                 talloc_free(tmp_ctx);
1550                 return NT_STATUS_INTERNAL_ERROR;
1551         }
1552
1553         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
1554                              "(|(grouptype=%d)(grouptype=%d)))",
1555                              GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1556                              GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1557         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1558                 talloc_free(tmp_ctx);
1559                 ldb_transaction_cancel(state->ldb);
1560                 return NT_STATUS_NO_SUCH_ALIAS;
1561         }
1562         rc = ldb_delete(state->ldb, dn);
1563         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1564                 talloc_free(tmp_ctx);
1565                 ldb_transaction_cancel(state->ldb);
1566                 return NT_STATUS_NO_SUCH_ALIAS;
1567         } else if (rc != LDB_SUCCESS) {
1568                 DEBUG(10, ("ldb_delete failed %s\n",
1569                            ldb_errstring(state->ldb)));
1570                 ldb_transaction_cancel(state->ldb);
1571                 talloc_free(tmp_ctx);
1572                 return NT_STATUS_LDAP(rc);
1573         }
1574
1575         if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1576                 DEBUG(0, ("Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s\n",
1577                           ldb_errstring(state->ldb)));
1578                 talloc_free(tmp_ctx);
1579                 return NT_STATUS_INTERNAL_ERROR;
1580         }
1581
1582         talloc_free(tmp_ctx);
1583         return NT_STATUS_OK;
1584 }
1585
1586 #if 0
1587 static NTSTATUS pdb_samba_dsdb_set_aliasinfo(struct pdb_methods *m,
1588                                       const struct dom_sid *sid,
1589                                       struct acct_info *info)
1590 {
1591         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1592                 m->private_data, struct pdb_samba_dsdb_state);
1593         struct tldap_context *ld;
1594         const char *attrs[3] = { "objectSid", "description",
1595                                  "samAccountName" };
1596         struct ldb_message **msg;
1597         char *sidstr, *dn;
1598         int rc;
1599         struct tldap_mod *mods;
1600         int num_mods;
1601         bool ok;
1602
1603         ld = pdb_samba_dsdb_ld(state);
1604         if (ld == NULL) {
1605                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1606         }
1607
1608         sidstr = sid_binstring(talloc_tos(), sid);
1609         NT_STATUS_HAVE_NO_MEMORY(sidstr);
1610
1611         rc = pdb_samba_dsdb_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1612                                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1613                                 &msg, "(&(objectSid=%s)(objectclass=group)"
1614                                 "(|(grouptype=%d)(grouptype=%d)))",
1615                                 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1616                                 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1617         TALLOC_FREE(sidstr)
1618         if (rc != LDB_SUCCESS) {
1619                 DEBUG(10, ("ldap_search failed %s\n",
1620                            ldb_errstring(state->ldb)));
1621                 return NT_STATUS_LDAP(rc);
1622         }
1623         switch talloc_array_length(msg) {
1624         case 0:
1625                 return NT_STATUS_NO_SUCH_ALIAS;
1626         case 1:
1627                 break;
1628         default:
1629                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1630         }
1631
1632         if (!tldap_entry_dn(msg[0], &dn)) {
1633                 TALLOC_FREE(msg);
1634                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1635         }
1636
1637         mods = NULL;
1638         num_mods = 0;
1639         ok = true;
1640
1641         ok &= tldap_make_mod_fmt(
1642                 msg[0], msg, &num_mods, &mods, "description",
1643                 "%s", info->acct_desc);
1644         ok &= tldap_make_mod_fmt(
1645                 msg[0], msg, &num_mods, &mods, "samAccountName",
1646                 "%s", info->acct_name);
1647         if (!ok) {
1648                 TALLOC_FREE(msg);
1649                 return NT_STATUS_NO_MEMORY;
1650         }
1651         if (num_mods == 0) {
1652                 /* no change */
1653                 TALLOC_FREE(msg);
1654                 return NT_STATUS_OK;
1655         }
1656
1657         rc = tldap_modify(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
1658         TALLOC_FREE(msg);
1659         if (rc != LDB_SUCCESS) {
1660                 DEBUG(10, ("ldap_modify failed: %s\n",
1661                            ldb_errstring(state->ldb)));
1662                 return NT_STATUS_LDAP(rc);
1663         }
1664         return NT_STATUS_OK;
1665 }
1666 #endif
1667 static NTSTATUS pdb_samba_dsdb_add_aliasmem(struct pdb_methods *m,
1668                                      const struct dom_sid *alias,
1669                                      const struct dom_sid *member)
1670 {
1671         NTSTATUS status;
1672         TALLOC_CTX *frame = talloc_stackframe();
1673         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_ADD);
1674         talloc_free(frame);
1675         return status;
1676 }
1677
1678 static NTSTATUS pdb_samba_dsdb_del_aliasmem(struct pdb_methods *m,
1679                                      const struct dom_sid *alias,
1680                                      const struct dom_sid *member)
1681 {
1682         NTSTATUS status;
1683         TALLOC_CTX *frame = talloc_stackframe();
1684         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
1685         talloc_free(frame);
1686         return status;
1687 }
1688
1689 static NTSTATUS pdb_samba_dsdb_enum_aliasmem(struct pdb_methods *m,
1690                                       const struct dom_sid *alias,
1691                                       TALLOC_CTX *mem_ctx,
1692                                       struct dom_sid **pmembers,
1693                                       size_t *pnum_members)
1694 {
1695         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1696                 m->private_data, struct pdb_samba_dsdb_state);
1697         struct ldb_dn *dn;
1698         unsigned int num_members;
1699         NTSTATUS status;
1700         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1701         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1702
1703         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, alias));
1704         if (!dn || !ldb_dn_validate(dn)) {
1705                 return NT_STATUS_NO_MEMORY;
1706         }
1707
1708         status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
1709         *pnum_members = num_members;
1710         if (NT_STATUS_IS_OK(status)) {
1711                 talloc_steal(mem_ctx, pmembers);
1712         }
1713         talloc_free(tmp_ctx);
1714         return status;
1715 }
1716
1717 static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1718                                                TALLOC_CTX *mem_ctx,
1719                                                const struct dom_sid *domain_sid,
1720                                                const struct dom_sid *members,
1721                                                size_t num_members,
1722                                                uint32_t **palias_rids,
1723                                                size_t *pnum_alias_rids)
1724 {
1725         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1726                 m->private_data, struct pdb_samba_dsdb_state);
1727         uint32_t *alias_rids = NULL;
1728         size_t num_alias_rids = 0;
1729         int i;
1730         struct dom_sid *groupSIDs = NULL;
1731         unsigned int num_groupSIDs = 0;
1732         char *filter;
1733         NTSTATUS status;
1734         const char *sid_string;
1735         const char *sid_dn;
1736         DATA_BLOB sid_blob;
1737
1738         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1739         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1740         /*
1741          * TODO: Get the filter right so that we only get the aliases from
1742          * either the SAM or BUILTIN
1743          */
1744
1745         filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
1746                                  GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1747         if (filter == NULL) {
1748                 return NT_STATUS_NO_MEMORY;
1749         }
1750
1751         for (i = 0; i < num_members; i++) {
1752                 sid_string = dom_sid_string(tmp_ctx, &members[i]);
1753                 if (sid_string == NULL) {
1754                         TALLOC_FREE(tmp_ctx);
1755                         return NT_STATUS_NO_MEMORY;
1756                 }
1757
1758                 sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", sid_string);
1759                 if (sid_dn == NULL) {
1760                         TALLOC_FREE(tmp_ctx);
1761                         return NT_STATUS_NO_MEMORY;
1762                 }
1763
1764                 sid_blob = data_blob_string_const(sid_dn);
1765
1766                 status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1767                                                    tmp_ctx, &groupSIDs, &num_groupSIDs);
1768                 if (!NT_STATUS_IS_OK(status)) {
1769                         talloc_free(tmp_ctx);
1770                         return status;
1771                 }
1772         }
1773
1774         alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1775         if (alias_rids == NULL) {
1776                 talloc_free(tmp_ctx);
1777                 return NT_STATUS_NO_MEMORY;
1778         }
1779
1780         for (i=0; i<num_groupSIDs; i++) {
1781                 if (sid_peek_check_rid(domain_sid, &groupSIDs[i],
1782                                        &alias_rids[num_alias_rids])) {
1783                         num_alias_rids++;;
1784                 }
1785         }
1786
1787         *palias_rids = alias_rids;
1788         *pnum_alias_rids = num_alias_rids;
1789         return NT_STATUS_OK;
1790 }
1791
1792 static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1793                                     const struct dom_sid *domain_sid,
1794                                     int num_rids,
1795                                     uint32 *rids,
1796                                     const char **names,
1797                                     enum lsa_SidType *lsa_attrs)
1798 {
1799         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1800                 m->private_data, struct pdb_samba_dsdb_state);
1801         NTSTATUS status;
1802
1803         TALLOC_CTX *tmp_ctx;
1804
1805         if (num_rids == 0) {
1806                 return NT_STATUS_NONE_MAPPED;
1807         }
1808
1809         tmp_ctx = talloc_stackframe();
1810         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1811
1812         status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1813         talloc_free(tmp_ctx);
1814         return status;
1815 }
1816
1817 static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1818                                      const struct dom_sid *domain_sid,
1819                                      int num_names,
1820                                      const char **pp_names,
1821                                      uint32 *rids,
1822                                      enum lsa_SidType *attrs)
1823 {
1824         return NT_STATUS_NOT_IMPLEMENTED;
1825 }
1826
1827 static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1828                                            enum pdb_policy_type type,
1829                                            uint32_t *value)
1830 {
1831         return account_policy_get(type, value)
1832                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1833 }
1834
1835 static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1836                                            enum pdb_policy_type type,
1837                                            uint32_t value)
1838 {
1839         return account_policy_set(type, value)
1840                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1841 }
1842
1843 static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1844                                     time_t *seq_num_out)
1845 {
1846         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1847                 m->private_data, struct pdb_samba_dsdb_state);
1848         uint64_t seq_num;
1849         int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1850         if (ret == LDB_SUCCESS) {
1851                 *seq_num_out = seq_num;
1852                 return NT_STATUS_OK;
1853         } else {
1854                 return NT_STATUS_UNSUCCESSFUL;
1855         }
1856 }
1857
1858 struct pdb_samba_dsdb_search_state {
1859         uint32_t acct_flags;
1860         struct samr_displayentry *entries;
1861         uint32_t num_entries;
1862         ssize_t array_size;
1863         uint32_t current;
1864 };
1865
1866 static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1867                                struct samr_displayentry *entry)
1868 {
1869         struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1870                 search->private_data, struct pdb_samba_dsdb_search_state);
1871
1872         if (state->current == state->num_entries) {
1873                 return false;
1874         }
1875
1876         entry->idx = state->entries[state->current].idx;
1877         entry->rid = state->entries[state->current].rid;
1878         entry->acct_flags = state->entries[state->current].acct_flags;
1879
1880         entry->account_name = talloc_strdup(
1881                 search, state->entries[state->current].account_name);
1882         entry->fullname = talloc_strdup(
1883                 search, state->entries[state->current].fullname);
1884         entry->description = talloc_strdup(
1885                 search, state->entries[state->current].description);
1886
1887         state->current += 1;
1888         return true;
1889 }
1890
1891 static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1892 {
1893         struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1894                 search->private_data, struct pdb_samba_dsdb_search_state);
1895         talloc_free(state);
1896 }
1897
1898 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1899                                      struct pdb_search *search,
1900                                      struct pdb_samba_dsdb_search_state **pstate,
1901                                      const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
1902 {
1903         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1904                 m->private_data, struct pdb_samba_dsdb_state);
1905         struct pdb_samba_dsdb_search_state *sstate;
1906         const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1907                                  "userAccountControl", "description", NULL };
1908         struct ldb_result *res;
1909         int i, rc, num_users;
1910
1911         va_list ap;
1912         char *expression = NULL;
1913
1914         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1915         if (!tmp_ctx) {
1916                 return false;
1917         }
1918
1919         va_start(ap, exp_fmt);
1920         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1921         va_end(ap);
1922
1923         if (!expression) {
1924                 talloc_free(tmp_ctx);
1925                 return LDB_ERR_OPERATIONS_ERROR;
1926         }
1927
1928         sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1929         if (sstate == NULL) {
1930                 talloc_free(tmp_ctx);
1931                 return false;
1932         }
1933
1934         rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1935         if (rc != LDB_SUCCESS) {
1936                 talloc_free(tmp_ctx);
1937                 DEBUG(10, ("dsdb_search failed: %s\n",
1938                            ldb_errstring(state->ldb)));
1939                 return false;
1940         }
1941
1942         num_users = res->count;
1943
1944         sstate->entries = talloc_array(sstate, struct samr_displayentry,
1945                                        num_users);
1946         if (sstate->entries == NULL) {
1947                 talloc_free(tmp_ctx);
1948                 DEBUG(10, ("talloc failed\n"));
1949                 return false;
1950         }
1951
1952         sstate->num_entries = 0;
1953
1954         for (i=0; i<num_users; i++) {
1955                 struct samr_displayentry *e;
1956                 struct dom_sid *sid;
1957
1958                 e = &sstate->entries[sstate->num_entries];
1959
1960                 e->idx = sstate->num_entries;
1961                 sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
1962                 if (!sid) {
1963                         talloc_free(tmp_ctx);
1964                         DEBUG(10, ("Could not pull SID\n"));
1965                         return false;
1966                 }
1967                 sid_peek_rid(sid, &e->rid);
1968
1969                 e->acct_flags = samdb_result_acct_flags(res->msgs[i], "userAccountControl");
1970                 e->account_name = ldb_msg_find_attr_as_string(
1971                         res->msgs[i], "samAccountName", NULL);
1972                 if (e->account_name == NULL) {
1973                         talloc_free(tmp_ctx);
1974                         return false;
1975                 }
1976                 e->fullname = ldb_msg_find_attr_as_string(
1977                         res->msgs[i], "displayName", "");
1978                 e->description = ldb_msg_find_attr_as_string(
1979                         res->msgs[i], "description", "");
1980
1981                 sstate->num_entries += 1;
1982                 if (sstate->num_entries >= num_users) {
1983                         break;
1984                 }
1985         }
1986         talloc_steal(sstate->entries, res->msgs);
1987         search->private_data = talloc_steal(search, sstate);
1988         search->next_entry = pdb_samba_dsdb_next_entry;
1989         search->search_end = pdb_samba_dsdb_search_end;
1990         *pstate = sstate;
1991         talloc_free(tmp_ctx);
1992         return true;
1993 }
1994
1995 static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
1996                                  struct pdb_search *search,
1997                                  uint32 acct_flags)
1998 {
1999         struct pdb_samba_dsdb_search_state *sstate;
2000         bool ret;
2001
2002         ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
2003         if (!ret) {
2004                 return false;
2005         }
2006         sstate->acct_flags = acct_flags;
2007         return true;
2008 }
2009
2010 static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
2011                                   struct pdb_search *search)
2012 {
2013         struct pdb_samba_dsdb_search_state *sstate;
2014         bool ret;
2015
2016         ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2017                                        "(&(grouptype=%d)(objectclass=group))",
2018                                        GTYPE_SECURITY_GLOBAL_GROUP);
2019         if (!ret) {
2020                 return false;
2021         }
2022         sstate->acct_flags = 0;
2023         return true;
2024 }
2025
2026 static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
2027                                    struct pdb_search *search,
2028                                    const struct dom_sid *sid)
2029 {
2030         struct pdb_samba_dsdb_search_state *sstate;
2031         bool ret;
2032
2033         ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2034                                        "(&(grouptype=%d)(objectclass=group))",
2035                                        sid_check_is_builtin(sid)
2036                                        ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2037                                        : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2038         if (!ret) {
2039                 return false;
2040         }
2041         sstate->acct_flags = 0;
2042         return true;
2043 }
2044
2045 /* 
2046  * Instead of taking a gid or uid, this function takes a pointer to a 
2047  * unixid. 
2048  *
2049  * This acts as an in-out variable so that the idmap functions can correctly
2050  * receive ID_TYPE_BOTH, and this function ensures cache details are filled
2051  * correctly rather than forcing the cache to store ID_TYPE_UID or ID_TYPE_GID. 
2052  */
2053 static bool pdb_samba_dsdb_id_to_sid(struct pdb_methods *m, struct unixid *id,
2054                                      struct dom_sid *sid)
2055 {
2056         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2057                 m->private_data, struct pdb_samba_dsdb_state);
2058         NTSTATUS status;
2059         struct id_map id_map;
2060         struct id_map *id_maps[2];
2061         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2062         if (!tmp_ctx) {
2063                 return false;
2064         }
2065
2066         id_map.xid = *id;
2067         id_maps[0] = &id_map;
2068         id_maps[1] = NULL;
2069
2070         status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2071         if (!NT_STATUS_IS_OK(status)) {
2072                 talloc_free(tmp_ctx);
2073                 return false;
2074         }
2075
2076         if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2077                 id->type = id_map.xid.type;
2078         }
2079         *sid = *id_map.sid;
2080         talloc_free(tmp_ctx);
2081         return true;
2082 }
2083
2084 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2085                                  struct unixid *id)
2086 {
2087         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2088                 m->private_data, struct pdb_samba_dsdb_state);
2089         struct id_map id_map;
2090         struct id_map *id_maps[2];
2091         NTSTATUS status;
2092         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2093         if (!tmp_ctx) {
2094                 return false;
2095         }
2096
2097         ZERO_STRUCT(id_map);
2098         id_map.sid = discard_const_p(struct dom_sid, sid);
2099         id_maps[0] = &id_map;
2100         id_maps[1] = NULL;
2101
2102         status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2103         talloc_free(tmp_ctx);
2104         if (!NT_STATUS_IS_OK(status)) {
2105                 return false;
2106         }
2107         if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2108                 *id = id_map.xid;
2109                 return true;
2110         }
2111         return false;
2112 }
2113
2114 static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2115 {
2116         return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
2117 }
2118
2119 static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32 *rid)
2120 {
2121         return false;
2122 }
2123
2124 static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2125                                       const char *domain, char** pwd,
2126                                       struct dom_sid *sid,
2127                                       time_t *pass_last_set_time)
2128 {
2129         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2130                 m->private_data, struct pdb_samba_dsdb_state);
2131         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2132         const char * const attrs[] = {
2133                 "securityIdentifier",
2134                 "trustPartner",
2135                 "trustAuthOutgoing",
2136                 "whenCreated",
2137                 "msDS-SupportedEncryptionTypes",
2138                 "trustAttributes",
2139                 "trustDirection",
2140                 "trustType",
2141                 NULL
2142         };
2143         struct ldb_message *msg;
2144         const struct ldb_val *password_val;
2145         int trust_direction_flags;
2146         int trust_type;
2147         int i;
2148         DATA_BLOB password_utf16;
2149         struct trustAuthInOutBlob password_blob;
2150         struct AuthenticationInformationArray *auth_array;
2151         char *password_talloc;
2152         size_t password_len;
2153         enum ndr_err_code ndr_err;
2154         NTSTATUS status;
2155
2156         status = sam_get_results_trust(state->ldb, tmp_ctx, domain,
2157                                        NULL, attrs, &msg);
2158         if (!NT_STATUS_IS_OK(status)) {
2159                 /*
2160                  * This can be called to work out of a domain is
2161                  * trusted, rather than just to get the password
2162                  */
2163                 DEBUG(2, ("Failed to get trusted domain password for %s.  "
2164                           "It may not be a trusted domain.\n", domain));
2165                 TALLOC_FREE(tmp_ctx);
2166                 return false;
2167         }
2168
2169         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2170         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2171                 DEBUG(2, ("Trusted domain %s is is not an outbound trust.\n",
2172                           domain));
2173                 TALLOC_FREE(tmp_ctx);
2174                 return false;
2175         }
2176
2177         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2178         if (trust_type == LSA_TRUST_TYPE_MIT) {
2179                 DEBUG(1, ("Trusted domain %s is is not an AD trust "
2180                           "(trustType == LSA_TRUST_TYPE_MIT).\n",
2181                           domain));
2182                 TALLOC_FREE(tmp_ctx);
2183                 return false;
2184         }
2185
2186         password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2187         if (password_val == NULL) {
2188                 DEBUG(2, ("Failed to get trusted domain password for %s, "
2189                           "attribute trustAuthOutgoing not returned.\n", domain));
2190                 TALLOC_FREE(tmp_ctx);
2191                 return false;
2192         }
2193
2194         ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2195                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2196         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2197                 DEBUG(0, ("Failed to get trusted domain password for %s, "
2198                           "attribute trustAuthOutgoing coult not be parsed %s.\n",
2199                           domain,
2200                           ndr_map_error2string(ndr_err)));
2201                 TALLOC_FREE(tmp_ctx);
2202                 return false;
2203         }
2204
2205         auth_array = &password_blob.current;
2206
2207         for (i=0; i < auth_array->count; i++) {
2208                 if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
2209                         break;
2210                 }
2211         }
2212
2213         if (i == auth_array->count) {
2214                 DEBUG(0, ("Trusted domain %s does not have a "
2215                           "clear-text password stored\n",
2216                           domain));
2217                 TALLOC_FREE(tmp_ctx);
2218                 return false;
2219         }
2220
2221         password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
2222                                          auth_array->array[i].AuthInfo.clear.size);
2223
2224         /*
2225          * In the future, make this function return a
2226          * cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash()
2227          * but for now convert to UTF8 and fail if the string can not be converted.
2228          *
2229          * We can't safely convert the random strings windows uses into
2230          * utf8.
2231          */
2232         if (!convert_string_talloc(tmp_ctx,
2233                                    CH_UTF16, CH_UTF8,
2234                                    password_utf16.data, password_utf16.length,
2235                                    (void *)&password_talloc,
2236                                    &password_len)) {
2237                 DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
2238                           " to UTF8. This may be a password set from Windows.\n",
2239                           domain));
2240                 TALLOC_FREE(tmp_ctx);
2241                 return false;
2242         }
2243         *pwd = SMB_STRNDUP(password_talloc, password_len);
2244         if (pass_last_set_time) {
2245                 *pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
2246         }
2247
2248         TALLOC_FREE(tmp_ctx);
2249         return true;
2250 }
2251
2252 static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2253                                       const char* domain, const char* pwd,
2254                                       const struct dom_sid *sid)
2255 {
2256         return false;
2257 }
2258
2259 static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2260                                       const char *domain)
2261 {
2262         return false;
2263 }
2264
2265 static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2266                                          TALLOC_CTX *mem_ctx,
2267                                          uint32 *num_domains,
2268                                          struct trustdom_info ***domains)
2269 {
2270         *num_domains = 0;
2271         *domains = NULL;
2272         return NT_STATUS_OK;
2273 }
2274
2275 static bool pdb_samba_dsdb_is_responsible_for_wellknown(struct pdb_methods *m)
2276 {
2277         return true;
2278 }
2279
2280 static bool pdb_samba_dsdb_is_responsible_for_everything_else(struct pdb_methods *m)
2281 {
2282         return true;
2283 }
2284
2285 static void pdb_samba_dsdb_init_methods(struct pdb_methods *m)
2286 {
2287         m->name = "samba_dsdb";
2288         m->get_domain_info = pdb_samba_dsdb_get_domain_info;
2289         m->getsampwnam = pdb_samba_dsdb_getsampwnam;
2290         m->getsampwsid = pdb_samba_dsdb_getsampwsid;
2291         m->create_user = pdb_samba_dsdb_create_user;
2292         m->delete_user = pdb_samba_dsdb_delete_user;
2293         m->add_sam_account = pdb_samba_dsdb_add_sam_account;
2294         m->update_sam_account = pdb_samba_dsdb_update_sam_account;
2295         m->delete_sam_account = pdb_samba_dsdb_delete_sam_account;
2296         m->rename_sam_account = pdb_samba_dsdb_rename_sam_account;
2297         m->update_login_attempts = pdb_samba_dsdb_update_login_attempts;
2298         m->getgrsid = pdb_samba_dsdb_getgrsid;
2299         m->getgrgid = pdb_samba_dsdb_getgrgid;
2300         m->getgrnam = pdb_samba_dsdb_getgrnam;
2301         m->create_dom_group = pdb_samba_dsdb_create_dom_group;
2302         m->delete_dom_group = pdb_samba_dsdb_delete_dom_group;
2303         m->add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry;
2304         m->update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry;
2305         m->delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry;
2306         m->enum_group_mapping = pdb_samba_dsdb_enum_group_mapping;
2307         m->enum_group_members = pdb_samba_dsdb_enum_group_members;
2308         m->enum_group_memberships = pdb_samba_dsdb_enum_group_memberships;
2309         m->set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group;
2310         m->add_groupmem = pdb_samba_dsdb_add_groupmem;
2311         m->del_groupmem = pdb_samba_dsdb_del_groupmem;
2312         m->create_alias = pdb_samba_dsdb_create_alias;
2313         m->delete_alias = pdb_samba_dsdb_delete_alias;
2314         m->get_aliasinfo = pdb_default_get_aliasinfo;
2315         m->add_aliasmem = pdb_samba_dsdb_add_aliasmem;
2316         m->del_aliasmem = pdb_samba_dsdb_del_aliasmem;
2317         m->enum_aliasmem = pdb_samba_dsdb_enum_aliasmem;
2318         m->enum_alias_memberships = pdb_samba_dsdb_enum_alias_memberships;
2319         m->lookup_rids = pdb_samba_dsdb_lookup_rids;
2320         m->lookup_names = pdb_samba_dsdb_lookup_names;
2321         m->get_account_policy = pdb_samba_dsdb_get_account_policy;
2322         m->set_account_policy = pdb_samba_dsdb_set_account_policy;
2323         m->get_seq_num = pdb_samba_dsdb_get_seq_num;
2324         m->search_users = pdb_samba_dsdb_search_users;
2325         m->search_groups = pdb_samba_dsdb_search_groups;
2326         m->search_aliases = pdb_samba_dsdb_search_aliases;
2327         m->id_to_sid = pdb_samba_dsdb_id_to_sid;
2328         m->sid_to_id = pdb_samba_dsdb_sid_to_id;
2329         m->capabilities = pdb_samba_dsdb_capabilities;
2330         m->new_rid = pdb_samba_dsdb_new_rid;
2331         m->get_trusteddom_pw = pdb_samba_dsdb_get_trusteddom_pw;
2332         m->set_trusteddom_pw = pdb_samba_dsdb_set_trusteddom_pw;
2333         m->del_trusteddom_pw = pdb_samba_dsdb_del_trusteddom_pw;
2334         m->enum_trusteddoms = pdb_samba_dsdb_enum_trusteddoms;
2335         m->is_responsible_for_wellknown =
2336                                 pdb_samba_dsdb_is_responsible_for_wellknown;
2337         m->is_responsible_for_everything_else =
2338                                 pdb_samba_dsdb_is_responsible_for_everything_else;
2339 }
2340
2341 static void free_private_data(void **vp)
2342 {
2343         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2344                 *vp, struct pdb_samba_dsdb_state);
2345         talloc_unlink(state, state->ldb);
2346         return;
2347 }
2348
2349 static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m)
2350 {
2351         struct pdb_domain_info *dom_info;
2352         struct dom_sid stored_sid;
2353         struct GUID stored_guid;
2354         bool sid_exists_and_matches = false;
2355         bool guid_exists_and_matches = false;
2356         bool ret;
2357
2358         dom_info = pdb_samba_dsdb_get_domain_info(m, m);
2359         if (!dom_info) {
2360                 return NT_STATUS_UNSUCCESSFUL;
2361         }
2362
2363         ret = secrets_fetch_domain_sid(dom_info->name, &stored_sid);
2364         if (ret) {
2365                 if (dom_sid_equal(&stored_sid, &dom_info->sid)) {
2366                         sid_exists_and_matches = true;
2367                 }
2368         }
2369
2370         if (sid_exists_and_matches == false) {
2371                 secrets_clear_domain_protection(dom_info->name);
2372                 ret = secrets_store_domain_sid(dom_info->name,
2373                                                &dom_info->sid);
2374                 ret &= secrets_mark_domain_protected(dom_info->name);
2375                 if (!ret) {
2376                         goto done;
2377                 }
2378         }
2379
2380         ret = secrets_fetch_domain_guid(dom_info->name, &stored_guid);
2381         if (ret) {
2382                 if (GUID_equal(&stored_guid, &dom_info->guid)) {
2383                         guid_exists_and_matches = true;
2384                 }
2385         }
2386
2387         if (guid_exists_and_matches == false) {
2388                 secrets_clear_domain_protection(dom_info->name);
2389                 ret = secrets_store_domain_guid(dom_info->name,
2390                                                &dom_info->guid);
2391                 ret &= secrets_mark_domain_protected(dom_info->name);
2392                 if (!ret) {
2393                         goto done;
2394                 }
2395         }
2396
2397 done:
2398         TALLOC_FREE(dom_info);
2399         if (!ret) {
2400                 return NT_STATUS_UNSUCCESSFUL;
2401         }
2402         return NT_STATUS_OK;
2403 }
2404
2405 static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
2406                              const char *location)
2407 {
2408         struct pdb_methods *m;
2409         struct pdb_samba_dsdb_state *state;
2410         NTSTATUS status;
2411
2412         if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
2413                 return status;
2414         }
2415
2416         state = talloc_zero(m, struct pdb_samba_dsdb_state);
2417         if (state == NULL) {
2418                 goto nomem;
2419         }
2420         m->private_data = state;
2421         m->free_private_data = free_private_data;
2422         pdb_samba_dsdb_init_methods(m);
2423
2424         state->ev = s4_event_context_init(state);
2425         if (!state->ev) {
2426                 DEBUG(0, ("s4_event_context_init failed\n"));
2427                 goto nomem;
2428         }
2429
2430         state->lp_ctx = loadparm_init_s3(state, loadparm_s3_helpers());
2431         if (state->lp_ctx == NULL) {
2432                 DEBUG(0, ("loadparm_init_s3 failed\n"));
2433                 goto nomem;
2434         }
2435
2436         if (location) {
2437                 state->ldb = samdb_connect_url(state,
2438                                    state->ev,
2439                                    state->lp_ctx,
2440                                    system_session(state->lp_ctx),
2441                                    0, location);
2442         } else {
2443                 state->ldb = samdb_connect(state,
2444                                    state->ev,
2445                                    state->lp_ctx,
2446                                    system_session(state->lp_ctx), 0);
2447         }
2448
2449         if (!state->ldb) {
2450                 DEBUG(0, ("samdb_connect failed\n"));
2451                 status = NT_STATUS_INTERNAL_ERROR;
2452                 goto fail;
2453         }
2454
2455         state->idmap_ctx = idmap_init(state, state->ev,
2456                                       state->lp_ctx);
2457         if (!state->idmap_ctx) {
2458                 DEBUG(0, ("idmap failed\n"));
2459                 status = NT_STATUS_INTERNAL_ERROR;
2460                 goto fail;
2461         }
2462
2463         status = pdb_samba_dsdb_init_secrets(m);
2464         if (!NT_STATUS_IS_OK(status)) {
2465                 DEBUG(10, ("pdb_samba_dsdb_init_secrets failed!\n"));
2466                 goto fail;
2467         }
2468
2469         *pdb_method = m;
2470         return NT_STATUS_OK;
2471 nomem:
2472         status = NT_STATUS_NO_MEMORY;
2473 fail:
2474         TALLOC_FREE(m);
2475         return status;
2476 }
2477
2478 NTSTATUS pdb_samba_dsdb_init(void);
2479 NTSTATUS pdb_samba_dsdb_init(void)
2480 {
2481         NTSTATUS status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba_dsdb",
2482                                               pdb_init_samba_dsdb);
2483         if (!NT_STATUS_IS_OK(status)) {
2484                 return status;
2485         }
2486         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4",
2487                                    pdb_init_samba_dsdb);
2488 }