talloc: Fix copy&paste errors
[Samba/gebeck_regimport.git] / source3 / passdb / pdb_ads.c
blobcd7781a1afa4c6e8607853ff6c76bcd5eb3bd7d7
1 /*
2 Unix SMB/CIFS implementation.
3 pdb_ldap with ads schema
4 Copyright (C) Volker Lendecke 2009
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "passdb.h"
22 #include "tldap.h"
23 #include "tldap_util.h"
24 #include "../libds/common/flags.h"
25 #include "secrets.h"
26 #include "../librpc/gen_ndr/samr.h"
27 #include "../libcli/ldap/ldap_ndr.h"
28 #include "../libcli/security/security.h"
29 #include "../libds/common/flag_mapping.h"
31 struct pdb_ads_state {
32 struct sockaddr_un socket_address;
33 struct tldap_context *ld;
34 struct dom_sid domainsid;
35 struct GUID domainguid;
36 char *domaindn;
37 char *configdn;
38 char *netbiosname;
41 struct pdb_ads_samu_private {
42 char *dn;
43 struct tldap_message *ldapmsg;
46 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
47 struct dom_sid *sid);
48 static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
49 struct dom_sid *psid);
50 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
51 const struct dom_sid *sid,
52 TALLOC_CTX *mem_ctx, char **pdn);
53 static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state);
54 static int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base,
55 int scope, const char *attrs[], int num_attrs,
56 int attrsonly,
57 TALLOC_CTX *mem_ctx, struct tldap_message ***res,
58 const char *fmt, ...);
59 static NTSTATUS pdb_ads_getsamupriv(struct pdb_ads_state *state,
60 const char *filter,
61 TALLOC_CTX *mem_ctx,
62 struct pdb_ads_samu_private **presult);
64 static bool pdb_ads_pull_time(struct tldap_message *msg, const char *attr,
65 time_t *ptime)
67 uint64_t tmp;
69 if (!tldap_pull_uint64(msg, attr, &tmp)) {
70 return false;
72 *ptime = nt_time_to_unix(tmp);
73 return true;
76 static gid_t pdb_ads_sid2gid(const struct dom_sid *sid)
78 uint32_t rid;
79 sid_peek_rid(sid, &rid);
80 return rid;
83 static char *pdb_ads_domaindn2dns(TALLOC_CTX *mem_ctx, char *dn)
85 char *result, *p;
87 result = talloc_string_sub2(mem_ctx, dn, "DC=", "", false, false,
88 true);
89 if (result == NULL) {
90 return NULL;
93 while ((p = strchr_m(result, ',')) != NULL) {
94 *p = '.';
97 return result;
100 static struct pdb_domain_info *pdb_ads_get_domain_info(
101 struct pdb_methods *m, TALLOC_CTX *mem_ctx)
103 struct pdb_ads_state *state = talloc_get_type_abort(
104 m->private_data, struct pdb_ads_state);
105 struct pdb_domain_info *info;
106 struct tldap_message *rootdse;
107 char *tmp;
109 info = talloc(mem_ctx, struct pdb_domain_info);
110 if (info == NULL) {
111 return NULL;
113 info->name = talloc_strdup(info, state->netbiosname);
114 if (info->name == NULL) {
115 goto fail;
117 info->dns_domain = pdb_ads_domaindn2dns(info, state->domaindn);
118 if (info->dns_domain == NULL) {
119 goto fail;
122 rootdse = tldap_rootdse(state->ld);
123 tmp = tldap_talloc_single_attribute(rootdse, "rootDomainNamingContext",
124 talloc_tos());
125 if (tmp == NULL) {
126 goto fail;
128 info->dns_forest = pdb_ads_domaindn2dns(info, tmp);
129 TALLOC_FREE(tmp);
130 if (info->dns_forest == NULL) {
131 goto fail;
133 info->sid = state->domainsid;
134 info->guid = state->domainguid;
135 return info;
137 fail:
138 TALLOC_FREE(info);
139 return NULL;
142 static struct pdb_ads_samu_private *pdb_ads_get_samu_private(
143 struct pdb_methods *m, struct samu *sam)
145 struct pdb_ads_state *state = talloc_get_type_abort(
146 m->private_data, struct pdb_ads_state);
147 struct pdb_ads_samu_private *result;
148 char *sidstr, *filter;
149 NTSTATUS status;
151 result = (struct pdb_ads_samu_private *)
152 pdb_get_backend_private_data(sam, m);
154 if (result != NULL) {
155 return talloc_get_type_abort(
156 result, struct pdb_ads_samu_private);
159 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), pdb_get_user_sid(sam));
160 if (sidstr == NULL) {
161 return NULL;
164 filter = talloc_asprintf(
165 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
166 TALLOC_FREE(sidstr);
167 if (filter == NULL) {
168 return NULL;
171 status = pdb_ads_getsamupriv(state, filter, sam, &result);
172 TALLOC_FREE(filter);
173 if (!NT_STATUS_IS_OK(status)) {
174 return NULL;
177 return result;
180 static NTSTATUS pdb_ads_init_sam_from_priv(struct pdb_methods *m,
181 struct samu *sam,
182 struct pdb_ads_samu_private *priv)
184 struct pdb_ads_state *state = talloc_get_type_abort(
185 m->private_data, struct pdb_ads_state);
186 TALLOC_CTX *frame = talloc_stackframe();
187 NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
188 struct tldap_message *entry = priv->ldapmsg;
189 char *str;
190 time_t tmp_time;
191 struct dom_sid sid;
192 uint64_t n;
193 uint32_t i;
194 DATA_BLOB blob;
196 str = tldap_talloc_single_attribute(entry, "samAccountName", sam);
197 if (str == NULL) {
198 DEBUG(10, ("no samAccountName\n"));
199 goto fail;
201 pdb_set_username(sam, str, PDB_SET);
203 if (pdb_ads_pull_time(entry, "lastLogon", &tmp_time)) {
204 pdb_set_logon_time(sam, tmp_time, PDB_SET);
206 if (pdb_ads_pull_time(entry, "lastLogoff", &tmp_time)) {
207 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
209 if (pdb_ads_pull_time(entry, "pwdLastSet", &tmp_time)) {
210 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
212 if (pdb_ads_pull_time(entry, "accountExpires", &tmp_time)) {
213 pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
216 str = tldap_talloc_single_attribute(entry, "displayName",
217 talloc_tos());
218 if (str != NULL) {
219 pdb_set_fullname(sam, str, PDB_SET);
222 str = tldap_talloc_single_attribute(entry, "homeDirectory",
223 talloc_tos());
224 if (str != NULL) {
225 pdb_set_homedir(sam, str, PDB_SET);
228 str = tldap_talloc_single_attribute(entry, "homeDrive", talloc_tos());
229 if (str != NULL) {
230 pdb_set_dir_drive(sam, str, PDB_SET);
233 str = tldap_talloc_single_attribute(entry, "scriptPath", talloc_tos());
234 if (str != NULL) {
235 pdb_set_logon_script(sam, str, PDB_SET);
238 str = tldap_talloc_single_attribute(entry, "profilePath",
239 talloc_tos());
240 if (str != NULL) {
241 pdb_set_profile_path(sam, str, PDB_SET);
244 str = tldap_talloc_single_attribute(entry, "profilePath",
245 talloc_tos());
246 if (str != NULL) {
247 pdb_set_profile_path(sam, str, PDB_SET);
250 str = tldap_talloc_single_attribute(entry, "comment",
251 talloc_tos());
252 if (str != NULL) {
253 pdb_set_comment(sam, str, PDB_SET);
256 str = tldap_talloc_single_attribute(entry, "description",
257 talloc_tos());
258 if (str != NULL) {
259 pdb_set_acct_desc(sam, str, PDB_SET);
262 str = tldap_talloc_single_attribute(entry, "userWorkstations",
263 talloc_tos());
264 if (str != NULL) {
265 pdb_set_workstations(sam, str, PDB_SET);
268 str = tldap_talloc_single_attribute(entry, "userParameters",
269 talloc_tos());
270 if (str != NULL) {
271 pdb_set_munged_dial(sam, str, PDB_SET);
274 if (!tldap_pull_binsid(entry, "objectSid", &sid)) {
275 DEBUG(10, ("Could not pull SID\n"));
276 goto fail;
278 pdb_set_user_sid(sam, &sid, PDB_SET);
280 if (!tldap_pull_uint64(entry, "userAccountControl", &n)) {
281 DEBUG(10, ("Could not pull userAccountControl\n"));
282 goto fail;
284 pdb_set_acct_ctrl(sam, ds_uf2acb(n), PDB_SET);
286 if (tldap_get_single_valueblob(entry, "unicodePwd", &blob)) {
287 if (blob.length != NT_HASH_LEN) {
288 DEBUG(0, ("Got NT hash of length %d, expected %d\n",
289 (int)blob.length, NT_HASH_LEN));
290 goto fail;
292 pdb_set_nt_passwd(sam, blob.data, PDB_SET);
295 if (tldap_get_single_valueblob(entry, "dBCSPwd", &blob)) {
296 if (blob.length != LM_HASH_LEN) {
297 DEBUG(0, ("Got LM hash of length %d, expected %d\n",
298 (int)blob.length, LM_HASH_LEN));
299 goto fail;
301 pdb_set_lanman_passwd(sam, blob.data, PDB_SET);
304 if (tldap_pull_uint64(entry, "primaryGroupID", &n)) {
305 sid_compose(&sid, &state->domainsid, n);
306 pdb_set_group_sid(sam, &sid, PDB_SET);
310 if (tldap_pull_uint32(entry, "countryCode", &i)) {
311 pdb_set_country_code(sam, i, PDB_SET);
314 if (tldap_pull_uint32(entry, "codePage", &i)) {
315 pdb_set_code_page(sam, i, PDB_SET);
318 if (tldap_get_single_valueblob(entry, "logonHours", &blob)) {
320 if (blob.length > MAX_HOURS_LEN) {
321 status = NT_STATUS_INVALID_PARAMETER;
322 goto fail;
324 pdb_set_logon_divs(sam, blob.length * 8, PDB_SET);
325 pdb_set_hours_len(sam, blob.length, PDB_SET);
326 pdb_set_hours(sam, blob.data, blob.length, PDB_SET);
328 } else {
329 uint8_t hours[21];
330 pdb_set_logon_divs(sam, sizeof(hours)/8, PDB_SET);
331 pdb_set_hours_len(sam, sizeof(hours), PDB_SET);
332 memset(hours, 0xff, sizeof(hours));
333 pdb_set_hours(sam, hours, sizeof(hours), PDB_SET);
336 status = NT_STATUS_OK;
337 fail:
338 TALLOC_FREE(frame);
339 return status;
342 static bool pdb_ads_make_time_mod(struct tldap_message *existing,
343 TALLOC_CTX *mem_ctx,
344 struct tldap_mod **pmods, int *pnum_mods,
345 const char *attrib, time_t t)
347 uint64_t nt_time;
349 unix_to_nt_time(&nt_time, t);
351 return tldap_make_mod_fmt(
352 existing, mem_ctx, pmods, pnum_mods, attrib,
353 "%llu", nt_time);
356 static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state,
357 struct tldap_message *existing,
358 TALLOC_CTX *mem_ctx,
359 struct tldap_mod **pmods, int *pnum_mods,
360 struct samu *sam)
362 bool ret = true;
363 DATA_BLOB blob;
364 const char *pw;
366 /* TODO: All fields :-) */
368 ret &= tldap_make_mod_fmt(
369 existing, mem_ctx, pmods, pnum_mods, "displayName",
370 "%s", pdb_get_fullname(sam));
372 pw = pdb_get_plaintext_passwd(sam);
375 * If we have the plain text pw, this is probably about to be
376 * set. Is this true always?
378 if (pw != NULL) {
379 char *pw_quote;
380 uint8_t *pw_utf16;
381 size_t pw_utf16_len;
383 pw_quote = talloc_asprintf(talloc_tos(), "\"%s\"", pw);
384 if (pw_quote == NULL) {
385 ret = false;
386 goto fail;
389 ret &= convert_string_talloc(talloc_tos(),
390 CH_UNIX, CH_UTF16LE,
391 pw_quote, strlen(pw_quote),
392 &pw_utf16, &pw_utf16_len);
393 if (!ret) {
394 goto fail;
396 blob = data_blob_const(pw_utf16, pw_utf16_len);
398 ret &= tldap_add_mod_blobs(mem_ctx, pmods, pnum_mods,
399 TLDAP_MOD_REPLACE,
400 "unicodePwd", &blob, 1);
401 TALLOC_FREE(pw_utf16);
402 TALLOC_FREE(pw_quote);
405 ret &= tldap_make_mod_fmt(
406 existing, mem_ctx, pmods, pnum_mods, "userAccountControl",
407 "%d", ds_acb2uf(pdb_get_acct_ctrl(sam)));
409 ret &= tldap_make_mod_fmt(
410 existing, mem_ctx, pmods, pnum_mods, "homeDirectory",
411 "%s", pdb_get_homedir(sam));
413 ret &= tldap_make_mod_fmt(
414 existing, mem_ctx, pmods, pnum_mods, "homeDrive",
415 "%s", pdb_get_dir_drive(sam));
417 ret &= tldap_make_mod_fmt(
418 existing, mem_ctx, pmods, pnum_mods, "scriptPath",
419 "%s", pdb_get_logon_script(sam));
421 ret &= tldap_make_mod_fmt(
422 existing, mem_ctx, pmods, pnum_mods, "profilePath",
423 "%s", pdb_get_profile_path(sam));
425 ret &= tldap_make_mod_fmt(
426 existing, mem_ctx, pmods, pnum_mods, "comment",
427 "%s", pdb_get_comment(sam));
429 ret &= tldap_make_mod_fmt(
430 existing, mem_ctx, pmods, pnum_mods, "description",
431 "%s", pdb_get_acct_desc(sam));
433 ret &= tldap_make_mod_fmt(
434 existing, mem_ctx, pmods, pnum_mods, "userWorkstations",
435 "%s", pdb_get_workstations(sam));
437 ret &= tldap_make_mod_fmt(
438 existing, mem_ctx, pmods, pnum_mods, "userParameters",
439 "%s", pdb_get_munged_dial(sam));
441 ret &= tldap_make_mod_fmt(
442 existing, mem_ctx, pmods, pnum_mods, "countryCode",
443 "%i", (int)pdb_get_country_code(sam));
445 ret &= tldap_make_mod_fmt(
446 existing, mem_ctx, pmods, pnum_mods, "codePage",
447 "%i", (int)pdb_get_code_page(sam));
449 ret &= pdb_ads_make_time_mod(
450 existing, mem_ctx, pmods, pnum_mods, "accountExpires",
451 (int)pdb_get_kickoff_time(sam));
453 ret &= tldap_make_mod_blob(
454 existing, mem_ctx, pmods, pnum_mods, "logonHours",
455 data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam)));
457 fail:
458 return ret;
461 static NTSTATUS pdb_ads_getsamupriv(struct pdb_ads_state *state,
462 const char *filter,
463 TALLOC_CTX *mem_ctx,
464 struct pdb_ads_samu_private **presult)
466 const char * attrs[] = {
467 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
468 "sAMAccountName", "displayName", "homeDirectory",
469 "homeDrive", "scriptPath", "profilePath", "description",
470 "userWorkstations", "comment", "userParameters", "objectSid",
471 "primaryGroupID", "userAccountControl", "logonHours",
472 "badPwdCount", "logonCount", "countryCode", "codePage",
473 "unicodePwd", "dBCSPwd" };
474 struct tldap_message **users;
475 int rc, count;
476 struct pdb_ads_samu_private *result;
478 result = talloc(mem_ctx, struct pdb_ads_samu_private);
479 if (result == NULL) {
480 return NT_STATUS_NO_MEMORY;
483 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
484 attrs, ARRAY_SIZE(attrs), 0, result,
485 &users, "%s", filter);
486 if (rc != TLDAP_SUCCESS) {
487 DEBUG(10, ("ldap_search failed %s\n",
488 tldap_errstr(talloc_tos(), state->ld, rc)));
489 TALLOC_FREE(result);
490 return NT_STATUS_LDAP(rc);
493 count = talloc_array_length(users);
494 if (count != 1) {
495 DEBUG(10, ("Expected 1 user, got %d\n", count));
496 TALLOC_FREE(result);
497 return NT_STATUS_NO_SUCH_USER;
500 result->ldapmsg = users[0];
501 if (!tldap_entry_dn(result->ldapmsg, &result->dn)) {
502 DEBUG(10, ("Could not extract dn\n"));
503 TALLOC_FREE(result);
504 return NT_STATUS_INTERNAL_DB_CORRUPTION;
507 *presult = result;
508 return NT_STATUS_OK;
511 static NTSTATUS pdb_ads_getsampwfilter(struct pdb_methods *m,
512 struct pdb_ads_state *state,
513 struct samu *sam_acct,
514 const char *filter)
516 struct pdb_ads_samu_private *priv;
517 NTSTATUS status;
519 status = pdb_ads_getsamupriv(state, filter, sam_acct, &priv);
520 if (!NT_STATUS_IS_OK(status)) {
521 DEBUG(10, ("pdb_ads_getsamupriv failed: %s\n",
522 nt_errstr(status)));
523 return status;
526 status = pdb_ads_init_sam_from_priv(m, sam_acct, priv);
527 if (!NT_STATUS_IS_OK(status)) {
528 DEBUG(10, ("pdb_ads_init_sam_from_priv failed: %s\n",
529 nt_errstr(status)));
530 TALLOC_FREE(priv);
531 return status;
534 pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
535 return NT_STATUS_OK;
538 static NTSTATUS pdb_ads_getsampwnam(struct pdb_methods *m,
539 struct samu *sam_acct,
540 const char *username)
542 struct pdb_ads_state *state = talloc_get_type_abort(
543 m->private_data, struct pdb_ads_state);
544 char *filter;
546 filter = talloc_asprintf(
547 talloc_tos(), "(&(samaccountname=%s)(objectclass=user))",
548 username);
549 NT_STATUS_HAVE_NO_MEMORY(filter);
551 return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
554 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
555 struct samu *sam_acct,
556 const struct dom_sid *sid)
558 struct pdb_ads_state *state = talloc_get_type_abort(
559 m->private_data, struct pdb_ads_state);
560 char *sidstr, *filter;
562 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
563 NT_STATUS_HAVE_NO_MEMORY(sidstr);
565 filter = talloc_asprintf(
566 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
567 TALLOC_FREE(sidstr);
568 NT_STATUS_HAVE_NO_MEMORY(filter);
570 return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
573 static NTSTATUS pdb_ads_create_user(struct pdb_methods *m,
574 TALLOC_CTX *tmp_ctx,
575 const char *name, uint32 acct_flags,
576 uint32 *rid)
578 struct pdb_ads_state *state = talloc_get_type_abort(
579 m->private_data, struct pdb_ads_state);
580 struct tldap_context *ld;
581 const char *attrs[1] = { "objectSid" };
582 struct tldap_mod *mods = NULL;
583 int num_mods = 0;
584 struct tldap_message **user;
585 struct dom_sid sid;
586 char *dn;
587 int rc;
588 bool ok;
590 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
591 state->domaindn);
592 if (dn == NULL) {
593 return NT_STATUS_NO_MEMORY;
596 ld = pdb_ads_ld(state);
597 if (ld == NULL) {
598 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
601 /* TODO: Create machines etc */
603 ok = true;
604 ok &= tldap_make_mod_fmt(
605 NULL, talloc_tos(), &mods, &num_mods, "objectClass", "user");
606 ok &= tldap_make_mod_fmt(
607 NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
608 name);
609 if (!ok) {
610 return NT_STATUS_NO_MEMORY;
614 rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
615 if (rc != TLDAP_SUCCESS) {
616 DEBUG(10, ("ldap_add failed %s\n",
617 tldap_errstr(talloc_tos(), ld, rc)));
618 TALLOC_FREE(dn);
619 return NT_STATUS_LDAP(rc);
622 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
623 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
624 &user,
625 "(&(objectclass=user)(samaccountname=%s))",
626 name);
627 if (rc != TLDAP_SUCCESS) {
628 DEBUG(10, ("Could not find just created user %s: %s\n",
629 name, tldap_errstr(talloc_tos(), state->ld, rc)));
630 TALLOC_FREE(dn);
631 return NT_STATUS_LDAP(rc);
634 if (talloc_array_length(user) != 1) {
635 DEBUG(10, ("Got %d users, expected one\n",
636 (int)talloc_array_length(user)));
637 TALLOC_FREE(dn);
638 return NT_STATUS_LDAP(rc);
641 if (!tldap_pull_binsid(user[0], "objectSid", &sid)) {
642 DEBUG(10, ("Could not fetch objectSid from user %s\n",
643 name));
644 TALLOC_FREE(dn);
645 return NT_STATUS_INTERNAL_DB_CORRUPTION;
648 sid_peek_rid(&sid, rid);
649 TALLOC_FREE(dn);
650 return NT_STATUS_OK;
653 static NTSTATUS pdb_ads_delete_user(struct pdb_methods *m,
654 TALLOC_CTX *tmp_ctx,
655 struct samu *sam)
657 struct pdb_ads_state *state = talloc_get_type_abort(
658 m->private_data, struct pdb_ads_state);
659 NTSTATUS status;
660 struct tldap_context *ld;
661 char *dn;
662 int rc;
664 ld = pdb_ads_ld(state);
665 if (ld == NULL) {
666 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
669 status = pdb_ads_sid2dn(state, pdb_get_user_sid(sam), talloc_tos(),
670 &dn);
671 if (!NT_STATUS_IS_OK(status)) {
672 return status;
675 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
676 TALLOC_FREE(dn);
677 if (rc != TLDAP_SUCCESS) {
678 DEBUG(10, ("ldap_delete for %s failed: %s\n", dn,
679 tldap_errstr(talloc_tos(), ld, rc)));
680 return NT_STATUS_LDAP(rc);
682 return NT_STATUS_OK;
685 static NTSTATUS pdb_ads_add_sam_account(struct pdb_methods *m,
686 struct samu *sampass)
688 return NT_STATUS_NOT_IMPLEMENTED;
691 static NTSTATUS pdb_ads_update_sam_account(struct pdb_methods *m,
692 struct samu *sam)
694 struct pdb_ads_state *state = talloc_get_type_abort(
695 m->private_data, struct pdb_ads_state);
696 struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam);
697 struct tldap_context *ld;
698 struct tldap_mod *mods = NULL;
699 int rc, num_mods = 0;
701 ld = pdb_ads_ld(state);
702 if (ld == NULL) {
703 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
706 if (!pdb_ads_init_ads_from_sam(state, priv->ldapmsg, talloc_tos(),
707 &mods, &num_mods, sam)) {
708 return NT_STATUS_NO_MEMORY;
711 if (num_mods == 0) {
712 /* Nothing to do, just return success */
713 return NT_STATUS_OK;
716 rc = tldap_modify(ld, priv->dn, mods, num_mods, NULL, 0,
717 NULL, 0);
718 TALLOC_FREE(mods);
719 if (rc != TLDAP_SUCCESS) {
720 DEBUG(10, ("ldap_modify for %s failed: %s\n", priv->dn,
721 tldap_errstr(talloc_tos(), ld, rc)));
722 return NT_STATUS_LDAP(rc);
725 return NT_STATUS_OK;
728 static NTSTATUS pdb_ads_delete_sam_account(struct pdb_methods *m,
729 struct samu *username)
731 return NT_STATUS_NOT_IMPLEMENTED;
734 static NTSTATUS pdb_ads_rename_sam_account(struct pdb_methods *m,
735 struct samu *oldname,
736 const char *newname)
738 return NT_STATUS_NOT_IMPLEMENTED;
741 static NTSTATUS pdb_ads_update_login_attempts(struct pdb_methods *m,
742 struct samu *sam_acct,
743 bool success)
745 return NT_STATUS_NOT_IMPLEMENTED;
748 static NTSTATUS pdb_ads_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
749 const char *filter,
750 TALLOC_CTX *mem_ctx,
751 struct tldap_message **pmsg)
753 struct pdb_ads_state *state = talloc_get_type_abort(
754 m->private_data, struct pdb_ads_state);
755 const char *attrs[4] = { "objectSid", "description", "samAccountName",
756 "groupType" };
757 char *str;
758 struct tldap_message **group;
759 uint32_t grouptype;
760 int rc;
762 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
763 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
764 &group, "%s", filter);
765 if (rc != TLDAP_SUCCESS) {
766 DEBUG(10, ("ldap_search failed %s\n",
767 tldap_errstr(talloc_tos(), state->ld, rc)));
768 return NT_STATUS_LDAP(rc);
770 if (talloc_array_length(group) != 1) {
771 DEBUG(10, ("Expected 1 group, got %d\n",
772 (int)talloc_array_length(group)));
773 return NT_STATUS_INTERNAL_DB_CORRUPTION;
776 if (!tldap_pull_binsid(group[0], "objectSid", &map->sid)) {
777 return NT_STATUS_INTERNAL_DB_CORRUPTION;
779 map->gid = pdb_ads_sid2gid(&map->sid);
781 if (!tldap_pull_uint32(group[0], "groupType", &grouptype)) {
782 return NT_STATUS_INTERNAL_DB_CORRUPTION;
784 switch (grouptype) {
785 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
786 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
787 map->sid_name_use = SID_NAME_ALIAS;
788 break;
789 case GTYPE_SECURITY_GLOBAL_GROUP:
790 map->sid_name_use = SID_NAME_DOM_GRP;
791 break;
792 default:
793 return NT_STATUS_INTERNAL_DB_CORRUPTION;
796 str = tldap_talloc_single_attribute(group[0], "samAccountName",
797 talloc_tos());
798 if (str == NULL) {
799 return NT_STATUS_INTERNAL_DB_CORRUPTION;
801 map->nt_name = talloc_move(map, &str);
803 str = tldap_talloc_single_attribute(group[0], "description",
804 talloc_tos());
805 if (str != NULL) {
806 map->comment = talloc_move(map, &str);
807 } else {
808 map->comment = talloc_strdup(map, "");
811 if (pmsg != NULL) {
812 *pmsg = talloc_move(mem_ctx, &group[0]);
814 TALLOC_FREE(group);
815 return NT_STATUS_OK;
818 static NTSTATUS pdb_ads_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
819 struct dom_sid sid)
821 char *filter;
822 NTSTATUS status;
824 filter = talloc_asprintf(talloc_tos(),
825 "(&(objectsid=%s)(objectclass=group))",
826 sid_string_talloc(talloc_tos(), &sid));
827 if (filter == NULL) {
828 return NT_STATUS_NO_MEMORY;
831 status = pdb_ads_getgrfilter(m, map, filter, NULL, NULL);
832 TALLOC_FREE(filter);
833 return status;
836 static NTSTATUS pdb_ads_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
837 gid_t gid)
839 struct dom_sid sid;
840 pdb_ads_gid_to_sid(m, gid, &sid);
841 return pdb_ads_getgrsid(m, map, sid);
844 static NTSTATUS pdb_ads_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
845 const char *name)
847 char *filter;
848 NTSTATUS status;
850 filter = talloc_asprintf(talloc_tos(),
851 "(&(samaccountname=%s)(objectclass=group))",
852 name);
853 if (filter == NULL) {
854 return NT_STATUS_NO_MEMORY;
857 status = pdb_ads_getgrfilter(m, map, filter, NULL, NULL);
858 TALLOC_FREE(filter);
859 return status;
862 static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m,
863 TALLOC_CTX *mem_ctx, const char *name,
864 uint32 *rid)
866 TALLOC_CTX *frame = talloc_stackframe();
867 struct pdb_ads_state *state = talloc_get_type_abort(
868 m->private_data, struct pdb_ads_state);
869 struct tldap_context *ld;
870 const char *attrs[1] = { "objectSid" };
871 int num_mods = 0;
872 struct tldap_mod *mods = NULL;
873 struct tldap_message **alias;
874 struct dom_sid sid;
875 char *dn;
876 int rc;
877 bool ok = true;
879 ld = pdb_ads_ld(state);
880 if (ld == NULL) {
881 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
884 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
885 state->domaindn);
886 if (dn == NULL) {
887 TALLOC_FREE(frame);
888 return NT_STATUS_NO_MEMORY;
891 ok &= tldap_make_mod_fmt(
892 NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
893 name);
894 ok &= tldap_make_mod_fmt(
895 NULL, talloc_tos(), &mods, &num_mods, "objectClass", "group");
896 ok &= tldap_make_mod_fmt(
897 NULL, talloc_tos(), &mods, &num_mods, "groupType",
898 "%d", (int)GTYPE_SECURITY_GLOBAL_GROUP);
900 if (!ok) {
901 TALLOC_FREE(frame);
902 return NT_STATUS_NO_MEMORY;
905 rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
906 if (rc != TLDAP_SUCCESS) {
907 DEBUG(10, ("ldap_add failed %s\n",
908 tldap_errstr(talloc_tos(), state->ld, rc)));
909 TALLOC_FREE(frame);
910 return NT_STATUS_LDAP(rc);
913 rc = pdb_ads_search_fmt(
914 state, state->domaindn, TLDAP_SCOPE_SUB,
915 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
916 "(&(objectclass=group)(samaccountname=%s))", name);
917 if (rc != TLDAP_SUCCESS) {
918 DEBUG(10, ("Could not find just created alias %s: %s\n",
919 name, tldap_errstr(talloc_tos(), state->ld, rc)));
920 TALLOC_FREE(frame);
921 return NT_STATUS_LDAP(rc);
924 if (talloc_array_length(alias) != 1) {
925 DEBUG(10, ("Got %d alias, expected one\n",
926 (int)talloc_array_length(alias)));
927 TALLOC_FREE(frame);
928 return NT_STATUS_LDAP(rc);
931 if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
932 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
933 name));
934 TALLOC_FREE(frame);
935 return NT_STATUS_INTERNAL_DB_CORRUPTION;
938 sid_peek_rid(&sid, rid);
939 TALLOC_FREE(frame);
940 return NT_STATUS_OK;
943 static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m,
944 TALLOC_CTX *mem_ctx, uint32 rid)
946 struct pdb_ads_state *state = talloc_get_type_abort(
947 m->private_data, struct pdb_ads_state);
948 struct tldap_context *ld;
949 struct dom_sid sid;
950 char *sidstr;
951 struct tldap_message **msg;
952 char *dn;
953 int rc;
955 sid_compose(&sid, &state->domainsid, rid);
957 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), &sid);
958 NT_STATUS_HAVE_NO_MEMORY(sidstr);
960 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
961 NULL, 0, 0, talloc_tos(), &msg,
962 ("(&(objectSid=%s)(objectClass=group))"),
963 sidstr);
964 TALLOC_FREE(sidstr);
965 if (rc != TLDAP_SUCCESS) {
966 DEBUG(10, ("ldap_search failed %s\n",
967 tldap_errstr(talloc_tos(), state->ld, rc)));
968 return NT_STATUS_LDAP(rc);
971 switch talloc_array_length(msg) {
972 case 0:
973 return NT_STATUS_NO_SUCH_GROUP;
974 case 1:
975 break;
976 default:
977 return NT_STATUS_INTERNAL_DB_CORRUPTION;
980 if (!tldap_entry_dn(msg[0], &dn)) {
981 TALLOC_FREE(msg);
982 return NT_STATUS_INTERNAL_DB_CORRUPTION;
985 ld = pdb_ads_ld(state);
986 if (ld == NULL) {
987 TALLOC_FREE(msg);
988 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
991 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
992 TALLOC_FREE(msg);
993 if (rc != TLDAP_SUCCESS) {
994 DEBUG(10, ("ldap_delete failed: %s\n",
995 tldap_errstr(talloc_tos(), state->ld, rc)));
996 return NT_STATUS_LDAP(rc);
999 return NT_STATUS_OK;
1002 static NTSTATUS pdb_ads_add_group_mapping_entry(struct pdb_methods *m,
1003 GROUP_MAP *map)
1005 return NT_STATUS_NOT_IMPLEMENTED;
1008 static NTSTATUS pdb_ads_update_group_mapping_entry(struct pdb_methods *m,
1009 GROUP_MAP *map)
1011 struct pdb_ads_state *state = talloc_get_type_abort(
1012 m->private_data, struct pdb_ads_state);
1013 struct tldap_context *ld;
1014 struct tldap_mod *mods = NULL;
1015 char *filter;
1016 struct tldap_message *existing;
1017 char *dn;
1018 GROUP_MAP *existing_map;
1019 int rc, num_mods = 0;
1020 bool ret;
1021 NTSTATUS status;
1023 ld = pdb_ads_ld(state);
1024 if (ld == NULL) {
1025 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1028 filter = talloc_asprintf(talloc_tos(),
1029 "(&(objectsid=%s)(objectclass=group))",
1030 sid_string_talloc(talloc_tos(), &map->sid));
1031 if (filter == NULL) {
1032 return NT_STATUS_NO_MEMORY;
1035 existing_map = talloc_zero(talloc_tos(), GROUP_MAP);
1036 if (!existing_map) {
1037 return NT_STATUS_NO_MEMORY;
1040 status = pdb_ads_getgrfilter(m, existing_map, filter,
1041 talloc_tos(), &existing);
1042 TALLOC_FREE(existing_map);
1043 TALLOC_FREE(filter);
1045 if (!tldap_entry_dn(existing, &dn)) {
1046 return NT_STATUS_LDAP(TLDAP_DECODING_ERROR);
1049 ret = true;
1051 ret &= tldap_make_mod_fmt(
1052 existing, talloc_tos(), &mods, &num_mods, "description",
1053 "%s", map->comment);
1054 ret &= tldap_make_mod_fmt(
1055 existing, talloc_tos(), &mods, &num_mods, "samaccountname",
1056 "%s", map->nt_name);
1058 if (!ret) {
1059 return NT_STATUS_NO_MEMORY;
1062 if (num_mods == 0) {
1063 TALLOC_FREE(existing);
1064 return NT_STATUS_OK;
1067 rc = tldap_modify(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
1068 if (rc != TLDAP_SUCCESS) {
1069 DEBUG(10, ("ldap_modify for %s failed: %s\n", dn,
1070 tldap_errstr(talloc_tos(), ld, rc)));
1071 TALLOC_FREE(existing);
1072 return NT_STATUS_LDAP(rc);
1074 TALLOC_FREE(existing);
1075 return NT_STATUS_OK;
1078 static NTSTATUS pdb_ads_delete_group_mapping_entry(struct pdb_methods *m,
1079 struct dom_sid sid)
1081 return NT_STATUS_NOT_IMPLEMENTED;
1084 static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m,
1085 const struct dom_sid *sid,
1086 enum lsa_SidType sid_name_use,
1087 GROUP_MAP ***pp_rmap,
1088 size_t *p_num_entries,
1089 bool unix_only)
1091 return NT_STATUS_NOT_IMPLEMENTED;
1094 static NTSTATUS pdb_ads_enum_group_members(struct pdb_methods *m,
1095 TALLOC_CTX *mem_ctx,
1096 const struct dom_sid *group,
1097 uint32 **pmembers,
1098 size_t *pnum_members)
1100 struct pdb_ads_state *state = talloc_get_type_abort(
1101 m->private_data, struct pdb_ads_state);
1102 const char *attrs[1] = { "member" };
1103 char *sidstr;
1104 struct tldap_message **msg;
1105 int i, rc, num_members;
1106 DATA_BLOB *blobs;
1107 uint32_t *members;
1109 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), group);
1110 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1112 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1113 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1114 &msg, "(objectsid=%s)", sidstr);
1115 TALLOC_FREE(sidstr);
1116 if (rc != TLDAP_SUCCESS) {
1117 DEBUG(10, ("ldap_search failed %s\n",
1118 tldap_errstr(talloc_tos(), state->ld, rc)));
1119 return NT_STATUS_LDAP(rc);
1121 switch talloc_array_length(msg) {
1122 case 0:
1123 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1124 break;
1125 case 1:
1126 break;
1127 default:
1128 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1129 break;
1132 if (!tldap_entry_values(msg[0], "member", &blobs, &num_members)) {
1133 *pmembers = NULL;
1134 *pnum_members = 0;
1135 return NT_STATUS_OK;
1138 members = talloc_array(mem_ctx, uint32_t, num_members);
1139 if (members == NULL) {
1140 return NT_STATUS_NO_MEMORY;
1143 for (i=0; i<num_members; i++) {
1144 struct dom_sid sid;
1145 if (!pdb_ads_dnblob2sid(state, &blobs[i], &sid)
1146 || !sid_peek_rid(&sid, &members[i])) {
1147 TALLOC_FREE(members);
1148 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1152 *pmembers = members;
1153 *pnum_members = num_members;
1154 return NT_STATUS_OK;
1157 static NTSTATUS pdb_ads_enum_group_memberships(struct pdb_methods *m,
1158 TALLOC_CTX *mem_ctx,
1159 struct samu *user,
1160 struct dom_sid **pp_sids,
1161 gid_t **pp_gids,
1162 uint32_t *p_num_groups)
1164 struct pdb_ads_state *state = talloc_get_type_abort(
1165 m->private_data, struct pdb_ads_state);
1166 struct pdb_ads_samu_private *priv;
1167 const char *attrs[1] = { "objectSid" };
1168 struct tldap_message **groups;
1169 int i, rc, count;
1170 size_t num_groups;
1171 struct dom_sid *group_sids;
1172 gid_t *gids;
1174 priv = pdb_ads_get_samu_private(m, user);
1175 if (priv != NULL) {
1176 rc = pdb_ads_search_fmt(
1177 state, state->domaindn, TLDAP_SCOPE_SUB,
1178 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &groups,
1179 "(&(member=%s)(grouptype=%d)(objectclass=group))",
1180 priv->dn, GTYPE_SECURITY_GLOBAL_GROUP);
1181 if (rc != TLDAP_SUCCESS) {
1182 DEBUG(10, ("ldap_search failed %s\n",
1183 tldap_errstr(talloc_tos(), state->ld, rc)));
1184 return NT_STATUS_LDAP(rc);
1186 count = talloc_array_length(groups);
1187 } else {
1189 * This happens for artificial samu users
1191 DEBUG(10, ("Could not get pdb_ads_samu_private\n"));
1192 count = 0;
1195 group_sids = talloc_array(mem_ctx, struct dom_sid, count+1);
1196 if (group_sids == NULL) {
1197 return NT_STATUS_NO_MEMORY;
1199 gids = talloc_array(mem_ctx, gid_t, count+1);
1200 if (gids == NULL) {
1201 TALLOC_FREE(group_sids);
1202 return NT_STATUS_NO_MEMORY;
1205 sid_copy(&group_sids[0], pdb_get_group_sid(user));
1206 if (!sid_to_gid(&group_sids[0], &gids[0])) {
1207 TALLOC_FREE(gids);
1208 TALLOC_FREE(group_sids);
1209 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1211 num_groups = 1;
1213 for (i=0; i<count; i++) {
1214 if (!tldap_pull_binsid(groups[i], "objectSid",
1215 &group_sids[num_groups])) {
1216 continue;
1218 gids[num_groups] = pdb_ads_sid2gid(&group_sids[num_groups]);
1220 num_groups += 1;
1221 if (num_groups == count) {
1222 break;
1226 *pp_sids = group_sids;
1227 *pp_gids = gids;
1228 *p_num_groups = num_groups;
1229 return NT_STATUS_OK;
1232 static NTSTATUS pdb_ads_set_unix_primary_group(struct pdb_methods *m,
1233 TALLOC_CTX *mem_ctx,
1234 struct samu *user)
1236 return NT_STATUS_NOT_IMPLEMENTED;
1239 static NTSTATUS pdb_ads_mod_groupmem(struct pdb_methods *m,
1240 TALLOC_CTX *mem_ctx,
1241 uint32 grouprid, uint32 memberrid,
1242 int mod_op)
1244 struct pdb_ads_state *state = talloc_get_type_abort(
1245 m->private_data, struct pdb_ads_state);
1246 TALLOC_CTX *frame = talloc_stackframe();
1247 struct tldap_context *ld;
1248 struct dom_sid groupsid, membersid;
1249 char *groupdn, *memberdn;
1250 struct tldap_mod *mods;
1251 int num_mods;
1252 int rc;
1253 NTSTATUS status;
1255 ld = pdb_ads_ld(state);
1256 if (ld == NULL) {
1257 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1260 sid_compose(&groupsid, &state->domainsid, grouprid);
1261 sid_compose(&membersid, &state->domainsid, memberrid);
1263 status = pdb_ads_sid2dn(state, &groupsid, talloc_tos(), &groupdn);
1264 if (!NT_STATUS_IS_OK(status)) {
1265 TALLOC_FREE(frame);
1266 return NT_STATUS_NO_SUCH_GROUP;
1268 status = pdb_ads_sid2dn(state, &membersid, talloc_tos(), &memberdn);
1269 if (!NT_STATUS_IS_OK(status)) {
1270 TALLOC_FREE(frame);
1271 return NT_STATUS_NO_SUCH_USER;
1274 mods = NULL;
1275 num_mods = 0;
1277 if (!tldap_add_mod_str(talloc_tos(), &mods, &num_mods, mod_op,
1278 "member", memberdn)) {
1279 TALLOC_FREE(frame);
1280 return NT_STATUS_NO_MEMORY;
1283 rc = tldap_modify(ld, groupdn, mods, num_mods, NULL, 0, NULL, 0);
1284 TALLOC_FREE(frame);
1285 if (rc != TLDAP_SUCCESS) {
1286 DEBUG(10, ("ldap_modify failed: %s\n",
1287 tldap_errstr(talloc_tos(), state->ld, rc)));
1288 if ((mod_op == TLDAP_MOD_ADD) &&
1289 (rc == TLDAP_ALREADY_EXISTS)) {
1290 return NT_STATUS_MEMBER_IN_GROUP;
1292 if ((mod_op == TLDAP_MOD_DELETE) &&
1293 (rc == TLDAP_UNWILLING_TO_PERFORM)) {
1294 return NT_STATUS_MEMBER_NOT_IN_GROUP;
1296 return NT_STATUS_LDAP(rc);
1299 return NT_STATUS_OK;
1302 static NTSTATUS pdb_ads_add_groupmem(struct pdb_methods *m,
1303 TALLOC_CTX *mem_ctx,
1304 uint32 group_rid, uint32 member_rid)
1306 return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1307 TLDAP_MOD_ADD);
1310 static NTSTATUS pdb_ads_del_groupmem(struct pdb_methods *m,
1311 TALLOC_CTX *mem_ctx,
1312 uint32 group_rid, uint32 member_rid)
1314 return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1315 TLDAP_MOD_DELETE);
1318 static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m,
1319 const char *name, uint32 *rid)
1321 TALLOC_CTX *frame = talloc_stackframe();
1322 struct pdb_ads_state *state = talloc_get_type_abort(
1323 m->private_data, struct pdb_ads_state);
1324 struct tldap_context *ld;
1325 const char *attrs[1] = { "objectSid" };
1326 int num_mods = 0;
1327 struct tldap_mod *mods = NULL;
1328 struct tldap_message **alias;
1329 struct dom_sid sid;
1330 char *dn;
1331 int rc;
1332 bool ok = true;
1334 ld = pdb_ads_ld(state);
1335 if (ld == NULL) {
1336 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1339 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
1340 state->domaindn);
1341 if (dn == NULL) {
1342 TALLOC_FREE(frame);
1343 return NT_STATUS_NO_MEMORY;
1346 ok &= tldap_make_mod_fmt(
1347 NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
1348 name);
1349 ok &= tldap_make_mod_fmt(
1350 NULL, talloc_tos(), &mods, &num_mods, "objectClass", "group");
1351 ok &= tldap_make_mod_fmt(
1352 NULL, talloc_tos(), &mods, &num_mods, "groupType",
1353 "%d", (int)GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1355 if (!ok) {
1356 TALLOC_FREE(frame);
1357 return NT_STATUS_NO_MEMORY;
1360 rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
1361 if (rc != TLDAP_SUCCESS) {
1362 DEBUG(10, ("ldap_add failed %s\n",
1363 tldap_errstr(talloc_tos(), state->ld, rc)));
1364 TALLOC_FREE(frame);
1365 return NT_STATUS_LDAP(rc);
1368 rc = pdb_ads_search_fmt(
1369 state, state->domaindn, TLDAP_SCOPE_SUB,
1370 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
1371 "(&(objectclass=group)(samaccountname=%s))", name);
1372 if (rc != TLDAP_SUCCESS) {
1373 DEBUG(10, ("Could not find just created alias %s: %s\n",
1374 name, tldap_errstr(talloc_tos(), state->ld, rc)));
1375 TALLOC_FREE(frame);
1376 return NT_STATUS_LDAP(rc);
1379 if (talloc_array_length(alias) != 1) {
1380 DEBUG(10, ("Got %d alias, expected one\n",
1381 (int)talloc_array_length(alias)));
1382 TALLOC_FREE(frame);
1383 return NT_STATUS_LDAP(rc);
1386 if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
1387 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
1388 name));
1389 TALLOC_FREE(frame);
1390 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1393 sid_peek_rid(&sid, rid);
1394 TALLOC_FREE(frame);
1395 return NT_STATUS_OK;
1398 static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m,
1399 const struct dom_sid *sid)
1401 struct pdb_ads_state *state = talloc_get_type_abort(
1402 m->private_data, struct pdb_ads_state);
1403 struct tldap_context *ld;
1404 struct tldap_message **alias;
1405 char *sidstr, *dn = NULL;
1406 int rc;
1408 ld = pdb_ads_ld(state);
1409 if (ld == NULL) {
1410 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1413 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
1414 if (sidstr == NULL) {
1415 return NT_STATUS_NO_MEMORY;
1418 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1419 NULL, 0, 0, talloc_tos(), &alias,
1420 "(&(objectSid=%s)(objectclass=group)"
1421 "(|(grouptype=%d)(grouptype=%d)))",
1422 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1423 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1424 TALLOC_FREE(sidstr);
1425 if (rc != TLDAP_SUCCESS) {
1426 DEBUG(10, ("ldap_search failed: %s\n",
1427 tldap_errstr(talloc_tos(), state->ld, rc)));
1428 return NT_STATUS_LDAP(rc);
1430 if (talloc_array_length(alias) != 1) {
1431 DEBUG(10, ("Expected 1 alias, got %d\n",
1432 (int)talloc_array_length(alias)));
1433 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1435 if (!tldap_entry_dn(alias[0], &dn)) {
1436 DEBUG(10, ("Could not get DN for alias %s\n",
1437 sid_string_dbg(sid)));
1438 return NT_STATUS_INTERNAL_ERROR;
1441 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
1442 if (rc != TLDAP_SUCCESS) {
1443 DEBUG(10, ("ldap_delete failed: %s\n",
1444 tldap_errstr(talloc_tos(), state->ld, rc)));
1445 return NT_STATUS_LDAP(rc);
1448 return NT_STATUS_OK;
1451 static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m,
1452 const struct dom_sid *sid,
1453 struct acct_info *info)
1455 struct pdb_ads_state *state = talloc_get_type_abort(
1456 m->private_data, struct pdb_ads_state);
1457 struct tldap_context *ld;
1458 const char *attrs[3] = { "objectSid", "description",
1459 "samAccountName" };
1460 struct tldap_message **msg;
1461 char *sidstr, *dn;
1462 int rc;
1463 struct tldap_mod *mods;
1464 int num_mods;
1465 bool ok;
1467 ld = pdb_ads_ld(state);
1468 if (ld == NULL) {
1469 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1472 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
1473 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1475 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1476 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1477 &msg, "(&(objectSid=%s)(objectclass=group)"
1478 "(|(grouptype=%d)(grouptype=%d)))",
1479 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1480 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1481 TALLOC_FREE(sidstr);
1482 if (rc != TLDAP_SUCCESS) {
1483 DEBUG(10, ("ldap_search failed %s\n",
1484 tldap_errstr(talloc_tos(), state->ld, rc)));
1485 return NT_STATUS_LDAP(rc);
1487 switch talloc_array_length(msg) {
1488 case 0:
1489 return NT_STATUS_NO_SUCH_ALIAS;
1490 case 1:
1491 break;
1492 default:
1493 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1496 if (!tldap_entry_dn(msg[0], &dn)) {
1497 TALLOC_FREE(msg);
1498 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1501 mods = NULL;
1502 num_mods = 0;
1503 ok = true;
1505 ok &= tldap_make_mod_fmt(
1506 msg[0], msg, &mods, &num_mods, "description",
1507 "%s", info->acct_desc);
1508 ok &= tldap_make_mod_fmt(
1509 msg[0], msg, &mods, &num_mods, "samAccountName",
1510 "%s", info->acct_name);
1511 if (!ok) {
1512 TALLOC_FREE(msg);
1513 return NT_STATUS_NO_MEMORY;
1515 if (num_mods == 0) {
1516 /* no change */
1517 TALLOC_FREE(msg);
1518 return NT_STATUS_OK;
1521 rc = tldap_modify(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
1522 TALLOC_FREE(msg);
1523 if (rc != TLDAP_SUCCESS) {
1524 DEBUG(10, ("ldap_modify failed: %s\n",
1525 tldap_errstr(talloc_tos(), state->ld, rc)));
1526 return NT_STATUS_LDAP(rc);
1528 return NT_STATUS_OK;
1531 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
1532 const struct dom_sid *sid,
1533 TALLOC_CTX *mem_ctx, char **pdn)
1535 struct tldap_message **msg;
1536 char *sidstr, *dn;
1537 int rc;
1539 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
1540 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1542 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1543 NULL, 0, 0, talloc_tos(), &msg,
1544 "(objectsid=%s)", sidstr);
1545 TALLOC_FREE(sidstr);
1546 if (rc != TLDAP_SUCCESS) {
1547 DEBUG(10, ("ldap_search failed %s\n",
1548 tldap_errstr(talloc_tos(), state->ld, rc)));
1549 return NT_STATUS_LDAP(rc);
1552 switch talloc_array_length(msg) {
1553 case 0:
1554 return NT_STATUS_NOT_FOUND;
1555 case 1:
1556 break;
1557 default:
1558 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1561 if (!tldap_entry_dn(msg[0], &dn)) {
1562 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1565 dn = talloc_strdup(mem_ctx, dn);
1566 if (dn == NULL) {
1567 return NT_STATUS_NO_MEMORY;
1569 TALLOC_FREE(msg);
1571 *pdn = dn;
1572 return NT_STATUS_OK;
1575 static NTSTATUS pdb_ads_mod_aliasmem(struct pdb_methods *m,
1576 const struct dom_sid *alias,
1577 const struct dom_sid *member,
1578 int mod_op)
1580 struct pdb_ads_state *state = talloc_get_type_abort(
1581 m->private_data, struct pdb_ads_state);
1582 struct tldap_context *ld;
1583 TALLOC_CTX *frame = talloc_stackframe();
1584 struct tldap_mod *mods;
1585 int num_mods;
1586 int rc;
1587 char *aliasdn, *memberdn;
1588 NTSTATUS status;
1590 ld = pdb_ads_ld(state);
1591 if (ld == NULL) {
1592 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1595 status = pdb_ads_sid2dn(state, alias, talloc_tos(), &aliasdn);
1596 if (!NT_STATUS_IS_OK(status)) {
1597 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1598 sid_string_dbg(alias), nt_errstr(status)));
1599 TALLOC_FREE(frame);
1600 return NT_STATUS_NO_SUCH_ALIAS;
1602 status = pdb_ads_sid2dn(state, member, talloc_tos(), &memberdn);
1603 if (!NT_STATUS_IS_OK(status)) {
1604 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1605 sid_string_dbg(member), nt_errstr(status)));
1606 TALLOC_FREE(frame);
1607 return status;
1610 mods = NULL;
1611 num_mods = 0;
1613 if (!tldap_add_mod_str(talloc_tos(), &mods, &num_mods, mod_op,
1614 "member", memberdn)) {
1615 TALLOC_FREE(frame);
1616 return NT_STATUS_NO_MEMORY;
1619 rc = tldap_modify(ld, aliasdn, mods, num_mods, NULL, 0, NULL, 0);
1620 TALLOC_FREE(frame);
1621 if (rc != TLDAP_SUCCESS) {
1622 DEBUG(10, ("ldap_modify failed: %s\n",
1623 tldap_errstr(talloc_tos(), state->ld, rc)));
1624 if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) {
1625 return NT_STATUS_MEMBER_IN_ALIAS;
1627 if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
1628 return NT_STATUS_MEMBER_NOT_IN_ALIAS;
1630 return NT_STATUS_LDAP(rc);
1633 return NT_STATUS_OK;
1636 static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
1637 const struct dom_sid *alias,
1638 const struct dom_sid *member)
1640 return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_ADD);
1643 static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
1644 const struct dom_sid *alias,
1645 const struct dom_sid *member)
1647 return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_DELETE);
1650 static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
1651 struct dom_sid *psid)
1653 const char *attrs[1] = { "objectSid" };
1654 struct tldap_message **msg;
1655 char *dn;
1656 size_t len;
1657 int rc;
1658 bool ret;
1660 if (!convert_string_talloc(talloc_tos(), CH_UTF8, CH_UNIX,
1661 dnblob->data, dnblob->length, &dn, &len)) {
1662 return false;
1664 rc = pdb_ads_search_fmt(state, dn, TLDAP_SCOPE_BASE,
1665 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1666 &msg, "(objectclass=*)");
1667 TALLOC_FREE(dn);
1668 if (talloc_array_length(msg) != 1) {
1669 DEBUG(10, ("Got %d objects, expected one\n",
1670 (int)talloc_array_length(msg)));
1671 TALLOC_FREE(msg);
1672 return false;
1675 ret = tldap_pull_binsid(msg[0], "objectSid", psid);
1676 TALLOC_FREE(msg);
1677 return ret;
1680 static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
1681 const struct dom_sid *alias,
1682 TALLOC_CTX *mem_ctx,
1683 struct dom_sid **pmembers,
1684 size_t *pnum_members)
1686 struct pdb_ads_state *state = talloc_get_type_abort(
1687 m->private_data, struct pdb_ads_state);
1688 const char *attrs[1] = { "member" };
1689 char *sidstr;
1690 struct tldap_message **msg;
1691 int i, rc, num_members;
1692 DATA_BLOB *blobs;
1693 struct dom_sid *members;
1695 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), alias);
1696 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1698 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1699 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1700 &msg, "(objectsid=%s)", sidstr);
1701 TALLOC_FREE(sidstr);
1702 if (rc != TLDAP_SUCCESS) {
1703 DEBUG(10, ("ldap_search failed %s\n",
1704 tldap_errstr(talloc_tos(), state->ld, rc)));
1705 return NT_STATUS_LDAP(rc);
1707 switch talloc_array_length(msg) {
1708 case 0:
1709 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1710 break;
1711 case 1:
1712 break;
1713 default:
1714 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1715 break;
1718 if (!tldap_entry_values(msg[0], "member", &blobs, &num_members)) {
1719 *pmembers = NULL;
1720 *pnum_members = 0;
1721 return NT_STATUS_OK;
1724 members = talloc_array(mem_ctx, struct dom_sid, num_members);
1725 if (members == NULL) {
1726 return NT_STATUS_NO_MEMORY;
1729 for (i=0; i<num_members; i++) {
1730 if (!pdb_ads_dnblob2sid(state, &blobs[i], &members[i])) {
1731 TALLOC_FREE(members);
1732 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1736 *pmembers = members;
1737 *pnum_members = num_members;
1738 return NT_STATUS_OK;
1741 static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,
1742 TALLOC_CTX *mem_ctx,
1743 const struct dom_sid *domain_sid,
1744 const struct dom_sid *members,
1745 size_t num_members,
1746 uint32_t **palias_rids,
1747 size_t *pnum_alias_rids)
1749 struct pdb_ads_state *state = talloc_get_type_abort(
1750 m->private_data, struct pdb_ads_state);
1751 const char *attrs[1] = { "objectSid" };
1752 struct tldap_message **msg = NULL;
1753 uint32_t *alias_rids = NULL;
1754 size_t num_alias_rids = 0;
1755 int i, rc, count;
1756 bool got_members = false;
1757 char *filter;
1758 NTSTATUS status;
1761 * TODO: Get the filter right so that we only get the aliases from
1762 * either the SAM or BUILTIN
1765 filter = talloc_asprintf(talloc_tos(),
1766 "(&(|(grouptype=%d)(grouptype=%d))"
1767 "(objectclass=group)(|",
1768 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1769 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1770 if (filter == NULL) {
1771 return NT_STATUS_NO_MEMORY;
1774 for (i=0; i<num_members; i++) {
1775 char *dn;
1777 status = pdb_ads_sid2dn(state, &members[i], talloc_tos(), &dn);
1778 if (!NT_STATUS_IS_OK(status)) {
1779 DEBUG(10, ("pdb_ads_sid2dn failed for %s: %s\n",
1780 sid_string_dbg(&members[i]),
1781 nt_errstr(status)));
1782 continue;
1784 filter = talloc_asprintf_append_buffer(
1785 filter, "(member=%s)", dn);
1786 TALLOC_FREE(dn);
1787 if (filter == NULL) {
1788 return NT_STATUS_NO_MEMORY;
1790 got_members = true;
1793 if (!got_members) {
1794 goto done;
1797 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1798 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1799 &msg, "%s))", filter);
1800 TALLOC_FREE(filter);
1801 if (rc != TLDAP_SUCCESS) {
1802 DEBUG(10, ("tldap_search failed %s\n",
1803 tldap_errstr(talloc_tos(), state->ld, rc)));
1804 return NT_STATUS_LDAP(rc);
1807 count = talloc_array_length(msg);
1808 if (count == 0) {
1809 goto done;
1812 alias_rids = talloc_array(mem_ctx, uint32_t, count);
1813 if (alias_rids == NULL) {
1814 TALLOC_FREE(msg);
1815 return NT_STATUS_NO_MEMORY;
1818 for (i=0; i<count; i++) {
1819 struct dom_sid sid;
1821 if (!tldap_pull_binsid(msg[i], "objectSid", &sid)) {
1822 DEBUG(10, ("Could not pull SID for member %d\n", i));
1823 continue;
1825 if (sid_peek_check_rid(domain_sid, &sid,
1826 &alias_rids[num_alias_rids])) {
1827 num_alias_rids += 1;
1830 done:
1831 TALLOC_FREE(msg);
1832 *palias_rids = alias_rids;
1833 *pnum_alias_rids = 0;
1834 return NT_STATUS_OK;
1837 static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m,
1838 const struct dom_sid *domain_sid,
1839 int num_rids,
1840 uint32 *rids,
1841 const char **names,
1842 enum lsa_SidType *lsa_attrs)
1844 struct pdb_ads_state *state = talloc_get_type_abort(
1845 m->private_data, struct pdb_ads_state);
1846 const char *attrs[2] = { "sAMAccountType", "sAMAccountName" };
1847 int i, num_mapped;
1849 if (num_rids == 0) {
1850 return NT_STATUS_NONE_MAPPED;
1853 num_mapped = 0;
1855 for (i=0; i<num_rids; i++) {
1856 struct dom_sid sid;
1857 struct tldap_message **msg;
1858 char *sidstr;
1859 uint32_t attr;
1860 int rc;
1862 lsa_attrs[i] = SID_NAME_UNKNOWN;
1864 sid_compose(&sid, domain_sid, rids[i]);
1866 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), &sid);
1867 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1869 rc = pdb_ads_search_fmt(state, state->domaindn,
1870 TLDAP_SCOPE_SUB, attrs,
1871 ARRAY_SIZE(attrs), 0, talloc_tos(),
1872 &msg, "(objectsid=%s)", sidstr);
1873 TALLOC_FREE(sidstr);
1874 if (rc != TLDAP_SUCCESS) {
1875 DEBUG(10, ("ldap_search failed %s\n",
1876 tldap_errstr(talloc_tos(), state->ld, rc)));
1877 continue;
1880 switch talloc_array_length(msg) {
1881 case 0:
1882 DEBUG(10, ("rid %d not found\n", (int)rids[i]));
1883 continue;
1884 case 1:
1885 break;
1886 default:
1887 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1890 names[i] = tldap_talloc_single_attribute(
1891 msg[0], "samAccountName", talloc_tos());
1892 if (names[i] == NULL) {
1893 DEBUG(10, ("no samAccountName\n"));
1894 continue;
1896 if (!tldap_pull_uint32(msg[0], "samAccountType", &attr)) {
1897 DEBUG(10, ("no samAccountType"));
1898 continue;
1900 lsa_attrs[i] = ds_atype_map(attr);
1901 num_mapped += 1;
1904 if (num_mapped == 0) {
1905 return NT_STATUS_NONE_MAPPED;
1907 if (num_mapped < num_rids) {
1908 return STATUS_SOME_UNMAPPED;
1910 return NT_STATUS_OK;
1913 static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m,
1914 const struct dom_sid *domain_sid,
1915 int num_names,
1916 const char **pp_names,
1917 uint32 *rids,
1918 enum lsa_SidType *attrs)
1920 return NT_STATUS_NOT_IMPLEMENTED;
1923 static NTSTATUS pdb_ads_get_account_policy(struct pdb_methods *m,
1924 enum pdb_policy_type type,
1925 uint32_t *value)
1927 return account_policy_get(type, value)
1928 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1931 static NTSTATUS pdb_ads_set_account_policy(struct pdb_methods *m,
1932 enum pdb_policy_type type,
1933 uint32_t value)
1935 return account_policy_set(type, value)
1936 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1939 static NTSTATUS pdb_ads_get_seq_num(struct pdb_methods *m,
1940 time_t *seq_num)
1942 return NT_STATUS_NOT_IMPLEMENTED;
1945 struct pdb_ads_search_state {
1946 uint32_t acct_flags;
1947 struct samr_displayentry *entries;
1948 uint32_t num_entries;
1949 ssize_t array_size;
1950 uint32_t current;
1953 static bool pdb_ads_next_entry(struct pdb_search *search,
1954 struct samr_displayentry *entry)
1956 struct pdb_ads_search_state *state = talloc_get_type_abort(
1957 search->private_data, struct pdb_ads_search_state);
1959 if (state->current == state->num_entries) {
1960 return false;
1963 entry->idx = state->entries[state->current].idx;
1964 entry->rid = state->entries[state->current].rid;
1965 entry->acct_flags = state->entries[state->current].acct_flags;
1967 entry->account_name = talloc_strdup(
1968 search, state->entries[state->current].account_name);
1969 entry->fullname = talloc_strdup(
1970 search, state->entries[state->current].fullname);
1971 entry->description = talloc_strdup(
1972 search, state->entries[state->current].description);
1974 if ((entry->account_name == NULL) || (entry->fullname == NULL)
1975 || (entry->description == NULL)) {
1976 DEBUG(0, ("talloc_strdup failed\n"));
1977 return false;
1980 state->current += 1;
1981 return true;
1984 static void pdb_ads_search_end(struct pdb_search *search)
1986 struct pdb_ads_search_state *state = talloc_get_type_abort(
1987 search->private_data, struct pdb_ads_search_state);
1988 TALLOC_FREE(state);
1991 static bool pdb_ads_search_filter(struct pdb_methods *m,
1992 struct pdb_search *search,
1993 const char *filter,
1994 uint32_t acct_flags,
1995 struct pdb_ads_search_state **pstate)
1997 struct pdb_ads_state *state = talloc_get_type_abort(
1998 m->private_data, struct pdb_ads_state);
1999 struct pdb_ads_search_state *sstate;
2000 const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
2001 "userAccountControl", "description" };
2002 struct tldap_message **users;
2003 int i, rc, num_users;
2005 sstate = talloc_zero(search, struct pdb_ads_search_state);
2006 if (sstate == NULL) {
2007 return false;
2009 sstate->acct_flags = acct_flags;
2011 rc = pdb_ads_search_fmt(
2012 state, state->domaindn, TLDAP_SCOPE_SUB,
2013 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &users,
2014 "%s", filter);
2015 if (rc != TLDAP_SUCCESS) {
2016 DEBUG(10, ("ldap_search_ext_s failed: %s\n",
2017 tldap_errstr(talloc_tos(), state->ld, rc)));
2018 return false;
2021 num_users = talloc_array_length(users);
2023 sstate->entries = talloc_array(sstate, struct samr_displayentry,
2024 num_users);
2025 if (sstate->entries == NULL) {
2026 DEBUG(10, ("talloc failed\n"));
2027 return false;
2030 sstate->num_entries = 0;
2032 for (i=0; i<num_users; i++) {
2033 struct samr_displayentry *e;
2034 struct dom_sid sid;
2035 uint32_t ctrl;
2037 e = &sstate->entries[sstate->num_entries];
2039 e->idx = sstate->num_entries;
2040 if (!tldap_pull_binsid(users[i], "objectSid", &sid)) {
2041 DEBUG(10, ("Could not pull sid\n"));
2042 continue;
2044 sid_peek_rid(&sid, &e->rid);
2046 if (tldap_pull_uint32(users[i], "userAccountControl", &ctrl)) {
2048 e->acct_flags = ds_uf2acb(ctrl);
2050 DEBUG(10, ("pdb_ads_search_filter: Found %x, "
2051 "filter %x\n", (int)e->acct_flags,
2052 (int)sstate->acct_flags));
2055 if ((sstate->acct_flags != 0) &&
2056 ((sstate->acct_flags & e->acct_flags) == 0)) {
2057 continue;
2060 if (e->acct_flags & (ACB_WSTRUST|ACB_SVRTRUST)) {
2061 e->acct_flags |= ACB_NORMAL;
2063 } else {
2064 e->acct_flags = ACB_NORMAL;
2067 if (e->rid == DOMAIN_RID_GUEST) {
2069 * Guest is specially crafted in s3. Make
2070 * QueryDisplayInfo match QueryUserInfo
2072 e->account_name = lp_guestaccount();
2073 e->fullname = lp_guestaccount();
2074 e->description = "";
2075 e->acct_flags = ACB_NORMAL;
2076 } else {
2077 e->account_name = tldap_talloc_single_attribute(
2078 users[i], "samAccountName", sstate->entries);
2079 e->fullname = tldap_talloc_single_attribute(
2080 users[i], "displayName", sstate->entries);
2081 e->description = tldap_talloc_single_attribute(
2082 users[i], "description", sstate->entries);
2084 if (e->account_name == NULL) {
2085 return false;
2087 if (e->fullname == NULL) {
2088 e->fullname = "";
2090 if (e->description == NULL) {
2091 e->description = "";
2094 sstate->num_entries += 1;
2095 if (sstate->num_entries >= num_users) {
2096 break;
2100 search->private_data = sstate;
2101 search->next_entry = pdb_ads_next_entry;
2102 search->search_end = pdb_ads_search_end;
2103 *pstate = sstate;
2104 return true;
2107 static bool pdb_ads_search_users(struct pdb_methods *m,
2108 struct pdb_search *search,
2109 uint32 acct_flags)
2111 struct pdb_ads_search_state *sstate;
2112 char *filter;
2113 bool ret;
2115 DEBUG(10, ("pdb_ads_search_users got flags %x\n", acct_flags));
2117 if (acct_flags & ACB_NORMAL) {
2118 filter = talloc_asprintf(
2119 talloc_tos(),
2120 "(&(objectclass=user)(sAMAccountType=%d))",
2121 ATYPE_NORMAL_ACCOUNT);
2122 } else if (acct_flags & ACB_WSTRUST) {
2123 filter = talloc_asprintf(
2124 talloc_tos(),
2125 "(&(objectclass=user)(sAMAccountType=%d))",
2126 ATYPE_WORKSTATION_TRUST);
2127 } else {
2128 filter = talloc_strdup(talloc_tos(), "(objectclass=user)");
2130 if (filter == NULL) {
2131 return false;
2134 ret = pdb_ads_search_filter(m, search, filter, acct_flags, &sstate);
2135 TALLOC_FREE(filter);
2136 if (!ret) {
2137 return false;
2139 return true;
2142 static bool pdb_ads_search_groups(struct pdb_methods *m,
2143 struct pdb_search *search)
2145 struct pdb_ads_search_state *sstate;
2146 char *filter;
2147 bool ret;
2149 filter = talloc_asprintf(talloc_tos(),
2150 "(&(grouptype=%d)(objectclass=group))",
2151 GTYPE_SECURITY_GLOBAL_GROUP);
2152 if (filter == NULL) {
2153 return false;
2155 ret = pdb_ads_search_filter(m, search, filter, 0, &sstate);
2156 TALLOC_FREE(filter);
2157 if (!ret) {
2158 return false;
2160 return true;
2163 static bool pdb_ads_search_aliases(struct pdb_methods *m,
2164 struct pdb_search *search,
2165 const struct dom_sid *sid)
2167 struct pdb_ads_search_state *sstate;
2168 char *filter;
2169 bool ret;
2171 filter = talloc_asprintf(
2172 talloc_tos(), "(&(grouptype=%d)(objectclass=group))",
2173 sid_check_is_builtin(sid)
2174 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2175 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2177 if (filter == NULL) {
2178 return false;
2180 ret = pdb_ads_search_filter(m, search, filter, 0, &sstate);
2181 TALLOC_FREE(filter);
2182 if (!ret) {
2183 return false;
2185 return true;
2188 static bool pdb_ads_uid_to_sid(struct pdb_methods *m, uid_t uid,
2189 struct dom_sid *sid)
2191 struct pdb_ads_state *state = talloc_get_type_abort(
2192 m->private_data, struct pdb_ads_state);
2193 sid_compose(sid, &state->domainsid, uid);
2194 return true;
2197 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
2198 struct dom_sid *sid)
2200 struct pdb_ads_state *state = talloc_get_type_abort(
2201 m->private_data, struct pdb_ads_state);
2202 sid_compose(sid, &state->domainsid, gid);
2203 return true;
2206 static bool pdb_ads_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2207 uid_t *uid, gid_t *gid, enum lsa_SidType *type)
2209 struct pdb_ads_state *state = talloc_get_type_abort(
2210 m->private_data, struct pdb_ads_state);
2211 const char *attrs[4] = { "objectClass", "samAccountType",
2212 "uidNumber", "gidNumber" };
2213 struct tldap_message **msg;
2214 char *sidstr, *base;
2215 uint32_t atype;
2216 int rc;
2217 bool ret = false;
2219 *uid = -1;
2220 *gid = -1;
2222 sidstr = sid_binstring_hex(sid);
2223 if (sidstr == NULL) {
2224 return false;
2226 base = talloc_asprintf(talloc_tos(), "<SID=%s>", sidstr);
2227 SAFE_FREE(sidstr);
2229 rc = pdb_ads_search_fmt(
2230 state, base, TLDAP_SCOPE_BASE,
2231 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &msg,
2232 "(objectclass=*)");
2233 TALLOC_FREE(base);
2235 if (rc != TLDAP_SUCCESS) {
2236 DEBUG(10, ("pdb_ads_search_fmt failed: %s\n",
2237 tldap_errstr(talloc_tos(), state->ld, rc)));
2238 return false;
2240 if (talloc_array_length(msg) != 1) {
2241 DEBUG(10, ("Got %d objects, expected 1\n",
2242 (int)talloc_array_length(msg)));
2243 goto fail;
2245 if (!tldap_pull_uint32(msg[0], "samAccountType", &atype)) {
2246 DEBUG(10, ("samAccountType not found\n"));
2247 goto fail;
2249 if (atype == ATYPE_ACCOUNT) {
2250 *type = SID_NAME_USER;
2251 if (!tldap_pull_uint32(msg[0], "uidNumber", uid)) {
2252 DEBUG(10, ("Did not find uidNumber\n"));
2253 goto fail;
2255 } else {
2256 *type = SID_NAME_DOM_GRP;
2257 if (!tldap_pull_uint32(msg[0], "gidNumber", gid)) {
2258 DEBUG(10, ("Did not find gidNumber\n"));
2259 goto fail;
2262 ret = true;
2263 fail:
2264 TALLOC_FREE(msg);
2265 return ret;
2268 static uint32_t pdb_ads_capabilities(struct pdb_methods *m)
2270 return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
2273 static bool pdb_ads_new_rid(struct pdb_methods *m, uint32 *rid)
2275 return false;
2278 static bool pdb_ads_get_trusteddom_pw(struct pdb_methods *m,
2279 const char *domain, char** pwd,
2280 struct dom_sid *sid,
2281 time_t *pass_last_set_time)
2283 return false;
2286 static bool pdb_ads_set_trusteddom_pw(struct pdb_methods *m,
2287 const char* domain, const char* pwd,
2288 const struct dom_sid *sid)
2290 return false;
2293 static bool pdb_ads_del_trusteddom_pw(struct pdb_methods *m,
2294 const char *domain)
2296 return false;
2299 static NTSTATUS pdb_ads_enum_trusteddoms(struct pdb_methods *m,
2300 TALLOC_CTX *mem_ctx,
2301 uint32 *num_domains,
2302 struct trustdom_info ***domains)
2304 *num_domains = 0;
2305 *domains = NULL;
2306 return NT_STATUS_OK;
2309 static void pdb_ads_init_methods(struct pdb_methods *m)
2311 m->name = "ads";
2312 m->get_domain_info = pdb_ads_get_domain_info;
2313 m->getsampwnam = pdb_ads_getsampwnam;
2314 m->getsampwsid = pdb_ads_getsampwsid;
2315 m->create_user = pdb_ads_create_user;
2316 m->delete_user = pdb_ads_delete_user;
2317 m->add_sam_account = pdb_ads_add_sam_account;
2318 m->update_sam_account = pdb_ads_update_sam_account;
2319 m->delete_sam_account = pdb_ads_delete_sam_account;
2320 m->rename_sam_account = pdb_ads_rename_sam_account;
2321 m->update_login_attempts = pdb_ads_update_login_attempts;
2322 m->getgrsid = pdb_ads_getgrsid;
2323 m->getgrgid = pdb_ads_getgrgid;
2324 m->getgrnam = pdb_ads_getgrnam;
2325 m->create_dom_group = pdb_ads_create_dom_group;
2326 m->delete_dom_group = pdb_ads_delete_dom_group;
2327 m->add_group_mapping_entry = pdb_ads_add_group_mapping_entry;
2328 m->update_group_mapping_entry = pdb_ads_update_group_mapping_entry;
2329 m->delete_group_mapping_entry = pdb_ads_delete_group_mapping_entry;
2330 m->enum_group_mapping = pdb_ads_enum_group_mapping;
2331 m->enum_group_members = pdb_ads_enum_group_members;
2332 m->enum_group_memberships = pdb_ads_enum_group_memberships;
2333 m->set_unix_primary_group = pdb_ads_set_unix_primary_group;
2334 m->add_groupmem = pdb_ads_add_groupmem;
2335 m->del_groupmem = pdb_ads_del_groupmem;
2336 m->create_alias = pdb_ads_create_alias;
2337 m->delete_alias = pdb_ads_delete_alias;
2338 m->get_aliasinfo = pdb_default_get_aliasinfo;
2339 m->set_aliasinfo = pdb_ads_set_aliasinfo;
2340 m->add_aliasmem = pdb_ads_add_aliasmem;
2341 m->del_aliasmem = pdb_ads_del_aliasmem;
2342 m->enum_aliasmem = pdb_ads_enum_aliasmem;
2343 m->enum_alias_memberships = pdb_ads_enum_alias_memberships;
2344 m->lookup_rids = pdb_ads_lookup_rids;
2345 m->lookup_names = pdb_ads_lookup_names;
2346 m->get_account_policy = pdb_ads_get_account_policy;
2347 m->set_account_policy = pdb_ads_set_account_policy;
2348 m->get_seq_num = pdb_ads_get_seq_num;
2349 m->search_users = pdb_ads_search_users;
2350 m->search_groups = pdb_ads_search_groups;
2351 m->search_aliases = pdb_ads_search_aliases;
2352 m->uid_to_sid = pdb_ads_uid_to_sid;
2353 m->gid_to_sid = pdb_ads_gid_to_sid;
2354 m->sid_to_id = pdb_ads_sid_to_id;
2355 m->capabilities = pdb_ads_capabilities;
2356 m->new_rid = pdb_ads_new_rid;
2357 m->get_trusteddom_pw = pdb_ads_get_trusteddom_pw;
2358 m->set_trusteddom_pw = pdb_ads_set_trusteddom_pw;
2359 m->del_trusteddom_pw = pdb_ads_del_trusteddom_pw;
2360 m->enum_trusteddoms = pdb_ads_enum_trusteddoms;
2363 static void free_private_data(void **vp)
2365 struct pdb_ads_state *state = talloc_get_type_abort(
2366 *vp, struct pdb_ads_state);
2368 TALLOC_FREE(state->ld);
2369 return;
2373 this is used to catch debug messages from events
2375 static void s3_tldap_debug(void *context, enum tldap_debug_level level,
2376 const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
2378 static void s3_tldap_debug(void *context, enum tldap_debug_level level,
2379 const char *fmt, va_list ap)
2381 int samba_level = -1;
2382 char *s = NULL;
2383 switch (level) {
2384 case TLDAP_DEBUG_FATAL:
2385 samba_level = 0;
2386 break;
2387 case TLDAP_DEBUG_ERROR:
2388 samba_level = 1;
2389 break;
2390 case TLDAP_DEBUG_WARNING:
2391 samba_level = 2;
2392 break;
2393 case TLDAP_DEBUG_TRACE:
2394 samba_level = 11;
2395 break;
2398 if (vasprintf(&s, fmt, ap) == -1) {
2399 return;
2401 DEBUG(samba_level, ("tldap: %s", s));
2402 free(s);
2405 static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state)
2407 NTSTATUS status;
2408 int fd;
2410 if (tldap_connection_ok(state->ld)) {
2411 return state->ld;
2413 TALLOC_FREE(state->ld);
2415 status = open_socket_out(
2416 (struct sockaddr_storage *)(void *)&state->socket_address,
2417 0, 0, &fd);
2418 if (!NT_STATUS_IS_OK(status)) {
2419 DEBUG(10, ("Could not connect to %s: %s\n",
2420 state->socket_address.sun_path, nt_errstr(status)));
2421 return NULL;
2424 set_blocking(fd, false);
2426 state->ld = tldap_context_create(state, fd);
2427 if (state->ld == NULL) {
2428 close(fd);
2429 return NULL;
2431 tldap_set_debug(state->ld, s3_tldap_debug, NULL);
2433 return state->ld;
2436 int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base,
2437 int scope, const char *attrs[], int num_attrs,
2438 int attrsonly,
2439 TALLOC_CTX *mem_ctx, struct tldap_message ***res,
2440 const char *fmt, ...)
2442 struct tldap_context *ld;
2443 va_list ap;
2444 int ret;
2446 ld = pdb_ads_ld(state);
2447 if (ld == NULL) {
2448 return TLDAP_SERVER_DOWN;
2451 va_start(ap, fmt);
2452 ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly,
2453 mem_ctx, res, fmt, ap);
2454 va_end(ap);
2456 if (ret != TLDAP_SERVER_DOWN) {
2457 return ret;
2460 /* retry once */
2461 ld = pdb_ads_ld(state);
2462 if (ld == NULL) {
2463 return TLDAP_SERVER_DOWN;
2466 va_start(ap, fmt);
2467 ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly,
2468 mem_ctx, res, fmt, ap);
2469 va_end(ap);
2470 return ret;
2473 static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state,
2474 const char *location)
2476 const char *domain_attrs[2] = { "objectSid", "objectGUID" };
2477 const char *ncname_attrs[1] = { "netbiosname" };
2478 struct tldap_context *ld;
2479 struct tldap_message *rootdse, **domain, **ncname;
2480 TALLOC_CTX *frame = talloc_stackframe();
2481 NTSTATUS status;
2482 int num_domains;
2483 int rc;
2485 ZERO_STRUCT(state->socket_address);
2486 state->socket_address.sun_family = AF_UNIX;
2487 strlcpy(state->socket_address.sun_path, location,
2488 sizeof(state->socket_address.sun_path));
2490 ld = pdb_ads_ld(state);
2491 if (ld == NULL) {
2492 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2493 goto done;
2496 rc = tldap_fetch_rootdse(ld);
2497 if (rc != TLDAP_SUCCESS) {
2498 DEBUG(10, ("Could not retrieve rootdse: %s\n",
2499 tldap_errstr(talloc_tos(), state->ld, rc)));
2500 status = NT_STATUS_LDAP(rc);
2501 goto done;
2503 rootdse = tldap_rootdse(state->ld);
2505 state->domaindn = tldap_talloc_single_attribute(
2506 rootdse, "defaultNamingContext", state);
2507 if (state->domaindn == NULL) {
2508 DEBUG(10, ("Could not get defaultNamingContext\n"));
2509 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2510 goto done;
2512 DEBUG(10, ("defaultNamingContext = %s\n", state->domaindn));
2514 state->configdn = tldap_talloc_single_attribute(
2515 rootdse, "configurationNamingContext", state);
2516 if (state->configdn == NULL) {
2517 DEBUG(10, ("Could not get configurationNamingContext\n"));
2518 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2519 goto done;
2521 DEBUG(10, ("configurationNamingContext = %s\n", state->configdn));
2524 * Figure out our domain's SID
2526 rc = pdb_ads_search_fmt(
2527 state, state->domaindn, TLDAP_SCOPE_BASE,
2528 domain_attrs, ARRAY_SIZE(domain_attrs), 0,
2529 talloc_tos(), &domain, "(objectclass=*)");
2530 if (rc != TLDAP_SUCCESS) {
2531 DEBUG(10, ("Could not retrieve domain: %s\n",
2532 tldap_errstr(talloc_tos(), state->ld, rc)));
2533 status = NT_STATUS_LDAP(rc);
2534 goto done;
2537 num_domains = talloc_array_length(domain);
2538 if (num_domains != 1) {
2539 DEBUG(10, ("Got %d domains, expected one\n", num_domains));
2540 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2541 goto done;
2543 if (!tldap_pull_binsid(domain[0], "objectSid", &state->domainsid)) {
2544 DEBUG(10, ("Could not retrieve domain SID\n"));
2545 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2546 goto done;
2548 if (!tldap_pull_guid(domain[0], "objectGUID", &state->domainguid)) {
2549 DEBUG(10, ("Could not retrieve domain GUID\n"));
2550 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2551 goto done;
2553 DEBUG(10, ("Domain SID: %s\n", sid_string_dbg(&state->domainsid)));
2556 * Figure out our domain's short name
2558 rc = pdb_ads_search_fmt(
2559 state, state->configdn, TLDAP_SCOPE_SUB,
2560 ncname_attrs, ARRAY_SIZE(ncname_attrs), 0,
2561 talloc_tos(), &ncname, "(ncname=%s)", state->domaindn);
2562 if (rc != TLDAP_SUCCESS) {
2563 DEBUG(10, ("Could not retrieve ncname: %s\n",
2564 tldap_errstr(talloc_tos(), state->ld, rc)));
2565 status = NT_STATUS_LDAP(rc);
2566 goto done;
2568 if (talloc_array_length(ncname) != 1) {
2569 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2570 goto done;
2573 state->netbiosname = tldap_talloc_single_attribute(
2574 ncname[0], "netbiosname", state);
2575 if (state->netbiosname == NULL) {
2576 DEBUG(10, ("Could not get netbiosname\n"));
2577 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2578 goto done;
2580 DEBUG(10, ("netbiosname: %s\n", state->netbiosname));
2582 if (!strequal(lp_workgroup(), state->netbiosname)) {
2583 DEBUG(1, ("ADS is different domain (%s) than ours (%s)\n",
2584 state->netbiosname, lp_workgroup()));
2585 status = NT_STATUS_NO_SUCH_DOMAIN;
2586 goto done;
2589 secrets_store_domain_sid(state->netbiosname, &state->domainsid);
2591 status = NT_STATUS_OK;
2592 done:
2593 TALLOC_FREE(frame);
2594 return status;
2597 static NTSTATUS pdb_ads_init_secrets(struct pdb_methods *m)
2599 #if _SAMBA_BUILD_ == 4
2600 struct pdb_domain_info *dom_info;
2601 bool ret;
2603 dom_info = pdb_ads_get_domain_info(m, m);
2604 if (!dom_info) {
2605 return NT_STATUS_UNSUCCESSFUL;
2608 secrets_clear_domain_protection(dom_info->name);
2609 ret = secrets_store_domain_sid(dom_info->name,
2610 &dom_info->sid);
2611 if (!ret) {
2612 goto done;
2614 ret = secrets_store_domain_guid(dom_info->name,
2615 &dom_info->guid);
2616 if (!ret) {
2617 goto done;
2619 ret = secrets_mark_domain_protected(dom_info->name);
2620 if (!ret) {
2621 goto done;
2624 done:
2625 TALLOC_FREE(dom_info);
2626 if (!ret) {
2627 return NT_STATUS_UNSUCCESSFUL;
2629 #endif
2630 return NT_STATUS_OK;
2633 static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method,
2634 const char *location)
2636 struct pdb_methods *m;
2637 struct pdb_ads_state *state;
2638 char *tmp = NULL;
2639 NTSTATUS status;
2641 m = talloc(NULL, struct pdb_methods);
2642 if (m == NULL) {
2643 return NT_STATUS_NO_MEMORY;
2645 state = talloc_zero(m, struct pdb_ads_state);
2646 if (state == NULL) {
2647 goto nomem;
2649 m->private_data = state;
2650 m->free_private_data = free_private_data;
2651 pdb_ads_init_methods(m);
2653 if (location == NULL) {
2654 tmp = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi",
2655 lp_private_dir());
2656 location = tmp;
2658 if (location == NULL) {
2659 goto nomem;
2662 status = pdb_ads_connect(state, location);
2663 if (!NT_STATUS_IS_OK(status)) {
2664 DEBUG(10, ("pdb_ads_connect failed: %s\n", nt_errstr(status)));
2665 goto fail;
2668 status = pdb_ads_init_secrets(m);
2669 if (!NT_STATUS_IS_OK(status)) {
2670 DEBUG(10, ("pdb_ads_init_secrets failed!\n"));
2671 goto fail;
2674 *pdb_method = m;
2675 return NT_STATUS_OK;
2676 nomem:
2677 status = NT_STATUS_NO_MEMORY;
2678 fail:
2679 TALLOC_FREE(m);
2680 return status;
2683 NTSTATUS pdb_ads_init(void);
2684 NTSTATUS pdb_ads_init(void)
2686 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "ads",
2687 pdb_init_ads);