libsmb: remove smb2 switch from cli_ntcreate
[Samba.git] / source3 / passdb / pdb_samba_dsdb.c
blob7e7468dcdb10fddc70b80c45870a8a090ef8fd3f
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 str = ldb_msg_find_attr_as_string(msg, "userParameters",
263 NULL);
264 if (str != NULL) {
265 pdb_set_munged_dial(sam, str, PDB_SET);
268 sid = samdb_result_dom_sid(talloc_tos(), msg, "objectSid");
269 if (!sid) {
270 DEBUG(10, ("Could not pull SID\n"));
271 goto fail;
273 pdb_set_user_sid(sam, sid, PDB_SET);
275 n = samdb_result_acct_flags(msg, "msDS-User-Account-Control-Computed");
276 if (n == 0) {
277 DEBUG(10, ("Could not pull userAccountControl\n"));
278 goto fail;
280 pdb_set_acct_ctrl(sam, n, PDB_SET);
282 blob = ldb_msg_find_ldb_val(msg, "unicodePwd");
283 if (blob) {
284 if (blob->length != NT_HASH_LEN) {
285 DEBUG(0, ("Got NT hash of length %d, expected %d\n",
286 (int)blob->length, NT_HASH_LEN));
287 goto fail;
289 pdb_set_nt_passwd(sam, blob->data, PDB_SET);
292 blob = ldb_msg_find_ldb_val(msg, "dBCSPwd");
293 if (blob) {
294 if (blob->length != LM_HASH_LEN) {
295 DEBUG(0, ("Got LM hash of length %d, expected %d\n",
296 (int)blob->length, LM_HASH_LEN));
297 goto fail;
299 pdb_set_lanman_passwd(sam, blob->data, PDB_SET);
302 n = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", 0);
303 if (n == 0) {
304 DEBUG(10, ("Could not pull primaryGroupID\n"));
305 goto fail;
307 sid_compose(&group_sid, samdb_domain_sid(state->ldb), n);
308 pdb_set_group_sid(sam, &group_sid, PDB_SET);
310 status = NT_STATUS_OK;
311 fail:
312 TALLOC_FREE(frame);
313 return status;
316 static bool pdb_samba_dsdb_add_time(struct ldb_message *msg,
317 const char *attrib, time_t t)
319 uint64_t nt_time;
321 unix_to_nt_time(&nt_time, t);
323 return ldb_msg_add_fmt(msg, attrib, "%llu", (unsigned long long) nt_time);
326 static int pdb_samba_dsdb_replace_by_sam(struct pdb_samba_dsdb_state *state,
327 bool (*need_update)(const struct samu *,
328 enum pdb_elements),
329 struct ldb_dn *dn,
330 struct samu *sam)
332 TALLOC_CTX *frame = talloc_stackframe();
333 int ret = LDB_SUCCESS;
334 const char *pw;
335 struct ldb_message *msg;
336 struct ldb_request *req;
337 uint32_t dsdb_flags = 0;
338 /* TODO: All fields :-) */
340 msg = ldb_msg_new(frame);
341 if (!msg) {
342 talloc_free(frame);
343 return false;
346 msg->dn = dn;
348 /* build modify request */
349 ret = ldb_build_mod_req(&req, state->ldb, frame, msg, NULL, NULL,
350 ldb_op_default_callback,
351 NULL);
352 if (ret != LDB_SUCCESS) {
353 talloc_free(frame);
354 return ret;
357 /* If we set a plaintext password, the system will
358 * force the pwdLastSet to now() */
359 if (need_update(sam, PDB_PASSLASTSET)) {
360 dsdb_flags = DSDB_PASSWORD_BYPASS_LAST_SET;
362 ret |= pdb_samba_dsdb_add_time(msg, "pwdLastSet",
363 pdb_get_pass_last_set_time(sam));
366 pw = pdb_get_plaintext_passwd(sam);
367 if (need_update(sam, PDB_PLAINTEXT_PW)) {
368 struct ldb_val pw_utf16;
369 if (pw == NULL) {
370 talloc_free(frame);
371 return LDB_ERR_OPERATIONS_ERROR;
374 if (!convert_string_talloc(msg,
375 CH_UNIX, CH_UTF16,
376 pw, strlen(pw),
377 (void *)&pw_utf16.data,
378 &pw_utf16.length)) {
379 talloc_free(frame);
380 return LDB_ERR_OPERATIONS_ERROR;
382 ret |= ldb_msg_add_value(msg, "clearTextPassword", &pw_utf16, NULL);
383 } else {
384 bool changed_lm_pw = false;
385 bool changed_nt_pw = false;
386 bool changed_history = false;
387 if (need_update(sam, PDB_LMPASSWD)) {
388 struct ldb_val val;
389 val.data = discard_const_p(uint8_t, pdb_get_lanman_passwd(sam));
390 if (!val.data) {
391 samdb_msg_add_delete(state->ldb, msg, msg,
392 "dBCSPwd");
393 } else {
394 val.length = LM_HASH_LEN;
395 ret |= ldb_msg_add_value(msg, "dBCSPwd", &val, NULL);
397 changed_lm_pw = true;
399 if (need_update(sam, PDB_NTPASSWD)) {
400 struct ldb_val val;
401 val.data = discard_const_p(uint8_t, pdb_get_nt_passwd(sam));
402 if (!val.data) {
403 samdb_msg_add_delete(state->ldb, msg, msg,
404 "unicodePwd");
405 } else {
406 val.length = NT_HASH_LEN;
407 ret |= ldb_msg_add_value(msg, "unicodePwd", &val, NULL);
409 changed_nt_pw = true;
412 /* Try to ensure we don't get out of sync */
413 if (changed_lm_pw && !changed_nt_pw) {
414 samdb_msg_add_delete(state->ldb, msg, msg,
415 "unicodePwd");
416 } else if (changed_nt_pw && !changed_lm_pw) {
417 samdb_msg_add_delete(state->ldb, msg, msg,
418 "dBCSPwd");
420 if (changed_lm_pw || changed_nt_pw) {
421 samdb_msg_add_delete(state->ldb, msg, msg,
422 "supplementalCredentials");
426 if (need_update(sam, PDB_PWHISTORY)) {
427 uint32_t current_hist_len;
428 const uint8_t *history = pdb_get_pw_history(sam, &current_hist_len);
430 bool invalid_history = false;
431 struct samr_Password *history_hashes = talloc_array(talloc_tos(), struct samr_Password,
432 current_hist_len);
433 if (!history) {
434 invalid_history = true;
435 } else {
436 unsigned int i;
437 static const uint8_t zeros[16];
438 /* Parse the history into the correct format */
439 for (i = 0; i < current_hist_len; i++) {
440 if (memcmp(&history[i*PW_HISTORY_ENTRY_LEN], zeros, 16) != 0) {
441 /* If the history is in the old format, with a salted hash, then we can't migrate it to AD format */
442 invalid_history = true;
443 break;
445 /* Copy out the 2nd 16 bytes of the 32 byte password history, containing the NT hash */
446 memcpy(history_hashes[i].hash,
447 &history[(i*PW_HISTORY_ENTRY_LEN) + PW_HISTORY_SALT_LEN],
448 sizeof(history_hashes[i].hash));
451 if (invalid_history) {
452 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
453 "ntPwdHistory");
455 ret |= samdb_msg_add_delete(state->ldb, msg, msg,
456 "lmPwdHistory");
457 } else {
458 ret |= samdb_msg_add_hashes(state->ldb, msg, msg,
459 "ntPwdHistory",
460 history_hashes,
461 current_hist_len);
463 changed_history = true;
465 if (changed_lm_pw || changed_nt_pw || changed_history) {
466 /* These attributes can only be modified directly by using a special control */
467 dsdb_flags = DSDB_BYPASS_PASSWORD_HASH;
471 /* PDB_USERSID is only allowed on ADD, handled in caller */
472 if (need_update(sam, PDB_GROUPSID)) {
473 const struct dom_sid *sid = pdb_get_group_sid(sam);
474 uint32_t rid;
475 NTSTATUS status = dom_sid_split_rid(NULL, sid, NULL, &rid);
476 if (!NT_STATUS_IS_OK(status)) {
477 talloc_free(frame);
478 return LDB_ERR_OPERATIONS_ERROR;
480 if (!dom_sid_in_domain(samdb_domain_sid(state->ldb), sid)) {
481 talloc_free(frame);
482 return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
484 ret |= samdb_msg_add_uint(state->ldb, msg, msg, "primaryGroupID", rid);
486 if (need_update(sam, PDB_FULLNAME)) {
487 ret |= ldb_msg_add_string(msg, "displayName", pdb_get_fullname(sam));
490 if (need_update(sam, PDB_SMBHOME)) {
491 ret |= ldb_msg_add_string(msg, "homeDirectory",
492 pdb_get_homedir(sam));
495 if (need_update(sam, PDB_PROFILE)) {
496 ret |= ldb_msg_add_string(msg, "profilePath",
497 pdb_get_profile_path(sam));
500 if (need_update(sam, PDB_DRIVE)) {
501 ret |= ldb_msg_add_string(msg, "homeDrive",
502 pdb_get_dir_drive(sam));
505 if (need_update(sam, PDB_LOGONSCRIPT)) {
506 ret |= ldb_msg_add_string(msg, "scriptPath",
507 pdb_get_logon_script(sam));
510 if (need_update(sam, PDB_KICKOFFTIME)) {
511 ret |= pdb_samba_dsdb_add_time(msg, "accountExpires",
512 pdb_get_kickoff_time(sam));
515 if (need_update(sam, PDB_LOGONTIME)) {
516 ret |= pdb_samba_dsdb_add_time(msg, "lastLogon",
517 pdb_get_logon_time(sam));
520 if (need_update(sam, PDB_LOGOFFTIME)) {
521 ret |= pdb_samba_dsdb_add_time(msg, "lastLogoff",
522 pdb_get_logoff_time(sam));
525 if (need_update(sam, PDB_USERNAME)) {
526 ret |= ldb_msg_add_string(msg, "samAccountName",
527 pdb_get_username(sam));
530 if (need_update(sam, PDB_HOURSLEN) || need_update(sam, PDB_HOURS)) {
531 struct ldb_val hours = data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam));
532 ret |= ldb_msg_add_value(msg, "logonHours",
533 &hours, NULL);
536 if (need_update(sam, PDB_ACCTCTRL)) {
537 ret |= samdb_msg_add_acct_flags(state->ldb, msg, msg,
538 "userAccountControl", pdb_get_acct_ctrl(sam));
541 if (need_update(sam, PDB_COMMENT)) {
542 ret |= ldb_msg_add_string(msg, "comment",
543 pdb_get_comment(sam));
546 if (need_update(sam, PDB_ACCTDESC)) {
547 ret |= ldb_msg_add_string(msg, "description",
548 pdb_get_acct_desc(sam));
551 if (need_update(sam, PDB_WORKSTATIONS)) {
552 ret |= ldb_msg_add_string(msg, "userWorkstations",
553 pdb_get_workstations(sam));
556 /* This will need work, it is actually a UTF8 'string' with internal NULLs, to handle TS parameters */
557 if (need_update(sam, PDB_MUNGEDDIAL)) {
558 ret |= ldb_msg_add_string(msg, "userParameters",
559 pdb_get_munged_dial(sam));
562 if (need_update(sam, PDB_COUNTRY_CODE)) {
563 ret |= ldb_msg_add_fmt(msg, "countryCode",
564 "%i", (int)pdb_get_country_code(sam));
567 if (need_update(sam, PDB_CODE_PAGE)) {
568 ret |= ldb_msg_add_fmt(msg, "codePage",
569 "%i", (int)pdb_get_code_page(sam));
572 /* Not yet handled here or not meaningful for modifies on a Samba_Dsdb backend:
573 PDB_BAD_PASSWORD_TIME,
574 PDB_CANCHANGETIME, - these are calculated per policy, not stored
575 PDB_DOMAIN,
576 PDB_NTUSERNAME, - this makes no sense, and never really did
577 PDB_LOGONDIVS,
578 PDB_USERSID, - Handled in pdb_samba_dsdb_add_sam_account()
579 PDB_FIELDS_PRESENT,
580 PDB_BAD_PASSWORD_COUNT,
581 PDB_LOGON_COUNT,
582 PDB_UNKNOWN6,
583 PDB_BACKEND_PRIVATE_DATA,
586 if (ret != LDB_SUCCESS) {
587 talloc_free(frame);
588 return LDB_ERR_OPERATIONS_ERROR;
591 if (msg->num_elements == 0) {
592 talloc_free(frame);
593 /* Nothing to do, just return success */
594 return LDB_SUCCESS;
597 ret = dsdb_replace(state->ldb, msg, dsdb_flags);
599 if (ret != LDB_SUCCESS) {
600 DEBUG(0,("Failed to modify account record %s to set user attributes: %s\n",
601 ldb_dn_get_linearized(msg->dn),
602 ldb_errstring(state->ldb)));
605 talloc_free(frame);
606 return ret;
609 static NTSTATUS pdb_samba_dsdb_getsamupriv(struct pdb_samba_dsdb_state *state,
610 const char *filter,
611 TALLOC_CTX *mem_ctx,
612 struct ldb_message **msg)
614 const char * attrs[] = {
615 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
616 "sAMAccountName", "displayName", "homeDirectory",
617 "homeDrive", "scriptPath", "profilePath", "description",
618 "userWorkstations", "comment", "userParameters", "objectSid",
619 "primaryGroupID", "userAccountControl",
620 "msDS-User-Account-Control-Computed", "logonHours",
621 "badPwdCount", "logonCount", "countryCode", "codePage",
622 "unicodePwd", "dBCSPwd", NULL };
624 int rc = dsdb_search_one(state->ldb, mem_ctx, msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", filter);
625 if (rc != LDB_SUCCESS) {
626 DEBUG(10, ("ldap_search failed %s\n",
627 ldb_errstring(state->ldb)));
628 return NT_STATUS_LDAP(rc);
631 return NT_STATUS_OK;
634 static NTSTATUS pdb_samba_dsdb_getsampwfilter(struct pdb_methods *m,
635 struct pdb_samba_dsdb_state *state,
636 struct samu *sam_acct,
637 const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
639 struct ldb_message *priv;
640 NTSTATUS status;
641 va_list ap;
642 char *expression = NULL;
643 TALLOC_CTX *tmp_ctx = talloc_new(state);
644 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
646 va_start(ap, exp_fmt);
647 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
648 va_end(ap);
650 if (!expression) {
651 talloc_free(tmp_ctx);
652 return NT_STATUS_NO_MEMORY;
655 status = pdb_samba_dsdb_getsamupriv(state, expression, sam_acct, &priv);
656 talloc_free(tmp_ctx);
657 if (!NT_STATUS_IS_OK(status)) {
658 DEBUG(10, ("pdb_samba_dsdb_getsamupriv failed: %s\n",
659 nt_errstr(status)));
660 return status;
663 status = pdb_samba_dsdb_init_sam_from_priv(m, sam_acct, priv);
664 if (!NT_STATUS_IS_OK(status)) {
665 DEBUG(10, ("pdb_samba_dsdb_init_sam_from_priv failed: %s\n",
666 nt_errstr(status)));
667 TALLOC_FREE(priv);
668 return status;
671 pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
672 return NT_STATUS_OK;
675 static NTSTATUS pdb_samba_dsdb_getsampwnam(struct pdb_methods *m,
676 struct samu *sam_acct,
677 const char *username)
679 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
680 m->private_data, struct pdb_samba_dsdb_state);
682 return pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
683 "(&(samaccountname=%s)(objectclass=user))",
684 username);
687 static NTSTATUS pdb_samba_dsdb_getsampwsid(struct pdb_methods *m,
688 struct samu *sam_acct,
689 const struct dom_sid *sid)
691 NTSTATUS status;
692 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
693 m->private_data, struct pdb_samba_dsdb_state);
694 char *sidstr;
696 sidstr = dom_sid_string(talloc_tos(), sid);
697 NT_STATUS_HAVE_NO_MEMORY(sidstr);
699 status = pdb_samba_dsdb_getsampwfilter(m, state, sam_acct,
700 "(&(objectsid=%s)(objectclass=user))",
701 sidstr);
702 talloc_free(sidstr);
703 return status;
706 static NTSTATUS pdb_samba_dsdb_create_user(struct pdb_methods *m,
707 TALLOC_CTX *mem_ctx,
708 const char *name, uint32 acct_flags,
709 uint32 *rid)
711 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
712 m->private_data, struct pdb_samba_dsdb_state);
713 struct dom_sid *sid;
714 struct ldb_dn *dn;
715 NTSTATUS status;
716 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
717 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
719 /* Internally this uses transactions to ensure all the steps
720 * happen or fail as one */
721 status = dsdb_add_user(state->ldb, tmp_ctx, name, acct_flags, NULL,
722 &sid, &dn);
723 if (!NT_STATUS_IS_OK(status)) {
724 talloc_free(tmp_ctx);
725 return status;
727 sid_peek_rid(sid, rid);
728 talloc_free(tmp_ctx);
729 return NT_STATUS_OK;
732 static NTSTATUS pdb_samba_dsdb_delete_user(struct pdb_methods *m,
733 TALLOC_CTX *mem_ctx,
734 struct samu *sam)
736 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
737 m->private_data, struct pdb_samba_dsdb_state);
738 struct ldb_dn *dn;
739 int rc;
740 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
741 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
743 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, pdb_get_user_sid(sam)));
744 if (!dn || !ldb_dn_validate(dn)) {
745 talloc_free(tmp_ctx);
746 return NT_STATUS_NO_MEMORY;
748 rc = ldb_delete(state->ldb, dn);
750 if (rc != LDB_SUCCESS) {
751 DEBUG(10, ("ldb_delete for %s failed: %s\n", ldb_dn_get_linearized(dn),
752 ldb_errstring(state->ldb)));
753 talloc_free(tmp_ctx);
754 return NT_STATUS_LDAP(rc);
756 talloc_free(tmp_ctx);
757 return NT_STATUS_OK;
760 /* This interface takes a fully populated struct samu and places it in
761 * the database. This is not implemented at this time as we need to
762 * be careful around the creation of arbitary SIDs (ie, we must ensrue
763 * they are not left in a RID pool */
764 static NTSTATUS pdb_samba_dsdb_add_sam_account(struct pdb_methods *m,
765 struct samu *sampass)
767 int ret;
768 NTSTATUS status;
769 struct ldb_dn *dn;
770 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
771 m->private_data, struct pdb_samba_dsdb_state);
772 uint32_t acb_flags = pdb_get_acct_ctrl(sampass);
773 const char *username = pdb_get_username(sampass);
774 const struct dom_sid *user_sid = pdb_get_user_sid(sampass);
775 TALLOC_CTX *tframe = talloc_stackframe();
777 acb_flags &= (ACB_NORMAL|ACB_WSTRUST|ACB_SVRTRUST|ACB_DOMTRUST);
779 ret = ldb_transaction_start(state->ldb);
780 if (ret != LDB_SUCCESS) {
781 talloc_free(tframe);
782 return NT_STATUS_LOCK_NOT_GRANTED;
785 status = dsdb_add_user(state->ldb, talloc_tos(), username,
786 acb_flags, user_sid, NULL, &dn);
787 if (!NT_STATUS_IS_OK(status)) {
788 ldb_transaction_cancel(state->ldb);
789 talloc_free(tframe);
790 return status;
793 ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_set_or_changed,
794 dn, sampass);
795 if (ret != LDB_SUCCESS) {
796 ldb_transaction_cancel(state->ldb);
797 talloc_free(tframe);
798 return dsdb_ldb_err_to_ntstatus(ret);
801 ret = ldb_transaction_commit(state->ldb);
802 if (ret != LDB_SUCCESS) {
803 DEBUG(0,("Failed to commit transaction to add and modify account record %s: %s\n",
804 ldb_dn_get_linearized(dn),
805 ldb_errstring(state->ldb)));
806 talloc_free(tframe);
807 return NT_STATUS_INTERNAL_DB_CORRUPTION;
809 talloc_free(tframe);
810 return NT_STATUS_OK;
814 * Update the Samba_Dsdb LDB with the changes from a struct samu.
816 * This takes care not to update elements that have not been changed
817 * by the caller
819 static NTSTATUS pdb_samba_dsdb_update_sam_account(struct pdb_methods *m,
820 struct samu *sam)
822 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
823 m->private_data, struct pdb_samba_dsdb_state);
824 struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
825 m, sam);
826 int ret;
828 ret = pdb_samba_dsdb_replace_by_sam(state, pdb_element_is_changed, msg->dn,
829 sam);
830 return dsdb_ldb_err_to_ntstatus(ret);
833 static NTSTATUS pdb_samba_dsdb_delete_sam_account(struct pdb_methods *m,
834 struct samu *username)
836 NTSTATUS status;
837 TALLOC_CTX *tmp_ctx = talloc_new(NULL);
838 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
839 status = pdb_samba_dsdb_delete_user(m, tmp_ctx, username);
840 talloc_free(tmp_ctx);
841 return status;
844 static NTSTATUS pdb_samba_dsdb_rename_sam_account(struct pdb_methods *m,
845 struct samu *oldname,
846 const char *newname)
848 return NT_STATUS_NOT_IMPLEMENTED;
851 /* This is not implemented, as this module is exptected to be used
852 * with auth_samba_dsdb, and this is responible for login counters etc
855 static NTSTATUS pdb_samba_dsdb_update_login_attempts(struct pdb_methods *m,
856 struct samu *sam_acct,
857 bool success)
859 return NT_STATUS_NOT_IMPLEMENTED;
862 static NTSTATUS pdb_samba_dsdb_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
863 const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
865 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
866 m->private_data, struct pdb_samba_dsdb_state);
867 const char *attrs[] = { "objectSid", "description", "samAccountName", "groupType",
868 NULL };
869 struct ldb_message *msg;
870 va_list ap;
871 char *expression = NULL;
872 struct dom_sid *sid;
873 const char *str;
874 int rc;
875 struct id_map id_map;
876 struct id_map *id_maps[2];
877 TALLOC_CTX *tmp_ctx = talloc_stackframe();
878 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
880 va_start(ap, exp_fmt);
881 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
882 va_end(ap);
884 if (!expression) {
885 talloc_free(tmp_ctx);
886 return NT_STATUS_NO_MEMORY;
889 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
890 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
891 talloc_free(tmp_ctx);
892 return NT_STATUS_NO_SUCH_GROUP;
893 } else if (rc != LDB_SUCCESS) {
894 talloc_free(tmp_ctx);
895 DEBUG(10, ("dsdb_search_one failed %s\n",
896 ldb_errstring(state->ldb)));
897 return NT_STATUS_LDAP(rc);
900 sid = samdb_result_dom_sid(tmp_ctx, msg, "objectSid");
901 if (!sid) {
902 talloc_free(tmp_ctx);
903 DEBUG(10, ("Could not pull SID\n"));
904 return NT_STATUS_INTERNAL_DB_CORRUPTION;
907 map->sid = *sid;
909 if (samdb_find_attribute(state->ldb, msg, "objectClass", "group")) {
910 NTSTATUS status;
911 uint32_t grouptype = ldb_msg_find_attr_as_uint(msg, "groupType", 0);
912 switch (grouptype) {
913 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
914 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
915 map->sid_name_use = SID_NAME_ALIAS;
916 break;
917 case GTYPE_SECURITY_GLOBAL_GROUP:
918 map->sid_name_use = SID_NAME_DOM_GRP;
919 break;
920 default:
921 talloc_free(tmp_ctx);
922 DEBUG(10, ("Could not pull groupType\n"));
923 return NT_STATUS_INTERNAL_DB_CORRUPTION;
926 map->sid_name_use = SID_NAME_DOM_GRP;
928 ZERO_STRUCT(id_map);
929 id_map.sid = sid;
930 id_maps[0] = &id_map;
931 id_maps[1] = NULL;
933 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
934 talloc_free(tmp_ctx);
935 if (!NT_STATUS_IS_OK(status)) {
936 talloc_free(tmp_ctx);
937 return status;
939 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
940 map->gid = id_map.xid.id;
941 } else {
942 DEBUG(1, (__location__ "Did not get GUID when mapping SID for %s", expression));
943 talloc_free(tmp_ctx);
944 return NT_STATUS_INTERNAL_DB_CORRUPTION;
946 } else if (samdb_find_attribute(state->ldb, msg, "objectClass", "user")) {
947 DEBUG(1, (__location__ "Got SID_NAME_USER when searching for a group with %s", expression));
948 talloc_free(tmp_ctx);
949 return NT_STATUS_INTERNAL_DB_CORRUPTION;
952 str = ldb_msg_find_attr_as_string(msg, "samAccountName",
953 NULL);
954 if (str == NULL) {
955 talloc_free(tmp_ctx);
956 return NT_STATUS_INTERNAL_DB_CORRUPTION;
958 map->nt_name = talloc_strdup(map, str);
959 if (!map->nt_name) {
960 talloc_free(tmp_ctx);
961 return NT_STATUS_NO_MEMORY;
964 str = ldb_msg_find_attr_as_string(msg, "description",
965 NULL);
966 if (str != NULL) {
967 map->comment = talloc_strdup(map, str);
968 } else {
969 map->comment = talloc_strdup(map, "");
971 if (!map->comment) {
972 talloc_free(tmp_ctx);
973 return NT_STATUS_NO_MEMORY;
976 talloc_free(tmp_ctx);
977 return NT_STATUS_OK;
980 static NTSTATUS pdb_samba_dsdb_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
981 struct dom_sid sid)
983 char *filter;
984 NTSTATUS status;
986 filter = talloc_asprintf(talloc_tos(),
987 "(&(objectsid=%s)(objectclass=group))",
988 sid_string_talloc(talloc_tos(), &sid));
989 if (filter == NULL) {
990 return NT_STATUS_NO_MEMORY;
993 status = pdb_samba_dsdb_getgrfilter(m, map, filter);
994 TALLOC_FREE(filter);
995 return status;
998 static NTSTATUS pdb_samba_dsdb_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
999 gid_t gid)
1001 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1002 m->private_data, struct pdb_samba_dsdb_state);
1003 NTSTATUS status;
1004 struct id_map id_map;
1005 struct id_map *id_maps[2];
1006 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1007 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1009 id_map.xid.id = gid;
1010 id_map.xid.type = ID_TYPE_GID;
1011 id_maps[0] = &id_map;
1012 id_maps[1] = NULL;
1014 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
1015 if (!NT_STATUS_IS_OK(status)) {
1016 talloc_free(tmp_ctx);
1017 return status;
1019 status = pdb_samba_dsdb_getgrsid(m, map, *id_map.sid);
1020 talloc_free(tmp_ctx);
1021 return status;
1024 static NTSTATUS pdb_samba_dsdb_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
1025 const char *name)
1027 char *filter;
1028 NTSTATUS status;
1030 filter = talloc_asprintf(talloc_tos(),
1031 "(&(samaccountname=%s)(objectclass=group))",
1032 name);
1033 if (filter == NULL) {
1034 return NT_STATUS_NO_MEMORY;
1037 status = pdb_samba_dsdb_getgrfilter(m, map, filter);
1038 TALLOC_FREE(filter);
1039 return status;
1042 static NTSTATUS pdb_samba_dsdb_create_dom_group(struct pdb_methods *m,
1043 TALLOC_CTX *mem_ctx, const char *name,
1044 uint32 *rid)
1046 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1047 m->private_data, struct pdb_samba_dsdb_state);
1048 NTSTATUS status;
1049 struct dom_sid *sid;
1050 struct ldb_dn *dn;
1051 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1052 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1054 status = dsdb_add_domain_group(state->ldb, tmp_ctx, name, &sid, &dn);
1055 if (!NT_STATUS_IS_OK(status)) {
1056 talloc_free(tmp_ctx);
1057 return status;
1060 sid_peek_rid(sid, rid);
1061 talloc_free(tmp_ctx);
1062 return NT_STATUS_OK;
1065 static NTSTATUS pdb_samba_dsdb_delete_dom_group(struct pdb_methods *m,
1066 TALLOC_CTX *mem_ctx, uint32 rid)
1068 const char *attrs[] = { NULL };
1069 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1070 m->private_data, struct pdb_samba_dsdb_state);
1071 struct dom_sid sid;
1072 struct ldb_message *msg;
1073 struct ldb_dn *dn;
1074 int rc;
1075 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1076 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1078 sid_compose(&sid, samdb_domain_sid(state->ldb), rid);
1080 if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1081 DEBUG(0, ("Unable to start transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1082 return NT_STATUS_INTERNAL_ERROR;
1085 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, &sid));
1086 if (!dn || !ldb_dn_validate(dn)) {
1087 talloc_free(tmp_ctx);
1088 ldb_transaction_cancel(state->ldb);
1089 return NT_STATUS_NO_MEMORY;
1091 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "objectclass=group");
1092 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1093 talloc_free(tmp_ctx);
1094 ldb_transaction_cancel(state->ldb);
1095 return NT_STATUS_NO_SUCH_GROUP;
1097 rc = ldb_delete(state->ldb, dn);
1098 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1099 talloc_free(tmp_ctx);
1100 ldb_transaction_cancel(state->ldb);
1101 return NT_STATUS_NO_SUCH_GROUP;
1102 } else if (rc != LDB_SUCCESS) {
1103 DEBUG(10, ("ldb_delete failed %s\n",
1104 ldb_errstring(state->ldb)));
1105 ldb_transaction_cancel(state->ldb);
1106 return NT_STATUS_LDAP(rc);
1109 if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1110 DEBUG(0, ("Unable to commit transaction in pdb_samba_dsdb_delete_dom_group()\n"));
1111 return NT_STATUS_INTERNAL_ERROR;
1113 return NT_STATUS_OK;
1116 static NTSTATUS pdb_samba_dsdb_add_group_mapping_entry(struct pdb_methods *m,
1117 GROUP_MAP *map)
1119 return NT_STATUS_NOT_IMPLEMENTED;
1122 static NTSTATUS pdb_samba_dsdb_update_group_mapping_entry(struct pdb_methods *m,
1123 GROUP_MAP *map)
1125 return NT_STATUS_NOT_IMPLEMENTED;
1128 static NTSTATUS pdb_samba_dsdb_delete_group_mapping_entry(struct pdb_methods *m,
1129 struct dom_sid sid)
1131 return NT_STATUS_NOT_IMPLEMENTED;
1134 static NTSTATUS pdb_samba_dsdb_enum_group_mapping(struct pdb_methods *m,
1135 const struct dom_sid *sid,
1136 enum lsa_SidType sid_name_use,
1137 GROUP_MAP ***pp_rmap,
1138 size_t *p_num_entries,
1139 bool unix_only)
1141 return NT_STATUS_NOT_IMPLEMENTED;
1144 static NTSTATUS pdb_samba_dsdb_enum_group_members(struct pdb_methods *m,
1145 TALLOC_CTX *mem_ctx,
1146 const struct dom_sid *group,
1147 uint32_t **pmembers,
1148 size_t *pnum_members)
1150 unsigned int i, num_sids, num_members;
1151 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1152 m->private_data, struct pdb_samba_dsdb_state);
1153 struct dom_sid *members_as_sids;
1154 struct dom_sid *dom_sid;
1155 uint32_t *members;
1156 struct ldb_dn *dn;
1157 NTSTATUS status;
1159 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1160 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1162 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, group));
1163 if (!dn || !ldb_dn_validate(dn)) {
1164 return NT_STATUS_NO_MEMORY;
1167 status = dsdb_enum_group_mem(state->ldb, tmp_ctx, dn, &members_as_sids, &num_sids);
1168 if (!NT_STATUS_IS_OK(status)) {
1169 talloc_free(tmp_ctx);
1170 return status;
1172 status = dom_sid_split_rid(tmp_ctx, group, &dom_sid, NULL);
1173 if (!NT_STATUS_IS_OK(status)) {
1174 talloc_free(tmp_ctx);
1175 return status;
1178 *pmembers = members = talloc_array(mem_ctx, uint32_t, num_sids);
1179 if (*pmembers == NULL) {
1180 TALLOC_FREE(tmp_ctx);
1181 return NT_STATUS_NO_MEMORY;
1183 num_members = 0;
1185 for (i = 0; i < num_sids; i++) {
1186 if (!dom_sid_in_domain(dom_sid, &members_as_sids[i])) {
1187 continue;
1189 status = dom_sid_split_rid(NULL, &members_as_sids[i],
1190 NULL, &members[num_members]);
1191 if (!NT_STATUS_IS_OK(status)) {
1192 talloc_free(tmp_ctx);
1193 return status;
1195 num_members++;
1197 *pnum_members = num_members;
1198 return NT_STATUS_OK;
1201 /* Just convert the primary group SID into a group */
1202 static NTSTATUS fake_enum_group_memberships(struct pdb_samba_dsdb_state *state,
1203 TALLOC_CTX *mem_ctx,
1204 struct samu *user,
1205 struct dom_sid **pp_sids,
1206 gid_t **pp_gids,
1207 uint32_t *p_num_groups)
1209 NTSTATUS status;
1210 size_t num_groups = 0;
1211 struct dom_sid *group_sids = NULL;
1212 gid_t *gids = NULL;
1213 TALLOC_CTX *tmp_ctx;
1215 tmp_ctx = talloc_new(mem_ctx);
1216 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1218 if (user->group_sid) {
1219 struct id_map *id_maps[2];
1220 struct id_map id_map;
1222 num_groups = 1;
1224 group_sids = talloc_array(tmp_ctx, struct dom_sid, num_groups);
1225 if (group_sids == NULL) {
1226 talloc_free(tmp_ctx);
1227 return NT_STATUS_NO_MEMORY;
1229 gids = talloc_array(tmp_ctx, gid_t, num_groups);
1230 if (gids == NULL) {
1231 talloc_free(tmp_ctx);
1232 return NT_STATUS_NO_MEMORY;
1235 group_sids[0] = *user->group_sid;
1237 ZERO_STRUCT(id_map);
1238 id_map.sid = &group_sids[0];
1239 id_maps[0] = &id_map;
1240 id_maps[1] = NULL;
1242 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1243 if (!NT_STATUS_IS_OK(status)) {
1244 talloc_free(tmp_ctx);
1245 return status;
1247 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1248 gids[0] = id_map.xid.id;
1249 } else {
1250 DEBUG(1, (__location__
1251 "Group %s, of which %s is a member, could not be converted to a GID\n",
1252 dom_sid_string(tmp_ctx, &group_sids[0]),
1253 dom_sid_string(tmp_ctx, &user->user_sid)));
1254 talloc_free(tmp_ctx);
1255 /* We must error out, otherwise a user might
1256 * avoid a DENY acl based on a group they
1257 * missed out on */
1258 return NT_STATUS_NO_SUCH_GROUP;
1262 *pp_sids = talloc_steal(mem_ctx, group_sids);
1263 *pp_gids = talloc_steal(mem_ctx, gids);
1264 *p_num_groups = num_groups;
1265 talloc_free(tmp_ctx);
1266 return NT_STATUS_OK;
1269 static NTSTATUS pdb_samba_dsdb_enum_group_memberships(struct pdb_methods *m,
1270 TALLOC_CTX *mem_ctx,
1271 struct samu *user,
1272 struct dom_sid **pp_sids,
1273 gid_t **pp_gids,
1274 uint32_t *p_num_groups)
1276 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1277 m->private_data, struct pdb_samba_dsdb_state);
1278 struct ldb_message *msg = pdb_samba_dsdb_get_samu_private(
1279 m, user);
1280 const char *attrs[] = { "tokenGroups", NULL};
1281 struct ldb_message *tokengroups_msg;
1282 struct ldb_message_element *tokengroups;
1283 int i, rc;
1284 NTSTATUS status;
1285 unsigned int count = 0;
1286 size_t num_groups;
1287 struct dom_sid *group_sids;
1288 gid_t *gids;
1289 TALLOC_CTX *tmp_ctx;
1291 if (msg == NULL) {
1292 /* Fake up some things here */
1293 return fake_enum_group_memberships(state,
1294 mem_ctx,
1295 user, pp_sids,
1296 pp_gids, p_num_groups);
1299 tmp_ctx = talloc_new(mem_ctx);
1300 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1302 rc = dsdb_search_one(state->ldb, tmp_ctx, &tokengroups_msg, msg->dn, LDB_SCOPE_BASE, attrs, 0, NULL);
1304 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1305 talloc_free(tmp_ctx);
1306 return NT_STATUS_NO_SUCH_USER;
1307 } else if (rc != LDB_SUCCESS) {
1308 DEBUG(10, ("dsdb_search_one failed %s\n",
1309 ldb_errstring(state->ldb)));
1310 talloc_free(tmp_ctx);
1311 return NT_STATUS_LDAP(rc);
1314 tokengroups = ldb_msg_find_element(tokengroups_msg, "tokenGroups");
1316 if (tokengroups) {
1317 count = tokengroups->num_values;
1320 group_sids = talloc_array(tmp_ctx, struct dom_sid, count);
1321 if (group_sids == NULL) {
1322 talloc_free(tmp_ctx);
1323 return NT_STATUS_NO_MEMORY;
1325 gids = talloc_array(tmp_ctx, gid_t, count);
1326 if (gids == NULL) {
1327 talloc_free(tmp_ctx);
1328 return NT_STATUS_NO_MEMORY;
1330 num_groups = 0;
1332 for (i=0; i<count; i++) {
1333 struct id_map *id_maps[2];
1334 struct id_map id_map;
1335 struct ldb_val *v = &tokengroups->values[i];
1336 enum ndr_err_code ndr_err
1337 = ndr_pull_struct_blob(v, group_sids, &group_sids[num_groups],
1338 (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
1339 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1340 talloc_free(tmp_ctx);
1341 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1344 ZERO_STRUCT(id_map);
1345 id_map.sid = &group_sids[num_groups];
1346 id_maps[0] = &id_map;
1347 id_maps[1] = NULL;
1349 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
1350 if (!NT_STATUS_IS_OK(status)) {
1351 talloc_free(tmp_ctx);
1352 return status;
1354 if (id_map.xid.type == ID_TYPE_GID || id_map.xid.type == ID_TYPE_BOTH) {
1355 gids[num_groups] = id_map.xid.id;
1356 } else {
1357 DEBUG(1, (__location__
1358 "Group %s, of which %s is a member, could not be converted to a GID\n",
1359 dom_sid_string(tmp_ctx, &group_sids[num_groups]),
1360 ldb_dn_get_linearized(msg->dn)));
1361 talloc_free(tmp_ctx);
1362 /* We must error out, otherwise a user might
1363 * avoid a DENY acl based on a group they
1364 * missed out on */
1365 return NT_STATUS_NO_SUCH_GROUP;
1368 num_groups += 1;
1369 if (num_groups == count) {
1370 break;
1374 *pp_sids = talloc_steal(mem_ctx, group_sids);
1375 *pp_gids = talloc_steal(mem_ctx, gids);
1376 *p_num_groups = num_groups;
1377 talloc_free(tmp_ctx);
1378 return NT_STATUS_OK;
1381 static NTSTATUS pdb_samba_dsdb_set_unix_primary_group(struct pdb_methods *m,
1382 TALLOC_CTX *mem_ctx,
1383 struct samu *user)
1385 return NT_STATUS_NOT_IMPLEMENTED;
1388 static NTSTATUS pdb_samba_dsdb_mod_groupmem_by_sid(struct pdb_methods *m,
1389 TALLOC_CTX *mem_ctx,
1390 const struct dom_sid *groupsid,
1391 const struct dom_sid *membersid,
1392 int mod_op)
1394 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1395 m->private_data, struct pdb_samba_dsdb_state);
1396 struct ldb_message *msg;
1397 int ret;
1398 struct ldb_message_element *el;
1399 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1400 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1401 msg = ldb_msg_new(tmp_ctx);
1402 if (msg == NULL) {
1403 TALLOC_FREE(tmp_ctx);
1404 return NT_STATUS_NO_MEMORY;
1407 msg->dn = ldb_dn_new_fmt(msg, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, groupsid));
1408 if (!msg->dn || !ldb_dn_validate(msg->dn)) {
1409 talloc_free(tmp_ctx);
1410 return NT_STATUS_NO_MEMORY;
1412 ret = ldb_msg_add_fmt(msg, "member", "<SID=%s>", dom_sid_string(tmp_ctx, membersid));
1413 if (ret != LDB_SUCCESS) {
1414 talloc_free(tmp_ctx);
1415 return NT_STATUS_NO_MEMORY;
1417 el = ldb_msg_find_element(msg, "member");
1418 el->flags = mod_op;
1420 /* No need for transactions here, the ldb auto-transaction
1421 * code will handle things for the single operation */
1422 ret = ldb_modify(state->ldb, msg);
1423 talloc_free(tmp_ctx);
1424 if (ret != LDB_SUCCESS) {
1425 DEBUG(10, ("ldb_modify failed: %s\n",
1426 ldb_errstring(state->ldb)));
1427 if (ret == LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS) {
1428 return NT_STATUS_MEMBER_IN_GROUP;
1430 if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
1431 return NT_STATUS_MEMBER_NOT_IN_GROUP;
1433 return NT_STATUS_LDAP(ret);
1436 return NT_STATUS_OK;
1439 static NTSTATUS pdb_samba_dsdb_mod_groupmem(struct pdb_methods *m,
1440 TALLOC_CTX *mem_ctx,
1441 uint32 grouprid, uint32 memberrid,
1442 int mod_op)
1444 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1445 m->private_data, struct pdb_samba_dsdb_state);
1446 const struct dom_sid *dom_sid, *groupsid, *membersid;
1447 NTSTATUS status;
1448 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1449 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1451 dom_sid = samdb_domain_sid(state->ldb);
1453 groupsid = dom_sid_add_rid(tmp_ctx, dom_sid, grouprid);
1454 if (groupsid == NULL) {
1455 TALLOC_FREE(tmp_ctx);
1456 return NT_STATUS_NO_MEMORY;
1458 membersid = dom_sid_add_rid(tmp_ctx, dom_sid, memberrid);
1459 if (membersid == NULL) {
1460 TALLOC_FREE(tmp_ctx);
1461 return NT_STATUS_NO_MEMORY;
1463 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, tmp_ctx, groupsid, membersid, mod_op);
1464 talloc_free(tmp_ctx);
1465 return status;
1468 static NTSTATUS pdb_samba_dsdb_add_groupmem(struct pdb_methods *m,
1469 TALLOC_CTX *mem_ctx,
1470 uint32 group_rid, uint32 member_rid)
1472 return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1473 LDB_FLAG_MOD_ADD);
1476 static NTSTATUS pdb_samba_dsdb_del_groupmem(struct pdb_methods *m,
1477 TALLOC_CTX *mem_ctx,
1478 uint32 group_rid, uint32 member_rid)
1480 return pdb_samba_dsdb_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1481 LDB_FLAG_MOD_DELETE);
1484 static NTSTATUS pdb_samba_dsdb_create_alias(struct pdb_methods *m,
1485 const char *name, uint32 *rid)
1487 TALLOC_CTX *frame = talloc_stackframe();
1488 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1489 m->private_data, struct pdb_samba_dsdb_state);
1490 struct dom_sid *sid;
1492 struct ldb_dn *dn;
1493 NTSTATUS status;
1495 /* Internally this uses transactions to ensure all the steps
1496 * happen or fail as one */
1497 status = dsdb_add_domain_alias(state->ldb, frame, name, &sid, &dn);
1498 if (!NT_STATUS_IS_OK(status)) {
1499 TALLOC_FREE(frame);
1502 sid_peek_rid(sid, rid);
1503 TALLOC_FREE(frame);
1504 return NT_STATUS_OK;
1507 static NTSTATUS pdb_samba_dsdb_delete_alias(struct pdb_methods *m,
1508 const struct dom_sid *sid)
1510 const char *attrs[] = { NULL };
1511 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1512 m->private_data, struct pdb_samba_dsdb_state);
1513 struct ldb_message *msg;
1514 struct ldb_dn *dn;
1515 int rc;
1516 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1517 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1519 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, sid));
1520 if (!dn || !ldb_dn_validate(dn)) {
1521 talloc_free(tmp_ctx);
1522 return NT_STATUS_NO_MEMORY;
1525 if (ldb_transaction_start(state->ldb) != LDB_SUCCESS) {
1526 DEBUG(0, ("Failed to start transaction in dsdb_add_domain_alias(): %s\n", ldb_errstring(state->ldb)));
1527 talloc_free(tmp_ctx);
1528 return NT_STATUS_INTERNAL_ERROR;
1531 rc = dsdb_search_one(state->ldb, tmp_ctx, &msg, dn, LDB_SCOPE_BASE, attrs, 0, "(objectclass=group)"
1532 "(|(grouptype=%d)(grouptype=%d)))",
1533 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1534 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1535 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1536 talloc_free(tmp_ctx);
1537 ldb_transaction_cancel(state->ldb);
1538 return NT_STATUS_NO_SUCH_ALIAS;
1540 rc = ldb_delete(state->ldb, dn);
1541 if (rc == LDB_ERR_NO_SUCH_OBJECT) {
1542 talloc_free(tmp_ctx);
1543 ldb_transaction_cancel(state->ldb);
1544 return NT_STATUS_NO_SUCH_ALIAS;
1545 } else if (rc != LDB_SUCCESS) {
1546 DEBUG(10, ("ldb_delete failed %s\n",
1547 ldb_errstring(state->ldb)));
1548 ldb_transaction_cancel(state->ldb);
1549 talloc_free(tmp_ctx);
1550 return NT_STATUS_LDAP(rc);
1553 if (ldb_transaction_commit(state->ldb) != LDB_SUCCESS) {
1554 DEBUG(0, ("Failed to commit transaction in pdb_samba_dsdb_delete_alias(): %s\n",
1555 ldb_errstring(state->ldb)));
1556 talloc_free(tmp_ctx);
1557 return NT_STATUS_INTERNAL_ERROR;
1560 talloc_free(tmp_ctx);
1561 return NT_STATUS_OK;
1564 #if 0
1565 static NTSTATUS pdb_samba_dsdb_set_aliasinfo(struct pdb_methods *m,
1566 const struct dom_sid *sid,
1567 struct acct_info *info)
1569 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1570 m->private_data, struct pdb_samba_dsdb_state);
1571 struct tldap_context *ld;
1572 const char *attrs[3] = { "objectSid", "description",
1573 "samAccountName" };
1574 struct ldb_message **msg;
1575 char *sidstr, *dn;
1576 int rc;
1577 struct tldap_mod *mods;
1578 int num_mods;
1579 bool ok;
1581 ld = pdb_samba_dsdb_ld(state);
1582 if (ld == NULL) {
1583 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1586 sidstr = sid_binstring(talloc_tos(), sid);
1587 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1589 rc = pdb_samba_dsdb_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1590 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1591 &msg, "(&(objectSid=%s)(objectclass=group)"
1592 "(|(grouptype=%d)(grouptype=%d)))",
1593 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1594 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1595 TALLOC_FREE(sidstr)
1596 if (rc != LDB_SUCCESS) {
1597 DEBUG(10, ("ldap_search failed %s\n",
1598 ldb_errstring(state->ldb)));
1599 return NT_STATUS_LDAP(rc);
1601 switch talloc_array_length(msg) {
1602 case 0:
1603 return NT_STATUS_NO_SUCH_ALIAS;
1604 case 1:
1605 break;
1606 default:
1607 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1610 if (!tldap_entry_dn(msg[0], &dn)) {
1611 TALLOC_FREE(msg);
1612 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1615 mods = NULL;
1616 num_mods = 0;
1617 ok = true;
1619 ok &= tldap_make_mod_fmt(
1620 msg[0], msg, &num_mods, &mods, "description",
1621 "%s", info->acct_desc);
1622 ok &= tldap_make_mod_fmt(
1623 msg[0], msg, &num_mods, &mods, "samAccountName",
1624 "%s", info->acct_name);
1625 if (!ok) {
1626 TALLOC_FREE(msg);
1627 return NT_STATUS_NO_MEMORY;
1629 if (num_mods == 0) {
1630 /* no change */
1631 TALLOC_FREE(msg);
1632 return NT_STATUS_OK;
1635 rc = tldap_modify(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
1636 TALLOC_FREE(msg);
1637 if (rc != LDB_SUCCESS) {
1638 DEBUG(10, ("ldap_modify failed: %s\n",
1639 ldb_errstring(state->ldb)));
1640 return NT_STATUS_LDAP(rc);
1642 return NT_STATUS_OK;
1644 #endif
1645 static NTSTATUS pdb_samba_dsdb_add_aliasmem(struct pdb_methods *m,
1646 const struct dom_sid *alias,
1647 const struct dom_sid *member)
1649 NTSTATUS status;
1650 TALLOC_CTX *frame = talloc_stackframe();
1651 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_ADD);
1652 talloc_free(frame);
1653 return status;
1656 static NTSTATUS pdb_samba_dsdb_del_aliasmem(struct pdb_methods *m,
1657 const struct dom_sid *alias,
1658 const struct dom_sid *member)
1660 NTSTATUS status;
1661 TALLOC_CTX *frame = talloc_stackframe();
1662 status = pdb_samba_dsdb_mod_groupmem_by_sid(m, frame, alias, member, LDB_FLAG_MOD_DELETE);
1663 talloc_free(frame);
1664 return status;
1667 static NTSTATUS pdb_samba_dsdb_enum_aliasmem(struct pdb_methods *m,
1668 const struct dom_sid *alias,
1669 TALLOC_CTX *mem_ctx,
1670 struct dom_sid **pmembers,
1671 size_t *pnum_members)
1673 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1674 m->private_data, struct pdb_samba_dsdb_state);
1675 struct ldb_dn *dn;
1676 unsigned int num_members;
1677 NTSTATUS status;
1678 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1679 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1681 dn = ldb_dn_new_fmt(tmp_ctx, state->ldb, "<SID=%s>", dom_sid_string(tmp_ctx, alias));
1682 if (!dn || !ldb_dn_validate(dn)) {
1683 return NT_STATUS_NO_MEMORY;
1686 status = dsdb_enum_group_mem(state->ldb, mem_ctx, dn, pmembers, &num_members);
1687 *pnum_members = num_members;
1688 if (NT_STATUS_IS_OK(status)) {
1689 talloc_steal(mem_ctx, pmembers);
1691 talloc_free(tmp_ctx);
1692 return status;
1695 static NTSTATUS pdb_samba_dsdb_enum_alias_memberships(struct pdb_methods *m,
1696 TALLOC_CTX *mem_ctx,
1697 const struct dom_sid *domain_sid,
1698 const struct dom_sid *members,
1699 size_t num_members,
1700 uint32_t **palias_rids,
1701 size_t *pnum_alias_rids)
1703 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1704 m->private_data, struct pdb_samba_dsdb_state);
1705 uint32_t *alias_rids = NULL;
1706 size_t num_alias_rids = 0;
1707 int i;
1708 struct dom_sid *groupSIDs = NULL;
1709 unsigned int num_groupSIDs = 0;
1710 char *filter;
1711 NTSTATUS status;
1712 const char *sid_string;
1713 const char *sid_dn;
1714 DATA_BLOB sid_blob;
1716 TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
1717 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1719 * TODO: Get the filter right so that we only get the aliases from
1720 * either the SAM or BUILTIN
1723 filter = talloc_asprintf(tmp_ctx, "(&(objectClass=group)(groupType:1.2.840.113556.1.4.803:=%u))",
1724 GROUP_TYPE_BUILTIN_LOCAL_GROUP);
1725 if (filter == NULL) {
1726 return NT_STATUS_NO_MEMORY;
1729 for (i = 0; i < num_members; i++) {
1730 sid_string = dom_sid_string(tmp_ctx, &members[i]);
1731 if (sid_string == NULL) {
1732 TALLOC_FREE(tmp_ctx);
1733 return NT_STATUS_NO_MEMORY;
1736 sid_dn = talloc_asprintf(tmp_ctx, "<SID=%s>", sid_string);
1737 if (sid_dn == NULL) {
1738 TALLOC_FREE(tmp_ctx);
1739 return NT_STATUS_NO_MEMORY;
1742 sid_blob = data_blob_string_const(sid_dn);
1744 status = dsdb_expand_nested_groups(state->ldb, &sid_blob, true, filter,
1745 tmp_ctx, &groupSIDs, &num_groupSIDs);
1746 if (!NT_STATUS_IS_OK(status)) {
1747 talloc_free(tmp_ctx);
1748 return status;
1752 alias_rids = talloc_array(mem_ctx, uint32_t, num_groupSIDs);
1753 if (alias_rids == NULL) {
1754 talloc_free(tmp_ctx);
1755 return NT_STATUS_NO_MEMORY;
1758 for (i=0; i<num_groupSIDs; i++) {
1759 if (sid_peek_check_rid(domain_sid, &groupSIDs[i],
1760 &alias_rids[num_alias_rids])) {
1761 num_alias_rids++;;
1765 *palias_rids = alias_rids;
1766 *pnum_alias_rids = num_alias_rids;
1767 return NT_STATUS_OK;
1770 static NTSTATUS pdb_samba_dsdb_lookup_rids(struct pdb_methods *m,
1771 const struct dom_sid *domain_sid,
1772 int num_rids,
1773 uint32 *rids,
1774 const char **names,
1775 enum lsa_SidType *lsa_attrs)
1777 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1778 m->private_data, struct pdb_samba_dsdb_state);
1779 NTSTATUS status;
1781 TALLOC_CTX *tmp_ctx;
1783 if (num_rids == 0) {
1784 return NT_STATUS_NONE_MAPPED;
1787 tmp_ctx = talloc_stackframe();
1788 NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
1790 status = dsdb_lookup_rids(state->ldb, tmp_ctx, domain_sid, num_rids, rids, names, lsa_attrs);
1791 talloc_free(tmp_ctx);
1792 return status;
1795 static NTSTATUS pdb_samba_dsdb_lookup_names(struct pdb_methods *m,
1796 const struct dom_sid *domain_sid,
1797 int num_names,
1798 const char **pp_names,
1799 uint32 *rids,
1800 enum lsa_SidType *attrs)
1802 return NT_STATUS_NOT_IMPLEMENTED;
1805 static NTSTATUS pdb_samba_dsdb_get_account_policy(struct pdb_methods *m,
1806 enum pdb_policy_type type,
1807 uint32_t *value)
1809 return account_policy_get(type, value)
1810 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1813 static NTSTATUS pdb_samba_dsdb_set_account_policy(struct pdb_methods *m,
1814 enum pdb_policy_type type,
1815 uint32_t value)
1817 return account_policy_set(type, value)
1818 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1821 static NTSTATUS pdb_samba_dsdb_get_seq_num(struct pdb_methods *m,
1822 time_t *seq_num_out)
1824 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1825 m->private_data, struct pdb_samba_dsdb_state);
1826 uint64_t seq_num;
1827 int ret = ldb_sequence_number(state->ldb, LDB_SEQ_HIGHEST_SEQ, &seq_num);
1828 if (ret == LDB_SUCCESS) {
1829 *seq_num_out = seq_num;
1830 return NT_STATUS_OK;
1831 } else {
1832 return NT_STATUS_UNSUCCESSFUL;
1836 struct pdb_samba_dsdb_search_state {
1837 uint32_t acct_flags;
1838 struct samr_displayentry *entries;
1839 uint32_t num_entries;
1840 ssize_t array_size;
1841 uint32_t current;
1844 static bool pdb_samba_dsdb_next_entry(struct pdb_search *search,
1845 struct samr_displayentry *entry)
1847 struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1848 search->private_data, struct pdb_samba_dsdb_search_state);
1850 if (state->current == state->num_entries) {
1851 return false;
1854 entry->idx = state->entries[state->current].idx;
1855 entry->rid = state->entries[state->current].rid;
1856 entry->acct_flags = state->entries[state->current].acct_flags;
1858 entry->account_name = talloc_strdup(
1859 search, state->entries[state->current].account_name);
1860 entry->fullname = talloc_strdup(
1861 search, state->entries[state->current].fullname);
1862 entry->description = talloc_strdup(
1863 search, state->entries[state->current].description);
1865 state->current += 1;
1866 return true;
1869 static void pdb_samba_dsdb_search_end(struct pdb_search *search)
1871 struct pdb_samba_dsdb_search_state *state = talloc_get_type_abort(
1872 search->private_data, struct pdb_samba_dsdb_search_state);
1873 talloc_free(state);
1876 static bool pdb_samba_dsdb_search_filter(struct pdb_methods *m,
1877 struct pdb_search *search,
1878 struct pdb_samba_dsdb_search_state **pstate,
1879 const char *exp_fmt, ...) _PRINTF_ATTRIBUTE(4, 5)
1881 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
1882 m->private_data, struct pdb_samba_dsdb_state);
1883 struct pdb_samba_dsdb_search_state *sstate;
1884 const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1885 "userAccountControl", "description", NULL };
1886 struct ldb_result *res;
1887 int i, rc, num_users;
1889 va_list ap;
1890 char *expression = NULL;
1892 TALLOC_CTX *tmp_ctx = talloc_stackframe();
1893 if (!tmp_ctx) {
1894 return false;
1897 va_start(ap, exp_fmt);
1898 expression = talloc_vasprintf(tmp_ctx, exp_fmt, ap);
1899 va_end(ap);
1901 if (!expression) {
1902 talloc_free(tmp_ctx);
1903 return LDB_ERR_OPERATIONS_ERROR;
1906 sstate = talloc_zero(tmp_ctx, struct pdb_samba_dsdb_search_state);
1907 if (sstate == NULL) {
1908 talloc_free(tmp_ctx);
1909 return false;
1912 rc = dsdb_search(state->ldb, tmp_ctx, &res, ldb_get_default_basedn(state->ldb), LDB_SCOPE_SUBTREE, attrs, 0, "%s", expression);
1913 if (rc != LDB_SUCCESS) {
1914 talloc_free(tmp_ctx);
1915 DEBUG(10, ("dsdb_search failed: %s\n",
1916 ldb_errstring(state->ldb)));
1917 return false;
1920 num_users = res->count;
1922 sstate->entries = talloc_array(sstate, struct samr_displayentry,
1923 num_users);
1924 if (sstate->entries == NULL) {
1925 talloc_free(tmp_ctx);
1926 DEBUG(10, ("talloc failed\n"));
1927 return false;
1930 sstate->num_entries = 0;
1932 for (i=0; i<num_users; i++) {
1933 struct samr_displayentry *e;
1934 struct dom_sid *sid;
1936 e = &sstate->entries[sstate->num_entries];
1938 e->idx = sstate->num_entries;
1939 sid = samdb_result_dom_sid(tmp_ctx, res->msgs[i], "objectSid");
1940 if (!sid) {
1941 talloc_free(tmp_ctx);
1942 DEBUG(10, ("Could not pull SID\n"));
1943 return false;
1945 sid_peek_rid(sid, &e->rid);
1947 e->acct_flags = samdb_result_acct_flags(res->msgs[i], "userAccountControl");
1948 e->account_name = ldb_msg_find_attr_as_string(
1949 res->msgs[i], "samAccountName", NULL);
1950 if (e->account_name == NULL) {
1951 talloc_free(tmp_ctx);
1952 return false;
1954 e->fullname = ldb_msg_find_attr_as_string(
1955 res->msgs[i], "displayName", "");
1956 e->description = ldb_msg_find_attr_as_string(
1957 res->msgs[i], "description", "");
1959 sstate->num_entries += 1;
1960 if (sstate->num_entries >= num_users) {
1961 break;
1964 talloc_steal(sstate->entries, res->msgs);
1965 search->private_data = talloc_steal(search, sstate);
1966 search->next_entry = pdb_samba_dsdb_next_entry;
1967 search->search_end = pdb_samba_dsdb_search_end;
1968 *pstate = sstate;
1969 talloc_free(tmp_ctx);
1970 return true;
1973 static bool pdb_samba_dsdb_search_users(struct pdb_methods *m,
1974 struct pdb_search *search,
1975 uint32 acct_flags)
1977 struct pdb_samba_dsdb_search_state *sstate;
1978 bool ret;
1980 ret = pdb_samba_dsdb_search_filter(m, search, &sstate, "(objectclass=user)");
1981 if (!ret) {
1982 return false;
1984 sstate->acct_flags = acct_flags;
1985 return true;
1988 static bool pdb_samba_dsdb_search_groups(struct pdb_methods *m,
1989 struct pdb_search *search)
1991 struct pdb_samba_dsdb_search_state *sstate;
1992 bool ret;
1994 ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
1995 "(&(grouptype=%d)(objectclass=group))",
1996 GTYPE_SECURITY_GLOBAL_GROUP);
1997 if (!ret) {
1998 return false;
2000 sstate->acct_flags = 0;
2001 return true;
2004 static bool pdb_samba_dsdb_search_aliases(struct pdb_methods *m,
2005 struct pdb_search *search,
2006 const struct dom_sid *sid)
2008 struct pdb_samba_dsdb_search_state *sstate;
2009 bool ret;
2011 ret = pdb_samba_dsdb_search_filter(m, search, &sstate,
2012 "(&(grouptype=%d)(objectclass=group))",
2013 sid_check_is_builtin(sid)
2014 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2015 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2016 if (!ret) {
2017 return false;
2019 sstate->acct_flags = 0;
2020 return true;
2023 static bool pdb_samba_dsdb_uid_to_sid(struct pdb_methods *m, uid_t uid,
2024 struct dom_sid *sid)
2026 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2027 m->private_data, struct pdb_samba_dsdb_state);
2028 NTSTATUS status;
2029 struct id_map id_map;
2030 struct id_map *id_maps[2];
2031 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2032 if (!tmp_ctx) {
2033 return false;
2036 id_map.xid.id = uid;
2037 id_map.xid.type = ID_TYPE_UID;
2038 id_maps[0] = &id_map;
2039 id_maps[1] = NULL;
2041 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2042 if (!NT_STATUS_IS_OK(status)) {
2043 talloc_free(tmp_ctx);
2044 return false;
2046 *sid = *id_map.sid;
2047 talloc_free(tmp_ctx);
2048 return true;
2051 static bool pdb_samba_dsdb_gid_to_sid(struct pdb_methods *m, gid_t gid,
2052 struct dom_sid *sid)
2054 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2055 m->private_data, struct pdb_samba_dsdb_state);
2056 NTSTATUS status;
2057 struct id_map id_map;
2058 struct id_map *id_maps[2];
2059 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2060 if (!tmp_ctx) {
2061 return false;
2064 id_map.xid.id = gid;
2065 id_map.xid.type = ID_TYPE_GID;
2066 id_maps[0] = &id_map;
2067 id_maps[1] = NULL;
2069 status = idmap_xids_to_sids(state->idmap_ctx, tmp_ctx, id_maps);
2070 if (!NT_STATUS_IS_OK(status)) {
2071 talloc_free(tmp_ctx);
2072 return false;
2074 *sid = *id_map.sid;
2075 talloc_free(tmp_ctx);
2076 return true;
2079 static bool pdb_samba_dsdb_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2080 struct unixid *id)
2082 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2083 m->private_data, struct pdb_samba_dsdb_state);
2084 struct id_map id_map;
2085 struct id_map *id_maps[2];
2086 NTSTATUS status;
2087 TALLOC_CTX *tmp_ctx = talloc_stackframe();
2088 if (!tmp_ctx) {
2089 return false;
2092 ZERO_STRUCT(id_map);
2093 id_map.sid = discard_const_p(struct dom_sid, sid);
2094 id_maps[0] = &id_map;
2095 id_maps[1] = NULL;
2097 status = idmap_sids_to_xids(state->idmap_ctx, tmp_ctx, id_maps);
2098 talloc_free(tmp_ctx);
2099 if (!NT_STATUS_IS_OK(status)) {
2100 return false;
2102 if (id_map.xid.type != ID_TYPE_NOT_SPECIFIED) {
2103 *id = id_map.xid;
2104 return true;
2106 return false;
2109 static uint32_t pdb_samba_dsdb_capabilities(struct pdb_methods *m)
2111 return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
2114 static bool pdb_samba_dsdb_new_rid(struct pdb_methods *m, uint32 *rid)
2116 return false;
2119 static bool pdb_samba_dsdb_get_trusteddom_pw(struct pdb_methods *m,
2120 const char *domain, char** pwd,
2121 struct dom_sid *sid,
2122 time_t *pass_last_set_time)
2124 return false;
2127 static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
2128 const char* domain, const char* pwd,
2129 const struct dom_sid *sid)
2131 return false;
2134 static bool pdb_samba_dsdb_del_trusteddom_pw(struct pdb_methods *m,
2135 const char *domain)
2137 return false;
2140 static NTSTATUS pdb_samba_dsdb_enum_trusteddoms(struct pdb_methods *m,
2141 TALLOC_CTX *mem_ctx,
2142 uint32 *num_domains,
2143 struct trustdom_info ***domains)
2145 *num_domains = 0;
2146 *domains = NULL;
2147 return NT_STATUS_OK;
2150 static bool pdb_samba_dsdb_is_responsible_for_wellknown(struct pdb_methods *m)
2152 return true;
2155 static bool pdb_samba_dsdb_is_responsible_for_everything_else(struct pdb_methods *m)
2157 return true;
2160 static void pdb_samba_dsdb_init_methods(struct pdb_methods *m)
2162 m->name = "samba_dsdb";
2163 m->get_domain_info = pdb_samba_dsdb_get_domain_info;
2164 m->getsampwnam = pdb_samba_dsdb_getsampwnam;
2165 m->getsampwsid = pdb_samba_dsdb_getsampwsid;
2166 m->create_user = pdb_samba_dsdb_create_user;
2167 m->delete_user = pdb_samba_dsdb_delete_user;
2168 m->add_sam_account = pdb_samba_dsdb_add_sam_account;
2169 m->update_sam_account = pdb_samba_dsdb_update_sam_account;
2170 m->delete_sam_account = pdb_samba_dsdb_delete_sam_account;
2171 m->rename_sam_account = pdb_samba_dsdb_rename_sam_account;
2172 m->update_login_attempts = pdb_samba_dsdb_update_login_attempts;
2173 m->getgrsid = pdb_samba_dsdb_getgrsid;
2174 m->getgrgid = pdb_samba_dsdb_getgrgid;
2175 m->getgrnam = pdb_samba_dsdb_getgrnam;
2176 m->create_dom_group = pdb_samba_dsdb_create_dom_group;
2177 m->delete_dom_group = pdb_samba_dsdb_delete_dom_group;
2178 m->add_group_mapping_entry = pdb_samba_dsdb_add_group_mapping_entry;
2179 m->update_group_mapping_entry = pdb_samba_dsdb_update_group_mapping_entry;
2180 m->delete_group_mapping_entry = pdb_samba_dsdb_delete_group_mapping_entry;
2181 m->enum_group_mapping = pdb_samba_dsdb_enum_group_mapping;
2182 m->enum_group_members = pdb_samba_dsdb_enum_group_members;
2183 m->enum_group_memberships = pdb_samba_dsdb_enum_group_memberships;
2184 m->set_unix_primary_group = pdb_samba_dsdb_set_unix_primary_group;
2185 m->add_groupmem = pdb_samba_dsdb_add_groupmem;
2186 m->del_groupmem = pdb_samba_dsdb_del_groupmem;
2187 m->create_alias = pdb_samba_dsdb_create_alias;
2188 m->delete_alias = pdb_samba_dsdb_delete_alias;
2189 m->get_aliasinfo = pdb_default_get_aliasinfo;
2190 m->add_aliasmem = pdb_samba_dsdb_add_aliasmem;
2191 m->del_aliasmem = pdb_samba_dsdb_del_aliasmem;
2192 m->enum_aliasmem = pdb_samba_dsdb_enum_aliasmem;
2193 m->enum_alias_memberships = pdb_samba_dsdb_enum_alias_memberships;
2194 m->lookup_rids = pdb_samba_dsdb_lookup_rids;
2195 m->lookup_names = pdb_samba_dsdb_lookup_names;
2196 m->get_account_policy = pdb_samba_dsdb_get_account_policy;
2197 m->set_account_policy = pdb_samba_dsdb_set_account_policy;
2198 m->get_seq_num = pdb_samba_dsdb_get_seq_num;
2199 m->search_users = pdb_samba_dsdb_search_users;
2200 m->search_groups = pdb_samba_dsdb_search_groups;
2201 m->search_aliases = pdb_samba_dsdb_search_aliases;
2202 m->uid_to_sid = pdb_samba_dsdb_uid_to_sid;
2203 m->gid_to_sid = pdb_samba_dsdb_gid_to_sid;
2204 m->sid_to_id = pdb_samba_dsdb_sid_to_id;
2205 m->capabilities = pdb_samba_dsdb_capabilities;
2206 m->new_rid = pdb_samba_dsdb_new_rid;
2207 m->get_trusteddom_pw = pdb_samba_dsdb_get_trusteddom_pw;
2208 m->set_trusteddom_pw = pdb_samba_dsdb_set_trusteddom_pw;
2209 m->del_trusteddom_pw = pdb_samba_dsdb_del_trusteddom_pw;
2210 m->enum_trusteddoms = pdb_samba_dsdb_enum_trusteddoms;
2211 m->is_responsible_for_wellknown =
2212 pdb_samba_dsdb_is_responsible_for_wellknown;
2213 m->is_responsible_for_everything_else =
2214 pdb_samba_dsdb_is_responsible_for_everything_else;
2217 static void free_private_data(void **vp)
2219 struct pdb_samba_dsdb_state *state = talloc_get_type_abort(
2220 *vp, struct pdb_samba_dsdb_state);
2221 talloc_unlink(state, state->ldb);
2222 return;
2225 static NTSTATUS pdb_samba_dsdb_init_secrets(struct pdb_methods *m)
2227 struct pdb_domain_info *dom_info;
2228 struct dom_sid stored_sid;
2229 struct GUID stored_guid;
2230 bool sid_exists_and_matches = false;
2231 bool guid_exists_and_matches = false;
2232 bool ret;
2234 dom_info = pdb_samba_dsdb_get_domain_info(m, m);
2235 if (!dom_info) {
2236 return NT_STATUS_UNSUCCESSFUL;
2239 ret = secrets_fetch_domain_sid(dom_info->name, &stored_sid);
2240 if (ret) {
2241 if (dom_sid_equal(&stored_sid, &dom_info->sid)) {
2242 sid_exists_and_matches = true;
2246 if (sid_exists_and_matches == false) {
2247 secrets_clear_domain_protection(dom_info->name);
2248 ret = secrets_store_domain_sid(dom_info->name,
2249 &dom_info->sid);
2250 ret &= secrets_mark_domain_protected(dom_info->name);
2251 if (!ret) {
2252 goto done;
2256 ret = secrets_fetch_domain_guid(dom_info->name, &stored_guid);
2257 if (ret) {
2258 if (GUID_equal(&stored_guid, &dom_info->guid)) {
2259 guid_exists_and_matches = true;
2263 if (guid_exists_and_matches == false) {
2264 secrets_clear_domain_protection(dom_info->name);
2265 ret = secrets_store_domain_guid(dom_info->name,
2266 &dom_info->guid);
2267 ret &= secrets_mark_domain_protected(dom_info->name);
2268 if (!ret) {
2269 goto done;
2273 done:
2274 TALLOC_FREE(dom_info);
2275 if (!ret) {
2276 return NT_STATUS_UNSUCCESSFUL;
2278 return NT_STATUS_OK;
2281 static NTSTATUS pdb_init_samba_dsdb(struct pdb_methods **pdb_method,
2282 const char *location)
2284 struct pdb_methods *m;
2285 struct pdb_samba_dsdb_state *state;
2286 NTSTATUS status;
2288 if ( !NT_STATUS_IS_OK(status = make_pdb_method( &m )) ) {
2289 return status;
2292 state = talloc_zero(m, struct pdb_samba_dsdb_state);
2293 if (state == NULL) {
2294 goto nomem;
2296 m->private_data = state;
2297 m->free_private_data = free_private_data;
2298 pdb_samba_dsdb_init_methods(m);
2300 state->ev = s4_event_context_init(state);
2301 if (!state->ev) {
2302 DEBUG(0, ("s4_event_context_init failed\n"));
2303 goto nomem;
2306 state->lp_ctx = loadparm_init_s3(state, loadparm_s3_helpers());
2307 if (state->lp_ctx == NULL) {
2308 DEBUG(0, ("loadparm_init_s3 failed\n"));
2309 goto nomem;
2312 if (location) {
2313 state->ldb = samdb_connect_url(state,
2314 state->ev,
2315 state->lp_ctx,
2316 system_session(state->lp_ctx),
2317 0, location);
2318 } else {
2319 state->ldb = samdb_connect(state,
2320 state->ev,
2321 state->lp_ctx,
2322 system_session(state->lp_ctx), 0);
2325 if (!state->ldb) {
2326 DEBUG(0, ("samdb_connect failed\n"));
2327 status = NT_STATUS_INTERNAL_ERROR;
2328 goto fail;
2331 state->idmap_ctx = idmap_init(state, state->ev,
2332 state->lp_ctx);
2333 if (!state->idmap_ctx) {
2334 DEBUG(0, ("idmap failed\n"));
2335 status = NT_STATUS_INTERNAL_ERROR;
2336 goto fail;
2339 status = pdb_samba_dsdb_init_secrets(m);
2340 if (!NT_STATUS_IS_OK(status)) {
2341 DEBUG(10, ("pdb_samba_dsdb_init_secrets failed!\n"));
2342 goto fail;
2345 *pdb_method = m;
2346 return NT_STATUS_OK;
2347 nomem:
2348 status = NT_STATUS_NO_MEMORY;
2349 fail:
2350 TALLOC_FREE(m);
2351 return status;
2354 NTSTATUS pdb_samba_dsdb_init(void);
2355 NTSTATUS pdb_samba_dsdb_init(void)
2357 NTSTATUS status = smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba_dsdb",
2358 pdb_init_samba_dsdb);
2359 if (!NT_STATUS_IS_OK(status)) {
2360 return status;
2362 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "samba4",
2363 pdb_init_samba_dsdb);