97c05c6224ea055c268cb56ffa5b06e1ac3808f3
[ambi/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                                 /* Parse the history into the correct format */
447                                 for (i = 0; i < current_hist_len; i++) {
448                                         if (!all_zero(&history[i*PW_HISTORY_ENTRY_LEN],
449                                                       16)) {
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, ...)
664                                           PRINTF_ATTRIBUTE(4,5);
665
666 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
667                                           struct pdb_samba_dsdb_state *state,
668                                           struct samu *sam_acct,
669                                           const char *exp_fmt, ...)
670 {
671         struct ldb_message *priv;
672         NTSTATUS status;
673         va_list ap;
674         char *expression = NULL;
675         TALLOC_CTX *tmp_ctx = talloc_new(state);
676         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
677
678         va_start(ap, exp_fmt);
679         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
680         va_end(ap);
681
682         if (!expression) {
683                 talloc_free(tmp_ctx);
684                 return NT_STATUS_NO_MEMORY;
685         }
686
687         status = pdb_samba_dsdb_getsamupriv(state, expression, sam_acct, &priv);
688         talloc_free(tmp_ctx);
689         if (!NT_STATUS_IS_OK(status)) {
690                 DEBUG(10, ("pdb_samba_dsdb_getsamupriv failed: %s\n",
691                            nt_errstr(status)));
692                 return status;
693         }
694
695         status = pdb_samba_dsdb_init_sam_from_priv(m, sam_acct, priv);
696         if (!NT_STATUS_IS_OK(status)) {
697                 DEBUG(10, ("pdb_samba_dsdb_init_sam_from_priv failed: %s\n",
698                            nt_errstr(status)));
699                 TALLOC_FREE(priv);
700                 return status;
701         }
702
703         pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
704         return NT_STATUS_OK;
705 }
706
707 static NTSTATUS pdb_samba_dsdb_getsampwnam(struct pdb_methods *m,
708                                     struct samu *sam_acct,
709                                     const char *username)
710 {
711         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
712                 m->private_data, struct pdb_samba_dsdb_state);
713
714         return pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
715                                          "(&(samaccountname=%s)(objectclass=user))",
716                                          username);
717 }
718
719 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
720                                     struct samu *sam_acct,
721                                     const struct dom_sid *sid)
722 {
723         NTSTATUS status;
724         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
725                 m->private_data, struct pdb_samba_dsdb_state);
726         char *sidstr;
727
728         sidstr = dom_sid_string(talloc_tos(), sid);
729         NT_STATUS_HAVE_NO_MEMORY(sidstr);
730
731         status = pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
732                                            "(&(objectsid=%s)(objectclass=user))",
733                                            sidstr);
734         talloc_free(sidstr);
735         return status;
736 }
737
738 static NTSTATUS pdb_samba_dsdb_create_user(struct pdb_methods *m,
739                                     TALLOC_CTX *mem_ctx,
740                                     const char *name, uint32_t acct_flags,
741                                     uint32_t *rid)
742 {
743         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
744                 m->private_data, struct pdb_samba_dsdb_state);
745         struct dom_sid *sid;
746         struct ldb_dn *dn;
747         NTSTATUS status;
748         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
749         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
750
751         /* Internally this uses transactions to ensure all the steps
752          * happen or fail as one */
753         status = dsdb_add_user(state->ldb, tmp_ctx, name, acct_flags, NULL,
754                                &sid, &dn);
755         if (!NT_STATUS_IS_OK(status)) {
756                 talloc_free(tmp_ctx);
757                 return status;
758         }
759         sid_peek_rid(sid, rid);
760         talloc_free(tmp_ctx);
761         return NT_STATUS_OK;
762 }
763
764 static NTSTATUS pdb_samba_dsdb_delete_user(struct pdb_methods *m,
765                                        TALLOC_CTX *mem_ctx,
766                                        struct samu *sam)
767 {
768         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
769                 m->private_data, struct pdb_samba_dsdb_state);
770         struct ldb_dn *dn;
771         int rc;
772         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
773         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
774
775         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, pdb_get_user_sid(sam)));
776         if (!dn || !ldb_dn_validate(dn)) {
777                 talloc_free(tmp_ctx);
778                 return NT_STATUS_NO_MEMORY;
779         }
780         rc = ldb_delete(state->ldb, dn);
781
782         if (rc != LDB_SUCCESS) {
783                 DEBUG(10, ("ldb_delete for %s failed: %s\n", ldb_dn_get_linearized(dn),
784                            ldb_errstring(state->ldb)));
785                 talloc_free(tmp_ctx);
786                 return NT_STATUS_LDAP(rc);
787         }
788         talloc_free(tmp_ctx);
789         return NT_STATUS_OK;
790 }
791
792 /* This interface takes a fully populated struct samu and places it in
793  * the database.  This is not implemented at this time as we need to
794  * be careful around the creation of arbitary SIDs (ie, we must ensrue
795  * they are not left in a RID pool */
796 static NTSTATUS pdb_samba_dsdb_add_sam_account(struct pdb_methods *m,
797                                         struct samu *sampass)
798 {
799         int ret;
800         NTSTATUS status;
801         struct ldb_dn *dn;
802         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
803                 m->private_data, struct pdb_samba_dsdb_state);
804         uint32_t acb_flags = pdb_get_acct_ctrl(sampass);
805         const char *username = pdb_get_username(sampass);
806         const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
807         TALLOC_CTX *tframe = talloc_stackframe();
808
809         acb_flags &= (ACB_NORMAL|ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST);
810
811         ret = ldb_transaction_start(state->ldb);
812         if (ret != LDB_SUCCESS) {
813                 talloc_free(tframe);
814                 return NT_STATUS_LOCK_NOT_GRANTED;
815         }
816
817         status = dsdb_add_user(state->ldb, talloc_tos(), username,
818                                acb_flags, user_sid, NULL, &dn);
819         if (!NT_STATUS_IS_OK(status)) {
820                 ldb_transaction_cancel(state->ldb);
821                 talloc_free(tframe);
822                 return status;
823         }
824
825         ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_set_or_changed,
826                                         dn, sampass);
827         if (ret != LDB_SUCCESS) {
828                 ldb_transaction_cancel(state->ldb);
829                 talloc_free(tframe);
830                 return dsdb_ldb_err_to_ntstatus(ret);
831         }
832
833         ret = ldb_transaction_commit(state->ldb);
834         if (ret != LDB_SUCCESS) {
835                 DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
836                          ldb_dn_get_linearized(dn),
837                          ldb_errstring(state->ldb)));
838                 talloc_free(tframe);
839                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
840         }
841         talloc_free(tframe);
842         return NT_STATUS_OK;
843 }
844
845 /*
846  * Update the Samba_Dsdb LDB with the changes from a struct samu.
847  *
848  * This takes care not to update elements that have not been changed
849  * by the caller
850  */
851 static NTSTATUS pdb_samba_dsdb_update_sam_account(struct pdb_methods *m,
852                                            struct samu *sam)
853 {
854         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
855                 m->private_data, struct pdb_samba_dsdb_state);
856         struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
857                 m, sam);
858         int ret;
859
860         ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_changed, msg->dn,
861                                         sam);
862         return dsdb_ldb_err_to_ntstatus(ret);
863 }
864
865 static NTSTATUS pdb_samba_dsdb_delete_sam_account(struct pdb_methods *m,
866                                            struct samu *username)
867 {
868         NTSTATUS status;
869         TALLOC_CTX *tmp_ctx = talloc_new(NULL);
870         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
871         status = pdb_samba_dsdb_delete_user(m, tmp_ctx, username);
872         talloc_free(tmp_ctx);
873         return status;
874 }
875
876 static NTSTATUS pdb_samba_dsdb_rename_sam_account(struct pdb_methods *m,
877                                            struct samu *oldname,
878                                            const char *newname)
879 {
880         return NT_STATUS_NOT_IMPLEMENTED;
881 }
882
883 /* This is not implemented, as this module is exptected to be used
884  * with auth_samba_dsdb, and this is responible for login counters etc
885  *
886  */
887 static NTSTATUS pdb_samba_dsdb_update_login_attempts(struct pdb_methods *m,
888                                               struct samu *sam_acct,
889                                               bool success)
890 {
891         return NT_STATUS_NOT_IMPLEMENTED;
892 }
893
894 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m,
895                                            GROUP_MAP *map,
896                                            const char *exp_fmt, ...)
897                                            PRINTF_ATTRIBUTE(3,4);
898
899 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
900                                     const char *exp_fmt, ...)
901 {
902         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
903                 m->private_data, struct pdb_samba_dsdb_state);
904         const char *attrs[] = { "objectClass", "objectSid", "description", "samAccountName", "groupType",
905                                 NULL };
906         struct ldb_message *msg;
907         va_list ap;
908         char *expression = NULL;
909         struct dom_sid *sid;
910         const char *str;
911         int rc;
912         struct id_map id_map;
913         struct id_map *id_maps[2];
914         TALLOC_CTX *tmp_ctx = talloc_stackframe();
915         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
916
917         va_start(ap, exp_fmt);
918         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
919         va_end(ap);
920
921         if (!expression) {
922                 talloc_free(tmp_ctx);
923                 return NT_STATUS_NO_MEMORY;
924         }
925
926         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
927         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
928                 talloc_free(tmp_ctx);
929                 return NT_STATUS_NO_SUCH_GROUP;
930         } else if (rc != LDB_SUCCESS) {
931                 talloc_free(tmp_ctx);
932                 DEBUG(10, ("dsdb_search_one failed %s\n",
933                            ldb_errstring(state->ldb)));
934                 return NT_STATUS_LDAP(rc);
935         }
936
937         sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
938         if (!sid) {
939                 talloc_free(tmp_ctx);
940                 DEBUG(10, ("Could not pull SID\n"));
941                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
942         }
943
944         map->sid = *sid;
945
946         if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) {
947                 NTSTATUS status;
948                 uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0);
949                 switch (grouptype) {
950                 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
951                 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
952                         map->sid_name_use = SID_NAME_ALIAS;
953                         break;
954                 case GTYPE_SECURITY_GLOBAL_GROUP:
955                         map->sid_name_use = SID_NAME_DOM_GRP;
956                         break;
957                 default:
958                         talloc_free(tmp_ctx);
959                         DEBUG(10, ("Could not pull groupType\n"));
960                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
961                 }
962
963                 ZERO_STRUCT(id_map);
964                 id_map.sid = sid;
965                 id_maps[0] = &id_map;
966                 id_maps[1] = NULL;
967
968                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
969
970                 if (!NT_STATUS_IS_OK(status)) {
971                         talloc_free(tmp_ctx);
972                         return status;
973                 }
974                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
975                         map->gid = id_map.xid.id;
976                 } else {
977                         DEBUG(1, (__location__ "Did not get GUID when mapping SID for %s", expression));
978                         talloc_free(tmp_ctx);
979                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
980                 }
981         } else if (samdb_find_attribute(state->ldb, msg, "objectClass", "user")) {
982                 DEBUG(1, (__location__ "Got SID_NAME_USER when searching for a group with %s", expression));
983                 talloc_free(tmp_ctx);
984                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
985         }
986
987         str = ldb_msg_find_attr_as_string(msg, "samAccountName",
988                                           NULL);
989         if (str == NULL) {
990                 talloc_free(tmp_ctx);
991                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
992         }
993         map->nt_name = talloc_strdup(map, str);
994         if (!map->nt_name) {
995                 talloc_free(tmp_ctx);
996                 return NT_STATUS_NO_MEMORY;
997         }
998
999         str = ldb_msg_find_attr_as_string(msg, "description",
1000                                             NULL);
1001         if (str != NULL) {
1002                 map->comment = talloc_strdup(map, str);
1003         } else {
1004                 map->comment = talloc_strdup(map, "");
1005         }
1006         if (!map->comment) {
1007                 talloc_free(tmp_ctx);
1008                 return NT_STATUS_NO_MEMORY;
1009         }
1010
1011         talloc_free(tmp_ctx);
1012         return NT_STATUS_OK;
1013 }
1014
1015 static NTSTATUS pdb_samba_dsdb_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
1016                                  struct dom_sid sid)
1017 {
1018         char *filter;
1019         NTSTATUS status;
1020
1021         filter = talloc_asprintf(talloc_tos(),
1022                                  "(&(objectsid=%s)(objectclass=group))",
1023                                  sid_string_talloc(talloc_tos(), &sid));
1024         if (filter == NULL) {
1025                 return NT_STATUS_NO_MEMORY;
1026         }
1027
1028         status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
1029         TALLOC_FREE(filter);
1030         return status;
1031 }
1032
1033 static NTSTATUS pdb_samba_dsdb_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
1034                                  gid_t gid)
1035 {
1036         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1037                 m->private_data, struct pdb_samba_dsdb_state);
1038         NTSTATUS status;
1039         struct id_map id_map;
1040         struct id_map *id_maps[2];
1041         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1042         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1043
1044         id_map.xid.id = gid;
1045         id_map.xid.type = ID_TYPE_GID;
1046         id_maps[0] = &id_map;
1047         id_maps[1] = NULL;
1048
1049         status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
1050         if (!NT_STATUS_IS_OK(status)) {
1051                 talloc_free(tmp_ctx);
1052                 return status;
1053         }
1054         status = pdb_samba_dsdb_getgrsid(m, map, *id_map.sid);
1055         talloc_free(tmp_ctx);
1056         return status;
1057 }
1058
1059 static NTSTATUS pdb_samba_dsdb_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
1060                                  const char *name)
1061 {
1062         char *filter;
1063         NTSTATUS status;
1064
1065         filter = talloc_asprintf(talloc_tos(),
1066                                  "(&(samaccountname=%s)(objectclass=group))",
1067                                  name);
1068         if (filter == NULL) {
1069                 return NT_STATUS_NO_MEMORY;
1070         }
1071
1072         status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
1073         TALLOC_FREE(filter);
1074         return status;
1075 }
1076
1077 static NTSTATUS pdb_samba_dsdb_create_dom_group(struct pdb_methods *m,
1078                                          TALLOC_CTX *mem_ctx, const char *name,
1079                                          uint32_t *rid)
1080 {
1081         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1082                 m->private_data, struct pdb_samba_dsdb_state);
1083         NTSTATUS status;
1084         struct dom_sid *sid;
1085         struct ldb_dn *dn;
1086         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1087         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1088
1089         status = dsdb_add_domain_group(state->ldb, tmp_ctx, name, &sid, &dn);
1090         if (!NT_STATUS_IS_OK(status)) {
1091                 talloc_free(tmp_ctx);
1092                 return status;
1093         }
1094
1095         sid_peek_rid(sid, rid);
1096         talloc_free(tmp_ctx);
1097         return NT_STATUS_OK;
1098 }
1099
1100 static NTSTATUS pdb_samba_dsdb_delete_dom_group(struct pdb_methods *m,
1101                                          TALLOC_CTX *mem_ctx, uint32_t rid)
1102 {
1103         const char *attrs[] = { NULL };
1104         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1105                 m->private_data, struct pdb_samba_dsdb_state);
1106         struct dom_sid sid;
1107         struct ldb_message *msg;
1108         struct ldb_dn *dn;
1109         int rc;
1110         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1111         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1112
1113         sid_compose(&sid, samdb_domain_sid(state->ldb), rid);
1114
1115         if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1116                 DEBUG(0, ("Unable to start transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1117                 return NT_STATUS_INTERNAL_ERROR;
1118         }
1119
1120         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, &sid));
1121         if (!dn || !ldb_dn_validate(dn)) {
1122                 talloc_free(tmp_ctx);
1123                 ldb_transaction_cancel(state->ldb);
1124                 return NT_STATUS_NO_MEMORY;
1125         }
1126         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "objectclass=group");
1127         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1128                 talloc_free(tmp_ctx);
1129                 ldb_transaction_cancel(state->ldb);
1130                 return NT_STATUS_NO_SUCH_GROUP;
1131         }
1132         rc = ldb_delete(state->ldb, dn);
1133         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1134                 talloc_free(tmp_ctx);
1135                 ldb_transaction_cancel(state->ldb);
1136                 return NT_STATUS_NO_SUCH_GROUP;
1137         } else if (rc != LDB_SUCCESS) {
1138                 DEBUG(10, ("ldb_delete failed %s\n",
1139                            ldb_errstring(state->ldb)));
1140                 ldb_transaction_cancel(state->ldb);
1141                 return NT_STATUS_LDAP(rc);
1142         }
1143
1144         if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1145                 DEBUG(0, ("Unable to commit transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1146                 return NT_STATUS_INTERNAL_ERROR;
1147         }
1148         return NT_STATUS_OK;
1149 }
1150
1151 static NTSTATUS pdb_samba_dsdb_add_group_mapping_entry(struct pdb_methods *m,
1152                                                 GROUP_MAP *map)
1153 {
1154         return NT_STATUS_NOT_IMPLEMENTED;
1155 }
1156
1157 static NTSTATUS pdb_samba_dsdb_update_group_mapping_entry(struct pdb_methods *m,
1158                                                    GROUP_MAP *map)
1159 {
1160         return NT_STATUS_NOT_IMPLEMENTED;
1161 }
1162
1163 static NTSTATUS pdb_samba_dsdb_delete_group_mapping_entry(struct pdb_methods *m,
1164                                                    struct dom_sid sid)
1165 {
1166         return NT_STATUS_NOT_IMPLEMENTED;
1167 }
1168
1169 static NTSTATUS pdb_samba_dsdb_enum_group_mapping(struct pdb_methods *m,
1170                                            const struct dom_sid *sid,
1171                                            enum lsa_SidType sid_name_use,
1172                                            GROUP_MAP ***pp_rmap,
1173                                            size_t *p_num_entries,
1174                                            bool unix_only)
1175 {
1176         return NT_STATUS_NOT_IMPLEMENTED;
1177 }
1178
1179 static NTSTATUS pdb_samba_dsdb_enum_group_members(struct pdb_methods *m,
1180                                            TALLOC_CTX *mem_ctx,
1181                                            const struct dom_sid *group,
1182                                            uint32_t **pmembers,
1183                                            size_t *pnum_members)
1184 {
1185         unsigned int i, num_sids, num_members;
1186         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1187                 m->private_data, struct pdb_samba_dsdb_state);
1188         struct dom_sid *members_as_sids;
1189         struct dom_sid *dom_sid;
1190         uint32_t *members;
1191         struct ldb_dn *dn;
1192         NTSTATUS status;
1193
1194         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1195         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1196
1197         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, group));
1198         if (!dn || !ldb_dn_validate(dn)) {
1199                 return NT_STATUS_NO_MEMORY;
1200         }
1201
1202         status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
1203         if (!NT_STATUS_IS_OK(status)) {
1204                 talloc_free(tmp_ctx);
1205                 return status;
1206         }
1207         status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
1208         if (!NT_STATUS_IS_OK(status)) {
1209                 talloc_free(tmp_ctx);
1210                 return status;
1211         }
1212
1213         *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
1214         if (*pmembers == NULL) {
1215                 TALLOC_FREE(tmp_ctx);
1216                 return NT_STATUS_NO_MEMORY;
1217         }
1218         num_members = 0;
1219
1220         for (i = 0; i < num_sids; i++) {
1221                 if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
1222                         continue;
1223                 }
1224                 status = dom_sid_split_rid(NULL, &members_as_sids[i],
1225                                            NULL, &members[num_members]);
1226                 if (!NT_STATUS_IS_OK(status)) {
1227                         talloc_free(tmp_ctx);
1228                         return status;
1229                 }
1230                 num_members++;
1231         }
1232         *pnum_members = num_members;
1233         return NT_STATUS_OK;
1234 }
1235
1236 /* Just convert the primary group SID into a group */
1237 static NTSTATUS fake_enum_group_memberships(struct pdb_samba_dsdb_state *state,
1238                                             TALLOC_CTX *mem_ctx,
1239                                             struct samu *user,
1240                                             struct dom_sid **pp_sids,
1241                                             gid_t **pp_gids,
1242                                             uint32_t *p_num_groups)
1243 {
1244         NTSTATUS status;
1245         size_t num_groups = 0;
1246         struct dom_sid *group_sids = NULL;
1247         gid_t *gids = NULL;
1248         TALLOC_CTX *tmp_ctx;
1249
1250         tmp_ctx = talloc_new(mem_ctx);
1251         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1252
1253         if (user->group_sid) {
1254                 struct id_map *id_maps[2];
1255                 struct id_map id_map;
1256
1257                 num_groups = 1;
1258
1259                 group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
1260                 if (group_sids == NULL) {
1261                         talloc_free(tmp_ctx);
1262                         return NT_STATUS_NO_MEMORY;
1263                 }
1264                 gids = talloc_array(tmp_ctx, gid_t, num_groups);
1265                 if (gids == NULL) {
1266                         talloc_free(tmp_ctx);
1267                         return NT_STATUS_NO_MEMORY;
1268                 }
1269
1270                 group_sids[0] = *user->group_sid;
1271
1272                 ZERO_STRUCT(id_map);
1273                 id_map.sid = &group_sids[0];
1274                 id_maps[0] = &id_map;
1275                 id_maps[1] = NULL;
1276
1277                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1278                 if (!NT_STATUS_IS_OK(status)) {
1279                         talloc_free(tmp_ctx);
1280                         return status;
1281                 }
1282                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1283                         gids[0] = id_map.xid.id;
1284                 } else {
1285                         DEBUG(1, (__location__
1286                                   "Group %s, of which %s is a member, could not be converted to a GID\n",
1287                                   dom_sid_string(tmp_ctx, &group_sids[0]),
1288                                   dom_sid_string(tmp_ctx, &user->user_sid)));
1289                         talloc_free(tmp_ctx);
1290                         /* We must error out, otherwise a user might
1291                          * avoid a DENY acl based on a group they
1292                          * missed out on */
1293                         return NT_STATUS_NO_SUCH_GROUP;
1294                 }
1295         }
1296
1297         *pp_sids = talloc_steal(mem_ctx, group_sids);
1298         *pp_gids = talloc_steal(mem_ctx, gids);
1299         *p_num_groups = num_groups;
1300         talloc_free(tmp_ctx);
1301         return NT_STATUS_OK;
1302 }
1303
1304 static NTSTATUS pdb_samba_dsdb_enum_group_memberships(struct pdb_methods *m,
1305                                                TALLOC_CTX *mem_ctx,
1306                                                struct samu *user,
1307                                                struct dom_sid **pp_sids,
1308                                                gid_t **pp_gids,
1309                                                uint32_t *p_num_groups)
1310 {
1311         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1312                 m->private_data, struct pdb_samba_dsdb_state);
1313         struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
1314                 m, user);
1315         const char *attrs[] = { "tokenGroups", NULL};
1316         struct ldb_message *tokengroups_msg;
1317         struct ldb_message_element *tokengroups;
1318         int i, rc;
1319         NTSTATUS status;
1320         unsigned int count = 0;
1321         size_t num_groups;
1322         struct dom_sid *group_sids;
1323         gid_t *gids;
1324         TALLOC_CTX *tmp_ctx;
1325
1326         if (msg == NULL) {
1327                 /* Fake up some things here */
1328                 return fake_enum_group_memberships(state,
1329                                                    mem_ctx,
1330                                                    user, pp_sids,
1331                                                    pp_gids, p_num_groups);
1332         }
1333
1334         tmp_ctx = talloc_new(mem_ctx);
1335         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1336
1337         rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
1338
1339         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1340                 talloc_free(tmp_ctx);
1341                 return NT_STATUS_NO_SUCH_USER;
1342         } else if (rc != LDB_SUCCESS) {
1343                 DEBUG(10, ("dsdb_search_one failed %s\n",
1344                            ldb_errstring(state->ldb)));
1345                 talloc_free(tmp_ctx);
1346                 return NT_STATUS_LDAP(rc);
1347         }
1348
1349         tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
1350
1351         if (tokengroups) {
1352                 count = tokengroups->num_values;
1353         }
1354
1355         group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
1356         if (group_sids == NULL) {
1357                 talloc_free(tmp_ctx);
1358                 return NT_STATUS_NO_MEMORY;
1359         }
1360         gids = talloc_array(tmp_ctx, gid_t, count);
1361         if (gids == NULL) {
1362                 talloc_free(tmp_ctx);
1363                 return NT_STATUS_NO_MEMORY;
1364         }
1365         num_groups = 0;
1366
1367         for (i=0; i<count; i++) {
1368                 struct id_map *id_maps[2];
1369                 struct id_map id_map;
1370                 struct ldb_val *v = &tokengroups->values[i];
1371                 enum ndr_err_code ndr_err
1372                         = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
1373                                                (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1374                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1375                         talloc_free(tmp_ctx);
1376                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1377                 }
1378
1379                 ZERO_STRUCT(id_map);
1380                 id_map.sid = &group_sids[num_groups];
1381                 id_maps[0] = &id_map;
1382                 id_maps[1] = NULL;
1383
1384                 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1385                 if (!NT_STATUS_IS_OK(status)) {
1386                         talloc_free(tmp_ctx);
1387                         return status;
1388                 }
1389                 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1390                         gids[num_groups] = id_map.xid.id;
1391                 } else {
1392                         DEBUG(1, (__location__
1393                                   "Group %s, of which %s is a member, could not be converted to a GID\n",
1394                                   dom_sid_string(tmp_ctx, &group_sids[num_groups]),
1395                                   ldb_dn_get_linearized(msg->dn)));
1396                         talloc_free(tmp_ctx);
1397                         /* We must error out, otherwise a user might
1398                          * avoid a DENY acl based on a group they
1399                          * missed out on */
1400                         return NT_STATUS_NO_SUCH_GROUP;
1401                 }
1402
1403                 num_groups += 1;
1404                 if (num_groups == count) {
1405                         break;
1406                 }
1407         }
1408
1409         *pp_sids = talloc_steal(mem_ctx, group_sids);
1410         *pp_gids = talloc_steal(mem_ctx, gids);
1411         *p_num_groups = num_groups;
1412         talloc_free(tmp_ctx);
1413         return NT_STATUS_OK;
1414 }
1415
1416 static NTSTATUS pdb_samba_dsdb_set_unix_primary_group(struct pdb_methods *m,
1417                                                TALLOC_CTX *mem_ctx,
1418                                                struct samu *user)
1419 {
1420         return NT_STATUS_NOT_IMPLEMENTED;
1421 }
1422
1423 static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid(struct pdb_methods *m,
1424                                                TALLOC_CTX *mem_ctx,
1425                                                const struct dom_sid *groupsid,
1426                                                const struct dom_sid *membersid,
1427                                                int mod_op)
1428 {
1429         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1430                 m->private_data, struct pdb_samba_dsdb_state);
1431         struct ldb_message *msg;
1432         int ret;
1433         struct ldb_message_element *el;
1434         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1435         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1436         msg = ldb_msg_new(tmp_ctx);
1437         if (msg == NULL) {
1438                 TALLOC_FREE(tmp_ctx);
1439                 return NT_STATUS_NO_MEMORY;
1440         }
1441
1442         msg->dn = ldb_dn_new_fmt(msg, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, groupsid));
1443         if (!msg->dn || !ldb_dn_validate(msg->dn)) {
1444                 talloc_free(tmp_ctx);
1445                 return NT_STATUS_NO_MEMORY;
1446         }
1447         ret = ldb_msg_add_fmt(msg, "member", "<SID=%s>", dom_sid_string(tmp_ctx, membersid));
1448         if (ret != LDB_SUCCESS) {
1449                 talloc_free(tmp_ctx);
1450                 return NT_STATUS_NO_MEMORY;
1451         }
1452         el = ldb_msg_find_element(msg, "member");
1453         el->flags = mod_op;
1454
1455         /* No need for transactions here, the ldb auto-transaction
1456          * code will handle things for the single operation */
1457         ret = ldb_modify(state->ldb, msg);
1458         talloc_free(tmp_ctx);
1459         if (ret != LDB_SUCCESS) {
1460                 DEBUG(10, ("ldb_modify failed: %s\n",
1461                            ldb_errstring(state->ldb)));
1462                 if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
1463                         return NT_STATUS_MEMBER_IN_GROUP;
1464                 }
1465                 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1466                         return NT_STATUS_MEMBER_NOT_IN_GROUP;
1467                 }
1468                 return NT_STATUS_LDAP(ret);
1469         }
1470
1471         return NT_STATUS_OK;
1472 }
1473
1474 static NTSTATUS pdb_samba_dsdb_mod_groupmem(struct pdb_methods *m,
1475                                      TALLOC_CTX *mem_ctx,
1476                                      uint32_t grouprid, uint32_t memberrid,
1477                                      int mod_op)
1478 {
1479         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1480                 m->private_data, struct pdb_samba_dsdb_state);
1481         const struct dom_sid *dom_sid, *groupsid, *membersid;
1482         NTSTATUS status;
1483         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1484         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1485
1486         dom_sid = samdb_domain_sid(state->ldb);
1487
1488         groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
1489         if (groupsid == NULL) {
1490                 TALLOC_FREE(tmp_ctx);
1491                 return NT_STATUS_NO_MEMORY;
1492         }
1493         membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
1494         if (membersid == NULL) {
1495                 TALLOC_FREE(tmp_ctx);
1496                 return NT_STATUS_NO_MEMORY;
1497         }
1498         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
1499         talloc_free(tmp_ctx);
1500         return status;
1501 }
1502
1503 static NTSTATUS pdb_samba_dsdb_add_groupmem(struct pdb_methods *m,
1504                                      TALLOC_CTX *mem_ctx,
1505                                      uint32_t group_rid, uint32_t member_rid)
1506 {
1507         return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1508                                     LDB_FLAG_MOD_ADD);
1509 }
1510
1511 static NTSTATUS pdb_samba_dsdb_del_groupmem(struct pdb_methods *m,
1512                                      TALLOC_CTX *mem_ctx,
1513                                      uint32_t group_rid, uint32_t member_rid)
1514 {
1515         return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1516                                        LDB_FLAG_MOD_DELETE);
1517 }
1518
1519 static NTSTATUS pdb_samba_dsdb_create_alias(struct pdb_methods *m,
1520                                      const char *name, uint32_t *rid)
1521 {
1522         TALLOC_CTX *frame = talloc_stackframe();
1523         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1524                 m->private_data, struct pdb_samba_dsdb_state);
1525         struct dom_sid *sid;
1526
1527         struct ldb_dn *dn;
1528         NTSTATUS status;
1529
1530         /* Internally this uses transactions to ensure all the steps
1531          * happen or fail as one */
1532         status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
1533         if (!NT_STATUS_IS_OK(status)) {
1534                 TALLOC_FREE(frame);
1535         }
1536
1537         sid_peek_rid(sid, rid);
1538         TALLOC_FREE(frame);
1539         return NT_STATUS_OK;
1540 }
1541
1542 static NTSTATUS pdb_samba_dsdb_delete_alias(struct pdb_methods *m,
1543                                      const struct dom_sid *sid)
1544 {
1545         const char *attrs[] = { NULL };
1546         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1547                 m->private_data, struct pdb_samba_dsdb_state);
1548         struct ldb_message *msg;
1549         struct ldb_dn *dn;
1550         int rc;
1551         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1552         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1553
1554         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, sid));
1555         if (!dn || !ldb_dn_validate(dn)) {
1556                 talloc_free(tmp_ctx);
1557                 return NT_STATUS_NO_MEMORY;
1558         }
1559
1560         if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1561                 DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(state->ldb)));
1562                 talloc_free(tmp_ctx);
1563                 return NT_STATUS_INTERNAL_ERROR;
1564         }
1565
1566         rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
1567                              "(|(grouptype=%d)(grouptype=%d)))",
1568                              GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1569                              GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1570         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1571                 talloc_free(tmp_ctx);
1572                 ldb_transaction_cancel(state->ldb);
1573                 return NT_STATUS_NO_SUCH_ALIAS;
1574         }
1575         rc = ldb_delete(state->ldb, dn);
1576         if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1577                 talloc_free(tmp_ctx);
1578                 ldb_transaction_cancel(state->ldb);
1579                 return NT_STATUS_NO_SUCH_ALIAS;
1580         } else if (rc != LDB_SUCCESS) {
1581                 DEBUG(10, ("ldb_delete failed %s\n",
1582                            ldb_errstring(state->ldb)));
1583                 ldb_transaction_cancel(state->ldb);
1584                 talloc_free(tmp_ctx);
1585                 return NT_STATUS_LDAP(rc);
1586         }
1587
1588         if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1589                 DEBUG(0, ("Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s\n",
1590                           ldb_errstring(state->ldb)));
1591                 talloc_free(tmp_ctx);
1592                 return NT_STATUS_INTERNAL_ERROR;
1593         }
1594
1595         talloc_free(tmp_ctx);
1596         return NT_STATUS_OK;
1597 }
1598
1599 #if 0
1600 static NTSTATUS pdb_samba_dsdb_set_aliasinfo(struct pdb_methods *m,
1601                                       const struct dom_sid *sid,
1602                                       struct acct_info *info)
1603 {
1604         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1605                 m->private_data, struct pdb_samba_dsdb_state);
1606         struct tldap_context *ld;
1607         const char *attrs[3] = { "objectSid", "description",
1608                                  "samAccountName" };
1609         struct ldb_message **msg;
1610         char *sidstr, *dn;
1611         int rc;
1612         struct tldap_mod *mods;
1613         int num_mods;
1614         bool ok;
1615
1616         ld = pdb_samba_dsdb_ld(state);
1617         if (ld == NULL) {
1618                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1619         }
1620
1621         sidstr = sid_binstring(talloc_tos(), sid);
1622         NT_STATUS_HAVE_NO_MEMORY(sidstr);
1623
1624         rc = pdb_samba_dsdb_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1625                                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1626                                 &msg, "(&(objectSid=%s)(objectclass=group)"
1627                                 "(|(grouptype=%d)(grouptype=%d)))",
1628                                 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1629                                 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1630         TALLOC_FREE(sidstr)
1631         if (rc != LDB_SUCCESS) {
1632                 DEBUG(10, ("ldap_search failed %s\n",
1633                            ldb_errstring(state->ldb)));
1634                 return NT_STATUS_LDAP(rc);
1635         }
1636         switch talloc_array_length(msg) {
1637         case 0:
1638                 return NT_STATUS_NO_SUCH_ALIAS;
1639         case 1:
1640                 break;
1641         default:
1642                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1643         }
1644
1645         if (!tldap_entry_dn(msg[0], &dn)) {
1646                 TALLOC_FREE(msg);
1647                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1648         }
1649
1650         mods = NULL;
1651         num_mods = 0;
1652         ok = true;
1653
1654         ok &= tldap_make_mod_fmt(
1655                 msg[0], msg, &num_mods, &mods, "description",
1656                 "%s", info->acct_desc);
1657         ok &= tldap_make_mod_fmt(
1658                 msg[0], msg, &num_mods, &mods, "samAccountName",
1659                 "%s", info->acct_name);
1660         if (!ok) {
1661                 TALLOC_FREE(msg);
1662                 return NT_STATUS_NO_MEMORY;
1663         }
1664         if (num_mods == 0) {
1665                 /* no change */
1666                 TALLOC_FREE(msg);
1667                 return NT_STATUS_OK;
1668         }
1669
1670         rc = tldap_modify(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
1671         TALLOC_FREE(msg);
1672         if (rc != LDB_SUCCESS) {
1673                 DEBUG(10, ("ldap_modify failed: %s\n",
1674                            ldb_errstring(state->ldb)));
1675                 return NT_STATUS_LDAP(rc);
1676         }
1677         return NT_STATUS_OK;
1678 }
1679 #endif
1680 static NTSTATUS pdb_samba_dsdb_add_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_ADD);
1687         talloc_free(frame);
1688         return status;
1689 }
1690
1691 static NTSTATUS pdb_samba_dsdb_del_aliasmem(struct pdb_methods *m,
1692                                      const struct dom_sid *alias,
1693                                      const struct dom_sid *member)
1694 {
1695         NTSTATUS status;
1696         TALLOC_CTX *frame = talloc_stackframe();
1697         status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
1698         talloc_free(frame);
1699         return status;
1700 }
1701
1702 static NTSTATUS pdb_samba_dsdb_enum_aliasmem(struct pdb_methods *m,
1703                                       const struct dom_sid *alias,
1704                                       TALLOC_CTX *mem_ctx,
1705                                       struct dom_sid **pmembers,
1706                                       size_t *pnum_members)
1707 {
1708         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1709                 m->private_data, struct pdb_samba_dsdb_state);
1710         struct ldb_dn *dn;
1711         unsigned int num_members;
1712         NTSTATUS status;
1713         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1714         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1715
1716         dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, alias));
1717         if (!dn || !ldb_dn_validate(dn)) {
1718                 return NT_STATUS_NO_MEMORY;
1719         }
1720
1721         status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
1722         *pnum_members = num_members;
1723         if (NT_STATUS_IS_OK(status)) {
1724                 talloc_steal(mem_ctx, pmembers);
1725         }
1726         talloc_free(tmp_ctx);
1727         return status;
1728 }
1729
1730 static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1731                                                TALLOC_CTX *mem_ctx,
1732                                                const struct dom_sid *domain_sid,
1733                                                const struct dom_sid *members,
1734                                                size_t num_members,
1735                                                uint32_t **palias_rids,
1736                                                size_t *pnum_alias_rids)
1737 {
1738         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1739                 m->private_data, struct pdb_samba_dsdb_state);
1740         uint32_t *alias_rids = NULL;
1741         size_t num_alias_rids = 0;
1742         int i;
1743         struct dom_sid *groupSIDs = NULL;
1744         unsigned int num_groupSIDs = 0;
1745         char *filter;
1746         NTSTATUS status;
1747         const char *sid_string;
1748         const char *sid_dn;
1749         DATA_BLOB sid_blob;
1750
1751         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1752         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1753         /*
1754          * TODO: Get the filter right so that we only get the aliases from
1755          * either the SAM or BUILTIN
1756          */
1757
1758         filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
1759                                  GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1760         if (filter == NULL) {
1761                 return NT_STATUS_NO_MEMORY;
1762         }
1763
1764         for (i = 0; i < num_members; i++) {
1765                 sid_string = dom_sid_string(tmp_ctx, &members[i]);
1766                 if (sid_string == NULL) {
1767                         TALLOC_FREE(tmp_ctx);
1768                         return NT_STATUS_NO_MEMORY;
1769                 }
1770
1771                 sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", sid_string);
1772                 if (sid_dn == NULL) {
1773                         TALLOC_FREE(tmp_ctx);
1774                         return NT_STATUS_NO_MEMORY;
1775                 }
1776
1777                 sid_blob = data_blob_string_const(sid_dn);
1778
1779                 status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1780                                                    tmp_ctx, &groupSIDs, &num_groupSIDs);
1781                 if (!NT_STATUS_IS_OK(status)) {
1782                         talloc_free(tmp_ctx);
1783                         return status;
1784                 }
1785         }
1786
1787         alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1788         if (alias_rids == NULL) {
1789                 talloc_free(tmp_ctx);
1790                 return NT_STATUS_NO_MEMORY;
1791         }
1792
1793         for (i=0; i<num_groupSIDs; i++) {
1794                 if (sid_peek_check_rid(domain_sid, &groupSIDs[i],
1795                                        &alias_rids[num_alias_rids])) {
1796                         num_alias_rids++;;
1797                 }
1798         }
1799
1800         *palias_rids = alias_rids;
1801         *pnum_alias_rids = num_alias_rids;
1802         return NT_STATUS_OK;
1803 }
1804
1805 static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1806                                     const struct dom_sid *domain_sid,
1807                                     int num_rids,
1808                                     uint32_t *rids,
1809                                     const char **names,
1810                                     enum lsa_SidType *lsa_attrs)
1811 {
1812         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1813                 m->private_data, struct pdb_samba_dsdb_state);
1814         NTSTATUS status;
1815
1816         TALLOC_CTX *tmp_ctx;
1817
1818         if (num_rids == 0) {
1819                 return NT_STATUS_NONE_MAPPED;
1820         }
1821
1822         tmp_ctx = talloc_stackframe();
1823         NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1824
1825         status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1826         talloc_free(tmp_ctx);
1827         return status;
1828 }
1829
1830 static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1831                                      const struct dom_sid *domain_sid,
1832                                      int num_names,
1833                                      const char **pp_names,
1834                                      uint32_t *rids,
1835                                      enum lsa_SidType *attrs)
1836 {
1837         return NT_STATUS_NOT_IMPLEMENTED;
1838 }
1839
1840 static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1841                                            enum pdb_policy_type type,
1842                                            uint32_t *value)
1843 {
1844         return account_policy_get(type, value)
1845                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1846 }
1847
1848 static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1849                                            enum pdb_policy_type type,
1850                                            uint32_t value)
1851 {
1852         return account_policy_set(type, value)
1853                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1854 }
1855
1856 static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1857                                     time_t *seq_num_out)
1858 {
1859         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1860                 m->private_data, struct pdb_samba_dsdb_state);
1861         uint64_t seq_num;
1862         int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1863         if (ret == LDB_SUCCESS) {
1864                 *seq_num_out = seq_num;
1865                 return NT_STATUS_OK;
1866         } else {
1867                 return NT_STATUS_UNSUCCESSFUL;
1868         }
1869 }
1870
1871 struct pdb_samba_dsdb_search_state {
1872         uint32_t acct_flags;
1873         struct samr_displayentry *entries;
1874         uint32_t num_entries;
1875         ssize_t array_size;
1876         uint32_t current;
1877 };
1878
1879 static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1880                                struct samr_displayentry *entry)
1881 {
1882         struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1883                 search->private_data, struct pdb_samba_dsdb_search_state);
1884
1885         if (state->current == state->num_entries) {
1886                 return false;
1887         }
1888
1889         entry->idx = state->entries[state->current].idx;
1890         entry->rid = state->entries[state->current].rid;
1891         entry->acct_flags = state->entries[state->current].acct_flags;
1892
1893         entry->account_name = talloc_strdup(
1894                 search, state->entries[state->current].account_name);
1895         entry->fullname = talloc_strdup(
1896                 search, state->entries[state->current].fullname);
1897         entry->description = talloc_strdup(
1898                 search, state->entries[state->current].description);
1899
1900         state->current += 1;
1901         return true;
1902 }
1903
1904 static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1905 {
1906         struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1907                 search->private_data, struct pdb_samba_dsdb_search_state);
1908         talloc_free(state);
1909 }
1910
1911 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1912                                          struct pdb_search *search,
1913                                          struct pdb_samba_dsdb_search_state **pstate,
1914                                          const char *exp_fmt, ...)
1915                                          PRINTF_ATTRIBUTE(4, 5);
1916
1917 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1918                                      struct pdb_search *search,
1919                                      struct pdb_samba_dsdb_search_state **pstate,
1920                                      const char *exp_fmt, ...)
1921 {
1922         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1923                 m->private_data, struct pdb_samba_dsdb_state);
1924         struct pdb_samba_dsdb_search_state *sstate;
1925         const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1926                                  "userAccountControl", "description", NULL };
1927         struct ldb_result *res;
1928         int i, rc, num_users;
1929
1930         va_list ap;
1931         char *expression = NULL;
1932
1933         TALLOC_CTX *tmp_ctx = talloc_stackframe();
1934         if (!tmp_ctx) {
1935                 return false;
1936         }
1937
1938         va_start(ap, exp_fmt);
1939         expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1940         va_end(ap);
1941
1942         if (!expression) {
1943                 talloc_free(tmp_ctx);
1944                 return LDB_ERR_OPERATIONS_ERROR;
1945         }
1946
1947         sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1948         if (sstate == NULL) {
1949                 talloc_free(tmp_ctx);
1950                 return false;
1951         }
1952
1953         rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1954         if (rc != LDB_SUCCESS) {
1955                 talloc_free(tmp_ctx);
1956                 DEBUG(10, ("dsdb_search failed: %s\n",
1957                            ldb_errstring(state->ldb)));
1958                 return false;
1959         }
1960
1961         num_users = res->count;
1962
1963         sstate->entries = talloc_array(sstate, struct samr_displayentry,
1964                                        num_users);
1965         if (sstate->entries == NULL) {
1966                 talloc_free(tmp_ctx);
1967                 DEBUG(10, ("talloc failed\n"));
1968                 return false;
1969         }
1970
1971         sstate->num_entries = 0;
1972
1973         for (i=0; i<num_users; i++) {
1974                 struct samr_displayentry *e;
1975                 struct dom_sid *sid;
1976
1977                 e = &sstate->entries[sstate->num_entries];
1978
1979                 e->idx = sstate->num_entries;
1980                 sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
1981                 if (!sid) {
1982                         talloc_free(tmp_ctx);
1983                         DEBUG(10, ("Could not pull SID\n"));
1984                         return false;
1985                 }
1986                 sid_peek_rid(sid, &e->rid);
1987
1988                 e->acct_flags = samdb_result_acct_flags(res->msgs[i], "userAccountControl");
1989                 e->account_name = ldb_msg_find_attr_as_string(
1990                         res->msgs[i], "samAccountName", NULL);
1991                 if (e->account_name == NULL) {
1992                         talloc_free(tmp_ctx);
1993                         return false;
1994                 }
1995                 e->fullname = ldb_msg_find_attr_as_string(
1996                         res->msgs[i], "displayName", "");
1997                 e->description = ldb_msg_find_attr_as_string(
1998                         res->msgs[i], "description", "");
1999
2000                 sstate->num_entries += 1;
2001                 if (sstate->num_entries >= num_users) {
2002                         break;
2003                 }
2004         }
2005         talloc_steal(sstate->entries, res->msgs);
2006         search->private_data = talloc_steal(search, sstate);
2007         search->next_entry = pdb_samba_dsdb_next_entry;
2008         search->search_end = pdb_samba_dsdb_search_end;
2009         *pstate = sstate;
2010         talloc_free(tmp_ctx);
2011         return true;
2012 }
2013
2014 static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
2015                                  struct pdb_search *search,
2016                                  uint32_t acct_flags)
2017 {
2018         struct pdb_samba_dsdb_search_state *sstate;
2019         bool ret;
2020
2021         ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
2022         if (!ret) {
2023                 return false;
2024         }
2025         sstate->acct_flags = acct_flags;
2026         return true;
2027 }
2028
2029 static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
2030                                   struct pdb_search *search)
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                                        GTYPE_SECURITY_GLOBAL_GROUP);
2038         if (!ret) {
2039                 return false;
2040         }
2041         sstate->acct_flags = 0;
2042         return true;
2043 }
2044
2045 static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
2046                                    struct pdb_search *search,
2047                                    const struct dom_sid *sid)
2048 {
2049         struct pdb_samba_dsdb_search_state *sstate;
2050         bool ret;
2051
2052         ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2053                                        "(&(grouptype=%d)(objectclass=group))",
2054                                        sid_check_is_builtin(sid)
2055                                        ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2056                                        : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2057         if (!ret) {
2058                 return false;
2059         }
2060         sstate->acct_flags = 0;
2061         return true;
2062 }
2063
2064 /* 
2065  * Instead of taking a gid or uid, this function takes a pointer to a 
2066  * unixid. 
2067  *
2068  * This acts as an in-out variable so that the idmap functions can correctly
2069  * receive ID_TYPE_BOTH, and this function ensures cache details are filled
2070  * correctly rather than forcing the cache to store ID_TYPE_UID or ID_TYPE_GID. 
2071  */
2072 static bool pdb_samba_dsdb_id_to_sid(struct pdb_methods *m, struct unixid *id,
2073                                      struct dom_sid *sid)
2074 {
2075         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2076                 m->private_data, struct pdb_samba_dsdb_state);
2077         NTSTATUS status;
2078         struct id_map id_map;
2079         struct id_map *id_maps[2];
2080         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2081         if (!tmp_ctx) {
2082                 return false;
2083         }
2084
2085         id_map.xid = *id;
2086         id_maps[0] = &id_map;
2087         id_maps[1] = NULL;
2088
2089         status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2090         if (!NT_STATUS_IS_OK(status)) {
2091                 talloc_free(tmp_ctx);
2092                 return false;
2093         }
2094
2095         if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2096                 id->type = id_map.xid.type;
2097         }
2098         *sid = *id_map.sid;
2099         talloc_free(tmp_ctx);
2100         return true;
2101 }
2102
2103 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2104                                  struct unixid *id)
2105 {
2106         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2107                 m->private_data, struct pdb_samba_dsdb_state);
2108         struct id_map id_map;
2109         struct id_map *id_maps[2];
2110         NTSTATUS status;
2111         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2112         if (!tmp_ctx) {
2113                 return false;
2114         }
2115
2116         ZERO_STRUCT(id_map);
2117         id_map.sid = discard_const_p(struct dom_sid, sid);
2118         id_maps[0] = &id_map;
2119         id_maps[1] = NULL;
2120
2121         status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2122         talloc_free(tmp_ctx);
2123         if (!NT_STATUS_IS_OK(status)) {
2124                 return false;
2125         }
2126         if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2127                 *id = id_map.xid;
2128                 return true;
2129         }
2130         return false;
2131 }
2132
2133 static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2134 {
2135         return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
2136 }
2137
2138 static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32_t *rid)
2139 {
2140         return false;
2141 }
2142
2143 static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2144                                       const char *domain, char** pwd,
2145                                       struct dom_sid *sid,
2146                                       time_t *pass_last_set_time)
2147 {
2148         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2149                 m->private_data, struct pdb_samba_dsdb_state);
2150         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2151         const char * const attrs[] = {
2152                 "securityIdentifier",
2153                 "flatName",
2154                 "trustPartner",
2155                 "trustAuthOutgoing",
2156                 "whenCreated",
2157                 "msDS-SupportedEncryptionTypes",
2158                 "trustAttributes",
2159                 "trustDirection",
2160                 "trustType",
2161                 NULL
2162         };
2163         struct ldb_message *msg;
2164         const struct ldb_val *password_val;
2165         int trust_direction_flags;
2166         int trust_type;
2167         int i;
2168         DATA_BLOB password_utf16;
2169         struct trustAuthInOutBlob password_blob;
2170         struct AuthenticationInformationArray *auth_array;
2171         char *password_talloc;
2172         size_t password_len;
2173         enum ndr_err_code ndr_err;
2174         NTSTATUS status;
2175         const char *netbios_domain = NULL;
2176         const struct dom_sid *domain_sid = NULL;
2177
2178         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2179                                        attrs, tmp_ctx, &msg);
2180         if (!NT_STATUS_IS_OK(status)) {
2181                 /*
2182                  * This can be called to work out of a domain is
2183                  * trusted, rather than just to get the password
2184                  */
2185                 DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
2186                           "It may not be a trusted domain.\n", domain,
2187                           nt_errstr(status)));
2188                 TALLOC_FREE(tmp_ctx);
2189                 return false;
2190         }
2191
2192         netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2193         if (netbios_domain == NULL) {
2194                 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2195                           domain));
2196                 TALLOC_FREE(tmp_ctx);
2197                 return false;
2198         }
2199
2200         domain_sid = samdb_result_dom_sid(tmp_ctx, msg, "securityIdentifier");
2201         if (domain_sid == NULL) {
2202                 DEBUG(2, ("Trusted domain %s has no securityIdentifier defined.\n",
2203                           domain));
2204                 TALLOC_FREE(tmp_ctx);
2205                 return false;
2206         }
2207
2208         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2209         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2210                 DEBUG(2, ("Trusted domain %s is is not an outbound trust.\n",
2211                           domain));
2212                 TALLOC_FREE(tmp_ctx);
2213                 return false;
2214         }
2215
2216         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2217         if (trust_type == LSA_TRUST_TYPE_MIT) {
2218                 DEBUG(1, ("Trusted domain %s is is not an AD trust "
2219                           "(trustType == LSA_TRUST_TYPE_MIT).\n",
2220                           domain));
2221                 TALLOC_FREE(tmp_ctx);
2222                 return false;
2223         }
2224
2225         password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2226         if (password_val == NULL) {
2227                 DEBUG(2, ("Failed to get trusted domain password for %s, "
2228                           "attribute trustAuthOutgoing not returned.\n", domain));
2229                 TALLOC_FREE(tmp_ctx);
2230                 return false;
2231         }
2232
2233         ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2234                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2235         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2236                 DEBUG(0, ("Failed to get trusted domain password for %s, "
2237                           "attribute trustAuthOutgoing coult not be parsed %s.\n",
2238                           domain,
2239                           ndr_map_error2string(ndr_err)));
2240                 TALLOC_FREE(tmp_ctx);
2241                 return false;
2242         }
2243
2244         auth_array = &password_blob.current;
2245
2246         for (i=0; i < auth_array->count; i++) {
2247                 if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
2248                         break;
2249                 }
2250         }
2251
2252         if (i == auth_array->count) {
2253                 DEBUG(0, ("Trusted domain %s does not have a "
2254                           "clear-text password stored\n",
2255                           domain));
2256                 TALLOC_FREE(tmp_ctx);
2257                 return false;
2258         }
2259
2260         password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
2261                                          auth_array->array[i].AuthInfo.clear.size);
2262
2263         /*
2264          * In the future, make this function return a
2265          * cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash()
2266          * but for now convert to UTF8 and fail if the string can not be converted.
2267          *
2268          * We can't safely convert the random strings windows uses into
2269          * utf8.
2270          */
2271         if (!convert_string_talloc(tmp_ctx,
2272                                    CH_UTF16MUNGED, CH_UTF8,
2273                                    password_utf16.data, password_utf16.length,
2274                                    (void *)&password_talloc,
2275                                    &password_len)) {
2276                 DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
2277                           " to UTF8. This may be a password set from Windows.\n",
2278                           domain));
2279                 TALLOC_FREE(tmp_ctx);
2280                 return false;
2281         }
2282         *pwd = SMB_STRNDUP(password_talloc, password_len);
2283         if (pass_last_set_time) {
2284                 *pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
2285         }
2286
2287         if (sid != NULL) {
2288                 sid_copy(sid, domain_sid);
2289         }
2290
2291         TALLOC_FREE(tmp_ctx);
2292         return true;
2293 }
2294
2295 static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
2296                                                     const char *domain,
2297                                                     TALLOC_CTX *mem_ctx,
2298                                                     struct cli_credentials **_creds)
2299 {
2300         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2301                 m->private_data, struct pdb_samba_dsdb_state);
2302         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2303         const char * const attrs[] = {
2304                 "securityIdentifier",
2305                 "flatName",
2306                 "trustPartner",
2307                 "trustAuthOutgoing",
2308                 "whenCreated",
2309                 "msDS-SupportedEncryptionTypes",
2310                 "trustAttributes",
2311                 "trustDirection",
2312                 "trustType",
2313                 NULL
2314         };
2315         struct ldb_message *msg;
2316         const struct ldb_val *password_val;
2317         int trust_direction_flags;
2318         int trust_type;
2319         int i;
2320         DATA_BLOB password_utf16 = {};
2321         struct samr_Password *password_nt = NULL;
2322         uint32_t password_version = 0;
2323         DATA_BLOB old_password_utf16 = {};
2324         struct samr_Password *old_password_nt = NULL;
2325         struct trustAuthInOutBlob password_blob;
2326         enum ndr_err_code ndr_err;
2327         NTSTATUS status;
2328         time_t last_set_time = 0;
2329         struct cli_credentials *creds = NULL;
2330         bool ok;
2331         const char *my_netbios_name = NULL;
2332         const char *my_netbios_domain = NULL;
2333         const char *my_dns_domain = NULL;
2334         const char *netbios_domain = NULL;
2335         char *account_name = NULL;
2336         char *principal_name = NULL;
2337         const char *dns_domain = NULL;
2338
2339         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2340                                        attrs, tmp_ctx, &msg);
2341         if (!NT_STATUS_IS_OK(status)) {
2342                 /*
2343                  * This can be called to work out of a domain is
2344                  * trusted, rather than just to get the password
2345                  */
2346                 DEBUG(2, ("Failed to get trusted domain password for %s - %s "
2347                           "It may not be a trusted domain.\n", domain,
2348                           nt_errstr(status)));
2349                 TALLOC_FREE(tmp_ctx);
2350                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2351         }
2352
2353         netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2354         if (netbios_domain == NULL) {
2355                 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2356                           domain));
2357                 TALLOC_FREE(tmp_ctx);
2358                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2359         }
2360
2361         dns_domain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2362
2363         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2364         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2365                 DEBUG(2, ("Trusted domain %s is is not an outbound trust.\n",
2366                           domain));
2367                 TALLOC_FREE(tmp_ctx);
2368                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2369         }
2370
2371         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2372         if (trust_type == LSA_TRUST_TYPE_MIT) {
2373                 DEBUG(1, ("Trusted domain %s is is not an AD trust "
2374                           "(trustType == LSA_TRUST_TYPE_MIT).\n",
2375                           domain));
2376                 TALLOC_FREE(tmp_ctx);
2377                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2378         }
2379
2380         password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2381         if (password_val == NULL) {
2382                 DEBUG(2, ("Failed to get trusted domain password for %s, "
2383                           "attribute trustAuthOutgoing not returned.\n", domain));
2384                 TALLOC_FREE(tmp_ctx);
2385                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2386         }
2387
2388         ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2389                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2390         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2391                 DEBUG(0, ("Failed to get trusted domain password for %s, "
2392                           "attribute trustAuthOutgoing coult not be parsed %s.\n",
2393                           domain,
2394                           ndr_map_error2string(ndr_err)));
2395                 TALLOC_FREE(tmp_ctx);
2396                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2397         }
2398
2399         for (i=0; i < password_blob.current.count; i++) {
2400                 struct AuthenticationInformation *a =
2401                         &password_blob.current.array[i];
2402
2403                 switch (a->AuthType) {
2404                 case TRUST_AUTH_TYPE_NONE:
2405                         break;
2406
2407                 case TRUST_AUTH_TYPE_VERSION:
2408                         password_version = a->AuthInfo.version.version;
2409                         break;
2410
2411                 case TRUST_AUTH_TYPE_CLEAR:
2412                         last_set_time = nt_time_to_unix(a->LastUpdateTime);
2413
2414                         password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2415                                                          a->AuthInfo.clear.size);
2416                         password_nt = NULL;
2417                         break;
2418
2419                 case TRUST_AUTH_TYPE_NT4OWF:
2420                         if (password_utf16.length != 0) {
2421                                 break;
2422                         }
2423
2424                         last_set_time = nt_time_to_unix(a->LastUpdateTime);
2425
2426                         password_nt = &a->AuthInfo.nt4owf.password;
2427                         break;
2428                 }
2429         }
2430
2431         for (i=0; i < password_blob.previous.count; i++) {
2432                 struct AuthenticationInformation *a = &password_blob.previous.array[i];
2433
2434                 switch (a->AuthType) {
2435                 case TRUST_AUTH_TYPE_NONE:
2436                         break;
2437
2438                 case TRUST_AUTH_TYPE_VERSION:
2439                         break;
2440
2441                 case TRUST_AUTH_TYPE_CLEAR:
2442                         old_password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2443                                                          a->AuthInfo.clear.size);
2444                         old_password_nt = NULL;
2445                         break;
2446
2447                 case TRUST_AUTH_TYPE_NT4OWF:
2448                         if (old_password_utf16.length != 0) {
2449                                 break;
2450                         }
2451
2452                         old_password_nt = &a->AuthInfo.nt4owf.password;
2453                         break;
2454                 }
2455         }
2456
2457         if (password_utf16.length == 0 && password_nt == NULL) {
2458                 DEBUG(0, ("Trusted domain %s does not have a "
2459                           "clear-text nor nt password stored\n",
2460                           domain));
2461                 TALLOC_FREE(tmp_ctx);
2462                 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2463         }
2464
2465         my_netbios_name = lpcfg_netbios_name(state->lp_ctx);
2466         my_netbios_domain = lpcfg_workgroup(state->lp_ctx);
2467         my_dns_domain = lpcfg_dnsdomain(state->lp_ctx);
2468
2469         creds = cli_credentials_init(tmp_ctx);
2470         if (creds == NULL) {
2471                 TALLOC_FREE(tmp_ctx);
2472                 return NT_STATUS_NO_MEMORY;
2473         }
2474
2475         ok = cli_credentials_set_workstation(creds, my_netbios_name, CRED_SPECIFIED);
2476         if (!ok) {
2477                 TALLOC_FREE(tmp_ctx);
2478                 return NT_STATUS_NO_MEMORY;
2479         }
2480
2481         ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2482         if (!ok) {
2483                 TALLOC_FREE(tmp_ctx);
2484                 return NT_STATUS_NO_MEMORY;
2485         }
2486         ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2487         if (!ok) {
2488                 TALLOC_FREE(tmp_ctx);
2489                 return NT_STATUS_NO_MEMORY;
2490         }
2491
2492         if (my_dns_domain != NULL && dns_domain != NULL) {
2493                 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DNS_DOMAIN);
2494                 account_name = talloc_asprintf(tmp_ctx, "%s.", my_dns_domain);
2495                 if (account_name == NULL) {
2496                         TALLOC_FREE(tmp_ctx);
2497                         return NT_STATUS_NO_MEMORY;
2498                 }
2499                 principal_name = talloc_asprintf(tmp_ctx, "%s$@%s", my_netbios_domain,
2500                                                  cli_credentials_get_realm(creds));
2501                 if (principal_name == NULL) {
2502                         TALLOC_FREE(tmp_ctx);
2503                         return NT_STATUS_NO_MEMORY;
2504                 }
2505         } else {
2506                 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DOMAIN);
2507                 account_name = talloc_asprintf(tmp_ctx, "%s$", my_netbios_domain);
2508                 if (account_name == NULL) {
2509                         TALLOC_FREE(tmp_ctx);
2510                         return NT_STATUS_NO_MEMORY;
2511                 }
2512                 principal_name = NULL;
2513         }
2514
2515         ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2516         if (!ok) {
2517                 TALLOC_FREE(tmp_ctx);
2518                 return NT_STATUS_NO_MEMORY;
2519         }
2520
2521         if (principal_name != NULL) {
2522                 ok = cli_credentials_set_principal(creds, principal_name,
2523                                                    CRED_SPECIFIED);
2524                 if (!ok) {
2525                         TALLOC_FREE(tmp_ctx);
2526                         return NT_STATUS_NO_MEMORY;
2527                 }
2528         }
2529
2530         if (old_password_nt != NULL) {
2531                 ok = cli_credentials_set_old_nt_hash(creds, old_password_nt);
2532                 if (!ok) {
2533                         TALLOC_FREE(tmp_ctx);
2534                         return NT_STATUS_NO_MEMORY;
2535                 }
2536         }
2537
2538         if (old_password_utf16.length > 0) {
2539                 ok = cli_credentials_set_old_utf16_password(creds,
2540                                                             &old_password_utf16);
2541                 if (!ok) {
2542                         TALLOC_FREE(tmp_ctx);
2543                         return NT_STATUS_NO_MEMORY;
2544                 }
2545         }
2546
2547         if (password_nt != NULL) {
2548                 ok = cli_credentials_set_nt_hash(creds, password_nt,
2549                                                  CRED_SPECIFIED);
2550                 if (!ok) {
2551                         TALLOC_FREE(tmp_ctx);
2552                         return NT_STATUS_NO_MEMORY;
2553                 }
2554         }
2555
2556         if (password_utf16.length > 0) {
2557                 ok = cli_credentials_set_utf16_password(creds,
2558                                                         &password_utf16,
2559                                                         CRED_SPECIFIED);
2560                 if (!ok) {
2561                         TALLOC_FREE(tmp_ctx);
2562                         return NT_STATUS_NO_MEMORY;
2563                 }
2564         }
2565
2566         cli_credentials_set_password_last_changed_time(creds, last_set_time);
2567         cli_credentials_set_kvno(creds, password_version);
2568
2569         if (password_utf16.length > 0 && dns_domain != NULL) {
2570                 /*
2571                  * Force kerberos if this is an active directory domain
2572                  */
2573                 cli_credentials_set_kerberos_state(creds,
2574                                                    CRED_MUST_USE_KERBEROS);
2575         } else  {
2576                 /*
2577                  * TODO: we should allow krb5 with the raw nt hash.
2578                  */
2579                 cli_credentials_set_kerberos_state(creds,
2580                                                    CRED_DONT_USE_KERBEROS);
2581         }
2582
2583         *_creds = talloc_move(mem_ctx, &creds);
2584         TALLOC_FREE(tmp_ctx);
2585         return NT_STATUS_OK;
2586 }
2587
2588 static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2589                                       const char* domain, const char* pwd,
2590                                       const struct dom_sid *sid)
2591 {
2592         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2593                 m->private_data, struct pdb_samba_dsdb_state);
2594         TALLOC_CTX *tmp_ctx = talloc_stackframe();
2595         const char * const attrs[] = {
2596                 "trustAuthOutgoing",
2597                 "trustDirection",
2598                 "trustType",
2599                 NULL
2600         };
2601         struct ldb_message *msg = NULL;
2602         int trust_direction_flags;
2603         int trust_type;
2604         int i;
2605         const struct ldb_val *old_val = NULL;
2606         struct trustAuthInOutBlob old_blob = {};
2607         uint32_t old_version = 0;
2608         uint32_t new_version = 0;
2609         DATA_BLOB new_utf16 = {};
2610         struct trustAuthInOutBlob new_blob = {};
2611         struct ldb_val new_val = {};
2612         struct timeval tv = timeval_current();
2613         NTTIME now = timeval_to_nttime(&tv);
2614         enum ndr_err_code ndr_err;
2615         NTSTATUS status;
2616         bool ok;
2617         int ret;
2618
2619         ret = ldb_transaction_start(state->ldb);
2620         if (ret != LDB_SUCCESS) {
2621                 DEBUG(2, ("Failed to start transaction.\n"));
2622                 TALLOC_FREE(tmp_ctx);
2623                 return false;
2624         }
2625
2626         ok = samdb_is_pdc(state->ldb);
2627         if (!ok) {
2628                 DEBUG(2, ("Password changes for domain %s are only allowed on a PDC.\n",
2629                           domain));
2630                 TALLOC_FREE(tmp_ctx);
2631                 ldb_transaction_cancel(state->ldb);
2632                 return false;
2633         }
2634
2635         status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2636                                        attrs, tmp_ctx, &msg);
2637         if (!NT_STATUS_IS_OK(status)) {
2638                 /*
2639                  * This can be called to work out of a domain is
2640                  * trusted, rather than just to get the password
2641                  */
2642                 DEBUG(2, ("Failed to get trusted domain password for %s - %s.  "
2643                           "It may not be a trusted domain.\n", domain,
2644                           nt_errstr(status)));
2645                 TALLOC_FREE(tmp_ctx);
2646                 ldb_transaction_cancel(state->ldb);
2647                 return false;
2648         }
2649
2650         trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2651         if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2652                 DEBUG(2, ("Trusted domain %s is is not an outbound trust, can't set a password.\n",
2653                           domain));
2654                 TALLOC_FREE(tmp_ctx);
2655                 ldb_transaction_cancel(state->ldb);
2656                 return false;
2657         }
2658
2659         trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2660         switch (trust_type) {
2661         case LSA_TRUST_TYPE_DOWNLEVEL:
2662         case LSA_TRUST_TYPE_UPLEVEL:
2663                 break;
2664         default:
2665                 DEBUG(0, ("Trusted domain %s is of type 0x%X - "
2666                           "password changes are not supported\n",
2667                           domain, (unsigned)trust_type));
2668                 TALLOC_FREE(tmp_ctx);
2669                 ldb_transaction_cancel(state->ldb);
2670                 return false;
2671         }
2672
2673         old_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2674         if (old_val != NULL) {
2675                 ndr_err = ndr_pull_struct_blob(old_val, tmp_ctx, &old_blob,
2676                                 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2677                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2678                         DEBUG(0, ("Failed to get trusted domain password for %s, "
2679                                   "attribute trustAuthOutgoing coult not be parsed %s.\n",
2680                                   domain,
2681                                   ndr_map_error2string(ndr_err)));
2682                         TALLOC_FREE(tmp_ctx);
2683                         ldb_transaction_cancel(state->ldb);
2684                         return false;
2685                 }
2686         }
2687
2688         for (i=0; i < old_blob.current.count; i++) {
2689                 struct AuthenticationInformation *a =
2690                         &old_blob.current.array[i];
2691
2692                 switch (a->AuthType) {
2693                 case TRUST_AUTH_TYPE_NONE:
2694                         break;
2695
2696                 case TRUST_AUTH_TYPE_VERSION:
2697                         old_version = a->AuthInfo.version.version;
2698                         break;
2699
2700                 case TRUST_AUTH_TYPE_CLEAR:
2701                         break;
2702
2703                 case TRUST_AUTH_TYPE_NT4OWF:
2704                         break;
2705                 }
2706         }
2707
2708         new_version = old_version + 1;
2709         ok = convert_string_talloc(tmp_ctx,
2710                                    CH_UNIX, CH_UTF16,
2711                                    pwd, strlen(pwd),
2712                                    (void *)&new_utf16.data,
2713                                    &new_utf16.length);
2714         if (!ok) {
2715                 DEBUG(0, ("Failed to generate new_utf16 password for  domain %s\n",
2716                           domain));
2717                 TALLOC_FREE(tmp_ctx);
2718                 ldb_transaction_cancel(state->ldb);
2719                 return false;
2720         }
2721
2722         if (new_utf16.length < 28) {
2723                 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to short.\n",
2724                           new_utf16.length,
2725                           (unsigned)new_version,
2726                           domain));
2727                 TALLOC_FREE(tmp_ctx);
2728                 ldb_transaction_cancel(state->ldb);
2729                 return false;
2730         }
2731         if (new_utf16.length > 498) {
2732                 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to long.\n",
2733                           new_utf16.length,
2734                           (unsigned)new_version,
2735                           domain));
2736                 TALLOC_FREE(tmp_ctx);
2737                 ldb_transaction_cancel(state->ldb);
2738                 return false;
2739         }
2740
2741         new_blob.count = MAX(old_blob.current.count, 2);
2742         new_blob.current.array = talloc_zero_array(tmp_ctx,
2743                                         struct AuthenticationInformation,
2744                                         new_blob.count);
2745         if (new_blob.current.array == NULL) {
2746                 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2747                           (unsigned)new_blob.count));
2748                 TALLOC_FREE(tmp_ctx);
2749                 ldb_transaction_cancel(state->ldb);
2750                 return false;
2751         }
2752         new_blob.previous.array = talloc_zero_array(tmp_ctx,
2753                                         struct AuthenticationInformation,
2754                                         new_blob.count);
2755         if (new_blob.current.array == NULL) {
2756                 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2757                           (unsigned)new_blob.count));
2758                 TALLOC_FREE(tmp_ctx);
2759                 ldb_transaction_cancel(state->ldb);
2760                 return false;
2761         }
2762
2763         for (i = 0; i < old_blob.current.count; i++) {
2764                 struct AuthenticationInformation *o =
2765                         &old_blob.current.array[i];
2766                 struct AuthenticationInformation *p =
2767                         &new_blob.previous.array[i];
2768
2769                 *p = *o;
2770                 new_blob.previous.count++;
2771         }
2772         for (; i < new_blob.count; i++) {
2773                 struct AuthenticationInformation *pi =
2774                         &new_blob.previous.array[i];
2775
2776                 if (i == 0) {
2777                         /*
2778                          * new_blob.previous is still empty so
2779                          * we'll do new_blob.previous = new_blob.current
2780                          * below.
2781                          */
2782                         break;
2783                 }
2784
2785                 pi->LastUpdateTime = now;
2786                 pi->AuthType = TRUST_AUTH_TYPE_NONE;
2787                 new_blob.previous.count++;
2788         }
2789
2790         for (i = 0; i < new_blob.count; i++) {
2791                 struct AuthenticationInformation *ci =
2792                         &new_blob.current.array[i];
2793
2794                 ci->LastUpdateTime = now;
2795                 switch (i) {
2796                 case 0:
2797                         ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
2798                         ci->AuthInfo.clear.size = new_utf16.length;
2799                         ci->AuthInfo.clear.password = new_utf16.data;
2800                         break;
2801                 case 1:
2802                         ci->AuthType = TRUST_AUTH_TYPE_VERSION;
2803                         ci->AuthInfo.version.version = new_version;
2804                         break;
2805                 default:
2806                         ci->AuthType = TRUST_AUTH_TYPE_NONE;
2807                         break;
2808                 }
2809
2810                 new_blob.current.count++;
2811         }
2812
2813         if (new_blob.previous.count == 0) {
2814                 TALLOC_FREE(new_blob.previous.array);
2815                 new_blob.previous = new_blob.current;
2816         }
2817
2818         ndr_err = ndr_push_struct_blob(&new_val, tmp_ctx, &new_blob,
2819                         (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
2820         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2821                 DEBUG(0, ("Failed to generate trustAuthOutgoing for "
2822                           "trusted domain password for %s: %s.\n",
2823                           domain, ndr_map_error2string(ndr_err)));
2824                 TALLOC_FREE(tmp_ctx);
2825                 ldb_transaction_cancel(state->ldb);
2826                 return false;
2827         }
2828
2829         msg->num_elements = 0;
2830         ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2831                                 LDB_FLAG_MOD_REPLACE, NULL);
2832         if (ret != LDB_SUCCESS) {
2833                 DEBUG(0, ("ldb_msg_add_empty() failed\n"));
2834                 TALLOC_FREE(tmp_ctx);
2835                 ldb_transaction_cancel(state->ldb);
2836                 return false;
2837         }
2838         ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2839                                 &new_val, NULL);
2840         if (ret != LDB_SUCCESS) {
2841                 DEBUG(0, ("ldb_msg_add_value() failed\n"));
2842                 TALLOC_FREE(tmp_ctx);
2843                 ldb_transaction_cancel(state->ldb);
2844                 return false;
2845         }
2846
2847         ret = ldb_modify(state->ldb, msg);
2848         if (ret != LDB_SUCCESS) {
2849                 DEBUG(0, ("Failed to replace trustAuthOutgoing for "
2850                           "trusted domain password for %s: %s - %s\n",
2851                           domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2852                 TALLOC_FREE(tmp_ctx);
2853                 ldb_transaction_cancel(state->ldb);
2854                 return false;
2855         }
2856
2857         ret = ldb_transaction_commit(state->ldb);
2858         if (ret != LDB_SUCCESS) {
2859                 DEBUG(0, ("Failed to commit trustAuthOutgoing for "
2860                           "trusted domain password for %s: %s - %s\n",
2861                           domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2862                 TALLOC_FREE(tmp_ctx);
2863                 return false;
2864         }
2865
2866         DEBUG(1, ("Added new_version[%u] to trustAuthOutgoing for "
2867                   "trusted domain password for %s.\n",
2868                   (unsigned)new_version, domain));
2869         TALLOC_FREE(tmp_ctx);
2870         return true;
2871 }
2872
2873 static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2874                                       const char *domain)
2875 {
2876         return false;
2877 }
2878
2879 static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2880                                          TALLOC_CTX *mem_ctx,
2881                                          uint32_t *num_domains,
2882                                          struct trustdom_info ***domains)
2883 {
2884         *num_domains = 0;
2885         *domains = NULL;
2886         return NT_STATUS_OK;
2887 }
2888
2889 static bool pdb_samba_dsdb_is_responsible_for_wellknown(struct pdb_methods *m)
2890 {
2891         return true;
2892 }
2893
2894 static bool pdb_samba_dsdb_is_responsible_for_everything_else(struct pdb_methods *m)
2895 {
2896         return true;
2897 }
2898
2899 static void pdb_samba_dsdb_init_methods(struct pdb_methods *m)
2900 {
2901         m->name = "samba_dsdb";
2902         m->get_domain_info = pdb_samba_dsdb_get_domain_info;
2903         m->getsampwnam = pdb_samba_dsdb_getsampwnam;
2904         m->getsampwsid = pdb_samba_dsdb_getsampwsid;
2905         m->create_user = pdb_samba_dsdb_create_user;
2906         m->delete_user = pdb_samba_dsdb_delete_user;
2907         m->add_sam_account = pdb_samba_dsdb_add_sam_account;
2908         m->update_sam_account = pdb_samba_dsdb_update_sam_account;
2909         m->delete_sam_account = pdb_samba_dsdb_delete_sam_account;
2910         m->rename_sam_account = pdb_samba_dsdb_rename_sam_account;
2911         m->update_login_attempts = pdb_samba_dsdb_update_login_attempts;
2912         m->getgrsid = pdb_samba_dsdb_getgrsid;
2913         m->getgrgid = pdb_samba_dsdb_getgrgid;
2914         m->getgrnam = pdb_samba_dsdb_getgrnam;
2915         m->create_dom_group = pdb_samba_dsdb_create_dom_group;
2916         m->delete_dom_group = pdb_samba_dsdb_delete_dom_group;
2917         m->add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry;
2918         m->update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry;
2919         m->delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry;
2920         m->enum_group_mapping = pdb_samba_dsdb_enum_group_mapping;
2921         m->enum_group_members = pdb_samba_dsdb_enum_group_members;
2922         m->enum_group_memberships = pdb_samba_dsdb_enum_group_memberships;
2923         m->set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group;
2924         m->add_groupmem = pdb_samba_dsdb_add_groupmem;
2925         m->del_groupmem = pdb_samba_dsdb_del_groupmem;
2926         m->create_alias = pdb_samba_dsdb_create_alias;
2927         m->delete_alias = pdb_samba_dsdb_delete_alias;
2928         m->get_aliasinfo = pdb_default_get_aliasinfo;
2929         m->add_aliasmem = pdb_samba_dsdb_add_aliasmem;
2930         m->del_aliasmem = pdb_samba_dsdb_del_aliasmem;
2931         m->enum_aliasmem = pdb_samba_dsdb_enum_aliasmem;
2932         m->enum_alias_memberships = pdb_samba_dsdb_enum_alias_memberships;
2933         m->lookup_rids = pdb_samba_dsdb_lookup_rids;
2934         m->lookup_names = pdb_samba_dsdb_lookup_names;
2935         m->get_account_policy = pdb_samba_dsdb_get_account_policy;
2936         m->set_account_policy = pdb_samba_dsdb_set_account_policy;
2937         m->get_seq_num = pdb_samba_dsdb_get_seq_num;
2938         m->search_users = pdb_samba_dsdb_search_users;
2939         m->search_groups = pdb_samba_dsdb_search_groups;
2940         m->search_aliases = pdb_samba_dsdb_search_aliases;
2941         m->id_to_sid = pdb_samba_dsdb_id_to_sid;
2942         m->sid_to_id = pdb_samba_dsdb_sid_to_id;
2943         m->capabilities = pdb_samba_dsdb_capabilities;
2944         m->new_rid = pdb_samba_dsdb_new_rid;
2945         m->get_trusteddom_pw = pdb_samba_dsdb_get_trusteddom_pw;
2946         m->get_trusteddom_creds = pdb_samba_dsdb_get_trusteddom_creds;
2947         m->set_trusteddom_pw = pdb_samba_dsdb_set_trusteddom_pw;
2948         m->del_trusteddom_pw = pdb_samba_dsdb_del_trusteddom_pw;
2949         m->enum_trusteddoms = pdb_samba_dsdb_enum_trusteddoms;
2950         m->is_responsible_for_wellknown =
2951                                 pdb_samba_dsdb_is_responsible_for_wellknown;
2952         m->is_responsible_for_everything_else =
2953                                 pdb_samba_dsdb_is_responsible_for_everything_else;
2954 }
2955
2956 static void free_private_data(void **vp)
2957 {
2958         struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2959                 *vp, struct pdb_samba_dsdb_state);
2960         talloc_unlink(state, state->ldb);
2961         return;
2962 }
2963
2964 static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m)
2965 {
2966         struct pdb_domain_info *dom_info;
2967         struct dom_sid stored_sid;
2968         struct GUID stored_guid;
2969         bool sid_exists_and_matches = false;
2970         bool guid_exists_and_matches = false;
2971         bool ret;
2972
2973         dom_info = pdb_samba_dsdb_get_domain_info(m, m);
2974         if (!dom_info) {
2975                 return NT_STATUS_UNSUCCESSFUL;
2976         }
2977
2978         ret = secrets_fetch_domain_sid(dom_info->name, &stored_sid);
2979         if (ret) {
2980                 if (dom_sid_equal(&stored_sid, &dom_info->sid)) {
2981                         sid_exists_and_matches = true;
2982                 }
2983         }
2984
2985         if (sid_exists_and_matches == false) {
2986                 secrets_clear_domain_protection(dom_info->name);
2987                 ret = secrets_store_domain_sid(dom_info->name,
2988                                                &dom_info->sid);
2989                 ret &= secrets_mark_domain_protected(dom_info->name);
2990                 if (!ret) {
2991                         goto done;
2992                 }
2993         }
2994
2995         ret = secrets_fetch_domain_guid(dom_info->name, &stored_guid);
2996         if (ret) {
2997                 if (GUID_equal(&stored_guid, &dom_info->guid)) {
2998                         guid_exists_and_matches = true;
2999                 }
3000         }
3001
3002         if (guid_exists_and_matches == false) {
3003                 secrets_clear_domain_protection(dom_info->name);
3004                 ret = secrets_store_domain_guid(dom_info->name,
3005                                                &dom_info->guid);
3006                 ret &= secrets_mark_domain_protected(dom_info->name);
3007                 if (!ret) {
3008                         goto done;
3009                 }
3010         }
3011
3012 done:
3013         TALLOC_FREE(dom_info);
3014         if (!ret) {
3015                 return NT_STATUS_UNSUCCESSFUL;
3016         }
3017         return NT_STATUS_OK;
3018 }
3019
3020 static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
3021                              const char *location)
3022 {
3023         struct pdb_methods *m;
3024         struct pdb_samba_dsdb_state *state;
3025         NTSTATUS status;
3026
3027         if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
3028                 return status;
3029         }
3030
3031         state = talloc_zero(m, struct pdb_samba_dsdb_state);
3032         if (state == NULL) {
3033                 goto nomem;
3034         }
3035         m->private_data = state;
3036         m->free_private_data = free_private_data;
3037         pdb_samba_dsdb_init_methods(m);
3038
3039         state->ev = s4_event_context_init(state);
3040         if (!state->ev) {
3041                 DEBUG(0, ("s4_event_context_init failed\n"));
3042                 goto nomem;
3043         }
3044
3045         state->lp_ctx = loadparm_init_s3(state, loadparm_s3_helpers());
3046         if (state->lp_ctx == NULL) {
3047                 DEBUG(0, ("loadparm_init_s3 failed\n"));
3048                 goto nomem;
3049         }
3050
3051         if (location) {
3052                 state->ldb = samdb_connect_url(state,
3053                                    state->ev,
3054                                    state->lp_ctx,
3055                                    system_session(state->lp_ctx),
3056                                    0, location);
3057         } else {
3058                 state->ldb = samdb_connect(state,
3059                                    state->ev,
3060                                    state->lp_ctx,
3061                                    system_session(state->lp_ctx), 0);
3062         }
3063
3064         if (!state->ldb) {
3065                 DEBUG(0, ("samdb_connect failed\n"));
3066                 status = NT_STATUS_INTERNAL_ERROR;
3067                 goto fail;
3068         }
3069
3070         state->idmap_ctx = idmap_init(state, state->ev,
3071                                       state->lp_ctx);
3072         if (!state->idmap_ctx) {
3073                 DEBUG(0, ("idmap failed\n"));
3074                 status = NT_STATUS_INTERNAL_ERROR;
3075                 goto fail;
3076         }
3077
3078         status = pdb_samba_dsdb_init_secrets(m);
3079         if (!NT_STATUS_IS_OK(status)) {
3080                 DEBUG(10, ("pdb_samba_dsdb_init_secrets failed!\n"));
3081                 goto fail;
3082         }
3083
3084         *pdb_method = m;
3085         return NT_STATUS_OK;
3086 nomem:
3087         status = NT_STATUS_NO_MEMORY;
3088 fail:
3089         TALLOC_FREE(m);
3090         return status;
3091 }
3092
3093 NTSTATUS pdb_samba_dsdb_init(void);
3094 NTSTATUS pdb_samba_dsdb_init(void)
3095 {
3096         NTSTATUS status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba_dsdb",
3097                                               pdb_init_samba_dsdb);
3098         if (!NT_STATUS_IS_OK(status)) {
3099                 return status;
3100         }
3101         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4",
3102                                    pdb_init_samba_dsdb);
3103 }