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