Revert "buildtools: Rename perl vendorarch configure option."
[Samba.git] / source3 / passdb / pdb_samba_dsdb.c
blob49b7cf0a63eb0bd96987c66a35ff39f7ea9df234
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 "libds/common/flag_mapping.h"
32 #include "source4/lib/events/events.h"
33 #include "source4/auth/session.h"
34 #include "source4/auth/system_session_proto.h"
35 #include "lib/param/param.h"
36 #include "source4/dsdb/common/util.h"
37 #include "source3/include/secrets.h"
39 struct pdb_samba_dsdb_state {
40 struct tevent_context *ev;
41 struct ldb_context *ldb;
42 struct idmap_context *idmap_ctx;
43 struct loadparm_context *lp_ctx;
46 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
47 struct samu *sam_acct,
48 const struct dom_sid *sid);
49 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
50 const char *filter,
51 TALLOC_CTX *mem_ctx,
52 struct ldb_message **pmsg);
53 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
54 struct unixid *id);
56 static bool pdb_samba_dsdb_pull_time(struct ldb_message *msg, const char *attr,
57 time_t *ptime)
59 uint64_t tmp;
60 if (! ldb_msg_find_element(msg, attr)) {
61 return false;
63 tmp = ldb_msg_find_attr_as_uint64(msg, attr, 0);
64 *ptime = nt_time_to_unix(tmp);
65 return true;
68 static struct pdb_domain_info *pdb_samba_dsdb_get_domain_info(
69 struct pdb_methods *m, TALLOC_CTX *mem_ctx)
71 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
72 m->private_data, struct pdb_samba_dsdb_state);
73 struct pdb_domain_info *info;
74 struct dom_sid *domain_sid;
75 struct ldb_dn *forest_dn, *domain_dn;
76 struct ldb_result *dom_res = NULL;
77 const char *dom_attrs[] = {
78 "objectSid",
79 "objectGUID",
80 "fSMORoleOwner",
81 NULL
83 char *p;
84 int ret;
86 info = talloc(mem_ctx, struct pdb_domain_info);
87 if (info == NULL) {
88 return NULL;
91 domain_dn = ldb_get_default_basedn(state->ldb);
93 ret = ldb_search(state->ldb, info, &dom_res,
94 domain_dn, LDB_SCOPE_BASE, dom_attrs, NULL);
95 if (ret != LDB_SUCCESS) {
96 goto fail;
98 if (dom_res->count != 1) {
99 goto fail;
102 info->guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
104 domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
105 if (!domain_sid) {
106 goto fail;
108 info->sid = *domain_sid;
110 TALLOC_FREE(dom_res);
112 info->name = talloc_strdup(info, lpcfg_sam_name(state->lp_ctx));
113 info->dns_domain = ldb_dn_canonical_string(info, domain_dn);
115 if (!info->dns_domain) {
116 goto fail;
118 p = strchr(info->dns_domain, '/');
119 if (p) {
120 *p = '\0';
123 forest_dn = ldb_get_root_basedn(state->ldb);
124 if (!forest_dn) {
125 goto fail;
128 info->dns_forest = ldb_dn_canonical_string(info, forest_dn);
129 if (!info->dns_forest) {
130 goto fail;
132 p = strchr(info->dns_forest, '/');
133 if (p) {
134 *p = '\0';
137 return info;
139 fail:
140 TALLOC_FREE(dom_res);
141 TALLOC_FREE(info);
142 return NULL;
145 static struct ldb_message *pdb_samba_dsdb_get_samu_private(
146 struct pdb_methods *m, struct samu *sam)
148 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
149 m->private_data, struct pdb_samba_dsdb_state);
150 struct ldb_message *msg;
151 char *sidstr, *filter;
152 NTSTATUS status;
154 msg = (struct ldb_message *)
155 pdb_get_backend_private_data(sam, m);
157 if (msg != NULL) {
158 return talloc_get_type_abort(msg, struct ldb_message);
161 sidstr = dom_sid_string(talloc_tos(), pdb_get_user_sid(sam));
162 if (sidstr == NULL) {
163 return NULL;
166 filter = talloc_asprintf(
167 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
168 TALLOC_FREE(sidstr);
169 if (filter == NULL) {
170 return NULL;
173 status = pdb_samba_dsdb_getsamupriv(state, filter, sam, &msg);
174 TALLOC_FREE(filter);
175 if (!NT_STATUS_IS_OK(status)) {
176 return NULL;
179 return msg;
182 static NTSTATUS pdb_samba_dsdb_init_sam_from_priv(struct pdb_methods *m,
183 struct samu *sam,
184 struct ldb_message *msg)
186 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
187 m->private_data, struct pdb_samba_dsdb_state);
188 TALLOC_CTX *frame = talloc_stackframe();
189 NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
190 const char *str;
191 time_t tmp_time;
192 struct dom_sid *sid, group_sid;
193 uint64_t n;
194 const DATA_BLOB *blob;
196 str = ldb_msg_find_attr_as_string(msg, "samAccountName", NULL);
197 if (str == NULL) {
198 DEBUG(10, ("no samAccountName\n"));
199 goto fail;
201 pdb_set_username(sam, str, PDB_SET);
203 if (pdb_samba_dsdb_pull_time(msg, "lastLogon", &tmp_time)) {
204 pdb_set_logon_time(sam, tmp_time, PDB_SET);
206 if (pdb_samba_dsdb_pull_time(msg, "lastLogoff", &tmp_time)) {
207 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
209 if (pdb_samba_dsdb_pull_time(msg, "pwdLastSet", &tmp_time)) {
210 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
212 if (pdb_samba_dsdb_pull_time(msg, "accountExpires", &tmp_time)) {
213 pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
216 str = ldb_msg_find_attr_as_string(msg, "displayName",
217 NULL);
218 if (str != NULL) {
219 pdb_set_fullname(sam, str, PDB_SET);
222 str = ldb_msg_find_attr_as_string(msg, "homeDirectory",
223 NULL);
224 if (str != NULL) {
225 pdb_set_homedir(sam, str, PDB_SET);
228 str = ldb_msg_find_attr_as_string(msg, "homeDrive", NULL);
229 if (str != NULL) {
230 pdb_set_dir_drive(sam, str, PDB_SET);
233 str = ldb_msg_find_attr_as_string(msg, "scriptPath", NULL);
234 if (str != NULL) {
235 pdb_set_logon_script(sam, str, PDB_SET);
238 str = ldb_msg_find_attr_as_string(msg, "profilePath",
239 NULL);
240 if (str != NULL) {
241 pdb_set_profile_path(sam, str, PDB_SET);
244 str = ldb_msg_find_attr_as_string(msg, "comment",
245 NULL);
246 if (str != NULL) {
247 pdb_set_comment(sam, str, PDB_SET);
250 str = ldb_msg_find_attr_as_string(msg, "description",
251 NULL);
252 if (str != NULL) {
253 pdb_set_acct_desc(sam, str, PDB_SET);
256 str = ldb_msg_find_attr_as_string(msg, "userWorkstations",
257 NULL);
258 if (str != NULL) {
259 pdb_set_workstations(sam, str, PDB_SET);
262 blob = ldb_msg_find_ldb_val(msg, "userParameters");
263 if (blob != NULL) {
264 str = base64_encode_data_blob(frame, *blob);
265 if (str == NULL) {
266 DEBUG(0, ("base64_encode_data_blob() failed\n"));
267 goto fail;
269 pdb_set_munged_dial(sam, str, PDB_SET);
272 sid = samdb_result_dom_sid(talloc_tos(), msg, "objectSid");
273 if (!sid) {
274 DEBUG(10, ("Could not pull SID\n"));
275 goto fail;
277 pdb_set_user_sid(sam, sid, PDB_SET);
279 n = ldb_msg_find_attr_as_uint(msg, "userAccountControl", 0);
280 if (n == 0) {
281 DEBUG(10, ("Could not pull userAccountControl\n"));
282 goto fail;
284 pdb_set_acct_ctrl(sam, ds_uf2acb(n), PDB_SET);
286 blob = ldb_msg_find_ldb_val(msg, "unicodePwd");
287 if (blob) {
288 if (blob->length != NT_HASH_LEN) {
289 DEBUG(0, ("Got NT hash of length %d, expected %d\n",
290 (int)blob->length, NT_HASH_LEN));
291 goto fail;
293 pdb_set_nt_passwd(sam, blob->data, PDB_SET);
296 blob = ldb_msg_find_ldb_val(msg, "dBCSPwd");
297 if (blob) {
298 if (blob->length != LM_HASH_LEN) {
299 DEBUG(0, ("Got LM hash of length %d, expected %d\n",
300 (int)blob->length, LM_HASH_LEN));
301 goto fail;
303 pdb_set_lanman_passwd(sam, blob->data, PDB_SET);
306 n = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", 0);
307 if (n == 0) {
308 DEBUG(10, ("Could not pull primaryGroupID\n"));
309 goto fail;
311 sid_compose(&group_sid, samdb_domain_sid(state->ldb), n);
312 pdb_set_group_sid(sam, &group_sid, PDB_SET);
314 status = NT_STATUS_OK;
315 fail:
316 TALLOC_FREE(frame);
317 return status;
320 static bool pdb_samba_dsdb_add_time(struct ldb_message *msg,
321 const char *attrib, time_t t)
323 uint64_t nt_time;
325 unix_to_nt_time(&nt_time, t);
327 return ldb_msg_add_fmt(msg, attrib, "%llu", (unsigned long long) nt_time);
330 static int pdb_samba_dsdb_replace_by_sam(struct pdb_samba_dsdb_state *state,
331 bool (*need_update)(const struct samu *,
332 enum pdb_elements),
333 struct ldb_dn *dn,
334 struct samu *sam)
336 TALLOC_CTX *frame = talloc_stackframe();
337 int ret = LDB_SUCCESS;
338 const char *pw;
339 struct ldb_message *msg;
340 struct ldb_request *req;
341 uint32_t dsdb_flags = 0;
342 /* TODO: All fields :-) */
344 msg = ldb_msg_new(frame);
345 if (!msg) {
346 return false;
349 msg->dn = dn;
351 /* build modify request */
352 ret = ldb_build_mod_req(&req, state->ldb, frame, msg, NULL, NULL,
353 ldb_op_default_callback,
354 NULL);
355 if (ret != LDB_SUCCESS) {
356 talloc_free(frame);
357 return ret;
360 /* If we set a plaintext password, the system will
361 * force the pwdLastSet to now() */
362 if (need_update(sam, PDB_PASSLASTSET)) {
363 dsdb_flags = DSDB_PASSWORD_BYPASS_LAST_SET;
365 ret |= pdb_samba_dsdb_add_time(msg, "pwdLastSet",
366 pdb_get_pass_last_set_time(sam));
369 pw = pdb_get_plaintext_passwd(sam);
370 if (need_update(sam, PDB_PLAINTEXT_PW)) {
371 struct ldb_val pw_utf16;
372 if (pw == NULL) {
373 talloc_free(frame);
374 return LDB_ERR_OPERATIONS_ERROR;
377 if (!convert_string_talloc(msg,
378 CH_UNIX, CH_UTF16,
379 pw, strlen(pw),
380 (void *)&pw_utf16.data,
381 &pw_utf16.length)) {
382 return LDB_ERR_OPERATIONS_ERROR;
384 ret |= ldb_msg_add_value(msg, "clearTextPassword", &pw_utf16, NULL);
385 } else {
386 bool changed_lm_pw = false;
387 bool changed_nt_pw = false;
388 bool changed_history = false;
389 if (need_update(sam, PDB_LMPASSWD)) {
390 struct ldb_val val;
391 val.data = discard_const_p(uint8_t, pdb_get_lanman_passwd(sam));
392 if (!val.data) {
393 samdb_msg_add_delete(state->ldb, msg, msg,
394 "dBCSPwd");
395 } else {
396 val.length = LM_HASH_LEN;
397 ret |= ldb_msg_add_value(msg, "dBCSPwd", &val, NULL);
399 changed_lm_pw = true;
401 if (need_update(sam, PDB_NTPASSWD)) {
402 struct ldb_val val;
403 val.data = discard_const_p(uint8_t, pdb_get_nt_passwd(sam));
404 if (!val.data) {
405 samdb_msg_add_delete(state->ldb, msg, msg,
406 "unicodePwd");
407 } else {
408 val.length = NT_HASH_LEN;
409 ret |= ldb_msg_add_value(msg, "unicodePwd", &val, NULL);
411 changed_nt_pw = true;
414 /* Try to ensure we don't get out of sync */
415 if (changed_lm_pw && !changed_nt_pw) {
416 samdb_msg_add_delete(state->ldb, msg, msg,
417 "unicodePwd");
418 } else if (changed_nt_pw && !changed_lm_pw) {
419 samdb_msg_add_delete(state->ldb, msg, msg,
420 "dBCSPwd");
422 if (changed_lm_pw || changed_nt_pw) {
423 samdb_msg_add_delete(state->ldb, msg, msg,
424 "supplementalCredentials");
428 if (need_update(sam, PDB_PWHISTORY)) {
429 uint32_t current_hist_len;
430 const uint8_t *history = pdb_get_pw_history(sam, &current_hist_len);
432 bool invalid_history = false;
433 struct samr_Password *history_hashes = talloc_array(talloc_tos(), struct samr_Password,
434 current_hist_len);
435 if (!history) {
436 invalid_history = true;
437 } else {
438 unsigned int i;
439 static const uint8_t zeros[16];
440 /* Parse the history into the correct format */
441 for (i = 0; i < current_hist_len; i++) {
442 if (memcmp(&history[i*PW_HISTORY_ENTRY_LEN], zeros, 16) != 0) {
443 /* If the history is in the old format, with a salted hash, then we can't migrate it to AD format */
444 invalid_history = true;
445 break;
447 /* Copy out the 2nd 16 bytes of the 32 byte password history, containing the NT hash */
448 memcpy(history_hashes[i].hash,
449 &history[(i*PW_HISTORY_ENTRY_LEN) + PW_HISTORY_SALT_LEN],
450 sizeof(history_hashes[i].hash));
453 if (invalid_history) {
454 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
455 "ntPwdHistory");
457 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
458 "lmPwdHistory");
459 } else {
460 ret |= samdb_msg_add_hashes(state->ldb, msg, msg,
461 "ntPwdHistory",
462 history_hashes,
463 current_hist_len);
465 changed_history = true;
467 if (changed_lm_pw || changed_nt_pw || changed_history) {
468 /* These attributes can only be modified directly by using a special control */
469 dsdb_flags = DSDB_BYPASS_PASSWORD_HASH;
473 /* PDB_USERSID is only allowed on ADD, handled in caller */
474 if (need_update(sam, PDB_GROUPSID)) {
475 const struct dom_sid *sid = pdb_get_group_sid(sam);
476 uint32_t rid;
477 NTSTATUS status = dom_sid_split_rid(NULL, sid, NULL, &rid);
478 if (!NT_STATUS_IS_OK(status)) {
479 talloc_free(frame);
480 return LDB_ERR_OPERATIONS_ERROR;
482 if (!dom_sid_in_domain(samdb_domain_sid(state->ldb), sid)) {
483 talloc_free(frame);
484 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
486 ret |= samdb_msg_add_uint(state->ldb, msg, msg, "primaryGroupID", rid);
488 if (need_update(sam, PDB_FULLNAME)) {
489 ret |= ldb_msg_add_string(msg, "displayName", pdb_get_fullname(sam));
492 if (need_update(sam, PDB_SMBHOME)) {
493 ret |= ldb_msg_add_string(msg, "homeDirectory",
494 pdb_get_homedir(sam));
497 if (need_update(sam, PDB_PROFILE)) {
498 ret |= ldb_msg_add_string(msg, "profilePath",
499 pdb_get_profile_path(sam));
502 if (need_update(sam, PDB_DRIVE)) {
503 ret |= ldb_msg_add_string(msg, "homeDrive",
504 pdb_get_dir_drive(sam));
507 if (need_update(sam, PDB_LOGONSCRIPT)) {
508 ret |= ldb_msg_add_string(msg, "scriptPath",
509 pdb_get_logon_script(sam));
512 if (need_update(sam, PDB_KICKOFFTIME)) {
513 ret |= pdb_samba_dsdb_add_time(msg, "accountExpires",
514 pdb_get_kickoff_time(sam));
517 if (need_update(sam, PDB_LOGONTIME)) {
518 ret |= pdb_samba_dsdb_add_time(msg, "lastLogon",
519 pdb_get_logon_time(sam));
522 if (need_update(sam, PDB_LOGOFFTIME)) {
523 ret |= pdb_samba_dsdb_add_time(msg, "lastLogoff",
524 pdb_get_logoff_time(sam));
527 if (need_update(sam, PDB_USERNAME)) {
528 ret |= ldb_msg_add_string(msg, "samAccountName",
529 pdb_get_username(sam));
532 if (need_update(sam, PDB_HOURSLEN) || need_update(sam, PDB_HOURS)) {
533 struct ldb_val hours = data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam));
534 ret |= ldb_msg_add_value(msg, "logonHours",
535 &hours, NULL);
538 if (need_update(sam, PDB_ACCTCTRL)) {
539 ret |= samdb_msg_add_acct_flags(state->ldb, msg, msg,
540 "userAccountControl", pdb_get_acct_ctrl(sam));
543 if (need_update(sam, PDB_COMMENT)) {
544 ret |= ldb_msg_add_string(msg, "comment",
545 pdb_get_comment(sam));
548 if (need_update(sam, PDB_ACCTDESC)) {
549 ret |= ldb_msg_add_string(msg, "description",
550 pdb_get_acct_desc(sam));
553 if (need_update(sam, PDB_WORKSTATIONS)) {
554 ret |= ldb_msg_add_string(msg, "userWorkstations",
555 pdb_get_workstations(sam));
558 /* This will need work, it is actually a UTF8 'string' with internal NULLs, to handle TS parameters */
559 if (need_update(sam, PDB_MUNGEDDIAL)) {
560 const char *base64_munged_dial = NULL;
562 base64_munged_dial = pdb_get_munged_dial(sam);
563 if (base64_munged_dial != NULL && strlen(base64_munged_dial) > 0) {
564 struct ldb_val blob;
566 blob = base64_decode_data_blob_talloc(msg,
567 base64_munged_dial);
568 if (blob.data == NULL) {
569 DEBUG(0, ("Failed to decode userParameters from "
570 "munged dialback string[%s] for %s\n",
571 base64_munged_dial,
572 ldb_dn_get_linearized(msg->dn)));
573 talloc_free(frame);
574 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
576 ret |= ldb_msg_add_steal_value(msg, "userParameters",
577 &blob);
581 if (need_update(sam, PDB_COUNTRY_CODE)) {
582 ret |= ldb_msg_add_fmt(msg, "countryCode",
583 "%i", (int)pdb_get_country_code(sam));
586 if (need_update(sam, PDB_CODE_PAGE)) {
587 ret |= ldb_msg_add_fmt(msg, "codePage",
588 "%i", (int)pdb_get_code_page(sam));
591 /* Not yet handled here or not meaningful for modifies on a Samba_Dsdb backend:
592 PDB_BAD_PASSWORD_TIME,
593 PDB_CANCHANGETIME, - these are calculated per policy, not stored
594 PDB_DOMAIN,
595 PDB_NTUSERNAME, - this makes no sense, and never really did
596 PDB_LOGONDIVS,
597 PDB_USERSID, - Handled in pdb_samba_dsdb_add_sam_account()
598 PDB_FIELDS_PRESENT,
599 PDB_BAD_PASSWORD_COUNT,
600 PDB_LOGON_COUNT,
601 PDB_UNKNOWN6,
602 PDB_BACKEND_PRIVATE_DATA,
605 if (ret != LDB_SUCCESS) {
606 talloc_free(frame);
607 return LDB_ERR_OPERATIONS_ERROR;
610 if (msg->num_elements == 0) {
611 talloc_free(frame);
612 /* Nothing to do, just return success */
613 return LDB_SUCCESS;
616 ret = dsdb_replace(state->ldb, msg, dsdb_flags);
618 if (ret != LDB_SUCCESS) {
619 DEBUG(0,("Failed to modify account record %s to set user attributes: %s\n",
620 ldb_dn_get_linearized(msg->dn),
621 ldb_errstring(state->ldb)));
624 talloc_free(frame);
625 return ret;
628 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
629 const char *filter,
630 TALLOC_CTX *mem_ctx,
631 struct ldb_message **msg)
633 const char * attrs[] = {
634 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
635 "sAMAccountName", "displayName", "homeDirectory",
636 "homeDrive", "scriptPath", "profilePath", "description",
637 "userWorkstations", "comment", "userParameters", "objectSid",
638 "primaryGroupID", "userAccountControl", "logonHours",
639 "badPwdCount", "logonCount", "countryCode", "codePage",
640 "unicodePwd", "dBCSPwd", NULL };
642 int rc = dsdb_search_one(state->ldb, mem_ctx, msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter);
643 if (rc != LDB_SUCCESS) {
644 DEBUG(10, ("ldap_search failed %s\n",
645 ldb_errstring(state->ldb)));
646 return NT_STATUS_LDAP(rc);
649 return NT_STATUS_OK;
652 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
653 struct pdb_samba_dsdb_state *state,
654 struct samu *sam_acct,
655 const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
657 struct ldb_message *priv;
658 NTSTATUS status;
659 va_list ap;
660 char *expression = NULL;
661 TALLOC_CTX *tmp_ctx = talloc_new(state);
662 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
664 va_start(ap, exp_fmt);
665 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
666 va_end(ap);
668 if (!expression) {
669 talloc_free(tmp_ctx);
670 return NT_STATUS_NO_MEMORY;
673 status = pdb_samba_dsdb_getsamupriv(state, expression, sam_acct, &priv);
674 talloc_free(tmp_ctx);
675 if (!NT_STATUS_IS_OK(status)) {
676 DEBUG(10, ("pdb_samba_dsdb_getsamupriv failed: %s\n",
677 nt_errstr(status)));
678 return status;
681 status = pdb_samba_dsdb_init_sam_from_priv(m, sam_acct, priv);
682 if (!NT_STATUS_IS_OK(status)) {
683 DEBUG(10, ("pdb_samba_dsdb_init_sam_from_priv failed: %s\n",
684 nt_errstr(status)));
685 TALLOC_FREE(priv);
686 return status;
689 pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
690 return NT_STATUS_OK;
693 static NTSTATUS pdb_samba_dsdb_getsampwnam(struct pdb_methods *m,
694 struct samu *sam_acct,
695 const char *username)
697 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
698 m->private_data, struct pdb_samba_dsdb_state);
700 return pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
701 "(&(samaccountname=%s)(objectclass=user))",
702 username);
705 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
706 struct samu *sam_acct,
707 const struct dom_sid *sid)
709 NTSTATUS status;
710 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
711 m->private_data, struct pdb_samba_dsdb_state);
712 char *sidstr;
714 sidstr = dom_sid_string(talloc_tos(), sid);
715 NT_STATUS_HAVE_NO_MEMORY(sidstr);
717 status = pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
718 "(&(objectsid=%s)(objectclass=user))",
719 sidstr);
720 talloc_free(sidstr);
721 return status;
724 static NTSTATUS pdb_samba_dsdb_create_user(struct pdb_methods *m,
725 TALLOC_CTX *mem_ctx,
726 const char *name, uint32 acct_flags,
727 uint32 *rid)
729 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
730 m->private_data, struct pdb_samba_dsdb_state);
731 struct dom_sid *sid;
732 struct ldb_dn *dn;
733 NTSTATUS status;
734 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
735 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
737 /* Internally this uses transactions to ensure all the steps
738 * happen or fail as one */
739 status = dsdb_add_user(state->ldb, tmp_ctx, name, acct_flags, NULL,
740 &sid, &dn);
741 if (!NT_STATUS_IS_OK(status)) {
742 talloc_free(tmp_ctx);
743 return status;
745 sid_peek_rid(sid, rid);
746 talloc_free(tmp_ctx);
747 return NT_STATUS_OK;
750 static NTSTATUS pdb_samba_dsdb_delete_user(struct pdb_methods *m,
751 TALLOC_CTX *mem_ctx,
752 struct samu *sam)
754 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
755 m->private_data, struct pdb_samba_dsdb_state);
756 struct ldb_dn *dn;
757 int rc;
758 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
759 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
761 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, pdb_get_user_sid(sam)));
762 if (!dn || !ldb_dn_validate(dn)) {
763 talloc_free(tmp_ctx);
764 return NT_STATUS_NO_MEMORY;
766 rc = ldb_delete(state->ldb, dn);
768 if (rc != LDB_SUCCESS) {
769 DEBUG(10, ("ldb_delete for %s failed: %s\n", ldb_dn_get_linearized(dn),
770 ldb_errstring(state->ldb)));
771 talloc_free(tmp_ctx);
772 return NT_STATUS_LDAP(rc);
774 talloc_free(tmp_ctx);
775 return NT_STATUS_OK;
778 /* This interface takes a fully populated struct samu and places it in
779 * the database. This is not implemented at this time as we need to
780 * be careful around the creation of arbitary SIDs (ie, we must ensrue
781 * they are not left in a RID pool */
782 static NTSTATUS pdb_samba_dsdb_add_sam_account(struct pdb_methods *m,
783 struct samu *sampass)
785 int ret;
786 NTSTATUS status;
787 struct ldb_dn *dn;
788 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
789 m->private_data, struct pdb_samba_dsdb_state);
790 uint32_t acb_flags = pdb_get_acct_ctrl(sampass);
791 const char *username = pdb_get_username(sampass);
792 const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
793 TALLOC_CTX *tframe = talloc_stackframe();
795 acb_flags &= (ACB_NORMAL|ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST);
797 ret = ldb_transaction_start(state->ldb);
798 if (ret != LDB_SUCCESS) {
799 talloc_free(tframe);
800 return NT_STATUS_LOCK_NOT_GRANTED;
803 status = dsdb_add_user(state->ldb, talloc_tos(), username,
804 acb_flags, user_sid, NULL, &dn);
805 if (!NT_STATUS_IS_OK(status)) {
806 ldb_transaction_cancel(state->ldb);
807 talloc_free(tframe);
808 return status;
811 ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_set_or_changed,
812 dn, sampass);
813 if (ret != LDB_SUCCESS) {
814 ldb_transaction_cancel(state->ldb);
815 talloc_free(tframe);
816 return dsdb_ldb_err_to_ntstatus(ret);
819 ret = ldb_transaction_commit(state->ldb);
820 if (ret != LDB_SUCCESS) {
821 DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
822 ldb_dn_get_linearized(dn),
823 ldb_errstring(state->ldb)));
824 talloc_free(tframe);
825 return NT_STATUS_INTERNAL_DB_CORRUPTION;
827 talloc_free(tframe);
828 return NT_STATUS_OK;
832 * Update the Samba_Dsdb LDB with the changes from a struct samu.
834 * This takes care not to update elements that have not been changed
835 * by the caller
837 static NTSTATUS pdb_samba_dsdb_update_sam_account(struct pdb_methods *m,
838 struct samu *sam)
840 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
841 m->private_data, struct pdb_samba_dsdb_state);
842 struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
843 m, sam);
844 int ret;
846 ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_changed, msg->dn,
847 sam);
848 return dsdb_ldb_err_to_ntstatus(ret);
851 static NTSTATUS pdb_samba_dsdb_delete_sam_account(struct pdb_methods *m,
852 struct samu *username)
854 NTSTATUS status;
855 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
856 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
857 status = pdb_samba_dsdb_delete_user(m, tmp_ctx, username);
858 talloc_free(tmp_ctx);
859 return status;
862 static NTSTATUS pdb_samba_dsdb_rename_sam_account(struct pdb_methods *m,
863 struct samu *oldname,
864 const char *newname)
866 return NT_STATUS_NOT_IMPLEMENTED;
869 /* This is not implemented, as this module is exptected to be used
870 * with auth_samba_dsdb, and this is responible for login counters etc
873 static NTSTATUS pdb_samba_dsdb_update_login_attempts(struct pdb_methods *m,
874 struct samu *sam_acct,
875 bool success)
877 return NT_STATUS_NOT_IMPLEMENTED;
880 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
881 const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
883 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
884 m->private_data, struct pdb_samba_dsdb_state);
885 const char *attrs[] = { "objectClass", "objectSid", "description", "samAccountName", "groupType",
886 NULL };
887 struct ldb_message *msg;
888 va_list ap;
889 char *expression = NULL;
890 struct dom_sid *sid;
891 const char *str;
892 int rc;
893 struct id_map id_map;
894 struct id_map *id_maps[2];
895 TALLOC_CTX *tmp_ctx = talloc_stackframe();
896 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
898 va_start(ap, exp_fmt);
899 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
900 va_end(ap);
902 if (!expression) {
903 talloc_free(tmp_ctx);
904 return NT_STATUS_NO_MEMORY;
907 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
908 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
909 talloc_free(tmp_ctx);
910 return NT_STATUS_NO_SUCH_GROUP;
911 } else if (rc != LDB_SUCCESS) {
912 talloc_free(tmp_ctx);
913 DEBUG(10, ("dsdb_search_one failed %s\n",
914 ldb_errstring(state->ldb)));
915 return NT_STATUS_LDAP(rc);
918 sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
919 if (!sid) {
920 talloc_free(tmp_ctx);
921 DEBUG(10, ("Could not pull SID\n"));
922 return NT_STATUS_INTERNAL_DB_CORRUPTION;
925 map->sid = *sid;
927 if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) {
928 NTSTATUS status;
929 uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0);
930 switch (grouptype) {
931 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
932 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
933 map->sid_name_use = SID_NAME_ALIAS;
934 break;
935 case GTYPE_SECURITY_GLOBAL_GROUP:
936 map->sid_name_use = SID_NAME_DOM_GRP;
937 break;
938 default:
939 talloc_free(tmp_ctx);
940 DEBUG(10, ("Could not pull groupType\n"));
941 return NT_STATUS_INTERNAL_DB_CORRUPTION;
944 ZERO_STRUCT(id_map);
945 id_map.sid = sid;
946 id_maps[0] = &id_map;
947 id_maps[1] = NULL;
949 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
951 if (!NT_STATUS_IS_OK(status)) {
952 talloc_free(tmp_ctx);
953 return status;
955 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
956 map->gid = id_map.xid.id;
957 } else {
958 DEBUG(1, (__location__ "Did not get GUID when mapping SID for %s", expression));
959 talloc_free(tmp_ctx);
960 return NT_STATUS_INTERNAL_DB_CORRUPTION;
962 } else if (samdb_find_attribute(state->ldb, msg, "objectClass", "user")) {
963 DEBUG(1, (__location__ "Got SID_NAME_USER when searching for a group with %s", expression));
964 talloc_free(tmp_ctx);
965 return NT_STATUS_INTERNAL_DB_CORRUPTION;
968 str = ldb_msg_find_attr_as_string(msg, "samAccountName",
969 NULL);
970 if (str == NULL) {
971 talloc_free(tmp_ctx);
972 return NT_STATUS_INTERNAL_DB_CORRUPTION;
974 map->nt_name = talloc_strdup(map, str);
975 if (!map->nt_name) {
976 talloc_free(tmp_ctx);
977 return NT_STATUS_NO_MEMORY;
980 str = ldb_msg_find_attr_as_string(msg, "description",
981 NULL);
982 if (str != NULL) {
983 map->comment = talloc_strdup(map, str);
984 } else {
985 map->comment = talloc_strdup(map, "");
987 if (!map->comment) {
988 talloc_free(tmp_ctx);
989 return NT_STATUS_NO_MEMORY;
992 talloc_free(tmp_ctx);
993 return NT_STATUS_OK;
996 static NTSTATUS pdb_samba_dsdb_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
997 struct dom_sid sid)
999 char *filter;
1000 NTSTATUS status;
1002 filter = talloc_asprintf(talloc_tos(),
1003 "(&(objectsid=%s)(objectclass=group))",
1004 sid_string_talloc(talloc_tos(), &sid));
1005 if (filter == NULL) {
1006 return NT_STATUS_NO_MEMORY;
1009 status = pdb_samba_dsdb_getgrfilter(m, map, filter);
1010 TALLOC_FREE(filter);
1011 return status;
1014 static NTSTATUS pdb_samba_dsdb_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
1015 gid_t gid)
1017 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1018 m->private_data, struct pdb_samba_dsdb_state);
1019 NTSTATUS status;
1020 struct id_map id_map;
1021 struct id_map *id_maps[2];
1022 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1023 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1025 id_map.xid.id = gid;
1026 id_map.xid.type = ID_TYPE_GID;
1027 id_maps[0] = &id_map;
1028 id_maps[1] = NULL;
1030 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
1031 if (!NT_STATUS_IS_OK(status)) {
1032 return status;
1034 status = pdb_samba_dsdb_getgrsid(m, map, *id_map.sid);
1035 talloc_free(tmp_ctx);
1036 return status;
1039 static NTSTATUS pdb_samba_dsdb_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
1040 const char *name)
1042 char *filter;
1043 NTSTATUS status;
1045 filter = talloc_asprintf(talloc_tos(),
1046 "(&(samaccountname=%s)(objectclass=group))",
1047 name);
1048 if (filter == NULL) {
1049 return NT_STATUS_NO_MEMORY;
1052 status = pdb_samba_dsdb_getgrfilter(m, map, filter);
1053 TALLOC_FREE(filter);
1054 return status;
1057 static NTSTATUS pdb_samba_dsdb_create_dom_group(struct pdb_methods *m,
1058 TALLOC_CTX *mem_ctx, const char *name,
1059 uint32 *rid)
1061 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1062 m->private_data, struct pdb_samba_dsdb_state);
1063 NTSTATUS status;
1064 struct dom_sid *sid;
1065 struct ldb_dn *dn;
1066 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1067 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1069 status = dsdb_add_domain_group(state->ldb, tmp_ctx, name, &sid, &dn);
1070 if (!NT_STATUS_IS_OK(status)) {
1071 talloc_free(tmp_ctx);
1072 return status;
1075 sid_peek_rid(sid, rid);
1076 talloc_free(tmp_ctx);
1077 return NT_STATUS_OK;
1080 static NTSTATUS pdb_samba_dsdb_delete_dom_group(struct pdb_methods *m,
1081 TALLOC_CTX *mem_ctx, uint32 rid)
1083 const char *attrs[] = { NULL };
1084 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1085 m->private_data, struct pdb_samba_dsdb_state);
1086 struct dom_sid sid;
1087 struct ldb_message *msg;
1088 struct ldb_dn *dn;
1089 int rc;
1090 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1091 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1093 sid_compose(&sid, samdb_domain_sid(state->ldb), rid);
1095 if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1096 DEBUG(0, ("Unable to start transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1097 return NT_STATUS_INTERNAL_ERROR;
1100 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, &sid));
1101 if (!dn || !ldb_dn_validate(dn)) {
1102 talloc_free(tmp_ctx);
1103 ldb_transaction_cancel(state->ldb);
1104 return NT_STATUS_NO_MEMORY;
1106 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "objectclass=group");
1107 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1108 talloc_free(tmp_ctx);
1109 ldb_transaction_cancel(state->ldb);
1110 return NT_STATUS_NO_SUCH_GROUP;
1112 rc = ldb_delete(state->ldb, dn);
1113 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1114 talloc_free(tmp_ctx);
1115 ldb_transaction_cancel(state->ldb);
1116 return NT_STATUS_NO_SUCH_GROUP;
1117 } else if (rc != LDB_SUCCESS) {
1118 DEBUG(10, ("ldb_delete failed %s\n",
1119 ldb_errstring(state->ldb)));
1120 ldb_transaction_cancel(state->ldb);
1121 return NT_STATUS_LDAP(rc);
1124 if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1125 DEBUG(0, ("Unable to commit transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1126 return NT_STATUS_INTERNAL_ERROR;
1128 return NT_STATUS_OK;
1131 static NTSTATUS pdb_samba_dsdb_add_group_mapping_entry(struct pdb_methods *m,
1132 GROUP_MAP *map)
1134 return NT_STATUS_NOT_IMPLEMENTED;
1137 static NTSTATUS pdb_samba_dsdb_update_group_mapping_entry(struct pdb_methods *m,
1138 GROUP_MAP *map)
1140 return NT_STATUS_NOT_IMPLEMENTED;
1143 static NTSTATUS pdb_samba_dsdb_delete_group_mapping_entry(struct pdb_methods *m,
1144 struct dom_sid sid)
1146 return NT_STATUS_NOT_IMPLEMENTED;
1149 static NTSTATUS pdb_samba_dsdb_enum_group_mapping(struct pdb_methods *m,
1150 const struct dom_sid *sid,
1151 enum lsa_SidType sid_name_use,
1152 GROUP_MAP ***pp_rmap,
1153 size_t *p_num_entries,
1154 bool unix_only)
1156 return NT_STATUS_NOT_IMPLEMENTED;
1159 static NTSTATUS pdb_samba_dsdb_enum_group_members(struct pdb_methods *m,
1160 TALLOC_CTX *mem_ctx,
1161 const struct dom_sid *group,
1162 uint32_t **pmembers,
1163 size_t *pnum_members)
1165 unsigned int i, num_sids, num_members;
1166 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1167 m->private_data, struct pdb_samba_dsdb_state);
1168 struct dom_sid *members_as_sids;
1169 struct dom_sid *dom_sid;
1170 uint32_t *members;
1171 struct ldb_dn *dn;
1172 NTSTATUS status;
1174 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1175 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1177 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, group));
1178 if (!dn || !ldb_dn_validate(dn)) {
1179 return NT_STATUS_NO_MEMORY;
1182 status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
1183 if (!NT_STATUS_IS_OK(status)) {
1184 talloc_free(tmp_ctx);
1185 return status;
1187 status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
1188 if (!NT_STATUS_IS_OK(status)) {
1189 talloc_free(tmp_ctx);
1190 return status;
1193 *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
1194 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(*pmembers, tmp_ctx);
1195 num_members = 0;
1197 for (i = 0; i < num_sids; i++) {
1198 if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
1199 continue;
1201 status = dom_sid_split_rid(NULL, &members_as_sids[i],
1202 NULL, &members[num_members]);
1203 if (!NT_STATUS_IS_OK(status)) {
1204 talloc_free(tmp_ctx);
1205 return status;
1207 num_members++;
1209 *pnum_members = num_members;
1210 return NT_STATUS_OK;
1213 /* Just convert the primary group SID into a group */
1214 static NTSTATUS fake_enum_group_memberships(struct pdb_samba_dsdb_state *state,
1215 TALLOC_CTX *mem_ctx,
1216 struct samu *user,
1217 struct dom_sid **pp_sids,
1218 gid_t **pp_gids,
1219 uint32_t *p_num_groups)
1221 NTSTATUS status;
1222 size_t num_groups = 0;
1223 struct dom_sid *group_sids = NULL;
1224 gid_t *gids = NULL;
1225 TALLOC_CTX *tmp_ctx;
1227 tmp_ctx = talloc_new(mem_ctx);
1228 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1230 if (user->group_sid) {
1231 struct id_map *id_maps[2];
1232 struct id_map id_map;
1234 num_groups = 1;
1236 group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
1237 if (group_sids == NULL) {
1238 talloc_free(tmp_ctx);
1239 return NT_STATUS_NO_MEMORY;
1241 gids = talloc_array(tmp_ctx, gid_t, num_groups);
1242 if (gids == NULL) {
1243 talloc_free(tmp_ctx);
1244 return NT_STATUS_NO_MEMORY;
1247 group_sids[0] = *user->group_sid;
1249 ZERO_STRUCT(id_map);
1250 id_map.sid = &group_sids[0];
1251 id_maps[0] = &id_map;
1252 id_maps[1] = NULL;
1254 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1255 if (!NT_STATUS_IS_OK(status)) {
1256 talloc_free(tmp_ctx);
1257 return status;
1259 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1260 gids[0] = id_map.xid.id;
1261 } else {
1262 DEBUG(1, (__location__
1263 "Group %s, of which %s is a member, could not be converted to a GID\n",
1264 dom_sid_string(tmp_ctx, &group_sids[0]),
1265 dom_sid_string(tmp_ctx, &user->user_sid)));
1266 talloc_free(tmp_ctx);
1267 /* We must error out, otherwise a user might
1268 * avoid a DENY acl based on a group they
1269 * missed out on */
1270 return NT_STATUS_NO_SUCH_GROUP;
1274 *pp_sids = talloc_steal(mem_ctx, group_sids);
1275 *pp_gids = talloc_steal(mem_ctx, gids);
1276 *p_num_groups = num_groups;
1277 talloc_free(tmp_ctx);
1278 return NT_STATUS_OK;
1281 static NTSTATUS pdb_samba_dsdb_enum_group_memberships(struct pdb_methods *m,
1282 TALLOC_CTX *mem_ctx,
1283 struct samu *user,
1284 struct dom_sid **pp_sids,
1285 gid_t **pp_gids,
1286 uint32_t *p_num_groups)
1288 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1289 m->private_data, struct pdb_samba_dsdb_state);
1290 struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
1291 m, user);
1292 const char *attrs[] = { "tokenGroups", NULL};
1293 struct ldb_message *tokengroups_msg;
1294 struct ldb_message_element *tokengroups;
1295 int i, rc;
1296 NTSTATUS status;
1297 unsigned int count = 0;
1298 size_t num_groups;
1299 struct dom_sid *group_sids;
1300 gid_t *gids;
1301 TALLOC_CTX *tmp_ctx;
1303 if (msg == NULL) {
1304 /* Fake up some things here */
1305 return fake_enum_group_memberships(state,
1306 mem_ctx,
1307 user, pp_sids,
1308 pp_gids, p_num_groups);
1311 tmp_ctx = talloc_new(mem_ctx);
1312 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1314 rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
1316 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1317 talloc_free(tmp_ctx);
1318 return NT_STATUS_NO_SUCH_USER;
1319 } else if (rc != LDB_SUCCESS) {
1320 DEBUG(10, ("dsdb_search_one failed %s\n",
1321 ldb_errstring(state->ldb)));
1322 talloc_free(tmp_ctx);
1323 return NT_STATUS_LDAP(rc);
1326 tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
1328 if (tokengroups) {
1329 count = tokengroups->num_values;
1332 group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
1333 if (group_sids == NULL) {
1334 talloc_free(tmp_ctx);
1335 return NT_STATUS_NO_MEMORY;
1337 gids = talloc_array(tmp_ctx, gid_t, count);
1338 if (gids == NULL) {
1339 talloc_free(tmp_ctx);
1340 return NT_STATUS_NO_MEMORY;
1342 num_groups = 0;
1344 for (i=0; i<count; i++) {
1345 struct id_map *id_maps[2];
1346 struct id_map id_map;
1347 struct ldb_val *v = &tokengroups->values[i];
1348 enum ndr_err_code ndr_err
1349 = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
1350 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1351 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1352 talloc_free(tmp_ctx);
1353 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1356 ZERO_STRUCT(id_map);
1357 id_map.sid = &group_sids[num_groups];
1358 id_maps[0] = &id_map;
1359 id_maps[1] = NULL;
1361 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1362 if (!NT_STATUS_IS_OK(status)) {
1363 talloc_free(tmp_ctx);
1364 return status;
1366 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1367 gids[num_groups] = id_map.xid.id;
1368 } else {
1369 DEBUG(1, (__location__
1370 "Group %s, of which %s is a member, could not be converted to a GID\n",
1371 dom_sid_string(tmp_ctx, &group_sids[num_groups]),
1372 ldb_dn_get_linearized(msg->dn)));
1373 talloc_free(tmp_ctx);
1374 /* We must error out, otherwise a user might
1375 * avoid a DENY acl based on a group they
1376 * missed out on */
1377 return NT_STATUS_NO_SUCH_GROUP;
1380 num_groups += 1;
1381 if (num_groups == count) {
1382 break;
1386 *pp_sids = talloc_steal(mem_ctx, group_sids);
1387 *pp_gids = talloc_steal(mem_ctx, gids);
1388 *p_num_groups = num_groups;
1389 talloc_free(tmp_ctx);
1390 return NT_STATUS_OK;
1393 static NTSTATUS pdb_samba_dsdb_set_unix_primary_group(struct pdb_methods *m,
1394 TALLOC_CTX *mem_ctx,
1395 struct samu *user)
1397 return NT_STATUS_NOT_IMPLEMENTED;
1400 static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid(struct pdb_methods *m,
1401 TALLOC_CTX *mem_ctx,
1402 const struct dom_sid *groupsid,
1403 const struct dom_sid *membersid,
1404 int mod_op)
1406 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1407 m->private_data, struct pdb_samba_dsdb_state);
1408 struct ldb_message *msg;
1409 int ret;
1410 struct ldb_message_element *el;
1411 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1412 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1413 msg = ldb_msg_new(tmp_ctx);
1414 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg, tmp_ctx);
1416 msg->dn = ldb_dn_new_fmt(msg, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, groupsid));
1417 if (!msg->dn || !ldb_dn_validate(msg->dn)) {
1418 talloc_free(tmp_ctx);
1419 return NT_STATUS_NO_MEMORY;
1421 ret = ldb_msg_add_fmt(msg, "member", "<SID=%s>", dom_sid_string(tmp_ctx, membersid));
1422 if (ret != LDB_SUCCESS) {
1423 talloc_free(tmp_ctx);
1424 return NT_STATUS_NO_MEMORY;
1426 el = ldb_msg_find_element(msg, "member");
1427 el->flags = mod_op;
1429 /* No need for transactions here, the ldb auto-transaction
1430 * code will handle things for the single operation */
1431 ret = ldb_modify(state->ldb, msg);
1432 talloc_free(tmp_ctx);
1433 if (ret != LDB_SUCCESS) {
1434 DEBUG(10, ("ldb_modify failed: %s\n",
1435 ldb_errstring(state->ldb)));
1436 if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
1437 return NT_STATUS_MEMBER_IN_GROUP;
1439 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1440 return NT_STATUS_MEMBER_NOT_IN_GROUP;
1442 return NT_STATUS_LDAP(ret);
1445 return NT_STATUS_OK;
1448 static NTSTATUS pdb_samba_dsdb_mod_groupmem(struct pdb_methods *m,
1449 TALLOC_CTX *mem_ctx,
1450 uint32 grouprid, uint32 memberrid,
1451 int mod_op)
1453 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1454 m->private_data, struct pdb_samba_dsdb_state);
1455 const struct dom_sid *dom_sid, *groupsid, *membersid;
1456 NTSTATUS status;
1457 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1458 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1460 dom_sid = samdb_domain_sid(state->ldb);
1462 groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
1463 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(groupsid, tmp_ctx);
1464 membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
1465 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(membersid, tmp_ctx);
1466 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
1467 talloc_free(tmp_ctx);
1468 return status;
1471 static NTSTATUS pdb_samba_dsdb_add_groupmem(struct pdb_methods *m,
1472 TALLOC_CTX *mem_ctx,
1473 uint32 group_rid, uint32 member_rid)
1475 return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1476 LDB_FLAG_MOD_ADD);
1479 static NTSTATUS pdb_samba_dsdb_del_groupmem(struct pdb_methods *m,
1480 TALLOC_CTX *mem_ctx,
1481 uint32 group_rid, uint32 member_rid)
1483 return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1484 LDB_FLAG_MOD_DELETE);
1487 static NTSTATUS pdb_samba_dsdb_create_alias(struct pdb_methods *m,
1488 const char *name, uint32 *rid)
1490 TALLOC_CTX *frame = talloc_stackframe();
1491 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1492 m->private_data, struct pdb_samba_dsdb_state);
1493 struct dom_sid *sid;
1495 struct ldb_dn *dn;
1496 NTSTATUS status;
1498 /* Internally this uses transactions to ensure all the steps
1499 * happen or fail as one */
1500 status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
1501 if (!NT_STATUS_IS_OK(status)) {
1502 TALLOC_FREE(frame);
1505 sid_peek_rid(sid, rid);
1506 TALLOC_FREE(frame);
1507 return NT_STATUS_OK;
1510 static NTSTATUS pdb_samba_dsdb_delete_alias(struct pdb_methods *m,
1511 const struct dom_sid *sid)
1513 const char *attrs[] = { NULL };
1514 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1515 m->private_data, struct pdb_samba_dsdb_state);
1516 struct ldb_message *msg;
1517 struct ldb_dn *dn;
1518 int rc;
1519 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1520 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1522 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, sid));
1523 if (!dn || !ldb_dn_validate(dn)) {
1524 talloc_free(tmp_ctx);
1525 return NT_STATUS_NO_MEMORY;
1528 if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1529 DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(state->ldb)));
1530 return NT_STATUS_INTERNAL_ERROR;
1533 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
1534 "(|(grouptype=%d)(grouptype=%d)))",
1535 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1536 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1537 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1538 talloc_free(tmp_ctx);
1539 ldb_transaction_cancel(state->ldb);
1540 return NT_STATUS_NO_SUCH_ALIAS;
1542 rc = ldb_delete(state->ldb, dn);
1543 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1544 talloc_free(tmp_ctx);
1545 ldb_transaction_cancel(state->ldb);
1546 return NT_STATUS_NO_SUCH_ALIAS;
1547 } else if (rc != LDB_SUCCESS) {
1548 DEBUG(10, ("ldb_delete failed %s\n",
1549 ldb_errstring(state->ldb)));
1550 ldb_transaction_cancel(state->ldb);
1551 return NT_STATUS_LDAP(rc);
1554 if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1555 DEBUG(0, ("Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s\n",
1556 ldb_errstring(state->ldb)));
1557 return NT_STATUS_INTERNAL_ERROR;
1560 return NT_STATUS_OK;
1563 #if 0
1564 static NTSTATUS pdb_samba_dsdb_set_aliasinfo(struct pdb_methods *m,
1565 const struct dom_sid *sid,
1566 struct acct_info *info)
1568 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1569 m->private_data, struct pdb_samba_dsdb_state);
1570 struct tldap_context *ld;
1571 const char *attrs[3] = { "objectSid", "description",
1572 "samAccountName" };
1573 struct ldb_message **msg;
1574 char *sidstr, *dn;
1575 int rc;
1576 struct tldap_mod *mods;
1577 int num_mods;
1578 bool ok;
1580 ld = pdb_samba_dsdb_ld(state);
1581 if (ld == NULL) {
1582 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1585 sidstr = sid_binstring(talloc_tos(), sid);
1586 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1588 rc = pdb_samba_dsdb_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1589 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1590 &msg, "(&(objectSid=%s)(objectclass=group)"
1591 "(|(grouptype=%d)(grouptype=%d)))",
1592 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1593 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1594 TALLOC_FREE(sidstr)
1595 if (rc != LDB_SUCCESS) {
1596 DEBUG(10, ("ldap_search failed %s\n",
1597 ldb_errstring(state->ldb)));
1598 return NT_STATUS_LDAP(rc);
1600 switch talloc_array_length(msg) {
1601 case 0:
1602 return NT_STATUS_NO_SUCH_ALIAS;
1603 case 1:
1604 break;
1605 default:
1606 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1609 if (!tldap_entry_dn(msg[0], &dn)) {
1610 TALLOC_FREE(msg);
1611 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1614 mods = NULL;
1615 num_mods = 0;
1616 ok = true;
1618 ok &= tldap_make_mod_fmt(
1619 msg[0], msg, &num_mods, &mods, "description",
1620 "%s", info->acct_desc);
1621 ok &= tldap_make_mod_fmt(
1622 msg[0], msg, &num_mods, &mods, "samAccountName",
1623 "%s", info->acct_name);
1624 if (!ok) {
1625 TALLOC_FREE(msg);
1626 return NT_STATUS_NO_MEMORY;
1628 if (num_mods == 0) {
1629 /* no change */
1630 TALLOC_FREE(msg);
1631 return NT_STATUS_OK;
1634 rc = tldap_modify(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
1635 TALLOC_FREE(msg);
1636 if (rc != LDB_SUCCESS) {
1637 DEBUG(10, ("ldap_modify failed: %s\n",
1638 ldb_errstring(state->ldb)));
1639 return NT_STATUS_LDAP(rc);
1641 return NT_STATUS_OK;
1643 #endif
1644 static NTSTATUS pdb_samba_dsdb_add_aliasmem(struct pdb_methods *m,
1645 const struct dom_sid *alias,
1646 const struct dom_sid *member)
1648 NTSTATUS status;
1649 TALLOC_CTX *frame = talloc_stackframe();
1650 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_ADD);
1651 talloc_free(frame);
1652 return status;
1655 static NTSTATUS pdb_samba_dsdb_del_aliasmem(struct pdb_methods *m,
1656 const struct dom_sid *alias,
1657 const struct dom_sid *member)
1659 NTSTATUS status;
1660 TALLOC_CTX *frame = talloc_stackframe();
1661 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
1662 talloc_free(frame);
1663 return status;
1666 static NTSTATUS pdb_samba_dsdb_enum_aliasmem(struct pdb_methods *m,
1667 const struct dom_sid *alias,
1668 TALLOC_CTX *mem_ctx,
1669 struct dom_sid **pmembers,
1670 size_t *pnum_members)
1672 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1673 m->private_data, struct pdb_samba_dsdb_state);
1674 struct ldb_dn *dn;
1675 unsigned int num_members;
1676 NTSTATUS status;
1677 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1678 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1680 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, alias));
1681 if (!dn || !ldb_dn_validate(dn)) {
1682 return NT_STATUS_NO_MEMORY;
1685 status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
1686 *pnum_members = num_members;
1687 if (NT_STATUS_IS_OK(status)) {
1688 talloc_steal(mem_ctx, pmembers);
1690 talloc_free(tmp_ctx);
1691 return status;
1694 static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1695 TALLOC_CTX *mem_ctx,
1696 const struct dom_sid *domain_sid,
1697 const struct dom_sid *members,
1698 size_t num_members,
1699 uint32_t **palias_rids,
1700 size_t *pnum_alias_rids)
1702 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1703 m->private_data, struct pdb_samba_dsdb_state);
1704 uint32_t *alias_rids = NULL;
1705 size_t num_alias_rids = 0;
1706 int i;
1707 struct dom_sid *groupSIDs = NULL;
1708 unsigned int num_groupSIDs = 0;
1709 char *filter;
1710 NTSTATUS status;
1711 const char *sid_string;
1712 const char *sid_dn;
1713 DATA_BLOB sid_blob;
1715 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1716 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1718 * TODO: Get the filter right so that we only get the aliases from
1719 * either the SAM or BUILTIN
1722 filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
1723 GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1724 if (filter == NULL) {
1725 return NT_STATUS_NO_MEMORY;
1728 for (i = 0; i < num_members; i++) {
1729 sid_string = dom_sid_string(tmp_ctx, &members[i]);
1730 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sid_string, tmp_ctx);
1732 sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", sid_string);
1733 NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sid_dn, tmp_ctx);
1735 sid_blob = data_blob_string_const(sid_dn);
1737 status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1738 tmp_ctx, &groupSIDs, &num_groupSIDs);
1739 if (!NT_STATUS_IS_OK(status)) {
1740 talloc_free(tmp_ctx);
1741 return status;
1745 alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1746 if (alias_rids == NULL) {
1747 talloc_free(tmp_ctx);
1748 return NT_STATUS_NO_MEMORY;
1751 for (i=0; i<num_groupSIDs; i++) {
1752 if (sid_peek_check_rid(domain_sid, &groupSIDs[i],
1753 &alias_rids[num_alias_rids])) {
1754 num_alias_rids++;;
1758 *palias_rids = alias_rids;
1759 *pnum_alias_rids = num_alias_rids;
1760 return NT_STATUS_OK;
1763 static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1764 const struct dom_sid *domain_sid,
1765 int num_rids,
1766 uint32 *rids,
1767 const char **names,
1768 enum lsa_SidType *lsa_attrs)
1770 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1771 m->private_data, struct pdb_samba_dsdb_state);
1772 NTSTATUS status;
1774 TALLOC_CTX *tmp_ctx;
1776 if (num_rids == 0) {
1777 return NT_STATUS_NONE_MAPPED;
1780 tmp_ctx = talloc_stackframe();
1781 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1783 status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1784 talloc_free(tmp_ctx);
1785 return status;
1788 static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1789 const struct dom_sid *domain_sid,
1790 int num_names,
1791 const char **pp_names,
1792 uint32 *rids,
1793 enum lsa_SidType *attrs)
1795 return NT_STATUS_NOT_IMPLEMENTED;
1798 static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1799 enum pdb_policy_type type,
1800 uint32_t *value)
1802 return account_policy_get(type, value)
1803 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1806 static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1807 enum pdb_policy_type type,
1808 uint32_t value)
1810 return account_policy_set(type, value)
1811 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1814 static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1815 time_t *seq_num_out)
1817 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1818 m->private_data, struct pdb_samba_dsdb_state);
1819 uint64_t seq_num;
1820 int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1821 if (ret == LDB_SUCCESS) {
1822 *seq_num_out = seq_num;
1823 return NT_STATUS_OK;
1824 } else {
1825 return NT_STATUS_UNSUCCESSFUL;
1829 struct pdb_samba_dsdb_search_state {
1830 uint32_t acct_flags;
1831 struct samr_displayentry *entries;
1832 uint32_t num_entries;
1833 ssize_t array_size;
1834 uint32_t current;
1837 static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1838 struct samr_displayentry *entry)
1840 struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1841 search->private_data, struct pdb_samba_dsdb_search_state);
1843 if (state->current == state->num_entries) {
1844 return false;
1847 entry->idx = state->entries[state->current].idx;
1848 entry->rid = state->entries[state->current].rid;
1849 entry->acct_flags = state->entries[state->current].acct_flags;
1851 entry->account_name = talloc_strdup(
1852 search, state->entries[state->current].account_name);
1853 entry->fullname = talloc_strdup(
1854 search, state->entries[state->current].fullname);
1855 entry->description = talloc_strdup(
1856 search, state->entries[state->current].description);
1858 state->current += 1;
1859 return true;
1862 static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1864 struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1865 search->private_data, struct pdb_samba_dsdb_search_state);
1866 talloc_free(state);
1869 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1870 struct pdb_search *search,
1871 struct pdb_samba_dsdb_search_state **pstate,
1872 const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
1874 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1875 m->private_data, struct pdb_samba_dsdb_state);
1876 struct pdb_samba_dsdb_search_state *sstate;
1877 const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1878 "userAccountControl", "description", NULL };
1879 struct ldb_result *res;
1880 int i, rc, num_users;
1882 va_list ap;
1883 char *expression = NULL;
1885 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1886 if (!tmp_ctx) {
1887 return false;
1890 va_start(ap, exp_fmt);
1891 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1892 va_end(ap);
1894 if (!expression) {
1895 talloc_free(tmp_ctx);
1896 return LDB_ERR_OPERATIONS_ERROR;
1899 sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1900 if (sstate == NULL) {
1901 talloc_free(tmp_ctx);
1902 return false;
1905 rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1906 if (rc != LDB_SUCCESS) {
1907 talloc_free(tmp_ctx);
1908 DEBUG(10, ("dsdb_search failed: %s\n",
1909 ldb_errstring(state->ldb)));
1910 return false;
1913 num_users = res->count;
1915 sstate->entries = talloc_array(sstate, struct samr_displayentry,
1916 num_users);
1917 if (sstate->entries == NULL) {
1918 talloc_free(tmp_ctx);
1919 DEBUG(10, ("talloc failed\n"));
1920 return false;
1923 sstate->num_entries = 0;
1925 for (i=0; i<num_users; i++) {
1926 struct samr_displayentry *e;
1927 struct dom_sid *sid;
1929 e = &sstate->entries[sstate->num_entries];
1931 e->idx = sstate->num_entries;
1932 sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
1933 if (!sid) {
1934 talloc_free(tmp_ctx);
1935 DEBUG(10, ("Could not pull SID\n"));
1936 return false;
1938 sid_peek_rid(sid, &e->rid);
1940 e->acct_flags = samdb_result_acct_flags(state->ldb, tmp_ctx,
1941 res->msgs[i],
1942 ldb_get_default_basedn(state->ldb));
1943 e->account_name = ldb_msg_find_attr_as_string(
1944 res->msgs[i], "samAccountName", NULL);
1945 if (e->account_name == NULL) {
1946 talloc_free(tmp_ctx);
1947 return false;
1949 e->fullname = ldb_msg_find_attr_as_string(
1950 res->msgs[i], "displayName", "");
1951 e->description = ldb_msg_find_attr_as_string(
1952 res->msgs[i], "description", "");
1954 sstate->num_entries += 1;
1955 if (sstate->num_entries >= num_users) {
1956 break;
1959 talloc_steal(sstate->entries, res->msgs);
1960 search->private_data = talloc_steal(search, sstate);
1961 search->next_entry = pdb_samba_dsdb_next_entry;
1962 search->search_end = pdb_samba_dsdb_search_end;
1963 *pstate = sstate;
1964 talloc_free(tmp_ctx);
1965 return true;
1968 static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
1969 struct pdb_search *search,
1970 uint32 acct_flags)
1972 struct pdb_samba_dsdb_search_state *sstate;
1973 bool ret;
1975 ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
1976 if (!ret) {
1977 return false;
1979 sstate->acct_flags = acct_flags;
1980 return true;
1983 static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
1984 struct pdb_search *search)
1986 struct pdb_samba_dsdb_search_state *sstate;
1987 bool ret;
1989 ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
1990 "(&(grouptype=%d)(objectclass=group))",
1991 GTYPE_SECURITY_GLOBAL_GROUP);
1992 if (!ret) {
1993 return false;
1995 sstate->acct_flags = 0;
1996 return true;
1999 static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
2000 struct pdb_search *search,
2001 const struct dom_sid *sid)
2003 struct pdb_samba_dsdb_search_state *sstate;
2004 bool ret;
2006 ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2007 "(&(grouptype=%d)(objectclass=group))",
2008 sid_check_is_builtin(sid)
2009 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2010 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2011 if (!ret) {
2012 return false;
2014 sstate->acct_flags = 0;
2015 return true;
2018 static bool pdb_samba_dsdb_uid_to_sid(struct pdb_methods *m, uid_t uid,
2019 struct dom_sid *sid)
2021 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2022 m->private_data, struct pdb_samba_dsdb_state);
2023 NTSTATUS status;
2024 struct id_map id_map;
2025 struct id_map *id_maps[2];
2026 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2027 if (!tmp_ctx) {
2028 return false;
2031 id_map.xid.id = uid;
2032 id_map.xid.type = ID_TYPE_UID;
2033 id_maps[0] = &id_map;
2034 id_maps[1] = NULL;
2036 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2037 if (!NT_STATUS_IS_OK(status)) {
2038 talloc_free(tmp_ctx);
2039 return false;
2041 *sid = *id_map.sid;
2042 talloc_free(tmp_ctx);
2043 return true;
2046 static bool pdb_samba_dsdb_gid_to_sid(struct pdb_methods *m, gid_t gid,
2047 struct dom_sid *sid)
2049 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2050 m->private_data, struct pdb_samba_dsdb_state);
2051 NTSTATUS status;
2052 struct id_map id_map;
2053 struct id_map *id_maps[2];
2054 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2055 if (!tmp_ctx) {
2056 return false;
2059 id_map.xid.id = gid;
2060 id_map.xid.type = ID_TYPE_GID;
2061 id_maps[0] = &id_map;
2062 id_maps[1] = NULL;
2064 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2065 if (!NT_STATUS_IS_OK(status)) {
2066 return false;
2068 *sid = *id_map.sid;
2069 talloc_free(tmp_ctx);
2070 return true;
2073 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2074 struct unixid *id)
2076 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2077 m->private_data, struct pdb_samba_dsdb_state);
2078 struct id_map id_map;
2079 struct id_map *id_maps[2];
2080 NTSTATUS status;
2081 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2082 if (!tmp_ctx) {
2083 return false;
2086 ZERO_STRUCT(id_map);
2087 id_map.sid = discard_const_p(struct dom_sid, sid);
2088 id_maps[0] = &id_map;
2089 id_maps[1] = NULL;
2091 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2092 talloc_free(tmp_ctx);
2093 if (!NT_STATUS_IS_OK(status)) {
2094 return false;
2096 if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2097 *id = id_map.xid;
2098 return true;
2100 return false;
2103 static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2105 return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
2108 static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32 *rid)
2110 return false;
2113 static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2114 const char *domain, char** pwd,
2115 struct dom_sid *sid,
2116 time_t *pass_last_set_time)
2118 return false;
2121 static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2122 const char* domain, const char* pwd,
2123 const struct dom_sid *sid)
2125 return false;
2128 static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2129 const char *domain)
2131 return false;
2134 static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2135 TALLOC_CTX *mem_ctx,
2136 uint32 *num_domains,
2137 struct trustdom_info ***domains)
2139 *num_domains = 0;
2140 *domains = NULL;
2141 return NT_STATUS_OK;
2144 static bool pdb_samba_dsdb_is_responsible_for_wellknown(struct pdb_methods *m)
2146 return true;
2149 static void pdb_samba_dsdb_init_methods(struct pdb_methods *m)
2151 m->name = "samba_dsdb";
2152 m->get_domain_info = pdb_samba_dsdb_get_domain_info;
2153 m->getsampwnam = pdb_samba_dsdb_getsampwnam;
2154 m->getsampwsid = pdb_samba_dsdb_getsampwsid;
2155 m->create_user = pdb_samba_dsdb_create_user;
2156 m->delete_user = pdb_samba_dsdb_delete_user;
2157 m->add_sam_account = pdb_samba_dsdb_add_sam_account;
2158 m->update_sam_account = pdb_samba_dsdb_update_sam_account;
2159 m->delete_sam_account = pdb_samba_dsdb_delete_sam_account;
2160 m->rename_sam_account = pdb_samba_dsdb_rename_sam_account;
2161 m->update_login_attempts = pdb_samba_dsdb_update_login_attempts;
2162 m->getgrsid = pdb_samba_dsdb_getgrsid;
2163 m->getgrgid = pdb_samba_dsdb_getgrgid;
2164 m->getgrnam = pdb_samba_dsdb_getgrnam;
2165 m->create_dom_group = pdb_samba_dsdb_create_dom_group;
2166 m->delete_dom_group = pdb_samba_dsdb_delete_dom_group;
2167 m->add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry;
2168 m->update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry;
2169 m->delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry;
2170 m->enum_group_mapping = pdb_samba_dsdb_enum_group_mapping;
2171 m->enum_group_members = pdb_samba_dsdb_enum_group_members;
2172 m->enum_group_memberships = pdb_samba_dsdb_enum_group_memberships;
2173 m->set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group;
2174 m->add_groupmem = pdb_samba_dsdb_add_groupmem;
2175 m->del_groupmem = pdb_samba_dsdb_del_groupmem;
2176 m->create_alias = pdb_samba_dsdb_create_alias;
2177 m->delete_alias = pdb_samba_dsdb_delete_alias;
2178 m->get_aliasinfo = pdb_default_get_aliasinfo;
2179 m->add_aliasmem = pdb_samba_dsdb_add_aliasmem;
2180 m->del_aliasmem = pdb_samba_dsdb_del_aliasmem;
2181 m->enum_aliasmem = pdb_samba_dsdb_enum_aliasmem;
2182 m->enum_alias_memberships = pdb_samba_dsdb_enum_alias_memberships;
2183 m->lookup_rids = pdb_samba_dsdb_lookup_rids;
2184 m->lookup_names = pdb_samba_dsdb_lookup_names;
2185 m->get_account_policy = pdb_samba_dsdb_get_account_policy;
2186 m->set_account_policy = pdb_samba_dsdb_set_account_policy;
2187 m->get_seq_num = pdb_samba_dsdb_get_seq_num;
2188 m->search_users = pdb_samba_dsdb_search_users;
2189 m->search_groups = pdb_samba_dsdb_search_groups;
2190 m->search_aliases = pdb_samba_dsdb_search_aliases;
2191 m->uid_to_sid = pdb_samba_dsdb_uid_to_sid;
2192 m->gid_to_sid = pdb_samba_dsdb_gid_to_sid;
2193 m->sid_to_id = pdb_samba_dsdb_sid_to_id;
2194 m->capabilities = pdb_samba_dsdb_capabilities;
2195 m->new_rid = pdb_samba_dsdb_new_rid;
2196 m->get_trusteddom_pw = pdb_samba_dsdb_get_trusteddom_pw;
2197 m->set_trusteddom_pw = pdb_samba_dsdb_set_trusteddom_pw;
2198 m->del_trusteddom_pw = pdb_samba_dsdb_del_trusteddom_pw;
2199 m->enum_trusteddoms = pdb_samba_dsdb_enum_trusteddoms;
2200 m->is_responsible_for_wellknown =
2201 pdb_samba_dsdb_is_responsible_for_wellknown;
2204 static void free_private_data(void **vp)
2206 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2207 *vp, struct pdb_samba_dsdb_state);
2208 talloc_unlink(state, state->ldb);
2209 return;
2212 static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m)
2214 struct pdb_domain_info *dom_info;
2215 struct dom_sid stored_sid;
2216 struct GUID stored_guid;
2217 bool sid_exists_and_matches = false;
2218 bool guid_exists_and_matches = false;
2219 bool ret;
2221 dom_info = pdb_samba_dsdb_get_domain_info(m, m);
2222 if (!dom_info) {
2223 return NT_STATUS_UNSUCCESSFUL;
2226 ret = secrets_fetch_domain_sid(dom_info->name, &stored_sid);
2227 if (ret) {
2228 if (dom_sid_equal(&stored_sid, &dom_info->sid)) {
2229 sid_exists_and_matches = true;
2233 if (sid_exists_and_matches == false) {
2234 secrets_clear_domain_protection(dom_info->name);
2235 ret = secrets_store_domain_sid(dom_info->name,
2236 &dom_info->sid);
2237 ret &= secrets_mark_domain_protected(dom_info->name);
2238 if (!ret) {
2239 goto done;
2243 ret = secrets_fetch_domain_guid(dom_info->name, &stored_guid);
2244 if (ret) {
2245 if (GUID_equal(&stored_guid, &dom_info->guid)) {
2246 guid_exists_and_matches = true;
2250 if (guid_exists_and_matches == false) {
2251 secrets_clear_domain_protection(dom_info->name);
2252 ret = secrets_store_domain_guid(dom_info->name,
2253 &dom_info->guid);
2254 ret &= secrets_mark_domain_protected(dom_info->name);
2255 if (!ret) {
2256 goto done;
2260 done:
2261 TALLOC_FREE(dom_info);
2262 if (!ret) {
2263 return NT_STATUS_UNSUCCESSFUL;
2265 return NT_STATUS_OK;
2268 static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
2269 const char *location)
2271 struct pdb_methods *m;
2272 struct pdb_samba_dsdb_state *state;
2273 NTSTATUS status;
2275 if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
2276 return status;
2279 state = talloc_zero(m, struct pdb_samba_dsdb_state);
2280 if (state == NULL) {
2281 goto nomem;
2283 m->private_data = state;
2284 m->free_private_data = free_private_data;
2285 pdb_samba_dsdb_init_methods(m);
2287 state->ev = s4_event_context_init(state);
2288 if (!state->ev) {
2289 DEBUG(0, ("s4_event_context_init failed\n"));
2290 goto nomem;
2293 state->lp_ctx = loadparm_init_s3(state, loadparm_s3_helpers());
2294 if (state->lp_ctx == NULL) {
2295 DEBUG(0, ("loadparm_init_s3 failed\n"));
2296 goto nomem;
2299 if (location) {
2300 state->ldb = samdb_connect_url(state,
2301 state->ev,
2302 state->lp_ctx,
2303 system_session(state->lp_ctx),
2304 0, location);
2305 } else {
2306 state->ldb = samdb_connect(state,
2307 state->ev,
2308 state->lp_ctx,
2309 system_session(state->lp_ctx), 0);
2312 if (!state->ldb) {
2313 DEBUG(0, ("samdb_connect failed\n"));
2314 status = NT_STATUS_INTERNAL_ERROR;
2315 goto fail;
2318 state->idmap_ctx = idmap_init(state, state->ev,
2319 state->lp_ctx);
2320 if (!state->idmap_ctx) {
2321 DEBUG(0, ("idmap failed\n"));
2322 status = NT_STATUS_INTERNAL_ERROR;
2323 goto fail;
2326 status = pdb_samba_dsdb_init_secrets(m);
2327 if (!NT_STATUS_IS_OK(status)) {
2328 DEBUG(10, ("pdb_samba_dsdb_init_secrets failed!\n"));
2329 goto fail;
2332 *pdb_method = m;
2333 return NT_STATUS_OK;
2334 nomem:
2335 status = NT_STATUS_NO_MEMORY;
2336 fail:
2337 TALLOC_FREE(m);
2338 return status;
2341 NTSTATUS pdb_samba_dsdb_init(void);
2342 NTSTATUS pdb_samba_dsdb_init(void)
2344 NTSTATUS status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba_dsdb",
2345 pdb_init_samba_dsdb);
2346 if (!NT_STATUS_IS_OK(status)) {
2347 return status;
2349 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4",
2350 pdb_init_samba_dsdb);