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