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