tevent: expose tevent_context_init_ops
[Samba/gebeck_regimport.git] / source3 / passdb / pdb_ads.c
blobdf9b7b3a958a8d85803787edcc3bcd32276a8216
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 "../librpc/gen_ndr/idmap.h"
28 #include "../libcli/ldap/ldap_ndr.h"
29 #include "../libcli/security/security.h"
30 #include "../libds/common/flag_mapping.h"
32 struct pdb_ads_state {
33 struct sockaddr_un socket_address;
34 struct tldap_context *ld;
35 struct dom_sid domainsid;
36 struct GUID domainguid;
37 char *domaindn;
38 char *configdn;
39 char *netbiosname;
42 struct pdb_ads_samu_private {
43 char *dn;
44 struct tldap_message *ldapmsg;
47 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
48 struct dom_sid *sid);
49 static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
50 struct dom_sid *psid);
51 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
52 const struct dom_sid *sid,
53 TALLOC_CTX *mem_ctx, char **pdn);
54 static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state);
55 static int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base,
56 int scope, const char *attrs[], int num_attrs,
57 int attrsonly,
58 TALLOC_CTX *mem_ctx, struct tldap_message ***res,
59 const char *fmt, ...);
60 static NTSTATUS pdb_ads_getsamupriv(struct pdb_ads_state *state,
61 const char *filter,
62 TALLOC_CTX *mem_ctx,
63 struct pdb_ads_samu_private **presult);
65 static bool pdb_ads_pull_time(struct tldap_message *msg, const char *attr,
66 time_t *ptime)
68 uint64_t tmp;
70 if (!tldap_pull_uint64(msg, attr, &tmp)) {
71 return false;
73 *ptime = nt_time_to_unix(tmp);
74 return true;
77 static gid_t pdb_ads_sid2gid(const struct dom_sid *sid)
79 uint32_t rid;
80 sid_peek_rid(sid, &rid);
81 return rid;
84 static char *pdb_ads_domaindn2dns(TALLOC_CTX *mem_ctx, char *dn)
86 char *result, *p;
88 result = talloc_string_sub2(mem_ctx, dn, "DC=", "", false, false,
89 true);
90 if (result == NULL) {
91 return NULL;
94 while ((p = strchr_m(result, ',')) != NULL) {
95 *p = '.';
98 return result;
101 static struct pdb_domain_info *pdb_ads_get_domain_info(
102 struct pdb_methods *m, TALLOC_CTX *mem_ctx)
104 struct pdb_ads_state *state = talloc_get_type_abort(
105 m->private_data, struct pdb_ads_state);
106 struct pdb_domain_info *info;
107 struct tldap_message *rootdse;
108 char *tmp;
110 info = talloc(mem_ctx, struct pdb_domain_info);
111 if (info == NULL) {
112 return NULL;
114 info->name = talloc_strdup(info, state->netbiosname);
115 if (info->name == NULL) {
116 goto fail;
118 info->dns_domain = pdb_ads_domaindn2dns(info, state->domaindn);
119 if (info->dns_domain == NULL) {
120 goto fail;
123 rootdse = tldap_rootdse(state->ld);
124 tmp = tldap_talloc_single_attribute(rootdse, "rootDomainNamingContext",
125 talloc_tos());
126 if (tmp == NULL) {
127 goto fail;
129 info->dns_forest = pdb_ads_domaindn2dns(info, tmp);
130 TALLOC_FREE(tmp);
131 if (info->dns_forest == NULL) {
132 goto fail;
134 info->sid = state->domainsid;
135 info->guid = state->domainguid;
136 return info;
138 fail:
139 TALLOC_FREE(info);
140 return NULL;
143 static struct pdb_ads_samu_private *pdb_ads_get_samu_private(
144 struct pdb_methods *m, struct samu *sam)
146 struct pdb_ads_state *state = talloc_get_type_abort(
147 m->private_data, struct pdb_ads_state);
148 struct pdb_ads_samu_private *result;
149 char *sidstr, *filter;
150 NTSTATUS status;
152 result = (struct pdb_ads_samu_private *)
153 pdb_get_backend_private_data(sam, m);
155 if (result != NULL) {
156 return talloc_get_type_abort(
157 result, struct pdb_ads_samu_private);
160 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), pdb_get_user_sid(sam));
161 if (sidstr == NULL) {
162 return NULL;
165 filter = talloc_asprintf(
166 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
167 TALLOC_FREE(sidstr);
168 if (filter == NULL) {
169 return NULL;
172 status = pdb_ads_getsamupriv(state, filter, sam, &result);
173 TALLOC_FREE(filter);
174 if (!NT_STATUS_IS_OK(status)) {
175 return NULL;
178 return result;
181 static NTSTATUS pdb_ads_init_sam_from_priv(struct pdb_methods *m,
182 struct samu *sam,
183 struct pdb_ads_samu_private *priv)
185 struct pdb_ads_state *state = talloc_get_type_abort(
186 m->private_data, struct pdb_ads_state);
187 TALLOC_CTX *frame = talloc_stackframe();
188 NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
189 struct tldap_message *entry = priv->ldapmsg;
190 char *str;
191 time_t tmp_time;
192 struct dom_sid sid;
193 uint64_t n;
194 uint32_t i;
195 DATA_BLOB blob;
197 str = tldap_talloc_single_attribute(entry, "samAccountName", sam);
198 if (str == NULL) {
199 DEBUG(10, ("no samAccountName\n"));
200 goto fail;
202 pdb_set_username(sam, str, PDB_SET);
204 if (pdb_ads_pull_time(entry, "lastLogon", &tmp_time)) {
205 pdb_set_logon_time(sam, tmp_time, PDB_SET);
207 if (pdb_ads_pull_time(entry, "lastLogoff", &tmp_time)) {
208 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
210 if (pdb_ads_pull_time(entry, "pwdLastSet", &tmp_time)) {
211 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
213 if (pdb_ads_pull_time(entry, "accountExpires", &tmp_time)) {
214 pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
217 str = tldap_talloc_single_attribute(entry, "displayName",
218 talloc_tos());
219 if (str != NULL) {
220 pdb_set_fullname(sam, str, PDB_SET);
223 str = tldap_talloc_single_attribute(entry, "homeDirectory",
224 talloc_tos());
225 if (str != NULL) {
226 pdb_set_homedir(sam, str, PDB_SET);
229 str = tldap_talloc_single_attribute(entry, "homeDrive", talloc_tos());
230 if (str != NULL) {
231 pdb_set_dir_drive(sam, str, PDB_SET);
234 str = tldap_talloc_single_attribute(entry, "scriptPath", talloc_tos());
235 if (str != NULL) {
236 pdb_set_logon_script(sam, str, PDB_SET);
239 str = tldap_talloc_single_attribute(entry, "profilePath",
240 talloc_tos());
241 if (str != NULL) {
242 pdb_set_profile_path(sam, str, PDB_SET);
245 str = tldap_talloc_single_attribute(entry, "profilePath",
246 talloc_tos());
247 if (str != NULL) {
248 pdb_set_profile_path(sam, str, PDB_SET);
251 str = tldap_talloc_single_attribute(entry, "comment",
252 talloc_tos());
253 if (str != NULL) {
254 pdb_set_comment(sam, str, PDB_SET);
257 str = tldap_talloc_single_attribute(entry, "description",
258 talloc_tos());
259 if (str != NULL) {
260 pdb_set_acct_desc(sam, str, PDB_SET);
263 str = tldap_talloc_single_attribute(entry, "userWorkstations",
264 talloc_tos());
265 if (str != NULL) {
266 pdb_set_workstations(sam, str, PDB_SET);
269 str = tldap_talloc_single_attribute(entry, "userParameters",
270 talloc_tos());
271 if (str != NULL) {
272 pdb_set_munged_dial(sam, str, PDB_SET);
275 if (!tldap_pull_binsid(entry, "objectSid", &sid)) {
276 DEBUG(10, ("Could not pull SID\n"));
277 goto fail;
279 pdb_set_user_sid(sam, &sid, PDB_SET);
281 if (!tldap_pull_uint64(entry, "userAccountControl", &n)) {
282 DEBUG(10, ("Could not pull userAccountControl\n"));
283 goto fail;
285 pdb_set_acct_ctrl(sam, ds_uf2acb(n), PDB_SET);
287 if (tldap_get_single_valueblob(entry, "unicodePwd", &blob)) {
288 if (blob.length != NT_HASH_LEN) {
289 DEBUG(0, ("Got NT hash of length %d, expected %d\n",
290 (int)blob.length, NT_HASH_LEN));
291 goto fail;
293 pdb_set_nt_passwd(sam, blob.data, PDB_SET);
296 if (tldap_get_single_valueblob(entry, "dBCSPwd", &blob)) {
297 if (blob.length != LM_HASH_LEN) {
298 DEBUG(0, ("Got LM hash of length %d, expected %d\n",
299 (int)blob.length, LM_HASH_LEN));
300 goto fail;
302 pdb_set_lanman_passwd(sam, blob.data, PDB_SET);
305 if (tldap_pull_uint64(entry, "primaryGroupID", &n)) {
306 sid_compose(&sid, &state->domainsid, n);
307 pdb_set_group_sid(sam, &sid, PDB_SET);
311 if (tldap_pull_uint32(entry, "countryCode", &i)) {
312 pdb_set_country_code(sam, i, PDB_SET);
315 if (tldap_pull_uint32(entry, "codePage", &i)) {
316 pdb_set_code_page(sam, i, PDB_SET);
319 if (tldap_get_single_valueblob(entry, "logonHours", &blob)) {
321 if (blob.length > MAX_HOURS_LEN) {
322 status = NT_STATUS_INVALID_PARAMETER;
323 goto fail;
325 pdb_set_logon_divs(sam, blob.length * 8, PDB_SET);
326 pdb_set_hours_len(sam, blob.length, PDB_SET);
327 pdb_set_hours(sam, blob.data, blob.length, PDB_SET);
329 } else {
330 uint8_t hours[21];
331 pdb_set_logon_divs(sam, sizeof(hours)/8, PDB_SET);
332 pdb_set_hours_len(sam, sizeof(hours), PDB_SET);
333 memset(hours, 0xff, sizeof(hours));
334 pdb_set_hours(sam, hours, sizeof(hours), PDB_SET);
337 status = NT_STATUS_OK;
338 fail:
339 TALLOC_FREE(frame);
340 return status;
343 static bool pdb_ads_make_time_mod(struct tldap_message *existing,
344 TALLOC_CTX *mem_ctx,
345 struct tldap_mod **pmods, int *pnum_mods,
346 const char *attrib, time_t t)
348 uint64_t nt_time;
350 unix_to_nt_time(&nt_time, t);
352 return tldap_make_mod_fmt(
353 existing, mem_ctx, pmods, pnum_mods, attrib,
354 "%llu", nt_time);
357 static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state,
358 struct tldap_message *existing,
359 TALLOC_CTX *mem_ctx,
360 struct tldap_mod **pmods, int *pnum_mods,
361 struct samu *sam)
363 bool ret = true;
364 DATA_BLOB blob;
365 const char *pw;
367 /* TODO: All fields :-) */
369 ret &= tldap_make_mod_fmt(
370 existing, mem_ctx, pmods, pnum_mods, "displayName",
371 "%s", pdb_get_fullname(sam));
373 pw = pdb_get_plaintext_passwd(sam);
376 * If we have the plain text pw, this is probably about to be
377 * set. Is this true always?
379 if (pw != NULL) {
380 char *pw_quote;
381 uint8_t *pw_utf16;
382 size_t pw_utf16_len;
384 pw_quote = talloc_asprintf(talloc_tos(), "\"%s\"", pw);
385 if (pw_quote == NULL) {
386 ret = false;
387 goto fail;
390 ret &= convert_string_talloc(talloc_tos(),
391 CH_UNIX, CH_UTF16LE,
392 pw_quote, strlen(pw_quote),
393 &pw_utf16, &pw_utf16_len);
394 if (!ret) {
395 goto fail;
397 blob = data_blob_const(pw_utf16, pw_utf16_len);
399 ret &= tldap_add_mod_blobs(mem_ctx, pmods, pnum_mods,
400 TLDAP_MOD_REPLACE,
401 "unicodePwd", &blob, 1);
402 TALLOC_FREE(pw_utf16);
403 TALLOC_FREE(pw_quote);
406 ret &= tldap_make_mod_fmt(
407 existing, mem_ctx, pmods, pnum_mods, "userAccountControl",
408 "%d", ds_acb2uf(pdb_get_acct_ctrl(sam)));
410 ret &= tldap_make_mod_fmt(
411 existing, mem_ctx, pmods, pnum_mods, "homeDirectory",
412 "%s", pdb_get_homedir(sam));
414 ret &= tldap_make_mod_fmt(
415 existing, mem_ctx, pmods, pnum_mods, "homeDrive",
416 "%s", pdb_get_dir_drive(sam));
418 ret &= tldap_make_mod_fmt(
419 existing, mem_ctx, pmods, pnum_mods, "scriptPath",
420 "%s", pdb_get_logon_script(sam));
422 ret &= tldap_make_mod_fmt(
423 existing, mem_ctx, pmods, pnum_mods, "profilePath",
424 "%s", pdb_get_profile_path(sam));
426 ret &= tldap_make_mod_fmt(
427 existing, mem_ctx, pmods, pnum_mods, "comment",
428 "%s", pdb_get_comment(sam));
430 ret &= tldap_make_mod_fmt(
431 existing, mem_ctx, pmods, pnum_mods, "description",
432 "%s", pdb_get_acct_desc(sam));
434 ret &= tldap_make_mod_fmt(
435 existing, mem_ctx, pmods, pnum_mods, "userWorkstations",
436 "%s", pdb_get_workstations(sam));
438 ret &= tldap_make_mod_fmt(
439 existing, mem_ctx, pmods, pnum_mods, "userParameters",
440 "%s", pdb_get_munged_dial(sam));
442 ret &= tldap_make_mod_fmt(
443 existing, mem_ctx, pmods, pnum_mods, "countryCode",
444 "%i", (int)pdb_get_country_code(sam));
446 ret &= tldap_make_mod_fmt(
447 existing, mem_ctx, pmods, pnum_mods, "codePage",
448 "%i", (int)pdb_get_code_page(sam));
450 ret &= pdb_ads_make_time_mod(
451 existing, mem_ctx, pmods, pnum_mods, "accountExpires",
452 (int)pdb_get_kickoff_time(sam));
454 ret &= tldap_make_mod_blob(
455 existing, mem_ctx, pmods, pnum_mods, "logonHours",
456 data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam)));
458 fail:
459 return ret;
462 static NTSTATUS pdb_ads_getsamupriv(struct pdb_ads_state *state,
463 const char *filter,
464 TALLOC_CTX *mem_ctx,
465 struct pdb_ads_samu_private **presult)
467 const char * attrs[] = {
468 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
469 "sAMAccountName", "displayName", "homeDirectory",
470 "homeDrive", "scriptPath", "profilePath", "description",
471 "userWorkstations", "comment", "userParameters", "objectSid",
472 "primaryGroupID", "userAccountControl", "logonHours",
473 "badPwdCount", "logonCount", "countryCode", "codePage",
474 "unicodePwd", "dBCSPwd" };
475 struct tldap_message **users;
476 int rc, count;
477 struct pdb_ads_samu_private *result;
479 result = talloc(mem_ctx, struct pdb_ads_samu_private);
480 if (result == NULL) {
481 return NT_STATUS_NO_MEMORY;
484 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
485 attrs, ARRAY_SIZE(attrs), 0, result,
486 &users, "%s", filter);
487 if (rc != TLDAP_SUCCESS) {
488 DEBUG(10, ("ldap_search failed %s\n",
489 tldap_errstr(talloc_tos(), state->ld, rc)));
490 TALLOC_FREE(result);
491 return NT_STATUS_LDAP(rc);
494 count = talloc_array_length(users);
495 if (count != 1) {
496 DEBUG(10, ("Expected 1 user, got %d\n", count));
497 TALLOC_FREE(result);
498 return NT_STATUS_NO_SUCH_USER;
501 result->ldapmsg = users[0];
502 if (!tldap_entry_dn(result->ldapmsg, &result->dn)) {
503 DEBUG(10, ("Could not extract dn\n"));
504 TALLOC_FREE(result);
505 return NT_STATUS_INTERNAL_DB_CORRUPTION;
508 *presult = result;
509 return NT_STATUS_OK;
512 static NTSTATUS pdb_ads_getsampwfilter(struct pdb_methods *m,
513 struct pdb_ads_state *state,
514 struct samu *sam_acct,
515 const char *filter)
517 struct pdb_ads_samu_private *priv;
518 NTSTATUS status;
520 status = pdb_ads_getsamupriv(state, filter, sam_acct, &priv);
521 if (!NT_STATUS_IS_OK(status)) {
522 DEBUG(10, ("pdb_ads_getsamupriv failed: %s\n",
523 nt_errstr(status)));
524 return status;
527 status = pdb_ads_init_sam_from_priv(m, sam_acct, priv);
528 if (!NT_STATUS_IS_OK(status)) {
529 DEBUG(10, ("pdb_ads_init_sam_from_priv failed: %s\n",
530 nt_errstr(status)));
531 TALLOC_FREE(priv);
532 return status;
535 pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
536 return NT_STATUS_OK;
539 static NTSTATUS pdb_ads_getsampwnam(struct pdb_methods *m,
540 struct samu *sam_acct,
541 const char *username)
543 struct pdb_ads_state *state = talloc_get_type_abort(
544 m->private_data, struct pdb_ads_state);
545 char *filter;
547 filter = talloc_asprintf(
548 talloc_tos(), "(&(samaccountname=%s)(objectclass=user))",
549 username);
550 NT_STATUS_HAVE_NO_MEMORY(filter);
552 return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
555 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
556 struct samu *sam_acct,
557 const struct dom_sid *sid)
559 struct pdb_ads_state *state = talloc_get_type_abort(
560 m->private_data, struct pdb_ads_state);
561 char *sidstr, *filter;
563 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
564 NT_STATUS_HAVE_NO_MEMORY(sidstr);
566 filter = talloc_asprintf(
567 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
568 TALLOC_FREE(sidstr);
569 NT_STATUS_HAVE_NO_MEMORY(filter);
571 return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
574 static NTSTATUS pdb_ads_create_user(struct pdb_methods *m,
575 TALLOC_CTX *tmp_ctx,
576 const char *name, uint32 acct_flags,
577 uint32 *rid)
579 struct pdb_ads_state *state = talloc_get_type_abort(
580 m->private_data, struct pdb_ads_state);
581 struct tldap_context *ld;
582 const char *attrs[1] = { "objectSid" };
583 struct tldap_mod *mods = NULL;
584 int num_mods = 0;
585 struct tldap_message **user;
586 struct dom_sid sid;
587 char *dn;
588 int rc;
589 bool ok;
591 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
592 state->domaindn);
593 if (dn == NULL) {
594 return NT_STATUS_NO_MEMORY;
597 ld = pdb_ads_ld(state);
598 if (ld == NULL) {
599 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
602 /* TODO: Create machines etc */
604 ok = true;
605 ok &= tldap_make_mod_fmt(
606 NULL, talloc_tos(), &mods, &num_mods, "objectClass", "user");
607 ok &= tldap_make_mod_fmt(
608 NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
609 name);
610 if (!ok) {
611 return NT_STATUS_NO_MEMORY;
615 rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
616 if (rc != TLDAP_SUCCESS) {
617 DEBUG(10, ("ldap_add failed %s\n",
618 tldap_errstr(talloc_tos(), ld, rc)));
619 TALLOC_FREE(dn);
620 return NT_STATUS_LDAP(rc);
623 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
624 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
625 &user,
626 "(&(objectclass=user)(samaccountname=%s))",
627 name);
628 if (rc != TLDAP_SUCCESS) {
629 DEBUG(10, ("Could not find just created user %s: %s\n",
630 name, tldap_errstr(talloc_tos(), state->ld, rc)));
631 TALLOC_FREE(dn);
632 return NT_STATUS_LDAP(rc);
635 if (talloc_array_length(user) != 1) {
636 DEBUG(10, ("Got %d users, expected one\n",
637 (int)talloc_array_length(user)));
638 TALLOC_FREE(dn);
639 return NT_STATUS_LDAP(rc);
642 if (!tldap_pull_binsid(user[0], "objectSid", &sid)) {
643 DEBUG(10, ("Could not fetch objectSid from user %s\n",
644 name));
645 TALLOC_FREE(dn);
646 return NT_STATUS_INTERNAL_DB_CORRUPTION;
649 sid_peek_rid(&sid, rid);
650 TALLOC_FREE(dn);
651 return NT_STATUS_OK;
654 static NTSTATUS pdb_ads_delete_user(struct pdb_methods *m,
655 TALLOC_CTX *tmp_ctx,
656 struct samu *sam)
658 struct pdb_ads_state *state = talloc_get_type_abort(
659 m->private_data, struct pdb_ads_state);
660 NTSTATUS status;
661 struct tldap_context *ld;
662 char *dn;
663 int rc;
665 ld = pdb_ads_ld(state);
666 if (ld == NULL) {
667 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
670 status = pdb_ads_sid2dn(state, pdb_get_user_sid(sam), talloc_tos(),
671 &dn);
672 if (!NT_STATUS_IS_OK(status)) {
673 return status;
676 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
677 TALLOC_FREE(dn);
678 if (rc != TLDAP_SUCCESS) {
679 DEBUG(10, ("ldap_delete for %s failed: %s\n", dn,
680 tldap_errstr(talloc_tos(), ld, rc)));
681 return NT_STATUS_LDAP(rc);
683 return NT_STATUS_OK;
686 static NTSTATUS pdb_ads_add_sam_account(struct pdb_methods *m,
687 struct samu *sampass)
689 return NT_STATUS_NOT_IMPLEMENTED;
692 static NTSTATUS pdb_ads_update_sam_account(struct pdb_methods *m,
693 struct samu *sam)
695 struct pdb_ads_state *state = talloc_get_type_abort(
696 m->private_data, struct pdb_ads_state);
697 struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam);
698 struct tldap_context *ld;
699 struct tldap_mod *mods = NULL;
700 int rc, num_mods = 0;
702 ld = pdb_ads_ld(state);
703 if (ld == NULL) {
704 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
707 if (!pdb_ads_init_ads_from_sam(state, priv->ldapmsg, talloc_tos(),
708 &mods, &num_mods, sam)) {
709 return NT_STATUS_NO_MEMORY;
712 if (num_mods == 0) {
713 /* Nothing to do, just return success */
714 return NT_STATUS_OK;
717 rc = tldap_modify(ld, priv->dn, mods, num_mods, NULL, 0,
718 NULL, 0);
719 TALLOC_FREE(mods);
720 if (rc != TLDAP_SUCCESS) {
721 DEBUG(10, ("ldap_modify for %s failed: %s\n", priv->dn,
722 tldap_errstr(talloc_tos(), ld, rc)));
723 return NT_STATUS_LDAP(rc);
726 return NT_STATUS_OK;
729 static NTSTATUS pdb_ads_delete_sam_account(struct pdb_methods *m,
730 struct samu *username)
732 return NT_STATUS_NOT_IMPLEMENTED;
735 static NTSTATUS pdb_ads_rename_sam_account(struct pdb_methods *m,
736 struct samu *oldname,
737 const char *newname)
739 return NT_STATUS_NOT_IMPLEMENTED;
742 static NTSTATUS pdb_ads_update_login_attempts(struct pdb_methods *m,
743 struct samu *sam_acct,
744 bool success)
746 return NT_STATUS_NOT_IMPLEMENTED;
749 static NTSTATUS pdb_ads_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
750 const char *filter,
751 TALLOC_CTX *mem_ctx,
752 struct tldap_message **pmsg)
754 struct pdb_ads_state *state = talloc_get_type_abort(
755 m->private_data, struct pdb_ads_state);
756 const char *attrs[4] = { "objectSid", "description", "samAccountName",
757 "groupType" };
758 char *str;
759 struct tldap_message **group;
760 uint32_t grouptype;
761 int rc;
763 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
764 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
765 &group, "%s", filter);
766 if (rc != TLDAP_SUCCESS) {
767 DEBUG(10, ("ldap_search failed %s\n",
768 tldap_errstr(talloc_tos(), state->ld, rc)));
769 return NT_STATUS_LDAP(rc);
771 if (talloc_array_length(group) != 1) {
772 DEBUG(10, ("Expected 1 group, got %d\n",
773 (int)talloc_array_length(group)));
774 return NT_STATUS_INTERNAL_DB_CORRUPTION;
777 if (!tldap_pull_binsid(group[0], "objectSid", &map->sid)) {
778 return NT_STATUS_INTERNAL_DB_CORRUPTION;
780 map->gid = pdb_ads_sid2gid(&map->sid);
782 if (!tldap_pull_uint32(group[0], "groupType", &grouptype)) {
783 return NT_STATUS_INTERNAL_DB_CORRUPTION;
785 switch (grouptype) {
786 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
787 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
788 map->sid_name_use = SID_NAME_ALIAS;
789 break;
790 case GTYPE_SECURITY_GLOBAL_GROUP:
791 map->sid_name_use = SID_NAME_DOM_GRP;
792 break;
793 default:
794 return NT_STATUS_INTERNAL_DB_CORRUPTION;
797 str = tldap_talloc_single_attribute(group[0], "samAccountName",
798 talloc_tos());
799 if (str == NULL) {
800 return NT_STATUS_INTERNAL_DB_CORRUPTION;
802 map->nt_name = talloc_move(map, &str);
804 str = tldap_talloc_single_attribute(group[0], "description",
805 talloc_tos());
806 if (str != NULL) {
807 map->comment = talloc_move(map, &str);
808 } else {
809 map->comment = talloc_strdup(map, "");
812 if (pmsg != NULL) {
813 *pmsg = talloc_move(mem_ctx, &group[0]);
815 TALLOC_FREE(group);
816 return NT_STATUS_OK;
819 static NTSTATUS pdb_ads_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
820 struct dom_sid sid)
822 char *filter;
823 NTSTATUS status;
825 filter = talloc_asprintf(talloc_tos(),
826 "(&(objectsid=%s)(objectclass=group))",
827 sid_string_talloc(talloc_tos(), &sid));
828 if (filter == NULL) {
829 return NT_STATUS_NO_MEMORY;
832 status = pdb_ads_getgrfilter(m, map, filter, NULL, NULL);
833 TALLOC_FREE(filter);
834 return status;
837 static NTSTATUS pdb_ads_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
838 gid_t gid)
840 struct dom_sid sid;
841 pdb_ads_gid_to_sid(m, gid, &sid);
842 return pdb_ads_getgrsid(m, map, sid);
845 static NTSTATUS pdb_ads_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
846 const char *name)
848 char *filter;
849 NTSTATUS status;
851 filter = talloc_asprintf(talloc_tos(),
852 "(&(samaccountname=%s)(objectclass=group))",
853 name);
854 if (filter == NULL) {
855 return NT_STATUS_NO_MEMORY;
858 status = pdb_ads_getgrfilter(m, map, filter, NULL, NULL);
859 TALLOC_FREE(filter);
860 return status;
863 static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m,
864 TALLOC_CTX *mem_ctx, const char *name,
865 uint32 *rid)
867 TALLOC_CTX *frame = talloc_stackframe();
868 struct pdb_ads_state *state = talloc_get_type_abort(
869 m->private_data, struct pdb_ads_state);
870 struct tldap_context *ld;
871 const char *attrs[1] = { "objectSid" };
872 int num_mods = 0;
873 struct tldap_mod *mods = NULL;
874 struct tldap_message **alias;
875 struct dom_sid sid;
876 char *dn;
877 int rc;
878 bool ok = true;
880 ld = pdb_ads_ld(state);
881 if (ld == NULL) {
882 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
885 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
886 state->domaindn);
887 if (dn == NULL) {
888 TALLOC_FREE(frame);
889 return NT_STATUS_NO_MEMORY;
892 ok &= tldap_make_mod_fmt(
893 NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
894 name);
895 ok &= tldap_make_mod_fmt(
896 NULL, talloc_tos(), &mods, &num_mods, "objectClass", "group");
897 ok &= tldap_make_mod_fmt(
898 NULL, talloc_tos(), &mods, &num_mods, "groupType",
899 "%d", (int)GTYPE_SECURITY_GLOBAL_GROUP);
901 if (!ok) {
902 TALLOC_FREE(frame);
903 return NT_STATUS_NO_MEMORY;
906 rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
907 if (rc != TLDAP_SUCCESS) {
908 DEBUG(10, ("ldap_add failed %s\n",
909 tldap_errstr(talloc_tos(), state->ld, rc)));
910 TALLOC_FREE(frame);
911 return NT_STATUS_LDAP(rc);
914 rc = pdb_ads_search_fmt(
915 state, state->domaindn, TLDAP_SCOPE_SUB,
916 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
917 "(&(objectclass=group)(samaccountname=%s))", name);
918 if (rc != TLDAP_SUCCESS) {
919 DEBUG(10, ("Could not find just created alias %s: %s\n",
920 name, tldap_errstr(talloc_tos(), state->ld, rc)));
921 TALLOC_FREE(frame);
922 return NT_STATUS_LDAP(rc);
925 if (talloc_array_length(alias) != 1) {
926 DEBUG(10, ("Got %d alias, expected one\n",
927 (int)talloc_array_length(alias)));
928 TALLOC_FREE(frame);
929 return NT_STATUS_LDAP(rc);
932 if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
933 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
934 name));
935 TALLOC_FREE(frame);
936 return NT_STATUS_INTERNAL_DB_CORRUPTION;
939 sid_peek_rid(&sid, rid);
940 TALLOC_FREE(frame);
941 return NT_STATUS_OK;
944 static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m,
945 TALLOC_CTX *mem_ctx, uint32 rid)
947 struct pdb_ads_state *state = talloc_get_type_abort(
948 m->private_data, struct pdb_ads_state);
949 struct tldap_context *ld;
950 struct dom_sid sid;
951 char *sidstr;
952 struct tldap_message **msg;
953 char *dn;
954 int rc;
956 sid_compose(&sid, &state->domainsid, rid);
958 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), &sid);
959 NT_STATUS_HAVE_NO_MEMORY(sidstr);
961 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
962 NULL, 0, 0, talloc_tos(), &msg,
963 ("(&(objectSid=%s)(objectClass=group))"),
964 sidstr);
965 TALLOC_FREE(sidstr);
966 if (rc != TLDAP_SUCCESS) {
967 DEBUG(10, ("ldap_search failed %s\n",
968 tldap_errstr(talloc_tos(), state->ld, rc)));
969 return NT_STATUS_LDAP(rc);
972 switch talloc_array_length(msg) {
973 case 0:
974 return NT_STATUS_NO_SUCH_GROUP;
975 case 1:
976 break;
977 default:
978 return NT_STATUS_INTERNAL_DB_CORRUPTION;
981 if (!tldap_entry_dn(msg[0], &dn)) {
982 TALLOC_FREE(msg);
983 return NT_STATUS_INTERNAL_DB_CORRUPTION;
986 ld = pdb_ads_ld(state);
987 if (ld == NULL) {
988 TALLOC_FREE(msg);
989 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
992 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
993 TALLOC_FREE(msg);
994 if (rc != TLDAP_SUCCESS) {
995 DEBUG(10, ("ldap_delete failed: %s\n",
996 tldap_errstr(talloc_tos(), state->ld, rc)));
997 return NT_STATUS_LDAP(rc);
1000 return NT_STATUS_OK;
1003 static NTSTATUS pdb_ads_add_group_mapping_entry(struct pdb_methods *m,
1004 GROUP_MAP *map)
1006 return NT_STATUS_NOT_IMPLEMENTED;
1009 static NTSTATUS pdb_ads_update_group_mapping_entry(struct pdb_methods *m,
1010 GROUP_MAP *map)
1012 struct pdb_ads_state *state = talloc_get_type_abort(
1013 m->private_data, struct pdb_ads_state);
1014 struct tldap_context *ld;
1015 struct tldap_mod *mods = NULL;
1016 char *filter;
1017 struct tldap_message *existing;
1018 char *dn;
1019 GROUP_MAP *existing_map;
1020 int rc, num_mods = 0;
1021 bool ret;
1022 NTSTATUS status;
1024 ld = pdb_ads_ld(state);
1025 if (ld == NULL) {
1026 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1029 filter = talloc_asprintf(talloc_tos(),
1030 "(&(objectsid=%s)(objectclass=group))",
1031 sid_string_talloc(talloc_tos(), &map->sid));
1032 if (filter == NULL) {
1033 return NT_STATUS_NO_MEMORY;
1036 existing_map = talloc_zero(talloc_tos(), GROUP_MAP);
1037 if (!existing_map) {
1038 return NT_STATUS_NO_MEMORY;
1041 status = pdb_ads_getgrfilter(m, existing_map, filter,
1042 talloc_tos(), &existing);
1043 TALLOC_FREE(existing_map);
1044 TALLOC_FREE(filter);
1046 if (!tldap_entry_dn(existing, &dn)) {
1047 return NT_STATUS_LDAP(TLDAP_DECODING_ERROR);
1050 ret = true;
1052 ret &= tldap_make_mod_fmt(
1053 existing, talloc_tos(), &mods, &num_mods, "description",
1054 "%s", map->comment);
1055 ret &= tldap_make_mod_fmt(
1056 existing, talloc_tos(), &mods, &num_mods, "samaccountname",
1057 "%s", map->nt_name);
1059 if (!ret) {
1060 return NT_STATUS_NO_MEMORY;
1063 if (num_mods == 0) {
1064 TALLOC_FREE(existing);
1065 return NT_STATUS_OK;
1068 rc = tldap_modify(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
1069 if (rc != TLDAP_SUCCESS) {
1070 DEBUG(10, ("ldap_modify for %s failed: %s\n", dn,
1071 tldap_errstr(talloc_tos(), ld, rc)));
1072 TALLOC_FREE(existing);
1073 return NT_STATUS_LDAP(rc);
1075 TALLOC_FREE(existing);
1076 return NT_STATUS_OK;
1079 static NTSTATUS pdb_ads_delete_group_mapping_entry(struct pdb_methods *m,
1080 struct dom_sid sid)
1082 return NT_STATUS_NOT_IMPLEMENTED;
1085 static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m,
1086 const struct dom_sid *sid,
1087 enum lsa_SidType sid_name_use,
1088 GROUP_MAP ***pp_rmap,
1089 size_t *p_num_entries,
1090 bool unix_only)
1092 return NT_STATUS_NOT_IMPLEMENTED;
1095 static NTSTATUS pdb_ads_enum_group_members(struct pdb_methods *m,
1096 TALLOC_CTX *mem_ctx,
1097 const struct dom_sid *group,
1098 uint32 **pmembers,
1099 size_t *pnum_members)
1101 struct pdb_ads_state *state = talloc_get_type_abort(
1102 m->private_data, struct pdb_ads_state);
1103 const char *attrs[1] = { "member" };
1104 char *sidstr;
1105 struct tldap_message **msg;
1106 int i, rc, num_members;
1107 DATA_BLOB *blobs;
1108 uint32_t *members;
1110 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), group);
1111 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1113 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1114 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1115 &msg, "(objectsid=%s)", sidstr);
1116 TALLOC_FREE(sidstr);
1117 if (rc != TLDAP_SUCCESS) {
1118 DEBUG(10, ("ldap_search failed %s\n",
1119 tldap_errstr(talloc_tos(), state->ld, rc)));
1120 return NT_STATUS_LDAP(rc);
1122 switch talloc_array_length(msg) {
1123 case 0:
1124 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1125 break;
1126 case 1:
1127 break;
1128 default:
1129 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1130 break;
1133 if (!tldap_entry_values(msg[0], "member", &blobs, &num_members)) {
1134 *pmembers = NULL;
1135 *pnum_members = 0;
1136 return NT_STATUS_OK;
1139 members = talloc_array(mem_ctx, uint32_t, num_members);
1140 if (members == NULL) {
1141 return NT_STATUS_NO_MEMORY;
1144 for (i=0; i<num_members; i++) {
1145 struct dom_sid sid;
1146 if (!pdb_ads_dnblob2sid(state, &blobs[i], &sid)
1147 || !sid_peek_rid(&sid, &members[i])) {
1148 TALLOC_FREE(members);
1149 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1153 *pmembers = members;
1154 *pnum_members = num_members;
1155 return NT_STATUS_OK;
1158 static NTSTATUS pdb_ads_enum_group_memberships(struct pdb_methods *m,
1159 TALLOC_CTX *mem_ctx,
1160 struct samu *user,
1161 struct dom_sid **pp_sids,
1162 gid_t **pp_gids,
1163 uint32_t *p_num_groups)
1165 struct pdb_ads_state *state = talloc_get_type_abort(
1166 m->private_data, struct pdb_ads_state);
1167 struct pdb_ads_samu_private *priv;
1168 const char *attrs[1] = { "objectSid" };
1169 struct tldap_message **groups;
1170 int i, rc, count;
1171 size_t num_groups;
1172 struct dom_sid *group_sids;
1173 gid_t *gids;
1175 priv = pdb_ads_get_samu_private(m, user);
1176 if (priv != NULL) {
1177 rc = pdb_ads_search_fmt(
1178 state, state->domaindn, TLDAP_SCOPE_SUB,
1179 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &groups,
1180 "(&(member=%s)(grouptype=%d)(objectclass=group))",
1181 priv->dn, GTYPE_SECURITY_GLOBAL_GROUP);
1182 if (rc != TLDAP_SUCCESS) {
1183 DEBUG(10, ("ldap_search failed %s\n",
1184 tldap_errstr(talloc_tos(), state->ld, rc)));
1185 return NT_STATUS_LDAP(rc);
1187 count = talloc_array_length(groups);
1188 } else {
1190 * This happens for artificial samu users
1192 DEBUG(10, ("Could not get pdb_ads_samu_private\n"));
1193 count = 0;
1196 group_sids = talloc_array(mem_ctx, struct dom_sid, count+1);
1197 if (group_sids == NULL) {
1198 return NT_STATUS_NO_MEMORY;
1200 gids = talloc_array(mem_ctx, gid_t, count+1);
1201 if (gids == NULL) {
1202 TALLOC_FREE(group_sids);
1203 return NT_STATUS_NO_MEMORY;
1206 sid_copy(&group_sids[0], pdb_get_group_sid(user));
1207 if (!sid_to_gid(&group_sids[0], &gids[0])) {
1208 TALLOC_FREE(gids);
1209 TALLOC_FREE(group_sids);
1210 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1212 num_groups = 1;
1214 for (i=0; i<count; i++) {
1215 if (!tldap_pull_binsid(groups[i], "objectSid",
1216 &group_sids[num_groups])) {
1217 continue;
1219 gids[num_groups] = pdb_ads_sid2gid(&group_sids[num_groups]);
1221 num_groups += 1;
1222 if (num_groups == count) {
1223 break;
1227 *pp_sids = group_sids;
1228 *pp_gids = gids;
1229 *p_num_groups = num_groups;
1230 return NT_STATUS_OK;
1233 static NTSTATUS pdb_ads_set_unix_primary_group(struct pdb_methods *m,
1234 TALLOC_CTX *mem_ctx,
1235 struct samu *user)
1237 return NT_STATUS_NOT_IMPLEMENTED;
1240 static NTSTATUS pdb_ads_mod_groupmem(struct pdb_methods *m,
1241 TALLOC_CTX *mem_ctx,
1242 uint32 grouprid, uint32 memberrid,
1243 int mod_op)
1245 struct pdb_ads_state *state = talloc_get_type_abort(
1246 m->private_data, struct pdb_ads_state);
1247 TALLOC_CTX *frame = talloc_stackframe();
1248 struct tldap_context *ld;
1249 struct dom_sid groupsid, membersid;
1250 char *groupdn, *memberdn;
1251 struct tldap_mod *mods;
1252 int num_mods;
1253 int rc;
1254 NTSTATUS status;
1256 ld = pdb_ads_ld(state);
1257 if (ld == NULL) {
1258 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1261 sid_compose(&groupsid, &state->domainsid, grouprid);
1262 sid_compose(&membersid, &state->domainsid, memberrid);
1264 status = pdb_ads_sid2dn(state, &groupsid, talloc_tos(), &groupdn);
1265 if (!NT_STATUS_IS_OK(status)) {
1266 TALLOC_FREE(frame);
1267 return NT_STATUS_NO_SUCH_GROUP;
1269 status = pdb_ads_sid2dn(state, &membersid, talloc_tos(), &memberdn);
1270 if (!NT_STATUS_IS_OK(status)) {
1271 TALLOC_FREE(frame);
1272 return NT_STATUS_NO_SUCH_USER;
1275 mods = NULL;
1276 num_mods = 0;
1278 if (!tldap_add_mod_str(talloc_tos(), &mods, &num_mods, mod_op,
1279 "member", memberdn)) {
1280 TALLOC_FREE(frame);
1281 return NT_STATUS_NO_MEMORY;
1284 rc = tldap_modify(ld, groupdn, mods, num_mods, NULL, 0, NULL, 0);
1285 TALLOC_FREE(frame);
1286 if (rc != TLDAP_SUCCESS) {
1287 DEBUG(10, ("ldap_modify failed: %s\n",
1288 tldap_errstr(talloc_tos(), state->ld, rc)));
1289 if ((mod_op == TLDAP_MOD_ADD) &&
1290 (rc == TLDAP_ALREADY_EXISTS)) {
1291 return NT_STATUS_MEMBER_IN_GROUP;
1293 if ((mod_op == TLDAP_MOD_DELETE) &&
1294 (rc == TLDAP_UNWILLING_TO_PERFORM)) {
1295 return NT_STATUS_MEMBER_NOT_IN_GROUP;
1297 return NT_STATUS_LDAP(rc);
1300 return NT_STATUS_OK;
1303 static NTSTATUS pdb_ads_add_groupmem(struct pdb_methods *m,
1304 TALLOC_CTX *mem_ctx,
1305 uint32 group_rid, uint32 member_rid)
1307 return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1308 TLDAP_MOD_ADD);
1311 static NTSTATUS pdb_ads_del_groupmem(struct pdb_methods *m,
1312 TALLOC_CTX *mem_ctx,
1313 uint32 group_rid, uint32 member_rid)
1315 return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1316 TLDAP_MOD_DELETE);
1319 static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m,
1320 const char *name, uint32 *rid)
1322 TALLOC_CTX *frame = talloc_stackframe();
1323 struct pdb_ads_state *state = talloc_get_type_abort(
1324 m->private_data, struct pdb_ads_state);
1325 struct tldap_context *ld;
1326 const char *attrs[1] = { "objectSid" };
1327 int num_mods = 0;
1328 struct tldap_mod *mods = NULL;
1329 struct tldap_message **alias;
1330 struct dom_sid sid;
1331 char *dn;
1332 int rc;
1333 bool ok = true;
1335 ld = pdb_ads_ld(state);
1336 if (ld == NULL) {
1337 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1340 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
1341 state->domaindn);
1342 if (dn == NULL) {
1343 TALLOC_FREE(frame);
1344 return NT_STATUS_NO_MEMORY;
1347 ok &= tldap_make_mod_fmt(
1348 NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
1349 name);
1350 ok &= tldap_make_mod_fmt(
1351 NULL, talloc_tos(), &mods, &num_mods, "objectClass", "group");
1352 ok &= tldap_make_mod_fmt(
1353 NULL, talloc_tos(), &mods, &num_mods, "groupType",
1354 "%d", (int)GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1356 if (!ok) {
1357 TALLOC_FREE(frame);
1358 return NT_STATUS_NO_MEMORY;
1361 rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
1362 if (rc != TLDAP_SUCCESS) {
1363 DEBUG(10, ("ldap_add failed %s\n",
1364 tldap_errstr(talloc_tos(), state->ld, rc)));
1365 TALLOC_FREE(frame);
1366 return NT_STATUS_LDAP(rc);
1369 rc = pdb_ads_search_fmt(
1370 state, state->domaindn, TLDAP_SCOPE_SUB,
1371 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
1372 "(&(objectclass=group)(samaccountname=%s))", name);
1373 if (rc != TLDAP_SUCCESS) {
1374 DEBUG(10, ("Could not find just created alias %s: %s\n",
1375 name, tldap_errstr(talloc_tos(), state->ld, rc)));
1376 TALLOC_FREE(frame);
1377 return NT_STATUS_LDAP(rc);
1380 if (talloc_array_length(alias) != 1) {
1381 DEBUG(10, ("Got %d alias, expected one\n",
1382 (int)talloc_array_length(alias)));
1383 TALLOC_FREE(frame);
1384 return NT_STATUS_LDAP(rc);
1387 if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
1388 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
1389 name));
1390 TALLOC_FREE(frame);
1391 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1394 sid_peek_rid(&sid, rid);
1395 TALLOC_FREE(frame);
1396 return NT_STATUS_OK;
1399 static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m,
1400 const struct dom_sid *sid)
1402 struct pdb_ads_state *state = talloc_get_type_abort(
1403 m->private_data, struct pdb_ads_state);
1404 struct tldap_context *ld;
1405 struct tldap_message **alias;
1406 char *sidstr, *dn = NULL;
1407 int rc;
1409 ld = pdb_ads_ld(state);
1410 if (ld == NULL) {
1411 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1414 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
1415 if (sidstr == NULL) {
1416 return NT_STATUS_NO_MEMORY;
1419 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1420 NULL, 0, 0, talloc_tos(), &alias,
1421 "(&(objectSid=%s)(objectclass=group)"
1422 "(|(grouptype=%d)(grouptype=%d)))",
1423 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1424 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1425 TALLOC_FREE(sidstr);
1426 if (rc != TLDAP_SUCCESS) {
1427 DEBUG(10, ("ldap_search failed: %s\n",
1428 tldap_errstr(talloc_tos(), state->ld, rc)));
1429 return NT_STATUS_LDAP(rc);
1431 if (talloc_array_length(alias) != 1) {
1432 DEBUG(10, ("Expected 1 alias, got %d\n",
1433 (int)talloc_array_length(alias)));
1434 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1436 if (!tldap_entry_dn(alias[0], &dn)) {
1437 DEBUG(10, ("Could not get DN for alias %s\n",
1438 sid_string_dbg(sid)));
1439 return NT_STATUS_INTERNAL_ERROR;
1442 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
1443 if (rc != TLDAP_SUCCESS) {
1444 DEBUG(10, ("ldap_delete failed: %s\n",
1445 tldap_errstr(talloc_tos(), state->ld, rc)));
1446 return NT_STATUS_LDAP(rc);
1449 return NT_STATUS_OK;
1452 static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m,
1453 const struct dom_sid *sid,
1454 struct acct_info *info)
1456 struct pdb_ads_state *state = talloc_get_type_abort(
1457 m->private_data, struct pdb_ads_state);
1458 struct tldap_context *ld;
1459 const char *attrs[3] = { "objectSid", "description",
1460 "samAccountName" };
1461 struct tldap_message **msg;
1462 char *sidstr, *dn;
1463 int rc;
1464 struct tldap_mod *mods;
1465 int num_mods;
1466 bool ok;
1468 ld = pdb_ads_ld(state);
1469 if (ld == NULL) {
1470 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1473 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
1474 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1476 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1477 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1478 &msg, "(&(objectSid=%s)(objectclass=group)"
1479 "(|(grouptype=%d)(grouptype=%d)))",
1480 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1481 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1482 TALLOC_FREE(sidstr);
1483 if (rc != TLDAP_SUCCESS) {
1484 DEBUG(10, ("ldap_search failed %s\n",
1485 tldap_errstr(talloc_tos(), state->ld, rc)));
1486 return NT_STATUS_LDAP(rc);
1488 switch talloc_array_length(msg) {
1489 case 0:
1490 return NT_STATUS_NO_SUCH_ALIAS;
1491 case 1:
1492 break;
1493 default:
1494 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1497 if (!tldap_entry_dn(msg[0], &dn)) {
1498 TALLOC_FREE(msg);
1499 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1502 mods = NULL;
1503 num_mods = 0;
1504 ok = true;
1506 ok &= tldap_make_mod_fmt(
1507 msg[0], msg, &mods, &num_mods, "description",
1508 "%s", info->acct_desc);
1509 ok &= tldap_make_mod_fmt(
1510 msg[0], msg, &mods, &num_mods, "samAccountName",
1511 "%s", info->acct_name);
1512 if (!ok) {
1513 TALLOC_FREE(msg);
1514 return NT_STATUS_NO_MEMORY;
1516 if (num_mods == 0) {
1517 /* no change */
1518 TALLOC_FREE(msg);
1519 return NT_STATUS_OK;
1522 rc = tldap_modify(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
1523 TALLOC_FREE(msg);
1524 if (rc != TLDAP_SUCCESS) {
1525 DEBUG(10, ("ldap_modify failed: %s\n",
1526 tldap_errstr(talloc_tos(), state->ld, rc)));
1527 return NT_STATUS_LDAP(rc);
1529 return NT_STATUS_OK;
1532 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
1533 const struct dom_sid *sid,
1534 TALLOC_CTX *mem_ctx, char **pdn)
1536 struct tldap_message **msg;
1537 char *sidstr, *dn;
1538 int rc;
1540 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
1541 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1543 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1544 NULL, 0, 0, talloc_tos(), &msg,
1545 "(objectsid=%s)", sidstr);
1546 TALLOC_FREE(sidstr);
1547 if (rc != TLDAP_SUCCESS) {
1548 DEBUG(10, ("ldap_search failed %s\n",
1549 tldap_errstr(talloc_tos(), state->ld, rc)));
1550 return NT_STATUS_LDAP(rc);
1553 switch talloc_array_length(msg) {
1554 case 0:
1555 return NT_STATUS_NOT_FOUND;
1556 case 1:
1557 break;
1558 default:
1559 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1562 if (!tldap_entry_dn(msg[0], &dn)) {
1563 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1566 dn = talloc_strdup(mem_ctx, dn);
1567 if (dn == NULL) {
1568 return NT_STATUS_NO_MEMORY;
1570 TALLOC_FREE(msg);
1572 *pdn = dn;
1573 return NT_STATUS_OK;
1576 static NTSTATUS pdb_ads_mod_aliasmem(struct pdb_methods *m,
1577 const struct dom_sid *alias,
1578 const struct dom_sid *member,
1579 int mod_op)
1581 struct pdb_ads_state *state = talloc_get_type_abort(
1582 m->private_data, struct pdb_ads_state);
1583 struct tldap_context *ld;
1584 TALLOC_CTX *frame = talloc_stackframe();
1585 struct tldap_mod *mods;
1586 int num_mods;
1587 int rc;
1588 char *aliasdn, *memberdn;
1589 NTSTATUS status;
1591 ld = pdb_ads_ld(state);
1592 if (ld == NULL) {
1593 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1596 status = pdb_ads_sid2dn(state, alias, talloc_tos(), &aliasdn);
1597 if (!NT_STATUS_IS_OK(status)) {
1598 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1599 sid_string_dbg(alias), nt_errstr(status)));
1600 TALLOC_FREE(frame);
1601 return NT_STATUS_NO_SUCH_ALIAS;
1603 status = pdb_ads_sid2dn(state, member, talloc_tos(), &memberdn);
1604 if (!NT_STATUS_IS_OK(status)) {
1605 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1606 sid_string_dbg(member), nt_errstr(status)));
1607 TALLOC_FREE(frame);
1608 return status;
1611 mods = NULL;
1612 num_mods = 0;
1614 if (!tldap_add_mod_str(talloc_tos(), &mods, &num_mods, mod_op,
1615 "member", memberdn)) {
1616 TALLOC_FREE(frame);
1617 return NT_STATUS_NO_MEMORY;
1620 rc = tldap_modify(ld, aliasdn, mods, num_mods, NULL, 0, NULL, 0);
1621 TALLOC_FREE(frame);
1622 if (rc != TLDAP_SUCCESS) {
1623 DEBUG(10, ("ldap_modify failed: %s\n",
1624 tldap_errstr(talloc_tos(), state->ld, rc)));
1625 if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) {
1626 return NT_STATUS_MEMBER_IN_ALIAS;
1628 if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
1629 return NT_STATUS_MEMBER_NOT_IN_ALIAS;
1631 return NT_STATUS_LDAP(rc);
1634 return NT_STATUS_OK;
1637 static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
1638 const struct dom_sid *alias,
1639 const struct dom_sid *member)
1641 return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_ADD);
1644 static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
1645 const struct dom_sid *alias,
1646 const struct dom_sid *member)
1648 return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_DELETE);
1651 static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
1652 struct dom_sid *psid)
1654 const char *attrs[1] = { "objectSid" };
1655 struct tldap_message **msg;
1656 char *dn;
1657 size_t len;
1658 int rc;
1659 bool ret;
1661 if (!convert_string_talloc(talloc_tos(), CH_UTF8, CH_UNIX,
1662 dnblob->data, dnblob->length, &dn, &len)) {
1663 return false;
1665 rc = pdb_ads_search_fmt(state, dn, TLDAP_SCOPE_BASE,
1666 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1667 &msg, "(objectclass=*)");
1668 TALLOC_FREE(dn);
1669 if (talloc_array_length(msg) != 1) {
1670 DEBUG(10, ("Got %d objects, expected one\n",
1671 (int)talloc_array_length(msg)));
1672 TALLOC_FREE(msg);
1673 return false;
1676 ret = tldap_pull_binsid(msg[0], "objectSid", psid);
1677 TALLOC_FREE(msg);
1678 return ret;
1681 static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
1682 const struct dom_sid *alias,
1683 TALLOC_CTX *mem_ctx,
1684 struct dom_sid **pmembers,
1685 size_t *pnum_members)
1687 struct pdb_ads_state *state = talloc_get_type_abort(
1688 m->private_data, struct pdb_ads_state);
1689 const char *attrs[1] = { "member" };
1690 char *sidstr;
1691 struct tldap_message **msg;
1692 int i, rc, num_members;
1693 DATA_BLOB *blobs;
1694 struct dom_sid *members;
1696 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), alias);
1697 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1699 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1700 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1701 &msg, "(objectsid=%s)", sidstr);
1702 TALLOC_FREE(sidstr);
1703 if (rc != TLDAP_SUCCESS) {
1704 DEBUG(10, ("ldap_search failed %s\n",
1705 tldap_errstr(talloc_tos(), state->ld, rc)));
1706 return NT_STATUS_LDAP(rc);
1708 switch talloc_array_length(msg) {
1709 case 0:
1710 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1711 break;
1712 case 1:
1713 break;
1714 default:
1715 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1716 break;
1719 if (!tldap_entry_values(msg[0], "member", &blobs, &num_members)) {
1720 *pmembers = NULL;
1721 *pnum_members = 0;
1722 return NT_STATUS_OK;
1725 members = talloc_array(mem_ctx, struct dom_sid, num_members);
1726 if (members == NULL) {
1727 return NT_STATUS_NO_MEMORY;
1730 for (i=0; i<num_members; i++) {
1731 if (!pdb_ads_dnblob2sid(state, &blobs[i], &members[i])) {
1732 TALLOC_FREE(members);
1733 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1737 *pmembers = members;
1738 *pnum_members = num_members;
1739 return NT_STATUS_OK;
1742 static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,
1743 TALLOC_CTX *mem_ctx,
1744 const struct dom_sid *domain_sid,
1745 const struct dom_sid *members,
1746 size_t num_members,
1747 uint32_t **palias_rids,
1748 size_t *pnum_alias_rids)
1750 struct pdb_ads_state *state = talloc_get_type_abort(
1751 m->private_data, struct pdb_ads_state);
1752 const char *attrs[1] = { "objectSid" };
1753 struct tldap_message **msg = NULL;
1754 uint32_t *alias_rids = NULL;
1755 size_t num_alias_rids = 0;
1756 int i, rc, count;
1757 bool got_members = false;
1758 char *filter;
1759 NTSTATUS status;
1762 * TODO: Get the filter right so that we only get the aliases from
1763 * either the SAM or BUILTIN
1766 filter = talloc_asprintf(talloc_tos(),
1767 "(&(|(grouptype=%d)(grouptype=%d))"
1768 "(objectclass=group)(|",
1769 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1770 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1771 if (filter == NULL) {
1772 return NT_STATUS_NO_MEMORY;
1775 for (i=0; i<num_members; i++) {
1776 char *dn;
1778 status = pdb_ads_sid2dn(state, &members[i], talloc_tos(), &dn);
1779 if (!NT_STATUS_IS_OK(status)) {
1780 DEBUG(10, ("pdb_ads_sid2dn failed for %s: %s\n",
1781 sid_string_dbg(&members[i]),
1782 nt_errstr(status)));
1783 continue;
1785 filter = talloc_asprintf_append_buffer(
1786 filter, "(member=%s)", dn);
1787 TALLOC_FREE(dn);
1788 if (filter == NULL) {
1789 return NT_STATUS_NO_MEMORY;
1791 got_members = true;
1794 if (!got_members) {
1795 goto done;
1798 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1799 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1800 &msg, "%s))", filter);
1801 TALLOC_FREE(filter);
1802 if (rc != TLDAP_SUCCESS) {
1803 DEBUG(10, ("tldap_search failed %s\n",
1804 tldap_errstr(talloc_tos(), state->ld, rc)));
1805 return NT_STATUS_LDAP(rc);
1808 count = talloc_array_length(msg);
1809 if (count == 0) {
1810 goto done;
1813 alias_rids = talloc_array(mem_ctx, uint32_t, count);
1814 if (alias_rids == NULL) {
1815 TALLOC_FREE(msg);
1816 return NT_STATUS_NO_MEMORY;
1819 for (i=0; i<count; i++) {
1820 struct dom_sid sid;
1822 if (!tldap_pull_binsid(msg[i], "objectSid", &sid)) {
1823 DEBUG(10, ("Could not pull SID for member %d\n", i));
1824 continue;
1826 if (sid_peek_check_rid(domain_sid, &sid,
1827 &alias_rids[num_alias_rids])) {
1828 num_alias_rids += 1;
1831 done:
1832 TALLOC_FREE(msg);
1833 *palias_rids = alias_rids;
1834 *pnum_alias_rids = 0;
1835 return NT_STATUS_OK;
1838 static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m,
1839 const struct dom_sid *domain_sid,
1840 int num_rids,
1841 uint32 *rids,
1842 const char **names,
1843 enum lsa_SidType *lsa_attrs)
1845 struct pdb_ads_state *state = talloc_get_type_abort(
1846 m->private_data, struct pdb_ads_state);
1847 const char *attrs[2] = { "sAMAccountType", "sAMAccountName" };
1848 int i, num_mapped;
1850 if (num_rids == 0) {
1851 return NT_STATUS_NONE_MAPPED;
1854 num_mapped = 0;
1856 for (i=0; i<num_rids; i++) {
1857 struct dom_sid sid;
1858 struct tldap_message **msg;
1859 char *sidstr;
1860 uint32_t attr;
1861 int rc;
1863 lsa_attrs[i] = SID_NAME_UNKNOWN;
1865 sid_compose(&sid, domain_sid, rids[i]);
1867 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), &sid);
1868 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1870 rc = pdb_ads_search_fmt(state, state->domaindn,
1871 TLDAP_SCOPE_SUB, attrs,
1872 ARRAY_SIZE(attrs), 0, talloc_tos(),
1873 &msg, "(objectsid=%s)", sidstr);
1874 TALLOC_FREE(sidstr);
1875 if (rc != TLDAP_SUCCESS) {
1876 DEBUG(10, ("ldap_search failed %s\n",
1877 tldap_errstr(talloc_tos(), state->ld, rc)));
1878 continue;
1881 switch talloc_array_length(msg) {
1882 case 0:
1883 DEBUG(10, ("rid %d not found\n", (int)rids[i]));
1884 continue;
1885 case 1:
1886 break;
1887 default:
1888 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1891 names[i] = tldap_talloc_single_attribute(
1892 msg[0], "samAccountName", talloc_tos());
1893 if (names[i] == NULL) {
1894 DEBUG(10, ("no samAccountName\n"));
1895 continue;
1897 if (!tldap_pull_uint32(msg[0], "samAccountType", &attr)) {
1898 DEBUG(10, ("no samAccountType"));
1899 continue;
1901 lsa_attrs[i] = ds_atype_map(attr);
1902 num_mapped += 1;
1905 if (num_mapped == 0) {
1906 return NT_STATUS_NONE_MAPPED;
1908 if (num_mapped < num_rids) {
1909 return STATUS_SOME_UNMAPPED;
1911 return NT_STATUS_OK;
1914 static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m,
1915 const struct dom_sid *domain_sid,
1916 int num_names,
1917 const char **pp_names,
1918 uint32 *rids,
1919 enum lsa_SidType *attrs)
1921 return NT_STATUS_NOT_IMPLEMENTED;
1924 static NTSTATUS pdb_ads_get_account_policy(struct pdb_methods *m,
1925 enum pdb_policy_type type,
1926 uint32_t *value)
1928 return account_policy_get(type, value)
1929 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1932 static NTSTATUS pdb_ads_set_account_policy(struct pdb_methods *m,
1933 enum pdb_policy_type type,
1934 uint32_t value)
1936 return account_policy_set(type, value)
1937 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1940 static NTSTATUS pdb_ads_get_seq_num(struct pdb_methods *m,
1941 time_t *seq_num)
1943 return NT_STATUS_NOT_IMPLEMENTED;
1946 struct pdb_ads_search_state {
1947 uint32_t acct_flags;
1948 struct samr_displayentry *entries;
1949 uint32_t num_entries;
1950 ssize_t array_size;
1951 uint32_t current;
1954 static bool pdb_ads_next_entry(struct pdb_search *search,
1955 struct samr_displayentry *entry)
1957 struct pdb_ads_search_state *state = talloc_get_type_abort(
1958 search->private_data, struct pdb_ads_search_state);
1960 if (state->current == state->num_entries) {
1961 return false;
1964 entry->idx = state->entries[state->current].idx;
1965 entry->rid = state->entries[state->current].rid;
1966 entry->acct_flags = state->entries[state->current].acct_flags;
1968 entry->account_name = talloc_strdup(
1969 search, state->entries[state->current].account_name);
1970 entry->fullname = talloc_strdup(
1971 search, state->entries[state->current].fullname);
1972 entry->description = talloc_strdup(
1973 search, state->entries[state->current].description);
1975 if ((entry->account_name == NULL) || (entry->fullname == NULL)
1976 || (entry->description == NULL)) {
1977 DEBUG(0, ("talloc_strdup failed\n"));
1978 return false;
1981 state->current += 1;
1982 return true;
1985 static void pdb_ads_search_end(struct pdb_search *search)
1987 struct pdb_ads_search_state *state = talloc_get_type_abort(
1988 search->private_data, struct pdb_ads_search_state);
1989 TALLOC_FREE(state);
1992 static bool pdb_ads_search_filter(struct pdb_methods *m,
1993 struct pdb_search *search,
1994 const char *filter,
1995 uint32_t acct_flags,
1996 struct pdb_ads_search_state **pstate)
1998 struct pdb_ads_state *state = talloc_get_type_abort(
1999 m->private_data, struct pdb_ads_state);
2000 struct pdb_ads_search_state *sstate;
2001 const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
2002 "userAccountControl", "description" };
2003 struct tldap_message **users;
2004 int i, rc, num_users;
2006 sstate = talloc_zero(search, struct pdb_ads_search_state);
2007 if (sstate == NULL) {
2008 return false;
2010 sstate->acct_flags = acct_flags;
2012 rc = pdb_ads_search_fmt(
2013 state, state->domaindn, TLDAP_SCOPE_SUB,
2014 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &users,
2015 "%s", filter);
2016 if (rc != TLDAP_SUCCESS) {
2017 DEBUG(10, ("ldap_search_ext_s failed: %s\n",
2018 tldap_errstr(talloc_tos(), state->ld, rc)));
2019 return false;
2022 num_users = talloc_array_length(users);
2024 sstate->entries = talloc_array(sstate, struct samr_displayentry,
2025 num_users);
2026 if (sstate->entries == NULL) {
2027 DEBUG(10, ("talloc failed\n"));
2028 return false;
2031 sstate->num_entries = 0;
2033 for (i=0; i<num_users; i++) {
2034 struct samr_displayentry *e;
2035 struct dom_sid sid;
2036 uint32_t ctrl;
2038 e = &sstate->entries[sstate->num_entries];
2040 e->idx = sstate->num_entries;
2041 if (!tldap_pull_binsid(users[i], "objectSid", &sid)) {
2042 DEBUG(10, ("Could not pull sid\n"));
2043 continue;
2045 sid_peek_rid(&sid, &e->rid);
2047 if (tldap_pull_uint32(users[i], "userAccountControl", &ctrl)) {
2049 e->acct_flags = ds_uf2acb(ctrl);
2051 DEBUG(10, ("pdb_ads_search_filter: Found %x, "
2052 "filter %x\n", (int)e->acct_flags,
2053 (int)sstate->acct_flags));
2056 if ((sstate->acct_flags != 0) &&
2057 ((sstate->acct_flags & e->acct_flags) == 0)) {
2058 continue;
2061 if (e->acct_flags & (ACB_WSTRUST|ACB_SVRTRUST)) {
2062 e->acct_flags |= ACB_NORMAL;
2064 } else {
2065 e->acct_flags = ACB_NORMAL;
2068 if (e->rid == DOMAIN_RID_GUEST) {
2070 * Guest is specially crafted in s3. Make
2071 * QueryDisplayInfo match QueryUserInfo
2073 e->account_name = lp_guestaccount();
2074 e->fullname = lp_guestaccount();
2075 e->description = "";
2076 e->acct_flags = ACB_NORMAL;
2077 } else {
2078 e->account_name = tldap_talloc_single_attribute(
2079 users[i], "samAccountName", sstate->entries);
2080 e->fullname = tldap_talloc_single_attribute(
2081 users[i], "displayName", sstate->entries);
2082 e->description = tldap_talloc_single_attribute(
2083 users[i], "description", sstate->entries);
2085 if (e->account_name == NULL) {
2086 return false;
2088 if (e->fullname == NULL) {
2089 e->fullname = "";
2091 if (e->description == NULL) {
2092 e->description = "";
2095 sstate->num_entries += 1;
2096 if (sstate->num_entries >= num_users) {
2097 break;
2101 search->private_data = sstate;
2102 search->next_entry = pdb_ads_next_entry;
2103 search->search_end = pdb_ads_search_end;
2104 *pstate = sstate;
2105 return true;
2108 static bool pdb_ads_search_users(struct pdb_methods *m,
2109 struct pdb_search *search,
2110 uint32 acct_flags)
2112 struct pdb_ads_search_state *sstate;
2113 char *filter;
2114 bool ret;
2116 DEBUG(10, ("pdb_ads_search_users got flags %x\n", acct_flags));
2118 if (acct_flags & ACB_NORMAL) {
2119 filter = talloc_asprintf(
2120 talloc_tos(),
2121 "(&(objectclass=user)(sAMAccountType=%d))",
2122 ATYPE_NORMAL_ACCOUNT);
2123 } else if (acct_flags & ACB_WSTRUST) {
2124 filter = talloc_asprintf(
2125 talloc_tos(),
2126 "(&(objectclass=user)(sAMAccountType=%d))",
2127 ATYPE_WORKSTATION_TRUST);
2128 } else {
2129 filter = talloc_strdup(talloc_tos(), "(objectclass=user)");
2131 if (filter == NULL) {
2132 return false;
2135 ret = pdb_ads_search_filter(m, search, filter, acct_flags, &sstate);
2136 TALLOC_FREE(filter);
2137 if (!ret) {
2138 return false;
2140 return true;
2143 static bool pdb_ads_search_groups(struct pdb_methods *m,
2144 struct pdb_search *search)
2146 struct pdb_ads_search_state *sstate;
2147 char *filter;
2148 bool ret;
2150 filter = talloc_asprintf(talloc_tos(),
2151 "(&(grouptype=%d)(objectclass=group))",
2152 GTYPE_SECURITY_GLOBAL_GROUP);
2153 if (filter == NULL) {
2154 return false;
2156 ret = pdb_ads_search_filter(m, search, filter, 0, &sstate);
2157 TALLOC_FREE(filter);
2158 if (!ret) {
2159 return false;
2161 return true;
2164 static bool pdb_ads_search_aliases(struct pdb_methods *m,
2165 struct pdb_search *search,
2166 const struct dom_sid *sid)
2168 struct pdb_ads_search_state *sstate;
2169 char *filter;
2170 bool ret;
2172 filter = talloc_asprintf(
2173 talloc_tos(), "(&(grouptype=%d)(objectclass=group))",
2174 sid_check_is_builtin(sid)
2175 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2176 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2178 if (filter == NULL) {
2179 return false;
2181 ret = pdb_ads_search_filter(m, search, filter, 0, &sstate);
2182 TALLOC_FREE(filter);
2183 if (!ret) {
2184 return false;
2186 return true;
2189 static bool pdb_ads_uid_to_sid(struct pdb_methods *m, uid_t uid,
2190 struct dom_sid *sid)
2192 struct pdb_ads_state *state = talloc_get_type_abort(
2193 m->private_data, struct pdb_ads_state);
2194 sid_compose(sid, &state->domainsid, uid);
2195 return true;
2198 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
2199 struct dom_sid *sid)
2201 struct pdb_ads_state *state = talloc_get_type_abort(
2202 m->private_data, struct pdb_ads_state);
2203 sid_compose(sid, &state->domainsid, gid);
2204 return true;
2207 static bool pdb_ads_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2208 struct unixid *id)
2210 struct pdb_ads_state *state = talloc_get_type_abort(
2211 m->private_data, struct pdb_ads_state);
2212 const char *attrs[4] = { "objectClass", "samAccountType",
2213 "uidNumber", "gidNumber" };
2214 struct tldap_message **msg;
2215 char *sidstr, *base;
2216 uint32_t atype;
2217 int rc;
2218 bool ret = false;
2220 id->id = -1;
2221 id->type = ID_TYPE_NOT_SPECIFIED;
2223 sidstr = sid_binstring_hex(sid);
2224 if (sidstr == NULL) {
2225 return false;
2227 base = talloc_asprintf(talloc_tos(), "<SID=%s>", sidstr);
2228 SAFE_FREE(sidstr);
2230 rc = pdb_ads_search_fmt(
2231 state, base, TLDAP_SCOPE_BASE,
2232 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &msg,
2233 "(objectclass=*)");
2234 TALLOC_FREE(base);
2236 if (rc != TLDAP_SUCCESS) {
2237 DEBUG(10, ("pdb_ads_search_fmt failed: %s\n",
2238 tldap_errstr(talloc_tos(), state->ld, rc)));
2239 return false;
2241 if (talloc_array_length(msg) != 1) {
2242 DEBUG(10, ("Got %d objects, expected 1\n",
2243 (int)talloc_array_length(msg)));
2244 goto fail;
2246 if (!tldap_pull_uint32(msg[0], "samAccountType", &atype)) {
2247 DEBUG(10, ("samAccountType not found\n"));
2248 goto fail;
2250 if (atype == ATYPE_ACCOUNT) {
2251 uid_t uid;
2252 id->type = ID_TYPE_UID;
2253 if (!tldap_pull_uint32(msg[0], "uidNumber", &uid)) {
2254 DEBUG(10, ("Did not find uidNumber\n"));
2255 goto fail;
2257 id->id = uid;
2258 } else {
2259 gid_t gid;
2260 id->type = ID_TYPE_GID;
2261 if (!tldap_pull_uint32(msg[0], "gidNumber", &gid)) {
2262 DEBUG(10, ("Did not find gidNumber\n"));
2263 goto fail;
2265 id->id = gid;
2267 ret = true;
2268 fail:
2269 TALLOC_FREE(msg);
2270 return ret;
2273 static uint32_t pdb_ads_capabilities(struct pdb_methods *m)
2275 return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
2278 static bool pdb_ads_new_rid(struct pdb_methods *m, uint32 *rid)
2280 return false;
2283 static bool pdb_ads_get_trusteddom_pw(struct pdb_methods *m,
2284 const char *domain, char** pwd,
2285 struct dom_sid *sid,
2286 time_t *pass_last_set_time)
2288 return false;
2291 static bool pdb_ads_set_trusteddom_pw(struct pdb_methods *m,
2292 const char* domain, const char* pwd,
2293 const struct dom_sid *sid)
2295 return false;
2298 static bool pdb_ads_del_trusteddom_pw(struct pdb_methods *m,
2299 const char *domain)
2301 return false;
2304 static NTSTATUS pdb_ads_enum_trusteddoms(struct pdb_methods *m,
2305 TALLOC_CTX *mem_ctx,
2306 uint32 *num_domains,
2307 struct trustdom_info ***domains)
2309 *num_domains = 0;
2310 *domains = NULL;
2311 return NT_STATUS_OK;
2314 static void pdb_ads_init_methods(struct pdb_methods *m)
2316 m->name = "ads";
2317 m->get_domain_info = pdb_ads_get_domain_info;
2318 m->getsampwnam = pdb_ads_getsampwnam;
2319 m->getsampwsid = pdb_ads_getsampwsid;
2320 m->create_user = pdb_ads_create_user;
2321 m->delete_user = pdb_ads_delete_user;
2322 m->add_sam_account = pdb_ads_add_sam_account;
2323 m->update_sam_account = pdb_ads_update_sam_account;
2324 m->delete_sam_account = pdb_ads_delete_sam_account;
2325 m->rename_sam_account = pdb_ads_rename_sam_account;
2326 m->update_login_attempts = pdb_ads_update_login_attempts;
2327 m->getgrsid = pdb_ads_getgrsid;
2328 m->getgrgid = pdb_ads_getgrgid;
2329 m->getgrnam = pdb_ads_getgrnam;
2330 m->create_dom_group = pdb_ads_create_dom_group;
2331 m->delete_dom_group = pdb_ads_delete_dom_group;
2332 m->add_group_mapping_entry = pdb_ads_add_group_mapping_entry;
2333 m->update_group_mapping_entry = pdb_ads_update_group_mapping_entry;
2334 m->delete_group_mapping_entry = pdb_ads_delete_group_mapping_entry;
2335 m->enum_group_mapping = pdb_ads_enum_group_mapping;
2336 m->enum_group_members = pdb_ads_enum_group_members;
2337 m->enum_group_memberships = pdb_ads_enum_group_memberships;
2338 m->set_unix_primary_group = pdb_ads_set_unix_primary_group;
2339 m->add_groupmem = pdb_ads_add_groupmem;
2340 m->del_groupmem = pdb_ads_del_groupmem;
2341 m->create_alias = pdb_ads_create_alias;
2342 m->delete_alias = pdb_ads_delete_alias;
2343 m->get_aliasinfo = pdb_default_get_aliasinfo;
2344 m->set_aliasinfo = pdb_ads_set_aliasinfo;
2345 m->add_aliasmem = pdb_ads_add_aliasmem;
2346 m->del_aliasmem = pdb_ads_del_aliasmem;
2347 m->enum_aliasmem = pdb_ads_enum_aliasmem;
2348 m->enum_alias_memberships = pdb_ads_enum_alias_memberships;
2349 m->lookup_rids = pdb_ads_lookup_rids;
2350 m->lookup_names = pdb_ads_lookup_names;
2351 m->get_account_policy = pdb_ads_get_account_policy;
2352 m->set_account_policy = pdb_ads_set_account_policy;
2353 m->get_seq_num = pdb_ads_get_seq_num;
2354 m->search_users = pdb_ads_search_users;
2355 m->search_groups = pdb_ads_search_groups;
2356 m->search_aliases = pdb_ads_search_aliases;
2357 m->uid_to_sid = pdb_ads_uid_to_sid;
2358 m->gid_to_sid = pdb_ads_gid_to_sid;
2359 m->sid_to_id = pdb_ads_sid_to_id;
2360 m->capabilities = pdb_ads_capabilities;
2361 m->new_rid = pdb_ads_new_rid;
2362 m->get_trusteddom_pw = pdb_ads_get_trusteddom_pw;
2363 m->set_trusteddom_pw = pdb_ads_set_trusteddom_pw;
2364 m->del_trusteddom_pw = pdb_ads_del_trusteddom_pw;
2365 m->enum_trusteddoms = pdb_ads_enum_trusteddoms;
2368 static void free_private_data(void **vp)
2370 struct pdb_ads_state *state = talloc_get_type_abort(
2371 *vp, struct pdb_ads_state);
2373 TALLOC_FREE(state->ld);
2374 return;
2378 this is used to catch debug messages from events
2380 static void s3_tldap_debug(void *context, enum tldap_debug_level level,
2381 const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
2383 static void s3_tldap_debug(void *context, enum tldap_debug_level level,
2384 const char *fmt, va_list ap)
2386 int samba_level = -1;
2387 char *s = NULL;
2388 switch (level) {
2389 case TLDAP_DEBUG_FATAL:
2390 samba_level = 0;
2391 break;
2392 case TLDAP_DEBUG_ERROR:
2393 samba_level = 1;
2394 break;
2395 case TLDAP_DEBUG_WARNING:
2396 samba_level = 2;
2397 break;
2398 case TLDAP_DEBUG_TRACE:
2399 samba_level = 11;
2400 break;
2403 if (vasprintf(&s, fmt, ap) == -1) {
2404 return;
2406 DEBUG(samba_level, ("tldap: %s", s));
2407 free(s);
2410 static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state)
2412 NTSTATUS status;
2413 int fd;
2415 if (tldap_connection_ok(state->ld)) {
2416 return state->ld;
2418 TALLOC_FREE(state->ld);
2420 status = open_socket_out(
2421 (struct sockaddr_storage *)(void *)&state->socket_address,
2422 0, 0, &fd);
2423 if (!NT_STATUS_IS_OK(status)) {
2424 DEBUG(10, ("Could not connect to %s: %s\n",
2425 state->socket_address.sun_path, nt_errstr(status)));
2426 return NULL;
2429 set_blocking(fd, false);
2431 state->ld = tldap_context_create(state, fd);
2432 if (state->ld == NULL) {
2433 close(fd);
2434 return NULL;
2436 tldap_set_debug(state->ld, s3_tldap_debug, NULL);
2438 return state->ld;
2441 int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base,
2442 int scope, const char *attrs[], int num_attrs,
2443 int attrsonly,
2444 TALLOC_CTX *mem_ctx, struct tldap_message ***res,
2445 const char *fmt, ...)
2447 struct tldap_context *ld;
2448 va_list ap;
2449 int ret;
2451 ld = pdb_ads_ld(state);
2452 if (ld == NULL) {
2453 return TLDAP_SERVER_DOWN;
2456 va_start(ap, fmt);
2457 ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly,
2458 mem_ctx, res, fmt, ap);
2459 va_end(ap);
2461 if (ret != TLDAP_SERVER_DOWN) {
2462 return ret;
2465 /* retry once */
2466 ld = pdb_ads_ld(state);
2467 if (ld == NULL) {
2468 return TLDAP_SERVER_DOWN;
2471 va_start(ap, fmt);
2472 ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly,
2473 mem_ctx, res, fmt, ap);
2474 va_end(ap);
2475 return ret;
2478 static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state,
2479 const char *location)
2481 const char *domain_attrs[2] = { "objectSid", "objectGUID" };
2482 const char *ncname_attrs[1] = { "netbiosname" };
2483 struct tldap_context *ld;
2484 struct tldap_message *rootdse, **domain, **ncname;
2485 TALLOC_CTX *frame = talloc_stackframe();
2486 NTSTATUS status;
2487 int num_domains;
2488 int rc;
2490 ZERO_STRUCT(state->socket_address);
2491 state->socket_address.sun_family = AF_UNIX;
2492 strlcpy(state->socket_address.sun_path, location,
2493 sizeof(state->socket_address.sun_path));
2495 ld = pdb_ads_ld(state);
2496 if (ld == NULL) {
2497 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2498 goto done;
2501 rc = tldap_fetch_rootdse(ld);
2502 if (rc != TLDAP_SUCCESS) {
2503 DEBUG(10, ("Could not retrieve rootdse: %s\n",
2504 tldap_errstr(talloc_tos(), state->ld, rc)));
2505 status = NT_STATUS_LDAP(rc);
2506 goto done;
2508 rootdse = tldap_rootdse(state->ld);
2510 state->domaindn = tldap_talloc_single_attribute(
2511 rootdse, "defaultNamingContext", state);
2512 if (state->domaindn == NULL) {
2513 DEBUG(10, ("Could not get defaultNamingContext\n"));
2514 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2515 goto done;
2517 DEBUG(10, ("defaultNamingContext = %s\n", state->domaindn));
2519 state->configdn = tldap_talloc_single_attribute(
2520 rootdse, "configurationNamingContext", state);
2521 if (state->configdn == NULL) {
2522 DEBUG(10, ("Could not get configurationNamingContext\n"));
2523 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2524 goto done;
2526 DEBUG(10, ("configurationNamingContext = %s\n", state->configdn));
2529 * Figure out our domain's SID
2531 rc = pdb_ads_search_fmt(
2532 state, state->domaindn, TLDAP_SCOPE_BASE,
2533 domain_attrs, ARRAY_SIZE(domain_attrs), 0,
2534 talloc_tos(), &domain, "(objectclass=*)");
2535 if (rc != TLDAP_SUCCESS) {
2536 DEBUG(10, ("Could not retrieve domain: %s\n",
2537 tldap_errstr(talloc_tos(), state->ld, rc)));
2538 status = NT_STATUS_LDAP(rc);
2539 goto done;
2542 num_domains = talloc_array_length(domain);
2543 if (num_domains != 1) {
2544 DEBUG(10, ("Got %d domains, expected one\n", num_domains));
2545 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2546 goto done;
2548 if (!tldap_pull_binsid(domain[0], "objectSid", &state->domainsid)) {
2549 DEBUG(10, ("Could not retrieve domain SID\n"));
2550 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2551 goto done;
2553 if (!tldap_pull_guid(domain[0], "objectGUID", &state->domainguid)) {
2554 DEBUG(10, ("Could not retrieve domain GUID\n"));
2555 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2556 goto done;
2558 DEBUG(10, ("Domain SID: %s\n", sid_string_dbg(&state->domainsid)));
2561 * Figure out our domain's short name
2563 rc = pdb_ads_search_fmt(
2564 state, state->configdn, TLDAP_SCOPE_SUB,
2565 ncname_attrs, ARRAY_SIZE(ncname_attrs), 0,
2566 talloc_tos(), &ncname, "(ncname=%s)", state->domaindn);
2567 if (rc != TLDAP_SUCCESS) {
2568 DEBUG(10, ("Could not retrieve ncname: %s\n",
2569 tldap_errstr(talloc_tos(), state->ld, rc)));
2570 status = NT_STATUS_LDAP(rc);
2571 goto done;
2573 if (talloc_array_length(ncname) != 1) {
2574 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2575 goto done;
2578 state->netbiosname = tldap_talloc_single_attribute(
2579 ncname[0], "netbiosname", state);
2580 if (state->netbiosname == NULL) {
2581 DEBUG(10, ("Could not get netbiosname\n"));
2582 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2583 goto done;
2585 DEBUG(10, ("netbiosname: %s\n", state->netbiosname));
2587 if (!strequal(lp_workgroup(), state->netbiosname)) {
2588 DEBUG(1, ("ADS is different domain (%s) than ours (%s)\n",
2589 state->netbiosname, lp_workgroup()));
2590 status = NT_STATUS_NO_SUCH_DOMAIN;
2591 goto done;
2594 secrets_store_domain_sid(state->netbiosname, &state->domainsid);
2596 status = NT_STATUS_OK;
2597 done:
2598 TALLOC_FREE(frame);
2599 return status;
2602 static NTSTATUS pdb_ads_init_secrets(struct pdb_methods *m)
2604 #if _SAMBA_BUILD_ == 4
2605 struct pdb_domain_info *dom_info;
2606 bool ret;
2608 dom_info = pdb_ads_get_domain_info(m, m);
2609 if (!dom_info) {
2610 return NT_STATUS_UNSUCCESSFUL;
2613 secrets_clear_domain_protection(dom_info->name);
2614 ret = secrets_store_domain_sid(dom_info->name,
2615 &dom_info->sid);
2616 if (!ret) {
2617 goto done;
2619 ret = secrets_store_domain_guid(dom_info->name,
2620 &dom_info->guid);
2621 if (!ret) {
2622 goto done;
2624 ret = secrets_mark_domain_protected(dom_info->name);
2625 if (!ret) {
2626 goto done;
2629 done:
2630 TALLOC_FREE(dom_info);
2631 if (!ret) {
2632 return NT_STATUS_UNSUCCESSFUL;
2634 #endif
2635 return NT_STATUS_OK;
2638 static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method,
2639 const char *location)
2641 struct pdb_methods *m;
2642 struct pdb_ads_state *state;
2643 char *tmp = NULL;
2644 NTSTATUS status;
2646 m = talloc(NULL, struct pdb_methods);
2647 if (m == NULL) {
2648 return NT_STATUS_NO_MEMORY;
2650 state = talloc_zero(m, struct pdb_ads_state);
2651 if (state == NULL) {
2652 goto nomem;
2654 m->private_data = state;
2655 m->free_private_data = free_private_data;
2656 pdb_ads_init_methods(m);
2658 if (location == NULL) {
2659 tmp = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi",
2660 lp_private_dir());
2661 location = tmp;
2663 if (location == NULL) {
2664 goto nomem;
2667 status = pdb_ads_connect(state, location);
2668 if (!NT_STATUS_IS_OK(status)) {
2669 DEBUG(10, ("pdb_ads_connect failed: %s\n", nt_errstr(status)));
2670 goto fail;
2673 status = pdb_ads_init_secrets(m);
2674 if (!NT_STATUS_IS_OK(status)) {
2675 DEBUG(10, ("pdb_ads_init_secrets failed!\n"));
2676 goto fail;
2679 *pdb_method = m;
2680 return NT_STATUS_OK;
2681 nomem:
2682 status = NT_STATUS_NO_MEMORY;
2683 fail:
2684 TALLOC_FREE(m);
2685 return status;
2688 NTSTATUS pdb_ads_init(void);
2689 NTSTATUS pdb_ads_init(void)
2691 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "ads",
2692 pdb_init_ads);