56f3f107cef6c86660aa0aab5ff1c03c8149da1f
[bbaumbach/samba-autobuild/.git] / source3 / passdb / pdb_samba_dsdb.c
1 /*
2    Unix SMB/CIFS implementation.
3    pdb glue module for direct access to the dsdb via LDB APIs
4    Copyright (C) Volker Lendecke 2009-2011
5    Copyright (C) Andrew Bartlett 2010-2012
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 "librpc/gen_ndr/ndr_drsblobs.h"
32 #include "librpc/gen_ndr/ndr_lsa.h"
33 #include "libds/common/flag_mapping.h"
34 #include "source4/lib/events/events.h"
35 #include "source4/auth/session.h"
36 #include "source4/auth/system_session_proto.h"
37 #include "lib/param/param.h"
38 #include "source4/dsdb/common/util.h"
39 #include "source3/include/secrets.h"
40 #include "source4/auth/auth_sam.h"
41 #include "auth/credentials/credentials.h"
42 #include "lib/util/base64.h"
43
44 struct pdb_samba_dsdb_state {
45         struct tevent_context *ev;
46         struct ldb_context *ldb;
47         struct idmap_context *idmap_ctx;
48         struct loadparm_context *lp_ctx;
49 };
50
51 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
52                                     struct samu *sam_acct,
53                                     const struct dom_sid *sid);
54 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
55                                     const char *filter,
56                                     TALLOC_CTX *mem_ctx,
57                                     struct ldb_message **pmsg);
58 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
59                                  struct unixid *id);
60
61 static bool pdb_samba_dsdb_pull_time(struct ldb_message *msg, const char *attr,
62                               time_t *ptime)
63 {
64         uint64_t tmp;
65         if (! ldb_msg_find_element(msg, attr)) {
66                 return false;
67         }
68         tmp = ldb_msg_find_attr_as_uint64(msg, attr, 0);
69         *ptime = nt_time_to_unix(tmp);
70         return true;
71 }
72
73 static struct pdb_domain_info *pdb_samba_dsdb_get_domain_info(
74         struct pdb_methods *m, TALLOC_CTX *mem_ctx)
75 {
76         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
77                 m->private_data, struct pdb_samba_dsdb_state);
78         struct pdb_domain_info *info;
79         struct dom_sid *domain_sid;
80         struct ldb_dn *forest_dn, *domain_dn;
81         struct ldb_result *dom_res = NULL;
82         const char *dom_attrs[] = {
83                 "objectSid",
84                 "objectGUID",
85                 "fSMORoleOwner",
86                 NULL
87         };
88         char *p;
89         int ret;
90
91         info = talloc(mem_ctx, struct pdb_domain_info);
92         if (info == NULL) {
93                 return NULL;
94         }
95
96         domain_dn = ldb_get_default_basedn(state->ldb);
97
98         ret = ldb_search(state->ldb, info, &dom_res,
99                          domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
100         if (ret != LDB_SUCCESS) {
101                 goto fail;
102         }
103         if (dom_res->count != 1) {
104                 goto fail;
105         }
106
107         info->guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
108
109         domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
110         if (!domain_sid) {
111                 goto fail;
112         }
113         info->sid = *domain_sid;
114
115         TALLOC_FREE(dom_res);
116
117         info->name = talloc_strdup(info, lpcfg_sam_name(state->lp_ctx));
118         info->dns_domain = ldb_dn_canonical_string(info, domain_dn);
119
120         if (!info->dns_domain) {
121                 goto fail;
122         }
123         p = strchr(info->dns_domain, '/');
124         if (p) {
125                 *p = '\0';
126         }
127
128         forest_dn = ldb_get_root_basedn(state->ldb);
129         if (!forest_dn) {
130                 goto fail;
131         }
132
133         info->dns_forest = ldb_dn_canonical_string(info, forest_dn);
134         if (!info->dns_forest) {
135                 goto fail;
136         }
137         p = strchr(info->dns_forest, '/');
138         if (p) {
139                 *p = '\0';
140         }
141
142         return info;
143
144 fail:
145         TALLOC_FREE(dom_res);
146         TALLOC_FREE(info);
147         return NULL;
148 }
149
150 static struct ldb_message *pdb_samba_dsdb_get_samu_private(
151         struct pdb_methods *m, struct samu *sam)
152 {
153         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
154                 m->private_data, struct pdb_samba_dsdb_state);
155         struct ldb_message *msg;
156         char *sidstr, *filter;
157         NTSTATUS status;
158
159         msg = (struct ldb_message *)
160                 pdb_get_backend_private_data(sam, m);
161
162         if (msg != NULL) {
163                 return talloc_get_type_abort(msg, struct ldb_message);
164         }
165
166         sidstr = dom_sid_string(talloc_tos(), pdb_get_user_sid(sam));
167         if (sidstr == NULL) {
168                 return NULL;
169         }
170
171         filter = talloc_asprintf(
172                 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
173         TALLOC_FREE(sidstr);
174         if (filter == NULL) {
175                 return NULL;
176         }
177
178         status = pdb_samba_dsdb_getsamupriv(state, filter, sam, &msg);
179         TALLOC_FREE(filter);
180         if (!NT_STATUS_IS_OK(status)) {
181                 return NULL;
182         }
183
184         return msg;
185 }
186
187 static NTSTATUS pdb_samba_dsdb_init_sam_from_priv(struct pdb_methods *m,
188                                            struct samu *sam,
189                                            struct ldb_message *msg)
190 {
191         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
192                 m->private_data, struct pdb_samba_dsdb_state);
193         TALLOC_CTX *frame = talloc_stackframe();
194         NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
195         const char *str;
196         time_t tmp_time;
197         struct dom_sid *sid, group_sid;
198         uint64_t n;
199         const DATA_BLOB *blob;
200
201         str = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
202         if (str == NULL) {
203                 DEBUG(10, ("no samAccountName\n"));
204                 goto fail;
205         }
206         pdb_set_username(sam, str, PDB_SET);
207
208         if (pdb_samba_dsdb_pull_time(msg, "lastLogon", &tmp_time)) {
209                 pdb_set_logon_time(sam, tmp_time, PDB_SET);
210         }
211         if (pdb_samba_dsdb_pull_time(msg, "lastLogoff", &tmp_time)) {
212                 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
213         }
214         if (pdb_samba_dsdb_pull_time(msg, "pwdLastSet", &tmp_time)) {
215                 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
216         }
217         if (pdb_samba_dsdb_pull_time(msg, "accountExpires", &tmp_time)) {
218                 pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
219         }
220
221         str = ldb_msg_find_attr_as_string(msg, "displayName",
222                                             NULL);
223         if (str != NULL) {
224                 pdb_set_fullname(sam, str, PDB_SET);
225         }
226
227         str = ldb_msg_find_attr_as_string(msg, "homeDirectory",
228                                             NULL);
229         if (str != NULL) {
230                 pdb_set_homedir(sam, str, PDB_SET);
231         }
232
233         str = ldb_msg_find_attr_as_string(msg, "homeDrive", NULL);
234         if (str != NULL) {
235                 pdb_set_dir_drive(sam, str, PDB_SET);
236         }
237
238         str = ldb_msg_find_attr_as_string(msg, "scriptPath", NULL);
239         if (str != NULL) {
240                 pdb_set_logon_script(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         blob = ldb_msg_find_ldb_val(msg, "userParameters");
268         if (blob != NULL) {
269                 str = base64_encode_data_blob(frame, *blob);
270                 if (str == NULL) {
271                         DEBUG(0, ("base64_encode_data_blob() failed\n"));
272                         goto fail;
273                 }
274                 pdb_set_munged_dial(sam, str, PDB_SET);
275         }
276
277         sid = samdb_result_dom_sid(talloc_tos(), msg, "objectSid");
278         if (!sid) {
279                 DEBUG(10, ("Could not pull SID\n"));
280                 goto fail;
281         }
282         pdb_set_user_sid(sam, sid, PDB_SET);
283
284         n = samdb_result_acct_flags(msg, "msDS-User-Account-Control-Computed");
285         if (n == 0) {
286                 DEBUG(10, ("Could not pull userAccountControl\n"));
287                 goto fail;
288         }
289         pdb_set_acct_ctrl(sam, n, PDB_SET);
290
291         blob = ldb_msg_find_ldb_val(msg, "unicodePwd");
292         if (blob) {
293                 if (blob->length != NT_HASH_LEN) {
294                         DEBUG(0, ("Got NT hash of length %d, expected %d\n",
295                                   (int)blob->length, NT_HASH_LEN));
296                         goto fail;
297                 }
298                 pdb_set_nt_passwd(sam, blob->data, PDB_SET);
299         }
300
301         blob = ldb_msg_find_ldb_val(msg, "dBCSPwd");
302         if (blob) {
303                 if (blob->length != LM_HASH_LEN) {
304                         DEBUG(0, ("Got LM hash of length %d, expected %d\n",
305                                   (int)blob->length, LM_HASH_LEN));
306                         goto fail;
307                 }
308                 pdb_set_lanman_passwd(sam, blob->data, PDB_SET);
309         }
310
311         n = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", 0);
312         if (n == 0) {
313                 DEBUG(10, ("Could not pull primaryGroupID\n"));
314                 goto fail;
315         }
316         sid_compose(&group_sid, samdb_domain_sid(state->ldb), n);
317         pdb_set_group_sid(sam, &group_sid, PDB_SET);
318
319         status = NT_STATUS_OK;
320 fail:
321         TALLOC_FREE(frame);
322         return status;
323 }
324
325 static bool pdb_samba_dsdb_add_time(struct ldb_message *msg,
326                                 const char *attrib, time_t t)
327 {
328         uint64_t nt_time;
329
330         unix_to_nt_time(&nt_time, t);
331
332         return ldb_msg_add_fmt(msg, attrib, "%llu", (unsigned long long) nt_time);
333 }
334
335 static int pdb_samba_dsdb_replace_by_sam(struct pdb_samba_dsdb_state *state,
336                                      bool (*need_update)(const struct samu *,
337                                                          enum pdb_elements),
338                                      struct ldb_dn *dn,
339                                      struct samu *sam)
340 {
341         TALLOC_CTX *frame = talloc_stackframe();
342         int ret = LDB_SUCCESS;
343         const char *pw;
344         struct ldb_message *msg;
345         struct ldb_request *req;
346         uint32_t dsdb_flags = 0;
347         /* TODO: All fields :-) */
348
349         msg = ldb_msg_new(frame);
350         if (!msg) {
351                 talloc_free(frame);
352                 return false;
353         }
354
355         msg->dn = dn;
356
357         /* build modify request */
358         ret = ldb_build_mod_req(&req, state->ldb, frame, msg, NULL, NULL,
359                                 ldb_op_default_callback,
360                                 NULL);
361         if (ret != LDB_SUCCESS) {
362                 talloc_free(frame);
363                 return ret;
364         }
365
366         /* If we set a plaintext password, the system will
367          * force the pwdLastSet to now() */
368         if (need_update(sam, PDB_PASSLASTSET)) {
369                 dsdb_flags = DSDB_PASSWORD_BYPASS_LAST_SET;
370
371                 ret |= pdb_samba_dsdb_add_time(msg, "pwdLastSet",
372                                            pdb_get_pass_last_set_time(sam));
373         }
374
375         pw = pdb_get_plaintext_passwd(sam);
376         if (need_update(sam, PDB_PLAINTEXT_PW)) {
377                 struct ldb_val pw_utf16;
378                 if (pw == NULL) {
379                         talloc_free(frame);
380                         return LDB_ERR_OPERATIONS_ERROR;
381                 }
382
383                 if (!convert_string_talloc(msg,
384                                            CH_UNIX, CH_UTF16,
385                                            pw, strlen(pw),
386                                            (void *)&pw_utf16.data,
387                                            &pw_utf16.length)) {
388                         talloc_free(frame);
389                         return LDB_ERR_OPERATIONS_ERROR;
390                 }
391                 ret |= ldb_msg_add_value(msg, "clearTextPassword", &pw_utf16, NULL);
392         } else {
393                 bool changed_lm_pw = false;
394                 bool changed_nt_pw = false;
395                 bool changed_history = false;
396                 if (need_update(sam, PDB_LMPASSWD)) {
397                         struct ldb_val val;
398                         val.data = discard_const_p(uint8_t, pdb_get_lanman_passwd(sam));
399                         if (!val.data) {
400                                 samdb_msg_add_delete(state->ldb, msg, msg,
401                                                      "dBCSPwd");
402                         } else {
403                                 val.length = LM_HASH_LEN;
404                                 ret |= ldb_msg_add_value(msg, "dBCSPwd", &val, NULL);
405                         }
406                         changed_lm_pw = true;
407                 }
408                 if (need_update(sam, PDB_NTPASSWD)) {
409                         struct ldb_val val;
410                         val.data = discard_const_p(uint8_t, pdb_get_nt_passwd(sam));
411                         if (!val.data) {
412                                 samdb_msg_add_delete(state->ldb, msg, msg,
413                                                      "unicodePwd");
414                         } else {
415                                 val.length = NT_HASH_LEN;
416                                 ret |= ldb_msg_add_value(msg, "unicodePwd", &val, NULL);
417                         }
418                         changed_nt_pw = true;
419                 }
420
421                 /* Try to ensure we don't get out of sync */
422                 if (changed_lm_pw && !changed_nt_pw) {
423                         samdb_msg_add_delete(state->ldb, msg, msg,
424                                              "unicodePwd");
425                 } else if (changed_nt_pw && !changed_lm_pw) {
426                         samdb_msg_add_delete(state->ldb, msg, msg,
427                                              "dBCSPwd");
428                 }
429                 if (changed_lm_pw || changed_nt_pw) {
430                         samdb_msg_add_delete(state->ldb, msg, msg,
431                                              "supplementalCredentials");
432
433                 }
434
435                 if (need_update(sam, PDB_PWHISTORY)) {
436                         uint32_t current_hist_len;
437                         const uint8_t *history = pdb_get_pw_history(sam, &current_hist_len);
438
439                         bool invalid_history = false;
440                         struct samr_Password *history_hashes = talloc_array(talloc_tos(), struct samr_Password,
441                                                                             current_hist_len);
442                         if (!history) {
443                                 invalid_history = true;
444                         } else {
445                                 unsigned int i;
446                                 static const uint8_t zeros[16];
447                                 /* Parse the history into the correct format */
448                                 for (i = 0; i < current_hist_len; i++) {
449                                         if (memcmp(&history[i*PW_HISTORY_ENTRY_LEN], zeros, 16) != 0) {
450                                                 /* If the history is in the old format, with a salted hash, then we can't migrate it to AD format */
451                                                 invalid_history = true;
452                                                 break;
453                                         }
454                                         /* Copy out the 2nd 16 bytes of the 32 byte password history, containing the NT hash */
455                                         memcpy(history_hashes[i].hash,
456                                                &history[(i*PW_HISTORY_ENTRY_LEN) + PW_HISTORY_SALT_LEN],
457                                                sizeof(history_hashes[i].hash));
458                                 }
459                         }
460                         if (invalid_history) {
461                                 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
462                                                      "ntPwdHistory");
463
464                                 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
465                                                      "lmPwdHistory");
466                         } else {
467                                 ret |= samdb_msg_add_hashes(state->ldb, msg, msg,
468                                                             "ntPwdHistory",
469                                                             history_hashes,
470                                                             current_hist_len);
471                         }
472                         changed_history = true;
473                 }
474                 if (changed_lm_pw || changed_nt_pw || changed_history) {
475                         /* These attributes can only be modified directly by using a special control */
476                         dsdb_flags = DSDB_BYPASS_PASSWORD_HASH;
477                 }
478         }
479
480         /* PDB_USERSID is only allowed on ADD, handled in caller */
481         if (need_update(sam, PDB_GROUPSID)) {
482                 const struct dom_sid *sid = pdb_get_group_sid(sam);
483                 uint32_t rid;
484                 NTSTATUS status = dom_sid_split_rid(NULL, sid, NULL, &rid);
485                 if (!NT_STATUS_IS_OK(status)) {
486                         talloc_free(frame);
487                         return LDB_ERR_OPERATIONS_ERROR;
488                 }
489                 if (!dom_sid_in_domain(samdb_domain_sid(state->ldb), sid)) {
490                         talloc_free(frame);
491                         return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
492                 }
493                 ret |= samdb_msg_add_uint(state->ldb, msg, msg, "primaryGroupID", rid);
494         }
495         if (need_update(sam, PDB_FULLNAME)) {
496                 ret |= ldb_msg_add_string(msg, "displayName", pdb_get_fullname(sam));
497         }
498
499         if (need_update(sam, PDB_SMBHOME)) {
500                 ret |= ldb_msg_add_string(msg, "homeDirectory",
501                                           pdb_get_homedir(sam));
502         }
503
504         if (need_update(sam, PDB_PROFILE)) {
505                 ret |= ldb_msg_add_string(msg, "profilePath",
506                                           pdb_get_profile_path(sam));
507         }
508
509         if (need_update(sam, PDB_DRIVE)) {
510                 ret |= ldb_msg_add_string(msg, "homeDrive",
511                                           pdb_get_dir_drive(sam));
512         }
513
514         if (need_update(sam, PDB_LOGONSCRIPT)) {
515                 ret |= ldb_msg_add_string(msg, "scriptPath",
516                                           pdb_get_logon_script(sam));
517         }
518
519         if (need_update(sam, PDB_KICKOFFTIME)) {
520                 ret |= pdb_samba_dsdb_add_time(msg, "accountExpires",
521                                         pdb_get_kickoff_time(sam));
522         }
523
524         if (need_update(sam, PDB_LOGONTIME)) {
525                 ret |= pdb_samba_dsdb_add_time(msg, "lastLogon",
526                                         pdb_get_logon_time(sam));
527         }
528
529         if (need_update(sam, PDB_LOGOFFTIME)) {
530                 ret |= pdb_samba_dsdb_add_time(msg, "lastLogoff",
531                                         pdb_get_logoff_time(sam));
532         }
533
534         if (need_update(sam, PDB_USERNAME)) {
535                 ret |= ldb_msg_add_string(msg, "samAccountName",
536                                           pdb_get_username(sam));
537         }
538
539         if (need_update(sam, PDB_HOURSLEN) || need_update(sam, PDB_HOURS)) {
540                 struct ldb_val hours = data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam));
541                 ret |= ldb_msg_add_value(msg, "logonHours",
542                                          &hours, NULL);
543         }
544
545         if (need_update(sam, PDB_ACCTCTRL)) {
546                 ret |= samdb_msg_add_acct_flags(state->ldb, msg, msg,
547                                                 "userAccountControl", pdb_get_acct_ctrl(sam));
548         }
549
550         if (need_update(sam, PDB_COMMENT)) {
551                 ret |= ldb_msg_add_string(msg, "comment",
552                                           pdb_get_comment(sam));
553         }
554
555         if (need_update(sam, PDB_ACCTDESC)) {
556                 ret |= ldb_msg_add_string(msg, "description",
557                                           pdb_get_acct_desc(sam));
558         }
559
560         if (need_update(sam, PDB_WORKSTATIONS)) {
561                 ret |= ldb_msg_add_string(msg, "userWorkstations",
562                                           pdb_get_workstations(sam));
563         }
564
565         /* This will need work, it is actually a UTF8 'string' with internal NULLs, to handle TS parameters */
566         if (need_update(sam, PDB_MUNGEDDIAL)) {
567                 const char *base64_munged_dial = NULL;
568
569                 base64_munged_dial = pdb_get_munged_dial(sam);
570                 if (base64_munged_dial != NULL && strlen(base64_munged_dial) > 0) {
571                         struct ldb_val blob;
572
573                         blob = base64_decode_data_blob_talloc(msg,
574                                                         base64_munged_dial);
575                         if (blob.data == NULL) {
576                                 DEBUG(0, ("Failed to decode userParameters from "
577                                           "munged dialback string[%s] for %s\n",
578                                           base64_munged_dial,
579                                           ldb_dn_get_linearized(msg->dn)));
580                                 talloc_free(frame);
581                                 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
582                         }
583                         ret |= ldb_msg_add_steal_value(msg, "userParameters",
584                                                        &blob);
585                 }
586         }
587
588         if (need_update(sam, PDB_COUNTRY_CODE)) {
589                 ret |= ldb_msg_add_fmt(msg, "countryCode",
590                                        "%i", (int)pdb_get_country_code(sam));
591         }
592
593         if (need_update(sam, PDB_CODE_PAGE)) {
594                 ret |= ldb_msg_add_fmt(msg, "codePage",
595                                        "%i", (int)pdb_get_code_page(sam));
596         }
597
598         /* Not yet handled here or not meaningful for modifies on a Samba_Dsdb backend:
599         PDB_BAD_PASSWORD_TIME,
600         PDB_CANCHANGETIME, - these are calculated per policy, not stored
601         PDB_DOMAIN,
602         PDB_NTUSERNAME, - this makes no sense, and never really did
603         PDB_LOGONDIVS,
604         PDB_USERSID, - Handled in pdb_samba_dsdb_add_sam_account()
605         PDB_FIELDS_PRESENT,
606         PDB_BAD_PASSWORD_COUNT,
607         PDB_LOGON_COUNT,
608         PDB_UNKNOWN6,
609         PDB_BACKEND_PRIVATE_DATA,
610
611  */
612         if (ret != LDB_SUCCESS) {
613                 talloc_free(frame);
614                 return LDB_ERR_OPERATIONS_ERROR;
615         }
616
617         if (msg->num_elements == 0) {
618                 talloc_free(frame);
619                 /* Nothing to do, just return success */
620                 return LDB_SUCCESS;
621         }
622
623         ret = dsdb_replace(state->ldb, msg, dsdb_flags);
624
625         if (ret != LDB_SUCCESS) {
626                 DEBUG(0,("Failed to modify account record %s to set user attributes: %s\n",
627                          ldb_dn_get_linearized(msg->dn),
628                          ldb_errstring(state->ldb)));
629         }
630
631         talloc_free(frame);
632         return ret;
633 }
634
635 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
636                                     const char *filter,
637                                     TALLOC_CTX *mem_ctx,
638                                     struct ldb_message **msg)
639 {
640         const char * attrs[] = {
641                 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
642                 "sAMAccountName", "displayName", "homeDirectory",
643                 "homeDrive", "scriptPath", "profilePath", "description",
644                 "userWorkstations", "comment", "userParameters", "objectSid",
645                 "primaryGroupID", "userAccountControl",
646                 "msDS-User-Account-Control-Computed", "logonHours",
647                 "badPwdCount", "logonCount", "countryCode", "codePage",
648                 "unicodePwd", "dBCSPwd", NULL };
649
650         int rc = dsdb_search_one(state->ldb, mem_ctx, msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter);
651         if (rc != LDB_SUCCESS) {
652                 DEBUG(10, ("ldap_search failed %s\n",
653                            ldb_errstring(state->ldb)));
654                 return NT_STATUS_LDAP(rc);
655         }
656
657         return NT_STATUS_OK;
658 }
659
660 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
661                                           struct pdb_samba_dsdb_state *state,
662                                           struct samu *sam_acct,
663                                           const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
664 {
665         struct ldb_message *priv;
666         NTSTATUS status;
667         va_list ap;
668         char *expression = NULL;
669         TALLOC_CTX *tmp_ctx = talloc_new(state);
670         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
671
672         va_start(ap, exp_fmt);
673         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
674         va_end(ap);
675
676         if (!expression) {
677                 talloc_free(tmp_ctx);
678                 return NT_STATUS_NO_MEMORY;
679         }
680
681         status = pdb_samba_dsdb_getsamupriv(state, expression, sam_acct, &priv);
682         talloc_free(tmp_ctx);
683         if (!NT_STATUS_IS_OK(status)) {
684                 DEBUG(10, ("pdb_samba_dsdb_getsamupriv failed: %s\n",
685                            nt_errstr(status)));
686                 return status;
687         }
688
689         status = pdb_samba_dsdb_init_sam_from_priv(m, sam_acct, priv);
690         if (!NT_STATUS_IS_OK(status)) {
691                 DEBUG(10, ("pdb_samba_dsdb_init_sam_from_priv failed: %s\n",
692                            nt_errstr(status)));
693                 TALLOC_FREE(priv);
694                 return status;
695         }
696
697         pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
698         return NT_STATUS_OK;
699 }
700
701 static NTSTATUS pdb_samba_dsdb_getsampwnam(struct pdb_methods *m,
702                                     struct samu *sam_acct,
703                                     const char *username)
704 {
705         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
706                 m->private_data, struct pdb_samba_dsdb_state);
707
708         return pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
709                                          "(&(samaccountname=%s)(objectclass=user))",
710                                          username);
711 }
712
713 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
714                                     struct samu *sam_acct,
715                                     const struct dom_sid *sid)
716 {
717         NTSTATUS status;
718         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
719                 m->private_data, struct pdb_samba_dsdb_state);
720         char *sidstr;
721
722         sidstr = dom_sid_string(talloc_tos(), sid);
723         NT_STATUS_HAVE_NO_MEMORY(sidstr);
724
725         status = pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
726                                            "(&(objectsid=%s)(objectclass=user))",
727                                            sidstr);
728         talloc_free(sidstr);
729         return status;
730 }
731
732 static NTSTATUS pdb_samba_dsdb_create_user(struct pdb_methods *m,
733                                     TALLOC_CTX *mem_ctx,
734                                     const char *name, uint32_t acct_flags,
735                                     uint32_t *rid)
736 {
737         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
738                 m->private_data, struct pdb_samba_dsdb_state);
739         struct dom_sid *sid;
740         struct ldb_dn *dn;
741         NTSTATUS status;
742         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
743         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
744
745         /* Internally this uses transactions to ensure all the steps
746          * happen or fail as one */
747         status = dsdb_add_user(state->ldb, tmp_ctx, name, acct_flags, NULL,
748                                &sid, &dn);
749         if (!NT_STATUS_IS_OK(status)) {
750                 talloc_free(tmp_ctx);
751                 return status;
752         }
753         sid_peek_rid(sid, rid);
754         talloc_free(tmp_ctx);
755         return NT_STATUS_OK;
756 }
757
758 static NTSTATUS pdb_samba_dsdb_delete_user(struct pdb_methods *m,
759                                        TALLOC_CTX *mem_ctx,
760                                        struct samu *sam)
761 {
762         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
763                 m->private_data, struct pdb_samba_dsdb_state);
764         struct ldb_dn *dn;
765         int rc;
766         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
767         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
768
769         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, pdb_get_user_sid(sam)));
770         if (!dn || !ldb_dn_validate(dn)) {
771                 talloc_free(tmp_ctx);
772                 return NT_STATUS_NO_MEMORY;
773         }
774         rc = ldb_delete(state->ldb, dn);
775
776         if (rc != LDB_SUCCESS) {
777                 DEBUG(10, ("ldb_delete for %s failed: %s\n", ldb_dn_get_linearized(dn),
778                            ldb_errstring(state->ldb)));
779                 talloc_free(tmp_ctx);
780                 return NT_STATUS_LDAP(rc);
781         }
782         talloc_free(tmp_ctx);
783         return NT_STATUS_OK;
784 }
785
786 /* This interface takes a fully populated struct samu and places it in
787  * the database.  This is not implemented at this time as we need to
788  * be careful around the creation of arbitary SIDs (ie, we must ensrue
789  * they are not left in a RID pool */
790 static NTSTATUS pdb_samba_dsdb_add_sam_account(struct pdb_methods *m,
791                                         struct samu *sampass)
792 {
793         int ret;
794         NTSTATUS status;
795         struct ldb_dn *dn;
796         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
797                 m->private_data, struct pdb_samba_dsdb_state);
798         uint32_t acb_flags = pdb_get_acct_ctrl(sampass);
799         const char *username = pdb_get_username(sampass);
800         const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
801         TALLOC_CTX *tframe = talloc_stackframe();
802
803         acb_flags &= (ACB_NORMAL|ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST);
804
805         ret = ldb_transaction_start(state->ldb);
806         if (ret != LDB_SUCCESS) {
807                 talloc_free(tframe);
808                 return NT_STATUS_LOCK_NOT_GRANTED;
809         }
810
811         status = dsdb_add_user(state->ldb, talloc_tos(), username,
812                                acb_flags, user_sid, NULL, &dn);
813         if (!NT_STATUS_IS_OK(status)) {
814                 ldb_transaction_cancel(state->ldb);
815                 talloc_free(tframe);
816                 return status;
817         }
818
819         ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_set_or_changed,
820                                         dn, sampass);
821         if (ret != LDB_SUCCESS) {
822                 ldb_transaction_cancel(state->ldb);
823                 talloc_free(tframe);
824                 return dsdb_ldb_err_to_ntstatus(ret);
825         }
826
827         ret = ldb_transaction_commit(state->ldb);
828         if (ret != LDB_SUCCESS) {
829                 DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
830                          ldb_dn_get_linearized(dn),
831                          ldb_errstring(state->ldb)));
832                 talloc_free(tframe);
833                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
834         }
835         talloc_free(tframe);
836         return NT_STATUS_OK;
837 }
838
839 /*
840  * Update the Samba_Dsdb LDB with the changes from a struct samu.
841  *
842  * This takes care not to update elements that have not been changed
843  * by the caller
844  */
845 static NTSTATUS pdb_samba_dsdb_update_sam_account(struct pdb_methods *m,
846                                            struct samu *sam)
847 {
848         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
849                 m->private_data, struct pdb_samba_dsdb_state);
850         struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
851                 m, sam);
852         int ret;
853
854         ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_changed, msg->dn,
855                                         sam);
856         return dsdb_ldb_err_to_ntstatus(ret);
857 }
858
859 static NTSTATUS pdb_samba_dsdb_delete_sam_account(struct pdb_methods *m,
860                                            struct samu *username)
861 {
862         NTSTATUS status;
863         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
864         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
865         status = pdb_samba_dsdb_delete_user(m, tmp_ctx, username);
866         talloc_free(tmp_ctx);
867         return status;
868 }
869
870 static NTSTATUS pdb_samba_dsdb_rename_sam_account(struct pdb_methods *m,
871                                            struct samu *oldname,
872                                            const char *newname)
873 {
874         return NT_STATUS_NOT_IMPLEMENTED;
875 }
876
877 /* This is not implemented, as this module is exptected to be used
878  * with auth_samba_dsdb, and this is responible for login counters etc
879  *
880  */
881 static NTSTATUS pdb_samba_dsdb_update_login_attempts(struct pdb_methods *m,
882                                               struct samu *sam_acct,
883                                               bool success)
884 {
885         return NT_STATUS_NOT_IMPLEMENTED;
886 }
887
888 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
889                                     const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
890 {
891         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
892                 m->private_data, struct pdb_samba_dsdb_state);
893         const char *attrs[] = { "objectClass", "objectSid", "description", "samAccountName", "groupType",
894                                 NULL };
895         struct ldb_message *msg;
896         va_list ap;
897         char *expression = NULL;
898         struct dom_sid *sid;
899         const char *str;
900         int rc;
901         struct id_map id_map;
902         struct id_map *id_maps[2];
903         TALLOC_CTX *tmp_ctx = talloc_stackframe();
904         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
905
906         va_start(ap, exp_fmt);
907         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
908         va_end(ap);
909
910         if (!expression) {
911                 talloc_free(tmp_ctx);
912                 return NT_STATUS_NO_MEMORY;
913         }
914
915         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
916         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
917                 talloc_free(tmp_ctx);
918                 return NT_STATUS_NO_SUCH_GROUP;
919         } else if (rc != LDB_SUCCESS) {
920                 talloc_free(tmp_ctx);
921                 DEBUG(10, ("dsdb_search_one failed %s\n",
922                            ldb_errstring(state->ldb)));
923                 return NT_STATUS_LDAP(rc);
924         }
925
926         sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
927         if (!sid) {
928                 talloc_free(tmp_ctx);
929                 DEBUG(10, ("Could not pull SID\n"));
930                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
931         }
932
933         map->sid = *sid;
934
935         if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) {
936                 NTSTATUS status;
937                 uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0);
938                 switch (grouptype) {
939                 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
940                 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
941                         map->sid_name_use = SID_NAME_ALIAS;
942                         break;
943                 case GTYPE_SECURITY_GLOBAL_GROUP:
944                         map->sid_name_use = SID_NAME_DOM_GRP;
945                         break;
946                 default:
947                         talloc_free(tmp_ctx);
948                         DEBUG(10, ("Could not pull groupType\n"));
949                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
950                 }
951
952                 ZERO_STRUCT(id_map);
953                 id_map.sid = sid;
954                 id_maps[0] = &id_map;
955                 id_maps[1] = NULL;
956
957                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
958
959                 if (!NT_STATUS_IS_OK(status)) {
960                         talloc_free(tmp_ctx);
961                         return status;
962                 }
963                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
964                         map->gid = id_map.xid.id;
965                 } else {
966                         DEBUG(1, (__location__ "Did not get GUID when mapping SID for %s", expression));
967                         talloc_free(tmp_ctx);
968                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
969                 }
970         } else if (samdb_find_attribute(state->ldb, msg, "objectClass", "user")) {
971                 DEBUG(1, (__location__ "Got SID_NAME_USER when searching for a group with %s", expression));
972                 talloc_free(tmp_ctx);
973                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
974         }
975
976         str = ldb_msg_find_attr_as_string(msg, "samAccountName",
977                                           NULL);
978         if (str == NULL) {
979                 talloc_free(tmp_ctx);
980                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
981         }
982         map->nt_name = talloc_strdup(map, str);
983         if (!map->nt_name) {
984                 talloc_free(tmp_ctx);
985                 return NT_STATUS_NO_MEMORY;
986         }
987
988         str = ldb_msg_find_attr_as_string(msg, "description",
989                                             NULL);
990         if (str != NULL) {
991                 map->comment = talloc_strdup(map, str);
992         } else {
993                 map->comment = talloc_strdup(map, "");
994         }
995         if (!map->comment) {
996                 talloc_free(tmp_ctx);
997                 return NT_STATUS_NO_MEMORY;
998         }
999
1000         talloc_free(tmp_ctx);
1001         return NT_STATUS_OK;
1002 }
1003
1004 static NTSTATUS pdb_samba_dsdb_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
1005                                  struct dom_sid sid)
1006 {
1007         char *filter;
1008         NTSTATUS status;
1009
1010         filter = talloc_asprintf(talloc_tos(),
1011                                  "(&(objectsid=%s)(objectclass=group))",
1012                                  sid_string_talloc(talloc_tos(), &sid));
1013         if (filter == NULL) {
1014                 return NT_STATUS_NO_MEMORY;
1015         }
1016
1017         status = pdb_samba_dsdb_getgrfilter(m, map, filter);
1018         TALLOC_FREE(filter);
1019         return status;
1020 }
1021
1022 static NTSTATUS pdb_samba_dsdb_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
1023                                  gid_t gid)
1024 {
1025         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1026                 m->private_data, struct pdb_samba_dsdb_state);
1027         NTSTATUS status;
1028         struct id_map id_map;
1029         struct id_map *id_maps[2];
1030         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1031         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1032
1033         id_map.xid.id = gid;
1034         id_map.xid.type = ID_TYPE_GID;
1035         id_maps[0] = &id_map;
1036         id_maps[1] = NULL;
1037
1038         status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
1039         if (!NT_STATUS_IS_OK(status)) {
1040                 talloc_free(tmp_ctx);
1041                 return status;
1042         }
1043         status = pdb_samba_dsdb_getgrsid(m, map, *id_map.sid);
1044         talloc_free(tmp_ctx);
1045         return status;
1046 }
1047
1048 static NTSTATUS pdb_samba_dsdb_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
1049                                  const char *name)
1050 {
1051         char *filter;
1052         NTSTATUS status;
1053
1054         filter = talloc_asprintf(talloc_tos(),
1055                                  "(&(samaccountname=%s)(objectclass=group))",
1056                                  name);
1057         if (filter == NULL) {
1058                 return NT_STATUS_NO_MEMORY;
1059         }
1060
1061         status = pdb_samba_dsdb_getgrfilter(m, map, filter);
1062         TALLOC_FREE(filter);
1063         return status;
1064 }
1065
1066 static NTSTATUS pdb_samba_dsdb_create_dom_group(struct pdb_methods *m,
1067                                          TALLOC_CTX *mem_ctx, const char *name,
1068                                          uint32_t *rid)
1069 {
1070         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1071                 m->private_data, struct pdb_samba_dsdb_state);
1072         NTSTATUS status;
1073         struct dom_sid *sid;
1074         struct ldb_dn *dn;
1075         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1076         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1077
1078         status = dsdb_add_domain_group(state->ldb, tmp_ctx, name, &sid, &dn);
1079         if (!NT_STATUS_IS_OK(status)) {
1080                 talloc_free(tmp_ctx);
1081                 return status;
1082         }
1083
1084         sid_peek_rid(sid, rid);
1085         talloc_free(tmp_ctx);
1086         return NT_STATUS_OK;
1087 }
1088
1089 static NTSTATUS pdb_samba_dsdb_delete_dom_group(struct pdb_methods *m,
1090                                          TALLOC_CTX *mem_ctx, uint32_t rid)
1091 {
1092         const char *attrs[] = { NULL };
1093         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1094                 m->private_data, struct pdb_samba_dsdb_state);
1095         struct dom_sid sid;
1096         struct ldb_message *msg;
1097         struct ldb_dn *dn;
1098         int rc;
1099         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1100         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1101
1102         sid_compose(&sid, samdb_domain_sid(state->ldb), rid);
1103
1104         if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1105                 DEBUG(0, ("Unable to start transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1106                 return NT_STATUS_INTERNAL_ERROR;
1107         }
1108
1109         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, &sid));
1110         if (!dn || !ldb_dn_validate(dn)) {
1111                 talloc_free(tmp_ctx);
1112                 ldb_transaction_cancel(state->ldb);
1113                 return NT_STATUS_NO_MEMORY;
1114         }
1115         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "objectclass=group");
1116         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1117                 talloc_free(tmp_ctx);
1118                 ldb_transaction_cancel(state->ldb);
1119                 return NT_STATUS_NO_SUCH_GROUP;
1120         }
1121         rc = ldb_delete(state->ldb, dn);
1122         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1123                 talloc_free(tmp_ctx);
1124                 ldb_transaction_cancel(state->ldb);
1125                 return NT_STATUS_NO_SUCH_GROUP;
1126         } else if (rc != LDB_SUCCESS) {
1127                 DEBUG(10, ("ldb_delete failed %s\n",
1128                            ldb_errstring(state->ldb)));
1129                 ldb_transaction_cancel(state->ldb);
1130                 return NT_STATUS_LDAP(rc);
1131         }
1132
1133         if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1134                 DEBUG(0, ("Unable to commit transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1135                 return NT_STATUS_INTERNAL_ERROR;
1136         }
1137         return NT_STATUS_OK;
1138 }
1139
1140 static NTSTATUS pdb_samba_dsdb_add_group_mapping_entry(struct pdb_methods *m,
1141                                                 GROUP_MAP *map)
1142 {
1143         return NT_STATUS_NOT_IMPLEMENTED;
1144 }
1145
1146 static NTSTATUS pdb_samba_dsdb_update_group_mapping_entry(struct pdb_methods *m,
1147                                                    GROUP_MAP *map)
1148 {
1149         return NT_STATUS_NOT_IMPLEMENTED;
1150 }
1151
1152 static NTSTATUS pdb_samba_dsdb_delete_group_mapping_entry(struct pdb_methods *m,
1153                                                    struct dom_sid sid)
1154 {
1155         return NT_STATUS_NOT_IMPLEMENTED;
1156 }
1157
1158 static NTSTATUS pdb_samba_dsdb_enum_group_mapping(struct pdb_methods *m,
1159                                            const struct dom_sid *sid,
1160                                            enum lsa_SidType sid_name_use,
1161                                            GROUP_MAP ***pp_rmap,
1162                                            size_t *p_num_entries,
1163                                            bool unix_only)
1164 {
1165         return NT_STATUS_NOT_IMPLEMENTED;
1166 }
1167
1168 static NTSTATUS pdb_samba_dsdb_enum_group_members(struct pdb_methods *m,
1169                                            TALLOC_CTX *mem_ctx,
1170                                            const struct dom_sid *group,
1171                                            uint32_t **pmembers,
1172                                            size_t *pnum_members)
1173 {
1174         unsigned int i, num_sids, num_members;
1175         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1176                 m->private_data, struct pdb_samba_dsdb_state);
1177         struct dom_sid *members_as_sids;
1178         struct dom_sid *dom_sid;
1179         uint32_t *members;
1180         struct ldb_dn *dn;
1181         NTSTATUS status;
1182
1183         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1184         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1185
1186         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, group));
1187         if (!dn || !ldb_dn_validate(dn)) {
1188                 return NT_STATUS_NO_MEMORY;
1189         }
1190
1191         status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
1192         if (!NT_STATUS_IS_OK(status)) {
1193                 talloc_free(tmp_ctx);
1194                 return status;
1195         }
1196         status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
1197         if (!NT_STATUS_IS_OK(status)) {
1198                 talloc_free(tmp_ctx);
1199                 return status;
1200         }
1201
1202         *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
1203         if (*pmembers == NULL) {
1204                 TALLOC_FREE(tmp_ctx);
1205                 return NT_STATUS_NO_MEMORY;
1206         }
1207         num_members = 0;
1208
1209         for (i = 0; i < num_sids; i++) {
1210                 if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
1211                         continue;
1212                 }
1213                 status = dom_sid_split_rid(NULL, &members_as_sids[i],
1214                                            NULL, &members[num_members]);
1215                 if (!NT_STATUS_IS_OK(status)) {
1216                         talloc_free(tmp_ctx);
1217                         return status;
1218                 }
1219                 num_members++;
1220         }
1221         *pnum_members = num_members;
1222         return NT_STATUS_OK;
1223 }
1224
1225 /* Just convert the primary group SID into a group */
1226 static NTSTATUS fake_enum_group_memberships(struct pdb_samba_dsdb_state *state,
1227                                             TALLOC_CTX *mem_ctx,
1228                                             struct samu *user,
1229                                             struct dom_sid **pp_sids,
1230                                             gid_t **pp_gids,
1231                                             uint32_t *p_num_groups)
1232 {
1233         NTSTATUS status;
1234         size_t num_groups = 0;
1235         struct dom_sid *group_sids = NULL;
1236         gid_t *gids = NULL;
1237         TALLOC_CTX *tmp_ctx;
1238
1239         tmp_ctx = talloc_new(mem_ctx);
1240         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1241
1242         if (user->group_sid) {
1243                 struct id_map *id_maps[2];
1244                 struct id_map id_map;
1245
1246                 num_groups = 1;
1247
1248                 group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
1249                 if (group_sids == NULL) {
1250                         talloc_free(tmp_ctx);
1251                         return NT_STATUS_NO_MEMORY;
1252                 }
1253                 gids = talloc_array(tmp_ctx, gid_t, num_groups);
1254                 if (gids == NULL) {
1255                         talloc_free(tmp_ctx);
1256                         return NT_STATUS_NO_MEMORY;
1257                 }
1258
1259                 group_sids[0] = *user->group_sid;
1260
1261                 ZERO_STRUCT(id_map);
1262                 id_map.sid = &group_sids[0];
1263                 id_maps[0] = &id_map;
1264                 id_maps[1] = NULL;
1265
1266                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1267                 if (!NT_STATUS_IS_OK(status)) {
1268                         talloc_free(tmp_ctx);
1269                         return status;
1270                 }
1271                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1272                         gids[0] = id_map.xid.id;
1273                 } else {
1274                         DEBUG(1, (__location__
1275                                   "Group %s, of which %s is a member, could not be converted to a GID\n",
1276                                   dom_sid_string(tmp_ctx, &group_sids[0]),
1277                                   dom_sid_string(tmp_ctx, &user->user_sid)));
1278                         talloc_free(tmp_ctx);
1279                         /* We must error out, otherwise a user might
1280                          * avoid a DENY acl based on a group they
1281                          * missed out on */
1282                         return NT_STATUS_NO_SUCH_GROUP;
1283                 }
1284         }
1285
1286         *pp_sids = talloc_steal(mem_ctx, group_sids);
1287         *pp_gids = talloc_steal(mem_ctx, gids);
1288         *p_num_groups = num_groups;
1289         talloc_free(tmp_ctx);
1290         return NT_STATUS_OK;
1291 }
1292
1293 static NTSTATUS pdb_samba_dsdb_enum_group_memberships(struct pdb_methods *m,
1294                                                TALLOC_CTX *mem_ctx,
1295                                                struct samu *user,
1296                                                struct dom_sid **pp_sids,
1297                                                gid_t **pp_gids,
1298                                                uint32_t *p_num_groups)
1299 {
1300         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1301                 m->private_data, struct pdb_samba_dsdb_state);
1302         struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
1303                 m, user);
1304         const char *attrs[] = { "tokenGroups", NULL};
1305         struct ldb_message *tokengroups_msg;
1306         struct ldb_message_element *tokengroups;
1307         int i, rc;
1308         NTSTATUS status;
1309         unsigned int count = 0;
1310         size_t num_groups;
1311         struct dom_sid *group_sids;
1312         gid_t *gids;
1313         TALLOC_CTX *tmp_ctx;
1314
1315         if (msg == NULL) {
1316                 /* Fake up some things here */
1317                 return fake_enum_group_memberships(state,
1318                                                    mem_ctx,
1319                                                    user, pp_sids,
1320                                                    pp_gids, p_num_groups);
1321         }
1322
1323         tmp_ctx = talloc_new(mem_ctx);
1324         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1325
1326         rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
1327
1328         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1329                 talloc_free(tmp_ctx);
1330                 return NT_STATUS_NO_SUCH_USER;
1331         } else if (rc != LDB_SUCCESS) {
1332                 DEBUG(10, ("dsdb_search_one failed %s\n",
1333                            ldb_errstring(state->ldb)));
1334                 talloc_free(tmp_ctx);
1335                 return NT_STATUS_LDAP(rc);
1336         }
1337
1338         tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
1339
1340         if (tokengroups) {
1341                 count = tokengroups->num_values;
1342         }
1343
1344         group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
1345         if (group_sids == NULL) {
1346                 talloc_free(tmp_ctx);
1347                 return NT_STATUS_NO_MEMORY;
1348         }
1349         gids = talloc_array(tmp_ctx, gid_t, count);
1350         if (gids == NULL) {
1351                 talloc_free(tmp_ctx);
1352                 return NT_STATUS_NO_MEMORY;
1353         }
1354         num_groups = 0;
1355
1356         for (i=0; i<count; i++) {
1357                 struct id_map *id_maps[2];
1358                 struct id_map id_map;
1359                 struct ldb_val *v = &tokengroups->values[i];
1360                 enum ndr_err_code ndr_err
1361                         = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
1362                                                (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1363                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1364                         talloc_free(tmp_ctx);
1365                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1366                 }
1367
1368                 ZERO_STRUCT(id_map);
1369                 id_map.sid = &group_sids[num_groups];
1370                 id_maps[0] = &id_map;
1371                 id_maps[1] = NULL;
1372
1373                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1374                 if (!NT_STATUS_IS_OK(status)) {
1375                         talloc_free(tmp_ctx);
1376                         return status;
1377                 }
1378                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1379                         gids[num_groups] = id_map.xid.id;
1380                 } else {
1381                         DEBUG(1, (__location__
1382                                   "Group %s, of which %s is a member, could not be converted to a GID\n",
1383                                   dom_sid_string(tmp_ctx, &group_sids[num_groups]),
1384                                   ldb_dn_get_linearized(msg->dn)));
1385                         talloc_free(tmp_ctx);
1386                         /* We must error out, otherwise a user might
1387                          * avoid a DENY acl based on a group they
1388                          * missed out on */
1389                         return NT_STATUS_NO_SUCH_GROUP;
1390                 }
1391
1392                 num_groups += 1;
1393                 if (num_groups == count) {
1394                         break;
1395                 }
1396         }
1397
1398         *pp_sids = talloc_steal(mem_ctx, group_sids);
1399         *pp_gids = talloc_steal(mem_ctx, gids);
1400         *p_num_groups = num_groups;
1401         talloc_free(tmp_ctx);
1402         return NT_STATUS_OK;
1403 }
1404
1405 static NTSTATUS pdb_samba_dsdb_set_unix_primary_group(struct pdb_methods *m,
1406                                                TALLOC_CTX *mem_ctx,
1407                                                struct samu *user)
1408 {
1409         return NT_STATUS_NOT_IMPLEMENTED;
1410 }
1411
1412 static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid(struct pdb_methods *m,
1413                                                TALLOC_CTX *mem_ctx,
1414                                                const struct dom_sid *groupsid,
1415                                                const struct dom_sid *membersid,
1416                                                int mod_op)
1417 {
1418         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1419                 m->private_data, struct pdb_samba_dsdb_state);
1420         struct ldb_message *msg;
1421         int ret;
1422         struct ldb_message_element *el;
1423         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1424         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1425         msg = ldb_msg_new(tmp_ctx);
1426         if (msg == NULL) {
1427                 TALLOC_FREE(tmp_ctx);
1428                 return NT_STATUS_NO_MEMORY;
1429         }
1430
1431         msg->dn = ldb_dn_new_fmt(msg, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, groupsid));
1432         if (!msg->dn || !ldb_dn_validate(msg->dn)) {
1433                 talloc_free(tmp_ctx);
1434                 return NT_STATUS_NO_MEMORY;
1435         }
1436         ret = ldb_msg_add_fmt(msg, "member", "<SID=%s>", dom_sid_string(tmp_ctx, membersid));
1437         if (ret != LDB_SUCCESS) {
1438                 talloc_free(tmp_ctx);
1439                 return NT_STATUS_NO_MEMORY;
1440         }
1441         el = ldb_msg_find_element(msg, "member");
1442         el->flags = mod_op;
1443
1444         /* No need for transactions here, the ldb auto-transaction
1445          * code will handle things for the single operation */
1446         ret = ldb_modify(state->ldb, msg);
1447         talloc_free(tmp_ctx);
1448         if (ret != LDB_SUCCESS) {
1449                 DEBUG(10, ("ldb_modify failed: %s\n",
1450                            ldb_errstring(state->ldb)));
1451                 if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
1452                         return NT_STATUS_MEMBER_IN_GROUP;
1453                 }
1454                 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1455                         return NT_STATUS_MEMBER_NOT_IN_GROUP;
1456                 }
1457                 return NT_STATUS_LDAP(ret);
1458         }
1459
1460         return NT_STATUS_OK;
1461 }
1462
1463 static NTSTATUS pdb_samba_dsdb_mod_groupmem(struct pdb_methods *m,
1464                                      TALLOC_CTX *mem_ctx,
1465                                      uint32_t grouprid, uint32_t memberrid,
1466                                      int mod_op)
1467 {
1468         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1469                 m->private_data, struct pdb_samba_dsdb_state);
1470         const struct dom_sid *dom_sid, *groupsid, *membersid;
1471         NTSTATUS status;
1472         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1473         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1474
1475         dom_sid = samdb_domain_sid(state->ldb);
1476
1477         groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
1478         if (groupsid == NULL) {
1479                 TALLOC_FREE(tmp_ctx);
1480                 return NT_STATUS_NO_MEMORY;
1481         }
1482         membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
1483         if (membersid == NULL) {
1484                 TALLOC_FREE(tmp_ctx);
1485                 return NT_STATUS_NO_MEMORY;
1486         }
1487         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
1488         talloc_free(tmp_ctx);
1489         return status;
1490 }
1491
1492 static NTSTATUS pdb_samba_dsdb_add_groupmem(struct pdb_methods *m,
1493                                      TALLOC_CTX *mem_ctx,
1494                                      uint32_t group_rid, uint32_t member_rid)
1495 {
1496         return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1497                                     LDB_FLAG_MOD_ADD);
1498 }
1499
1500 static NTSTATUS pdb_samba_dsdb_del_groupmem(struct pdb_methods *m,
1501                                      TALLOC_CTX *mem_ctx,
1502                                      uint32_t group_rid, uint32_t member_rid)
1503 {
1504         return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1505                                        LDB_FLAG_MOD_DELETE);
1506 }
1507
1508 static NTSTATUS pdb_samba_dsdb_create_alias(struct pdb_methods *m,
1509                                      const char *name, uint32_t *rid)
1510 {
1511         TALLOC_CTX *frame = talloc_stackframe();
1512         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1513                 m->private_data, struct pdb_samba_dsdb_state);
1514         struct dom_sid *sid;
1515
1516         struct ldb_dn *dn;
1517         NTSTATUS status;
1518
1519         /* Internally this uses transactions to ensure all the steps
1520          * happen or fail as one */
1521         status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
1522         if (!NT_STATUS_IS_OK(status)) {
1523                 TALLOC_FREE(frame);
1524         }
1525
1526         sid_peek_rid(sid, rid);
1527         TALLOC_FREE(frame);
1528         return NT_STATUS_OK;
1529 }
1530
1531 static NTSTATUS pdb_samba_dsdb_delete_alias(struct pdb_methods *m,
1532                                      const struct dom_sid *sid)
1533 {
1534         const char *attrs[] = { NULL };
1535         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1536                 m->private_data, struct pdb_samba_dsdb_state);
1537         struct ldb_message *msg;
1538         struct ldb_dn *dn;
1539         int rc;
1540         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1541         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1542
1543         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, sid));
1544         if (!dn || !ldb_dn_validate(dn)) {
1545                 talloc_free(tmp_ctx);
1546                 return NT_STATUS_NO_MEMORY;
1547         }
1548
1549         if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1550                 DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(state->ldb)));
1551                 talloc_free(tmp_ctx);
1552                 return NT_STATUS_INTERNAL_ERROR;
1553         }
1554
1555         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
1556                              "(|(grouptype=%d)(grouptype=%d)))",
1557                              GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1558                              GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1559         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1560                 talloc_free(tmp_ctx);
1561                 ldb_transaction_cancel(state->ldb);
1562                 return NT_STATUS_NO_SUCH_ALIAS;
1563         }
1564         rc = ldb_delete(state->ldb, dn);
1565         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1566                 talloc_free(tmp_ctx);
1567                 ldb_transaction_cancel(state->ldb);
1568                 return NT_STATUS_NO_SUCH_ALIAS;
1569         } else if (rc != LDB_SUCCESS) {
1570                 DEBUG(10, ("ldb_delete failed %s\n",
1571                            ldb_errstring(state->ldb)));
1572                 ldb_transaction_cancel(state->ldb);
1573                 talloc_free(tmp_ctx);
1574                 return NT_STATUS_LDAP(rc);
1575         }
1576
1577         if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1578                 DEBUG(0, ("Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s\n",
1579                           ldb_errstring(state->ldb)));
1580                 talloc_free(tmp_ctx);
1581                 return NT_STATUS_INTERNAL_ERROR;
1582         }
1583
1584         talloc_free(tmp_ctx);
1585         return NT_STATUS_OK;
1586 }
1587
1588 #if 0
1589 static NTSTATUS pdb_samba_dsdb_set_aliasinfo(struct pdb_methods *m,
1590                                       const struct dom_sid *sid,
1591                                       struct acct_info *info)
1592 {
1593         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1594                 m->private_data, struct pdb_samba_dsdb_state);
1595         struct tldap_context *ld;
1596         const char *attrs[3] = { "objectSid", "description",
1597                                  "samAccountName" };
1598         struct ldb_message **msg;
1599         char *sidstr, *dn;
1600         int rc;
1601         struct tldap_mod *mods;
1602         int num_mods;
1603         bool ok;
1604
1605         ld = pdb_samba_dsdb_ld(state);
1606         if (ld == NULL) {
1607                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1608         }
1609
1610         sidstr = sid_binstring(talloc_tos(), sid);
1611         NT_STATUS_HAVE_NO_MEMORY(sidstr);
1612
1613         rc = pdb_samba_dsdb_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1614                                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1615                                 &msg, "(&(objectSid=%s)(objectclass=group)"
1616                                 "(|(grouptype=%d)(grouptype=%d)))",
1617                                 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1618                                 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1619         TALLOC_FREE(sidstr)
1620         if (rc != LDB_SUCCESS) {
1621                 DEBUG(10, ("ldap_search failed %s\n",
1622                            ldb_errstring(state->ldb)));
1623                 return NT_STATUS_LDAP(rc);
1624         }
1625         switch talloc_array_length(msg) {
1626         case 0:
1627                 return NT_STATUS_NO_SUCH_ALIAS;
1628         case 1:
1629                 break;
1630         default:
1631                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1632         }
1633
1634         if (!tldap_entry_dn(msg[0], &dn)) {
1635                 TALLOC_FREE(msg);
1636                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1637         }
1638
1639         mods = NULL;
1640         num_mods = 0;
1641         ok = true;
1642
1643         ok &= tldap_make_mod_fmt(
1644                 msg[0], msg, &num_mods, &mods, "description",
1645                 "%s", info->acct_desc);
1646         ok &= tldap_make_mod_fmt(
1647                 msg[0], msg, &num_mods, &mods, "samAccountName",
1648                 "%s", info->acct_name);
1649         if (!ok) {
1650                 TALLOC_FREE(msg);
1651                 return NT_STATUS_NO_MEMORY;
1652         }
1653         if (num_mods == 0) {
1654                 /* no change */
1655                 TALLOC_FREE(msg);
1656                 return NT_STATUS_OK;
1657         }
1658
1659         rc = tldap_modify(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
1660         TALLOC_FREE(msg);
1661         if (rc != LDB_SUCCESS) {
1662                 DEBUG(10, ("ldap_modify failed: %s\n",
1663                            ldb_errstring(state->ldb)));
1664                 return NT_STATUS_LDAP(rc);
1665         }
1666         return NT_STATUS_OK;
1667 }
1668 #endif
1669 static NTSTATUS pdb_samba_dsdb_add_aliasmem(struct pdb_methods *m,
1670                                      const struct dom_sid *alias,
1671                                      const struct dom_sid *member)
1672 {
1673         NTSTATUS status;
1674         TALLOC_CTX *frame = talloc_stackframe();
1675         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_ADD);
1676         talloc_free(frame);
1677         return status;
1678 }
1679
1680 static NTSTATUS pdb_samba_dsdb_del_aliasmem(struct pdb_methods *m,
1681                                      const struct dom_sid *alias,
1682                                      const struct dom_sid *member)
1683 {
1684         NTSTATUS status;
1685         TALLOC_CTX *frame = talloc_stackframe();
1686         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
1687         talloc_free(frame);
1688         return status;
1689 }
1690
1691 static NTSTATUS pdb_samba_dsdb_enum_aliasmem(struct pdb_methods *m,
1692                                       const struct dom_sid *alias,
1693                                       TALLOC_CTX *mem_ctx,
1694                                       struct dom_sid **pmembers,
1695                                       size_t *pnum_members)
1696 {
1697         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1698                 m->private_data, struct pdb_samba_dsdb_state);
1699         struct ldb_dn *dn;
1700         unsigned int num_members;
1701         NTSTATUS status;
1702         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1703         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1704
1705         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, alias));
1706         if (!dn || !ldb_dn_validate(dn)) {
1707                 return NT_STATUS_NO_MEMORY;
1708         }
1709
1710         status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
1711         *pnum_members = num_members;
1712         if (NT_STATUS_IS_OK(status)) {
1713                 talloc_steal(mem_ctx, pmembers);
1714         }
1715         talloc_free(tmp_ctx);
1716         return status;
1717 }
1718
1719 static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1720                                                TALLOC_CTX *mem_ctx,
1721                                                const struct dom_sid *domain_sid,
1722                                                const struct dom_sid *members,
1723                                                size_t num_members,
1724                                                uint32_t **palias_rids,
1725                                                size_t *pnum_alias_rids)
1726 {
1727         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1728                 m->private_data, struct pdb_samba_dsdb_state);
1729         uint32_t *alias_rids = NULL;
1730         size_t num_alias_rids = 0;
1731         int i;
1732         struct dom_sid *groupSIDs = NULL;
1733         unsigned int num_groupSIDs = 0;
1734         char *filter;
1735         NTSTATUS status;
1736         const char *sid_string;
1737         const char *sid_dn;
1738         DATA_BLOB sid_blob;
1739
1740         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1741         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1742         /*
1743          * TODO: Get the filter right so that we only get the aliases from
1744          * either the SAM or BUILTIN
1745          */
1746
1747         filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
1748                                  GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1749         if (filter == NULL) {
1750                 return NT_STATUS_NO_MEMORY;
1751         }
1752
1753         for (i = 0; i < num_members; i++) {
1754                 sid_string = dom_sid_string(tmp_ctx, &members[i]);
1755                 if (sid_string == NULL) {
1756                         TALLOC_FREE(tmp_ctx);
1757                         return NT_STATUS_NO_MEMORY;
1758                 }
1759
1760                 sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", sid_string);
1761                 if (sid_dn == NULL) {
1762                         TALLOC_FREE(tmp_ctx);
1763                         return NT_STATUS_NO_MEMORY;
1764                 }
1765
1766                 sid_blob = data_blob_string_const(sid_dn);
1767
1768                 status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1769                                                    tmp_ctx, &groupSIDs, &num_groupSIDs);
1770                 if (!NT_STATUS_IS_OK(status)) {
1771                         talloc_free(tmp_ctx);
1772                         return status;
1773                 }
1774         }
1775
1776         alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1777         if (alias_rids == NULL) {
1778                 talloc_free(tmp_ctx);
1779                 return NT_STATUS_NO_MEMORY;
1780         }
1781
1782         for (i=0; i<num_groupSIDs; i++) {
1783                 if (sid_peek_check_rid(domain_sid, &groupSIDs[i],
1784                                        &alias_rids[num_alias_rids])) {
1785                         num_alias_rids++;;
1786                 }
1787         }
1788
1789         *palias_rids = alias_rids;
1790         *pnum_alias_rids = num_alias_rids;
1791         return NT_STATUS_OK;
1792 }
1793
1794 static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1795                                     const struct dom_sid *domain_sid,
1796                                     int num_rids,
1797                                     uint32_t *rids,
1798                                     const char **names,
1799                                     enum lsa_SidType *lsa_attrs)
1800 {
1801         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1802                 m->private_data, struct pdb_samba_dsdb_state);
1803         NTSTATUS status;
1804
1805         TALLOC_CTX *tmp_ctx;
1806
1807         if (num_rids == 0) {
1808                 return NT_STATUS_NONE_MAPPED;
1809         }
1810
1811         tmp_ctx = talloc_stackframe();
1812         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1813
1814         status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1815         talloc_free(tmp_ctx);
1816         return status;
1817 }
1818
1819 static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1820                                      const struct dom_sid *domain_sid,
1821                                      int num_names,
1822                                      const char **pp_names,
1823                                      uint32_t *rids,
1824                                      enum lsa_SidType *attrs)
1825 {
1826         return NT_STATUS_NOT_IMPLEMENTED;
1827 }
1828
1829 static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1830                                            enum pdb_policy_type type,
1831                                            uint32_t *value)
1832 {
1833         return account_policy_get(type, value)
1834                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1835 }
1836
1837 static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1838                                            enum pdb_policy_type type,
1839                                            uint32_t value)
1840 {
1841         return account_policy_set(type, value)
1842                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1843 }
1844
1845 static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1846                                     time_t *seq_num_out)
1847 {
1848         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1849                 m->private_data, struct pdb_samba_dsdb_state);
1850         uint64_t seq_num;
1851         int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1852         if (ret == LDB_SUCCESS) {
1853                 *seq_num_out = seq_num;
1854                 return NT_STATUS_OK;
1855         } else {
1856                 return NT_STATUS_UNSUCCESSFUL;
1857         }
1858 }
1859
1860 struct pdb_samba_dsdb_search_state {
1861         uint32_t acct_flags;
1862         struct samr_displayentry *entries;
1863         uint32_t num_entries;
1864         ssize_t array_size;
1865         uint32_t current;
1866 };
1867
1868 static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1869                                struct samr_displayentry *entry)
1870 {
1871         struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1872                 search->private_data, struct pdb_samba_dsdb_search_state);
1873
1874         if (state->current == state->num_entries) {
1875                 return false;
1876         }
1877
1878         entry->idx = state->entries[state->current].idx;
1879         entry->rid = state->entries[state->current].rid;
1880         entry->acct_flags = state->entries[state->current].acct_flags;
1881
1882         entry->account_name = talloc_strdup(
1883                 search, state->entries[state->current].account_name);
1884         entry->fullname = talloc_strdup(
1885                 search, state->entries[state->current].fullname);
1886         entry->description = talloc_strdup(
1887                 search, state->entries[state->current].description);
1888
1889         state->current += 1;
1890         return true;
1891 }
1892
1893 static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1894 {
1895         struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1896                 search->private_data, struct pdb_samba_dsdb_search_state);
1897         talloc_free(state);
1898 }
1899
1900 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1901                                      struct pdb_search *search,
1902                                      struct pdb_samba_dsdb_search_state **pstate,
1903                                      const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
1904 {
1905         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1906                 m->private_data, struct pdb_samba_dsdb_state);
1907         struct pdb_samba_dsdb_search_state *sstate;
1908         const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1909                                  "userAccountControl", "description", NULL };
1910         struct ldb_result *res;
1911         int i, rc, num_users;
1912
1913         va_list ap;
1914         char *expression = NULL;
1915
1916         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1917         if (!tmp_ctx) {
1918                 return false;
1919         }
1920
1921         va_start(ap, exp_fmt);
1922         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1923         va_end(ap);
1924
1925         if (!expression) {
1926                 talloc_free(tmp_ctx);
1927                 return LDB_ERR_OPERATIONS_ERROR;
1928         }
1929
1930         sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1931         if (sstate == NULL) {
1932                 talloc_free(tmp_ctx);
1933                 return false;
1934         }
1935
1936         rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1937         if (rc != LDB_SUCCESS) {
1938                 talloc_free(tmp_ctx);
1939                 DEBUG(10, ("dsdb_search failed: %s\n",
1940                            ldb_errstring(state->ldb)));
1941                 return false;
1942         }
1943
1944         num_users = res->count;
1945
1946         sstate->entries = talloc_array(sstate, struct samr_displayentry,
1947                                        num_users);
1948         if (sstate->entries == NULL) {
1949                 talloc_free(tmp_ctx);
1950                 DEBUG(10, ("talloc failed\n"));
1951                 return false;
1952         }
1953
1954         sstate->num_entries = 0;
1955
1956         for (i=0; i<num_users; i++) {
1957                 struct samr_displayentry *e;
1958                 struct dom_sid *sid;
1959
1960                 e = &sstate->entries[sstate->num_entries];
1961
1962                 e->idx = sstate->num_entries;
1963                 sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
1964                 if (!sid) {
1965                         talloc_free(tmp_ctx);
1966                         DEBUG(10, ("Could not pull SID\n"));
1967                         return false;
1968                 }
1969                 sid_peek_rid(sid, &e->rid);
1970
1971                 e->acct_flags = samdb_result_acct_flags(res->msgs[i], "userAccountControl");
1972                 e->account_name = ldb_msg_find_attr_as_string(
1973                         res->msgs[i], "samAccountName", NULL);
1974                 if (e->account_name == NULL) {
1975                         talloc_free(tmp_ctx);
1976                         return false;
1977                 }
1978                 e->fullname = ldb_msg_find_attr_as_string(
1979                         res->msgs[i], "displayName", "");
1980                 e->description = ldb_msg_find_attr_as_string(
1981                         res->msgs[i], "description", "");
1982
1983                 sstate->num_entries += 1;
1984                 if (sstate->num_entries >= num_users) {
1985                         break;
1986                 }
1987         }
1988         talloc_steal(sstate->entries, res->msgs);
1989         search->private_data = talloc_steal(search, sstate);
1990         search->next_entry = pdb_samba_dsdb_next_entry;
1991         search->search_end = pdb_samba_dsdb_search_end;
1992         *pstate = sstate;
1993         talloc_free(tmp_ctx);
1994         return true;
1995 }
1996
1997 static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
1998                                  struct pdb_search *search,
1999                                  uint32_t acct_flags)
2000 {
2001         struct pdb_samba_dsdb_search_state *sstate;
2002         bool ret;
2003
2004         ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
2005         if (!ret) {
2006                 return false;
2007         }
2008         sstate->acct_flags = acct_flags;
2009         return true;
2010 }
2011
2012 static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
2013                                   struct pdb_search *search)
2014 {
2015         struct pdb_samba_dsdb_search_state *sstate;
2016         bool ret;
2017
2018         ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2019                                        "(&(grouptype=%d)(objectclass=group))",
2020                                        GTYPE_SECURITY_GLOBAL_GROUP);
2021         if (!ret) {
2022                 return false;
2023         }
2024         sstate->acct_flags = 0;
2025         return true;
2026 }
2027
2028 static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
2029                                    struct pdb_search *search,
2030                                    const struct dom_sid *sid)
2031 {
2032         struct pdb_samba_dsdb_search_state *sstate;
2033         bool ret;
2034
2035         ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2036                                        "(&(grouptype=%d)(objectclass=group))",
2037                                        sid_check_is_builtin(sid)
2038                                        ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2039                                        : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2040         if (!ret) {
2041                 return false;
2042         }
2043         sstate->acct_flags = 0;
2044         return true;
2045 }
2046
2047 /* 
2048  * Instead of taking a gid or uid, this function takes a pointer to a 
2049  * unixid. 
2050  *
2051  * This acts as an in-out variable so that the idmap functions can correctly
2052  * receive ID_TYPE_BOTH, and this function ensures cache details are filled
2053  * correctly rather than forcing the cache to store ID_TYPE_UID or ID_TYPE_GID. 
2054  */
2055 static bool pdb_samba_dsdb_id_to_sid(struct pdb_methods *m, struct unixid *id,
2056                                      struct dom_sid *sid)
2057 {
2058         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2059                 m->private_data, struct pdb_samba_dsdb_state);
2060         NTSTATUS status;
2061         struct id_map id_map;
2062         struct id_map *id_maps[2];
2063         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2064         if (!tmp_ctx) {
2065                 return false;
2066         }
2067
2068         id_map.xid = *id;
2069         id_maps[0] = &id_map;
2070         id_maps[1] = NULL;
2071
2072         status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2073         if (!NT_STATUS_IS_OK(status)) {
2074                 talloc_free(tmp_ctx);
2075                 return false;
2076         }
2077
2078         if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2079                 id->type = id_map.xid.type;
2080         }
2081         *sid = *id_map.sid;
2082         talloc_free(tmp_ctx);
2083         return true;
2084 }
2085
2086 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2087                                  struct unixid *id)
2088 {
2089         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2090                 m->private_data, struct pdb_samba_dsdb_state);
2091         struct id_map id_map;
2092         struct id_map *id_maps[2];
2093         NTSTATUS status;
2094         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2095         if (!tmp_ctx) {
2096                 return false;
2097         }
2098
2099         ZERO_STRUCT(id_map);
2100         id_map.sid = discard_const_p(struct dom_sid, sid);
2101         id_maps[0] = &id_map;
2102         id_maps[1] = NULL;
2103
2104         status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2105         talloc_free(tmp_ctx);
2106         if (!NT_STATUS_IS_OK(status)) {
2107                 return false;
2108         }
2109         if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2110                 *id = id_map.xid;
2111                 return true;
2112         }
2113         return false;
2114 }
2115
2116 static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2117 {
2118         return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
2119 }
2120
2121 static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32_t *rid)
2122 {
2123         return false;
2124 }
2125
2126 static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2127                                       const char *domain, char** pwd,
2128                                       struct dom_sid *sid,
2129                                       time_t *pass_last_set_time)
2130 {
2131         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2132                 m->private_data, struct pdb_samba_dsdb_state);
2133         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2134         const char * const attrs[] = {
2135                 "securityIdentifier",
2136                 "flatName",
2137                 "trustPartner",
2138                 "trustAuthOutgoing",
2139                 "whenCreated",
2140                 "msDS-SupportedEncryptionTypes",
2141                 "trustAttributes",
2142                 "trustDirection",
2143                 "trustType",
2144                 NULL
2145         };
2146         struct ldb_message *msg;
2147         const struct ldb_val *password_val;
2148         int trust_direction_flags;
2149         int trust_type;
2150         int i;
2151         DATA_BLOB password_utf16;
2152         struct trustAuthInOutBlob password_blob;
2153         struct AuthenticationInformationArray *auth_array;
2154         char *password_talloc;
2155         size_t password_len;
2156         enum ndr_err_code ndr_err;
2157         NTSTATUS status;
2158         const char *netbios_domain = NULL;
2159         const struct dom_sid *domain_sid = NULL;
2160
2161         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2162                                        attrs, tmp_ctx, &msg);
2163         if (!NT_STATUS_IS_OK(status)) {
2164                 /*
2165                  * This can be called to work out of a domain is
2166                  * trusted, rather than just to get the password
2167                  */
2168                 DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
2169                           "It may not be a trusted domain.\n", domain,
2170                           nt_errstr(status)));
2171                 TALLOC_FREE(tmp_ctx);
2172                 return false;
2173         }
2174
2175         netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2176         if (netbios_domain == NULL) {
2177                 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2178                           domain));
2179                 TALLOC_FREE(tmp_ctx);
2180                 return false;
2181         }
2182
2183         domain_sid = samdb_result_dom_sid(tmp_ctx, msg, "securityIdentifier");
2184         if (domain_sid == NULL) {
2185                 DEBUG(2, ("Trusted domain %s has no securityIdentifier defined.\n",
2186                           domain));
2187                 TALLOC_FREE(tmp_ctx);
2188                 return false;
2189         }
2190
2191         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2192         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2193                 DEBUG(2, ("Trusted domain %s is is not an outbound trust.\n",
2194                           domain));
2195                 TALLOC_FREE(tmp_ctx);
2196                 return false;
2197         }
2198
2199         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2200         if (trust_type == LSA_TRUST_TYPE_MIT) {
2201                 DEBUG(1, ("Trusted domain %s is is not an AD trust "
2202                           "(trustType == LSA_TRUST_TYPE_MIT).\n",
2203                           domain));
2204                 TALLOC_FREE(tmp_ctx);
2205                 return false;
2206         }
2207
2208         password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2209         if (password_val == NULL) {
2210                 DEBUG(2, ("Failed to get trusted domain password for %s, "
2211                           "attribute trustAuthOutgoing not returned.\n", domain));
2212                 TALLOC_FREE(tmp_ctx);
2213                 return false;
2214         }
2215
2216         ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2217                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2218         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2219                 DEBUG(0, ("Failed to get trusted domain password for %s, "
2220                           "attribute trustAuthOutgoing coult not be parsed %s.\n",
2221                           domain,
2222                           ndr_map_error2string(ndr_err)));
2223                 TALLOC_FREE(tmp_ctx);
2224                 return false;
2225         }
2226
2227         auth_array = &password_blob.current;
2228
2229         for (i=0; i < auth_array->count; i++) {
2230                 if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
2231                         break;
2232                 }
2233         }
2234
2235         if (i == auth_array->count) {
2236                 DEBUG(0, ("Trusted domain %s does not have a "
2237                           "clear-text password stored\n",
2238                           domain));
2239                 TALLOC_FREE(tmp_ctx);
2240                 return false;
2241         }
2242
2243         password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
2244                                          auth_array->array[i].AuthInfo.clear.size);
2245
2246         /*
2247          * In the future, make this function return a
2248          * cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash()
2249          * but for now convert to UTF8 and fail if the string can not be converted.
2250          *
2251          * We can't safely convert the random strings windows uses into
2252          * utf8.
2253          */
2254         if (!convert_string_talloc(tmp_ctx,
2255                                    CH_UTF16MUNGED, CH_UTF8,
2256                                    password_utf16.data, password_utf16.length,
2257                                    (void *)&password_talloc,
2258                                    &password_len)) {
2259                 DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
2260                           " to UTF8. This may be a password set from Windows.\n",
2261                           domain));
2262                 TALLOC_FREE(tmp_ctx);
2263                 return false;
2264         }
2265         *pwd = SMB_STRNDUP(password_talloc, password_len);
2266         if (pass_last_set_time) {
2267                 *pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
2268         }
2269
2270         if (sid != NULL) {
2271                 sid_copy(sid, domain_sid);
2272         }
2273
2274         TALLOC_FREE(tmp_ctx);
2275         return true;
2276 }
2277
2278 static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
2279                                                     const char *domain,
2280                                                     TALLOC_CTX *mem_ctx,
2281                                                     struct cli_credentials **_creds)
2282 {
2283         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2284                 m->private_data, struct pdb_samba_dsdb_state);
2285         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2286         const char * const attrs[] = {
2287                 "securityIdentifier",
2288                 "flatName",
2289                 "trustPartner",
2290                 "trustAuthOutgoing",
2291                 "whenCreated",
2292                 "msDS-SupportedEncryptionTypes",
2293                 "trustAttributes",
2294                 "trustDirection",
2295                 "trustType",
2296                 NULL
2297         };
2298         struct ldb_message *msg;
2299         const struct ldb_val *password_val;
2300         int trust_direction_flags;
2301         int trust_type;
2302         int i;
2303         DATA_BLOB password_utf16 = {};
2304         struct samr_Password *password_nt = NULL;
2305         uint32_t password_version = 0;
2306         DATA_BLOB old_password_utf16 = {};
2307         struct samr_Password *old_password_nt = NULL;
2308         struct trustAuthInOutBlob password_blob;
2309         enum ndr_err_code ndr_err;
2310         NTSTATUS status;
2311         time_t last_set_time = 0;
2312         struct cli_credentials *creds = NULL;
2313         bool ok;
2314         const char *my_netbios_name = NULL;
2315         const char *my_netbios_domain = NULL;
2316         const char *my_dns_domain = NULL;
2317         const char *netbios_domain = NULL;
2318         char *account_name = NULL;
2319         char *principal_name = NULL;
2320         const char *dns_domain = NULL;
2321
2322         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2323                                        attrs, tmp_ctx, &msg);
2324         if (!NT_STATUS_IS_OK(status)) {
2325                 /*
2326                  * This can be called to work out of a domain is
2327                  * trusted, rather than just to get the password
2328                  */
2329                 DEBUG(2, ("Failed to get trusted domain password for %s - %s "
2330                           "It may not be a trusted domain.\n", domain,
2331                           nt_errstr(status)));
2332                 TALLOC_FREE(tmp_ctx);
2333                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2334         }
2335
2336         netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2337         if (netbios_domain == NULL) {
2338                 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2339                           domain));
2340                 TALLOC_FREE(tmp_ctx);
2341                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2342         }
2343
2344         dns_domain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2345
2346         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2347         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2348                 DEBUG(2, ("Trusted domain %s is is not an outbound trust.\n",
2349                           domain));
2350                 TALLOC_FREE(tmp_ctx);
2351                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2352         }
2353
2354         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2355         if (trust_type == LSA_TRUST_TYPE_MIT) {
2356                 DEBUG(1, ("Trusted domain %s is is not an AD trust "
2357                           "(trustType == LSA_TRUST_TYPE_MIT).\n",
2358                           domain));
2359                 TALLOC_FREE(tmp_ctx);
2360                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2361         }
2362
2363         password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2364         if (password_val == NULL) {
2365                 DEBUG(2, ("Failed to get trusted domain password for %s, "
2366                           "attribute trustAuthOutgoing not returned.\n", domain));
2367                 TALLOC_FREE(tmp_ctx);
2368                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2369         }
2370
2371         ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2372                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2373         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2374                 DEBUG(0, ("Failed to get trusted domain password for %s, "
2375                           "attribute trustAuthOutgoing coult not be parsed %s.\n",
2376                           domain,
2377                           ndr_map_error2string(ndr_err)));
2378                 TALLOC_FREE(tmp_ctx);
2379                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2380         }
2381
2382         for (i=0; i < password_blob.current.count; i++) {
2383                 struct AuthenticationInformation *a =
2384                         &password_blob.current.array[i];
2385
2386                 switch (a->AuthType) {
2387                 case TRUST_AUTH_TYPE_NONE:
2388                         break;
2389
2390                 case TRUST_AUTH_TYPE_VERSION:
2391                         password_version = a->AuthInfo.version.version;
2392                         break;
2393
2394                 case TRUST_AUTH_TYPE_CLEAR:
2395                         last_set_time = nt_time_to_unix(a->LastUpdateTime);
2396
2397                         password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2398                                                          a->AuthInfo.clear.size);
2399                         password_nt = NULL;
2400                         break;
2401
2402                 case TRUST_AUTH_TYPE_NT4OWF:
2403                         if (password_utf16.length != 0) {
2404                                 break;
2405                         }
2406
2407                         last_set_time = nt_time_to_unix(a->LastUpdateTime);
2408
2409                         password_nt = &a->AuthInfo.nt4owf.password;
2410                         break;
2411                 }
2412         }
2413
2414         for (i=0; i < password_blob.previous.count; i++) {
2415                 struct AuthenticationInformation *a = &password_blob.previous.array[i];
2416
2417                 switch (a->AuthType) {
2418                 case TRUST_AUTH_TYPE_NONE:
2419                         break;
2420
2421                 case TRUST_AUTH_TYPE_VERSION:
2422                         break;
2423
2424                 case TRUST_AUTH_TYPE_CLEAR:
2425                         old_password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2426                                                          a->AuthInfo.clear.size);
2427                         old_password_nt = NULL;
2428                         break;
2429
2430                 case TRUST_AUTH_TYPE_NT4OWF:
2431                         if (old_password_utf16.length != 0) {
2432                                 break;
2433                         }
2434
2435                         old_password_nt = &a->AuthInfo.nt4owf.password;
2436                         break;
2437                 }
2438         }
2439
2440         if (password_utf16.length == 0 && password_nt == NULL) {
2441                 DEBUG(0, ("Trusted domain %s does not have a "
2442                           "clear-text nor nt password stored\n",
2443                           domain));
2444                 TALLOC_FREE(tmp_ctx);
2445                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2446         }
2447
2448         my_netbios_name = lpcfg_netbios_name(state->lp_ctx);
2449         my_netbios_domain = lpcfg_workgroup(state->lp_ctx);
2450         my_dns_domain = lpcfg_dnsdomain(state->lp_ctx);
2451
2452         creds = cli_credentials_init(tmp_ctx);
2453         if (creds == NULL) {
2454                 TALLOC_FREE(tmp_ctx);
2455                 return NT_STATUS_NO_MEMORY;
2456         }
2457
2458         ok = cli_credentials_set_workstation(creds, my_netbios_name, CRED_SPECIFIED);
2459         if (!ok) {
2460                 TALLOC_FREE(tmp_ctx);
2461                 return NT_STATUS_NO_MEMORY;
2462         }
2463
2464         ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2465         if (!ok) {
2466                 TALLOC_FREE(tmp_ctx);
2467                 return NT_STATUS_NO_MEMORY;
2468         }
2469         ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2470         if (!ok) {
2471                 TALLOC_FREE(tmp_ctx);
2472                 return NT_STATUS_NO_MEMORY;
2473         }
2474
2475         if (my_dns_domain != NULL && dns_domain != NULL) {
2476                 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DNS_DOMAIN);
2477                 account_name = talloc_asprintf(tmp_ctx, "%s.", my_dns_domain);
2478                 if (account_name == NULL) {
2479                         TALLOC_FREE(tmp_ctx);
2480                         return NT_STATUS_NO_MEMORY;
2481                 }
2482                 principal_name = talloc_asprintf(tmp_ctx, "%s$@%s", my_netbios_domain,
2483                                                  cli_credentials_get_realm(creds));
2484                 if (principal_name == NULL) {
2485                         TALLOC_FREE(tmp_ctx);
2486                         return NT_STATUS_NO_MEMORY;
2487                 }
2488         } else {
2489                 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DOMAIN);
2490                 account_name = talloc_asprintf(tmp_ctx, "%s$", my_netbios_domain);
2491                 if (account_name == NULL) {
2492                         TALLOC_FREE(tmp_ctx);
2493                         return NT_STATUS_NO_MEMORY;
2494                 }
2495                 principal_name = NULL;
2496         }
2497
2498         ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2499         if (!ok) {
2500                 TALLOC_FREE(tmp_ctx);
2501                 return NT_STATUS_NO_MEMORY;
2502         }
2503
2504         if (principal_name != NULL) {
2505                 ok = cli_credentials_set_principal(creds, principal_name,
2506                                                    CRED_SPECIFIED);
2507                 if (!ok) {
2508                         TALLOC_FREE(tmp_ctx);
2509                         return NT_STATUS_NO_MEMORY;
2510                 }
2511         }
2512
2513         if (old_password_nt != NULL) {
2514                 ok = cli_credentials_set_old_nt_hash(creds, old_password_nt);
2515                 if (!ok) {
2516                         TALLOC_FREE(tmp_ctx);
2517                         return NT_STATUS_NO_MEMORY;
2518                 }
2519         }
2520
2521         if (old_password_utf16.length > 0) {
2522                 ok = cli_credentials_set_old_utf16_password(creds,
2523                                                             &old_password_utf16);
2524                 if (!ok) {
2525                         TALLOC_FREE(tmp_ctx);
2526                         return NT_STATUS_NO_MEMORY;
2527                 }
2528         }
2529
2530         if (password_nt != NULL) {
2531                 ok = cli_credentials_set_nt_hash(creds, password_nt,
2532                                                  CRED_SPECIFIED);
2533                 if (!ok) {
2534                         TALLOC_FREE(tmp_ctx);
2535                         return NT_STATUS_NO_MEMORY;
2536                 }
2537         }
2538
2539         if (password_utf16.length > 0) {
2540                 ok = cli_credentials_set_utf16_password(creds,
2541                                                         &password_utf16,
2542                                                         CRED_SPECIFIED);
2543                 if (!ok) {
2544                         TALLOC_FREE(tmp_ctx);
2545                         return NT_STATUS_NO_MEMORY;
2546                 }
2547         }
2548
2549         cli_credentials_set_password_last_changed_time(creds, last_set_time);
2550         cli_credentials_set_kvno(creds, password_version);
2551
2552         if (password_utf16.length > 0 && dns_domain != NULL) {
2553                 /*
2554                  * Force kerberos if this is an active directory domain
2555                  */
2556                 cli_credentials_set_kerberos_state(creds,
2557                                                    CRED_MUST_USE_KERBEROS);
2558         } else  {
2559                 /*
2560                  * TODO: we should allow krb5 with the raw nt hash.
2561                  */
2562                 cli_credentials_set_kerberos_state(creds,
2563                                                    CRED_DONT_USE_KERBEROS);
2564         }
2565
2566         *_creds = talloc_move(mem_ctx, &creds);
2567         TALLOC_FREE(tmp_ctx);
2568         return NT_STATUS_OK;
2569 }
2570
2571 static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2572                                       const char* domain, const char* pwd,
2573                                       const struct dom_sid *sid)
2574 {
2575         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2576                 m->private_data, struct pdb_samba_dsdb_state);
2577         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2578         const char * const attrs[] = {
2579                 "trustAuthOutgoing",
2580                 "trustDirection",
2581                 "trustType",
2582                 NULL
2583         };
2584         struct ldb_message *msg = NULL;
2585         int trust_direction_flags;
2586         int trust_type;
2587         int i;
2588         const struct ldb_val *old_val = NULL;
2589         struct trustAuthInOutBlob old_blob = {};
2590         uint32_t old_version = 0;
2591         uint32_t new_version = 0;
2592         DATA_BLOB new_utf16 = {};
2593         struct trustAuthInOutBlob new_blob = {};
2594         struct ldb_val new_val = {};
2595         struct timeval tv = timeval_current();
2596         NTTIME now = timeval_to_nttime(&tv);
2597         enum ndr_err_code ndr_err;
2598         NTSTATUS status;
2599         bool ok;
2600         int ret;
2601
2602         ret = ldb_transaction_start(state->ldb);
2603         if (ret != LDB_SUCCESS) {
2604                 DEBUG(2, ("Failed to start transaction.\n"));
2605                 TALLOC_FREE(tmp_ctx);
2606                 return false;
2607         }
2608
2609         ok = samdb_is_pdc(state->ldb);
2610         if (!ok) {
2611                 DEBUG(2, ("Password changes for domain %s are only allowed on a PDC.\n",
2612                           domain));
2613                 TALLOC_FREE(tmp_ctx);
2614                 ldb_transaction_cancel(state->ldb);
2615                 return false;
2616         }
2617
2618         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2619                                        attrs, tmp_ctx, &msg);
2620         if (!NT_STATUS_IS_OK(status)) {
2621                 /*
2622                  * This can be called to work out of a domain is
2623                  * trusted, rather than just to get the password
2624                  */
2625                 DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
2626                           "It may not be a trusted domain.\n", domain,
2627                           nt_errstr(status)));
2628                 TALLOC_FREE(tmp_ctx);
2629                 ldb_transaction_cancel(state->ldb);
2630                 return false;
2631         }
2632
2633         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2634         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2635                 DEBUG(2, ("Trusted domain %s is is not an outbound trust, can't set a password.\n",
2636                           domain));
2637                 TALLOC_FREE(tmp_ctx);
2638                 ldb_transaction_cancel(state->ldb);
2639                 return false;
2640         }
2641
2642         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2643         switch (trust_type) {
2644         case LSA_TRUST_TYPE_DOWNLEVEL:
2645         case LSA_TRUST_TYPE_UPLEVEL:
2646                 break;
2647         default:
2648                 DEBUG(0, ("Trusted domain %s is of type 0x%X - "
2649                           "password changes are not supported\n",
2650                           domain, (unsigned)trust_type));
2651                 TALLOC_FREE(tmp_ctx);
2652                 ldb_transaction_cancel(state->ldb);
2653                 return false;
2654         }
2655
2656         old_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2657         if (old_val != NULL) {
2658                 ndr_err = ndr_pull_struct_blob(old_val, tmp_ctx, &old_blob,
2659                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2660                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2661                         DEBUG(0, ("Failed to get trusted domain password for %s, "
2662                                   "attribute trustAuthOutgoing coult not be parsed %s.\n",
2663                                   domain,
2664                                   ndr_map_error2string(ndr_err)));
2665                         TALLOC_FREE(tmp_ctx);
2666                         ldb_transaction_cancel(state->ldb);
2667                         return false;
2668                 }
2669         }
2670
2671         for (i=0; i < old_blob.current.count; i++) {
2672                 struct AuthenticationInformation *a =
2673                         &old_blob.current.array[i];
2674
2675                 switch (a->AuthType) {
2676                 case TRUST_AUTH_TYPE_NONE:
2677                         break;
2678
2679                 case TRUST_AUTH_TYPE_VERSION:
2680                         old_version = a->AuthInfo.version.version;
2681                         break;
2682
2683                 case TRUST_AUTH_TYPE_CLEAR:
2684                         break;
2685
2686                 case TRUST_AUTH_TYPE_NT4OWF:
2687                         break;
2688                 }
2689         }
2690
2691         new_version = old_version + 1;
2692         ok = convert_string_talloc(tmp_ctx,
2693                                    CH_UNIX, CH_UTF16,
2694                                    pwd, strlen(pwd),
2695                                    (void *)&new_utf16.data,
2696                                    &new_utf16.length);
2697         if (!ok) {
2698                 DEBUG(0, ("Failed to generate new_utf16 password for  domain %s\n",
2699                           domain));
2700                 TALLOC_FREE(tmp_ctx);
2701                 ldb_transaction_cancel(state->ldb);
2702                 return false;
2703         }
2704
2705         if (new_utf16.length < 28) {
2706                 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to short.\n",
2707                           new_utf16.length,
2708                           (unsigned)new_version,
2709                           domain));
2710                 TALLOC_FREE(tmp_ctx);
2711                 ldb_transaction_cancel(state->ldb);
2712                 return false;
2713         }
2714         if (new_utf16.length > 498) {
2715                 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to long.\n",
2716                           new_utf16.length,
2717                           (unsigned)new_version,
2718                           domain));
2719                 TALLOC_FREE(tmp_ctx);
2720                 ldb_transaction_cancel(state->ldb);
2721                 return false;
2722         }
2723
2724         new_blob.count = MAX(old_blob.current.count, 2);
2725         new_blob.current.array = talloc_zero_array(tmp_ctx,
2726                                         struct AuthenticationInformation,
2727                                         new_blob.count);
2728         if (new_blob.current.array == NULL) {
2729                 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2730                           (unsigned)new_blob.count));
2731                 TALLOC_FREE(tmp_ctx);
2732                 ldb_transaction_cancel(state->ldb);
2733                 return false;
2734         }
2735         new_blob.previous.array = talloc_zero_array(tmp_ctx,
2736                                         struct AuthenticationInformation,
2737                                         new_blob.count);
2738         if (new_blob.current.array == NULL) {
2739                 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2740                           (unsigned)new_blob.count));
2741                 TALLOC_FREE(tmp_ctx);
2742                 ldb_transaction_cancel(state->ldb);
2743                 return false;
2744         }
2745
2746         for (i = 0; i < old_blob.current.count; i++) {
2747                 struct AuthenticationInformation *o =
2748                         &old_blob.current.array[i];
2749                 struct AuthenticationInformation *p =
2750                         &new_blob.previous.array[i];
2751
2752                 *p = *o;
2753                 new_blob.previous.count++;
2754         }
2755         for (; i < new_blob.count; i++) {
2756                 struct AuthenticationInformation *pi =
2757                         &new_blob.previous.array[i];
2758
2759                 if (i == 0) {
2760                         /*
2761                          * new_blob.previous is still empty so
2762                          * we'll do new_blob.previous = new_blob.current
2763                          * below.
2764                          */
2765                         break;
2766                 }
2767
2768                 pi->LastUpdateTime = now;
2769                 pi->AuthType = TRUST_AUTH_TYPE_NONE;
2770                 new_blob.previous.count++;
2771         }
2772
2773         for (i = 0; i < new_blob.count; i++) {
2774                 struct AuthenticationInformation *ci =
2775                         &new_blob.current.array[i];
2776
2777                 ci->LastUpdateTime = now;
2778                 switch (i) {
2779                 case 0:
2780                         ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
2781                         ci->AuthInfo.clear.size = new_utf16.length;
2782                         ci->AuthInfo.clear.password = new_utf16.data;
2783                         break;
2784                 case 1:
2785                         ci->AuthType = TRUST_AUTH_TYPE_VERSION;
2786                         ci->AuthInfo.version.version = new_version;
2787                         break;
2788                 default:
2789                         ci->AuthType = TRUST_AUTH_TYPE_NONE;
2790                         break;
2791                 }
2792
2793                 new_blob.current.count++;
2794         }
2795
2796         if (new_blob.previous.count == 0) {
2797                 TALLOC_FREE(new_blob.previous.array);
2798                 new_blob.previous = new_blob.current;
2799         }
2800
2801         ndr_err = ndr_push_struct_blob(&new_val, tmp_ctx, &new_blob,
2802                         (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
2803         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2804                 DEBUG(0, ("Failed to generate trustAuthOutgoing for "
2805                           "trusted domain password for %s: %s.\n",
2806                           domain, ndr_map_error2string(ndr_err)));
2807                 TALLOC_FREE(tmp_ctx);
2808                 ldb_transaction_cancel(state->ldb);
2809                 return false;
2810         }
2811
2812         msg->num_elements = 0;
2813         ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2814                                 LDB_FLAG_MOD_REPLACE, NULL);
2815         if (ret != LDB_SUCCESS) {
2816                 DEBUG(0, ("ldb_msg_add_empty() failed\n"));
2817                 TALLOC_FREE(tmp_ctx);
2818                 ldb_transaction_cancel(state->ldb);
2819                 return false;
2820         }
2821         ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2822                                 &new_val, NULL);
2823         if (ret != LDB_SUCCESS) {
2824                 DEBUG(0, ("ldb_msg_add_value() failed\n"));
2825                 TALLOC_FREE(tmp_ctx);
2826                 ldb_transaction_cancel(state->ldb);
2827                 return false;
2828         }
2829
2830         ret = ldb_modify(state->ldb, msg);
2831         if (ret != LDB_SUCCESS) {
2832                 DEBUG(0, ("Failed to replace trustAuthOutgoing for "
2833                           "trusted domain password for %s: %s - %s\n",
2834                           domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2835                 TALLOC_FREE(tmp_ctx);
2836                 ldb_transaction_cancel(state->ldb);
2837                 return false;
2838         }
2839
2840         ret = ldb_transaction_commit(state->ldb);
2841         if (ret != LDB_SUCCESS) {
2842                 DEBUG(0, ("Failed to commit trustAuthOutgoing for "
2843                           "trusted domain password for %s: %s - %s\n",
2844                           domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2845                 TALLOC_FREE(tmp_ctx);
2846                 return false;
2847         }
2848
2849         DEBUG(1, ("Added new_version[%u] to trustAuthOutgoing for "
2850                   "trusted domain password for %s.\n",
2851                   (unsigned)new_version, domain));
2852         TALLOC_FREE(tmp_ctx);
2853         return true;
2854 }
2855
2856 static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2857                                       const char *domain)
2858 {
2859         return false;
2860 }
2861
2862 static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2863                                          TALLOC_CTX *mem_ctx,
2864                                          uint32_t *num_domains,
2865                                          struct trustdom_info ***domains)
2866 {
2867         *num_domains = 0;
2868         *domains = NULL;
2869         return NT_STATUS_OK;
2870 }
2871
2872 static bool pdb_samba_dsdb_is_responsible_for_wellknown(struct pdb_methods *m)
2873 {
2874         return true;
2875 }
2876
2877 static bool pdb_samba_dsdb_is_responsible_for_everything_else(struct pdb_methods *m)
2878 {
2879         return true;
2880 }
2881
2882 static void pdb_samba_dsdb_init_methods(struct pdb_methods *m)
2883 {
2884         m->name = "samba_dsdb";
2885         m->get_domain_info = pdb_samba_dsdb_get_domain_info;
2886         m->getsampwnam = pdb_samba_dsdb_getsampwnam;
2887         m->getsampwsid = pdb_samba_dsdb_getsampwsid;
2888         m->create_user = pdb_samba_dsdb_create_user;
2889         m->delete_user = pdb_samba_dsdb_delete_user;
2890         m->add_sam_account = pdb_samba_dsdb_add_sam_account;
2891         m->update_sam_account = pdb_samba_dsdb_update_sam_account;
2892         m->delete_sam_account = pdb_samba_dsdb_delete_sam_account;
2893         m->rename_sam_account = pdb_samba_dsdb_rename_sam_account;
2894         m->update_login_attempts = pdb_samba_dsdb_update_login_attempts;
2895         m->getgrsid = pdb_samba_dsdb_getgrsid;
2896         m->getgrgid = pdb_samba_dsdb_getgrgid;
2897         m->getgrnam = pdb_samba_dsdb_getgrnam;
2898         m->create_dom_group = pdb_samba_dsdb_create_dom_group;
2899         m->delete_dom_group = pdb_samba_dsdb_delete_dom_group;
2900         m->add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry;
2901         m->update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry;
2902         m->delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry;
2903         m->enum_group_mapping = pdb_samba_dsdb_enum_group_mapping;
2904         m->enum_group_members = pdb_samba_dsdb_enum_group_members;
2905         m->enum_group_memberships = pdb_samba_dsdb_enum_group_memberships;
2906         m->set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group;
2907         m->add_groupmem = pdb_samba_dsdb_add_groupmem;
2908         m->del_groupmem = pdb_samba_dsdb_del_groupmem;