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