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