s3:vfs:gpfs: fix flapping offline: always get winAttrs from gpfs for is_offline
[Samba.git] / source3 / passdb / pdb_samba_dsdb.c
blobb04e7b230a791f09d75cda238229066ea33e0120
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 = samdb_result_acct_flags(msg, "msDS-User-Account-Control-Computed");
280 if (n == 0) {
281 DEBUG(10, ("Could not pull userAccountControl\n"));
282 goto fail;
284 pdb_set_acct_ctrl(sam, 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 talloc_free(frame);
347 return false;
350 msg->dn = dn;
352 /* build modify request */
353 ret = ldb_build_mod_req(&req, state->ldb, frame, msg, NULL, NULL,
354 ldb_op_default_callback,
355 NULL);
356 if (ret != LDB_SUCCESS) {
357 talloc_free(frame);
358 return ret;
361 /* If we set a plaintext password, the system will
362 * force the pwdLastSet to now() */
363 if (need_update(sam, PDB_PASSLASTSET)) {
364 dsdb_flags = DSDB_PASSWORD_BYPASS_LAST_SET;
366 ret |= pdb_samba_dsdb_add_time(msg, "pwdLastSet",
367 pdb_get_pass_last_set_time(sam));
370 pw = pdb_get_plaintext_passwd(sam);
371 if (need_update(sam, PDB_PLAINTEXT_PW)) {
372 struct ldb_val pw_utf16;
373 if (pw == NULL) {
374 talloc_free(frame);
375 return LDB_ERR_OPERATIONS_ERROR;
378 if (!convert_string_talloc(msg,
379 CH_UNIX, CH_UTF16,
380 pw, strlen(pw),
381 (void *)&pw_utf16.data,
382 &pw_utf16.length)) {
383 talloc_free(frame);
384 return LDB_ERR_OPERATIONS_ERROR;
386 ret |= ldb_msg_add_value(msg, "clearTextPassword", &pw_utf16, NULL);
387 } else {
388 bool changed_lm_pw = false;
389 bool changed_nt_pw = false;
390 bool changed_history = false;
391 if (need_update(sam, PDB_LMPASSWD)) {
392 struct ldb_val val;
393 val.data = discard_const_p(uint8_t, pdb_get_lanman_passwd(sam));
394 if (!val.data) {
395 samdb_msg_add_delete(state->ldb, msg, msg,
396 "dBCSPwd");
397 } else {
398 val.length = LM_HASH_LEN;
399 ret |= ldb_msg_add_value(msg, "dBCSPwd", &val, NULL);
401 changed_lm_pw = true;
403 if (need_update(sam, PDB_NTPASSWD)) {
404 struct ldb_val val;
405 val.data = discard_const_p(uint8_t, pdb_get_nt_passwd(sam));
406 if (!val.data) {
407 samdb_msg_add_delete(state->ldb, msg, msg,
408 "unicodePwd");
409 } else {
410 val.length = NT_HASH_LEN;
411 ret |= ldb_msg_add_value(msg, "unicodePwd", &val, NULL);
413 changed_nt_pw = true;
416 /* Try to ensure we don't get out of sync */
417 if (changed_lm_pw && !changed_nt_pw) {
418 samdb_msg_add_delete(state->ldb, msg, msg,
419 "unicodePwd");
420 } else if (changed_nt_pw && !changed_lm_pw) {
421 samdb_msg_add_delete(state->ldb, msg, msg,
422 "dBCSPwd");
424 if (changed_lm_pw || changed_nt_pw) {
425 samdb_msg_add_delete(state->ldb, msg, msg,
426 "supplementalCredentials");
430 if (need_update(sam, PDB_PWHISTORY)) {
431 uint32_t current_hist_len;
432 const uint8_t *history = pdb_get_pw_history(sam, &current_hist_len);
434 bool invalid_history = false;
435 struct samr_Password *history_hashes = talloc_array(talloc_tos(), struct samr_Password,
436 current_hist_len);
437 if (!history) {
438 invalid_history = true;
439 } else {
440 unsigned int i;
441 static const uint8_t zeros[16];
442 /* Parse the history into the correct format */
443 for (i = 0; i < current_hist_len; i++) {
444 if (memcmp(&history[i*PW_HISTORY_ENTRY_LEN], zeros, 16) != 0) {
445 /* If the history is in the old format, with a salted hash, then we can't migrate it to AD format */
446 invalid_history = true;
447 break;
449 /* Copy out the 2nd 16 bytes of the 32 byte password history, containing the NT hash */
450 memcpy(history_hashes[i].hash,
451 &history[(i*PW_HISTORY_ENTRY_LEN) + PW_HISTORY_SALT_LEN],
452 sizeof(history_hashes[i].hash));
455 if (invalid_history) {
456 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
457 "ntPwdHistory");
459 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
460 "lmPwdHistory");
461 } else {
462 ret |= samdb_msg_add_hashes(state->ldb, msg, msg,
463 "ntPwdHistory",
464 history_hashes,
465 current_hist_len);
467 changed_history = true;
469 if (changed_lm_pw || changed_nt_pw || changed_history) {
470 /* These attributes can only be modified directly by using a special control */
471 dsdb_flags = DSDB_BYPASS_PASSWORD_HASH;
475 /* PDB_USERSID is only allowed on ADD, handled in caller */
476 if (need_update(sam, PDB_GROUPSID)) {
477 const struct dom_sid *sid = pdb_get_group_sid(sam);
478 uint32_t rid;
479 NTSTATUS status = dom_sid_split_rid(NULL, sid, NULL, &rid);
480 if (!NT_STATUS_IS_OK(status)) {
481 talloc_free(frame);
482 return LDB_ERR_OPERATIONS_ERROR;
484 if (!dom_sid_in_domain(samdb_domain_sid(state->ldb), sid)) {
485 talloc_free(frame);
486 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
488 ret |= samdb_msg_add_uint(state->ldb, msg, msg, "primaryGroupID", rid);
490 if (need_update(sam, PDB_FULLNAME)) {
491 ret |= ldb_msg_add_string(msg, "displayName", pdb_get_fullname(sam));
494 if (need_update(sam, PDB_SMBHOME)) {
495 ret |= ldb_msg_add_string(msg, "homeDirectory",
496 pdb_get_homedir(sam));
499 if (need_update(sam, PDB_PROFILE)) {
500 ret |= ldb_msg_add_string(msg, "profilePath",
501 pdb_get_profile_path(sam));
504 if (need_update(sam, PDB_DRIVE)) {
505 ret |= ldb_msg_add_string(msg, "homeDrive",
506 pdb_get_dir_drive(sam));
509 if (need_update(sam, PDB_LOGONSCRIPT)) {
510 ret |= ldb_msg_add_string(msg, "scriptPath",
511 pdb_get_logon_script(sam));
514 if (need_update(sam, PDB_KICKOFFTIME)) {
515 ret |= pdb_samba_dsdb_add_time(msg, "accountExpires",
516 pdb_get_kickoff_time(sam));
519 if (need_update(sam, PDB_LOGONTIME)) {
520 ret |= pdb_samba_dsdb_add_time(msg, "lastLogon",
521 pdb_get_logon_time(sam));
524 if (need_update(sam, PDB_LOGOFFTIME)) {
525 ret |= pdb_samba_dsdb_add_time(msg, "lastLogoff",
526 pdb_get_logoff_time(sam));
529 if (need_update(sam, PDB_USERNAME)) {
530 ret |= ldb_msg_add_string(msg, "samAccountName",
531 pdb_get_username(sam));
534 if (need_update(sam, PDB_HOURSLEN) || need_update(sam, PDB_HOURS)) {
535 struct ldb_val hours = data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam));
536 ret |= ldb_msg_add_value(msg, "logonHours",
537 &hours, NULL);
540 if (need_update(sam, PDB_ACCTCTRL)) {
541 ret |= samdb_msg_add_acct_flags(state->ldb, msg, msg,
542 "userAccountControl", pdb_get_acct_ctrl(sam));
545 if (need_update(sam, PDB_COMMENT)) {
546 ret |= ldb_msg_add_string(msg, "comment",
547 pdb_get_comment(sam));
550 if (need_update(sam, PDB_ACCTDESC)) {
551 ret |= ldb_msg_add_string(msg, "description",
552 pdb_get_acct_desc(sam));
555 if (need_update(sam, PDB_WORKSTATIONS)) {
556 ret |= ldb_msg_add_string(msg, "userWorkstations",
557 pdb_get_workstations(sam));
560 /* This will need work, it is actually a UTF8 'string' with internal NULLs, to handle TS parameters */
561 if (need_update(sam, PDB_MUNGEDDIAL)) {
562 const char *base64_munged_dial = NULL;
564 base64_munged_dial = pdb_get_munged_dial(sam);
565 if (base64_munged_dial != NULL && strlen(base64_munged_dial) > 0) {
566 struct ldb_val blob;
568 blob = base64_decode_data_blob_talloc(msg,
569 base64_munged_dial);
570 if (blob.data == NULL) {
571 DEBUG(0, ("Failed to decode userParameters from "
572 "munged dialback string[%s] for %s\n",
573 base64_munged_dial,
574 ldb_dn_get_linearized(msg->dn)));
575 talloc_free(frame);
576 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
578 ret |= ldb_msg_add_steal_value(msg, "userParameters",
579 &blob);
583 if (need_update(sam, PDB_COUNTRY_CODE)) {
584 ret |= ldb_msg_add_fmt(msg, "countryCode",
585 "%i", (int)pdb_get_country_code(sam));
588 if (need_update(sam, PDB_CODE_PAGE)) {
589 ret |= ldb_msg_add_fmt(msg, "codePage",
590 "%i", (int)pdb_get_code_page(sam));
593 /* Not yet handled here or not meaningful for modifies on a Samba_Dsdb backend:
594 PDB_BAD_PASSWORD_TIME,
595 PDB_CANCHANGETIME, - these are calculated per policy, not stored
596 PDB_DOMAIN,
597 PDB_NTUSERNAME, - this makes no sense, and never really did
598 PDB_LOGONDIVS,
599 PDB_USERSID, - Handled in pdb_samba_dsdb_add_sam_account()
600 PDB_FIELDS_PRESENT,
601 PDB_BAD_PASSWORD_COUNT,
602 PDB_LOGON_COUNT,
603 PDB_UNKNOWN6,
604 PDB_BACKEND_PRIVATE_DATA,
607 if (ret != LDB_SUCCESS) {
608 talloc_free(frame);
609 return LDB_ERR_OPERATIONS_ERROR;
612 if (msg->num_elements == 0) {
613 talloc_free(frame);
614 /* Nothing to do, just return success */
615 return LDB_SUCCESS;
618 ret = dsdb_replace(state->ldb, msg, dsdb_flags);
620 if (ret != LDB_SUCCESS) {
621 DEBUG(0,("Failed to modify account record %s to set user attributes: %s\n",
622 ldb_dn_get_linearized(msg->dn),
623 ldb_errstring(state->ldb)));
626 talloc_free(frame);
627 return ret;
630 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
631 const char *filter,
632 TALLOC_CTX *mem_ctx,
633 struct ldb_message **msg)
635 const char * attrs[] = {
636 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
637 "sAMAccountName", "displayName", "homeDirectory",
638 "homeDrive", "scriptPath", "profilePath", "description",
639 "userWorkstations", "comment", "userParameters", "objectSid",
640 "primaryGroupID", "userAccountControl",
641 "msDS-User-Account-Control-Computed", "logonHours",
642 "badPwdCount", "logonCount", "countryCode", "codePage",
643 "unicodePwd", "dBCSPwd", NULL };
645 int rc = dsdb_search_one(state->ldb, mem_ctx, msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter);
646 if (rc != LDB_SUCCESS) {
647 DEBUG(10, ("ldap_search failed %s\n",
648 ldb_errstring(state->ldb)));
649 return NT_STATUS_LDAP(rc);
652 return NT_STATUS_OK;
655 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
656 struct pdb_samba_dsdb_state *state,
657 struct samu *sam_acct,
658 const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
660 struct ldb_message *priv;
661 NTSTATUS status;
662 va_list ap;
663 char *expression = NULL;
664 TALLOC_CTX *tmp_ctx = talloc_new(state);
665 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
667 va_start(ap, exp_fmt);
668 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
669 va_end(ap);
671 if (!expression) {
672 talloc_free(tmp_ctx);
673 return NT_STATUS_NO_MEMORY;
676 status = pdb_samba_dsdb_getsamupriv(state, expression, sam_acct, &priv);
677 talloc_free(tmp_ctx);
678 if (!NT_STATUS_IS_OK(status)) {
679 DEBUG(10, ("pdb_samba_dsdb_getsamupriv failed: %s\n",
680 nt_errstr(status)));
681 return status;
684 status = pdb_samba_dsdb_init_sam_from_priv(m, sam_acct, priv);
685 if (!NT_STATUS_IS_OK(status)) {
686 DEBUG(10, ("pdb_samba_dsdb_init_sam_from_priv failed: %s\n",
687 nt_errstr(status)));
688 TALLOC_FREE(priv);
689 return status;
692 pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
693 return NT_STATUS_OK;
696 static NTSTATUS pdb_samba_dsdb_getsampwnam(struct pdb_methods *m,
697 struct samu *sam_acct,
698 const char *username)
700 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
701 m->private_data, struct pdb_samba_dsdb_state);
703 return pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
704 "(&(samaccountname=%s)(objectclass=user))",
705 username);
708 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
709 struct samu *sam_acct,
710 const struct dom_sid *sid)
712 NTSTATUS status;
713 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
714 m->private_data, struct pdb_samba_dsdb_state);
715 char *sidstr;
717 sidstr = dom_sid_string(talloc_tos(), sid);
718 NT_STATUS_HAVE_NO_MEMORY(sidstr);
720 status = pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
721 "(&(objectsid=%s)(objectclass=user))",
722 sidstr);
723 talloc_free(sidstr);
724 return status;
727 static NTSTATUS pdb_samba_dsdb_create_user(struct pdb_methods *m,
728 TALLOC_CTX *mem_ctx,
729 const char *name, uint32 acct_flags,
730 uint32 *rid)
732 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
733 m->private_data, struct pdb_samba_dsdb_state);
734 struct dom_sid *sid;
735 struct ldb_dn *dn;
736 NTSTATUS status;
737 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
738 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
740 /* Internally this uses transactions to ensure all the steps
741 * happen or fail as one */
742 status = dsdb_add_user(state->ldb, tmp_ctx, name, acct_flags, NULL,
743 &sid, &dn);
744 if (!NT_STATUS_IS_OK(status)) {
745 talloc_free(tmp_ctx);
746 return status;
748 sid_peek_rid(sid, rid);
749 talloc_free(tmp_ctx);
750 return NT_STATUS_OK;
753 static NTSTATUS pdb_samba_dsdb_delete_user(struct pdb_methods *m,
754 TALLOC_CTX *mem_ctx,
755 struct samu *sam)
757 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
758 m->private_data, struct pdb_samba_dsdb_state);
759 struct ldb_dn *dn;
760 int rc;
761 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
762 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
764 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, pdb_get_user_sid(sam)));
765 if (!dn || !ldb_dn_validate(dn)) {
766 talloc_free(tmp_ctx);
767 return NT_STATUS_NO_MEMORY;
769 rc = ldb_delete(state->ldb, dn);
771 if (rc != LDB_SUCCESS) {
772 DEBUG(10, ("ldb_delete for %s failed: %s\n", ldb_dn_get_linearized(dn),
773 ldb_errstring(state->ldb)));
774 talloc_free(tmp_ctx);
775 return NT_STATUS_LDAP(rc);
777 talloc_free(tmp_ctx);
778 return NT_STATUS_OK;
781 /* This interface takes a fully populated struct samu and places it in
782 * the database. This is not implemented at this time as we need to
783 * be careful around the creation of arbitary SIDs (ie, we must ensrue
784 * they are not left in a RID pool */
785 static NTSTATUS pdb_samba_dsdb_add_sam_account(struct pdb_methods *m,
786 struct samu *sampass)
788 int ret;
789 NTSTATUS status;
790 struct ldb_dn *dn;
791 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
792 m->private_data, struct pdb_samba_dsdb_state);
793 uint32_t acb_flags = pdb_get_acct_ctrl(sampass);
794 const char *username = pdb_get_username(sampass);
795 const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
796 TALLOC_CTX *tframe = talloc_stackframe();
798 acb_flags &= (ACB_NORMAL|ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST);
800 ret = ldb_transaction_start(state->ldb);
801 if (ret != LDB_SUCCESS) {
802 talloc_free(tframe);
803 return NT_STATUS_LOCK_NOT_GRANTED;
806 status = dsdb_add_user(state->ldb, talloc_tos(), username,
807 acb_flags, user_sid, NULL, &dn);
808 if (!NT_STATUS_IS_OK(status)) {
809 ldb_transaction_cancel(state->ldb);
810 talloc_free(tframe);
811 return status;
814 ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_set_or_changed,
815 dn, sampass);
816 if (ret != LDB_SUCCESS) {
817 ldb_transaction_cancel(state->ldb);
818 talloc_free(tframe);
819 return dsdb_ldb_err_to_ntstatus(ret);
822 ret = ldb_transaction_commit(state->ldb);
823 if (ret != LDB_SUCCESS) {
824 DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
825 ldb_dn_get_linearized(dn),
826 ldb_errstring(state->ldb)));
827 talloc_free(tframe);
828 return NT_STATUS_INTERNAL_DB_CORRUPTION;
830 talloc_free(tframe);
831 return NT_STATUS_OK;
835 * Update the Samba_Dsdb LDB with the changes from a struct samu.
837 * This takes care not to update elements that have not been changed
838 * by the caller
840 static NTSTATUS pdb_samba_dsdb_update_sam_account(struct pdb_methods *m,
841 struct samu *sam)
843 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
844 m->private_data, struct pdb_samba_dsdb_state);
845 struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
846 m, sam);
847 int ret;
849 ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_changed, msg->dn,
850 sam);
851 return dsdb_ldb_err_to_ntstatus(ret);
854 static NTSTATUS pdb_samba_dsdb_delete_sam_account(struct pdb_methods *m,
855 struct samu *username)
857 NTSTATUS status;
858 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
859 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
860 status = pdb_samba_dsdb_delete_user(m, tmp_ctx, username);
861 talloc_free(tmp_ctx);
862 return status;
865 static NTSTATUS pdb_samba_dsdb_rename_sam_account(struct pdb_methods *m,
866 struct samu *oldname,
867 const char *newname)
869 return NT_STATUS_NOT_IMPLEMENTED;
872 /* This is not implemented, as this module is exptected to be used
873 * with auth_samba_dsdb, and this is responible for login counters etc
876 static NTSTATUS pdb_samba_dsdb_update_login_attempts(struct pdb_methods *m,
877 struct samu *sam_acct,
878 bool success)
880 return NT_STATUS_NOT_IMPLEMENTED;
883 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
884 const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
886 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
887 m->private_data, struct pdb_samba_dsdb_state);
888 const char *attrs[] = { "objectSid", "description", "samAccountName", "groupType",
889 NULL };
890 struct ldb_message *msg;
891 va_list ap;
892 char *expression = NULL;
893 struct dom_sid *sid;
894 const char *str;
895 int rc;
896 struct id_map id_map;
897 struct id_map *id_maps[2];
898 TALLOC_CTX *tmp_ctx = talloc_stackframe();
899 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
901 va_start(ap, exp_fmt);
902 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
903 va_end(ap);
905 if (!expression) {
906 talloc_free(tmp_ctx);
907 return NT_STATUS_NO_MEMORY;
910 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
911 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
912 talloc_free(tmp_ctx);
913 return NT_STATUS_NO_SUCH_GROUP;
914 } else if (rc != LDB_SUCCESS) {
915 talloc_free(tmp_ctx);
916 DEBUG(10, ("dsdb_search_one failed %s\n",
917 ldb_errstring(state->ldb)));
918 return NT_STATUS_LDAP(rc);
921 sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
922 if (!sid) {
923 talloc_free(tmp_ctx);
924 DEBUG(10, ("Could not pull SID\n"));
925 return NT_STATUS_INTERNAL_DB_CORRUPTION;
928 map->sid = *sid;
930 if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) {
931 NTSTATUS status;
932 uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0);
933 switch (grouptype) {
934 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
935 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
936 map->sid_name_use = SID_NAME_ALIAS;
937 break;
938 case GTYPE_SECURITY_GLOBAL_GROUP:
939 map->sid_name_use = SID_NAME_DOM_GRP;
940 break;
941 default:
942 talloc_free(tmp_ctx);
943 DEBUG(10, ("Could not pull groupType\n"));
944 return NT_STATUS_INTERNAL_DB_CORRUPTION;
947 map->sid_name_use = SID_NAME_DOM_GRP;
949 ZERO_STRUCT(id_map);
950 id_map.sid = sid;
951 id_maps[0] = &id_map;
952 id_maps[1] = NULL;
954 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
955 talloc_free(tmp_ctx);
956 if (!NT_STATUS_IS_OK(status)) {
957 talloc_free(tmp_ctx);
958 return status;
960 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
961 map->gid = id_map.xid.id;
962 } else {
963 DEBUG(1, (__location__ "Did not get GUID when mapping SID for %s", expression));
964 talloc_free(tmp_ctx);
965 return NT_STATUS_INTERNAL_DB_CORRUPTION;
967 } else if (samdb_find_attribute(state->ldb, msg, "objectClass", "user")) {
968 DEBUG(1, (__location__ "Got SID_NAME_USER when searching for a group with %s", expression));
969 talloc_free(tmp_ctx);
970 return NT_STATUS_INTERNAL_DB_CORRUPTION;
973 str = ldb_msg_find_attr_as_string(msg, "samAccountName",
974 NULL);
975 if (str == NULL) {
976 talloc_free(tmp_ctx);
977 return NT_STATUS_INTERNAL_DB_CORRUPTION;
979 map->nt_name = talloc_strdup(map, str);
980 if (!map->nt_name) {
981 talloc_free(tmp_ctx);
982 return NT_STATUS_NO_MEMORY;
985 str = ldb_msg_find_attr_as_string(msg, "description",
986 NULL);
987 if (str != NULL) {
988 map->comment = talloc_strdup(map, str);
989 } else {
990 map->comment = talloc_strdup(map, "");
992 if (!map->comment) {
993 talloc_free(tmp_ctx);
994 return NT_STATUS_NO_MEMORY;
997 talloc_free(tmp_ctx);
998 return NT_STATUS_OK;
1001 static NTSTATUS pdb_samba_dsdb_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
1002 struct dom_sid sid)
1004 char *filter;
1005 NTSTATUS status;
1007 filter = talloc_asprintf(talloc_tos(),
1008 "(&(objectsid=%s)(objectclass=group))",
1009 sid_string_talloc(talloc_tos(), &sid));
1010 if (filter == NULL) {
1011 return NT_STATUS_NO_MEMORY;
1014 status = pdb_samba_dsdb_getgrfilter(m, map, filter);
1015 TALLOC_FREE(filter);
1016 return status;
1019 static NTSTATUS pdb_samba_dsdb_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
1020 gid_t gid)
1022 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1023 m->private_data, struct pdb_samba_dsdb_state);
1024 NTSTATUS status;
1025 struct id_map id_map;
1026 struct id_map *id_maps[2];
1027 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1028 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1030 id_map.xid.id = gid;
1031 id_map.xid.type = ID_TYPE_GID;
1032 id_maps[0] = &id_map;
1033 id_maps[1] = NULL;
1035 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
1036 if (!NT_STATUS_IS_OK(status)) {
1037 talloc_free(tmp_ctx);
1038 return status;
1040 status = pdb_samba_dsdb_getgrsid(m, map, *id_map.sid);
1041 talloc_free(tmp_ctx);
1042 return status;
1045 static NTSTATUS pdb_samba_dsdb_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
1046 const char *name)
1048 char *filter;
1049 NTSTATUS status;
1051 filter = talloc_asprintf(talloc_tos(),
1052 "(&(samaccountname=%s)(objectclass=group))",
1053 name);
1054 if (filter == NULL) {
1055 return NT_STATUS_NO_MEMORY;
1058 status = pdb_samba_dsdb_getgrfilter(m, map, filter);
1059 TALLOC_FREE(filter);
1060 return status;
1063 static NTSTATUS pdb_samba_dsdb_create_dom_group(struct pdb_methods *m,
1064 TALLOC_CTX *mem_ctx, const char *name,
1065 uint32 *rid)
1067 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1068 m->private_data, struct pdb_samba_dsdb_state);
1069 NTSTATUS status;
1070 struct dom_sid *sid;
1071 struct ldb_dn *dn;
1072 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1073 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1075 status = dsdb_add_domain_group(state->ldb, tmp_ctx, name, &sid, &dn);
1076 if (!NT_STATUS_IS_OK(status)) {
1077 talloc_free(tmp_ctx);
1078 return status;
1081 sid_peek_rid(sid, rid);
1082 talloc_free(tmp_ctx);
1083 return NT_STATUS_OK;
1086 static NTSTATUS pdb_samba_dsdb_delete_dom_group(struct pdb_methods *m,
1087 TALLOC_CTX *mem_ctx, uint32 rid)
1089 const char *attrs[] = { NULL };
1090 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1091 m->private_data, struct pdb_samba_dsdb_state);
1092 struct dom_sid sid;
1093 struct ldb_message *msg;
1094 struct ldb_dn *dn;
1095 int rc;
1096 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1097 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1099 sid_compose(&sid, samdb_domain_sid(state->ldb), rid);
1101 if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1102 DEBUG(0, ("Unable to start transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1103 return NT_STATUS_INTERNAL_ERROR;
1106 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, &sid));
1107 if (!dn || !ldb_dn_validate(dn)) {
1108 talloc_free(tmp_ctx);
1109 ldb_transaction_cancel(state->ldb);
1110 return NT_STATUS_NO_MEMORY;
1112 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "objectclass=group");
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;
1118 rc = ldb_delete(state->ldb, dn);
1119 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1120 talloc_free(tmp_ctx);
1121 ldb_transaction_cancel(state->ldb);
1122 return NT_STATUS_NO_SUCH_GROUP;
1123 } else if (rc != LDB_SUCCESS) {
1124 DEBUG(10, ("ldb_delete failed %s\n",
1125 ldb_errstring(state->ldb)));
1126 ldb_transaction_cancel(state->ldb);
1127 return NT_STATUS_LDAP(rc);
1130 if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1131 DEBUG(0, ("Unable to commit transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1132 return NT_STATUS_INTERNAL_ERROR;
1134 return NT_STATUS_OK;
1137 static NTSTATUS pdb_samba_dsdb_add_group_mapping_entry(struct pdb_methods *m,
1138 GROUP_MAP *map)
1140 return NT_STATUS_NOT_IMPLEMENTED;
1143 static NTSTATUS pdb_samba_dsdb_update_group_mapping_entry(struct pdb_methods *m,
1144 GROUP_MAP *map)
1146 return NT_STATUS_NOT_IMPLEMENTED;
1149 static NTSTATUS pdb_samba_dsdb_delete_group_mapping_entry(struct pdb_methods *m,
1150 struct dom_sid sid)
1152 return NT_STATUS_NOT_IMPLEMENTED;
1155 static NTSTATUS pdb_samba_dsdb_enum_group_mapping(struct pdb_methods *m,
1156 const struct dom_sid *sid,
1157 enum lsa_SidType sid_name_use,
1158 GROUP_MAP ***pp_rmap,
1159 size_t *p_num_entries,
1160 bool unix_only)
1162 return NT_STATUS_NOT_IMPLEMENTED;
1165 static NTSTATUS pdb_samba_dsdb_enum_group_members(struct pdb_methods *m,
1166 TALLOC_CTX *mem_ctx,
1167 const struct dom_sid *group,
1168 uint32_t **pmembers,
1169 size_t *pnum_members)
1171 unsigned int i, num_sids, num_members;
1172 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1173 m->private_data, struct pdb_samba_dsdb_state);
1174 struct dom_sid *members_as_sids;
1175 struct dom_sid *dom_sid;
1176 uint32_t *members;
1177 struct ldb_dn *dn;
1178 NTSTATUS status;
1180 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1181 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1183 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, group));
1184 if (!dn || !ldb_dn_validate(dn)) {
1185 return NT_STATUS_NO_MEMORY;
1188 status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
1189 if (!NT_STATUS_IS_OK(status)) {
1190 talloc_free(tmp_ctx);
1191 return status;
1193 status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
1194 if (!NT_STATUS_IS_OK(status)) {
1195 talloc_free(tmp_ctx);
1196 return status;
1199 *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
1200 if (*pmembers == NULL) {
1201 TALLOC_FREE(tmp_ctx);
1202 return NT_STATUS_NO_MEMORY;
1204 num_members = 0;
1206 for (i = 0; i < num_sids; i++) {
1207 if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
1208 continue;
1210 status = dom_sid_split_rid(NULL, &members_as_sids[i],
1211 NULL, &members[num_members]);
1212 if (!NT_STATUS_IS_OK(status)) {
1213 talloc_free(tmp_ctx);
1214 return status;
1216 num_members++;
1218 *pnum_members = num_members;
1219 return NT_STATUS_OK;
1222 /* Just convert the primary group SID into a group */
1223 static NTSTATUS fake_enum_group_memberships(struct pdb_samba_dsdb_state *state,
1224 TALLOC_CTX *mem_ctx,
1225 struct samu *user,
1226 struct dom_sid **pp_sids,
1227 gid_t **pp_gids,
1228 uint32_t *p_num_groups)
1230 NTSTATUS status;
1231 size_t num_groups = 0;
1232 struct dom_sid *group_sids = NULL;
1233 gid_t *gids = NULL;
1234 TALLOC_CTX *tmp_ctx;
1236 tmp_ctx = talloc_new(mem_ctx);
1237 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1239 if (user->group_sid) {
1240 struct id_map *id_maps[2];
1241 struct id_map id_map;
1243 num_groups = 1;
1245 group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
1246 if (group_sids == NULL) {
1247 talloc_free(tmp_ctx);
1248 return NT_STATUS_NO_MEMORY;
1250 gids = talloc_array(tmp_ctx, gid_t, num_groups);
1251 if (gids == NULL) {
1252 talloc_free(tmp_ctx);
1253 return NT_STATUS_NO_MEMORY;
1256 group_sids[0] = *user->group_sid;
1258 ZERO_STRUCT(id_map);
1259 id_map.sid = &group_sids[0];
1260 id_maps[0] = &id_map;
1261 id_maps[1] = NULL;
1263 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1264 if (!NT_STATUS_IS_OK(status)) {
1265 talloc_free(tmp_ctx);
1266 return status;
1268 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1269 gids[0] = id_map.xid.id;
1270 } else {
1271 DEBUG(1, (__location__
1272 "Group %s, of which %s is a member, could not be converted to a GID\n",
1273 dom_sid_string(tmp_ctx, &group_sids[0]),
1274 dom_sid_string(tmp_ctx, &user->user_sid)));
1275 talloc_free(tmp_ctx);
1276 /* We must error out, otherwise a user might
1277 * avoid a DENY acl based on a group they
1278 * missed out on */
1279 return NT_STATUS_NO_SUCH_GROUP;
1283 *pp_sids = talloc_steal(mem_ctx, group_sids);
1284 *pp_gids = talloc_steal(mem_ctx, gids);
1285 *p_num_groups = num_groups;
1286 talloc_free(tmp_ctx);
1287 return NT_STATUS_OK;
1290 static NTSTATUS pdb_samba_dsdb_enum_group_memberships(struct pdb_methods *m,
1291 TALLOC_CTX *mem_ctx,
1292 struct samu *user,
1293 struct dom_sid **pp_sids,
1294 gid_t **pp_gids,
1295 uint32_t *p_num_groups)
1297 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1298 m->private_data, struct pdb_samba_dsdb_state);
1299 struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
1300 m, user);
1301 const char *attrs[] = { "tokenGroups", NULL};
1302 struct ldb_message *tokengroups_msg;
1303 struct ldb_message_element *tokengroups;
1304 int i, rc;
1305 NTSTATUS status;
1306 unsigned int count = 0;
1307 size_t num_groups;
1308 struct dom_sid *group_sids;
1309 gid_t *gids;
1310 TALLOC_CTX *tmp_ctx;
1312 if (msg == NULL) {
1313 /* Fake up some things here */
1314 return fake_enum_group_memberships(state,
1315 mem_ctx,
1316 user, pp_sids,
1317 pp_gids, p_num_groups);
1320 tmp_ctx = talloc_new(mem_ctx);
1321 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1323 rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
1325 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1326 talloc_free(tmp_ctx);
1327 return NT_STATUS_NO_SUCH_USER;
1328 } else if (rc != LDB_SUCCESS) {
1329 DEBUG(10, ("dsdb_search_one failed %s\n",
1330 ldb_errstring(state->ldb)));
1331 talloc_free(tmp_ctx);
1332 return NT_STATUS_LDAP(rc);
1335 tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
1337 if (tokengroups) {
1338 count = tokengroups->num_values;
1341 group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
1342 if (group_sids == NULL) {
1343 talloc_free(tmp_ctx);
1344 return NT_STATUS_NO_MEMORY;
1346 gids = talloc_array(tmp_ctx, gid_t, count);
1347 if (gids == NULL) {
1348 talloc_free(tmp_ctx);
1349 return NT_STATUS_NO_MEMORY;
1351 num_groups = 0;
1353 for (i=0; i<count; i++) {
1354 struct id_map *id_maps[2];
1355 struct id_map id_map;
1356 struct ldb_val *v = &tokengroups->values[i];
1357 enum ndr_err_code ndr_err
1358 = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
1359 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1360 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1361 talloc_free(tmp_ctx);
1362 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1365 ZERO_STRUCT(id_map);
1366 id_map.sid = &group_sids[num_groups];
1367 id_maps[0] = &id_map;
1368 id_maps[1] = NULL;
1370 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1371 if (!NT_STATUS_IS_OK(status)) {
1372 talloc_free(tmp_ctx);
1373 return status;
1375 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1376 gids[num_groups] = id_map.xid.id;
1377 } else {
1378 DEBUG(1, (__location__
1379 "Group %s, of which %s is a member, could not be converted to a GID\n",
1380 dom_sid_string(tmp_ctx, &group_sids[num_groups]),
1381 ldb_dn_get_linearized(msg->dn)));
1382 talloc_free(tmp_ctx);
1383 /* We must error out, otherwise a user might
1384 * avoid a DENY acl based on a group they
1385 * missed out on */
1386 return NT_STATUS_NO_SUCH_GROUP;
1389 num_groups += 1;
1390 if (num_groups == count) {
1391 break;
1395 *pp_sids = talloc_steal(mem_ctx, group_sids);
1396 *pp_gids = talloc_steal(mem_ctx, gids);
1397 *p_num_groups = num_groups;
1398 talloc_free(tmp_ctx);
1399 return NT_STATUS_OK;
1402 static NTSTATUS pdb_samba_dsdb_set_unix_primary_group(struct pdb_methods *m,
1403 TALLOC_CTX *mem_ctx,
1404 struct samu *user)
1406 return NT_STATUS_NOT_IMPLEMENTED;
1409 static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid(struct pdb_methods *m,
1410 TALLOC_CTX *mem_ctx,
1411 const struct dom_sid *groupsid,
1412 const struct dom_sid *membersid,
1413 int mod_op)
1415 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1416 m->private_data, struct pdb_samba_dsdb_state);
1417 struct ldb_message *msg;
1418 int ret;
1419 struct ldb_message_element *el;
1420 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1421 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1422 msg = ldb_msg_new(tmp_ctx);
1423 if (msg == NULL) {
1424 TALLOC_FREE(tmp_ctx);
1425 return NT_STATUS_NO_MEMORY;
1428 msg->dn = ldb_dn_new_fmt(msg, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, groupsid));
1429 if (!msg->dn || !ldb_dn_validate(msg->dn)) {
1430 talloc_free(tmp_ctx);
1431 return NT_STATUS_NO_MEMORY;
1433 ret = ldb_msg_add_fmt(msg, "member", "<SID=%s>", dom_sid_string(tmp_ctx, membersid));
1434 if (ret != LDB_SUCCESS) {
1435 talloc_free(tmp_ctx);
1436 return NT_STATUS_NO_MEMORY;
1438 el = ldb_msg_find_element(msg, "member");
1439 el->flags = mod_op;
1441 /* No need for transactions here, the ldb auto-transaction
1442 * code will handle things for the single operation */
1443 ret = ldb_modify(state->ldb, msg);
1444 talloc_free(tmp_ctx);
1445 if (ret != LDB_SUCCESS) {
1446 DEBUG(10, ("ldb_modify failed: %s\n",
1447 ldb_errstring(state->ldb)));
1448 if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
1449 return NT_STATUS_MEMBER_IN_GROUP;
1451 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1452 return NT_STATUS_MEMBER_NOT_IN_GROUP;
1454 return NT_STATUS_LDAP(ret);
1457 return NT_STATUS_OK;
1460 static NTSTATUS pdb_samba_dsdb_mod_groupmem(struct pdb_methods *m,
1461 TALLOC_CTX *mem_ctx,
1462 uint32 grouprid, uint32 memberrid,
1463 int mod_op)
1465 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1466 m->private_data, struct pdb_samba_dsdb_state);
1467 const struct dom_sid *dom_sid, *groupsid, *membersid;
1468 NTSTATUS status;
1469 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1470 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1472 dom_sid = samdb_domain_sid(state->ldb);
1474 groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
1475 if (groupsid == NULL) {
1476 TALLOC_FREE(tmp_ctx);
1477 return NT_STATUS_NO_MEMORY;
1479 membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
1480 if (membersid == NULL) {
1481 TALLOC_FREE(tmp_ctx);
1482 return NT_STATUS_NO_MEMORY;
1484 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
1485 talloc_free(tmp_ctx);
1486 return status;
1489 static NTSTATUS pdb_samba_dsdb_add_groupmem(struct pdb_methods *m,
1490 TALLOC_CTX *mem_ctx,
1491 uint32 group_rid, uint32 member_rid)
1493 return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1494 LDB_FLAG_MOD_ADD);
1497 static NTSTATUS pdb_samba_dsdb_del_groupmem(struct pdb_methods *m,
1498 TALLOC_CTX *mem_ctx,
1499 uint32 group_rid, uint32 member_rid)
1501 return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1502 LDB_FLAG_MOD_DELETE);
1505 static NTSTATUS pdb_samba_dsdb_create_alias(struct pdb_methods *m,
1506 const char *name, uint32 *rid)
1508 TALLOC_CTX *frame = talloc_stackframe();
1509 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1510 m->private_data, struct pdb_samba_dsdb_state);
1511 struct dom_sid *sid;
1513 struct ldb_dn *dn;
1514 NTSTATUS status;
1516 /* Internally this uses transactions to ensure all the steps
1517 * happen or fail as one */
1518 status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
1519 if (!NT_STATUS_IS_OK(status)) {
1520 TALLOC_FREE(frame);
1523 sid_peek_rid(sid, rid);
1524 TALLOC_FREE(frame);
1525 return NT_STATUS_OK;
1528 static NTSTATUS pdb_samba_dsdb_delete_alias(struct pdb_methods *m,
1529 const struct dom_sid *sid)
1531 const char *attrs[] = { NULL };
1532 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1533 m->private_data, struct pdb_samba_dsdb_state);
1534 struct ldb_message *msg;
1535 struct ldb_dn *dn;
1536 int rc;
1537 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1538 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1540 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, sid));
1541 if (!dn || !ldb_dn_validate(dn)) {
1542 talloc_free(tmp_ctx);
1543 return NT_STATUS_NO_MEMORY;
1546 if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1547 DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(state->ldb)));
1548 talloc_free(tmp_ctx);
1549 return NT_STATUS_INTERNAL_ERROR;
1552 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
1553 "(|(grouptype=%d)(grouptype=%d)))",
1554 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1555 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1556 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1557 talloc_free(tmp_ctx);
1558 ldb_transaction_cancel(state->ldb);
1559 return NT_STATUS_NO_SUCH_ALIAS;
1561 rc = ldb_delete(state->ldb, dn);
1562 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1563 talloc_free(tmp_ctx);
1564 ldb_transaction_cancel(state->ldb);
1565 return NT_STATUS_NO_SUCH_ALIAS;
1566 } else if (rc != LDB_SUCCESS) {
1567 DEBUG(10, ("ldb_delete failed %s\n",
1568 ldb_errstring(state->ldb)));
1569 ldb_transaction_cancel(state->ldb);
1570 talloc_free(tmp_ctx);
1571 return NT_STATUS_LDAP(rc);
1574 if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1575 DEBUG(0, ("Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s\n",
1576 ldb_errstring(state->ldb)));
1577 talloc_free(tmp_ctx);
1578 return NT_STATUS_INTERNAL_ERROR;
1581 talloc_free(tmp_ctx);
1582 return NT_STATUS_OK;
1585 #if 0
1586 static NTSTATUS pdb_samba_dsdb_set_aliasinfo(struct pdb_methods *m,
1587 const struct dom_sid *sid,
1588 struct acct_info *info)
1590 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1591 m->private_data, struct pdb_samba_dsdb_state);
1592 struct tldap_context *ld;
1593 const char *attrs[3] = { "objectSid", "description",
1594 "samAccountName" };
1595 struct ldb_message **msg;
1596 char *sidstr, *dn;
1597 int rc;
1598 struct tldap_mod *mods;
1599 int num_mods;
1600 bool ok;
1602 ld = pdb_samba_dsdb_ld(state);
1603 if (ld == NULL) {
1604 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1607 sidstr = sid_binstring(talloc_tos(), sid);
1608 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1610 rc = pdb_samba_dsdb_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1611 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1612 &msg, "(&(objectSid=%s)(objectclass=group)"
1613 "(|(grouptype=%d)(grouptype=%d)))",
1614 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1615 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1616 TALLOC_FREE(sidstr)
1617 if (rc != LDB_SUCCESS) {
1618 DEBUG(10, ("ldap_search failed %s\n",
1619 ldb_errstring(state->ldb)));
1620 return NT_STATUS_LDAP(rc);
1622 switch talloc_array_length(msg) {
1623 case 0:
1624 return NT_STATUS_NO_SUCH_ALIAS;
1625 case 1:
1626 break;
1627 default:
1628 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1631 if (!tldap_entry_dn(msg[0], &dn)) {
1632 TALLOC_FREE(msg);
1633 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1636 mods = NULL;
1637 num_mods = 0;
1638 ok = true;
1640 ok &= tldap_make_mod_fmt(
1641 msg[0], msg, &num_mods, &mods, "description",
1642 "%s", info->acct_desc);
1643 ok &= tldap_make_mod_fmt(
1644 msg[0], msg, &num_mods, &mods, "samAccountName",
1645 "%s", info->acct_name);
1646 if (!ok) {
1647 TALLOC_FREE(msg);
1648 return NT_STATUS_NO_MEMORY;
1650 if (num_mods == 0) {
1651 /* no change */
1652 TALLOC_FREE(msg);
1653 return NT_STATUS_OK;
1656 rc = tldap_modify(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
1657 TALLOC_FREE(msg);
1658 if (rc != LDB_SUCCESS) {
1659 DEBUG(10, ("ldap_modify failed: %s\n",
1660 ldb_errstring(state->ldb)));
1661 return NT_STATUS_LDAP(rc);
1663 return NT_STATUS_OK;
1665 #endif
1666 static NTSTATUS pdb_samba_dsdb_add_aliasmem(struct pdb_methods *m,
1667 const struct dom_sid *alias,
1668 const struct dom_sid *member)
1670 NTSTATUS status;
1671 TALLOC_CTX *frame = talloc_stackframe();
1672 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_ADD);
1673 talloc_free(frame);
1674 return status;
1677 static NTSTATUS pdb_samba_dsdb_del_aliasmem(struct pdb_methods *m,
1678 const struct dom_sid *alias,
1679 const struct dom_sid *member)
1681 NTSTATUS status;
1682 TALLOC_CTX *frame = talloc_stackframe();
1683 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
1684 talloc_free(frame);
1685 return status;
1688 static NTSTATUS pdb_samba_dsdb_enum_aliasmem(struct pdb_methods *m,
1689 const struct dom_sid *alias,
1690 TALLOC_CTX *mem_ctx,
1691 struct dom_sid **pmembers,
1692 size_t *pnum_members)
1694 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1695 m->private_data, struct pdb_samba_dsdb_state);
1696 struct ldb_dn *dn;
1697 unsigned int num_members;
1698 NTSTATUS status;
1699 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1700 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1702 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, alias));
1703 if (!dn || !ldb_dn_validate(dn)) {
1704 return NT_STATUS_NO_MEMORY;
1707 status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
1708 *pnum_members = num_members;
1709 if (NT_STATUS_IS_OK(status)) {
1710 talloc_steal(mem_ctx, pmembers);
1712 talloc_free(tmp_ctx);
1713 return status;
1716 static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1717 TALLOC_CTX *mem_ctx,
1718 const struct dom_sid *domain_sid,
1719 const struct dom_sid *members,
1720 size_t num_members,
1721 uint32_t **palias_rids,
1722 size_t *pnum_alias_rids)
1724 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1725 m->private_data, struct pdb_samba_dsdb_state);
1726 uint32_t *alias_rids = NULL;
1727 size_t num_alias_rids = 0;
1728 int i;
1729 struct dom_sid *groupSIDs = NULL;
1730 unsigned int num_groupSIDs = 0;
1731 char *filter;
1732 NTSTATUS status;
1733 const char *sid_string;
1734 const char *sid_dn;
1735 DATA_BLOB sid_blob;
1737 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1738 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1740 * TODO: Get the filter right so that we only get the aliases from
1741 * either the SAM or BUILTIN
1744 filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
1745 GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1746 if (filter == NULL) {
1747 return NT_STATUS_NO_MEMORY;
1750 for (i = 0; i < num_members; i++) {
1751 sid_string = dom_sid_string(tmp_ctx, &members[i]);
1752 if (sid_string == NULL) {
1753 TALLOC_FREE(tmp_ctx);
1754 return NT_STATUS_NO_MEMORY;
1757 sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", sid_string);
1758 if (sid_dn == NULL) {
1759 TALLOC_FREE(tmp_ctx);
1760 return NT_STATUS_NO_MEMORY;
1763 sid_blob = data_blob_string_const(sid_dn);
1765 status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1766 tmp_ctx, &groupSIDs, &num_groupSIDs);
1767 if (!NT_STATUS_IS_OK(status)) {
1768 talloc_free(tmp_ctx);
1769 return status;
1773 alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1774 if (alias_rids == NULL) {
1775 talloc_free(tmp_ctx);
1776 return NT_STATUS_NO_MEMORY;
1779 for (i=0; i<num_groupSIDs; i++) {
1780 if (sid_peek_check_rid(domain_sid, &groupSIDs[i],
1781 &alias_rids[num_alias_rids])) {
1782 num_alias_rids++;;
1786 *palias_rids = alias_rids;
1787 *pnum_alias_rids = num_alias_rids;
1788 return NT_STATUS_OK;
1791 static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1792 const struct dom_sid *domain_sid,
1793 int num_rids,
1794 uint32 *rids,
1795 const char **names,
1796 enum lsa_SidType *lsa_attrs)
1798 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1799 m->private_data, struct pdb_samba_dsdb_state);
1800 NTSTATUS status;
1802 TALLOC_CTX *tmp_ctx;
1804 if (num_rids == 0) {
1805 return NT_STATUS_NONE_MAPPED;
1808 tmp_ctx = talloc_stackframe();
1809 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1811 status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1812 talloc_free(tmp_ctx);
1813 return status;
1816 static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1817 const struct dom_sid *domain_sid,
1818 int num_names,
1819 const char **pp_names,
1820 uint32 *rids,
1821 enum lsa_SidType *attrs)
1823 return NT_STATUS_NOT_IMPLEMENTED;
1826 static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1827 enum pdb_policy_type type,
1828 uint32_t *value)
1830 return account_policy_get(type, value)
1831 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1834 static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1835 enum pdb_policy_type type,
1836 uint32_t value)
1838 return account_policy_set(type, value)
1839 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1842 static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1843 time_t *seq_num_out)
1845 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1846 m->private_data, struct pdb_samba_dsdb_state);
1847 uint64_t seq_num;
1848 int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1849 if (ret == LDB_SUCCESS) {
1850 *seq_num_out = seq_num;
1851 return NT_STATUS_OK;
1852 } else {
1853 return NT_STATUS_UNSUCCESSFUL;
1857 struct pdb_samba_dsdb_search_state {
1858 uint32_t acct_flags;
1859 struct samr_displayentry *entries;
1860 uint32_t num_entries;
1861 ssize_t array_size;
1862 uint32_t current;
1865 static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1866 struct samr_displayentry *entry)
1868 struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1869 search->private_data, struct pdb_samba_dsdb_search_state);
1871 if (state->current == state->num_entries) {
1872 return false;
1875 entry->idx = state->entries[state->current].idx;
1876 entry->rid = state->entries[state->current].rid;
1877 entry->acct_flags = state->entries[state->current].acct_flags;
1879 entry->account_name = talloc_strdup(
1880 search, state->entries[state->current].account_name);
1881 entry->fullname = talloc_strdup(
1882 search, state->entries[state->current].fullname);
1883 entry->description = talloc_strdup(
1884 search, state->entries[state->current].description);
1886 state->current += 1;
1887 return true;
1890 static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1892 struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1893 search->private_data, struct pdb_samba_dsdb_search_state);
1894 talloc_free(state);
1897 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1898 struct pdb_search *search,
1899 struct pdb_samba_dsdb_search_state **pstate,
1900 const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
1902 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1903 m->private_data, struct pdb_samba_dsdb_state);
1904 struct pdb_samba_dsdb_search_state *sstate;
1905 const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1906 "userAccountControl", "description", NULL };
1907 struct ldb_result *res;
1908 int i, rc, num_users;
1910 va_list ap;
1911 char *expression = NULL;
1913 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1914 if (!tmp_ctx) {
1915 return false;
1918 va_start(ap, exp_fmt);
1919 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1920 va_end(ap);
1922 if (!expression) {
1923 talloc_free(tmp_ctx);
1924 return LDB_ERR_OPERATIONS_ERROR;
1927 sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1928 if (sstate == NULL) {
1929 talloc_free(tmp_ctx);
1930 return false;
1933 rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1934 if (rc != LDB_SUCCESS) {
1935 talloc_free(tmp_ctx);
1936 DEBUG(10, ("dsdb_search failed: %s\n",
1937 ldb_errstring(state->ldb)));
1938 return false;
1941 num_users = res->count;
1943 sstate->entries = talloc_array(sstate, struct samr_displayentry,
1944 num_users);
1945 if (sstate->entries == NULL) {
1946 talloc_free(tmp_ctx);
1947 DEBUG(10, ("talloc failed\n"));
1948 return false;
1951 sstate->num_entries = 0;
1953 for (i=0; i<num_users; i++) {
1954 struct samr_displayentry *e;
1955 struct dom_sid *sid;
1957 e = &sstate->entries[sstate->num_entries];
1959 e->idx = sstate->num_entries;
1960 sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
1961 if (!sid) {
1962 talloc_free(tmp_ctx);
1963 DEBUG(10, ("Could not pull SID\n"));
1964 return false;
1966 sid_peek_rid(sid, &e->rid);
1968 e->acct_flags = samdb_result_acct_flags(res->msgs[i], "userAccountControl");
1969 e->account_name = ldb_msg_find_attr_as_string(
1970 res->msgs[i], "samAccountName", NULL);
1971 if (e->account_name == NULL) {
1972 talloc_free(tmp_ctx);
1973 return false;
1975 e->fullname = ldb_msg_find_attr_as_string(
1976 res->msgs[i], "displayName", "");
1977 e->description = ldb_msg_find_attr_as_string(
1978 res->msgs[i], "description", "");
1980 sstate->num_entries += 1;
1981 if (sstate->num_entries >= num_users) {
1982 break;
1985 talloc_steal(sstate->entries, res->msgs);
1986 search->private_data = talloc_steal(search, sstate);
1987 search->next_entry = pdb_samba_dsdb_next_entry;
1988 search->search_end = pdb_samba_dsdb_search_end;
1989 *pstate = sstate;
1990 talloc_free(tmp_ctx);
1991 return true;
1994 static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
1995 struct pdb_search *search,
1996 uint32 acct_flags)
1998 struct pdb_samba_dsdb_search_state *sstate;
1999 bool ret;
2001 ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
2002 if (!ret) {
2003 return false;
2005 sstate->acct_flags = acct_flags;
2006 return true;
2009 static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
2010 struct pdb_search *search)
2012 struct pdb_samba_dsdb_search_state *sstate;
2013 bool ret;
2015 ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2016 "(&(grouptype=%d)(objectclass=group))",
2017 GTYPE_SECURITY_GLOBAL_GROUP);
2018 if (!ret) {
2019 return false;
2021 sstate->acct_flags = 0;
2022 return true;
2025 static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
2026 struct pdb_search *search,
2027 const struct dom_sid *sid)
2029 struct pdb_samba_dsdb_search_state *sstate;
2030 bool ret;
2032 ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2033 "(&(grouptype=%d)(objectclass=group))",
2034 sid_check_is_builtin(sid)
2035 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2036 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2037 if (!ret) {
2038 return false;
2040 sstate->acct_flags = 0;
2041 return true;
2044 static bool pdb_samba_dsdb_uid_to_sid(struct pdb_methods *m, uid_t uid,
2045 struct dom_sid *sid)
2047 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2048 m->private_data, struct pdb_samba_dsdb_state);
2049 NTSTATUS status;
2050 struct id_map id_map;
2051 struct id_map *id_maps[2];
2052 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2053 if (!tmp_ctx) {
2054 return false;
2057 id_map.xid.id = uid;
2058 id_map.xid.type = ID_TYPE_UID;
2059 id_maps[0] = &id_map;
2060 id_maps[1] = NULL;
2062 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2063 if (!NT_STATUS_IS_OK(status)) {
2064 talloc_free(tmp_ctx);
2065 return false;
2067 *sid = *id_map.sid;
2068 talloc_free(tmp_ctx);
2069 return true;
2072 static bool pdb_samba_dsdb_gid_to_sid(struct pdb_methods *m, gid_t gid,
2073 struct dom_sid *sid)
2075 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2076 m->private_data, struct pdb_samba_dsdb_state);
2077 NTSTATUS status;
2078 struct id_map id_map;
2079 struct id_map *id_maps[2];
2080 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2081 if (!tmp_ctx) {
2082 return false;
2085 id_map.xid.id = gid;
2086 id_map.xid.type = ID_TYPE_GID;
2087 id_maps[0] = &id_map;
2088 id_maps[1] = NULL;
2090 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2091 if (!NT_STATUS_IS_OK(status)) {
2092 talloc_free(tmp_ctx);
2093 return false;
2095 *sid = *id_map.sid;
2096 talloc_free(tmp_ctx);
2097 return true;
2100 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2101 struct unixid *id)
2103 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2104 m->private_data, struct pdb_samba_dsdb_state);
2105 struct id_map id_map;
2106 struct id_map *id_maps[2];
2107 NTSTATUS status;
2108 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2109 if (!tmp_ctx) {
2110 return false;
2113 ZERO_STRUCT(id_map);
2114 id_map.sid = discard_const_p(struct dom_sid, sid);
2115 id_maps[0] = &id_map;
2116 id_maps[1] = NULL;
2118 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2119 talloc_free(tmp_ctx);
2120 if (!NT_STATUS_IS_OK(status)) {
2121 return false;
2123 if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2124 *id = id_map.xid;
2125 return true;
2127 return false;
2130 static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2132 return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
2135 static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32 *rid)
2137 return false;
2140 static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2141 const char *domain, char** pwd,
2142 struct dom_sid *sid,
2143 time_t *pass_last_set_time)
2145 return false;
2148 static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2149 const char* domain, const char* pwd,
2150 const struct dom_sid *sid)
2152 return false;
2155 static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2156 const char *domain)
2158 return false;
2161 static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2162 TALLOC_CTX *mem_ctx,
2163 uint32 *num_domains,
2164 struct trustdom_info ***domains)
2166 *num_domains = 0;
2167 *domains = NULL;
2168 return NT_STATUS_OK;
2171 static bool pdb_samba_dsdb_is_responsible_for_wellknown(struct pdb_methods *m)
2173 return true;
2176 static bool pdb_samba_dsdb_is_responsible_for_everything_else(struct pdb_methods *m)
2178 return true;
2181 static void pdb_samba_dsdb_init_methods(struct pdb_methods *m)
2183 m->name = "samba_dsdb";
2184 m->get_domain_info = pdb_samba_dsdb_get_domain_info;
2185 m->getsampwnam = pdb_samba_dsdb_getsampwnam;
2186 m->getsampwsid = pdb_samba_dsdb_getsampwsid;
2187 m->create_user = pdb_samba_dsdb_create_user;
2188 m->delete_user = pdb_samba_dsdb_delete_user;
2189 m->add_sam_account = pdb_samba_dsdb_add_sam_account;
2190 m->update_sam_account = pdb_samba_dsdb_update_sam_account;
2191 m->delete_sam_account = pdb_samba_dsdb_delete_sam_account;
2192 m->rename_sam_account = pdb_samba_dsdb_rename_sam_account;
2193 m->update_login_attempts = pdb_samba_dsdb_update_login_attempts;
2194 m->getgrsid = pdb_samba_dsdb_getgrsid;
2195 m->getgrgid = pdb_samba_dsdb_getgrgid;
2196 m->getgrnam = pdb_samba_dsdb_getgrnam;
2197 m->create_dom_group = pdb_samba_dsdb_create_dom_group;
2198 m->delete_dom_group = pdb_samba_dsdb_delete_dom_group;
2199 m->add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry;
2200 m->update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry;
2201 m->delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry;
2202 m->enum_group_mapping = pdb_samba_dsdb_enum_group_mapping;
2203 m->enum_group_members = pdb_samba_dsdb_enum_group_members;
2204 m->enum_group_memberships = pdb_samba_dsdb_enum_group_memberships;
2205 m->set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group;
2206 m->add_groupmem = pdb_samba_dsdb_add_groupmem;
2207 m->del_groupmem = pdb_samba_dsdb_del_groupmem;
2208 m->create_alias = pdb_samba_dsdb_create_alias;
2209 m->delete_alias = pdb_samba_dsdb_delete_alias;
2210 m->get_aliasinfo = pdb_default_get_aliasinfo;
2211 m->add_aliasmem = pdb_samba_dsdb_add_aliasmem;
2212 m->del_aliasmem = pdb_samba_dsdb_del_aliasmem;
2213 m->enum_aliasmem = pdb_samba_dsdb_enum_aliasmem;
2214 m->enum_alias_memberships = pdb_samba_dsdb_enum_alias_memberships;
2215 m->lookup_rids = pdb_samba_dsdb_lookup_rids;
2216 m->lookup_names = pdb_samba_dsdb_lookup_names;
2217 m->get_account_policy = pdb_samba_dsdb_get_account_policy;
2218 m->set_account_policy = pdb_samba_dsdb_set_account_policy;
2219 m->get_seq_num = pdb_samba_dsdb_get_seq_num;
2220 m->search_users = pdb_samba_dsdb_search_users;
2221 m->search_groups = pdb_samba_dsdb_search_groups;
2222 m->search_aliases = pdb_samba_dsdb_search_aliases;
2223 m->uid_to_sid = pdb_samba_dsdb_uid_to_sid;
2224 m->gid_to_sid = pdb_samba_dsdb_gid_to_sid;
2225 m->sid_to_id = pdb_samba_dsdb_sid_to_id;
2226 m->capabilities = pdb_samba_dsdb_capabilities;
2227 m->new_rid = pdb_samba_dsdb_new_rid;
2228 m->get_trusteddom_pw = pdb_samba_dsdb_get_trusteddom_pw;
2229 m->set_trusteddom_pw = pdb_samba_dsdb_set_trusteddom_pw;
2230 m->del_trusteddom_pw = pdb_samba_dsdb_del_trusteddom_pw;
2231 m->enum_trusteddoms = pdb_samba_dsdb_enum_trusteddoms;
2232 m->is_responsible_for_wellknown =
2233 pdb_samba_dsdb_is_responsible_for_wellknown;
2234 m->is_responsible_for_everything_else =
2235 pdb_samba_dsdb_is_responsible_for_everything_else;
2238 static void free_private_data(void **vp)
2240 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2241 *vp, struct pdb_samba_dsdb_state);
2242 talloc_unlink(state, state->ldb);
2243 return;
2246 static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m)
2248 struct pdb_domain_info *dom_info;
2249 struct dom_sid stored_sid;
2250 struct GUID stored_guid;
2251 bool sid_exists_and_matches = false;
2252 bool guid_exists_and_matches = false;
2253 bool ret;
2255 dom_info = pdb_samba_dsdb_get_domain_info(m, m);
2256 if (!dom_info) {
2257 return NT_STATUS_UNSUCCESSFUL;
2260 ret = secrets_fetch_domain_sid(dom_info->name, &stored_sid);
2261 if (ret) {
2262 if (dom_sid_equal(&stored_sid, &dom_info->sid)) {
2263 sid_exists_and_matches = true;
2267 if (sid_exists_and_matches == false) {
2268 secrets_clear_domain_protection(dom_info->name);
2269 ret = secrets_store_domain_sid(dom_info->name,
2270 &dom_info->sid);
2271 ret &= secrets_mark_domain_protected(dom_info->name);
2272 if (!ret) {
2273 goto done;
2277 ret = secrets_fetch_domain_guid(dom_info->name, &stored_guid);
2278 if (ret) {
2279 if (GUID_equal(&stored_guid, &dom_info->guid)) {
2280 guid_exists_and_matches = true;
2284 if (guid_exists_and_matches == false) {
2285 secrets_clear_domain_protection(dom_info->name);
2286 ret = secrets_store_domain_guid(dom_info->name,
2287 &dom_info->guid);
2288 ret &= secrets_mark_domain_protected(dom_info->name);
2289 if (!ret) {
2290 goto done;
2294 done:
2295 TALLOC_FREE(dom_info);
2296 if (!ret) {
2297 return NT_STATUS_UNSUCCESSFUL;
2299 return NT_STATUS_OK;
2302 static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
2303 const char *location)
2305 struct pdb_methods *m;
2306 struct pdb_samba_dsdb_state *state;
2307 NTSTATUS status;
2309 if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
2310 return status;
2313 state = talloc_zero(m, struct pdb_samba_dsdb_state);
2314 if (state == NULL) {
2315 goto nomem;
2317 m->private_data = state;
2318 m->free_private_data = free_private_data;
2319 pdb_samba_dsdb_init_methods(m);
2321 state->ev = s4_event_context_init(state);
2322 if (!state->ev) {
2323 DEBUG(0, ("s4_event_context_init failed\n"));
2324 goto nomem;
2327 state->lp_ctx = loadparm_init_s3(state, loadparm_s3_helpers());
2328 if (state->lp_ctx == NULL) {
2329 DEBUG(0, ("loadparm_init_s3 failed\n"));
2330 goto nomem;
2333 if (location) {
2334 state->ldb = samdb_connect_url(state,
2335 state->ev,
2336 state->lp_ctx,
2337 system_session(state->lp_ctx),
2338 0, location);
2339 } else {
2340 state->ldb = samdb_connect(state,
2341 state->ev,
2342 state->lp_ctx,
2343 system_session(state->lp_ctx), 0);
2346 if (!state->ldb) {
2347 DEBUG(0, ("samdb_connect failed\n"));
2348 status = NT_STATUS_INTERNAL_ERROR;
2349 goto fail;
2352 state->idmap_ctx = idmap_init(state, state->ev,
2353 state->lp_ctx);
2354 if (!state->idmap_ctx) {
2355 DEBUG(0, ("idmap failed\n"));
2356 status = NT_STATUS_INTERNAL_ERROR;
2357 goto fail;
2360 status = pdb_samba_dsdb_init_secrets(m);
2361 if (!NT_STATUS_IS_OK(status)) {
2362 DEBUG(10, ("pdb_samba_dsdb_init_secrets failed!\n"));
2363 goto fail;
2366 *pdb_method = m;
2367 return NT_STATUS_OK;
2368 nomem:
2369 status = NT_STATUS_NO_MEMORY;
2370 fail:
2371 TALLOC_FREE(m);
2372 return status;
2375 NTSTATUS pdb_samba_dsdb_init(void);
2376 NTSTATUS pdb_samba_dsdb_init(void)
2378 NTSTATUS status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba_dsdb",
2379 pdb_init_samba_dsdb);
2380 if (!NT_STATUS_IS_OK(status)) {
2381 return status;
2383 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4",
2384 pdb_init_samba_dsdb);