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