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