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