s3:libads: remove unused ads->auth.renewable
[Samba.git] / source3 / passdb / pdb_samba_dsdb.c
blobbc3fa743b08157c776f16450a7354d1a493e4ae3
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
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.
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.
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/>.
22 /* This module, is a port of Volker's pdb_ads to ldb and DSDB APIs */
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 #include "libcli/ldap/ldap_ndr.h"
44 #include "lib/util/util_ldb.h"
46 struct pdb_samba_dsdb_state {
47 struct tevent_context *ev;
48 struct ldb_context *ldb;
49 struct idmap_context *idmap_ctx;
50 struct loadparm_context *lp_ctx;
53 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
54 struct samu *sam_acct,
55 const struct dom_sid *sid);
56 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
57 const char *filter,
58 TALLOC_CTX *mem_ctx,
59 struct ldb_message **pmsg);
60 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
61 struct unixid *id);
63 static bool pdb_samba_dsdb_pull_time(struct ldb_message *msg, const char *attr,
64 time_t *ptime)
66 uint64_t tmp;
67 if (! ldb_msg_find_element(msg, attr)) {
68 return false;
70 tmp = ldb_msg_find_attr_as_uint64(msg, attr, 0);
71 *ptime = nt_time_to_unix(tmp);
72 return true;
75 static struct pdb_domain_info *pdb_samba_dsdb_get_domain_info(
76 struct pdb_methods *m, TALLOC_CTX *mem_ctx)
78 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
79 m->private_data, struct pdb_samba_dsdb_state);
80 struct pdb_domain_info *info;
81 struct dom_sid *domain_sid;
82 struct ldb_dn *forest_dn, *domain_dn;
83 struct ldb_result *dom_res = NULL;
84 const char *dom_attrs[] = {
85 "objectSid",
86 "objectGUID",
87 "fSMORoleOwner",
88 NULL
90 char *p;
91 int ret;
93 info = talloc(mem_ctx, struct pdb_domain_info);
94 if (info == NULL) {
95 return NULL;
98 domain_dn = ldb_get_default_basedn(state->ldb);
100 ret = ldb_search(state->ldb, info, &dom_res,
101 domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
102 if (ret != LDB_SUCCESS) {
103 goto fail;
105 if (dom_res->count != 1) {
106 goto fail;
109 info->guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
111 domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
112 if (!domain_sid) {
113 goto fail;
115 info->sid = *domain_sid;
117 TALLOC_FREE(dom_res);
119 info->name = talloc_strdup(info, lpcfg_sam_name(state->lp_ctx));
120 info->dns_domain = ldb_dn_canonical_string(info, domain_dn);
122 if (!info->dns_domain) {
123 goto fail;
125 p = strchr(info->dns_domain, '/');
126 if (p) {
127 *p = '\0';
130 forest_dn = ldb_get_root_basedn(state->ldb);
131 if (!forest_dn) {
132 goto fail;
135 info->dns_forest = ldb_dn_canonical_string(info, forest_dn);
136 if (!info->dns_forest) {
137 goto fail;
139 p = strchr(info->dns_forest, '/');
140 if (p) {
141 *p = '\0';
144 return info;
146 fail:
147 TALLOC_FREE(dom_res);
148 TALLOC_FREE(info);
149 return NULL;
152 static struct ldb_message *pdb_samba_dsdb_get_samu_private(
153 struct pdb_methods *m, struct samu *sam)
155 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
156 m->private_data, struct pdb_samba_dsdb_state);
157 struct ldb_message *msg;
158 struct dom_sid_buf sidstr;
159 char *filter;
160 NTSTATUS status;
162 msg = (struct ldb_message *)
163 pdb_get_backend_private_data(sam, m);
165 if (msg != NULL) {
166 return talloc_get_type_abort(msg, struct ldb_message);
169 filter = talloc_asprintf(
170 talloc_tos(),
171 "(&(objectsid=%s)(objectclass=user))",
172 dom_sid_str_buf(pdb_get_user_sid(sam), &sidstr));
173 if (filter == NULL) {
174 return NULL;
177 status = pdb_samba_dsdb_getsamupriv(state, filter, sam, &msg);
178 TALLOC_FREE(filter);
179 if (!NT_STATUS_IS_OK(status)) {
180 return NULL;
183 return msg;
186 static NTSTATUS pdb_samba_dsdb_init_sam_from_priv(struct pdb_methods *m,
187 struct samu *sam,
188 struct ldb_message *msg)
190 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
191 m->private_data, struct pdb_samba_dsdb_state);
192 TALLOC_CTX *frame = talloc_stackframe();
193 NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
194 const char *str;
195 time_t tmp_time;
196 struct dom_sid *sid, group_sid;
197 uint64_t n;
198 const DATA_BLOB *blob;
200 str = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
201 if (str == NULL) {
202 DEBUG(10, ("no samAccountName\n"));
203 goto fail;
205 pdb_set_username(sam, str, PDB_SET);
207 if (pdb_samba_dsdb_pull_time(msg, "lastLogon", &tmp_time)) {
208 pdb_set_logon_time(sam, tmp_time, PDB_SET);
210 if (pdb_samba_dsdb_pull_time(msg, "lastLogoff", &tmp_time)) {
211 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
213 if (pdb_samba_dsdb_pull_time(msg, "pwdLastSet", &tmp_time)) {
214 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
216 if (pdb_samba_dsdb_pull_time(msg, "accountExpires", &tmp_time)) {
217 pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
220 str = ldb_msg_find_attr_as_string(msg, "displayName",
221 NULL);
222 if (str != NULL) {
223 pdb_set_fullname(sam, str, PDB_SET);
226 str = ldb_msg_find_attr_as_string(msg, "homeDirectory",
227 NULL);
228 if (str != NULL) {
229 pdb_set_homedir(sam, str, PDB_SET);
232 str = ldb_msg_find_attr_as_string(msg, "homeDrive", NULL);
233 if (str != NULL) {
234 pdb_set_dir_drive(sam, str, PDB_SET);
237 str = ldb_msg_find_attr_as_string(msg, "scriptPath", NULL);
238 if (str != NULL) {
239 pdb_set_logon_script(sam, str, PDB_SET);
242 str = ldb_msg_find_attr_as_string(msg, "profilePath",
243 NULL);
244 if (str != NULL) {
245 pdb_set_profile_path(sam, str, PDB_SET);
248 str = ldb_msg_find_attr_as_string(msg, "comment",
249 NULL);
250 if (str != NULL) {
251 pdb_set_comment(sam, str, PDB_SET);
254 str = ldb_msg_find_attr_as_string(msg, "description",
255 NULL);
256 if (str != NULL) {
257 pdb_set_acct_desc(sam, str, PDB_SET);
260 str = ldb_msg_find_attr_as_string(msg, "userWorkstations",
261 NULL);
262 if (str != NULL) {
263 pdb_set_workstations(sam, str, PDB_SET);
266 blob = ldb_msg_find_ldb_val(msg, "userParameters");
267 if (blob != NULL) {
268 str = base64_encode_data_blob(frame, *blob);
269 if (str == NULL) {
270 DEBUG(0, ("base64_encode_data_blob() failed\n"));
271 goto fail;
273 pdb_set_munged_dial(sam, str, PDB_SET);
276 sid = samdb_result_dom_sid(talloc_tos(), msg, "objectSid");
277 if (!sid) {
278 DEBUG(10, ("Could not pull SID\n"));
279 goto fail;
281 pdb_set_user_sid(sam, sid, PDB_SET);
283 n = samdb_result_acct_flags(msg, "msDS-User-Account-Control-Computed");
284 if (n == 0) {
285 DEBUG(10, ("Could not pull userAccountControl\n"));
286 goto fail;
288 pdb_set_acct_ctrl(sam, n, PDB_SET);
290 blob = ldb_msg_find_ldb_val(msg, "unicodePwd");
291 if (blob) {
292 if (blob->length != NT_HASH_LEN) {
293 DEBUG(0, ("Got NT hash of length %d, expected %d\n",
294 (int)blob->length, NT_HASH_LEN));
295 goto fail;
297 pdb_set_nt_passwd(sam, blob->data, PDB_SET);
300 blob = ldb_msg_find_ldb_val(msg, "dBCSPwd");
301 if (blob) {
302 if (blob->length != LM_HASH_LEN) {
303 DEBUG(0, ("Got LM hash of length %d, expected %d\n",
304 (int)blob->length, LM_HASH_LEN));
305 goto fail;
307 pdb_set_lanman_passwd(sam, blob->data, PDB_SET);
310 n = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", 0);
311 if (n == 0) {
312 DEBUG(10, ("Could not pull primaryGroupID\n"));
313 goto fail;
315 sid_compose(&group_sid, samdb_domain_sid(state->ldb), n);
316 pdb_set_group_sid(sam, &group_sid, PDB_SET);
318 status = NT_STATUS_OK;
319 fail:
320 TALLOC_FREE(frame);
321 return status;
324 static bool pdb_samba_dsdb_add_time(struct ldb_message *msg,
325 const char *attrib, time_t t)
327 uint64_t nt_time;
329 unix_to_nt_time(&nt_time, t);
331 return ldb_msg_add_fmt(msg, attrib, "%llu", (unsigned long long) nt_time);
334 static int pdb_samba_dsdb_replace_by_sam(struct pdb_samba_dsdb_state *state,
335 bool (*need_update)(const struct samu *,
336 enum pdb_elements),
337 struct ldb_dn *dn,
338 struct samu *sam)
340 TALLOC_CTX *frame = talloc_stackframe();
341 int ret = LDB_SUCCESS;
342 const char *pw;
343 struct ldb_message *msg;
344 struct ldb_request *req;
345 uint32_t dsdb_flags = 0;
346 /* TODO: All fields :-) */
348 msg = ldb_msg_new(frame);
349 if (!msg) {
350 talloc_free(frame);
351 return false;
354 msg->dn = dn;
356 /* build modify request */
357 ret = ldb_build_mod_req(&req, state->ldb, frame, msg, NULL, NULL,
358 ldb_op_default_callback,
359 NULL);
360 if (ret != LDB_SUCCESS) {
361 talloc_free(frame);
362 return ret;
365 /* If we set a plaintext password, the system will
366 * force the pwdLastSet to now() */
367 if (need_update(sam, PDB_PASSLASTSET)) {
368 dsdb_flags |= DSDB_PASSWORD_BYPASS_LAST_SET;
370 ret |= pdb_samba_dsdb_add_time(msg, "pwdLastSet",
371 pdb_get_pass_last_set_time(sam));
374 pw = pdb_get_plaintext_passwd(sam);
375 if (need_update(sam, PDB_PLAINTEXT_PW)) {
376 struct ldb_val pw_utf16;
377 if (pw == NULL) {
378 talloc_free(frame);
379 return LDB_ERR_OPERATIONS_ERROR;
382 if (!convert_string_talloc(msg,
383 CH_UNIX, CH_UTF16,
384 pw, strlen(pw),
385 (void *)&pw_utf16.data,
386 &pw_utf16.length)) {
387 talloc_free(frame);
388 return LDB_ERR_OPERATIONS_ERROR;
390 ret |= ldb_msg_add_value(msg, "clearTextPassword", &pw_utf16, NULL);
391 } else {
392 bool changed_lm_pw = false;
393 bool changed_nt_pw = false;
394 bool changed_history = false;
395 if (need_update(sam, PDB_LMPASSWD)) {
396 struct ldb_val val;
397 val.data = discard_const_p(uint8_t, pdb_get_lanman_passwd(sam));
398 if (!val.data) {
399 samdb_msg_add_delete(state->ldb, msg, msg,
400 "dBCSPwd");
401 } else {
402 val.length = LM_HASH_LEN;
403 ret |= ldb_msg_add_value(msg, "dBCSPwd", &val, NULL);
405 changed_lm_pw = true;
407 if (need_update(sam, PDB_NTPASSWD)) {
408 struct ldb_val val;
409 val.data = discard_const_p(uint8_t, pdb_get_nt_passwd(sam));
410 if (!val.data) {
411 samdb_msg_add_delete(state->ldb, msg, msg,
412 "unicodePwd");
413 } else {
414 val.length = NT_HASH_LEN;
415 ret |= ldb_msg_add_value(msg, "unicodePwd", &val, NULL);
417 changed_nt_pw = true;
420 /* Try to ensure we don't get out of sync */
421 if (changed_lm_pw && !changed_nt_pw) {
422 samdb_msg_add_delete(state->ldb, msg, msg,
423 "unicodePwd");
424 } else if (changed_nt_pw && !changed_lm_pw) {
425 samdb_msg_add_delete(state->ldb, msg, msg,
426 "dBCSPwd");
428 if (changed_lm_pw || changed_nt_pw) {
429 samdb_msg_add_delete(state->ldb, msg, msg,
430 "supplementalCredentials");
434 if (need_update(sam, PDB_PWHISTORY)) {
435 uint32_t current_hist_len;
436 const uint8_t *history = pdb_get_pw_history(sam, &current_hist_len);
438 bool invalid_history = false;
439 struct samr_Password *history_hashes = talloc_array(talloc_tos(), struct samr_Password,
440 current_hist_len);
441 if (!history) {
442 invalid_history = true;
443 } else {
444 unsigned int i;
445 /* Parse the history into the correct format */
446 for (i = 0; i < current_hist_len; i++) {
447 if (!all_zero(&history[i*PW_HISTORY_ENTRY_LEN],
448 16)) {
449 /* If the history is in the old format, with a salted hash, then we can't migrate it to AD format */
450 invalid_history = true;
451 break;
453 /* Copy out the 2nd 16 bytes of the 32 byte password history, containing the NT hash */
454 memcpy(history_hashes[i].hash,
455 &history[(i*PW_HISTORY_ENTRY_LEN) + PW_HISTORY_SALT_LEN],
456 sizeof(history_hashes[i].hash));
459 if (invalid_history) {
460 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
461 "ntPwdHistory");
463 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
464 "lmPwdHistory");
465 } else {
466 ret |= samdb_msg_add_hashes(state->ldb, msg, msg,
467 "ntPwdHistory",
468 history_hashes,
469 current_hist_len);
471 changed_history = true;
473 if (changed_lm_pw || changed_nt_pw || changed_history) {
474 /* These attributes can only be modified directly by using a special control */
475 dsdb_flags |= DSDB_BYPASS_PASSWORD_HASH;
479 /* PDB_USERSID is only allowed on ADD, handled in caller */
480 if (need_update(sam, PDB_GROUPSID)) {
481 const struct dom_sid *sid = pdb_get_group_sid(sam);
482 uint32_t rid;
483 NTSTATUS status = dom_sid_split_rid(NULL, sid, NULL, &rid);
484 if (!NT_STATUS_IS_OK(status)) {
485 talloc_free(frame);
486 return LDB_ERR_OPERATIONS_ERROR;
488 if (!dom_sid_in_domain(samdb_domain_sid(state->ldb), sid)) {
489 talloc_free(frame);
490 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
492 ret |= samdb_msg_add_uint(state->ldb, msg, msg, "primaryGroupID", rid);
494 if (need_update(sam, PDB_FULLNAME)) {
495 ret |= ldb_msg_add_string(msg, "displayName", pdb_get_fullname(sam));
498 if (need_update(sam, PDB_SMBHOME)) {
499 ret |= ldb_msg_add_string(msg, "homeDirectory",
500 pdb_get_homedir(sam));
503 if (need_update(sam, PDB_PROFILE)) {
504 ret |= ldb_msg_add_string(msg, "profilePath",
505 pdb_get_profile_path(sam));
508 if (need_update(sam, PDB_DRIVE)) {
509 ret |= ldb_msg_add_string(msg, "homeDrive",
510 pdb_get_dir_drive(sam));
513 if (need_update(sam, PDB_LOGONSCRIPT)) {
514 ret |= ldb_msg_add_string(msg, "scriptPath",
515 pdb_get_logon_script(sam));
518 if (need_update(sam, PDB_KICKOFFTIME)) {
519 ret |= pdb_samba_dsdb_add_time(msg, "accountExpires",
520 pdb_get_kickoff_time(sam));
523 if (need_update(sam, PDB_LOGONTIME)) {
524 ret |= pdb_samba_dsdb_add_time(msg, "lastLogon",
525 pdb_get_logon_time(sam));
528 if (need_update(sam, PDB_LOGOFFTIME)) {
529 ret |= pdb_samba_dsdb_add_time(msg, "lastLogoff",
530 pdb_get_logoff_time(sam));
533 if (need_update(sam, PDB_USERNAME)) {
534 ret |= ldb_msg_add_string(msg, "samAccountName",
535 pdb_get_username(sam));
538 if (need_update(sam, PDB_HOURSLEN) || need_update(sam, PDB_HOURS)) {
539 struct ldb_val hours = data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam));
540 ret |= ldb_msg_add_value(msg, "logonHours",
541 &hours, NULL);
544 if (need_update(sam, PDB_ACCTCTRL)) {
545 ret |= samdb_msg_add_acct_flags(state->ldb, msg, msg,
546 "userAccountControl", pdb_get_acct_ctrl(sam));
549 if (need_update(sam, PDB_COMMENT)) {
550 ret |= ldb_msg_add_string(msg, "comment",
551 pdb_get_comment(sam));
554 if (need_update(sam, PDB_ACCTDESC)) {
555 ret |= ldb_msg_add_string(msg, "description",
556 pdb_get_acct_desc(sam));
559 if (need_update(sam, PDB_WORKSTATIONS)) {
560 ret |= ldb_msg_add_string(msg, "userWorkstations",
561 pdb_get_workstations(sam));
564 /* This will need work, it is actually a UTF8 'string' with internal NULLs, to handle TS parameters */
565 if (need_update(sam, PDB_MUNGEDDIAL)) {
566 const char *base64_munged_dial = NULL;
568 base64_munged_dial = pdb_get_munged_dial(sam);
569 if (base64_munged_dial != NULL && strlen(base64_munged_dial) > 0) {
570 struct ldb_val blob;
572 blob = base64_decode_data_blob_talloc(msg,
573 base64_munged_dial);
574 if (blob.data == NULL) {
575 DEBUG(0, ("Failed to decode userParameters from "
576 "munged dialback string[%s] for %s\n",
577 base64_munged_dial,
578 ldb_dn_get_linearized(msg->dn)));
579 talloc_free(frame);
580 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
582 ret |= ldb_msg_add_steal_value(msg, "userParameters",
583 &blob);
587 if (need_update(sam, PDB_COUNTRY_CODE)) {
588 ret |= ldb_msg_add_fmt(msg, "countryCode",
589 "%i", (int)pdb_get_country_code(sam));
592 if (need_update(sam, PDB_CODE_PAGE)) {
593 ret |= ldb_msg_add_fmt(msg, "codePage",
594 "%i", (int)pdb_get_code_page(sam));
597 /* Not yet handled here or not meaningful for modifies on a Samba_Dsdb backend:
598 PDB_BAD_PASSWORD_TIME,
599 PDB_CANCHANGETIME, - these are calculated per policy, not stored
600 PDB_DOMAIN,
601 PDB_NTUSERNAME, - this makes no sense, and never really did
602 PDB_LOGONDIVS,
603 PDB_USERSID, - Handled in pdb_samba_dsdb_add_sam_account()
604 PDB_FIELDS_PRESENT,
605 PDB_BAD_PASSWORD_COUNT,
606 PDB_LOGON_COUNT,
607 PDB_UNKNOWN6,
608 PDB_BACKEND_PRIVATE_DATA,
611 if (ret != LDB_SUCCESS) {
612 talloc_free(frame);
613 return LDB_ERR_OPERATIONS_ERROR;
616 if (msg->num_elements == 0) {
617 talloc_free(frame);
618 /* Nothing to do, just return success */
619 return LDB_SUCCESS;
622 ret = dsdb_replace(state->ldb, msg, dsdb_flags);
624 if (ret != LDB_SUCCESS) {
625 DEBUG(0,("Failed to modify account record %s to set user attributes: %s\n",
626 ldb_dn_get_linearized(msg->dn),
627 ldb_errstring(state->ldb)));
630 talloc_free(frame);
631 return ret;
634 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
635 const char *filter,
636 TALLOC_CTX *mem_ctx,
637 struct ldb_message **msg)
639 static const char *attrs[] = {
640 "lastLogon",
641 "lastLogoff",
642 "pwdLastSet",
643 "accountExpires",
644 "sAMAccountName",
645 "displayName",
646 "homeDirectory",
647 "homeDrive",
648 "scriptPath",
649 "profilePath",
650 "description",
651 "userWorkstations",
652 "comment",
653 "userParameters",
654 "objectSid",
655 "primaryGroupID",
656 "userAccountControl",
657 "msDS-User-Account-Control-Computed",
658 "logonHours",
659 "badPwdCount",
660 "logonCount",
661 "countryCode",
662 "codePage",
663 "unicodePwd",
664 "dBCSPwd",
665 /* Required for Group Managed Service Accounts. */
666 "msDS-ManagedPasswordId",
667 "msDS-ManagedPasswordInterval",
668 "objectClass",
669 "whenCreated",
670 NULL};
672 int rc = dsdb_search_one(state->ldb,
673 mem_ctx,
674 msg,
675 ldb_get_default_basedn(state->ldb),
676 LDB_SCOPE_SUBTREE,
677 attrs,
678 DSDB_SEARCH_UPDATE_MANAGED_PASSWORDS,
679 "%s",
680 filter);
681 if (rc != LDB_SUCCESS) {
682 DEBUG(10, ("ldap_search failed %s\n",
683 ldb_errstring(state->ldb)));
684 return NT_STATUS_LDAP(rc);
687 return NT_STATUS_OK;
690 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
691 struct pdb_samba_dsdb_state *state,
692 struct samu *sam_acct,
693 const char *exp_fmt, ...)
694 PRINTF_ATTRIBUTE(4,5);
696 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
697 struct pdb_samba_dsdb_state *state,
698 struct samu *sam_acct,
699 const char *exp_fmt, ...)
701 struct ldb_message *priv;
702 NTSTATUS status;
703 va_list ap;
704 char *expression = NULL;
705 TALLOC_CTX *tmp_ctx = talloc_new(state);
706 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
708 va_start(ap, exp_fmt);
709 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
710 va_end(ap);
712 if (!expression) {
713 talloc_free(tmp_ctx);
714 return NT_STATUS_NO_MEMORY;
717 status = pdb_samba_dsdb_getsamupriv(state, expression, sam_acct, &priv);
718 talloc_free(tmp_ctx);
719 if (!NT_STATUS_IS_OK(status)) {
720 DEBUG(10, ("pdb_samba_dsdb_getsamupriv failed: %s\n",
721 nt_errstr(status)));
722 return status;
725 status = pdb_samba_dsdb_init_sam_from_priv(m, sam_acct, priv);
726 if (!NT_STATUS_IS_OK(status)) {
727 DEBUG(10, ("pdb_samba_dsdb_init_sam_from_priv failed: %s\n",
728 nt_errstr(status)));
729 TALLOC_FREE(priv);
730 return status;
733 pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
734 return NT_STATUS_OK;
737 static NTSTATUS pdb_samba_dsdb_getsampwnam(struct pdb_methods *m,
738 struct samu *sam_acct,
739 const char *username)
741 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
742 m->private_data, struct pdb_samba_dsdb_state);
744 return pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
745 "(&(samaccountname=%s)(objectclass=user))",
746 username);
749 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
750 struct samu *sam_acct,
751 const struct dom_sid *sid)
753 NTSTATUS status;
754 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
755 m->private_data, struct pdb_samba_dsdb_state);
756 struct dom_sid_buf buf;
758 status = pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
759 "(&(objectsid=%s)(objectclass=user))",
760 dom_sid_str_buf(sid, &buf));
761 return status;
764 static NTSTATUS pdb_samba_dsdb_create_user(struct pdb_methods *m,
765 TALLOC_CTX *mem_ctx,
766 const char *name, uint32_t acct_flags,
767 uint32_t *rid)
769 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
770 m->private_data, struct pdb_samba_dsdb_state);
771 struct dom_sid *sid;
772 struct ldb_dn *dn;
773 NTSTATUS status;
774 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
775 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
777 /* Internally this uses transactions to ensure all the steps
778 * happen or fail as one */
779 status = dsdb_add_user(state->ldb, tmp_ctx, name, acct_flags, NULL,
780 &sid, &dn);
781 if (!NT_STATUS_IS_OK(status)) {
782 talloc_free(tmp_ctx);
783 return status;
785 sid_peek_rid(sid, rid);
786 talloc_free(tmp_ctx);
787 return NT_STATUS_OK;
790 static NTSTATUS pdb_samba_dsdb_delete_user(struct pdb_methods *m,
791 TALLOC_CTX *mem_ctx,
792 struct samu *sam)
794 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
795 m->private_data, struct pdb_samba_dsdb_state);
796 struct ldb_dn *dn;
797 int rc;
798 struct dom_sid_buf buf;
799 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
800 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
802 dn = ldb_dn_new_fmt(
803 tmp_ctx,
804 state->ldb,
805 "<SID=%s>",
806 dom_sid_str_buf(pdb_get_user_sid(sam), &buf));
807 if (!dn || !ldb_dn_validate(dn)) {
808 talloc_free(tmp_ctx);
809 return NT_STATUS_NO_MEMORY;
811 rc = ldb_delete(state->ldb, dn);
813 if (rc != LDB_SUCCESS) {
814 DEBUG(10, ("ldb_delete for %s failed: %s\n", ldb_dn_get_linearized(dn),
815 ldb_errstring(state->ldb)));
816 talloc_free(tmp_ctx);
817 return NT_STATUS_LDAP(rc);
819 talloc_free(tmp_ctx);
820 return NT_STATUS_OK;
823 /* This interface takes a fully populated struct samu and places it in
824 * the database. This is not implemented at this time as we need to
825 * be careful around the creation of arbitrary SIDs (ie, we must ensure
826 * they are not left in a RID pool */
827 static NTSTATUS pdb_samba_dsdb_add_sam_account(struct pdb_methods *m,
828 struct samu *sampass)
830 int ret;
831 NTSTATUS status;
832 struct ldb_dn *dn;
833 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
834 m->private_data, struct pdb_samba_dsdb_state);
835 uint32_t acb_flags = pdb_get_acct_ctrl(sampass);
836 const char *username = pdb_get_username(sampass);
837 const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
838 TALLOC_CTX *tframe = talloc_stackframe();
840 acb_flags &= (ACB_NORMAL|ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST);
842 ret = ldb_transaction_start(state->ldb);
843 if (ret != LDB_SUCCESS) {
844 talloc_free(tframe);
845 return NT_STATUS_LOCK_NOT_GRANTED;
848 status = dsdb_add_user(state->ldb, talloc_tos(), username,
849 acb_flags, user_sid, NULL, &dn);
850 if (!NT_STATUS_IS_OK(status)) {
851 ldb_transaction_cancel(state->ldb);
852 talloc_free(tframe);
853 return status;
856 ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_set_or_changed,
857 dn, sampass);
858 if (ret != LDB_SUCCESS) {
859 ldb_transaction_cancel(state->ldb);
860 talloc_free(tframe);
861 return dsdb_ldb_err_to_ntstatus(ret);
864 ret = ldb_transaction_commit(state->ldb);
865 if (ret != LDB_SUCCESS) {
866 DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
867 ldb_dn_get_linearized(dn),
868 ldb_errstring(state->ldb)));
869 talloc_free(tframe);
870 return NT_STATUS_INTERNAL_DB_CORRUPTION;
872 talloc_free(tframe);
873 return NT_STATUS_OK;
877 * Update the Samba_Dsdb LDB with the changes from a struct samu.
879 * This takes care not to update elements that have not been changed
880 * by the caller
882 static NTSTATUS pdb_samba_dsdb_update_sam_account(struct pdb_methods *m,
883 struct samu *sam)
885 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
886 m->private_data, struct pdb_samba_dsdb_state);
887 struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
888 m, sam);
889 int ret;
891 ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_changed, msg->dn,
892 sam);
893 return dsdb_ldb_err_to_ntstatus(ret);
896 static NTSTATUS pdb_samba_dsdb_delete_sam_account(struct pdb_methods *m,
897 struct samu *username)
899 NTSTATUS status;
900 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
901 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
902 status = pdb_samba_dsdb_delete_user(m, tmp_ctx, username);
903 talloc_free(tmp_ctx);
904 return status;
907 static NTSTATUS pdb_samba_dsdb_rename_sam_account(struct pdb_methods *m,
908 struct samu *oldname,
909 const char *newname)
911 return NT_STATUS_NOT_IMPLEMENTED;
914 /* This is not implemented, as this module is expected to be used
915 * with auth_samba_dsdb, and this is responsible for login counters etc
918 static NTSTATUS pdb_samba_dsdb_update_login_attempts(struct pdb_methods *m,
919 struct samu *sam_acct,
920 bool success)
922 return NT_STATUS_NOT_IMPLEMENTED;
925 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m,
926 GROUP_MAP *map,
927 const char *exp_fmt, ...)
928 PRINTF_ATTRIBUTE(3,4);
930 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
931 const char *exp_fmt, ...)
933 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
934 m->private_data, struct pdb_samba_dsdb_state);
935 const char *attrs[] = { "objectClass", "objectSid", "description", "samAccountName", "groupType",
936 NULL };
937 struct ldb_message *msg;
938 va_list ap;
939 char *expression = NULL;
940 struct dom_sid *sid;
941 const char *str;
942 int rc;
943 struct id_map id_map;
944 struct id_map *id_maps[2];
945 TALLOC_CTX *tmp_ctx = talloc_stackframe();
946 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
948 va_start(ap, exp_fmt);
949 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
950 va_end(ap);
952 if (!expression) {
953 talloc_free(tmp_ctx);
954 return NT_STATUS_NO_MEMORY;
957 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
958 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
959 talloc_free(tmp_ctx);
960 return NT_STATUS_NO_SUCH_GROUP;
961 } else if (rc != LDB_SUCCESS) {
962 talloc_free(tmp_ctx);
963 DEBUG(10, ("dsdb_search_one failed %s\n",
964 ldb_errstring(state->ldb)));
965 return NT_STATUS_LDAP(rc);
968 sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
969 if (!sid) {
970 talloc_free(tmp_ctx);
971 DEBUG(10, ("Could not pull SID\n"));
972 return NT_STATUS_INTERNAL_DB_CORRUPTION;
975 map->sid = *sid;
977 if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) {
978 NTSTATUS status;
979 uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0);
980 switch (grouptype) {
981 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
982 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
983 map->sid_name_use = SID_NAME_ALIAS;
984 break;
985 case GTYPE_SECURITY_GLOBAL_GROUP:
986 map->sid_name_use = SID_NAME_DOM_GRP;
987 break;
988 default:
989 talloc_free(tmp_ctx);
990 DEBUG(10, ("Could not pull groupType\n"));
991 return NT_STATUS_INTERNAL_DB_CORRUPTION;
994 ZERO_STRUCT(id_map);
995 id_map.sid = sid;
996 id_maps[0] = &id_map;
997 id_maps[1] = NULL;
999 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1001 if (!NT_STATUS_IS_OK(status)) {
1002 talloc_free(tmp_ctx);
1003 return status;
1005 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1006 map->gid = id_map.xid.id;
1007 } else {
1008 DEBUG(1, (__location__ "Did not get GUID when mapping SID for %s\n", expression));
1009 talloc_free(tmp_ctx);
1010 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1012 } else if (samdb_find_attribute(state->ldb, msg, "objectClass", "user")) {
1013 DEBUG(1, (__location__ "Got SID_NAME_USER when searching for a group with %s\n", expression));
1014 talloc_free(tmp_ctx);
1015 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1018 str = ldb_msg_find_attr_as_string(msg, "samAccountName",
1019 NULL);
1020 if (str == NULL) {
1021 talloc_free(tmp_ctx);
1022 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1024 map->nt_name = talloc_strdup(map, str);
1025 if (!map->nt_name) {
1026 talloc_free(tmp_ctx);
1027 return NT_STATUS_NO_MEMORY;
1030 str = ldb_msg_find_attr_as_string(msg, "description",
1031 NULL);
1032 if (str != NULL) {
1033 map->comment = talloc_strdup(map, str);
1034 } else {
1035 map->comment = talloc_strdup(map, "");
1037 if (!map->comment) {
1038 talloc_free(tmp_ctx);
1039 return NT_STATUS_NO_MEMORY;
1042 talloc_free(tmp_ctx);
1043 return NT_STATUS_OK;
1046 static NTSTATUS pdb_samba_dsdb_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
1047 struct dom_sid sid)
1049 char *filter;
1050 NTSTATUS status;
1051 struct dom_sid_buf buf;
1053 filter = talloc_asprintf(talloc_tos(),
1054 "(&(objectsid=%s)(objectclass=group))",
1055 dom_sid_str_buf(&sid, &buf));
1056 if (filter == NULL) {
1057 return NT_STATUS_NO_MEMORY;
1060 status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
1061 TALLOC_FREE(filter);
1062 return status;
1065 static NTSTATUS pdb_samba_dsdb_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
1066 gid_t gid)
1068 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1069 m->private_data, struct pdb_samba_dsdb_state);
1070 NTSTATUS status;
1071 struct id_map id_map;
1072 struct id_map *id_maps[2];
1073 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1074 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1076 id_map.xid.id = gid;
1077 id_map.xid.type = ID_TYPE_GID;
1078 id_maps[0] = &id_map;
1079 id_maps[1] = NULL;
1081 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
1082 if (!NT_STATUS_IS_OK(status)) {
1083 talloc_free(tmp_ctx);
1084 return status;
1086 status = pdb_samba_dsdb_getgrsid(m, map, *id_map.sid);
1087 talloc_free(tmp_ctx);
1088 return status;
1091 static NTSTATUS pdb_samba_dsdb_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
1092 const char *name)
1094 char *filter;
1095 NTSTATUS status;
1097 filter = talloc_asprintf(talloc_tos(),
1098 "(&(samaccountname=%s)(objectclass=group))",
1099 name);
1100 if (filter == NULL) {
1101 return NT_STATUS_NO_MEMORY;
1104 status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
1105 TALLOC_FREE(filter);
1106 return status;
1109 static NTSTATUS pdb_samba_dsdb_create_dom_group(struct pdb_methods *m,
1110 TALLOC_CTX *mem_ctx, const char *name,
1111 uint32_t *rid)
1113 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1114 m->private_data, struct pdb_samba_dsdb_state);
1115 NTSTATUS status;
1116 struct dom_sid *sid;
1117 struct ldb_dn *dn;
1118 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1119 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1121 status = dsdb_add_domain_group(state->ldb, tmp_ctx, name, &sid, &dn);
1122 if (!NT_STATUS_IS_OK(status)) {
1123 talloc_free(tmp_ctx);
1124 return status;
1127 sid_peek_rid(sid, rid);
1128 talloc_free(tmp_ctx);
1129 return NT_STATUS_OK;
1132 static NTSTATUS pdb_samba_dsdb_delete_dom_group(struct pdb_methods *m,
1133 TALLOC_CTX *mem_ctx, uint32_t rid)
1135 const char *attrs[] = { NULL };
1136 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1137 m->private_data, struct pdb_samba_dsdb_state);
1138 struct dom_sid sid;
1139 struct ldb_message *msg;
1140 struct ldb_dn *dn;
1141 int rc;
1142 struct dom_sid_buf buf;
1143 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1144 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1146 sid_compose(&sid, samdb_domain_sid(state->ldb), rid);
1148 if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1149 DEBUG(0, ("Unable to start transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1150 return NT_STATUS_INTERNAL_ERROR;
1153 dn = ldb_dn_new_fmt(
1154 tmp_ctx,
1155 state->ldb,
1156 "<SID=%s>",
1157 dom_sid_str_buf(&sid, &buf));
1158 if (!dn || !ldb_dn_validate(dn)) {
1159 talloc_free(tmp_ctx);
1160 ldb_transaction_cancel(state->ldb);
1161 return NT_STATUS_NO_MEMORY;
1163 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "objectclass=group");
1164 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1165 talloc_free(tmp_ctx);
1166 ldb_transaction_cancel(state->ldb);
1167 return NT_STATUS_NO_SUCH_GROUP;
1168 } else if (rc != LDB_SUCCESS) {
1169 talloc_free(tmp_ctx);
1170 DEBUG(10, ("dsdb_search_one failed %s\n",
1171 ldb_errstring(state->ldb)));
1172 ldb_transaction_cancel(state->ldb);
1173 return NT_STATUS_LDAP(rc);
1175 rc = ldb_delete(state->ldb, dn);
1176 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1177 talloc_free(tmp_ctx);
1178 ldb_transaction_cancel(state->ldb);
1179 return NT_STATUS_NO_SUCH_GROUP;
1180 } else if (rc != LDB_SUCCESS) {
1181 DEBUG(10, ("ldb_delete failed %s\n",
1182 ldb_errstring(state->ldb)));
1183 ldb_transaction_cancel(state->ldb);
1184 return NT_STATUS_LDAP(rc);
1187 if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1188 DEBUG(0, ("Unable to commit transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1189 return NT_STATUS_INTERNAL_ERROR;
1191 return NT_STATUS_OK;
1194 static NTSTATUS pdb_samba_dsdb_add_group_mapping_entry(struct pdb_methods *m,
1195 GROUP_MAP *map)
1197 return NT_STATUS_NOT_IMPLEMENTED;
1200 static NTSTATUS pdb_samba_dsdb_update_group_mapping_entry(struct pdb_methods *m,
1201 GROUP_MAP *map)
1203 return NT_STATUS_NOT_IMPLEMENTED;
1206 static NTSTATUS pdb_samba_dsdb_delete_group_mapping_entry(struct pdb_methods *m,
1207 struct dom_sid sid)
1209 return NT_STATUS_NOT_IMPLEMENTED;
1212 static NTSTATUS pdb_samba_dsdb_enum_group_mapping(struct pdb_methods *m,
1213 const struct dom_sid *sid,
1214 enum lsa_SidType sid_name_use,
1215 GROUP_MAP ***pp_rmap,
1216 size_t *p_num_entries,
1217 bool unix_only)
1219 return NT_STATUS_NOT_IMPLEMENTED;
1222 static NTSTATUS pdb_samba_dsdb_enum_group_members(struct pdb_methods *m,
1223 TALLOC_CTX *mem_ctx,
1224 const struct dom_sid *group,
1225 uint32_t **pmembers,
1226 size_t *pnum_members)
1228 unsigned int i, num_sids, num_members;
1229 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1230 m->private_data, struct pdb_samba_dsdb_state);
1231 struct dom_sid *members_as_sids;
1232 struct dom_sid *dom_sid;
1233 uint32_t *members;
1234 struct ldb_dn *dn;
1235 NTSTATUS status;
1236 struct dom_sid_buf buf;
1238 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1239 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1241 dn = ldb_dn_new_fmt(
1242 tmp_ctx,
1243 state->ldb,
1244 "<SID=%s>",
1245 dom_sid_str_buf(group, &buf));
1246 if (!dn || !ldb_dn_validate(dn)) {
1247 return NT_STATUS_NO_MEMORY;
1250 status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
1251 if (!NT_STATUS_IS_OK(status)) {
1252 talloc_free(tmp_ctx);
1253 return status;
1255 status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
1256 if (!NT_STATUS_IS_OK(status)) {
1257 talloc_free(tmp_ctx);
1258 return status;
1261 *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
1262 if (*pmembers == NULL) {
1263 TALLOC_FREE(tmp_ctx);
1264 return NT_STATUS_NO_MEMORY;
1266 num_members = 0;
1268 for (i = 0; i < num_sids; i++) {
1269 if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
1270 continue;
1272 status = dom_sid_split_rid(NULL, &members_as_sids[i],
1273 NULL, &members[num_members]);
1274 if (!NT_STATUS_IS_OK(status)) {
1275 talloc_free(tmp_ctx);
1276 return status;
1278 num_members++;
1280 *pnum_members = num_members;
1281 return NT_STATUS_OK;
1284 /* Just convert the primary group SID into a group */
1285 static NTSTATUS fake_enum_group_memberships(struct pdb_samba_dsdb_state *state,
1286 TALLOC_CTX *mem_ctx,
1287 struct samu *user,
1288 struct dom_sid **pp_sids,
1289 gid_t **pp_gids,
1290 uint32_t *p_num_groups)
1292 NTSTATUS status;
1293 size_t num_groups = 0;
1294 struct dom_sid *group_sids = NULL;
1295 gid_t *gids = NULL;
1296 TALLOC_CTX *tmp_ctx;
1298 tmp_ctx = talloc_new(mem_ctx);
1299 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1301 if (user->group_sid) {
1302 struct id_map *id_maps[2];
1303 struct id_map id_map;
1305 num_groups = 1;
1307 group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
1308 if (group_sids == NULL) {
1309 talloc_free(tmp_ctx);
1310 return NT_STATUS_NO_MEMORY;
1312 gids = talloc_array(tmp_ctx, gid_t, num_groups);
1313 if (gids == NULL) {
1314 talloc_free(tmp_ctx);
1315 return NT_STATUS_NO_MEMORY;
1318 group_sids[0] = *user->group_sid;
1320 ZERO_STRUCT(id_map);
1321 id_map.sid = &group_sids[0];
1322 id_maps[0] = &id_map;
1323 id_maps[1] = NULL;
1325 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1326 if (!NT_STATUS_IS_OK(status)) {
1327 talloc_free(tmp_ctx);
1328 return status;
1330 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1331 gids[0] = id_map.xid.id;
1332 } else {
1333 struct dom_sid_buf buf1, buf2;
1334 DEBUG(1, (__location__
1335 "Group %s, of which %s is a member, could not be converted to a GID\n",
1336 dom_sid_str_buf(&group_sids[0], &buf1),
1337 dom_sid_str_buf(&user->user_sid, &buf2)));
1338 talloc_free(tmp_ctx);
1339 /* We must error out, otherwise a user might
1340 * avoid a DENY acl based on a group they
1341 * missed out on */
1342 return NT_STATUS_NO_SUCH_GROUP;
1346 *pp_sids = talloc_steal(mem_ctx, group_sids);
1347 *pp_gids = talloc_steal(mem_ctx, gids);
1348 *p_num_groups = num_groups;
1349 talloc_free(tmp_ctx);
1350 return NT_STATUS_OK;
1353 static NTSTATUS pdb_samba_dsdb_enum_group_memberships(struct pdb_methods *m,
1354 TALLOC_CTX *mem_ctx,
1355 struct samu *user,
1356 struct dom_sid **pp_sids,
1357 gid_t **pp_gids,
1358 uint32_t *p_num_groups)
1360 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1361 m->private_data, struct pdb_samba_dsdb_state);
1362 struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
1363 m, user);
1364 const char *attrs[] = { "tokenGroups", NULL};
1365 struct ldb_message *tokengroups_msg;
1366 struct ldb_message_element *tokengroups;
1367 int i, rc;
1368 NTSTATUS status;
1369 unsigned int count = 0;
1370 size_t num_groups;
1371 struct dom_sid *group_sids;
1372 gid_t *gids;
1373 TALLOC_CTX *tmp_ctx;
1375 if (msg == NULL) {
1376 /* Fake up some things here */
1377 return fake_enum_group_memberships(state,
1378 mem_ctx,
1379 user, pp_sids,
1380 pp_gids, p_num_groups);
1383 tmp_ctx = talloc_new(mem_ctx);
1384 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1386 rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
1388 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1389 talloc_free(tmp_ctx);
1390 return NT_STATUS_NO_SUCH_USER;
1391 } else if (rc != LDB_SUCCESS) {
1392 DEBUG(10, ("dsdb_search_one failed %s\n",
1393 ldb_errstring(state->ldb)));
1394 talloc_free(tmp_ctx);
1395 return NT_STATUS_LDAP(rc);
1398 tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
1400 if (tokengroups) {
1401 count = tokengroups->num_values;
1404 group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
1405 if (group_sids == NULL) {
1406 talloc_free(tmp_ctx);
1407 return NT_STATUS_NO_MEMORY;
1409 gids = talloc_array(tmp_ctx, gid_t, count);
1410 if (gids == NULL) {
1411 talloc_free(tmp_ctx);
1412 return NT_STATUS_NO_MEMORY;
1414 num_groups = 0;
1416 for (i=0; i<count; i++) {
1417 struct id_map *id_maps[2];
1418 struct id_map id_map;
1419 struct ldb_val *v = &tokengroups->values[i];
1420 enum ndr_err_code ndr_err
1421 = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
1422 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1423 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1424 talloc_free(tmp_ctx);
1425 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1428 ZERO_STRUCT(id_map);
1429 id_map.sid = &group_sids[num_groups];
1430 id_maps[0] = &id_map;
1431 id_maps[1] = NULL;
1433 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1434 if (!NT_STATUS_IS_OK(status)) {
1435 talloc_free(tmp_ctx);
1436 return status;
1438 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1439 gids[num_groups] = id_map.xid.id;
1440 } else {
1441 struct dom_sid_buf buf;
1442 DEBUG(1, (__location__
1443 "Group %s, of which %s is a member, could not be converted to a GID\n",
1444 dom_sid_str_buf(&group_sids[num_groups],
1445 &buf),
1446 ldb_dn_get_linearized(msg->dn)));
1447 talloc_free(tmp_ctx);
1448 /* We must error out, otherwise a user might
1449 * avoid a DENY acl based on a group they
1450 * missed out on */
1451 return NT_STATUS_NO_SUCH_GROUP;
1454 num_groups += 1;
1455 if (num_groups == count) {
1456 break;
1460 *pp_sids = talloc_steal(mem_ctx, group_sids);
1461 *pp_gids = talloc_steal(mem_ctx, gids);
1462 *p_num_groups = num_groups;
1463 talloc_free(tmp_ctx);
1464 return NT_STATUS_OK;
1467 static NTSTATUS pdb_samba_dsdb_set_unix_primary_group(struct pdb_methods *m,
1468 TALLOC_CTX *mem_ctx,
1469 struct samu *user)
1471 return NT_STATUS_NOT_IMPLEMENTED;
1474 static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid(struct pdb_methods *m,
1475 TALLOC_CTX *mem_ctx,
1476 const struct dom_sid *groupsid,
1477 const struct dom_sid *membersid,
1478 int mod_op)
1480 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1481 m->private_data, struct pdb_samba_dsdb_state);
1482 struct ldb_message *msg;
1483 int ret;
1484 struct ldb_message_element *el;
1485 struct dom_sid_buf buf;
1486 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1487 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1488 msg = ldb_msg_new(tmp_ctx);
1489 if (msg == NULL) {
1490 TALLOC_FREE(tmp_ctx);
1491 return NT_STATUS_NO_MEMORY;
1494 msg->dn = ldb_dn_new_fmt(
1495 msg,
1496 state->ldb,
1497 "<SID=%s>",
1498 dom_sid_str_buf(groupsid, &buf));
1499 if (!msg->dn || !ldb_dn_validate(msg->dn)) {
1500 talloc_free(tmp_ctx);
1501 return NT_STATUS_NO_MEMORY;
1503 ret = ldb_msg_add_fmt(
1504 msg,
1505 "member",
1506 "<SID=%s>",
1507 dom_sid_str_buf(membersid, &buf));
1508 if (ret != LDB_SUCCESS) {
1509 talloc_free(tmp_ctx);
1510 return NT_STATUS_NO_MEMORY;
1512 el = ldb_msg_find_element(msg, "member");
1513 el->flags = mod_op;
1515 /* No need for transactions here, the ldb auto-transaction
1516 * code will handle things for the single operation */
1517 ret = ldb_modify(state->ldb, msg);
1518 talloc_free(tmp_ctx);
1519 if (ret != LDB_SUCCESS) {
1520 DEBUG(10, ("ldb_modify failed: %s\n",
1521 ldb_errstring(state->ldb)));
1522 if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
1523 return NT_STATUS_MEMBER_IN_GROUP;
1525 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1526 return NT_STATUS_MEMBER_NOT_IN_GROUP;
1528 return NT_STATUS_LDAP(ret);
1531 return NT_STATUS_OK;
1534 static NTSTATUS pdb_samba_dsdb_mod_groupmem(struct pdb_methods *m,
1535 TALLOC_CTX *mem_ctx,
1536 uint32_t grouprid, uint32_t memberrid,
1537 int mod_op)
1539 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1540 m->private_data, struct pdb_samba_dsdb_state);
1541 const struct dom_sid *dom_sid, *groupsid, *membersid;
1542 NTSTATUS status;
1543 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1544 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1546 dom_sid = samdb_domain_sid(state->ldb);
1548 groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
1549 if (groupsid == NULL) {
1550 TALLOC_FREE(tmp_ctx);
1551 return NT_STATUS_NO_MEMORY;
1553 membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
1554 if (membersid == NULL) {
1555 TALLOC_FREE(tmp_ctx);
1556 return NT_STATUS_NO_MEMORY;
1558 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
1559 talloc_free(tmp_ctx);
1560 return status;
1563 static NTSTATUS pdb_samba_dsdb_add_groupmem(struct pdb_methods *m,
1564 TALLOC_CTX *mem_ctx,
1565 uint32_t group_rid, uint32_t member_rid)
1567 return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1568 LDB_FLAG_MOD_ADD);
1571 static NTSTATUS pdb_samba_dsdb_del_groupmem(struct pdb_methods *m,
1572 TALLOC_CTX *mem_ctx,
1573 uint32_t group_rid, uint32_t member_rid)
1575 return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1576 LDB_FLAG_MOD_DELETE);
1579 static NTSTATUS pdb_samba_dsdb_create_alias(struct pdb_methods *m,
1580 const char *name, uint32_t *rid)
1582 TALLOC_CTX *frame = talloc_stackframe();
1583 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1584 m->private_data, struct pdb_samba_dsdb_state);
1585 struct dom_sid *sid;
1587 struct ldb_dn *dn;
1588 NTSTATUS status;
1590 /* Internally this uses transactions to ensure all the steps
1591 * happen or fail as one */
1592 status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
1593 if (!NT_STATUS_IS_OK(status)) {
1594 TALLOC_FREE(frame);
1597 sid_peek_rid(sid, rid);
1598 TALLOC_FREE(frame);
1599 return NT_STATUS_OK;
1602 static NTSTATUS pdb_samba_dsdb_delete_alias(struct pdb_methods *m,
1603 const struct dom_sid *sid)
1605 const char *attrs[] = { NULL };
1606 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1607 m->private_data, struct pdb_samba_dsdb_state);
1608 struct ldb_message *msg;
1609 struct ldb_dn *dn;
1610 int rc;
1611 struct dom_sid_buf buf;
1612 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1613 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1615 dn = ldb_dn_new_fmt(
1616 tmp_ctx,
1617 state->ldb,
1618 "<SID=%s>",
1619 dom_sid_str_buf(sid, &buf));
1620 if (!dn || !ldb_dn_validate(dn)) {
1621 talloc_free(tmp_ctx);
1622 return NT_STATUS_NO_MEMORY;
1625 if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1626 DBG_ERR("Failed to start transaction: %s\n",
1627 ldb_errstring(state->ldb));
1628 talloc_free(tmp_ctx);
1629 return NT_STATUS_INTERNAL_ERROR;
1632 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
1633 "(|(grouptype=%d)(grouptype=%d)))",
1634 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1635 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1636 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1637 talloc_free(tmp_ctx);
1638 ldb_transaction_cancel(state->ldb);
1639 return NT_STATUS_NO_SUCH_ALIAS;
1640 } else if (rc != LDB_SUCCESS) {
1641 talloc_free(tmp_ctx);
1642 DEBUG(10, ("dsdb_search_one failed %s\n",
1643 ldb_errstring(state->ldb)));
1644 ldb_transaction_cancel(state->ldb);
1645 return NT_STATUS_LDAP(rc);
1647 rc = ldb_delete(state->ldb, dn);
1648 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1649 talloc_free(tmp_ctx);
1650 ldb_transaction_cancel(state->ldb);
1651 return NT_STATUS_NO_SUCH_ALIAS;
1652 } else if (rc != LDB_SUCCESS) {
1653 DEBUG(10, ("ldb_delete failed %s\n",
1654 ldb_errstring(state->ldb)));
1655 ldb_transaction_cancel(state->ldb);
1656 talloc_free(tmp_ctx);
1657 return NT_STATUS_LDAP(rc);
1660 if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1661 DEBUG(0, ("Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s\n",
1662 ldb_errstring(state->ldb)));
1663 talloc_free(tmp_ctx);
1664 return NT_STATUS_INTERNAL_ERROR;
1667 talloc_free(tmp_ctx);
1668 return NT_STATUS_OK;
1671 static NTSTATUS pdb_samba_dsdb_add_aliasmem(struct pdb_methods *m,
1672 const struct dom_sid *alias,
1673 const struct dom_sid *member)
1675 NTSTATUS status;
1676 TALLOC_CTX *frame = talloc_stackframe();
1677 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_ADD);
1678 talloc_free(frame);
1679 return status;
1682 static NTSTATUS pdb_samba_dsdb_del_aliasmem(struct pdb_methods *m,
1683 const struct dom_sid *alias,
1684 const struct dom_sid *member)
1686 NTSTATUS status;
1687 TALLOC_CTX *frame = talloc_stackframe();
1688 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
1689 talloc_free(frame);
1690 return status;
1693 static NTSTATUS pdb_samba_dsdb_enum_aliasmem(struct pdb_methods *m,
1694 const struct dom_sid *alias,
1695 TALLOC_CTX *mem_ctx,
1696 struct dom_sid **pmembers,
1697 size_t *pnum_members)
1699 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1700 m->private_data, struct pdb_samba_dsdb_state);
1701 struct ldb_dn *dn;
1702 unsigned int num_members;
1703 NTSTATUS status;
1704 struct dom_sid_buf buf;
1705 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1706 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1708 dn = ldb_dn_new_fmt(
1709 tmp_ctx,
1710 state->ldb,
1711 "<SID=%s>",
1712 dom_sid_str_buf(alias, &buf));
1713 if (!dn || !ldb_dn_validate(dn)) {
1714 return NT_STATUS_NO_MEMORY;
1717 status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
1718 if (NT_STATUS_IS_OK(status)) {
1719 *pnum_members = num_members;
1721 talloc_free(tmp_ctx);
1722 return status;
1725 static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1726 TALLOC_CTX *mem_ctx,
1727 const struct dom_sid *domain_sid,
1728 const struct dom_sid *members,
1729 size_t num_members,
1730 uint32_t **palias_rids,
1731 size_t *pnum_alias_rids)
1733 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1734 m->private_data, struct pdb_samba_dsdb_state);
1735 uint32_t *alias_rids = NULL;
1736 size_t num_alias_rids = 0;
1737 int i;
1738 struct auth_SidAttr *groupSIDs = NULL;
1739 uint32_t num_groupSIDs = 0;
1740 char *filter;
1741 NTSTATUS status;
1742 const char *sid_dn;
1743 DATA_BLOB sid_blob;
1745 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1746 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1748 * TODO: Get the filter right so that we only get the aliases from
1749 * either the SAM or BUILTIN
1752 filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:"LDB_OID_COMPARATOR_AND":=%u))",
1753 GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1754 if (filter == NULL) {
1755 return NT_STATUS_NO_MEMORY;
1758 for (i = 0; i < num_members; i++) {
1759 struct dom_sid_buf buf;
1761 sid_dn = talloc_asprintf(
1762 tmp_ctx,
1763 "<SID=%s>",
1764 dom_sid_str_buf(&members[i], &buf));
1765 if (sid_dn == NULL) {
1766 TALLOC_FREE(tmp_ctx);
1767 return NT_STATUS_NO_MEMORY;
1770 sid_blob = data_blob_string_const(sid_dn);
1772 status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1773 tmp_ctx, &groupSIDs, &num_groupSIDs);
1774 if (!NT_STATUS_IS_OK(status)) {
1775 talloc_free(tmp_ctx);
1776 return status;
1780 alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1781 if (alias_rids == NULL) {
1782 talloc_free(tmp_ctx);
1783 return NT_STATUS_NO_MEMORY;
1786 for (i=0; i<num_groupSIDs; i++) {
1787 if (sid_peek_check_rid(domain_sid, &groupSIDs[i].sid,
1788 &alias_rids[num_alias_rids])) {
1789 num_alias_rids++;;
1793 *palias_rids = alias_rids;
1794 *pnum_alias_rids = num_alias_rids;
1795 return NT_STATUS_OK;
1798 static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1799 const struct dom_sid *domain_sid,
1800 int num_rids,
1801 uint32_t *rids,
1802 const char **names,
1803 enum lsa_SidType *lsa_attrs)
1805 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1806 m->private_data, struct pdb_samba_dsdb_state);
1807 NTSTATUS status;
1809 TALLOC_CTX *tmp_ctx;
1811 if (num_rids == 0) {
1812 return NT_STATUS_NONE_MAPPED;
1815 tmp_ctx = talloc_stackframe();
1816 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1818 status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1819 talloc_free(tmp_ctx);
1820 return status;
1823 static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1824 const struct dom_sid *domain_sid,
1825 int num_names,
1826 const char **pp_names,
1827 uint32_t *rids,
1828 enum lsa_SidType *attrs)
1830 return NT_STATUS_NOT_IMPLEMENTED;
1833 static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1834 enum pdb_policy_type type,
1835 uint32_t *value)
1837 return account_policy_get(type, value)
1838 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1841 static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1842 enum pdb_policy_type type,
1843 uint32_t value)
1845 return account_policy_set(type, value)
1846 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1849 static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1850 time_t *seq_num_out)
1852 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1853 m->private_data, struct pdb_samba_dsdb_state);
1854 uint64_t seq_num;
1855 int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1856 if (ret == LDB_SUCCESS) {
1857 *seq_num_out = seq_num;
1858 return NT_STATUS_OK;
1859 } else {
1860 return NT_STATUS_UNSUCCESSFUL;
1864 struct pdb_samba_dsdb_search_state {
1865 uint32_t acct_flags;
1866 struct samr_displayentry *entries;
1867 uint32_t num_entries;
1868 ssize_t array_size;
1869 uint32_t current;
1872 static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1873 struct samr_displayentry *entry)
1875 struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1876 search->private_data, struct pdb_samba_dsdb_search_state);
1878 if (state->current == state->num_entries) {
1879 return false;
1882 entry->idx = state->entries[state->current].idx;
1883 entry->rid = state->entries[state->current].rid;
1884 entry->acct_flags = state->entries[state->current].acct_flags;
1886 entry->account_name = talloc_strdup(
1887 search, state->entries[state->current].account_name);
1888 entry->fullname = talloc_strdup(
1889 search, state->entries[state->current].fullname);
1890 entry->description = talloc_strdup(
1891 search, state->entries[state->current].description);
1893 state->current += 1;
1894 return true;
1897 static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1899 struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1900 search->private_data, struct pdb_samba_dsdb_search_state);
1901 talloc_free(state);
1904 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1905 struct pdb_search *search,
1906 struct pdb_samba_dsdb_search_state **pstate,
1907 const char *exp_fmt, ...)
1908 PRINTF_ATTRIBUTE(4, 5);
1910 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1911 struct pdb_search *search,
1912 struct pdb_samba_dsdb_search_state **pstate,
1913 const char *exp_fmt, ...)
1915 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1916 m->private_data, struct pdb_samba_dsdb_state);
1917 struct pdb_samba_dsdb_search_state *sstate;
1918 const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1919 "userAccountControl", "description", NULL };
1920 struct ldb_result *res;
1921 int i, rc, num_users;
1923 va_list ap;
1924 char *expression = NULL;
1926 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1927 if (!tmp_ctx) {
1928 return false;
1931 va_start(ap, exp_fmt);
1932 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1933 va_end(ap);
1935 if (!expression) {
1936 talloc_free(tmp_ctx);
1937 return LDB_ERR_OPERATIONS_ERROR;
1940 sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1941 if (sstate == NULL) {
1942 talloc_free(tmp_ctx);
1943 return false;
1946 rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1947 if (rc != LDB_SUCCESS) {
1948 talloc_free(tmp_ctx);
1949 DEBUG(10, ("dsdb_search failed: %s\n",
1950 ldb_errstring(state->ldb)));
1951 return false;
1954 num_users = res->count;
1956 sstate->entries = talloc_array(sstate, struct samr_displayentry,
1957 num_users);
1958 if (sstate->entries == NULL) {
1959 talloc_free(tmp_ctx);
1960 DEBUG(10, ("talloc failed\n"));
1961 return false;
1964 sstate->num_entries = 0;
1966 for (i=0; i<num_users; i++) {
1967 struct samr_displayentry *e;
1968 struct dom_sid *sid;
1970 e = &sstate->entries[sstate->num_entries];
1972 e->idx = sstate->num_entries;
1973 sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
1974 if (!sid) {
1975 talloc_free(tmp_ctx);
1976 DEBUG(10, ("Could not pull SID\n"));
1977 return false;
1979 sid_peek_rid(sid, &e->rid);
1981 e->acct_flags = samdb_result_acct_flags(res->msgs[i], "userAccountControl");
1982 e->account_name = ldb_msg_find_attr_as_string(
1983 res->msgs[i], "samAccountName", NULL);
1984 if (e->account_name == NULL) {
1985 talloc_free(tmp_ctx);
1986 return false;
1988 e->fullname = ldb_msg_find_attr_as_string(
1989 res->msgs[i], "displayName", "");
1990 e->description = ldb_msg_find_attr_as_string(
1991 res->msgs[i], "description", "");
1993 sstate->num_entries += 1;
1994 if (sstate->num_entries >= num_users) {
1995 break;
1998 talloc_steal(sstate->entries, res->msgs);
1999 search->private_data = talloc_steal(search, sstate);
2000 search->next_entry = pdb_samba_dsdb_next_entry;
2001 search->search_end = pdb_samba_dsdb_search_end;
2002 *pstate = sstate;
2003 talloc_free(tmp_ctx);
2004 return true;
2007 static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
2008 struct pdb_search *search,
2009 uint32_t acct_flags)
2011 struct pdb_samba_dsdb_search_state *sstate;
2012 bool ret;
2014 ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
2015 if (!ret) {
2016 return false;
2018 sstate->acct_flags = acct_flags;
2019 return true;
2022 static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
2023 struct pdb_search *search)
2025 struct pdb_samba_dsdb_search_state *sstate;
2026 bool ret;
2028 ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2029 "(&(grouptype=%d)(objectclass=group))",
2030 GTYPE_SECURITY_GLOBAL_GROUP);
2031 if (!ret) {
2032 return false;
2034 sstate->acct_flags = 0;
2035 return true;
2038 static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
2039 struct pdb_search *search,
2040 const struct dom_sid *sid)
2042 struct pdb_samba_dsdb_search_state *sstate;
2043 bool ret;
2045 ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2046 "(&(grouptype=%d)(objectclass=group))",
2047 sid_check_is_builtin(sid)
2048 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2049 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2050 if (!ret) {
2051 return false;
2053 sstate->acct_flags = 0;
2054 return true;
2058 * Instead of taking a gid or uid, this function takes a pointer to a
2059 * unixid.
2061 * This acts as an in-out variable so that the idmap functions can correctly
2062 * receive ID_TYPE_BOTH, and this function ensures cache details are filled
2063 * correctly rather than forcing the cache to store ID_TYPE_UID or ID_TYPE_GID.
2065 static bool pdb_samba_dsdb_id_to_sid(struct pdb_methods *m, struct unixid *id,
2066 struct dom_sid *sid)
2068 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2069 m->private_data, struct pdb_samba_dsdb_state);
2070 NTSTATUS status;
2071 struct id_map id_map;
2072 struct id_map *id_maps[2];
2073 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2074 if (!tmp_ctx) {
2075 return false;
2078 id_map.xid = *id;
2079 id_maps[0] = &id_map;
2080 id_maps[1] = NULL;
2082 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2083 if (!NT_STATUS_IS_OK(status)) {
2084 talloc_free(tmp_ctx);
2085 return false;
2088 if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2089 id->type = id_map.xid.type;
2091 *sid = *id_map.sid;
2092 talloc_free(tmp_ctx);
2093 return true;
2096 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2097 struct unixid *id)
2099 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2100 m->private_data, struct pdb_samba_dsdb_state);
2101 struct id_map id_map;
2102 struct id_map *id_maps[2];
2103 NTSTATUS status;
2104 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2105 if (!tmp_ctx) {
2106 return false;
2109 ZERO_STRUCT(id_map);
2110 id_map.sid = discard_const_p(struct dom_sid, sid);
2111 id_maps[0] = &id_map;
2112 id_maps[1] = NULL;
2114 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2115 talloc_free(tmp_ctx);
2116 if (!NT_STATUS_IS_OK(status)) {
2117 return false;
2119 if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2120 *id = id_map.xid;
2121 return true;
2123 return false;
2126 static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2128 return PDB_CAP_STORE_RIDS | PDB_CAP_ADS | PDB_CAP_TRUSTED_DOMAINS_EX;
2131 static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32_t *rid)
2133 return false;
2136 static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2137 const char *domain, char** pwd,
2138 struct dom_sid *sid,
2139 time_t *pass_last_set_time)
2141 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2142 m->private_data, struct pdb_samba_dsdb_state);
2143 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2144 const char * const attrs[] = {
2145 "securityIdentifier",
2146 "flatName",
2147 "trustPartner",
2148 "trustAuthOutgoing",
2149 "whenCreated",
2150 "msDS-SupportedEncryptionTypes",
2151 "trustAttributes",
2152 "trustDirection",
2153 "trustType",
2154 NULL
2156 struct ldb_message *msg;
2157 const struct ldb_val *password_val;
2158 int trust_direction_flags;
2159 int trust_type;
2160 int i;
2161 DATA_BLOB password_utf16;
2162 struct trustAuthInOutBlob password_blob;
2163 struct AuthenticationInformationArray *auth_array;
2164 char *password_talloc;
2165 size_t password_len;
2166 enum ndr_err_code ndr_err;
2167 NTSTATUS status;
2168 const char *netbios_domain = NULL;
2169 const struct dom_sid *domain_sid = NULL;
2171 status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2172 attrs, tmp_ctx, &msg);
2173 if (!NT_STATUS_IS_OK(status)) {
2175 * This can be called to work out of a domain is
2176 * trusted, rather than just to get the password
2178 DEBUG(2, ("Failed to get trusted domain password for %s - %s. "
2179 "It may not be a trusted domain.\n", domain,
2180 nt_errstr(status)));
2181 TALLOC_FREE(tmp_ctx);
2182 return false;
2185 netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2186 if (netbios_domain == NULL) {
2187 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2188 domain));
2189 TALLOC_FREE(tmp_ctx);
2190 return false;
2193 domain_sid = samdb_result_dom_sid(tmp_ctx, msg, "securityIdentifier");
2194 if (domain_sid == NULL) {
2195 DEBUG(2, ("Trusted domain %s has no securityIdentifier defined.\n",
2196 domain));
2197 TALLOC_FREE(tmp_ctx);
2198 return false;
2201 trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2202 if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2203 DBG_WARNING("Trusted domain %s is not an outbound trust.\n",
2204 domain);
2205 TALLOC_FREE(tmp_ctx);
2206 return false;
2209 trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2210 if (trust_type == LSA_TRUST_TYPE_MIT) {
2211 DBG_WARNING("Trusted domain %s is not an AD trust "
2212 "(trustType == LSA_TRUST_TYPE_MIT).\n", domain);
2213 TALLOC_FREE(tmp_ctx);
2214 return false;
2217 password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2218 if (password_val == NULL) {
2219 DEBUG(2, ("Failed to get trusted domain password for %s, "
2220 "attribute trustAuthOutgoing not returned.\n", domain));
2221 TALLOC_FREE(tmp_ctx);
2222 return false;
2225 ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2226 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2227 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2228 DEBUG(0, ("Failed to get trusted domain password for %s, "
2229 "attribute trustAuthOutgoing could not be parsed %s.\n",
2230 domain,
2231 ndr_map_error2string(ndr_err)));
2232 TALLOC_FREE(tmp_ctx);
2233 return false;
2236 auth_array = &password_blob.current;
2238 for (i=0; i < auth_array->count; i++) {
2239 if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
2240 break;
2244 if (i == auth_array->count) {
2245 DEBUG(0, ("Trusted domain %s does not have a "
2246 "clear-text password stored\n",
2247 domain));
2248 TALLOC_FREE(tmp_ctx);
2249 return false;
2252 password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
2253 auth_array->array[i].AuthInfo.clear.size);
2256 * In the future, make this function return a
2257 * cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash()
2258 * but for now convert to UTF8 and fail if the string can not be converted.
2260 * We can't safely convert the random strings windows uses into
2261 * utf8.
2263 if (!convert_string_talloc(tmp_ctx,
2264 CH_UTF16MUNGED, CH_UTF8,
2265 password_utf16.data, password_utf16.length,
2266 (void *)&password_talloc,
2267 &password_len)) {
2268 DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
2269 " to UTF8. This may be a password set from Windows.\n",
2270 domain));
2271 TALLOC_FREE(tmp_ctx);
2272 return false;
2274 *pwd = SMB_STRNDUP(password_talloc, password_len);
2275 if (pass_last_set_time) {
2276 *pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
2279 if (sid != NULL) {
2280 sid_copy(sid, domain_sid);
2283 TALLOC_FREE(tmp_ctx);
2284 return true;
2287 static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
2288 const char *domain,
2289 TALLOC_CTX *mem_ctx,
2290 struct cli_credentials **_creds)
2292 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2293 m->private_data, struct pdb_samba_dsdb_state);
2294 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2295 const char * const attrs[] = {
2296 "securityIdentifier",
2297 "flatName",
2298 "trustPartner",
2299 "trustAuthOutgoing",
2300 "whenCreated",
2301 "msDS-SupportedEncryptionTypes",
2302 "trustAttributes",
2303 "trustDirection",
2304 "trustType",
2305 NULL
2307 struct ldb_message *msg;
2308 const struct ldb_val *password_val;
2309 int trust_direction_flags;
2310 int trust_type;
2311 int i;
2312 DATA_BLOB password_utf16 = {};
2313 struct samr_Password *password_nt = NULL;
2314 uint32_t password_version = 0;
2315 DATA_BLOB old_password_utf16 = {};
2316 struct samr_Password *old_password_nt = NULL;
2317 struct trustAuthInOutBlob password_blob;
2318 enum ndr_err_code ndr_err;
2319 NTSTATUS status;
2320 time_t last_set_time = 0;
2321 struct cli_credentials *creds = NULL;
2322 bool ok;
2323 const char *my_netbios_name = NULL;
2324 const char *my_netbios_domain = NULL;
2325 const char *my_dns_domain = NULL;
2326 const char *netbios_domain = NULL;
2327 char *account_name = NULL;
2328 char *principal_name = NULL;
2329 const char *dns_domain = NULL;
2331 status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2332 attrs, tmp_ctx, &msg);
2333 if (!NT_STATUS_IS_OK(status)) {
2335 * This can be called to work out of a domain is
2336 * trusted, rather than just to get the password
2338 DEBUG(2, ("Failed to get trusted domain password for %s - %s "
2339 "It may not be a trusted domain.\n", domain,
2340 nt_errstr(status)));
2341 TALLOC_FREE(tmp_ctx);
2342 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2345 netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2346 if (netbios_domain == NULL) {
2347 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2348 domain));
2349 TALLOC_FREE(tmp_ctx);
2350 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2353 dns_domain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2355 trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2356 if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2357 DBG_WARNING("Trusted domain %s is not an outbound trust.\n",
2358 domain);
2359 TALLOC_FREE(tmp_ctx);
2360 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2363 trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2364 if (trust_type == LSA_TRUST_TYPE_MIT) {
2365 DBG_WARNING("Trusted domain %s is not an AD trust "
2366 "(trustType == LSA_TRUST_TYPE_MIT).\n", domain);
2367 TALLOC_FREE(tmp_ctx);
2368 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2371 password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2372 if (password_val == NULL) {
2373 DEBUG(2, ("Failed to get trusted domain password for %s, "
2374 "attribute trustAuthOutgoing not returned.\n", domain));
2375 TALLOC_FREE(tmp_ctx);
2376 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2379 ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2380 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2381 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2382 DEBUG(0, ("Failed to get trusted domain password for %s, "
2383 "attribute trustAuthOutgoing could not be parsed %s.\n",
2384 domain,
2385 ndr_map_error2string(ndr_err)));
2386 TALLOC_FREE(tmp_ctx);
2387 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2390 for (i=0; i < password_blob.current.count; i++) {
2391 struct AuthenticationInformation *a =
2392 &password_blob.current.array[i];
2394 switch (a->AuthType) {
2395 case TRUST_AUTH_TYPE_NONE:
2396 break;
2398 case TRUST_AUTH_TYPE_VERSION:
2399 password_version = a->AuthInfo.version.version;
2400 break;
2402 case TRUST_AUTH_TYPE_CLEAR:
2403 last_set_time = nt_time_to_unix(a->LastUpdateTime);
2405 password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2406 a->AuthInfo.clear.size);
2407 password_nt = NULL;
2408 break;
2410 case TRUST_AUTH_TYPE_NT4OWF:
2411 if (password_utf16.length != 0) {
2412 break;
2415 last_set_time = nt_time_to_unix(a->LastUpdateTime);
2417 password_nt = &a->AuthInfo.nt4owf.password;
2418 break;
2422 for (i=0; i < password_blob.previous.count; i++) {
2423 struct AuthenticationInformation *a = &password_blob.previous.array[i];
2425 switch (a->AuthType) {
2426 case TRUST_AUTH_TYPE_NONE:
2427 break;
2429 case TRUST_AUTH_TYPE_VERSION:
2430 break;
2432 case TRUST_AUTH_TYPE_CLEAR:
2433 old_password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2434 a->AuthInfo.clear.size);
2435 old_password_nt = NULL;
2436 break;
2438 case TRUST_AUTH_TYPE_NT4OWF:
2439 if (old_password_utf16.length != 0) {
2440 break;
2443 old_password_nt = &a->AuthInfo.nt4owf.password;
2444 break;
2448 if (password_utf16.length == 0 && password_nt == NULL) {
2449 DEBUG(0, ("Trusted domain %s does not have a "
2450 "clear-text nor nt password stored\n",
2451 domain));
2452 TALLOC_FREE(tmp_ctx);
2453 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2456 my_netbios_name = lpcfg_netbios_name(state->lp_ctx);
2457 my_netbios_domain = lpcfg_workgroup(state->lp_ctx);
2458 my_dns_domain = lpcfg_dnsdomain(state->lp_ctx);
2460 creds = cli_credentials_init(tmp_ctx);
2461 if (creds == NULL) {
2462 TALLOC_FREE(tmp_ctx);
2463 return NT_STATUS_NO_MEMORY;
2466 ok = cli_credentials_set_workstation(creds, my_netbios_name, CRED_SPECIFIED);
2467 if (!ok) {
2468 TALLOC_FREE(tmp_ctx);
2469 return NT_STATUS_NO_MEMORY;
2472 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2473 if (!ok) {
2474 TALLOC_FREE(tmp_ctx);
2475 return NT_STATUS_NO_MEMORY;
2477 ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2478 if (!ok) {
2479 TALLOC_FREE(tmp_ctx);
2480 return NT_STATUS_NO_MEMORY;
2483 if (my_dns_domain != NULL && dns_domain != NULL) {
2484 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DNS_DOMAIN);
2485 account_name = talloc_asprintf(tmp_ctx, "%s.", my_dns_domain);
2486 if (account_name == NULL) {
2487 TALLOC_FREE(tmp_ctx);
2488 return NT_STATUS_NO_MEMORY;
2490 principal_name = talloc_asprintf(tmp_ctx, "%s$@%s", my_netbios_domain,
2491 cli_credentials_get_realm(creds));
2492 if (principal_name == NULL) {
2493 TALLOC_FREE(tmp_ctx);
2494 return NT_STATUS_NO_MEMORY;
2496 } else {
2497 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DOMAIN);
2498 account_name = talloc_asprintf(tmp_ctx, "%s$", my_netbios_domain);
2499 if (account_name == NULL) {
2500 TALLOC_FREE(tmp_ctx);
2501 return NT_STATUS_NO_MEMORY;
2503 principal_name = NULL;
2506 ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2507 if (!ok) {
2508 TALLOC_FREE(tmp_ctx);
2509 return NT_STATUS_NO_MEMORY;
2512 if (principal_name != NULL) {
2513 ok = cli_credentials_set_principal(creds, principal_name,
2514 CRED_SPECIFIED);
2515 if (!ok) {
2516 TALLOC_FREE(tmp_ctx);
2517 return NT_STATUS_NO_MEMORY;
2521 if (old_password_nt != NULL) {
2522 ok = cli_credentials_set_old_nt_hash(creds, old_password_nt);
2523 if (!ok) {
2524 TALLOC_FREE(tmp_ctx);
2525 return NT_STATUS_NO_MEMORY;
2529 if (old_password_utf16.length > 0) {
2530 ok = cli_credentials_set_old_utf16_password(creds,
2531 &old_password_utf16);
2532 if (!ok) {
2533 TALLOC_FREE(tmp_ctx);
2534 return NT_STATUS_NO_MEMORY;
2538 if (password_nt != NULL) {
2539 ok = cli_credentials_set_nt_hash(creds, password_nt,
2540 CRED_SPECIFIED);
2541 if (!ok) {
2542 TALLOC_FREE(tmp_ctx);
2543 return NT_STATUS_NO_MEMORY;
2547 if (password_utf16.length > 0) {
2548 ok = cli_credentials_set_utf16_password(creds,
2549 &password_utf16,
2550 CRED_SPECIFIED);
2551 if (!ok) {
2552 TALLOC_FREE(tmp_ctx);
2553 return NT_STATUS_NO_MEMORY;
2557 cli_credentials_set_password_last_changed_time(creds, last_set_time);
2558 cli_credentials_set_kvno(creds, password_version);
2560 if (password_utf16.length > 0 && dns_domain != NULL) {
2562 * Force kerberos if this is an active directory domain
2564 cli_credentials_set_kerberos_state(creds,
2565 CRED_USE_KERBEROS_REQUIRED,
2566 CRED_SPECIFIED);
2567 } else {
2569 * TODO: we should allow krb5 with the raw nt hash.
2571 cli_credentials_set_kerberos_state(creds,
2572 CRED_USE_KERBEROS_DISABLED,
2573 CRED_SPECIFIED);
2576 *_creds = talloc_move(mem_ctx, &creds);
2577 TALLOC_FREE(tmp_ctx);
2578 return NT_STATUS_OK;
2581 static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2582 const char* domain, const char* pwd,
2583 const struct dom_sid *sid)
2585 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2586 m->private_data, struct pdb_samba_dsdb_state);
2587 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2588 const char * const attrs[] = {
2589 "trustAuthOutgoing",
2590 "trustDirection",
2591 "trustType",
2592 NULL
2594 struct ldb_message *msg = NULL;
2595 int trust_direction_flags;
2596 int trust_type;
2597 uint32_t i; /* The same type as old_blob.current.count */
2598 const struct ldb_val *old_val = NULL;
2599 struct trustAuthInOutBlob old_blob = {};
2600 uint32_t old_version = 0;
2601 uint32_t new_version = 0;
2602 DATA_BLOB new_utf16 = {};
2603 struct trustAuthInOutBlob new_blob = {};
2604 struct ldb_val new_val = {};
2605 struct timeval tv = timeval_current();
2606 NTTIME now = timeval_to_nttime(&tv);
2607 enum ndr_err_code ndr_err;
2608 NTSTATUS status;
2609 bool ok;
2610 int ret;
2612 ret = ldb_transaction_start(state->ldb);
2613 if (ret != LDB_SUCCESS) {
2614 DEBUG(2, ("Failed to start transaction.\n"));
2615 TALLOC_FREE(tmp_ctx);
2616 return false;
2619 ok = samdb_is_pdc(state->ldb);
2620 if (!ok) {
2621 DEBUG(2, ("Password changes for domain %s are only allowed on a PDC.\n",
2622 domain));
2623 TALLOC_FREE(tmp_ctx);
2624 ldb_transaction_cancel(state->ldb);
2625 return false;
2628 status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2629 attrs, tmp_ctx, &msg);
2630 if (!NT_STATUS_IS_OK(status)) {
2632 * This can be called to work out of a domain is
2633 * trusted, rather than just to get the password
2635 DEBUG(2, ("Failed to get trusted domain password for %s - %s. "
2636 "It may not be a trusted domain.\n", domain,
2637 nt_errstr(status)));
2638 TALLOC_FREE(tmp_ctx);
2639 ldb_transaction_cancel(state->ldb);
2640 return false;
2643 trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2644 if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2645 DBG_WARNING("Trusted domain %s is not an outbound trust, can't set a password.\n",
2646 domain);
2647 TALLOC_FREE(tmp_ctx);
2648 ldb_transaction_cancel(state->ldb);
2649 return false;
2652 trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2653 switch (trust_type) {
2654 case LSA_TRUST_TYPE_DOWNLEVEL:
2655 case LSA_TRUST_TYPE_UPLEVEL:
2656 break;
2657 default:
2658 DEBUG(0, ("Trusted domain %s is of type 0x%X - "
2659 "password changes are not supported\n",
2660 domain, (unsigned)trust_type));
2661 TALLOC_FREE(tmp_ctx);
2662 ldb_transaction_cancel(state->ldb);
2663 return false;
2666 old_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2667 if (old_val != NULL) {
2668 ndr_err = ndr_pull_struct_blob(old_val, tmp_ctx, &old_blob,
2669 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2670 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2671 DEBUG(0, ("Failed to get trusted domain password for %s, "
2672 "attribute trustAuthOutgoing could not be parsed %s.\n",
2673 domain,
2674 ndr_map_error2string(ndr_err)));
2675 TALLOC_FREE(tmp_ctx);
2676 ldb_transaction_cancel(state->ldb);
2677 return false;
2681 for (i=0; i < old_blob.current.count; i++) {
2682 struct AuthenticationInformation *a =
2683 &old_blob.current.array[i];
2685 switch (a->AuthType) {
2686 case TRUST_AUTH_TYPE_NONE:
2687 break;
2689 case TRUST_AUTH_TYPE_VERSION:
2690 old_version = a->AuthInfo.version.version;
2691 break;
2693 case TRUST_AUTH_TYPE_CLEAR:
2694 break;
2696 case TRUST_AUTH_TYPE_NT4OWF:
2697 break;
2701 new_version = old_version + 1;
2702 ok = convert_string_talloc(tmp_ctx,
2703 CH_UNIX, CH_UTF16,
2704 pwd, strlen(pwd),
2705 (void *)&new_utf16.data,
2706 &new_utf16.length);
2707 if (!ok) {
2708 DEBUG(0, ("Failed to generate new_utf16 password for domain %s\n",
2709 domain));
2710 TALLOC_FREE(tmp_ctx);
2711 ldb_transaction_cancel(state->ldb);
2712 return false;
2715 if (new_utf16.length < 28) {
2716 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to short.\n",
2717 new_utf16.length,
2718 (unsigned)new_version,
2719 domain));
2720 TALLOC_FREE(tmp_ctx);
2721 ldb_transaction_cancel(state->ldb);
2722 return false;
2724 if (new_utf16.length > 498) {
2725 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to long.\n",
2726 new_utf16.length,
2727 (unsigned)new_version,
2728 domain));
2729 TALLOC_FREE(tmp_ctx);
2730 ldb_transaction_cancel(state->ldb);
2731 return false;
2734 new_blob.count = MAX(old_blob.current.count, 2);
2735 new_blob.current.array = talloc_zero_array(tmp_ctx,
2736 struct AuthenticationInformation,
2737 new_blob.count);
2738 if (new_blob.current.array == NULL) {
2739 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2740 (unsigned)new_blob.count));
2741 TALLOC_FREE(tmp_ctx);
2742 ldb_transaction_cancel(state->ldb);
2743 return false;
2745 new_blob.previous.array = talloc_zero_array(tmp_ctx,
2746 struct AuthenticationInformation,
2747 new_blob.count);
2748 if (new_blob.current.array == NULL) {
2749 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2750 (unsigned)new_blob.count));
2751 TALLOC_FREE(tmp_ctx);
2752 ldb_transaction_cancel(state->ldb);
2753 return false;
2756 for (i = 0; i < old_blob.current.count; i++) {
2757 new_blob.previous.array[i] = old_blob.current.array[i];
2758 new_blob.previous.count++;
2760 for (; i < new_blob.count; i++) {
2761 struct AuthenticationInformation *pi =
2762 &new_blob.previous.array[i];
2764 if (i == 0) {
2766 * new_blob.previous is still empty so
2767 * we'll do new_blob.previous = new_blob.current
2768 * below.
2770 break;
2773 pi->LastUpdateTime = now;
2774 pi->AuthType = TRUST_AUTH_TYPE_NONE;
2775 new_blob.previous.count++;
2778 for (i = 0; i < new_blob.count; i++) {
2779 struct AuthenticationInformation *ci =
2780 &new_blob.current.array[i];
2782 ci->LastUpdateTime = now;
2783 switch (i) {
2784 case 0:
2785 ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
2786 ci->AuthInfo.clear.size = new_utf16.length;
2787 ci->AuthInfo.clear.password = new_utf16.data;
2788 break;
2789 case 1:
2790 ci->AuthType = TRUST_AUTH_TYPE_VERSION;
2791 ci->AuthInfo.version.version = new_version;
2792 break;
2793 default:
2794 ci->AuthType = TRUST_AUTH_TYPE_NONE;
2795 break;
2798 new_blob.current.count++;
2801 if (new_blob.previous.count == 0) {
2802 TALLOC_FREE(new_blob.previous.array);
2803 new_blob.previous = new_blob.current;
2806 ndr_err = ndr_push_struct_blob(&new_val, tmp_ctx, &new_blob,
2807 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
2808 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2809 DEBUG(0, ("Failed to generate trustAuthOutgoing for "
2810 "trusted domain password for %s: %s.\n",
2811 domain, ndr_map_error2string(ndr_err)));
2812 TALLOC_FREE(tmp_ctx);
2813 ldb_transaction_cancel(state->ldb);
2814 return false;
2817 msg->num_elements = 0;
2818 ret = ldb_msg_append_value(msg, "trustAuthOutgoing",
2819 &new_val, LDB_FLAG_MOD_REPLACE);
2820 if (ret != LDB_SUCCESS) {
2821 DEBUG(0, ("ldb_msg_append_value() failed\n"));
2822 TALLOC_FREE(tmp_ctx);
2823 ldb_transaction_cancel(state->ldb);
2824 return false;
2827 ret = ldb_modify(state->ldb, msg);
2828 if (ret != LDB_SUCCESS) {
2829 DEBUG(0, ("Failed to replace trustAuthOutgoing for "
2830 "trusted domain password for %s: %s - %s\n",
2831 domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2832 TALLOC_FREE(tmp_ctx);
2833 ldb_transaction_cancel(state->ldb);
2834 return false;
2837 ret = ldb_transaction_commit(state->ldb);
2838 if (ret != LDB_SUCCESS) {
2839 DEBUG(0, ("Failed to commit trustAuthOutgoing for "
2840 "trusted domain password for %s: %s - %s\n",
2841 domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2842 TALLOC_FREE(tmp_ctx);
2843 return false;
2846 DEBUG(1, ("Added new_version[%u] to trustAuthOutgoing for "
2847 "trusted domain password for %s.\n",
2848 (unsigned)new_version, domain));
2849 TALLOC_FREE(tmp_ctx);
2850 return true;
2853 static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2854 const char *domain)
2856 return false;
2859 static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2860 TALLOC_CTX *mem_ctx,
2861 uint32_t *_num_domains,
2862 struct trustdom_info ***_domains)
2864 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2865 m->private_data, struct pdb_samba_dsdb_state);
2866 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2867 const char * const attrs[] = {
2868 "securityIdentifier",
2869 "flatName",
2870 "trustDirection",
2871 NULL
2873 struct ldb_result *res = NULL;
2874 unsigned int i;
2875 struct trustdom_info **domains = NULL;
2876 NTSTATUS status;
2877 uint32_t di = 0;
2879 *_num_domains = 0;
2880 *_domains = NULL;
2882 status = dsdb_trust_search_tdos(state->ldb, NULL,
2883 attrs, tmp_ctx, &res);
2884 if (!NT_STATUS_IS_OK(status)) {
2885 DBG_ERR("dsdb_trust_search_tdos() - %s\n", nt_errstr(status));
2886 TALLOC_FREE(tmp_ctx);
2887 return status;
2890 if (res->count == 0) {
2891 TALLOC_FREE(tmp_ctx);
2892 return NT_STATUS_OK;
2895 domains = talloc_zero_array(tmp_ctx, struct trustdom_info *,
2896 res->count);
2897 if (domains == NULL) {
2898 TALLOC_FREE(tmp_ctx);
2899 return NT_STATUS_NO_MEMORY;
2902 for (i = 0; i < res->count; i++) {
2903 struct ldb_message *msg = res->msgs[i];
2904 struct trustdom_info *d = NULL;
2905 const char *name = NULL;
2906 struct dom_sid *sid = NULL;
2907 uint32_t direction;
2909 d = talloc_zero(domains, struct trustdom_info);
2910 if (d == NULL) {
2911 TALLOC_FREE(tmp_ctx);
2912 return NT_STATUS_NO_MEMORY;
2915 name = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2916 if (name == NULL) {
2917 TALLOC_FREE(tmp_ctx);
2918 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2920 sid = samdb_result_dom_sid(msg, msg, "securityIdentifier");
2921 if (sid == NULL) {
2922 continue;
2925 direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
2926 if (!(direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2927 continue;
2930 d->name = talloc_strdup(d, name);
2931 if (d->name == NULL) {
2932 TALLOC_FREE(tmp_ctx);
2933 return NT_STATUS_NO_MEMORY;
2935 d->sid = *sid;
2937 domains[di++] = d;
2940 domains = talloc_realloc(domains, domains, struct trustdom_info *, di);
2941 *_domains = talloc_move(mem_ctx, &domains);
2942 *_num_domains = di;
2943 TALLOC_FREE(tmp_ctx);
2944 return NT_STATUS_OK;
2947 static NTSTATUS pdb_samba_dsdb_msg_to_trusted_domain(const struct ldb_message *msg,
2948 TALLOC_CTX *mem_ctx,
2949 struct pdb_trusted_domain **_d)
2951 struct pdb_trusted_domain *d = NULL;
2952 const char *str = NULL;
2953 struct dom_sid *sid = NULL;
2954 const struct ldb_val *val = NULL;
2955 uint64_t val64;
2957 *_d = NULL;
2959 d = talloc_zero(mem_ctx, struct pdb_trusted_domain);
2960 if (d == NULL) {
2961 return NT_STATUS_NO_MEMORY;
2964 str = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2965 if (str == NULL) {
2966 TALLOC_FREE(d);
2967 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2969 d->netbios_name = talloc_strdup(d, str);
2970 if (d->netbios_name == NULL) {
2971 TALLOC_FREE(d);
2972 return NT_STATUS_NO_MEMORY;
2975 str = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2976 if (str != NULL) {
2977 d->domain_name = talloc_strdup(d, str);
2978 if (d->domain_name == NULL) {
2979 TALLOC_FREE(d);
2980 return NT_STATUS_NO_MEMORY;
2984 sid = samdb_result_dom_sid(d, msg, "securityIdentifier");
2985 if (sid != NULL) {
2986 d->security_identifier = *sid;
2987 TALLOC_FREE(sid);
2990 val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2991 if (val != NULL) {
2992 d->trust_auth_outgoing = data_blob_dup_talloc(d, *val);
2993 if (d->trust_auth_outgoing.data == NULL) {
2994 TALLOC_FREE(d);
2995 return NT_STATUS_NO_MEMORY;
2998 val = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
2999 if (val != NULL) {
3000 d->trust_auth_incoming = data_blob_dup_talloc(d, *val);
3001 if (d->trust_auth_incoming.data == NULL) {
3002 TALLOC_FREE(d);
3003 return NT_STATUS_NO_MEMORY;
3007 d->trust_direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
3008 d->trust_type = ldb_msg_find_attr_as_uint(msg, "trustType", 0);
3009 d->trust_attributes = ldb_msg_find_attr_as_uint(msg, "trustAttributes", 0);
3011 val64 = ldb_msg_find_attr_as_uint64(msg, "trustPosixOffset", UINT64_MAX);
3012 if (val64 != UINT64_MAX) {
3013 d->trust_posix_offset = talloc(d, uint32_t);
3014 if (d->trust_posix_offset == NULL) {
3015 TALLOC_FREE(d);
3016 return NT_STATUS_NO_MEMORY;
3018 *d->trust_posix_offset = (uint32_t)val64;
3021 val64 = ldb_msg_find_attr_as_uint64(msg, "msDS-SupportedEncryptionTypes", UINT64_MAX);
3022 if (val64 != UINT64_MAX) {
3023 d->supported_enc_type = talloc(d, uint32_t);
3024 if (d->supported_enc_type == NULL) {
3025 TALLOC_FREE(d);
3026 return NT_STATUS_NO_MEMORY;
3028 *d->supported_enc_type = (uint32_t)val64;
3031 val = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3032 if (val != NULL) {
3033 d->trust_forest_trust_info = data_blob_dup_talloc(d, *val);
3034 if (d->trust_forest_trust_info.data == NULL) {
3035 TALLOC_FREE(d);
3036 return NT_STATUS_NO_MEMORY;
3040 *_d = d;
3041 return NT_STATUS_OK;
3044 static NTSTATUS pdb_samba_dsdb_get_trusted_domain(struct pdb_methods *m,
3045 TALLOC_CTX *mem_ctx,
3046 const char *domain,
3047 struct pdb_trusted_domain **td)
3049 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3050 m->private_data, struct pdb_samba_dsdb_state);
3051 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3052 const char * const attrs[] = {
3053 "securityIdentifier",
3054 "flatName",
3055 "trustPartner",
3056 "trustAuthOutgoing",
3057 "trustAuthIncoming",
3058 "trustAttributes",
3059 "trustDirection",
3060 "trustType",
3061 "trustPosixOffset",
3062 "msDS-SupportedEncryptionTypes",
3063 "msDS-TrustForestTrustInfo",
3064 NULL
3066 struct ldb_message *msg = NULL;
3067 struct pdb_trusted_domain *d = NULL;
3068 NTSTATUS status;
3070 status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
3071 attrs, tmp_ctx, &msg);
3072 if (!NT_STATUS_IS_OK(status)) {
3073 DBG_ERR("dsdb_trust_search_tdo(%s) - %s\n",
3074 domain, nt_errstr(status));
3075 TALLOC_FREE(tmp_ctx);
3076 return status;
3079 status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3080 if (!NT_STATUS_IS_OK(status)) {
3081 DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s\n",
3082 domain, nt_errstr(status));
3083 TALLOC_FREE(tmp_ctx);
3084 return status;
3087 *td = d;
3088 TALLOC_FREE(tmp_ctx);
3089 return NT_STATUS_OK;
3092 static NTSTATUS pdb_samba_dsdb_get_trusted_domain_by_sid(struct pdb_methods *m,
3093 TALLOC_CTX *mem_ctx,
3094 struct dom_sid *sid,
3095 struct pdb_trusted_domain **td)
3097 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3098 m->private_data, struct pdb_samba_dsdb_state);
3099 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3100 const char * const attrs[] = {
3101 "securityIdentifier",
3102 "flatName",
3103 "trustPartner",
3104 "trustAuthOutgoing",
3105 "trustAuthIncoming",
3106 "trustAttributes",
3107 "trustDirection",
3108 "trustType",
3109 "trustPosixOffset",
3110 "msDS-SupportedEncryptionTypes",
3111 "msDS-TrustForestTrustInfo",
3112 NULL
3114 struct ldb_message *msg = NULL;
3115 struct pdb_trusted_domain *d = NULL;
3116 struct dom_sid_buf buf;
3117 NTSTATUS status;
3119 status = dsdb_trust_search_tdo_by_sid(state->ldb, sid,
3120 attrs, tmp_ctx, &msg);
3121 if (!NT_STATUS_IS_OK(status)) {
3122 DBG_ERR("dsdb_trust_search_tdo_by_sid(%s) - %s\n",
3123 dom_sid_str_buf(sid, &buf),
3124 nt_errstr(status));
3125 TALLOC_FREE(tmp_ctx);
3126 return status;
3129 status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3130 if (!NT_STATUS_IS_OK(status)) {
3131 DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s\n",
3132 dom_sid_str_buf(sid, &buf),
3133 nt_errstr(status));
3134 TALLOC_FREE(tmp_ctx);
3135 return status;
3138 *td = d;
3139 TALLOC_FREE(tmp_ctx);
3140 return NT_STATUS_OK;
3143 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
3144 struct ldb_context *sam_ldb,
3145 struct ldb_dn *base_dn,
3146 const char *netbios_name,
3147 struct trustAuthInOutBlob *taiob)
3149 struct ldb_request *req = NULL;
3150 struct ldb_message *msg = NULL;
3151 struct ldb_dn *dn = NULL;
3152 uint32_t i;
3153 int ret;
3154 bool ok;
3156 dn = ldb_dn_copy(mem_ctx, base_dn);
3157 if (dn == NULL) {
3158 return NT_STATUS_NO_MEMORY;
3160 ok = ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name);
3161 if (!ok) {
3162 return NT_STATUS_NO_MEMORY;
3165 msg = ldb_msg_new(mem_ctx);
3166 if (msg == NULL) {
3167 return NT_STATUS_NO_MEMORY;
3169 msg->dn = dn;
3171 ret = ldb_msg_add_string(msg, "objectClass", "user");
3172 if (ret != LDB_SUCCESS) {
3173 return NT_STATUS_NO_MEMORY;
3176 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
3177 if (ret != LDB_SUCCESS) {
3178 return NT_STATUS_NO_MEMORY;
3181 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
3182 UF_INTERDOMAIN_TRUST_ACCOUNT);
3183 if (ret != LDB_SUCCESS) {
3184 return NT_STATUS_NO_MEMORY;
3187 for (i = 0; i < taiob->count; i++) {
3188 struct AuthenticationInformation *auth_info =
3189 &taiob->current.array[i];
3190 const char *attribute = NULL;
3191 struct ldb_val v;
3193 switch (taiob->current.array[i].AuthType) {
3194 case TRUST_AUTH_TYPE_NT4OWF:
3195 attribute = "unicodePwd";
3196 v.data = (uint8_t *)&auth_info->AuthInfo.nt4owf.password;
3197 v.length = 16;
3198 break;
3200 case TRUST_AUTH_TYPE_CLEAR:
3201 attribute = "clearTextPassword";
3202 v.data = auth_info->AuthInfo.clear.password;
3203 v.length = auth_info->AuthInfo.clear.size;
3204 break;
3206 default:
3207 continue;
3210 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
3211 if (ret != LDB_SUCCESS) {
3212 return NT_STATUS_NO_MEMORY;
3216 /* create the trusted_domain user account */
3217 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
3218 ldb_op_default_callback, NULL);
3219 if (ret != LDB_SUCCESS) {
3220 return NT_STATUS_NO_MEMORY;
3223 ret = ldb_request_add_control(
3224 req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
3225 false, NULL);
3226 if (ret != LDB_SUCCESS) {
3227 return NT_STATUS_NO_MEMORY;
3230 ret = dsdb_autotransaction_request(sam_ldb, req);
3231 if (ret != LDB_SUCCESS) {
3232 DEBUG(0,("Failed to create user record %s: %s\n",
3233 ldb_dn_get_linearized(msg->dn),
3234 ldb_errstring(sam_ldb)));
3236 switch (ret) {
3237 case LDB_ERR_ENTRY_ALREADY_EXISTS:
3238 return NT_STATUS_DOMAIN_EXISTS;
3239 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3240 return NT_STATUS_ACCESS_DENIED;
3241 default:
3242 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3246 return NT_STATUS_OK;
3249 static NTSTATUS pdb_samba_dsdb_set_trusted_domain(struct pdb_methods *methods,
3250 const char* domain,
3251 const struct pdb_trusted_domain *td)
3253 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3254 methods->private_data, struct pdb_samba_dsdb_state);
3255 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3256 bool in_txn = false;
3257 struct ldb_dn *base_dn = NULL;
3258 struct ldb_message *msg = NULL;
3259 const char *attrs[] = {
3260 NULL
3262 char *netbios_encoded = NULL;
3263 char *dns_encoded = NULL;
3264 char *sid_encoded = NULL;
3265 int ret;
3266 struct trustAuthInOutBlob taiob;
3267 enum ndr_err_code ndr_err;
3268 NTSTATUS status;
3269 bool ok;
3271 base_dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(state->ldb));
3272 if (base_dn == NULL) {
3273 TALLOC_FREE(tmp_ctx);
3274 status = NT_STATUS_NO_MEMORY;
3275 goto out;
3278 * We expect S-1-5-21-A-B-C, but we don't
3279 * allow S-1-5-21-0-0-0 as this is used
3280 * for claims and compound identities.
3282 ok = dom_sid_is_valid_account_domain(&td->security_identifier);
3283 if (!ok) {
3284 status = NT_STATUS_INVALID_PARAMETER;
3285 goto out;
3288 if (strequal(td->netbios_name, "BUILTIN")) {
3289 status = NT_STATUS_INVALID_PARAMETER;
3290 goto out;
3292 if (strequal(td->domain_name, "BUILTIN")) {
3293 status = NT_STATUS_INVALID_PARAMETER;
3294 goto out;
3297 dns_encoded = ldb_binary_encode_string(tmp_ctx, td->domain_name);
3298 if (dns_encoded == NULL) {
3299 status = NT_STATUS_NO_MEMORY;
3300 goto out;
3302 netbios_encoded = ldb_binary_encode_string(tmp_ctx, td->netbios_name);
3303 if (netbios_encoded == NULL) {
3304 status =NT_STATUS_NO_MEMORY;
3305 goto out;
3307 sid_encoded = ldap_encode_ndr_dom_sid(tmp_ctx, &td->security_identifier);
3308 if (sid_encoded == NULL) {
3309 status = NT_STATUS_NO_MEMORY;
3310 goto out;
3313 ok = samdb_is_pdc(state->ldb);
3314 if (!ok) {
3315 DBG_ERR("Adding TDO is only allowed on a PDC.\n");
3316 TALLOC_FREE(tmp_ctx);
3317 status = NT_STATUS_INVALID_DOMAIN_ROLE;
3318 goto out;
3321 status = dsdb_trust_search_tdo(state->ldb,
3322 td->netbios_name,
3323 td->domain_name,
3324 attrs,
3325 tmp_ctx,
3326 &msg);
3327 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3328 DBG_ERR("dsdb_trust_search_tdo returned %s\n",
3329 nt_errstr(status));
3330 status = NT_STATUS_INVALID_DOMAIN_STATE;
3331 goto out;
3334 ret = ldb_transaction_start(state->ldb);
3335 if (ret != LDB_SUCCESS) {
3336 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3337 goto out;
3339 in_txn = true;
3341 msg = ldb_msg_new(tmp_ctx);
3342 if (msg == NULL) {
3343 status = NT_STATUS_NO_MEMORY;
3344 goto out;
3347 msg->dn = samdb_system_container_dn(state->ldb, tmp_ctx);
3348 if (msg->dn == NULL) {
3349 status = NT_STATUS_NO_MEMORY;
3350 goto out;
3353 ok = ldb_dn_add_child_fmt(msg->dn, "cn=%s", td->domain_name);
3354 if (!ok) {
3355 status = NT_STATUS_NO_MEMORY;
3356 goto out;
3359 ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
3360 if (ret != LDB_SUCCESS) {
3361 status = NT_STATUS_NO_MEMORY;
3362 goto out;
3365 ret = ldb_msg_add_string(msg, "flatname", td->netbios_name);
3366 if (ret != LDB_SUCCESS) {
3367 status = NT_STATUS_NO_MEMORY;
3368 goto out;
3371 ret = ldb_msg_add_string(msg, "trustPartner", td->domain_name);
3372 if (ret != LDB_SUCCESS) {
3373 status = NT_STATUS_NO_MEMORY;
3374 goto out;
3377 ret = samdb_msg_add_dom_sid(state->ldb,
3378 tmp_ctx,
3379 msg,
3380 "securityIdentifier",
3381 &td->security_identifier);
3382 if (ret != LDB_SUCCESS) {
3383 status = NT_STATUS_NO_MEMORY;
3384 goto out;
3387 ret = samdb_msg_add_int(state->ldb,
3388 tmp_ctx,
3389 msg,
3390 "trustType",
3391 td->trust_type);
3392 if (ret != LDB_SUCCESS) {
3393 status = NT_STATUS_NO_MEMORY;
3394 goto out;
3397 ret = samdb_msg_add_int(state->ldb,
3398 tmp_ctx,
3399 msg,
3400 "trustAttributes",
3401 td->trust_attributes);
3402 if (ret != LDB_SUCCESS) {
3403 status =NT_STATUS_NO_MEMORY;
3404 goto out;
3407 ret = samdb_msg_add_int(state->ldb,
3408 tmp_ctx,
3409 msg,
3410 "trustDirection",
3411 td->trust_direction);
3412 if (ret != LDB_SUCCESS) {
3413 status = NT_STATUS_NO_MEMORY;
3414 goto out;
3417 if (td->trust_auth_incoming.data != NULL) {
3418 ret = ldb_msg_add_value(msg,
3419 "trustAuthIncoming",
3420 &td->trust_auth_incoming,
3421 NULL);
3422 if (ret != LDB_SUCCESS) {
3423 status = NT_STATUS_NO_MEMORY;
3424 goto out;
3427 if (td->trust_auth_outgoing.data != NULL) {
3428 ret = ldb_msg_add_value(msg,
3429 "trustAuthOutgoing",
3430 &td->trust_auth_outgoing,
3431 NULL);
3432 if (ret != LDB_SUCCESS) {
3433 status = NT_STATUS_NO_MEMORY;
3434 goto out;
3438 /* create the trusted_domain */
3439 ret = ldb_add(state->ldb, msg);
3440 switch (ret) {
3441 case LDB_SUCCESS:
3442 break;
3444 case LDB_ERR_ENTRY_ALREADY_EXISTS:
3445 DBG_ERR("Failed to create trusted domain record %s: %s\n",
3446 ldb_dn_get_linearized(msg->dn),
3447 ldb_errstring(state->ldb));
3448 status = NT_STATUS_DOMAIN_EXISTS;
3449 goto out;
3451 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3452 DBG_ERR("Failed to create trusted domain record %s: %s\n",
3453 ldb_dn_get_linearized(msg->dn),
3454 ldb_errstring(state->ldb));
3455 status = NT_STATUS_ACCESS_DENIED;
3456 goto out;
3458 default:
3459 DBG_ERR("Failed to create trusted domain record %s: %s\n",
3460 ldb_dn_get_linearized(msg->dn),
3461 ldb_errstring(state->ldb));
3462 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3463 goto out;
3466 ndr_err = ndr_pull_struct_blob(
3467 &td->trust_auth_outgoing,
3468 tmp_ctx,
3469 &taiob,
3470 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
3471 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3472 status = ndr_map_error2ntstatus(ndr_err);
3473 goto out;
3476 if (td->trust_direction == LSA_TRUST_DIRECTION_INBOUND) {
3477 status = add_trust_user(tmp_ctx,
3478 state->ldb,
3479 base_dn,
3480 td->netbios_name,
3481 &taiob);
3482 if (!NT_STATUS_IS_OK(status)) {
3483 goto out;
3487 ret = ldb_transaction_commit(state->ldb);
3488 if (ret != LDB_SUCCESS) {
3489 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3491 in_txn = false;
3494 * TODO: Notify winbindd that we have a new trust
3497 status = NT_STATUS_OK;
3499 out:
3500 if (in_txn) {
3501 ldb_transaction_cancel(state->ldb);
3503 TALLOC_FREE(tmp_ctx);
3504 return status;
3507 static NTSTATUS delete_trust_user(TALLOC_CTX *mem_ctx,
3508 struct pdb_samba_dsdb_state *state,
3509 const char *trust_user)
3511 const char *attrs[] = { "userAccountControl", NULL };
3512 struct ldb_message **msgs;
3513 uint32_t uac;
3514 int ret;
3516 ret = gendb_search(state->ldb,
3517 mem_ctx,
3518 ldb_get_default_basedn(state->ldb),
3519 &msgs,
3520 attrs,
3521 "samAccountName=%s$",
3522 trust_user);
3523 if (ret > 1) {
3524 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3527 if (ret == 0) {
3528 return NT_STATUS_OK;
3531 uac = ldb_msg_find_attr_as_uint(msgs[0],
3532 "userAccountControl",
3534 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3535 return NT_STATUS_OBJECT_NAME_COLLISION;
3538 ret = ldb_delete(state->ldb, msgs[0]->dn);
3539 switch (ret) {
3540 case LDB_SUCCESS:
3541 break;
3542 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3543 return NT_STATUS_ACCESS_DENIED;
3544 default:
3545 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3548 return NT_STATUS_OK;
3551 static NTSTATUS pdb_samba_dsdb_del_trusted_domain(struct pdb_methods *methods,
3552 const char *domain)
3554 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3555 methods->private_data, struct pdb_samba_dsdb_state);
3556 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3557 struct pdb_trusted_domain *td = NULL;
3558 struct ldb_dn *tdo_dn = NULL;
3559 bool in_txn = false;
3560 NTSTATUS status;
3561 int ret;
3562 bool ok;
3564 status = pdb_samba_dsdb_get_trusted_domain(methods,
3565 tmp_ctx,
3566 domain,
3567 &td);
3568 if (!NT_STATUS_IS_OK(status)) {
3569 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3570 DBG_ERR("Searching TDO for %s returned %s\n",
3571 domain, nt_errstr(status));
3572 return status;
3574 DBG_NOTICE("No TDO object for %s\n", domain);
3575 return NT_STATUS_OK;
3578 tdo_dn = samdb_system_container_dn(state->ldb, tmp_ctx);
3579 if (tdo_dn == NULL) {
3580 status = NT_STATUS_NO_MEMORY;
3581 goto out;
3584 ok = ldb_dn_add_child_fmt(tdo_dn, "cn=%s", domain);
3585 if (!ok) {
3586 TALLOC_FREE(tmp_ctx);
3587 status = NT_STATUS_NO_MEMORY;
3588 goto out;
3591 ret = ldb_transaction_start(state->ldb);
3592 if (ret != LDB_SUCCESS) {
3593 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3594 goto out;
3596 in_txn = true;
3598 ret = ldb_delete(state->ldb, tdo_dn);
3599 if (ret != LDB_SUCCESS) {
3600 status = NT_STATUS_INVALID_HANDLE;
3601 goto out;
3604 if (td->trust_direction == LSA_TRUST_DIRECTION_INBOUND) {
3605 status = delete_trust_user(tmp_ctx, state, domain);
3606 if (!NT_STATUS_IS_OK(status)) {
3607 goto out;
3611 ret = ldb_transaction_commit(state->ldb);
3612 if (ret != LDB_SUCCESS) {
3613 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3614 goto out;
3616 in_txn = false;
3618 status = NT_STATUS_OK;
3620 out:
3621 if (in_txn) {
3622 ldb_transaction_cancel(state->ldb);
3624 TALLOC_FREE(tmp_ctx);
3626 return status;
3629 static NTSTATUS pdb_samba_dsdb_enum_trusted_domains(struct pdb_methods *m,
3630 TALLOC_CTX *mem_ctx,
3631 uint32_t *_num_domains,
3632 struct pdb_trusted_domain ***_domains)
3634 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3635 m->private_data, struct pdb_samba_dsdb_state);
3636 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3637 const char * const attrs[] = {
3638 "securityIdentifier",
3639 "flatName",
3640 "trustPartner",
3641 "trustAuthOutgoing",
3642 "trustAuthIncoming",
3643 "trustAttributes",
3644 "trustDirection",
3645 "trustType",
3646 "trustPosixOffset",
3647 "msDS-SupportedEncryptionTypes",
3648 "msDS-TrustForestTrustInfo",
3649 NULL
3651 struct ldb_result *res = NULL;
3652 unsigned int i;
3653 struct pdb_trusted_domain **domains = NULL;
3654 NTSTATUS status;
3655 uint32_t di = 0;
3657 *_num_domains = 0;
3658 *_domains = NULL;
3660 status = dsdb_trust_search_tdos(state->ldb, NULL,
3661 attrs, tmp_ctx, &res);
3662 if (!NT_STATUS_IS_OK(status)) {
3663 DBG_ERR("dsdb_trust_search_tdos() - %s\n", nt_errstr(status));
3664 TALLOC_FREE(tmp_ctx);
3665 return status;
3668 if (res->count == 0) {
3669 TALLOC_FREE(tmp_ctx);
3670 return NT_STATUS_OK;
3673 domains = talloc_zero_array(tmp_ctx, struct pdb_trusted_domain *,
3674 res->count);
3675 if (domains == NULL) {
3676 TALLOC_FREE(tmp_ctx);
3677 return NT_STATUS_NO_MEMORY;
3680 for (i = 0; i < res->count; i++) {
3681 struct ldb_message *msg = res->msgs[i];
3682 struct pdb_trusted_domain *d = NULL;
3684 status = pdb_samba_dsdb_msg_to_trusted_domain(msg, domains, &d);
3685 if (!NT_STATUS_IS_OK(status)) {
3686 DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain() - %s\n",
3687 nt_errstr(status));
3688 TALLOC_FREE(tmp_ctx);
3689 return status;
3692 domains[di++] = d;
3695 domains = talloc_realloc(domains, domains, struct pdb_trusted_domain *,
3696 di);
3697 *_domains = talloc_move(mem_ctx, &domains);
3698 *_num_domains = di;
3699 TALLOC_FREE(tmp_ctx);
3700 return NT_STATUS_OK;
3703 static bool pdb_samba_dsdb_is_responsible_for_wellknown(struct pdb_methods *m)
3705 return true;
3708 static bool pdb_samba_dsdb_is_responsible_for_everything_else(struct pdb_methods *m)
3710 return true;
3713 static void pdb_samba_dsdb_init_methods(struct pdb_methods *m)
3715 m->name = "samba_dsdb";
3716 m->get_domain_info = pdb_samba_dsdb_get_domain_info;
3717 m->getsampwnam = pdb_samba_dsdb_getsampwnam;
3718 m->getsampwsid = pdb_samba_dsdb_getsampwsid;
3719 m->create_user = pdb_samba_dsdb_create_user;
3720 m->delete_user = pdb_samba_dsdb_delete_user;
3721 m->add_sam_account = pdb_samba_dsdb_add_sam_account;
3722 m->update_sam_account = pdb_samba_dsdb_update_sam_account;
3723 m->delete_sam_account = pdb_samba_dsdb_delete_sam_account;
3724 m->rename_sam_account = pdb_samba_dsdb_rename_sam_account;
3725 m->update_login_attempts = pdb_samba_dsdb_update_login_attempts;
3726 m->getgrsid = pdb_samba_dsdb_getgrsid;
3727 m->getgrgid = pdb_samba_dsdb_getgrgid;
3728 m->getgrnam = pdb_samba_dsdb_getgrnam;
3729 m->create_dom_group = pdb_samba_dsdb_create_dom_group;
3730 m->delete_dom_group = pdb_samba_dsdb_delete_dom_group;
3731 m->add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry;
3732 m->update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry;
3733 m->delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry;
3734 m->enum_group_mapping = pdb_samba_dsdb_enum_group_mapping;
3735 m->enum_group_members = pdb_samba_dsdb_enum_group_members;
3736 m->enum_group_memberships = pdb_samba_dsdb_enum_group_memberships;
3737 m->set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group;
3738 m->add_groupmem = pdb_samba_dsdb_add_groupmem;
3739 m->del_groupmem = pdb_samba_dsdb_del_groupmem;
3740 m->create_alias = pdb_samba_dsdb_create_alias;
3741 m->delete_alias = pdb_samba_dsdb_delete_alias;
3742 m->get_aliasinfo = pdb_default_get_aliasinfo;
3743 m->add_aliasmem = pdb_samba_dsdb_add_aliasmem;
3744 m->del_aliasmem = pdb_samba_dsdb_del_aliasmem;
3745 m->enum_aliasmem = pdb_samba_dsdb_enum_aliasmem;
3746 m->enum_alias_memberships = pdb_samba_dsdb_enum_alias_memberships;
3747 m->lookup_rids = pdb_samba_dsdb_lookup_rids;
3748 m->lookup_names = pdb_samba_dsdb_lookup_names;
3749 m->get_account_policy = pdb_samba_dsdb_get_account_policy;
3750 m->set_account_policy = pdb_samba_dsdb_set_account_policy;
3751 m->get_seq_num = pdb_samba_dsdb_get_seq_num;
3752 m->search_users = pdb_samba_dsdb_search_users;
3753 m->search_groups = pdb_samba_dsdb_search_groups;
3754 m->search_aliases = pdb_samba_dsdb_search_aliases;
3755 m->id_to_sid = pdb_samba_dsdb_id_to_sid;
3756 m->sid_to_id = pdb_samba_dsdb_sid_to_id;
3757 m->capabilities = pdb_samba_dsdb_capabilities;
3758 m->new_rid = pdb_samba_dsdb_new_rid;
3759 m->get_trusteddom_pw = pdb_samba_dsdb_get_trusteddom_pw;
3760 m->get_trusteddom_creds = pdb_samba_dsdb_get_trusteddom_creds;
3761 m->set_trusteddom_pw = pdb_samba_dsdb_set_trusteddom_pw;
3762 m->del_trusteddom_pw = pdb_samba_dsdb_del_trusteddom_pw;
3763 m->enum_trusteddoms = pdb_samba_dsdb_enum_trusteddoms;
3764 m->get_trusted_domain = pdb_samba_dsdb_get_trusted_domain;
3765 m->get_trusted_domain_by_sid = pdb_samba_dsdb_get_trusted_domain_by_sid;
3766 m->set_trusted_domain = pdb_samba_dsdb_set_trusted_domain;
3767 m->del_trusted_domain = pdb_samba_dsdb_del_trusted_domain;
3768 m->enum_trusted_domains = pdb_samba_dsdb_enum_trusted_domains;
3769 m->is_responsible_for_wellknown =
3770 pdb_samba_dsdb_is_responsible_for_wellknown;
3771 m->is_responsible_for_everything_else =
3772 pdb_samba_dsdb_is_responsible_for_everything_else;
3775 static void free_private_data(void **vp)
3777 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3778 *vp, struct pdb_samba_dsdb_state);
3779 talloc_unlink(state, state->ldb);
3780 return;
3783 static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m)
3785 struct pdb_domain_info *dom_info;
3786 struct dom_sid stored_sid;
3787 struct GUID stored_guid;
3788 bool sid_exists_and_matches = false;
3789 bool guid_exists_and_matches = false;
3790 bool ret;
3792 dom_info = pdb_samba_dsdb_get_domain_info(m, m);
3793 if (!dom_info) {
3794 return NT_STATUS_UNSUCCESSFUL;
3797 ret = secrets_fetch_domain_sid(dom_info->name, &stored_sid);
3798 if (ret) {
3799 if (dom_sid_equal(&stored_sid, &dom_info->sid)) {
3800 sid_exists_and_matches = true;
3804 if (sid_exists_and_matches == false) {
3805 secrets_clear_domain_protection(dom_info->name);
3806 ret = secrets_store_domain_sid(dom_info->name,
3807 &dom_info->sid);
3808 ret &= secrets_mark_domain_protected(dom_info->name);
3809 if (!ret) {
3810 goto done;
3814 ret = secrets_fetch_domain_guid(dom_info->name, &stored_guid);
3815 if (ret) {
3816 if (GUID_equal(&stored_guid, &dom_info->guid)) {
3817 guid_exists_and_matches = true;
3821 if (guid_exists_and_matches == false) {
3822 secrets_clear_domain_protection(dom_info->name);
3823 ret = secrets_store_domain_guid(dom_info->name,
3824 &dom_info->guid);
3825 ret &= secrets_mark_domain_protected(dom_info->name);
3826 if (!ret) {
3827 goto done;
3831 done:
3832 TALLOC_FREE(dom_info);
3833 if (!ret) {
3834 return NT_STATUS_UNSUCCESSFUL;
3836 return NT_STATUS_OK;
3839 static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
3840 const char *location)
3842 struct pdb_methods *m;
3843 struct pdb_samba_dsdb_state *state;
3844 NTSTATUS status;
3845 char *errstring = NULL;
3846 int ret;
3848 if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
3849 return status;
3852 state = talloc_zero(m, struct pdb_samba_dsdb_state);
3853 if (state == NULL) {
3854 goto nomem;
3856 m->private_data = state;
3857 m->free_private_data = free_private_data;
3858 pdb_samba_dsdb_init_methods(m);
3860 state->ev = s4_event_context_init(state);
3861 if (!state->ev) {
3862 DEBUG(0, ("s4_event_context_init failed\n"));
3863 goto nomem;
3866 state->lp_ctx = loadparm_init_s3(state, loadparm_s3_helpers());
3867 if (state->lp_ctx == NULL) {
3868 DEBUG(0, ("loadparm_init_s3 failed\n"));
3869 goto nomem;
3872 if (location == NULL) {
3873 location = "sam.ldb";
3876 ret = samdb_connect_url(state,
3877 state->ev,
3878 state->lp_ctx,
3879 system_session(state->lp_ctx),
3881 location,
3882 NULL,
3883 &state->ldb,
3884 &errstring);
3886 if (!state->ldb) {
3887 DEBUG(0, ("samdb_connect failed: %s: %s\n",
3888 errstring, ldb_strerror(ret)));
3889 status = NT_STATUS_INTERNAL_ERROR;
3890 goto fail;
3893 state->idmap_ctx = idmap_init(state, state->ev,
3894 state->lp_ctx);
3895 if (!state->idmap_ctx) {
3896 DEBUG(0, ("idmap failed\n"));
3897 status = NT_STATUS_INTERNAL_ERROR;
3898 goto fail;
3901 status = pdb_samba_dsdb_init_secrets(m);
3902 if (!NT_STATUS_IS_OK(status)) {
3903 DEBUG(10, ("pdb_samba_dsdb_init_secrets failed!\n"));
3904 goto fail;
3907 *pdb_method = m;
3908 return NT_STATUS_OK;
3909 nomem:
3910 status = NT_STATUS_NO_MEMORY;
3911 fail:
3912 TALLOC_FREE(m);
3913 return status;
3916 NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *);
3917 NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *ctx)
3919 NTSTATUS status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba_dsdb",
3920 pdb_init_samba_dsdb);
3921 if (!NT_STATUS_IS_OK(status)) {
3922 return status;
3924 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4",
3925 pdb_init_samba_dsdb);