winbind: Keep "force_reauth" in invalidate_cm_connection
[Samba.git] / source3 / passdb / pdb_samba_dsdb.c
blob4e55a15a0cc0cd4dd06df3e331d32bc8bbc7cc9a
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 char *sidstr, *filter;
159 NTSTATUS status;
161 msg = (struct ldb_message *)
162 pdb_get_backend_private_data(sam, m);
164 if (msg != NULL) {
165 return talloc_get_type_abort(msg, struct ldb_message);
168 sidstr = dom_sid_string(talloc_tos(), pdb_get_user_sid(sam));
169 if (sidstr == NULL) {
170 return NULL;
173 filter = talloc_asprintf(
174 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
175 TALLOC_FREE(sidstr);
176 if (filter == NULL) {
177 return NULL;
180 status = pdb_samba_dsdb_getsamupriv(state, filter, sam, &msg);
181 TALLOC_FREE(filter);
182 if (!NT_STATUS_IS_OK(status)) {
183 return NULL;
186 return msg;
189 static NTSTATUS pdb_samba_dsdb_init_sam_from_priv(struct pdb_methods *m,
190 struct samu *sam,
191 struct ldb_message *msg)
193 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
194 m->private_data, struct pdb_samba_dsdb_state);
195 TALLOC_CTX *frame = talloc_stackframe();
196 NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
197 const char *str;
198 time_t tmp_time;
199 struct dom_sid *sid, group_sid;
200 uint64_t n;
201 const DATA_BLOB *blob;
203 str = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
204 if (str == NULL) {
205 DEBUG(10, ("no samAccountName\n"));
206 goto fail;
208 pdb_set_username(sam, str, PDB_SET);
210 if (pdb_samba_dsdb_pull_time(msg, "lastLogon", &tmp_time)) {
211 pdb_set_logon_time(sam, tmp_time, PDB_SET);
213 if (pdb_samba_dsdb_pull_time(msg, "lastLogoff", &tmp_time)) {
214 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
216 if (pdb_samba_dsdb_pull_time(msg, "pwdLastSet", &tmp_time)) {
217 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
219 if (pdb_samba_dsdb_pull_time(msg, "accountExpires", &tmp_time)) {
220 pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
223 str = ldb_msg_find_attr_as_string(msg, "displayName",
224 NULL);
225 if (str != NULL) {
226 pdb_set_fullname(sam, str, PDB_SET);
229 str = ldb_msg_find_attr_as_string(msg, "homeDirectory",
230 NULL);
231 if (str != NULL) {
232 pdb_set_homedir(sam, str, PDB_SET);
235 str = ldb_msg_find_attr_as_string(msg, "homeDrive", NULL);
236 if (str != NULL) {
237 pdb_set_dir_drive(sam, str, PDB_SET);
240 str = ldb_msg_find_attr_as_string(msg, "scriptPath", NULL);
241 if (str != NULL) {
242 pdb_set_logon_script(sam, str, PDB_SET);
245 str = ldb_msg_find_attr_as_string(msg, "profilePath",
246 NULL);
247 if (str != NULL) {
248 pdb_set_profile_path(sam, str, PDB_SET);
251 str = ldb_msg_find_attr_as_string(msg, "comment",
252 NULL);
253 if (str != NULL) {
254 pdb_set_comment(sam, str, PDB_SET);
257 str = ldb_msg_find_attr_as_string(msg, "description",
258 NULL);
259 if (str != NULL) {
260 pdb_set_acct_desc(sam, str, PDB_SET);
263 str = ldb_msg_find_attr_as_string(msg, "userWorkstations",
264 NULL);
265 if (str != NULL) {
266 pdb_set_workstations(sam, str, PDB_SET);
269 blob = ldb_msg_find_ldb_val(msg, "userParameters");
270 if (blob != NULL) {
271 str = base64_encode_data_blob(frame, *blob);
272 if (str == NULL) {
273 DEBUG(0, ("base64_encode_data_blob() failed\n"));
274 goto fail;
276 pdb_set_munged_dial(sam, str, PDB_SET);
279 sid = samdb_result_dom_sid(talloc_tos(), msg, "objectSid");
280 if (!sid) {
281 DEBUG(10, ("Could not pull SID\n"));
282 goto fail;
284 pdb_set_user_sid(sam, sid, PDB_SET);
286 n = samdb_result_acct_flags(msg, "msDS-User-Account-Control-Computed");
287 if (n == 0) {
288 DEBUG(10, ("Could not pull userAccountControl\n"));
289 goto fail;
291 pdb_set_acct_ctrl(sam, n, PDB_SET);
293 blob = ldb_msg_find_ldb_val(msg, "unicodePwd");
294 if (blob) {
295 if (blob->length != NT_HASH_LEN) {
296 DEBUG(0, ("Got NT hash of length %d, expected %d\n",
297 (int)blob->length, NT_HASH_LEN));
298 goto fail;
300 pdb_set_nt_passwd(sam, blob->data, PDB_SET);
303 blob = ldb_msg_find_ldb_val(msg, "dBCSPwd");
304 if (blob) {
305 if (blob->length != LM_HASH_LEN) {
306 DEBUG(0, ("Got LM hash of length %d, expected %d\n",
307 (int)blob->length, LM_HASH_LEN));
308 goto fail;
310 pdb_set_lanman_passwd(sam, blob->data, PDB_SET);
313 n = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", 0);
314 if (n == 0) {
315 DEBUG(10, ("Could not pull primaryGroupID\n"));
316 goto fail;
318 sid_compose(&group_sid, samdb_domain_sid(state->ldb), n);
319 pdb_set_group_sid(sam, &group_sid, PDB_SET);
321 status = NT_STATUS_OK;
322 fail:
323 TALLOC_FREE(frame);
324 return status;
327 static bool pdb_samba_dsdb_add_time(struct ldb_message *msg,
328 const char *attrib, time_t t)
330 uint64_t nt_time;
332 unix_to_nt_time(&nt_time, t);
334 return ldb_msg_add_fmt(msg, attrib, "%llu", (unsigned long long) nt_time);
337 static int pdb_samba_dsdb_replace_by_sam(struct pdb_samba_dsdb_state *state,
338 bool (*need_update)(const struct samu *,
339 enum pdb_elements),
340 struct ldb_dn *dn,
341 struct samu *sam)
343 TALLOC_CTX *frame = talloc_stackframe();
344 int ret = LDB_SUCCESS;
345 const char *pw;
346 struct ldb_message *msg;
347 struct ldb_request *req;
348 uint32_t dsdb_flags = 0;
349 /* TODO: All fields :-) */
351 msg = ldb_msg_new(frame);
352 if (!msg) {
353 talloc_free(frame);
354 return false;
357 msg->dn = dn;
359 /* build modify request */
360 ret = ldb_build_mod_req(&req, state->ldb, frame, msg, NULL, NULL,
361 ldb_op_default_callback,
362 NULL);
363 if (ret != LDB_SUCCESS) {
364 talloc_free(frame);
365 return ret;
368 /* If we set a plaintext password, the system will
369 * force the pwdLastSet to now() */
370 if (need_update(sam, PDB_PASSLASTSET)) {
371 dsdb_flags |= DSDB_PASSWORD_BYPASS_LAST_SET;
373 ret |= pdb_samba_dsdb_add_time(msg, "pwdLastSet",
374 pdb_get_pass_last_set_time(sam));
377 pw = pdb_get_plaintext_passwd(sam);
378 if (need_update(sam, PDB_PLAINTEXT_PW)) {
379 struct ldb_val pw_utf16;
380 if (pw == NULL) {
381 talloc_free(frame);
382 return LDB_ERR_OPERATIONS_ERROR;
385 if (!convert_string_talloc(msg,
386 CH_UNIX, CH_UTF16,
387 pw, strlen(pw),
388 (void *)&pw_utf16.data,
389 &pw_utf16.length)) {
390 talloc_free(frame);
391 return LDB_ERR_OPERATIONS_ERROR;
393 ret |= ldb_msg_add_value(msg, "clearTextPassword", &pw_utf16, NULL);
394 } else {
395 bool changed_lm_pw = false;
396 bool changed_nt_pw = false;
397 bool changed_history = false;
398 if (need_update(sam, PDB_LMPASSWD)) {
399 struct ldb_val val;
400 val.data = discard_const_p(uint8_t, pdb_get_lanman_passwd(sam));
401 if (!val.data) {
402 samdb_msg_add_delete(state->ldb, msg, msg,
403 "dBCSPwd");
404 } else {
405 val.length = LM_HASH_LEN;
406 ret |= ldb_msg_add_value(msg, "dBCSPwd", &val, NULL);
408 changed_lm_pw = true;
410 if (need_update(sam, PDB_NTPASSWD)) {
411 struct ldb_val val;
412 val.data = discard_const_p(uint8_t, pdb_get_nt_passwd(sam));
413 if (!val.data) {
414 samdb_msg_add_delete(state->ldb, msg, msg,
415 "unicodePwd");
416 } else {
417 val.length = NT_HASH_LEN;
418 ret |= ldb_msg_add_value(msg, "unicodePwd", &val, NULL);
420 changed_nt_pw = true;
423 /* Try to ensure we don't get out of sync */
424 if (changed_lm_pw && !changed_nt_pw) {
425 samdb_msg_add_delete(state->ldb, msg, msg,
426 "unicodePwd");
427 } else if (changed_nt_pw && !changed_lm_pw) {
428 samdb_msg_add_delete(state->ldb, msg, msg,
429 "dBCSPwd");
431 if (changed_lm_pw || changed_nt_pw) {
432 samdb_msg_add_delete(state->ldb, msg, msg,
433 "supplementalCredentials");
437 if (need_update(sam, PDB_PWHISTORY)) {
438 uint32_t current_hist_len;
439 const uint8_t *history = pdb_get_pw_history(sam, &current_hist_len);
441 bool invalid_history = false;
442 struct samr_Password *history_hashes = talloc_array(talloc_tos(), struct samr_Password,
443 current_hist_len);
444 if (!history) {
445 invalid_history = true;
446 } else {
447 unsigned int i;
448 /* Parse the history into the correct format */
449 for (i = 0; i < current_hist_len; i++) {
450 if (!all_zero(&history[i*PW_HISTORY_ENTRY_LEN],
451 16)) {
452 /* If the history is in the old format, with a salted hash, then we can't migrate it to AD format */
453 invalid_history = true;
454 break;
456 /* Copy out the 2nd 16 bytes of the 32 byte password history, containing the NT hash */
457 memcpy(history_hashes[i].hash,
458 &history[(i*PW_HISTORY_ENTRY_LEN) + PW_HISTORY_SALT_LEN],
459 sizeof(history_hashes[i].hash));
462 if (invalid_history) {
463 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
464 "ntPwdHistory");
466 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
467 "lmPwdHistory");
468 } else {
469 ret |= samdb_msg_add_hashes(state->ldb, msg, msg,
470 "ntPwdHistory",
471 history_hashes,
472 current_hist_len);
474 changed_history = true;
476 if (changed_lm_pw || changed_nt_pw || changed_history) {
477 /* These attributes can only be modified directly by using a special control */
478 dsdb_flags |= DSDB_BYPASS_PASSWORD_HASH;
482 /* PDB_USERSID is only allowed on ADD, handled in caller */
483 if (need_update(sam, PDB_GROUPSID)) {
484 const struct dom_sid *sid = pdb_get_group_sid(sam);
485 uint32_t rid;
486 NTSTATUS status = dom_sid_split_rid(NULL, sid, NULL, &rid);
487 if (!NT_STATUS_IS_OK(status)) {
488 talloc_free(frame);
489 return LDB_ERR_OPERATIONS_ERROR;
491 if (!dom_sid_in_domain(samdb_domain_sid(state->ldb), sid)) {
492 talloc_free(frame);
493 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
495 ret |= samdb_msg_add_uint(state->ldb, msg, msg, "primaryGroupID", rid);
497 if (need_update(sam, PDB_FULLNAME)) {
498 ret |= ldb_msg_add_string(msg, "displayName", pdb_get_fullname(sam));
501 if (need_update(sam, PDB_SMBHOME)) {
502 ret |= ldb_msg_add_string(msg, "homeDirectory",
503 pdb_get_homedir(sam));
506 if (need_update(sam, PDB_PROFILE)) {
507 ret |= ldb_msg_add_string(msg, "profilePath",
508 pdb_get_profile_path(sam));
511 if (need_update(sam, PDB_DRIVE)) {
512 ret |= ldb_msg_add_string(msg, "homeDrive",
513 pdb_get_dir_drive(sam));
516 if (need_update(sam, PDB_LOGONSCRIPT)) {
517 ret |= ldb_msg_add_string(msg, "scriptPath",
518 pdb_get_logon_script(sam));
521 if (need_update(sam, PDB_KICKOFFTIME)) {
522 ret |= pdb_samba_dsdb_add_time(msg, "accountExpires",
523 pdb_get_kickoff_time(sam));
526 if (need_update(sam, PDB_LOGONTIME)) {
527 ret |= pdb_samba_dsdb_add_time(msg, "lastLogon",
528 pdb_get_logon_time(sam));
531 if (need_update(sam, PDB_LOGOFFTIME)) {
532 ret |= pdb_samba_dsdb_add_time(msg, "lastLogoff",
533 pdb_get_logoff_time(sam));
536 if (need_update(sam, PDB_USERNAME)) {
537 ret |= ldb_msg_add_string(msg, "samAccountName",
538 pdb_get_username(sam));
541 if (need_update(sam, PDB_HOURSLEN) || need_update(sam, PDB_HOURS)) {
542 struct ldb_val hours = data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam));
543 ret |= ldb_msg_add_value(msg, "logonHours",
544 &hours, NULL);
547 if (need_update(sam, PDB_ACCTCTRL)) {
548 ret |= samdb_msg_add_acct_flags(state->ldb, msg, msg,
549 "userAccountControl", pdb_get_acct_ctrl(sam));
552 if (need_update(sam, PDB_COMMENT)) {
553 ret |= ldb_msg_add_string(msg, "comment",
554 pdb_get_comment(sam));
557 if (need_update(sam, PDB_ACCTDESC)) {
558 ret |= ldb_msg_add_string(msg, "description",
559 pdb_get_acct_desc(sam));
562 if (need_update(sam, PDB_WORKSTATIONS)) {
563 ret |= ldb_msg_add_string(msg, "userWorkstations",
564 pdb_get_workstations(sam));
567 /* This will need work, it is actually a UTF8 'string' with internal NULLs, to handle TS parameters */
568 if (need_update(sam, PDB_MUNGEDDIAL)) {
569 const char *base64_munged_dial = NULL;
571 base64_munged_dial = pdb_get_munged_dial(sam);
572 if (base64_munged_dial != NULL && strlen(base64_munged_dial) > 0) {
573 struct ldb_val blob;
575 blob = base64_decode_data_blob_talloc(msg,
576 base64_munged_dial);
577 if (blob.data == NULL) {
578 DEBUG(0, ("Failed to decode userParameters from "
579 "munged dialback string[%s] for %s\n",
580 base64_munged_dial,
581 ldb_dn_get_linearized(msg->dn)));
582 talloc_free(frame);
583 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
585 ret |= ldb_msg_add_steal_value(msg, "userParameters",
586 &blob);
590 if (need_update(sam, PDB_COUNTRY_CODE)) {
591 ret |= ldb_msg_add_fmt(msg, "countryCode",
592 "%i", (int)pdb_get_country_code(sam));
595 if (need_update(sam, PDB_CODE_PAGE)) {
596 ret |= ldb_msg_add_fmt(msg, "codePage",
597 "%i", (int)pdb_get_code_page(sam));
600 /* Not yet handled here or not meaningful for modifies on a Samba_Dsdb backend:
601 PDB_BAD_PASSWORD_TIME,
602 PDB_CANCHANGETIME, - these are calculated per policy, not stored
603 PDB_DOMAIN,
604 PDB_NTUSERNAME, - this makes no sense, and never really did
605 PDB_LOGONDIVS,
606 PDB_USERSID, - Handled in pdb_samba_dsdb_add_sam_account()
607 PDB_FIELDS_PRESENT,
608 PDB_BAD_PASSWORD_COUNT,
609 PDB_LOGON_COUNT,
610 PDB_UNKNOWN6,
611 PDB_BACKEND_PRIVATE_DATA,
614 if (ret != LDB_SUCCESS) {
615 talloc_free(frame);
616 return LDB_ERR_OPERATIONS_ERROR;
619 if (msg->num_elements == 0) {
620 talloc_free(frame);
621 /* Nothing to do, just return success */
622 return LDB_SUCCESS;
625 ret = dsdb_replace(state->ldb, msg, dsdb_flags);
627 if (ret != LDB_SUCCESS) {
628 DEBUG(0,("Failed to modify account record %s to set user attributes: %s\n",
629 ldb_dn_get_linearized(msg->dn),
630 ldb_errstring(state->ldb)));
633 talloc_free(frame);
634 return ret;
637 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
638 const char *filter,
639 TALLOC_CTX *mem_ctx,
640 struct ldb_message **msg)
642 const char * attrs[] = {
643 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
644 "sAMAccountName", "displayName", "homeDirectory",
645 "homeDrive", "scriptPath", "profilePath", "description",
646 "userWorkstations", "comment", "userParameters", "objectSid",
647 "primaryGroupID", "userAccountControl",
648 "msDS-User-Account-Control-Computed", "logonHours",
649 "badPwdCount", "logonCount", "countryCode", "codePage",
650 "unicodePwd", "dBCSPwd", NULL };
652 int rc = dsdb_search_one(state->ldb, mem_ctx, msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter);
653 if (rc != LDB_SUCCESS) {
654 DEBUG(10, ("ldap_search failed %s\n",
655 ldb_errstring(state->ldb)));
656 return NT_STATUS_LDAP(rc);
659 return NT_STATUS_OK;
662 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
663 struct pdb_samba_dsdb_state *state,
664 struct samu *sam_acct,
665 const char *exp_fmt, ...)
666 PRINTF_ATTRIBUTE(4,5);
668 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
669 struct pdb_samba_dsdb_state *state,
670 struct samu *sam_acct,
671 const char *exp_fmt, ...)
673 struct ldb_message *priv;
674 NTSTATUS status;
675 va_list ap;
676 char *expression = NULL;
677 TALLOC_CTX *tmp_ctx = talloc_new(state);
678 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
680 va_start(ap, exp_fmt);
681 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
682 va_end(ap);
684 if (!expression) {
685 talloc_free(tmp_ctx);
686 return NT_STATUS_NO_MEMORY;
689 status = pdb_samba_dsdb_getsamupriv(state, expression, sam_acct, &priv);
690 talloc_free(tmp_ctx);
691 if (!NT_STATUS_IS_OK(status)) {
692 DEBUG(10, ("pdb_samba_dsdb_getsamupriv failed: %s\n",
693 nt_errstr(status)));
694 return status;
697 status = pdb_samba_dsdb_init_sam_from_priv(m, sam_acct, priv);
698 if (!NT_STATUS_IS_OK(status)) {
699 DEBUG(10, ("pdb_samba_dsdb_init_sam_from_priv failed: %s\n",
700 nt_errstr(status)));
701 TALLOC_FREE(priv);
702 return status;
705 pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
706 return NT_STATUS_OK;
709 static NTSTATUS pdb_samba_dsdb_getsampwnam(struct pdb_methods *m,
710 struct samu *sam_acct,
711 const char *username)
713 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
714 m->private_data, struct pdb_samba_dsdb_state);
716 return pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
717 "(&(samaccountname=%s)(objectclass=user))",
718 username);
721 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
722 struct samu *sam_acct,
723 const struct dom_sid *sid)
725 NTSTATUS status;
726 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
727 m->private_data, struct pdb_samba_dsdb_state);
728 char *sidstr;
730 sidstr = dom_sid_string(talloc_tos(), sid);
731 NT_STATUS_HAVE_NO_MEMORY(sidstr);
733 status = pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
734 "(&(objectsid=%s)(objectclass=user))",
735 sidstr);
736 talloc_free(sidstr);
737 return status;
740 static NTSTATUS pdb_samba_dsdb_create_user(struct pdb_methods *m,
741 TALLOC_CTX *mem_ctx,
742 const char *name, uint32_t acct_flags,
743 uint32_t *rid)
745 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
746 m->private_data, struct pdb_samba_dsdb_state);
747 struct dom_sid *sid;
748 struct ldb_dn *dn;
749 NTSTATUS status;
750 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
751 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
753 /* Internally this uses transactions to ensure all the steps
754 * happen or fail as one */
755 status = dsdb_add_user(state->ldb, tmp_ctx, name, acct_flags, NULL,
756 &sid, &dn);
757 if (!NT_STATUS_IS_OK(status)) {
758 talloc_free(tmp_ctx);
759 return status;
761 sid_peek_rid(sid, rid);
762 talloc_free(tmp_ctx);
763 return NT_STATUS_OK;
766 static NTSTATUS pdb_samba_dsdb_delete_user(struct pdb_methods *m,
767 TALLOC_CTX *mem_ctx,
768 struct samu *sam)
770 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
771 m->private_data, struct pdb_samba_dsdb_state);
772 struct ldb_dn *dn;
773 int rc;
774 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
775 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
777 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, pdb_get_user_sid(sam)));
778 if (!dn || !ldb_dn_validate(dn)) {
779 talloc_free(tmp_ctx);
780 return NT_STATUS_NO_MEMORY;
782 rc = ldb_delete(state->ldb, dn);
784 if (rc != LDB_SUCCESS) {
785 DEBUG(10, ("ldb_delete for %s failed: %s\n", ldb_dn_get_linearized(dn),
786 ldb_errstring(state->ldb)));
787 talloc_free(tmp_ctx);
788 return NT_STATUS_LDAP(rc);
790 talloc_free(tmp_ctx);
791 return NT_STATUS_OK;
794 /* This interface takes a fully populated struct samu and places it in
795 * the database. This is not implemented at this time as we need to
796 * be careful around the creation of arbitary SIDs (ie, we must ensrue
797 * they are not left in a RID pool */
798 static NTSTATUS pdb_samba_dsdb_add_sam_account(struct pdb_methods *m,
799 struct samu *sampass)
801 int ret;
802 NTSTATUS status;
803 struct ldb_dn *dn;
804 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
805 m->private_data, struct pdb_samba_dsdb_state);
806 uint32_t acb_flags = pdb_get_acct_ctrl(sampass);
807 const char *username = pdb_get_username(sampass);
808 const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
809 TALLOC_CTX *tframe = talloc_stackframe();
811 acb_flags &= (ACB_NORMAL|ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST);
813 ret = ldb_transaction_start(state->ldb);
814 if (ret != LDB_SUCCESS) {
815 talloc_free(tframe);
816 return NT_STATUS_LOCK_NOT_GRANTED;
819 status = dsdb_add_user(state->ldb, talloc_tos(), username,
820 acb_flags, user_sid, NULL, &dn);
821 if (!NT_STATUS_IS_OK(status)) {
822 ldb_transaction_cancel(state->ldb);
823 talloc_free(tframe);
824 return status;
827 ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_set_or_changed,
828 dn, sampass);
829 if (ret != LDB_SUCCESS) {
830 ldb_transaction_cancel(state->ldb);
831 talloc_free(tframe);
832 return dsdb_ldb_err_to_ntstatus(ret);
835 ret = ldb_transaction_commit(state->ldb);
836 if (ret != LDB_SUCCESS) {
837 DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
838 ldb_dn_get_linearized(dn),
839 ldb_errstring(state->ldb)));
840 talloc_free(tframe);
841 return NT_STATUS_INTERNAL_DB_CORRUPTION;
843 talloc_free(tframe);
844 return NT_STATUS_OK;
848 * Update the Samba_Dsdb LDB with the changes from a struct samu.
850 * This takes care not to update elements that have not been changed
851 * by the caller
853 static NTSTATUS pdb_samba_dsdb_update_sam_account(struct pdb_methods *m,
854 struct samu *sam)
856 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
857 m->private_data, struct pdb_samba_dsdb_state);
858 struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
859 m, sam);
860 int ret;
862 ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_changed, msg->dn,
863 sam);
864 return dsdb_ldb_err_to_ntstatus(ret);
867 static NTSTATUS pdb_samba_dsdb_delete_sam_account(struct pdb_methods *m,
868 struct samu *username)
870 NTSTATUS status;
871 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
872 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
873 status = pdb_samba_dsdb_delete_user(m, tmp_ctx, username);
874 talloc_free(tmp_ctx);
875 return status;
878 static NTSTATUS pdb_samba_dsdb_rename_sam_account(struct pdb_methods *m,
879 struct samu *oldname,
880 const char *newname)
882 return NT_STATUS_NOT_IMPLEMENTED;
885 /* This is not implemented, as this module is exptected to be used
886 * with auth_samba_dsdb, and this is responible for login counters etc
889 static NTSTATUS pdb_samba_dsdb_update_login_attempts(struct pdb_methods *m,
890 struct samu *sam_acct,
891 bool success)
893 return NT_STATUS_NOT_IMPLEMENTED;
896 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m,
897 GROUP_MAP *map,
898 const char *exp_fmt, ...)
899 PRINTF_ATTRIBUTE(3,4);
901 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
902 const char *exp_fmt, ...)
904 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
905 m->private_data, struct pdb_samba_dsdb_state);
906 const char *attrs[] = { "objectClass", "objectSid", "description", "samAccountName", "groupType",
907 NULL };
908 struct ldb_message *msg;
909 va_list ap;
910 char *expression = NULL;
911 struct dom_sid *sid;
912 const char *str;
913 int rc;
914 struct id_map id_map;
915 struct id_map *id_maps[2];
916 TALLOC_CTX *tmp_ctx = talloc_stackframe();
917 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
919 va_start(ap, exp_fmt);
920 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
921 va_end(ap);
923 if (!expression) {
924 talloc_free(tmp_ctx);
925 return NT_STATUS_NO_MEMORY;
928 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
929 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
930 talloc_free(tmp_ctx);
931 return NT_STATUS_NO_SUCH_GROUP;
932 } else if (rc != LDB_SUCCESS) {
933 talloc_free(tmp_ctx);
934 DEBUG(10, ("dsdb_search_one failed %s\n",
935 ldb_errstring(state->ldb)));
936 return NT_STATUS_LDAP(rc);
939 sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
940 if (!sid) {
941 talloc_free(tmp_ctx);
942 DEBUG(10, ("Could not pull SID\n"));
943 return NT_STATUS_INTERNAL_DB_CORRUPTION;
946 map->sid = *sid;
948 if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) {
949 NTSTATUS status;
950 uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0);
951 switch (grouptype) {
952 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
953 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
954 map->sid_name_use = SID_NAME_ALIAS;
955 break;
956 case GTYPE_SECURITY_GLOBAL_GROUP:
957 map->sid_name_use = SID_NAME_DOM_GRP;
958 break;
959 default:
960 talloc_free(tmp_ctx);
961 DEBUG(10, ("Could not pull groupType\n"));
962 return NT_STATUS_INTERNAL_DB_CORRUPTION;
965 ZERO_STRUCT(id_map);
966 id_map.sid = sid;
967 id_maps[0] = &id_map;
968 id_maps[1] = NULL;
970 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
972 if (!NT_STATUS_IS_OK(status)) {
973 talloc_free(tmp_ctx);
974 return status;
976 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
977 map->gid = id_map.xid.id;
978 } else {
979 DEBUG(1, (__location__ "Did not get GUID when mapping SID for %s", expression));
980 talloc_free(tmp_ctx);
981 return NT_STATUS_INTERNAL_DB_CORRUPTION;
983 } else if (samdb_find_attribute(state->ldb, msg, "objectClass", "user")) {
984 DEBUG(1, (__location__ "Got SID_NAME_USER when searching for a group with %s", expression));
985 talloc_free(tmp_ctx);
986 return NT_STATUS_INTERNAL_DB_CORRUPTION;
989 str = ldb_msg_find_attr_as_string(msg, "samAccountName",
990 NULL);
991 if (str == NULL) {
992 talloc_free(tmp_ctx);
993 return NT_STATUS_INTERNAL_DB_CORRUPTION;
995 map->nt_name = talloc_strdup(map, str);
996 if (!map->nt_name) {
997 talloc_free(tmp_ctx);
998 return NT_STATUS_NO_MEMORY;
1001 str = ldb_msg_find_attr_as_string(msg, "description",
1002 NULL);
1003 if (str != NULL) {
1004 map->comment = talloc_strdup(map, str);
1005 } else {
1006 map->comment = talloc_strdup(map, "");
1008 if (!map->comment) {
1009 talloc_free(tmp_ctx);
1010 return NT_STATUS_NO_MEMORY;
1013 talloc_free(tmp_ctx);
1014 return NT_STATUS_OK;
1017 static NTSTATUS pdb_samba_dsdb_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
1018 struct dom_sid sid)
1020 char *filter;
1021 NTSTATUS status;
1023 filter = talloc_asprintf(talloc_tos(),
1024 "(&(objectsid=%s)(objectclass=group))",
1025 sid_string_talloc(talloc_tos(), &sid));
1026 if (filter == NULL) {
1027 return NT_STATUS_NO_MEMORY;
1030 status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
1031 TALLOC_FREE(filter);
1032 return status;
1035 static NTSTATUS pdb_samba_dsdb_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
1036 gid_t gid)
1038 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1039 m->private_data, struct pdb_samba_dsdb_state);
1040 NTSTATUS status;
1041 struct id_map id_map;
1042 struct id_map *id_maps[2];
1043 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1044 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1046 id_map.xid.id = gid;
1047 id_map.xid.type = ID_TYPE_GID;
1048 id_maps[0] = &id_map;
1049 id_maps[1] = NULL;
1051 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
1052 if (!NT_STATUS_IS_OK(status)) {
1053 talloc_free(tmp_ctx);
1054 return status;
1056 status = pdb_samba_dsdb_getgrsid(m, map, *id_map.sid);
1057 talloc_free(tmp_ctx);
1058 return status;
1061 static NTSTATUS pdb_samba_dsdb_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
1062 const char *name)
1064 char *filter;
1065 NTSTATUS status;
1067 filter = talloc_asprintf(talloc_tos(),
1068 "(&(samaccountname=%s)(objectclass=group))",
1069 name);
1070 if (filter == NULL) {
1071 return NT_STATUS_NO_MEMORY;
1074 status = pdb_samba_dsdb_getgrfilter(m, map, "%s", filter);
1075 TALLOC_FREE(filter);
1076 return status;
1079 static NTSTATUS pdb_samba_dsdb_create_dom_group(struct pdb_methods *m,
1080 TALLOC_CTX *mem_ctx, const char *name,
1081 uint32_t *rid)
1083 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1084 m->private_data, struct pdb_samba_dsdb_state);
1085 NTSTATUS status;
1086 struct dom_sid *sid;
1087 struct ldb_dn *dn;
1088 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1089 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1091 status = dsdb_add_domain_group(state->ldb, tmp_ctx, name, &sid, &dn);
1092 if (!NT_STATUS_IS_OK(status)) {
1093 talloc_free(tmp_ctx);
1094 return status;
1097 sid_peek_rid(sid, rid);
1098 talloc_free(tmp_ctx);
1099 return NT_STATUS_OK;
1102 static NTSTATUS pdb_samba_dsdb_delete_dom_group(struct pdb_methods *m,
1103 TALLOC_CTX *mem_ctx, uint32_t rid)
1105 const char *attrs[] = { NULL };
1106 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1107 m->private_data, struct pdb_samba_dsdb_state);
1108 struct dom_sid sid;
1109 struct ldb_message *msg;
1110 struct ldb_dn *dn;
1111 int rc;
1112 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1113 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1115 sid_compose(&sid, samdb_domain_sid(state->ldb), rid);
1117 if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1118 DEBUG(0, ("Unable to start transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1119 return NT_STATUS_INTERNAL_ERROR;
1122 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, &sid));
1123 if (!dn || !ldb_dn_validate(dn)) {
1124 talloc_free(tmp_ctx);
1125 ldb_transaction_cancel(state->ldb);
1126 return NT_STATUS_NO_MEMORY;
1128 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "objectclass=group");
1129 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1130 talloc_free(tmp_ctx);
1131 ldb_transaction_cancel(state->ldb);
1132 return NT_STATUS_NO_SUCH_GROUP;
1134 rc = ldb_delete(state->ldb, dn);
1135 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1136 talloc_free(tmp_ctx);
1137 ldb_transaction_cancel(state->ldb);
1138 return NT_STATUS_NO_SUCH_GROUP;
1139 } else if (rc != LDB_SUCCESS) {
1140 DEBUG(10, ("ldb_delete failed %s\n",
1141 ldb_errstring(state->ldb)));
1142 ldb_transaction_cancel(state->ldb);
1143 return NT_STATUS_LDAP(rc);
1146 if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1147 DEBUG(0, ("Unable to commit transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1148 return NT_STATUS_INTERNAL_ERROR;
1150 return NT_STATUS_OK;
1153 static NTSTATUS pdb_samba_dsdb_add_group_mapping_entry(struct pdb_methods *m,
1154 GROUP_MAP *map)
1156 return NT_STATUS_NOT_IMPLEMENTED;
1159 static NTSTATUS pdb_samba_dsdb_update_group_mapping_entry(struct pdb_methods *m,
1160 GROUP_MAP *map)
1162 return NT_STATUS_NOT_IMPLEMENTED;
1165 static NTSTATUS pdb_samba_dsdb_delete_group_mapping_entry(struct pdb_methods *m,
1166 struct dom_sid sid)
1168 return NT_STATUS_NOT_IMPLEMENTED;
1171 static NTSTATUS pdb_samba_dsdb_enum_group_mapping(struct pdb_methods *m,
1172 const struct dom_sid *sid,
1173 enum lsa_SidType sid_name_use,
1174 GROUP_MAP ***pp_rmap,
1175 size_t *p_num_entries,
1176 bool unix_only)
1178 return NT_STATUS_NOT_IMPLEMENTED;
1181 static NTSTATUS pdb_samba_dsdb_enum_group_members(struct pdb_methods *m,
1182 TALLOC_CTX *mem_ctx,
1183 const struct dom_sid *group,
1184 uint32_t **pmembers,
1185 size_t *pnum_members)
1187 unsigned int i, num_sids, num_members;
1188 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1189 m->private_data, struct pdb_samba_dsdb_state);
1190 struct dom_sid *members_as_sids;
1191 struct dom_sid *dom_sid;
1192 uint32_t *members;
1193 struct ldb_dn *dn;
1194 NTSTATUS status;
1196 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1197 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1199 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, group));
1200 if (!dn || !ldb_dn_validate(dn)) {
1201 return NT_STATUS_NO_MEMORY;
1204 status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
1205 if (!NT_STATUS_IS_OK(status)) {
1206 talloc_free(tmp_ctx);
1207 return status;
1209 status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
1210 if (!NT_STATUS_IS_OK(status)) {
1211 talloc_free(tmp_ctx);
1212 return status;
1215 *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
1216 if (*pmembers == NULL) {
1217 TALLOC_FREE(tmp_ctx);
1218 return NT_STATUS_NO_MEMORY;
1220 num_members = 0;
1222 for (i = 0; i < num_sids; i++) {
1223 if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
1224 continue;
1226 status = dom_sid_split_rid(NULL, &members_as_sids[i],
1227 NULL, &members[num_members]);
1228 if (!NT_STATUS_IS_OK(status)) {
1229 talloc_free(tmp_ctx);
1230 return status;
1232 num_members++;
1234 *pnum_members = num_members;
1235 return NT_STATUS_OK;
1238 /* Just convert the primary group SID into a group */
1239 static NTSTATUS fake_enum_group_memberships(struct pdb_samba_dsdb_state *state,
1240 TALLOC_CTX *mem_ctx,
1241 struct samu *user,
1242 struct dom_sid **pp_sids,
1243 gid_t **pp_gids,
1244 uint32_t *p_num_groups)
1246 NTSTATUS status;
1247 size_t num_groups = 0;
1248 struct dom_sid *group_sids = NULL;
1249 gid_t *gids = NULL;
1250 TALLOC_CTX *tmp_ctx;
1252 tmp_ctx = talloc_new(mem_ctx);
1253 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1255 if (user->group_sid) {
1256 struct id_map *id_maps[2];
1257 struct id_map id_map;
1259 num_groups = 1;
1261 group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
1262 if (group_sids == NULL) {
1263 talloc_free(tmp_ctx);
1264 return NT_STATUS_NO_MEMORY;
1266 gids = talloc_array(tmp_ctx, gid_t, num_groups);
1267 if (gids == NULL) {
1268 talloc_free(tmp_ctx);
1269 return NT_STATUS_NO_MEMORY;
1272 group_sids[0] = *user->group_sid;
1274 ZERO_STRUCT(id_map);
1275 id_map.sid = &group_sids[0];
1276 id_maps[0] = &id_map;
1277 id_maps[1] = NULL;
1279 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1280 if (!NT_STATUS_IS_OK(status)) {
1281 talloc_free(tmp_ctx);
1282 return status;
1284 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1285 gids[0] = id_map.xid.id;
1286 } else {
1287 DEBUG(1, (__location__
1288 "Group %s, of which %s is a member, could not be converted to a GID\n",
1289 dom_sid_string(tmp_ctx, &group_sids[0]),
1290 dom_sid_string(tmp_ctx, &user->user_sid)));
1291 talloc_free(tmp_ctx);
1292 /* We must error out, otherwise a user might
1293 * avoid a DENY acl based on a group they
1294 * missed out on */
1295 return NT_STATUS_NO_SUCH_GROUP;
1299 *pp_sids = talloc_steal(mem_ctx, group_sids);
1300 *pp_gids = talloc_steal(mem_ctx, gids);
1301 *p_num_groups = num_groups;
1302 talloc_free(tmp_ctx);
1303 return NT_STATUS_OK;
1306 static NTSTATUS pdb_samba_dsdb_enum_group_memberships(struct pdb_methods *m,
1307 TALLOC_CTX *mem_ctx,
1308 struct samu *user,
1309 struct dom_sid **pp_sids,
1310 gid_t **pp_gids,
1311 uint32_t *p_num_groups)
1313 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1314 m->private_data, struct pdb_samba_dsdb_state);
1315 struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
1316 m, user);
1317 const char *attrs[] = { "tokenGroups", NULL};
1318 struct ldb_message *tokengroups_msg;
1319 struct ldb_message_element *tokengroups;
1320 int i, rc;
1321 NTSTATUS status;
1322 unsigned int count = 0;
1323 size_t num_groups;
1324 struct dom_sid *group_sids;
1325 gid_t *gids;
1326 TALLOC_CTX *tmp_ctx;
1328 if (msg == NULL) {
1329 /* Fake up some things here */
1330 return fake_enum_group_memberships(state,
1331 mem_ctx,
1332 user, pp_sids,
1333 pp_gids, p_num_groups);
1336 tmp_ctx = talloc_new(mem_ctx);
1337 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1339 rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
1341 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1342 talloc_free(tmp_ctx);
1343 return NT_STATUS_NO_SUCH_USER;
1344 } else if (rc != LDB_SUCCESS) {
1345 DEBUG(10, ("dsdb_search_one failed %s\n",
1346 ldb_errstring(state->ldb)));
1347 talloc_free(tmp_ctx);
1348 return NT_STATUS_LDAP(rc);
1351 tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
1353 if (tokengroups) {
1354 count = tokengroups->num_values;
1357 group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
1358 if (group_sids == NULL) {
1359 talloc_free(tmp_ctx);
1360 return NT_STATUS_NO_MEMORY;
1362 gids = talloc_array(tmp_ctx, gid_t, count);
1363 if (gids == NULL) {
1364 talloc_free(tmp_ctx);
1365 return NT_STATUS_NO_MEMORY;
1367 num_groups = 0;
1369 for (i=0; i<count; i++) {
1370 struct id_map *id_maps[2];
1371 struct id_map id_map;
1372 struct ldb_val *v = &tokengroups->values[i];
1373 enum ndr_err_code ndr_err
1374 = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
1375 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1376 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1377 talloc_free(tmp_ctx);
1378 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1381 ZERO_STRUCT(id_map);
1382 id_map.sid = &group_sids[num_groups];
1383 id_maps[0] = &id_map;
1384 id_maps[1] = NULL;
1386 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1387 if (!NT_STATUS_IS_OK(status)) {
1388 talloc_free(tmp_ctx);
1389 return status;
1391 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1392 gids[num_groups] = id_map.xid.id;
1393 } else {
1394 DEBUG(1, (__location__
1395 "Group %s, of which %s is a member, could not be converted to a GID\n",
1396 dom_sid_string(tmp_ctx, &group_sids[num_groups]),
1397 ldb_dn_get_linearized(msg->dn)));
1398 talloc_free(tmp_ctx);
1399 /* We must error out, otherwise a user might
1400 * avoid a DENY acl based on a group they
1401 * missed out on */
1402 return NT_STATUS_NO_SUCH_GROUP;
1405 num_groups += 1;
1406 if (num_groups == count) {
1407 break;
1411 *pp_sids = talloc_steal(mem_ctx, group_sids);
1412 *pp_gids = talloc_steal(mem_ctx, gids);
1413 *p_num_groups = num_groups;
1414 talloc_free(tmp_ctx);
1415 return NT_STATUS_OK;
1418 static NTSTATUS pdb_samba_dsdb_set_unix_primary_group(struct pdb_methods *m,
1419 TALLOC_CTX *mem_ctx,
1420 struct samu *user)
1422 return NT_STATUS_NOT_IMPLEMENTED;
1425 static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid(struct pdb_methods *m,
1426 TALLOC_CTX *mem_ctx,
1427 const struct dom_sid *groupsid,
1428 const struct dom_sid *membersid,
1429 int mod_op)
1431 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1432 m->private_data, struct pdb_samba_dsdb_state);
1433 struct ldb_message *msg;
1434 int ret;
1435 struct ldb_message_element *el;
1436 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1437 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1438 msg = ldb_msg_new(tmp_ctx);
1439 if (msg == NULL) {
1440 TALLOC_FREE(tmp_ctx);
1441 return NT_STATUS_NO_MEMORY;
1444 msg->dn = ldb_dn_new_fmt(msg, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, groupsid));
1445 if (!msg->dn || !ldb_dn_validate(msg->dn)) {
1446 talloc_free(tmp_ctx);
1447 return NT_STATUS_NO_MEMORY;
1449 ret = ldb_msg_add_fmt(msg, "member", "<SID=%s>", dom_sid_string(tmp_ctx, membersid));
1450 if (ret != LDB_SUCCESS) {
1451 talloc_free(tmp_ctx);
1452 return NT_STATUS_NO_MEMORY;
1454 el = ldb_msg_find_element(msg, "member");
1455 el->flags = mod_op;
1457 /* No need for transactions here, the ldb auto-transaction
1458 * code will handle things for the single operation */
1459 ret = ldb_modify(state->ldb, msg);
1460 talloc_free(tmp_ctx);
1461 if (ret != LDB_SUCCESS) {
1462 DEBUG(10, ("ldb_modify failed: %s\n",
1463 ldb_errstring(state->ldb)));
1464 if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
1465 return NT_STATUS_MEMBER_IN_GROUP;
1467 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1468 return NT_STATUS_MEMBER_NOT_IN_GROUP;
1470 return NT_STATUS_LDAP(ret);
1473 return NT_STATUS_OK;
1476 static NTSTATUS pdb_samba_dsdb_mod_groupmem(struct pdb_methods *m,
1477 TALLOC_CTX *mem_ctx,
1478 uint32_t grouprid, uint32_t memberrid,
1479 int mod_op)
1481 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1482 m->private_data, struct pdb_samba_dsdb_state);
1483 const struct dom_sid *dom_sid, *groupsid, *membersid;
1484 NTSTATUS status;
1485 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1486 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1488 dom_sid = samdb_domain_sid(state->ldb);
1490 groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
1491 if (groupsid == NULL) {
1492 TALLOC_FREE(tmp_ctx);
1493 return NT_STATUS_NO_MEMORY;
1495 membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
1496 if (membersid == NULL) {
1497 TALLOC_FREE(tmp_ctx);
1498 return NT_STATUS_NO_MEMORY;
1500 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
1501 talloc_free(tmp_ctx);
1502 return status;
1505 static NTSTATUS pdb_samba_dsdb_add_groupmem(struct pdb_methods *m,
1506 TALLOC_CTX *mem_ctx,
1507 uint32_t group_rid, uint32_t member_rid)
1509 return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1510 LDB_FLAG_MOD_ADD);
1513 static NTSTATUS pdb_samba_dsdb_del_groupmem(struct pdb_methods *m,
1514 TALLOC_CTX *mem_ctx,
1515 uint32_t group_rid, uint32_t member_rid)
1517 return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1518 LDB_FLAG_MOD_DELETE);
1521 static NTSTATUS pdb_samba_dsdb_create_alias(struct pdb_methods *m,
1522 const char *name, uint32_t *rid)
1524 TALLOC_CTX *frame = talloc_stackframe();
1525 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1526 m->private_data, struct pdb_samba_dsdb_state);
1527 struct dom_sid *sid;
1529 struct ldb_dn *dn;
1530 NTSTATUS status;
1532 /* Internally this uses transactions to ensure all the steps
1533 * happen or fail as one */
1534 status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
1535 if (!NT_STATUS_IS_OK(status)) {
1536 TALLOC_FREE(frame);
1539 sid_peek_rid(sid, rid);
1540 TALLOC_FREE(frame);
1541 return NT_STATUS_OK;
1544 static NTSTATUS pdb_samba_dsdb_delete_alias(struct pdb_methods *m,
1545 const struct dom_sid *sid)
1547 const char *attrs[] = { NULL };
1548 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1549 m->private_data, struct pdb_samba_dsdb_state);
1550 struct ldb_message *msg;
1551 struct ldb_dn *dn;
1552 int rc;
1553 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1554 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1556 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, sid));
1557 if (!dn || !ldb_dn_validate(dn)) {
1558 talloc_free(tmp_ctx);
1559 return NT_STATUS_NO_MEMORY;
1562 if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1563 DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(state->ldb)));
1564 talloc_free(tmp_ctx);
1565 return NT_STATUS_INTERNAL_ERROR;
1568 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
1569 "(|(grouptype=%d)(grouptype=%d)))",
1570 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1571 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1572 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1573 talloc_free(tmp_ctx);
1574 ldb_transaction_cancel(state->ldb);
1575 return NT_STATUS_NO_SUCH_ALIAS;
1577 rc = ldb_delete(state->ldb, dn);
1578 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1579 talloc_free(tmp_ctx);
1580 ldb_transaction_cancel(state->ldb);
1581 return NT_STATUS_NO_SUCH_ALIAS;
1582 } else if (rc != LDB_SUCCESS) {
1583 DEBUG(10, ("ldb_delete failed %s\n",
1584 ldb_errstring(state->ldb)));
1585 ldb_transaction_cancel(state->ldb);
1586 talloc_free(tmp_ctx);
1587 return NT_STATUS_LDAP(rc);
1590 if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1591 DEBUG(0, ("Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s\n",
1592 ldb_errstring(state->ldb)));
1593 talloc_free(tmp_ctx);
1594 return NT_STATUS_INTERNAL_ERROR;
1597 talloc_free(tmp_ctx);
1598 return NT_STATUS_OK;
1601 #if 0
1602 static NTSTATUS pdb_samba_dsdb_set_aliasinfo(struct pdb_methods *m,
1603 const struct dom_sid *sid,
1604 struct acct_info *info)
1606 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1607 m->private_data, struct pdb_samba_dsdb_state);
1608 struct tldap_context *ld;
1609 const char *attrs[3] = { "objectSid", "description",
1610 "samAccountName" };
1611 struct ldb_message **msg;
1612 char *sidstr, *dn;
1613 int rc;
1614 struct tldap_mod *mods;
1615 int num_mods;
1616 bool ok;
1618 ld = pdb_samba_dsdb_ld(state);
1619 if (ld == NULL) {
1620 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1623 sidstr = sid_binstring(talloc_tos(), sid);
1624 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1626 rc = pdb_samba_dsdb_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1627 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1628 &msg, "(&(objectSid=%s)(objectclass=group)"
1629 "(|(grouptype=%d)(grouptype=%d)))",
1630 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1631 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1632 TALLOC_FREE(sidstr)
1633 if (rc != LDB_SUCCESS) {
1634 DEBUG(10, ("ldap_search failed %s\n",
1635 ldb_errstring(state->ldb)));
1636 return NT_STATUS_LDAP(rc);
1638 switch talloc_array_length(msg) {
1639 case 0:
1640 return NT_STATUS_NO_SUCH_ALIAS;
1641 case 1:
1642 break;
1643 default:
1644 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1647 if (!tldap_entry_dn(msg[0], &dn)) {
1648 TALLOC_FREE(msg);
1649 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1652 mods = NULL;
1653 num_mods = 0;
1654 ok = true;
1656 ok &= tldap_make_mod_fmt(
1657 msg[0], msg, &num_mods, &mods, "description",
1658 "%s", info->acct_desc);
1659 ok &= tldap_make_mod_fmt(
1660 msg[0], msg, &num_mods, &mods, "samAccountName",
1661 "%s", info->acct_name);
1662 if (!ok) {
1663 TALLOC_FREE(msg);
1664 return NT_STATUS_NO_MEMORY;
1666 if (num_mods == 0) {
1667 /* no change */
1668 TALLOC_FREE(msg);
1669 return NT_STATUS_OK;
1672 rc = tldap_modify(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
1673 TALLOC_FREE(msg);
1674 if (rc != LDB_SUCCESS) {
1675 DEBUG(10, ("ldap_modify failed: %s\n",
1676 ldb_errstring(state->ldb)));
1677 return NT_STATUS_LDAP(rc);
1679 return NT_STATUS_OK;
1681 #endif
1682 static NTSTATUS pdb_samba_dsdb_add_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_ADD);
1689 talloc_free(frame);
1690 return status;
1693 static NTSTATUS pdb_samba_dsdb_del_aliasmem(struct pdb_methods *m,
1694 const struct dom_sid *alias,
1695 const struct dom_sid *member)
1697 NTSTATUS status;
1698 TALLOC_CTX *frame = talloc_stackframe();
1699 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
1700 talloc_free(frame);
1701 return status;
1704 static NTSTATUS pdb_samba_dsdb_enum_aliasmem(struct pdb_methods *m,
1705 const struct dom_sid *alias,
1706 TALLOC_CTX *mem_ctx,
1707 struct dom_sid **pmembers,
1708 size_t *pnum_members)
1710 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1711 m->private_data, struct pdb_samba_dsdb_state);
1712 struct ldb_dn *dn;
1713 unsigned int num_members;
1714 NTSTATUS status;
1715 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1716 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1718 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, alias));
1719 if (!dn || !ldb_dn_validate(dn)) {
1720 return NT_STATUS_NO_MEMORY;
1723 status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
1724 *pnum_members = num_members;
1725 if (NT_STATUS_IS_OK(status)) {
1726 talloc_steal(mem_ctx, pmembers);
1728 talloc_free(tmp_ctx);
1729 return status;
1732 static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1733 TALLOC_CTX *mem_ctx,
1734 const struct dom_sid *domain_sid,
1735 const struct dom_sid *members,
1736 size_t num_members,
1737 uint32_t **palias_rids,
1738 size_t *pnum_alias_rids)
1740 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1741 m->private_data, struct pdb_samba_dsdb_state);
1742 uint32_t *alias_rids = NULL;
1743 size_t num_alias_rids = 0;
1744 int i;
1745 struct dom_sid *groupSIDs = NULL;
1746 unsigned int num_groupSIDs = 0;
1747 char *filter;
1748 NTSTATUS status;
1749 const char *sid_string;
1750 const char *sid_dn;
1751 DATA_BLOB sid_blob;
1753 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1754 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1756 * TODO: Get the filter right so that we only get the aliases from
1757 * either the SAM or BUILTIN
1760 filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
1761 GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1762 if (filter == NULL) {
1763 return NT_STATUS_NO_MEMORY;
1766 for (i = 0; i < num_members; i++) {
1767 sid_string = dom_sid_string(tmp_ctx, &members[i]);
1768 if (sid_string == NULL) {
1769 TALLOC_FREE(tmp_ctx);
1770 return NT_STATUS_NO_MEMORY;
1773 sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", sid_string);
1774 if (sid_dn == NULL) {
1775 TALLOC_FREE(tmp_ctx);
1776 return NT_STATUS_NO_MEMORY;
1779 sid_blob = data_blob_string_const(sid_dn);
1781 status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1782 tmp_ctx, &groupSIDs, &num_groupSIDs);
1783 if (!NT_STATUS_IS_OK(status)) {
1784 talloc_free(tmp_ctx);
1785 return status;
1789 alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1790 if (alias_rids == NULL) {
1791 talloc_free(tmp_ctx);
1792 return NT_STATUS_NO_MEMORY;
1795 for (i=0; i<num_groupSIDs; i++) {
1796 if (sid_peek_check_rid(domain_sid, &groupSIDs[i],
1797 &alias_rids[num_alias_rids])) {
1798 num_alias_rids++;;
1802 *palias_rids = alias_rids;
1803 *pnum_alias_rids = num_alias_rids;
1804 return NT_STATUS_OK;
1807 static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1808 const struct dom_sid *domain_sid,
1809 int num_rids,
1810 uint32_t *rids,
1811 const char **names,
1812 enum lsa_SidType *lsa_attrs)
1814 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1815 m->private_data, struct pdb_samba_dsdb_state);
1816 NTSTATUS status;
1818 TALLOC_CTX *tmp_ctx;
1820 if (num_rids == 0) {
1821 return NT_STATUS_NONE_MAPPED;
1824 tmp_ctx = talloc_stackframe();
1825 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1827 status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1828 talloc_free(tmp_ctx);
1829 return status;
1832 static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1833 const struct dom_sid *domain_sid,
1834 int num_names,
1835 const char **pp_names,
1836 uint32_t *rids,
1837 enum lsa_SidType *attrs)
1839 return NT_STATUS_NOT_IMPLEMENTED;
1842 static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1843 enum pdb_policy_type type,
1844 uint32_t *value)
1846 return account_policy_get(type, value)
1847 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1850 static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1851 enum pdb_policy_type type,
1852 uint32_t value)
1854 return account_policy_set(type, value)
1855 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1858 static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1859 time_t *seq_num_out)
1861 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1862 m->private_data, struct pdb_samba_dsdb_state);
1863 uint64_t seq_num;
1864 int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1865 if (ret == LDB_SUCCESS) {
1866 *seq_num_out = seq_num;
1867 return NT_STATUS_OK;
1868 } else {
1869 return NT_STATUS_UNSUCCESSFUL;
1873 struct pdb_samba_dsdb_search_state {
1874 uint32_t acct_flags;
1875 struct samr_displayentry *entries;
1876 uint32_t num_entries;
1877 ssize_t array_size;
1878 uint32_t current;
1881 static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1882 struct samr_displayentry *entry)
1884 struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1885 search->private_data, struct pdb_samba_dsdb_search_state);
1887 if (state->current == state->num_entries) {
1888 return false;
1891 entry->idx = state->entries[state->current].idx;
1892 entry->rid = state->entries[state->current].rid;
1893 entry->acct_flags = state->entries[state->current].acct_flags;
1895 entry->account_name = talloc_strdup(
1896 search, state->entries[state->current].account_name);
1897 entry->fullname = talloc_strdup(
1898 search, state->entries[state->current].fullname);
1899 entry->description = talloc_strdup(
1900 search, state->entries[state->current].description);
1902 state->current += 1;
1903 return true;
1906 static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1908 struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1909 search->private_data, struct pdb_samba_dsdb_search_state);
1910 talloc_free(state);
1913 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1914 struct pdb_search *search,
1915 struct pdb_samba_dsdb_search_state **pstate,
1916 const char *exp_fmt, ...)
1917 PRINTF_ATTRIBUTE(4, 5);
1919 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1920 struct pdb_search *search,
1921 struct pdb_samba_dsdb_search_state **pstate,
1922 const char *exp_fmt, ...)
1924 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1925 m->private_data, struct pdb_samba_dsdb_state);
1926 struct pdb_samba_dsdb_search_state *sstate;
1927 const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1928 "userAccountControl", "description", NULL };
1929 struct ldb_result *res;
1930 int i, rc, num_users;
1932 va_list ap;
1933 char *expression = NULL;
1935 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1936 if (!tmp_ctx) {
1937 return false;
1940 va_start(ap, exp_fmt);
1941 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1942 va_end(ap);
1944 if (!expression) {
1945 talloc_free(tmp_ctx);
1946 return LDB_ERR_OPERATIONS_ERROR;
1949 sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1950 if (sstate == NULL) {
1951 talloc_free(tmp_ctx);
1952 return false;
1955 rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1956 if (rc != LDB_SUCCESS) {
1957 talloc_free(tmp_ctx);
1958 DEBUG(10, ("dsdb_search failed: %s\n",
1959 ldb_errstring(state->ldb)));
1960 return false;
1963 num_users = res->count;
1965 sstate->entries = talloc_array(sstate, struct samr_displayentry,
1966 num_users);
1967 if (sstate->entries == NULL) {
1968 talloc_free(tmp_ctx);
1969 DEBUG(10, ("talloc failed\n"));
1970 return false;
1973 sstate->num_entries = 0;
1975 for (i=0; i<num_users; i++) {
1976 struct samr_displayentry *e;
1977 struct dom_sid *sid;
1979 e = &sstate->entries[sstate->num_entries];
1981 e->idx = sstate->num_entries;
1982 sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
1983 if (!sid) {
1984 talloc_free(tmp_ctx);
1985 DEBUG(10, ("Could not pull SID\n"));
1986 return false;
1988 sid_peek_rid(sid, &e->rid);
1990 e->acct_flags = samdb_result_acct_flags(res->msgs[i], "userAccountControl");
1991 e->account_name = ldb_msg_find_attr_as_string(
1992 res->msgs[i], "samAccountName", NULL);
1993 if (e->account_name == NULL) {
1994 talloc_free(tmp_ctx);
1995 return false;
1997 e->fullname = ldb_msg_find_attr_as_string(
1998 res->msgs[i], "displayName", "");
1999 e->description = ldb_msg_find_attr_as_string(
2000 res->msgs[i], "description", "");
2002 sstate->num_entries += 1;
2003 if (sstate->num_entries >= num_users) {
2004 break;
2007 talloc_steal(sstate->entries, res->msgs);
2008 search->private_data = talloc_steal(search, sstate);
2009 search->next_entry = pdb_samba_dsdb_next_entry;
2010 search->search_end = pdb_samba_dsdb_search_end;
2011 *pstate = sstate;
2012 talloc_free(tmp_ctx);
2013 return true;
2016 static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
2017 struct pdb_search *search,
2018 uint32_t acct_flags)
2020 struct pdb_samba_dsdb_search_state *sstate;
2021 bool ret;
2023 ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
2024 if (!ret) {
2025 return false;
2027 sstate->acct_flags = acct_flags;
2028 return true;
2031 static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
2032 struct pdb_search *search)
2034 struct pdb_samba_dsdb_search_state *sstate;
2035 bool ret;
2037 ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2038 "(&(grouptype=%d)(objectclass=group))",
2039 GTYPE_SECURITY_GLOBAL_GROUP);
2040 if (!ret) {
2041 return false;
2043 sstate->acct_flags = 0;
2044 return true;
2047 static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
2048 struct pdb_search *search,
2049 const struct dom_sid *sid)
2051 struct pdb_samba_dsdb_search_state *sstate;
2052 bool ret;
2054 ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2055 "(&(grouptype=%d)(objectclass=group))",
2056 sid_check_is_builtin(sid)
2057 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2058 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2059 if (!ret) {
2060 return false;
2062 sstate->acct_flags = 0;
2063 return true;
2067 * Instead of taking a gid or uid, this function takes a pointer to a
2068 * unixid.
2070 * This acts as an in-out variable so that the idmap functions can correctly
2071 * receive ID_TYPE_BOTH, and this function ensures cache details are filled
2072 * correctly rather than forcing the cache to store ID_TYPE_UID or ID_TYPE_GID.
2074 static bool pdb_samba_dsdb_id_to_sid(struct pdb_methods *m, struct unixid *id,
2075 struct dom_sid *sid)
2077 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2078 m->private_data, struct pdb_samba_dsdb_state);
2079 NTSTATUS status;
2080 struct id_map id_map;
2081 struct id_map *id_maps[2];
2082 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2083 if (!tmp_ctx) {
2084 return false;
2087 id_map.xid = *id;
2088 id_maps[0] = &id_map;
2089 id_maps[1] = NULL;
2091 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2092 if (!NT_STATUS_IS_OK(status)) {
2093 talloc_free(tmp_ctx);
2094 return false;
2097 if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2098 id->type = id_map.xid.type;
2100 *sid = *id_map.sid;
2101 talloc_free(tmp_ctx);
2102 return true;
2105 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2106 struct unixid *id)
2108 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2109 m->private_data, struct pdb_samba_dsdb_state);
2110 struct id_map id_map;
2111 struct id_map *id_maps[2];
2112 NTSTATUS status;
2113 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2114 if (!tmp_ctx) {
2115 return false;
2118 ZERO_STRUCT(id_map);
2119 id_map.sid = discard_const_p(struct dom_sid, sid);
2120 id_maps[0] = &id_map;
2121 id_maps[1] = NULL;
2123 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2124 talloc_free(tmp_ctx);
2125 if (!NT_STATUS_IS_OK(status)) {
2126 return false;
2128 if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2129 *id = id_map.xid;
2130 return true;
2132 return false;
2135 static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2137 return PDB_CAP_STORE_RIDS | PDB_CAP_ADS | PDB_CAP_TRUSTED_DOMAINS_EX;
2140 static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32_t *rid)
2142 return false;
2145 static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2146 const char *domain, char** pwd,
2147 struct dom_sid *sid,
2148 time_t *pass_last_set_time)
2150 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2151 m->private_data, struct pdb_samba_dsdb_state);
2152 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2153 const char * const attrs[] = {
2154 "securityIdentifier",
2155 "flatName",
2156 "trustPartner",
2157 "trustAuthOutgoing",
2158 "whenCreated",
2159 "msDS-SupportedEncryptionTypes",
2160 "trustAttributes",
2161 "trustDirection",
2162 "trustType",
2163 NULL
2165 struct ldb_message *msg;
2166 const struct ldb_val *password_val;
2167 int trust_direction_flags;
2168 int trust_type;
2169 int i;
2170 DATA_BLOB password_utf16;
2171 struct trustAuthInOutBlob password_blob;
2172 struct AuthenticationInformationArray *auth_array;
2173 char *password_talloc;
2174 size_t password_len;
2175 enum ndr_err_code ndr_err;
2176 NTSTATUS status;
2177 const char *netbios_domain = NULL;
2178 const struct dom_sid *domain_sid = NULL;
2180 status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2181 attrs, tmp_ctx, &msg);
2182 if (!NT_STATUS_IS_OK(status)) {
2184 * This can be called to work out of a domain is
2185 * trusted, rather than just to get the password
2187 DEBUG(2, ("Failed to get trusted domain password for %s - %s. "
2188 "It may not be a trusted domain.\n", domain,
2189 nt_errstr(status)));
2190 TALLOC_FREE(tmp_ctx);
2191 return false;
2194 netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2195 if (netbios_domain == NULL) {
2196 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2197 domain));
2198 TALLOC_FREE(tmp_ctx);
2199 return false;
2202 domain_sid = samdb_result_dom_sid(tmp_ctx, msg, "securityIdentifier");
2203 if (domain_sid == NULL) {
2204 DEBUG(2, ("Trusted domain %s has no securityIdentifier defined.\n",
2205 domain));
2206 TALLOC_FREE(tmp_ctx);
2207 return false;
2210 trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2211 if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2212 DEBUG(2, ("Trusted domain %s is is not an outbound trust.\n",
2213 domain));
2214 TALLOC_FREE(tmp_ctx);
2215 return false;
2218 trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2219 if (trust_type == LSA_TRUST_TYPE_MIT) {
2220 DEBUG(1, ("Trusted domain %s is is not an AD trust "
2221 "(trustType == LSA_TRUST_TYPE_MIT).\n",
2222 domain));
2223 TALLOC_FREE(tmp_ctx);
2224 return false;
2227 password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2228 if (password_val == NULL) {
2229 DEBUG(2, ("Failed to get trusted domain password for %s, "
2230 "attribute trustAuthOutgoing not returned.\n", domain));
2231 TALLOC_FREE(tmp_ctx);
2232 return false;
2235 ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2236 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2237 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2238 DEBUG(0, ("Failed to get trusted domain password for %s, "
2239 "attribute trustAuthOutgoing coult not be parsed %s.\n",
2240 domain,
2241 ndr_map_error2string(ndr_err)));
2242 TALLOC_FREE(tmp_ctx);
2243 return false;
2246 auth_array = &password_blob.current;
2248 for (i=0; i < auth_array->count; i++) {
2249 if (auth_array->array[i].AuthType == TRUST_AUTH_TYPE_CLEAR) {
2250 break;
2254 if (i == auth_array->count) {
2255 DEBUG(0, ("Trusted domain %s does not have a "
2256 "clear-text password stored\n",
2257 domain));
2258 TALLOC_FREE(tmp_ctx);
2259 return false;
2262 password_utf16 = data_blob_const(auth_array->array[i].AuthInfo.clear.password,
2263 auth_array->array[i].AuthInfo.clear.size);
2266 * In the future, make this function return a
2267 * cli_credentials that can store a MD4 hash with cli_credential_set_nt_hash()
2268 * but for now convert to UTF8 and fail if the string can not be converted.
2270 * We can't safely convert the random strings windows uses into
2271 * utf8.
2273 if (!convert_string_talloc(tmp_ctx,
2274 CH_UTF16MUNGED, CH_UTF8,
2275 password_utf16.data, password_utf16.length,
2276 (void *)&password_talloc,
2277 &password_len)) {
2278 DEBUG(0, ("FIXME: Could not convert password for trusted domain %s"
2279 " to UTF8. This may be a password set from Windows.\n",
2280 domain));
2281 TALLOC_FREE(tmp_ctx);
2282 return false;
2284 *pwd = SMB_STRNDUP(password_talloc, password_len);
2285 if (pass_last_set_time) {
2286 *pass_last_set_time = nt_time_to_unix(auth_array->array[i].LastUpdateTime);
2289 if (sid != NULL) {
2290 sid_copy(sid, domain_sid);
2293 TALLOC_FREE(tmp_ctx);
2294 return true;
2297 static NTSTATUS pdb_samba_dsdb_get_trusteddom_creds(struct pdb_methods *m,
2298 const char *domain,
2299 TALLOC_CTX *mem_ctx,
2300 struct cli_credentials **_creds)
2302 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2303 m->private_data, struct pdb_samba_dsdb_state);
2304 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2305 const char * const attrs[] = {
2306 "securityIdentifier",
2307 "flatName",
2308 "trustPartner",
2309 "trustAuthOutgoing",
2310 "whenCreated",
2311 "msDS-SupportedEncryptionTypes",
2312 "trustAttributes",
2313 "trustDirection",
2314 "trustType",
2315 NULL
2317 struct ldb_message *msg;
2318 const struct ldb_val *password_val;
2319 int trust_direction_flags;
2320 int trust_type;
2321 int i;
2322 DATA_BLOB password_utf16 = {};
2323 struct samr_Password *password_nt = NULL;
2324 uint32_t password_version = 0;
2325 DATA_BLOB old_password_utf16 = {};
2326 struct samr_Password *old_password_nt = NULL;
2327 struct trustAuthInOutBlob password_blob;
2328 enum ndr_err_code ndr_err;
2329 NTSTATUS status;
2330 time_t last_set_time = 0;
2331 struct cli_credentials *creds = NULL;
2332 bool ok;
2333 const char *my_netbios_name = NULL;
2334 const char *my_netbios_domain = NULL;
2335 const char *my_dns_domain = NULL;
2336 const char *netbios_domain = NULL;
2337 char *account_name = NULL;
2338 char *principal_name = NULL;
2339 const char *dns_domain = NULL;
2341 status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2342 attrs, tmp_ctx, &msg);
2343 if (!NT_STATUS_IS_OK(status)) {
2345 * This can be called to work out of a domain is
2346 * trusted, rather than just to get the password
2348 DEBUG(2, ("Failed to get trusted domain password for %s - %s "
2349 "It may not be a trusted domain.\n", domain,
2350 nt_errstr(status)));
2351 TALLOC_FREE(tmp_ctx);
2352 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2355 netbios_domain = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2356 if (netbios_domain == NULL) {
2357 DEBUG(2, ("Trusted domain %s has to flatName defined.\n",
2358 domain));
2359 TALLOC_FREE(tmp_ctx);
2360 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2363 dns_domain = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2365 trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2366 if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2367 DEBUG(2, ("Trusted domain %s is is not an outbound trust.\n",
2368 domain));
2369 TALLOC_FREE(tmp_ctx);
2370 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2373 trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2374 if (trust_type == LSA_TRUST_TYPE_MIT) {
2375 DEBUG(1, ("Trusted domain %s is is not an AD trust "
2376 "(trustType == LSA_TRUST_TYPE_MIT).\n",
2377 domain));
2378 TALLOC_FREE(tmp_ctx);
2379 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2382 password_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2383 if (password_val == NULL) {
2384 DEBUG(2, ("Failed to get trusted domain password for %s, "
2385 "attribute trustAuthOutgoing not returned.\n", domain));
2386 TALLOC_FREE(tmp_ctx);
2387 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2390 ndr_err = ndr_pull_struct_blob(password_val, tmp_ctx, &password_blob,
2391 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2392 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2393 DEBUG(0, ("Failed to get trusted domain password for %s, "
2394 "attribute trustAuthOutgoing coult not be parsed %s.\n",
2395 domain,
2396 ndr_map_error2string(ndr_err)));
2397 TALLOC_FREE(tmp_ctx);
2398 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2401 for (i=0; i < password_blob.current.count; i++) {
2402 struct AuthenticationInformation *a =
2403 &password_blob.current.array[i];
2405 switch (a->AuthType) {
2406 case TRUST_AUTH_TYPE_NONE:
2407 break;
2409 case TRUST_AUTH_TYPE_VERSION:
2410 password_version = a->AuthInfo.version.version;
2411 break;
2413 case TRUST_AUTH_TYPE_CLEAR:
2414 last_set_time = nt_time_to_unix(a->LastUpdateTime);
2416 password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2417 a->AuthInfo.clear.size);
2418 password_nt = NULL;
2419 break;
2421 case TRUST_AUTH_TYPE_NT4OWF:
2422 if (password_utf16.length != 0) {
2423 break;
2426 last_set_time = nt_time_to_unix(a->LastUpdateTime);
2428 password_nt = &a->AuthInfo.nt4owf.password;
2429 break;
2433 for (i=0; i < password_blob.previous.count; i++) {
2434 struct AuthenticationInformation *a = &password_blob.previous.array[i];
2436 switch (a->AuthType) {
2437 case TRUST_AUTH_TYPE_NONE:
2438 break;
2440 case TRUST_AUTH_TYPE_VERSION:
2441 break;
2443 case TRUST_AUTH_TYPE_CLEAR:
2444 old_password_utf16 = data_blob_const(a->AuthInfo.clear.password,
2445 a->AuthInfo.clear.size);
2446 old_password_nt = NULL;
2447 break;
2449 case TRUST_AUTH_TYPE_NT4OWF:
2450 if (old_password_utf16.length != 0) {
2451 break;
2454 old_password_nt = &a->AuthInfo.nt4owf.password;
2455 break;
2459 if (password_utf16.length == 0 && password_nt == NULL) {
2460 DEBUG(0, ("Trusted domain %s does not have a "
2461 "clear-text nor nt password stored\n",
2462 domain));
2463 TALLOC_FREE(tmp_ctx);
2464 return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2467 my_netbios_name = lpcfg_netbios_name(state->lp_ctx);
2468 my_netbios_domain = lpcfg_workgroup(state->lp_ctx);
2469 my_dns_domain = lpcfg_dnsdomain(state->lp_ctx);
2471 creds = cli_credentials_init(tmp_ctx);
2472 if (creds == NULL) {
2473 TALLOC_FREE(tmp_ctx);
2474 return NT_STATUS_NO_MEMORY;
2477 ok = cli_credentials_set_workstation(creds, my_netbios_name, CRED_SPECIFIED);
2478 if (!ok) {
2479 TALLOC_FREE(tmp_ctx);
2480 return NT_STATUS_NO_MEMORY;
2483 ok = cli_credentials_set_domain(creds, netbios_domain, CRED_SPECIFIED);
2484 if (!ok) {
2485 TALLOC_FREE(tmp_ctx);
2486 return NT_STATUS_NO_MEMORY;
2488 ok = cli_credentials_set_realm(creds, dns_domain, CRED_SPECIFIED);
2489 if (!ok) {
2490 TALLOC_FREE(tmp_ctx);
2491 return NT_STATUS_NO_MEMORY;
2494 if (my_dns_domain != NULL && dns_domain != NULL) {
2495 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DNS_DOMAIN);
2496 account_name = talloc_asprintf(tmp_ctx, "%s.", my_dns_domain);
2497 if (account_name == NULL) {
2498 TALLOC_FREE(tmp_ctx);
2499 return NT_STATUS_NO_MEMORY;
2501 principal_name = talloc_asprintf(tmp_ctx, "%s$@%s", my_netbios_domain,
2502 cli_credentials_get_realm(creds));
2503 if (principal_name == NULL) {
2504 TALLOC_FREE(tmp_ctx);
2505 return NT_STATUS_NO_MEMORY;
2507 } else {
2508 cli_credentials_set_secure_channel_type(creds, SEC_CHAN_DOMAIN);
2509 account_name = talloc_asprintf(tmp_ctx, "%s$", my_netbios_domain);
2510 if (account_name == NULL) {
2511 TALLOC_FREE(tmp_ctx);
2512 return NT_STATUS_NO_MEMORY;
2514 principal_name = NULL;
2517 ok = cli_credentials_set_username(creds, account_name, CRED_SPECIFIED);
2518 if (!ok) {
2519 TALLOC_FREE(tmp_ctx);
2520 return NT_STATUS_NO_MEMORY;
2523 if (principal_name != NULL) {
2524 ok = cli_credentials_set_principal(creds, principal_name,
2525 CRED_SPECIFIED);
2526 if (!ok) {
2527 TALLOC_FREE(tmp_ctx);
2528 return NT_STATUS_NO_MEMORY;
2532 if (old_password_nt != NULL) {
2533 ok = cli_credentials_set_old_nt_hash(creds, old_password_nt);
2534 if (!ok) {
2535 TALLOC_FREE(tmp_ctx);
2536 return NT_STATUS_NO_MEMORY;
2540 if (old_password_utf16.length > 0) {
2541 ok = cli_credentials_set_old_utf16_password(creds,
2542 &old_password_utf16);
2543 if (!ok) {
2544 TALLOC_FREE(tmp_ctx);
2545 return NT_STATUS_NO_MEMORY;
2549 if (password_nt != NULL) {
2550 ok = cli_credentials_set_nt_hash(creds, password_nt,
2551 CRED_SPECIFIED);
2552 if (!ok) {
2553 TALLOC_FREE(tmp_ctx);
2554 return NT_STATUS_NO_MEMORY;
2558 if (password_utf16.length > 0) {
2559 ok = cli_credentials_set_utf16_password(creds,
2560 &password_utf16,
2561 CRED_SPECIFIED);
2562 if (!ok) {
2563 TALLOC_FREE(tmp_ctx);
2564 return NT_STATUS_NO_MEMORY;
2568 cli_credentials_set_password_last_changed_time(creds, last_set_time);
2569 cli_credentials_set_kvno(creds, password_version);
2571 if (password_utf16.length > 0 && dns_domain != NULL) {
2573 * Force kerberos if this is an active directory domain
2575 cli_credentials_set_kerberos_state(creds,
2576 CRED_MUST_USE_KERBEROS);
2577 } else {
2579 * TODO: we should allow krb5 with the raw nt hash.
2581 cli_credentials_set_kerberos_state(creds,
2582 CRED_DONT_USE_KERBEROS);
2585 *_creds = talloc_move(mem_ctx, &creds);
2586 TALLOC_FREE(tmp_ctx);
2587 return NT_STATUS_OK;
2590 static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2591 const char* domain, const char* pwd,
2592 const struct dom_sid *sid)
2594 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2595 m->private_data, struct pdb_samba_dsdb_state);
2596 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2597 const char * const attrs[] = {
2598 "trustAuthOutgoing",
2599 "trustDirection",
2600 "trustType",
2601 NULL
2603 struct ldb_message *msg = NULL;
2604 int trust_direction_flags;
2605 int trust_type;
2606 int i;
2607 const struct ldb_val *old_val = NULL;
2608 struct trustAuthInOutBlob old_blob = {};
2609 uint32_t old_version = 0;
2610 uint32_t new_version = 0;
2611 DATA_BLOB new_utf16 = {};
2612 struct trustAuthInOutBlob new_blob = {};
2613 struct ldb_val new_val = {};
2614 struct timeval tv = timeval_current();
2615 NTTIME now = timeval_to_nttime(&tv);
2616 enum ndr_err_code ndr_err;
2617 NTSTATUS status;
2618 bool ok;
2619 int ret;
2621 ret = ldb_transaction_start(state->ldb);
2622 if (ret != LDB_SUCCESS) {
2623 DEBUG(2, ("Failed to start transaction.\n"));
2624 TALLOC_FREE(tmp_ctx);
2625 return false;
2628 ok = samdb_is_pdc(state->ldb);
2629 if (!ok) {
2630 DEBUG(2, ("Password changes for domain %s are only allowed on a PDC.\n",
2631 domain));
2632 TALLOC_FREE(tmp_ctx);
2633 ldb_transaction_cancel(state->ldb);
2634 return false;
2637 status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
2638 attrs, tmp_ctx, &msg);
2639 if (!NT_STATUS_IS_OK(status)) {
2641 * This can be called to work out of a domain is
2642 * trusted, rather than just to get the password
2644 DEBUG(2, ("Failed to get trusted domain password for %s - %s. "
2645 "It may not be a trusted domain.\n", domain,
2646 nt_errstr(status)));
2647 TALLOC_FREE(tmp_ctx);
2648 ldb_transaction_cancel(state->ldb);
2649 return false;
2652 trust_direction_flags = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2653 if (!(trust_direction_flags & LSA_TRUST_DIRECTION_OUTBOUND)) {
2654 DEBUG(2, ("Trusted domain %s is is not an outbound trust, can't set a password.\n",
2655 domain));
2656 TALLOC_FREE(tmp_ctx);
2657 ldb_transaction_cancel(state->ldb);
2658 return false;
2661 trust_type = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2662 switch (trust_type) {
2663 case LSA_TRUST_TYPE_DOWNLEVEL:
2664 case LSA_TRUST_TYPE_UPLEVEL:
2665 break;
2666 default:
2667 DEBUG(0, ("Trusted domain %s is of type 0x%X - "
2668 "password changes are not supported\n",
2669 domain, (unsigned)trust_type));
2670 TALLOC_FREE(tmp_ctx);
2671 ldb_transaction_cancel(state->ldb);
2672 return false;
2675 old_val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
2676 if (old_val != NULL) {
2677 ndr_err = ndr_pull_struct_blob(old_val, tmp_ctx, &old_blob,
2678 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
2679 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2680 DEBUG(0, ("Failed to get trusted domain password for %s, "
2681 "attribute trustAuthOutgoing coult not be parsed %s.\n",
2682 domain,
2683 ndr_map_error2string(ndr_err)));
2684 TALLOC_FREE(tmp_ctx);
2685 ldb_transaction_cancel(state->ldb);
2686 return false;
2690 for (i=0; i < old_blob.current.count; i++) {
2691 struct AuthenticationInformation *a =
2692 &old_blob.current.array[i];
2694 switch (a->AuthType) {
2695 case TRUST_AUTH_TYPE_NONE:
2696 break;
2698 case TRUST_AUTH_TYPE_VERSION:
2699 old_version = a->AuthInfo.version.version;
2700 break;
2702 case TRUST_AUTH_TYPE_CLEAR:
2703 break;
2705 case TRUST_AUTH_TYPE_NT4OWF:
2706 break;
2710 new_version = old_version + 1;
2711 ok = convert_string_talloc(tmp_ctx,
2712 CH_UNIX, CH_UTF16,
2713 pwd, strlen(pwd),
2714 (void *)&new_utf16.data,
2715 &new_utf16.length);
2716 if (!ok) {
2717 DEBUG(0, ("Failed to generate new_utf16 password for domain %s\n",
2718 domain));
2719 TALLOC_FREE(tmp_ctx);
2720 ldb_transaction_cancel(state->ldb);
2721 return false;
2724 if (new_utf16.length < 28) {
2725 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to short.\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;
2733 if (new_utf16.length > 498) {
2734 DEBUG(0, ("new_utf16[%zu] version[%u] for domain %s to long.\n",
2735 new_utf16.length,
2736 (unsigned)new_version,
2737 domain));
2738 TALLOC_FREE(tmp_ctx);
2739 ldb_transaction_cancel(state->ldb);
2740 return false;
2743 new_blob.count = MAX(old_blob.current.count, 2);
2744 new_blob.current.array = talloc_zero_array(tmp_ctx,
2745 struct AuthenticationInformation,
2746 new_blob.count);
2747 if (new_blob.current.array == NULL) {
2748 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2749 (unsigned)new_blob.count));
2750 TALLOC_FREE(tmp_ctx);
2751 ldb_transaction_cancel(state->ldb);
2752 return false;
2754 new_blob.previous.array = talloc_zero_array(tmp_ctx,
2755 struct AuthenticationInformation,
2756 new_blob.count);
2757 if (new_blob.current.array == NULL) {
2758 DEBUG(0, ("talloc_zero_array(%u) failed\n",
2759 (unsigned)new_blob.count));
2760 TALLOC_FREE(tmp_ctx);
2761 ldb_transaction_cancel(state->ldb);
2762 return false;
2765 for (i = 0; i < old_blob.current.count; i++) {
2766 struct AuthenticationInformation *o =
2767 &old_blob.current.array[i];
2768 struct AuthenticationInformation *p =
2769 &new_blob.previous.array[i];
2771 *p = *o;
2772 new_blob.previous.count++;
2774 for (; i < new_blob.count; i++) {
2775 struct AuthenticationInformation *pi =
2776 &new_blob.previous.array[i];
2778 if (i == 0) {
2780 * new_blob.previous is still empty so
2781 * we'll do new_blob.previous = new_blob.current
2782 * below.
2784 break;
2787 pi->LastUpdateTime = now;
2788 pi->AuthType = TRUST_AUTH_TYPE_NONE;
2789 new_blob.previous.count++;
2792 for (i = 0; i < new_blob.count; i++) {
2793 struct AuthenticationInformation *ci =
2794 &new_blob.current.array[i];
2796 ci->LastUpdateTime = now;
2797 switch (i) {
2798 case 0:
2799 ci->AuthType = TRUST_AUTH_TYPE_CLEAR;
2800 ci->AuthInfo.clear.size = new_utf16.length;
2801 ci->AuthInfo.clear.password = new_utf16.data;
2802 break;
2803 case 1:
2804 ci->AuthType = TRUST_AUTH_TYPE_VERSION;
2805 ci->AuthInfo.version.version = new_version;
2806 break;
2807 default:
2808 ci->AuthType = TRUST_AUTH_TYPE_NONE;
2809 break;
2812 new_blob.current.count++;
2815 if (new_blob.previous.count == 0) {
2816 TALLOC_FREE(new_blob.previous.array);
2817 new_blob.previous = new_blob.current;
2820 ndr_err = ndr_push_struct_blob(&new_val, tmp_ctx, &new_blob,
2821 (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
2822 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
2823 DEBUG(0, ("Failed to generate trustAuthOutgoing for "
2824 "trusted domain password for %s: %s.\n",
2825 domain, ndr_map_error2string(ndr_err)));
2826 TALLOC_FREE(tmp_ctx);
2827 ldb_transaction_cancel(state->ldb);
2828 return false;
2831 msg->num_elements = 0;
2832 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2833 LDB_FLAG_MOD_REPLACE, NULL);
2834 if (ret != LDB_SUCCESS) {
2835 DEBUG(0, ("ldb_msg_add_empty() failed\n"));
2836 TALLOC_FREE(tmp_ctx);
2837 ldb_transaction_cancel(state->ldb);
2838 return false;
2840 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2841 &new_val, NULL);
2842 if (ret != LDB_SUCCESS) {
2843 DEBUG(0, ("ldb_msg_add_value() failed\n"));
2844 TALLOC_FREE(tmp_ctx);
2845 ldb_transaction_cancel(state->ldb);
2846 return false;
2849 ret = ldb_modify(state->ldb, msg);
2850 if (ret != LDB_SUCCESS) {
2851 DEBUG(0, ("Failed to replace trustAuthOutgoing for "
2852 "trusted domain password for %s: %s - %s\n",
2853 domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2854 TALLOC_FREE(tmp_ctx);
2855 ldb_transaction_cancel(state->ldb);
2856 return false;
2859 ret = ldb_transaction_commit(state->ldb);
2860 if (ret != LDB_SUCCESS) {
2861 DEBUG(0, ("Failed to commit trustAuthOutgoing for "
2862 "trusted domain password for %s: %s - %s\n",
2863 domain, ldb_strerror(ret), ldb_errstring(state->ldb)));
2864 TALLOC_FREE(tmp_ctx);
2865 return false;
2868 DEBUG(1, ("Added new_version[%u] to trustAuthOutgoing for "
2869 "trusted domain password for %s.\n",
2870 (unsigned)new_version, domain));
2871 TALLOC_FREE(tmp_ctx);
2872 return true;
2875 static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2876 const char *domain)
2878 return false;
2881 static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2882 TALLOC_CTX *mem_ctx,
2883 uint32_t *_num_domains,
2884 struct trustdom_info ***_domains)
2886 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2887 m->private_data, struct pdb_samba_dsdb_state);
2888 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2889 const char * const attrs[] = {
2890 "securityIdentifier",
2891 "flatName",
2892 "trustDirection",
2893 NULL
2895 struct ldb_result *res = NULL;
2896 unsigned int i;
2897 struct trustdom_info **domains = NULL;
2898 NTSTATUS status;
2899 uint32_t di = 0;
2901 *_num_domains = 0;
2902 *_domains = NULL;
2904 status = dsdb_trust_search_tdos(state->ldb, NULL,
2905 attrs, tmp_ctx, &res);
2906 if (!NT_STATUS_IS_OK(status)) {
2907 DBG_ERR("dsdb_trust_search_tdos() - %s ", nt_errstr(status));
2908 TALLOC_FREE(tmp_ctx);
2909 return status;
2912 if (res->count == 0) {
2913 TALLOC_FREE(tmp_ctx);
2914 return NT_STATUS_OK;
2917 domains = talloc_zero_array(tmp_ctx, struct trustdom_info *,
2918 res->count);
2919 if (domains == NULL) {
2920 TALLOC_FREE(tmp_ctx);
2921 return NT_STATUS_NO_MEMORY;
2924 for (i = 0; i < res->count; i++) {
2925 struct ldb_message *msg = res->msgs[i];
2926 struct trustdom_info *d = NULL;
2927 const char *name = NULL;
2928 struct dom_sid *sid = NULL;
2929 uint32_t direction;
2931 d = talloc_zero(domains, struct trustdom_info);
2932 if (d == NULL) {
2933 TALLOC_FREE(tmp_ctx);
2934 return NT_STATUS_NO_MEMORY;
2937 name = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2938 if (name == NULL) {
2939 TALLOC_FREE(tmp_ctx);
2940 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2942 sid = samdb_result_dom_sid(msg, msg, "securityIdentifier");
2943 if (sid == NULL) {
2944 continue;
2947 direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
2948 if (!(direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2949 continue;
2952 d->name = talloc_strdup(d, name);
2953 if (d->name == NULL) {
2954 TALLOC_FREE(tmp_ctx);
2955 return NT_STATUS_NO_MEMORY;
2957 d->sid = *sid;
2959 domains[di++] = d;
2962 domains = talloc_realloc(domains, domains, struct trustdom_info *, di);
2963 *_domains = talloc_move(mem_ctx, &domains);
2964 *_num_domains = di;
2965 TALLOC_FREE(tmp_ctx);
2966 return NT_STATUS_OK;
2969 static NTSTATUS pdb_samba_dsdb_msg_to_trusted_domain(const struct ldb_message *msg,
2970 TALLOC_CTX *mem_ctx,
2971 struct pdb_trusted_domain **_d)
2973 struct pdb_trusted_domain *d = NULL;
2974 const char *str = NULL;
2975 struct dom_sid *sid = NULL;
2976 const struct ldb_val *val = NULL;
2977 uint64_t val64;
2979 *_d = NULL;
2981 d = talloc_zero(mem_ctx, struct pdb_trusted_domain);
2982 if (d == NULL) {
2983 return NT_STATUS_NO_MEMORY;
2986 str = ldb_msg_find_attr_as_string(msg, "flatName", NULL);
2987 if (str == NULL) {
2988 TALLOC_FREE(d);
2989 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2991 d->netbios_name = talloc_strdup(d, str);
2992 if (d->netbios_name == NULL) {
2993 TALLOC_FREE(d);
2994 return NT_STATUS_NO_MEMORY;
2997 str = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2998 if (str != NULL) {
2999 d->domain_name = talloc_strdup(d, str);
3000 if (d->domain_name == NULL) {
3001 TALLOC_FREE(d);
3002 return NT_STATUS_NO_MEMORY;
3006 sid = samdb_result_dom_sid(d, msg, "securityIdentifier");
3007 if (sid != NULL) {
3008 d->security_identifier = *sid;
3009 TALLOC_FREE(sid);
3012 val = ldb_msg_find_ldb_val(msg, "trustAuthOutgoing");
3013 if (val != NULL) {
3014 d->trust_auth_outgoing = data_blob_dup_talloc(d, *val);
3015 if (d->trust_auth_outgoing.data == NULL) {
3016 TALLOC_FREE(d);
3017 return NT_STATUS_NO_MEMORY;
3020 val = ldb_msg_find_ldb_val(msg, "trustAuthIncoming");
3021 if (val != NULL) {
3022 d->trust_auth_incoming = data_blob_dup_talloc(d, *val);
3023 if (d->trust_auth_incoming.data == NULL) {
3024 TALLOC_FREE(d);
3025 return NT_STATUS_NO_MEMORY;
3029 d->trust_direction = ldb_msg_find_attr_as_uint(msg, "trustDirection", 0);
3030 d->trust_type = ldb_msg_find_attr_as_uint(msg, "trustType", 0);
3031 d->trust_attributes = ldb_msg_find_attr_as_uint(msg, "trustAttributes", 0);
3033 val64 = ldb_msg_find_attr_as_uint64(msg, "trustPosixOffset", UINT64_MAX);
3034 if (val64 != UINT64_MAX) {
3035 d->trust_posix_offset = talloc(d, uint32_t);
3036 if (d->trust_posix_offset == NULL) {
3037 TALLOC_FREE(d);
3038 return NT_STATUS_NO_MEMORY;
3040 *d->trust_posix_offset = (uint32_t)val64;
3043 val64 = ldb_msg_find_attr_as_uint64(msg, "msDS-SupportedEncryptionTypes", UINT64_MAX);
3044 if (val64 != UINT64_MAX) {
3045 d->supported_enc_type = talloc(d, uint32_t);
3046 if (d->supported_enc_type == NULL) {
3047 TALLOC_FREE(d);
3048 return NT_STATUS_NO_MEMORY;
3050 *d->supported_enc_type = (uint32_t)val64;
3053 val = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3054 if (val != NULL) {
3055 d->trust_forest_trust_info = data_blob_dup_talloc(d, *val);
3056 if (d->trust_forest_trust_info.data == NULL) {
3057 TALLOC_FREE(d);
3058 return NT_STATUS_NO_MEMORY;
3062 *_d = d;
3063 return NT_STATUS_OK;
3066 static NTSTATUS pdb_samba_dsdb_get_trusted_domain(struct pdb_methods *m,
3067 TALLOC_CTX *mem_ctx,
3068 const char *domain,
3069 struct pdb_trusted_domain **td)
3071 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3072 m->private_data, struct pdb_samba_dsdb_state);
3073 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3074 const char * const attrs[] = {
3075 "securityIdentifier",
3076 "flatName",
3077 "trustPartner",
3078 "trustAuthOutgoing",
3079 "trustAuthIncoming",
3080 "trustAttributes",
3081 "trustDirection",
3082 "trustType",
3083 "trustPosixOffset",
3084 "msDS-SupportedEncryptionTypes",
3085 "msDS-TrustForestTrustInfo",
3086 NULL
3088 struct ldb_message *msg = NULL;
3089 struct pdb_trusted_domain *d = NULL;
3090 NTSTATUS status;
3092 status = dsdb_trust_search_tdo(state->ldb, domain, NULL,
3093 attrs, tmp_ctx, &msg);
3094 if (!NT_STATUS_IS_OK(status)) {
3095 DBG_ERR("dsdb_trust_search_tdo(%s) - %s ",
3096 domain, nt_errstr(status));
3097 TALLOC_FREE(tmp_ctx);
3098 return status;
3101 status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3102 if (!NT_STATUS_IS_OK(status)) {
3103 DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s ",
3104 domain, nt_errstr(status));
3105 TALLOC_FREE(tmp_ctx);
3106 return status;
3109 *td = d;
3110 TALLOC_FREE(tmp_ctx);
3111 return NT_STATUS_OK;
3114 static NTSTATUS pdb_samba_dsdb_get_trusted_domain_by_sid(struct pdb_methods *m,
3115 TALLOC_CTX *mem_ctx,
3116 struct dom_sid *sid,
3117 struct pdb_trusted_domain **td)
3119 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3120 m->private_data, struct pdb_samba_dsdb_state);
3121 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3122 const char * const attrs[] = {
3123 "securityIdentifier",
3124 "flatName",
3125 "trustPartner",
3126 "trustAuthOutgoing",
3127 "trustAuthIncoming",
3128 "trustAttributes",
3129 "trustDirection",
3130 "trustType",
3131 "trustPosixOffset",
3132 "msDS-SupportedEncryptionTypes",
3133 "msDS-TrustForestTrustInfo",
3134 NULL
3136 struct ldb_message *msg = NULL;
3137 struct pdb_trusted_domain *d = NULL;
3138 NTSTATUS status;
3140 status = dsdb_trust_search_tdo_by_sid(state->ldb, sid,
3141 attrs, tmp_ctx, &msg);
3142 if (!NT_STATUS_IS_OK(status)) {
3143 DBG_ERR("dsdb_trust_search_tdo_by_sid(%s) - %s ",
3144 dom_sid_string(tmp_ctx, sid), nt_errstr(status));
3145 TALLOC_FREE(tmp_ctx);
3146 return status;
3149 status = pdb_samba_dsdb_msg_to_trusted_domain(msg, mem_ctx, &d);
3150 if (!NT_STATUS_IS_OK(status)) {
3151 DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain(%s) - %s ",
3152 dom_sid_string(tmp_ctx, sid), nt_errstr(status));
3153 TALLOC_FREE(tmp_ctx);
3154 return status;
3157 *td = d;
3158 TALLOC_FREE(tmp_ctx);
3159 return NT_STATUS_OK;
3162 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
3163 struct ldb_context *sam_ldb,
3164 struct ldb_dn *base_dn,
3165 const char *netbios_name,
3166 struct trustAuthInOutBlob *taiob)
3168 struct ldb_request *req = NULL;
3169 struct ldb_message *msg = NULL;
3170 struct ldb_dn *dn = NULL;
3171 uint32_t i;
3172 int ret;
3173 bool ok;
3175 dn = ldb_dn_copy(mem_ctx, base_dn);
3176 if (dn == NULL) {
3177 return NT_STATUS_NO_MEMORY;
3179 ok = ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name);
3180 if (!ok) {
3181 return NT_STATUS_NO_MEMORY;
3184 msg = ldb_msg_new(mem_ctx);
3185 if (msg == NULL) {
3186 return NT_STATUS_NO_MEMORY;
3188 msg->dn = dn;
3190 ret = ldb_msg_add_string(msg, "objectClass", "user");
3191 if (ret != LDB_SUCCESS) {
3192 return NT_STATUS_NO_MEMORY;
3195 ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
3196 if (ret != LDB_SUCCESS) {
3197 return NT_STATUS_NO_MEMORY;
3200 ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
3201 UF_INTERDOMAIN_TRUST_ACCOUNT);
3202 if (ret != LDB_SUCCESS) {
3203 return NT_STATUS_NO_MEMORY;
3206 for (i = 0; i < taiob->count; i++) {
3207 struct AuthenticationInformation *auth_info =
3208 &taiob->current.array[i];
3209 const char *attribute = NULL;
3210 struct ldb_val v;
3212 switch (taiob->current.array[i].AuthType) {
3213 case TRUST_AUTH_TYPE_NT4OWF:
3214 attribute = "unicodePwd";
3215 v.data = (uint8_t *)&auth_info->AuthInfo.nt4owf.password;
3216 v.length = 16;
3217 break;
3219 case TRUST_AUTH_TYPE_CLEAR:
3220 attribute = "clearTextPassword";
3221 v.data = auth_info->AuthInfo.clear.password;
3222 v.length = auth_info->AuthInfo.clear.size;
3223 break;
3225 default:
3226 continue;
3229 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
3230 if (ret != LDB_SUCCESS) {
3231 return NT_STATUS_NO_MEMORY;
3235 /* create the trusted_domain user account */
3236 ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
3237 ldb_op_default_callback, NULL);
3238 if (ret != LDB_SUCCESS) {
3239 return NT_STATUS_NO_MEMORY;
3242 ret = ldb_request_add_control(
3243 req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
3244 false, NULL);
3245 if (ret != LDB_SUCCESS) {
3246 return NT_STATUS_NO_MEMORY;
3249 ret = dsdb_autotransaction_request(sam_ldb, req);
3250 if (ret != LDB_SUCCESS) {
3251 DEBUG(0,("Failed to create user record %s: %s\n",
3252 ldb_dn_get_linearized(msg->dn),
3253 ldb_errstring(sam_ldb)));
3255 switch (ret) {
3256 case LDB_ERR_ENTRY_ALREADY_EXISTS:
3257 return NT_STATUS_DOMAIN_EXISTS;
3258 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3259 return NT_STATUS_ACCESS_DENIED;
3260 default:
3261 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3265 return NT_STATUS_OK;
3268 static NTSTATUS pdb_samba_dsdb_set_trusted_domain(struct pdb_methods *methods,
3269 const char* domain,
3270 const struct pdb_trusted_domain *td)
3272 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3273 methods->private_data, struct pdb_samba_dsdb_state);
3274 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3275 bool in_txn = false;
3276 struct ldb_dn *base_dn = NULL;
3277 struct ldb_message *msg = NULL;
3278 const char *attrs[] = {
3279 NULL
3281 char *netbios_encoded = NULL;
3282 char *dns_encoded = NULL;
3283 struct dom_sid *tmp_sid1;
3284 struct dom_sid *tmp_sid2;
3285 uint32_t tmp_rid;
3286 char *sid_encoded = NULL;
3287 int ret;
3288 struct trustAuthInOutBlob taiob;
3289 enum ndr_err_code ndr_err;
3290 NTSTATUS status;
3291 bool ok;
3293 base_dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(state->ldb));
3294 if (base_dn == NULL) {
3295 TALLOC_FREE(tmp_ctx);
3296 status = NT_STATUS_NO_MEMORY;
3297 goto out;
3300 * We expect S-1-5-21-A-B-C, but we don't
3301 * allow S-1-5-21-0-0-0 as this is used
3302 * for claims and compound identities.
3304 * So we call dom_sid_split_rid() 3 times
3305 * and compare the result to S-1-5-21
3307 status = dom_sid_split_rid(tmp_ctx,
3308 &td->security_identifier,
3309 &tmp_sid1, &tmp_rid);
3310 if (!NT_STATUS_IS_OK(status)) {
3311 goto out;
3313 status = dom_sid_split_rid(tmp_ctx, tmp_sid1, &tmp_sid2, &tmp_rid);
3314 if (!NT_STATUS_IS_OK(status)) {
3315 goto out;
3317 status = dom_sid_split_rid(tmp_ctx, tmp_sid2, &tmp_sid1, &tmp_rid);
3318 if (!NT_STATUS_IS_OK(status)) {
3319 goto out;
3321 ok = dom_sid_parse("S-1-5-21", tmp_sid2);
3322 if (!ok) {
3323 status = NT_STATUS_INTERNAL_ERROR;
3324 goto out;
3326 ok = dom_sid_equal(tmp_sid1, tmp_sid2);
3327 if (!ok) {
3328 status = NT_STATUS_INVALID_PARAMETER;
3329 goto out;
3331 ok = dom_sid_parse("S-1-5-21-0-0-0", tmp_sid2);
3332 if (!ok) {
3333 return NT_STATUS_INTERNAL_ERROR;
3335 ok = !dom_sid_equal(&td->security_identifier, tmp_sid2);
3336 if (!ok) {
3337 status = NT_STATUS_INVALID_PARAMETER;
3338 goto out;
3341 if (strequal(td->netbios_name, "BUILTIN")) {
3342 status = NT_STATUS_INVALID_PARAMETER;
3343 goto out;
3345 if (strequal(td->domain_name, "BUILTIN")) {
3346 status = NT_STATUS_INVALID_PARAMETER;
3347 goto out;
3350 dns_encoded = ldb_binary_encode_string(tmp_ctx, td->domain_name);
3351 if (dns_encoded == NULL) {
3352 status = NT_STATUS_NO_MEMORY;
3353 goto out;
3355 netbios_encoded = ldb_binary_encode_string(tmp_ctx, td->netbios_name);
3356 if (netbios_encoded == NULL) {
3357 status =NT_STATUS_NO_MEMORY;
3358 goto out;
3360 sid_encoded = ldap_encode_ndr_dom_sid(tmp_ctx, &td->security_identifier);
3361 if (sid_encoded == NULL) {
3362 status = NT_STATUS_NO_MEMORY;
3363 goto out;
3366 ok = samdb_is_pdc(state->ldb);
3367 if (!ok) {
3368 DBG_ERR("Adding TDO is only allowed on a PDC.\n");
3369 TALLOC_FREE(tmp_ctx);
3370 status = NT_STATUS_INVALID_DOMAIN_ROLE;
3371 goto out;
3374 status = dsdb_trust_search_tdo(state->ldb,
3375 td->netbios_name,
3376 td->domain_name,
3377 attrs,
3378 tmp_ctx,
3379 &msg);
3380 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3381 DBG_ERR("dsdb_trust_search_tdo returned %s\n",
3382 nt_errstr(status));
3383 status = NT_STATUS_INVALID_DOMAIN_STATE;
3384 goto out;
3387 ret = ldb_transaction_start(state->ldb);
3388 if (ret != LDB_SUCCESS) {
3389 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3390 goto out;
3392 in_txn = true;
3394 msg = ldb_msg_new(tmp_ctx);
3395 if (msg == NULL) {
3396 status = NT_STATUS_NO_MEMORY;
3397 goto out;
3400 msg->dn = ldb_dn_copy(tmp_ctx, base_dn);
3402 ok = ldb_dn_add_child_fmt(msg->dn, "cn=%s,cn=System", td->domain_name);
3403 if (!ok) {
3404 status = NT_STATUS_NO_MEMORY;
3405 goto out;
3408 ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
3409 if (ret != LDB_SUCCESS) {
3410 status = NT_STATUS_NO_MEMORY;
3411 goto out;
3414 ret = ldb_msg_add_string(msg, "flatname", td->netbios_name);
3415 if (ret != LDB_SUCCESS) {
3416 status = NT_STATUS_NO_MEMORY;
3417 goto out;
3420 ret = ldb_msg_add_string(msg, "trustPartner", td->domain_name);
3421 if (ret != LDB_SUCCESS) {
3422 status = NT_STATUS_NO_MEMORY;
3423 goto out;
3426 ret = samdb_msg_add_dom_sid(state->ldb,
3427 tmp_ctx,
3428 msg,
3429 "securityIdentifier",
3430 &td->security_identifier);
3431 if (ret != LDB_SUCCESS) {
3432 status = NT_STATUS_NO_MEMORY;
3433 goto out;
3436 ret = samdb_msg_add_int(state->ldb,
3437 tmp_ctx,
3438 msg,
3439 "trustType",
3440 td->trust_type);
3441 if (ret != LDB_SUCCESS) {
3442 status = NT_STATUS_NO_MEMORY;
3443 goto out;
3446 ret = samdb_msg_add_int(state->ldb,
3447 tmp_ctx,
3448 msg,
3449 "trustAttributes",
3450 td->trust_attributes);
3451 if (ret != LDB_SUCCESS) {
3452 status =NT_STATUS_NO_MEMORY;
3453 goto out;
3456 ret = samdb_msg_add_int(state->ldb,
3457 tmp_ctx,
3458 msg,
3459 "trustDirection",
3460 td->trust_direction);
3461 if (ret != LDB_SUCCESS) {
3462 status = NT_STATUS_NO_MEMORY;
3463 goto out;
3466 if (td->trust_auth_incoming.data != NULL) {
3467 ret = ldb_msg_add_value(msg,
3468 "trustAuthIncoming",
3469 &td->trust_auth_incoming,
3470 NULL);
3471 if (ret != LDB_SUCCESS) {
3472 status = NT_STATUS_NO_MEMORY;
3473 goto out;
3476 if (td->trust_auth_outgoing.data != NULL) {
3477 ret = ldb_msg_add_value(msg,
3478 "trustAuthOutgoing",
3479 &td->trust_auth_outgoing,
3480 NULL);
3481 if (ret != LDB_SUCCESS) {
3482 status = NT_STATUS_NO_MEMORY;
3483 goto out;
3487 /* create the trusted_domain */
3488 ret = ldb_add(state->ldb, msg);
3489 switch (ret) {
3490 case LDB_SUCCESS:
3491 break;
3493 case LDB_ERR_ENTRY_ALREADY_EXISTS:
3494 DBG_ERR("Failed to create trusted domain record %s: %s\n",
3495 ldb_dn_get_linearized(msg->dn),
3496 ldb_errstring(state->ldb));
3497 status = NT_STATUS_DOMAIN_EXISTS;
3498 goto out;
3500 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3501 DBG_ERR("Failed to create trusted domain record %s: %s\n",
3502 ldb_dn_get_linearized(msg->dn),
3503 ldb_errstring(state->ldb));
3504 status = NT_STATUS_ACCESS_DENIED;
3505 goto out;
3507 default:
3508 DBG_ERR("Failed to create trusted domain record %s: %s\n",
3509 ldb_dn_get_linearized(msg->dn),
3510 ldb_errstring(state->ldb));
3511 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3512 goto out;
3515 ndr_err = ndr_pull_struct_blob(
3516 &td->trust_auth_outgoing,
3517 tmp_ctx,
3518 &taiob,
3519 (ndr_pull_flags_fn_t)ndr_pull_trustAuthInOutBlob);
3520 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3521 status = ndr_map_error2ntstatus(ndr_err);
3522 goto out;
3525 if (td->trust_direction == LSA_TRUST_DIRECTION_INBOUND) {
3526 status = add_trust_user(tmp_ctx,
3527 state->ldb,
3528 base_dn,
3529 td->netbios_name,
3530 &taiob);
3531 if (!NT_STATUS_IS_OK(status)) {
3532 goto out;
3536 ret = ldb_transaction_commit(state->ldb);
3537 if (ret != LDB_SUCCESS) {
3538 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3540 in_txn = false;
3543 * TODO: Notify winbindd that we have a new trust
3546 status = NT_STATUS_OK;
3548 out:
3549 if (in_txn) {
3550 ldb_transaction_cancel(state->ldb);
3552 TALLOC_FREE(tmp_ctx);
3553 return status;
3556 static NTSTATUS delete_trust_user(TALLOC_CTX *mem_ctx,
3557 struct pdb_samba_dsdb_state *state,
3558 const char *trust_user)
3560 const char *attrs[] = { "userAccountControl", NULL };
3561 struct ldb_message **msgs;
3562 uint32_t uac;
3563 int ret;
3565 ret = gendb_search(state->ldb,
3566 mem_ctx,
3567 ldb_get_default_basedn(state->ldb),
3568 &msgs,
3569 attrs,
3570 "samAccountName=%s$",
3571 trust_user);
3572 if (ret > 1) {
3573 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3576 if (ret == 0) {
3577 return NT_STATUS_OK;
3580 uac = ldb_msg_find_attr_as_uint(msgs[0],
3581 "userAccountControl",
3583 if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
3584 return NT_STATUS_OBJECT_NAME_COLLISION;
3587 ret = ldb_delete(state->ldb, msgs[0]->dn);
3588 switch (ret) {
3589 case LDB_SUCCESS:
3590 break;
3591 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
3592 return NT_STATUS_ACCESS_DENIED;
3593 default:
3594 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3597 return NT_STATUS_OK;
3600 static NTSTATUS pdb_samba_dsdb_del_trusted_domain(struct pdb_methods *methods,
3601 const char *domain)
3603 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3604 methods->private_data, struct pdb_samba_dsdb_state);
3605 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3606 struct pdb_trusted_domain *td = NULL;
3607 struct ldb_dn *tdo_dn = NULL;
3608 bool in_txn = false;
3609 NTSTATUS status;
3610 int ret;
3611 bool ok;
3613 status = pdb_samba_dsdb_get_trusted_domain(methods,
3614 tmp_ctx,
3615 domain,
3616 &td);
3617 if (!NT_STATUS_IS_OK(status)) {
3618 if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
3619 DBG_ERR("Searching TDO for %s returned %s\n",
3620 domain, nt_errstr(status));
3621 return status;
3623 DBG_NOTICE("No TDO object for %s\n", domain);
3624 return NT_STATUS_OK;
3627 tdo_dn = ldb_dn_copy(tmp_ctx, ldb_get_default_basedn(state->ldb));
3628 if (tdo_dn == NULL) {
3629 status = NT_STATUS_NO_MEMORY;
3630 goto out;
3633 ok = ldb_dn_add_child_fmt(tdo_dn, "cn=%s,cn=System", domain);
3634 if (!ok) {
3635 TALLOC_FREE(tmp_ctx);
3636 status = NT_STATUS_NO_MEMORY;
3637 goto out;
3640 ret = ldb_transaction_start(state->ldb);
3641 if (ret != LDB_SUCCESS) {
3642 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3643 goto out;
3645 in_txn = true;
3647 ret = ldb_delete(state->ldb, tdo_dn);
3648 if (ret != LDB_SUCCESS) {
3649 status = NT_STATUS_INVALID_HANDLE;
3650 goto out;
3653 if (td->trust_direction == LSA_TRUST_DIRECTION_INBOUND) {
3654 status = delete_trust_user(tmp_ctx, state, domain);
3655 if (!NT_STATUS_IS_OK(status)) {
3656 goto out;
3660 ret = ldb_transaction_commit(state->ldb);
3661 if (ret != LDB_SUCCESS) {
3662 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
3663 goto out;
3665 in_txn = false;
3667 status = NT_STATUS_OK;
3669 out:
3670 if (in_txn) {
3671 ldb_transaction_cancel(state->ldb);
3673 TALLOC_FREE(tmp_ctx);
3675 return status;
3678 static NTSTATUS pdb_samba_dsdb_enum_trusted_domains(struct pdb_methods *m,
3679 TALLOC_CTX *mem_ctx,
3680 uint32_t *_num_domains,
3681 struct pdb_trusted_domain ***_domains)
3683 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3684 m->private_data, struct pdb_samba_dsdb_state);
3685 TALLOC_CTX *tmp_ctx = talloc_stackframe();
3686 const char * const attrs[] = {
3687 "securityIdentifier",
3688 "flatName",
3689 "trustPartner",
3690 "trustAuthOutgoing",
3691 "trustAuthIncoming",
3692 "trustAttributes",
3693 "trustDirection",
3694 "trustType",
3695 "trustPosixOffset",
3696 "msDS-SupportedEncryptionTypes",
3697 "msDS-TrustForestTrustInfo",
3698 NULL
3700 struct ldb_result *res = NULL;
3701 unsigned int i;
3702 struct pdb_trusted_domain **domains = NULL;
3703 NTSTATUS status;
3704 uint32_t di = 0;
3706 *_num_domains = 0;
3707 *_domains = NULL;
3709 status = dsdb_trust_search_tdos(state->ldb, NULL,
3710 attrs, tmp_ctx, &res);
3711 if (!NT_STATUS_IS_OK(status)) {
3712 DBG_ERR("dsdb_trust_search_tdos() - %s ", nt_errstr(status));
3713 TALLOC_FREE(tmp_ctx);
3714 return status;
3717 if (res->count == 0) {
3718 TALLOC_FREE(tmp_ctx);
3719 return NT_STATUS_OK;
3722 domains = talloc_zero_array(tmp_ctx, struct pdb_trusted_domain *,
3723 res->count);
3724 if (domains == NULL) {
3725 TALLOC_FREE(tmp_ctx);
3726 return NT_STATUS_NO_MEMORY;
3729 for (i = 0; i < res->count; i++) {
3730 struct ldb_message *msg = res->msgs[i];
3731 struct pdb_trusted_domain *d = NULL;
3733 status = pdb_samba_dsdb_msg_to_trusted_domain(msg, domains, &d);
3734 if (!NT_STATUS_IS_OK(status)) {
3735 DBG_ERR("pdb_samba_dsdb_msg_to_trusted_domain() - %s ",
3736 nt_errstr(status));
3737 TALLOC_FREE(tmp_ctx);
3738 return status;
3741 domains[di++] = d;
3744 domains = talloc_realloc(domains, domains, struct pdb_trusted_domain *,
3745 di);
3746 *_domains = talloc_move(mem_ctx, &domains);
3747 *_num_domains = di;
3748 TALLOC_FREE(tmp_ctx);
3749 return NT_STATUS_OK;
3752 static bool pdb_samba_dsdb_is_responsible_for_wellknown(struct pdb_methods *m)
3754 return true;
3757 static bool pdb_samba_dsdb_is_responsible_for_everything_else(struct pdb_methods *m)
3759 return true;
3762 static void pdb_samba_dsdb_init_methods(struct pdb_methods *m)
3764 m->name = "samba_dsdb";
3765 m->get_domain_info = pdb_samba_dsdb_get_domain_info;
3766 m->getsampwnam = pdb_samba_dsdb_getsampwnam;
3767 m->getsampwsid = pdb_samba_dsdb_getsampwsid;
3768 m->create_user = pdb_samba_dsdb_create_user;
3769 m->delete_user = pdb_samba_dsdb_delete_user;
3770 m->add_sam_account = pdb_samba_dsdb_add_sam_account;
3771 m->update_sam_account = pdb_samba_dsdb_update_sam_account;
3772 m->delete_sam_account = pdb_samba_dsdb_delete_sam_account;
3773 m->rename_sam_account = pdb_samba_dsdb_rename_sam_account;
3774 m->update_login_attempts = pdb_samba_dsdb_update_login_attempts;
3775 m->getgrsid = pdb_samba_dsdb_getgrsid;
3776 m->getgrgid = pdb_samba_dsdb_getgrgid;
3777 m->getgrnam = pdb_samba_dsdb_getgrnam;
3778 m->create_dom_group = pdb_samba_dsdb_create_dom_group;
3779 m->delete_dom_group = pdb_samba_dsdb_delete_dom_group;
3780 m->add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry;
3781 m->update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry;
3782 m->delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry;
3783 m->enum_group_mapping = pdb_samba_dsdb_enum_group_mapping;
3784 m->enum_group_members = pdb_samba_dsdb_enum_group_members;
3785 m->enum_group_memberships = pdb_samba_dsdb_enum_group_memberships;
3786 m->set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group;
3787 m->add_groupmem = pdb_samba_dsdb_add_groupmem;
3788 m->del_groupmem = pdb_samba_dsdb_del_groupmem;
3789 m->create_alias = pdb_samba_dsdb_create_alias;
3790 m->delete_alias = pdb_samba_dsdb_delete_alias;
3791 m->get_aliasinfo = pdb_default_get_aliasinfo;
3792 m->add_aliasmem = pdb_samba_dsdb_add_aliasmem;
3793 m->del_aliasmem = pdb_samba_dsdb_del_aliasmem;
3794 m->enum_aliasmem = pdb_samba_dsdb_enum_aliasmem;
3795 m->enum_alias_memberships = pdb_samba_dsdb_enum_alias_memberships;
3796 m->lookup_rids = pdb_samba_dsdb_lookup_rids;
3797 m->lookup_names = pdb_samba_dsdb_lookup_names;
3798 m->get_account_policy = pdb_samba_dsdb_get_account_policy;
3799 m->set_account_policy = pdb_samba_dsdb_set_account_policy;
3800 m->get_seq_num = pdb_samba_dsdb_get_seq_num;
3801 m->search_users = pdb_samba_dsdb_search_users;
3802 m->search_groups = pdb_samba_dsdb_search_groups;
3803 m->search_aliases = pdb_samba_dsdb_search_aliases;
3804 m->id_to_sid = pdb_samba_dsdb_id_to_sid;
3805 m->sid_to_id = pdb_samba_dsdb_sid_to_id;
3806 m->capabilities = pdb_samba_dsdb_capabilities;
3807 m->new_rid = pdb_samba_dsdb_new_rid;
3808 m->get_trusteddom_pw = pdb_samba_dsdb_get_trusteddom_pw;
3809 m->get_trusteddom_creds = pdb_samba_dsdb_get_trusteddom_creds;
3810 m->set_trusteddom_pw = pdb_samba_dsdb_set_trusteddom_pw;
3811 m->del_trusteddom_pw = pdb_samba_dsdb_del_trusteddom_pw;
3812 m->enum_trusteddoms = pdb_samba_dsdb_enum_trusteddoms;
3813 m->get_trusted_domain = pdb_samba_dsdb_get_trusted_domain;
3814 m->get_trusted_domain_by_sid = pdb_samba_dsdb_get_trusted_domain_by_sid;
3815 m->set_trusted_domain = pdb_samba_dsdb_set_trusted_domain;
3816 m->del_trusted_domain = pdb_samba_dsdb_del_trusted_domain;
3817 m->enum_trusted_domains = pdb_samba_dsdb_enum_trusted_domains;
3818 m->is_responsible_for_wellknown =
3819 pdb_samba_dsdb_is_responsible_for_wellknown;
3820 m->is_responsible_for_everything_else =
3821 pdb_samba_dsdb_is_responsible_for_everything_else;
3824 static void free_private_data(void **vp)
3826 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
3827 *vp, struct pdb_samba_dsdb_state);
3828 talloc_unlink(state, state->ldb);
3829 return;
3832 static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m)
3834 struct pdb_domain_info *dom_info;
3835 struct dom_sid stored_sid;
3836 struct GUID stored_guid;
3837 bool sid_exists_and_matches = false;
3838 bool guid_exists_and_matches = false;
3839 bool ret;
3841 dom_info = pdb_samba_dsdb_get_domain_info(m, m);
3842 if (!dom_info) {
3843 return NT_STATUS_UNSUCCESSFUL;
3846 ret = secrets_fetch_domain_sid(dom_info->name, &stored_sid);
3847 if (ret) {
3848 if (dom_sid_equal(&stored_sid, &dom_info->sid)) {
3849 sid_exists_and_matches = true;
3853 if (sid_exists_and_matches == false) {
3854 secrets_clear_domain_protection(dom_info->name);
3855 ret = secrets_store_domain_sid(dom_info->name,
3856 &dom_info->sid);
3857 ret &= secrets_mark_domain_protected(dom_info->name);
3858 if (!ret) {
3859 goto done;
3863 ret = secrets_fetch_domain_guid(dom_info->name, &stored_guid);
3864 if (ret) {
3865 if (GUID_equal(&stored_guid, &dom_info->guid)) {
3866 guid_exists_and_matches = true;
3870 if (guid_exists_and_matches == false) {
3871 secrets_clear_domain_protection(dom_info->name);
3872 ret = secrets_store_domain_guid(dom_info->name,
3873 &dom_info->guid);
3874 ret &= secrets_mark_domain_protected(dom_info->name);
3875 if (!ret) {
3876 goto done;
3880 done:
3881 TALLOC_FREE(dom_info);
3882 if (!ret) {
3883 return NT_STATUS_UNSUCCESSFUL;
3885 return NT_STATUS_OK;
3888 static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
3889 const char *location)
3891 struct pdb_methods *m;
3892 struct pdb_samba_dsdb_state *state;
3893 NTSTATUS status;
3894 char *errstring = NULL;
3895 int ret;
3897 if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
3898 return status;
3901 state = talloc_zero(m, struct pdb_samba_dsdb_state);
3902 if (state == NULL) {
3903 goto nomem;
3905 m->private_data = state;
3906 m->free_private_data = free_private_data;
3907 pdb_samba_dsdb_init_methods(m);
3909 state->ev = s4_event_context_init(state);
3910 if (!state->ev) {
3911 DEBUG(0, ("s4_event_context_init failed\n"));
3912 goto nomem;
3915 state->lp_ctx = loadparm_init_s3(state, loadparm_s3_helpers());
3916 if (state->lp_ctx == NULL) {
3917 DEBUG(0, ("loadparm_init_s3 failed\n"));
3918 goto nomem;
3921 if (location == NULL) {
3922 location = "sam.ldb";
3925 ret = samdb_connect_url(state,
3926 state->ev,
3927 state->lp_ctx,
3928 system_session(state->lp_ctx),
3929 0, location,
3930 &state->ldb, &errstring);
3932 if (!state->ldb) {
3933 DEBUG(0, ("samdb_connect failed: %s: %s\n",
3934 errstring, ldb_strerror(ret)));
3935 status = NT_STATUS_INTERNAL_ERROR;
3936 goto fail;
3939 state->idmap_ctx = idmap_init(state, state->ev,
3940 state->lp_ctx);
3941 if (!state->idmap_ctx) {
3942 DEBUG(0, ("idmap failed\n"));
3943 status = NT_STATUS_INTERNAL_ERROR;
3944 goto fail;
3947 status = pdb_samba_dsdb_init_secrets(m);
3948 if (!NT_STATUS_IS_OK(status)) {
3949 DEBUG(10, ("pdb_samba_dsdb_init_secrets failed!\n"));
3950 goto fail;
3953 *pdb_method = m;
3954 return NT_STATUS_OK;
3955 nomem:
3956 status = NT_STATUS_NO_MEMORY;
3957 fail:
3958 TALLOC_FREE(m);
3959 return status;
3962 NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *);
3963 NTSTATUS pdb_samba_dsdb_init(TALLOC_CTX *ctx)
3965 NTSTATUS status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba_dsdb",
3966 pdb_init_samba_dsdb);
3967 if (!NT_STATUS_IS_OK(status)) {
3968 return status;
3970 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4",
3971 pdb_init_samba_dsdb);