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