WHATSNEW: Start release notes for 3.6.2.
[Samba.git] / source3 / passdb / pdb_ads.c
blob6a47bb34ca4655ff76087b359b6a9df8f5d9cc75
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, false);
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 fstrcpy(map->nt_name, str);
802 TALLOC_FREE(str);
804 str = tldap_talloc_single_attribute(group[0], "description",
805 talloc_tos());
806 if (str != NULL) {
807 fstrcpy(map->comment, str);
808 TALLOC_FREE(str);
809 } else {
810 map->comment[0] = '\0';
813 if (pmsg != NULL) {
814 *pmsg = talloc_move(mem_ctx, &group[0]);
816 TALLOC_FREE(group);
817 return NT_STATUS_OK;
820 static NTSTATUS pdb_ads_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
821 struct dom_sid sid)
823 char *filter;
824 NTSTATUS status;
826 filter = talloc_asprintf(talloc_tos(),
827 "(&(objectsid=%s)(objectclass=group))",
828 sid_string_talloc(talloc_tos(), &sid));
829 if (filter == NULL) {
830 return NT_STATUS_NO_MEMORY;
833 status = pdb_ads_getgrfilter(m, map, filter, NULL, NULL);
834 TALLOC_FREE(filter);
835 return status;
838 static NTSTATUS pdb_ads_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
839 gid_t gid)
841 struct dom_sid sid;
842 pdb_ads_gid_to_sid(m, gid, &sid);
843 return pdb_ads_getgrsid(m, map, sid);
846 static NTSTATUS pdb_ads_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
847 const char *name)
849 char *filter;
850 NTSTATUS status;
852 filter = talloc_asprintf(talloc_tos(),
853 "(&(samaccountname=%s)(objectclass=group))",
854 name);
855 if (filter == NULL) {
856 return NT_STATUS_NO_MEMORY;
859 status = pdb_ads_getgrfilter(m, map, filter, NULL, NULL);
860 TALLOC_FREE(filter);
861 return status;
864 static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m,
865 TALLOC_CTX *mem_ctx, const char *name,
866 uint32 *rid)
868 TALLOC_CTX *frame = talloc_stackframe();
869 struct pdb_ads_state *state = talloc_get_type_abort(
870 m->private_data, struct pdb_ads_state);
871 struct tldap_context *ld;
872 const char *attrs[1] = { "objectSid" };
873 int num_mods = 0;
874 struct tldap_mod *mods = NULL;
875 struct tldap_message **alias;
876 struct dom_sid sid;
877 char *dn;
878 int rc;
879 bool ok = true;
881 ld = pdb_ads_ld(state);
882 if (ld == NULL) {
883 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
886 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
887 state->domaindn);
888 if (dn == NULL) {
889 TALLOC_FREE(frame);
890 return NT_STATUS_NO_MEMORY;
893 ok &= tldap_make_mod_fmt(
894 NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
895 name);
896 ok &= tldap_make_mod_fmt(
897 NULL, talloc_tos(), &mods, &num_mods, "objectClass", "group");
898 ok &= tldap_make_mod_fmt(
899 NULL, talloc_tos(), &mods, &num_mods, "groupType",
900 "%d", (int)GTYPE_SECURITY_GLOBAL_GROUP);
902 if (!ok) {
903 TALLOC_FREE(frame);
904 return NT_STATUS_NO_MEMORY;
907 rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
908 if (rc != TLDAP_SUCCESS) {
909 DEBUG(10, ("ldap_add failed %s\n",
910 tldap_errstr(talloc_tos(), state->ld, rc)));
911 TALLOC_FREE(frame);
912 return NT_STATUS_LDAP(rc);
915 rc = pdb_ads_search_fmt(
916 state, state->domaindn, TLDAP_SCOPE_SUB,
917 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
918 "(&(objectclass=group)(samaccountname=%s))", name);
919 if (rc != TLDAP_SUCCESS) {
920 DEBUG(10, ("Could not find just created alias %s: %s\n",
921 name, tldap_errstr(talloc_tos(), state->ld, rc)));
922 TALLOC_FREE(frame);
923 return NT_STATUS_LDAP(rc);
926 if (talloc_array_length(alias) != 1) {
927 DEBUG(10, ("Got %d alias, expected one\n",
928 (int)talloc_array_length(alias)));
929 TALLOC_FREE(frame);
930 return NT_STATUS_LDAP(rc);
933 if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
934 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
935 name));
936 TALLOC_FREE(frame);
937 return NT_STATUS_INTERNAL_DB_CORRUPTION;
940 sid_peek_rid(&sid, rid);
941 TALLOC_FREE(frame);
942 return NT_STATUS_OK;
945 static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m,
946 TALLOC_CTX *mem_ctx, uint32 rid)
948 struct pdb_ads_state *state = talloc_get_type_abort(
949 m->private_data, struct pdb_ads_state);
950 struct tldap_context *ld;
951 struct dom_sid sid;
952 char *sidstr;
953 struct tldap_message **msg;
954 char *dn;
955 int rc;
957 sid_compose(&sid, &state->domainsid, rid);
959 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), &sid);
960 NT_STATUS_HAVE_NO_MEMORY(sidstr);
962 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
963 NULL, 0, 0, talloc_tos(), &msg,
964 ("(&(objectSid=%s)(objectClass=group))"),
965 sidstr);
966 TALLOC_FREE(sidstr);
967 if (rc != TLDAP_SUCCESS) {
968 DEBUG(10, ("ldap_search failed %s\n",
969 tldap_errstr(talloc_tos(), state->ld, rc)));
970 return NT_STATUS_LDAP(rc);
973 switch talloc_array_length(msg) {
974 case 0:
975 return NT_STATUS_NO_SUCH_GROUP;
976 case 1:
977 break;
978 default:
979 return NT_STATUS_INTERNAL_DB_CORRUPTION;
982 if (!tldap_entry_dn(msg[0], &dn)) {
983 TALLOC_FREE(msg);
984 return NT_STATUS_INTERNAL_DB_CORRUPTION;
987 ld = pdb_ads_ld(state);
988 if (ld == NULL) {
989 TALLOC_FREE(msg);
990 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
993 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
994 TALLOC_FREE(msg);
995 if (rc != TLDAP_SUCCESS) {
996 DEBUG(10, ("ldap_delete failed: %s\n",
997 tldap_errstr(talloc_tos(), state->ld, rc)));
998 return NT_STATUS_LDAP(rc);
1001 return NT_STATUS_OK;
1004 static NTSTATUS pdb_ads_add_group_mapping_entry(struct pdb_methods *m,
1005 GROUP_MAP *map)
1007 return NT_STATUS_NOT_IMPLEMENTED;
1010 static NTSTATUS pdb_ads_update_group_mapping_entry(struct pdb_methods *m,
1011 GROUP_MAP *map)
1013 struct pdb_ads_state *state = talloc_get_type_abort(
1014 m->private_data, struct pdb_ads_state);
1015 struct tldap_context *ld;
1016 struct tldap_mod *mods = NULL;
1017 char *filter;
1018 struct tldap_message *existing;
1019 char *dn;
1020 GROUP_MAP existing_map;
1021 int rc, num_mods = 0;
1022 bool ret;
1023 NTSTATUS status;
1025 ld = pdb_ads_ld(state);
1026 if (ld == NULL) {
1027 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1030 filter = talloc_asprintf(talloc_tos(),
1031 "(&(objectsid=%s)(objectclass=group))",
1032 sid_string_talloc(talloc_tos(), &map->sid));
1033 if (filter == NULL) {
1034 return NT_STATUS_NO_MEMORY;
1036 status = pdb_ads_getgrfilter(m, &existing_map, filter,
1037 talloc_tos(), &existing);
1038 TALLOC_FREE(filter);
1040 if (!tldap_entry_dn(existing, &dn)) {
1041 return NT_STATUS_LDAP(TLDAP_DECODING_ERROR);
1044 ret = true;
1046 ret &= tldap_make_mod_fmt(
1047 existing, talloc_tos(), &mods, &num_mods, "description",
1048 "%s", map->comment);
1049 ret &= tldap_make_mod_fmt(
1050 existing, talloc_tos(), &mods, &num_mods, "samaccountname",
1051 "%s", map->nt_name);
1053 if (!ret) {
1054 return NT_STATUS_NO_MEMORY;
1057 if (num_mods == 0) {
1058 TALLOC_FREE(existing);
1059 return NT_STATUS_OK;
1062 rc = tldap_modify(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
1063 if (rc != TLDAP_SUCCESS) {
1064 DEBUG(10, ("ldap_modify for %s failed: %s\n", dn,
1065 tldap_errstr(talloc_tos(), ld, rc)));
1066 TALLOC_FREE(existing);
1067 return NT_STATUS_LDAP(rc);
1069 TALLOC_FREE(existing);
1070 return NT_STATUS_OK;
1073 static NTSTATUS pdb_ads_delete_group_mapping_entry(struct pdb_methods *m,
1074 struct dom_sid sid)
1076 return NT_STATUS_NOT_IMPLEMENTED;
1079 static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m,
1080 const struct dom_sid *sid,
1081 enum lsa_SidType sid_name_use,
1082 GROUP_MAP **pp_rmap,
1083 size_t *p_num_entries,
1084 bool unix_only)
1086 return NT_STATUS_NOT_IMPLEMENTED;
1089 static NTSTATUS pdb_ads_enum_group_members(struct pdb_methods *m,
1090 TALLOC_CTX *mem_ctx,
1091 const struct dom_sid *group,
1092 uint32 **pmembers,
1093 size_t *pnum_members)
1095 struct pdb_ads_state *state = talloc_get_type_abort(
1096 m->private_data, struct pdb_ads_state);
1097 const char *attrs[1] = { "member" };
1098 char *sidstr;
1099 struct tldap_message **msg;
1100 int i, rc, num_members;
1101 DATA_BLOB *blobs;
1102 uint32_t *members;
1104 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), group);
1105 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1107 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1108 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1109 &msg, "(objectsid=%s)", sidstr);
1110 TALLOC_FREE(sidstr);
1111 if (rc != TLDAP_SUCCESS) {
1112 DEBUG(10, ("ldap_search failed %s\n",
1113 tldap_errstr(talloc_tos(), state->ld, rc)));
1114 return NT_STATUS_LDAP(rc);
1116 switch talloc_array_length(msg) {
1117 case 0:
1118 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1119 break;
1120 case 1:
1121 break;
1122 default:
1123 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1124 break;
1127 if (!tldap_entry_values(msg[0], "member", &blobs, &num_members)) {
1128 *pmembers = NULL;
1129 *pnum_members = 0;
1130 return NT_STATUS_OK;
1133 members = talloc_array(mem_ctx, uint32_t, num_members);
1134 if (members == NULL) {
1135 return NT_STATUS_NO_MEMORY;
1138 for (i=0; i<num_members; i++) {
1139 struct dom_sid sid;
1140 if (!pdb_ads_dnblob2sid(state, &blobs[i], &sid)
1141 || !sid_peek_rid(&sid, &members[i])) {
1142 TALLOC_FREE(members);
1143 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1147 *pmembers = members;
1148 *pnum_members = num_members;
1149 return NT_STATUS_OK;
1152 static NTSTATUS pdb_ads_enum_group_memberships(struct pdb_methods *m,
1153 TALLOC_CTX *mem_ctx,
1154 struct samu *user,
1155 struct dom_sid **pp_sids,
1156 gid_t **pp_gids,
1157 uint32_t *p_num_groups)
1159 struct pdb_ads_state *state = talloc_get_type_abort(
1160 m->private_data, struct pdb_ads_state);
1161 struct pdb_ads_samu_private *priv;
1162 const char *attrs[1] = { "objectSid" };
1163 struct tldap_message **groups;
1164 int i, rc, count;
1165 size_t num_groups;
1166 struct dom_sid *group_sids;
1167 gid_t *gids;
1169 priv = pdb_ads_get_samu_private(m, user);
1170 if (priv != NULL) {
1171 rc = pdb_ads_search_fmt(
1172 state, state->domaindn, TLDAP_SCOPE_SUB,
1173 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &groups,
1174 "(&(member=%s)(grouptype=%d)(objectclass=group))",
1175 priv->dn, GTYPE_SECURITY_GLOBAL_GROUP);
1176 if (rc != TLDAP_SUCCESS) {
1177 DEBUG(10, ("ldap_search failed %s\n",
1178 tldap_errstr(talloc_tos(), state->ld, rc)));
1179 return NT_STATUS_LDAP(rc);
1181 count = talloc_array_length(groups);
1182 } else {
1184 * This happens for artificial samu users
1186 DEBUG(10, ("Could not get pdb_ads_samu_private\n"));
1187 count = 0;
1190 group_sids = talloc_array(mem_ctx, struct dom_sid, count+1);
1191 if (group_sids == NULL) {
1192 return NT_STATUS_NO_MEMORY;
1194 gids = talloc_array(mem_ctx, gid_t, count+1);
1195 if (gids == NULL) {
1196 TALLOC_FREE(group_sids);
1197 return NT_STATUS_NO_MEMORY;
1200 sid_copy(&group_sids[0], pdb_get_group_sid(user));
1201 if (!sid_to_gid(&group_sids[0], &gids[0])) {
1202 TALLOC_FREE(gids);
1203 TALLOC_FREE(group_sids);
1204 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1206 num_groups = 1;
1208 for (i=0; i<count; i++) {
1209 if (!tldap_pull_binsid(groups[i], "objectSid",
1210 &group_sids[num_groups])) {
1211 continue;
1213 gids[num_groups] = pdb_ads_sid2gid(&group_sids[num_groups]);
1215 num_groups += 1;
1216 if (num_groups == count) {
1217 break;
1221 *pp_sids = group_sids;
1222 *pp_gids = gids;
1223 *p_num_groups = num_groups;
1224 return NT_STATUS_OK;
1227 static NTSTATUS pdb_ads_set_unix_primary_group(struct pdb_methods *m,
1228 TALLOC_CTX *mem_ctx,
1229 struct samu *user)
1231 return NT_STATUS_NOT_IMPLEMENTED;
1234 static NTSTATUS pdb_ads_mod_groupmem(struct pdb_methods *m,
1235 TALLOC_CTX *mem_ctx,
1236 uint32 grouprid, uint32 memberrid,
1237 int mod_op)
1239 struct pdb_ads_state *state = talloc_get_type_abort(
1240 m->private_data, struct pdb_ads_state);
1241 TALLOC_CTX *frame = talloc_stackframe();
1242 struct tldap_context *ld;
1243 struct dom_sid groupsid, membersid;
1244 char *groupdn, *memberdn;
1245 struct tldap_mod *mods;
1246 int num_mods;
1247 int rc;
1248 NTSTATUS status;
1250 ld = pdb_ads_ld(state);
1251 if (ld == NULL) {
1252 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1255 sid_compose(&groupsid, &state->domainsid, grouprid);
1256 sid_compose(&membersid, &state->domainsid, memberrid);
1258 status = pdb_ads_sid2dn(state, &groupsid, talloc_tos(), &groupdn);
1259 if (!NT_STATUS_IS_OK(status)) {
1260 TALLOC_FREE(frame);
1261 return NT_STATUS_NO_SUCH_GROUP;
1263 status = pdb_ads_sid2dn(state, &membersid, talloc_tos(), &memberdn);
1264 if (!NT_STATUS_IS_OK(status)) {
1265 TALLOC_FREE(frame);
1266 return NT_STATUS_NO_SUCH_USER;
1269 mods = NULL;
1270 num_mods = 0;
1272 if (!tldap_add_mod_str(talloc_tos(), &mods, &num_mods, mod_op,
1273 "member", memberdn)) {
1274 TALLOC_FREE(frame);
1275 return NT_STATUS_NO_MEMORY;
1278 rc = tldap_modify(ld, groupdn, mods, num_mods, NULL, 0, NULL, 0);
1279 TALLOC_FREE(frame);
1280 if (rc != TLDAP_SUCCESS) {
1281 DEBUG(10, ("ldap_modify failed: %s\n",
1282 tldap_errstr(talloc_tos(), state->ld, rc)));
1283 if ((mod_op == TLDAP_MOD_ADD) &&
1284 (rc == TLDAP_ALREADY_EXISTS)) {
1285 return NT_STATUS_MEMBER_IN_GROUP;
1287 if ((mod_op == TLDAP_MOD_DELETE) &&
1288 (rc == TLDAP_UNWILLING_TO_PERFORM)) {
1289 return NT_STATUS_MEMBER_NOT_IN_GROUP;
1291 return NT_STATUS_LDAP(rc);
1294 return NT_STATUS_OK;
1297 static NTSTATUS pdb_ads_add_groupmem(struct pdb_methods *m,
1298 TALLOC_CTX *mem_ctx,
1299 uint32 group_rid, uint32 member_rid)
1301 return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1302 TLDAP_MOD_ADD);
1305 static NTSTATUS pdb_ads_del_groupmem(struct pdb_methods *m,
1306 TALLOC_CTX *mem_ctx,
1307 uint32 group_rid, uint32 member_rid)
1309 return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1310 TLDAP_MOD_DELETE);
1313 static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m,
1314 const char *name, uint32 *rid)
1316 TALLOC_CTX *frame = talloc_stackframe();
1317 struct pdb_ads_state *state = talloc_get_type_abort(
1318 m->private_data, struct pdb_ads_state);
1319 struct tldap_context *ld;
1320 const char *attrs[1] = { "objectSid" };
1321 int num_mods = 0;
1322 struct tldap_mod *mods = NULL;
1323 struct tldap_message **alias;
1324 struct dom_sid sid;
1325 char *dn;
1326 int rc;
1327 bool ok = true;
1329 ld = pdb_ads_ld(state);
1330 if (ld == NULL) {
1331 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1334 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
1335 state->domaindn);
1336 if (dn == NULL) {
1337 TALLOC_FREE(frame);
1338 return NT_STATUS_NO_MEMORY;
1341 ok &= tldap_make_mod_fmt(
1342 NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
1343 name);
1344 ok &= tldap_make_mod_fmt(
1345 NULL, talloc_tos(), &mods, &num_mods, "objectClass", "group");
1346 ok &= tldap_make_mod_fmt(
1347 NULL, talloc_tos(), &mods, &num_mods, "groupType",
1348 "%d", (int)GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1350 if (!ok) {
1351 TALLOC_FREE(frame);
1352 return NT_STATUS_NO_MEMORY;
1355 rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
1356 if (rc != TLDAP_SUCCESS) {
1357 DEBUG(10, ("ldap_add failed %s\n",
1358 tldap_errstr(talloc_tos(), state->ld, rc)));
1359 TALLOC_FREE(frame);
1360 return NT_STATUS_LDAP(rc);
1363 rc = pdb_ads_search_fmt(
1364 state, state->domaindn, TLDAP_SCOPE_SUB,
1365 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
1366 "(&(objectclass=group)(samaccountname=%s))", name);
1367 if (rc != TLDAP_SUCCESS) {
1368 DEBUG(10, ("Could not find just created alias %s: %s\n",
1369 name, tldap_errstr(talloc_tos(), state->ld, rc)));
1370 TALLOC_FREE(frame);
1371 return NT_STATUS_LDAP(rc);
1374 if (talloc_array_length(alias) != 1) {
1375 DEBUG(10, ("Got %d alias, expected one\n",
1376 (int)talloc_array_length(alias)));
1377 TALLOC_FREE(frame);
1378 return NT_STATUS_LDAP(rc);
1381 if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
1382 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
1383 name));
1384 TALLOC_FREE(frame);
1385 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1388 sid_peek_rid(&sid, rid);
1389 TALLOC_FREE(frame);
1390 return NT_STATUS_OK;
1393 static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m,
1394 const struct dom_sid *sid)
1396 struct pdb_ads_state *state = talloc_get_type_abort(
1397 m->private_data, struct pdb_ads_state);
1398 struct tldap_context *ld;
1399 struct tldap_message **alias;
1400 char *sidstr, *dn = NULL;
1401 int rc;
1403 ld = pdb_ads_ld(state);
1404 if (ld == NULL) {
1405 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1408 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
1409 if (sidstr == NULL) {
1410 return NT_STATUS_NO_MEMORY;
1413 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1414 NULL, 0, 0, talloc_tos(), &alias,
1415 "(&(objectSid=%s)(objectclass=group)"
1416 "(|(grouptype=%d)(grouptype=%d)))",
1417 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1418 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1419 TALLOC_FREE(sidstr);
1420 if (rc != TLDAP_SUCCESS) {
1421 DEBUG(10, ("ldap_search failed: %s\n",
1422 tldap_errstr(talloc_tos(), state->ld, rc)));
1423 return NT_STATUS_LDAP(rc);
1425 if (talloc_array_length(alias) != 1) {
1426 DEBUG(10, ("Expected 1 alias, got %d\n",
1427 (int)talloc_array_length(alias)));
1428 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1430 if (!tldap_entry_dn(alias[0], &dn)) {
1431 DEBUG(10, ("Could not get DN for alias %s\n",
1432 sid_string_dbg(sid)));
1433 return NT_STATUS_INTERNAL_ERROR;
1436 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
1437 if (rc != TLDAP_SUCCESS) {
1438 DEBUG(10, ("ldap_delete failed: %s\n",
1439 tldap_errstr(talloc_tos(), state->ld, rc)));
1440 return NT_STATUS_LDAP(rc);
1443 return NT_STATUS_OK;
1446 static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m,
1447 const struct dom_sid *sid,
1448 struct acct_info *info)
1450 struct pdb_ads_state *state = talloc_get_type_abort(
1451 m->private_data, struct pdb_ads_state);
1452 struct tldap_context *ld;
1453 const char *attrs[3] = { "objectSid", "description",
1454 "samAccountName" };
1455 struct tldap_message **msg;
1456 char *sidstr, *dn;
1457 int rc;
1458 struct tldap_mod *mods;
1459 int num_mods;
1460 bool ok;
1462 ld = pdb_ads_ld(state);
1463 if (ld == NULL) {
1464 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1467 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
1468 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1470 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1471 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1472 &msg, "(&(objectSid=%s)(objectclass=group)"
1473 "(|(grouptype=%d)(grouptype=%d)))",
1474 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1475 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1476 TALLOC_FREE(sidstr);
1477 if (rc != TLDAP_SUCCESS) {
1478 DEBUG(10, ("ldap_search failed %s\n",
1479 tldap_errstr(talloc_tos(), state->ld, rc)));
1480 return NT_STATUS_LDAP(rc);
1482 switch talloc_array_length(msg) {
1483 case 0:
1484 return NT_STATUS_NO_SUCH_ALIAS;
1485 case 1:
1486 break;
1487 default:
1488 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1491 if (!tldap_entry_dn(msg[0], &dn)) {
1492 TALLOC_FREE(msg);
1493 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1496 mods = NULL;
1497 num_mods = 0;
1498 ok = true;
1500 ok &= tldap_make_mod_fmt(
1501 msg[0], msg, &mods, &num_mods, "description",
1502 "%s", info->acct_desc);
1503 ok &= tldap_make_mod_fmt(
1504 msg[0], msg, &mods, &num_mods, "samAccountName",
1505 "%s", info->acct_name);
1506 if (!ok) {
1507 TALLOC_FREE(msg);
1508 return NT_STATUS_NO_MEMORY;
1510 if (num_mods == 0) {
1511 /* no change */
1512 TALLOC_FREE(msg);
1513 return NT_STATUS_OK;
1516 rc = tldap_modify(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
1517 TALLOC_FREE(msg);
1518 if (rc != TLDAP_SUCCESS) {
1519 DEBUG(10, ("ldap_modify failed: %s\n",
1520 tldap_errstr(talloc_tos(), state->ld, rc)));
1521 return NT_STATUS_LDAP(rc);
1523 return NT_STATUS_OK;
1526 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
1527 const struct dom_sid *sid,
1528 TALLOC_CTX *mem_ctx, char **pdn)
1530 struct tldap_message **msg;
1531 char *sidstr, *dn;
1532 int rc;
1534 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
1535 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1537 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1538 NULL, 0, 0, talloc_tos(), &msg,
1539 "(objectsid=%s)", sidstr);
1540 TALLOC_FREE(sidstr);
1541 if (rc != TLDAP_SUCCESS) {
1542 DEBUG(10, ("ldap_search failed %s\n",
1543 tldap_errstr(talloc_tos(), state->ld, rc)));
1544 return NT_STATUS_LDAP(rc);
1547 switch talloc_array_length(msg) {
1548 case 0:
1549 return NT_STATUS_NOT_FOUND;
1550 case 1:
1551 break;
1552 default:
1553 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1556 if (!tldap_entry_dn(msg[0], &dn)) {
1557 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1560 dn = talloc_strdup(mem_ctx, dn);
1561 if (dn == NULL) {
1562 return NT_STATUS_NO_MEMORY;
1564 TALLOC_FREE(msg);
1566 *pdn = dn;
1567 return NT_STATUS_OK;
1570 static NTSTATUS pdb_ads_mod_aliasmem(struct pdb_methods *m,
1571 const struct dom_sid *alias,
1572 const struct dom_sid *member,
1573 int mod_op)
1575 struct pdb_ads_state *state = talloc_get_type_abort(
1576 m->private_data, struct pdb_ads_state);
1577 struct tldap_context *ld;
1578 TALLOC_CTX *frame = talloc_stackframe();
1579 struct tldap_mod *mods;
1580 int num_mods;
1581 int rc;
1582 char *aliasdn, *memberdn;
1583 NTSTATUS status;
1585 ld = pdb_ads_ld(state);
1586 if (ld == NULL) {
1587 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1590 status = pdb_ads_sid2dn(state, alias, talloc_tos(), &aliasdn);
1591 if (!NT_STATUS_IS_OK(status)) {
1592 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1593 sid_string_dbg(alias), nt_errstr(status)));
1594 TALLOC_FREE(frame);
1595 return NT_STATUS_NO_SUCH_ALIAS;
1597 status = pdb_ads_sid2dn(state, member, talloc_tos(), &memberdn);
1598 if (!NT_STATUS_IS_OK(status)) {
1599 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1600 sid_string_dbg(member), nt_errstr(status)));
1601 TALLOC_FREE(frame);
1602 return status;
1605 mods = NULL;
1606 num_mods = 0;
1608 if (!tldap_add_mod_str(talloc_tos(), &mods, &num_mods, mod_op,
1609 "member", memberdn)) {
1610 TALLOC_FREE(frame);
1611 return NT_STATUS_NO_MEMORY;
1614 rc = tldap_modify(ld, aliasdn, mods, num_mods, NULL, 0, NULL, 0);
1615 TALLOC_FREE(frame);
1616 if (rc != TLDAP_SUCCESS) {
1617 DEBUG(10, ("ldap_modify failed: %s\n",
1618 tldap_errstr(talloc_tos(), state->ld, rc)));
1619 if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) {
1620 return NT_STATUS_MEMBER_IN_ALIAS;
1622 if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
1623 return NT_STATUS_MEMBER_NOT_IN_ALIAS;
1625 return NT_STATUS_LDAP(rc);
1628 return NT_STATUS_OK;
1631 static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
1632 const struct dom_sid *alias,
1633 const struct dom_sid *member)
1635 return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_ADD);
1638 static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
1639 const struct dom_sid *alias,
1640 const struct dom_sid *member)
1642 return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_DELETE);
1645 static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
1646 struct dom_sid *psid)
1648 const char *attrs[1] = { "objectSid" };
1649 struct tldap_message **msg;
1650 char *dn;
1651 size_t len;
1652 int rc;
1653 bool ret;
1655 if (!convert_string_talloc(talloc_tos(), CH_UTF8, CH_UNIX,
1656 dnblob->data, dnblob->length, &dn, &len,
1657 false)) {
1658 return false;
1660 rc = pdb_ads_search_fmt(state, dn, TLDAP_SCOPE_BASE,
1661 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1662 &msg, "(objectclass=*)");
1663 TALLOC_FREE(dn);
1664 if (talloc_array_length(msg) != 1) {
1665 DEBUG(10, ("Got %d objects, expected one\n",
1666 (int)talloc_array_length(msg)));
1667 TALLOC_FREE(msg);
1668 return false;
1671 ret = tldap_pull_binsid(msg[0], "objectSid", psid);
1672 TALLOC_FREE(msg);
1673 return ret;
1676 static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
1677 const struct dom_sid *alias,
1678 TALLOC_CTX *mem_ctx,
1679 struct dom_sid **pmembers,
1680 size_t *pnum_members)
1682 struct pdb_ads_state *state = talloc_get_type_abort(
1683 m->private_data, struct pdb_ads_state);
1684 const char *attrs[1] = { "member" };
1685 char *sidstr;
1686 struct tldap_message **msg;
1687 int i, rc, num_members;
1688 DATA_BLOB *blobs;
1689 struct dom_sid *members;
1691 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), alias);
1692 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1694 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1695 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1696 &msg, "(objectsid=%s)", sidstr);
1697 TALLOC_FREE(sidstr);
1698 if (rc != TLDAP_SUCCESS) {
1699 DEBUG(10, ("ldap_search failed %s\n",
1700 tldap_errstr(talloc_tos(), state->ld, rc)));
1701 return NT_STATUS_LDAP(rc);
1703 switch talloc_array_length(msg) {
1704 case 0:
1705 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1706 break;
1707 case 1:
1708 break;
1709 default:
1710 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1711 break;
1714 if (!tldap_entry_values(msg[0], "member", &blobs, &num_members)) {
1715 *pmembers = NULL;
1716 *pnum_members = 0;
1717 return NT_STATUS_OK;
1720 members = talloc_array(mem_ctx, struct dom_sid, num_members);
1721 if (members == NULL) {
1722 return NT_STATUS_NO_MEMORY;
1725 for (i=0; i<num_members; i++) {
1726 if (!pdb_ads_dnblob2sid(state, &blobs[i], &members[i])) {
1727 TALLOC_FREE(members);
1728 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1732 *pmembers = members;
1733 *pnum_members = num_members;
1734 return NT_STATUS_OK;
1737 static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,
1738 TALLOC_CTX *mem_ctx,
1739 const struct dom_sid *domain_sid,
1740 const struct dom_sid *members,
1741 size_t num_members,
1742 uint32_t **palias_rids,
1743 size_t *pnum_alias_rids)
1745 struct pdb_ads_state *state = talloc_get_type_abort(
1746 m->private_data, struct pdb_ads_state);
1747 const char *attrs[1] = { "objectSid" };
1748 struct tldap_message **msg = NULL;
1749 uint32_t *alias_rids = NULL;
1750 size_t num_alias_rids = 0;
1751 int i, rc, count;
1752 bool got_members = false;
1753 char *filter;
1754 NTSTATUS status;
1757 * TODO: Get the filter right so that we only get the aliases from
1758 * either the SAM or BUILTIN
1761 filter = talloc_asprintf(talloc_tos(),
1762 "(&(|(grouptype=%d)(grouptype=%d))"
1763 "(objectclass=group)(|",
1764 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1765 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1766 if (filter == NULL) {
1767 return NT_STATUS_NO_MEMORY;
1770 for (i=0; i<num_members; i++) {
1771 char *dn;
1773 status = pdb_ads_sid2dn(state, &members[i], talloc_tos(), &dn);
1774 if (!NT_STATUS_IS_OK(status)) {
1775 DEBUG(10, ("pdb_ads_sid2dn failed for %s: %s\n",
1776 sid_string_dbg(&members[i]),
1777 nt_errstr(status)));
1778 continue;
1780 filter = talloc_asprintf_append_buffer(
1781 filter, "(member=%s)", dn);
1782 TALLOC_FREE(dn);
1783 if (filter == NULL) {
1784 return NT_STATUS_NO_MEMORY;
1786 got_members = true;
1789 if (!got_members) {
1790 goto done;
1793 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1794 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1795 &msg, "%s))", filter);
1796 TALLOC_FREE(filter);
1797 if (rc != TLDAP_SUCCESS) {
1798 DEBUG(10, ("tldap_search failed %s\n",
1799 tldap_errstr(talloc_tos(), state->ld, rc)));
1800 return NT_STATUS_LDAP(rc);
1803 count = talloc_array_length(msg);
1804 if (count == 0) {
1805 goto done;
1808 alias_rids = talloc_array(mem_ctx, uint32_t, count);
1809 if (alias_rids == NULL) {
1810 TALLOC_FREE(msg);
1811 return NT_STATUS_NO_MEMORY;
1814 for (i=0; i<count; i++) {
1815 struct dom_sid sid;
1817 if (!tldap_pull_binsid(msg[i], "objectSid", &sid)) {
1818 DEBUG(10, ("Could not pull SID for member %d\n", i));
1819 continue;
1821 if (sid_peek_check_rid(domain_sid, &sid,
1822 &alias_rids[num_alias_rids])) {
1823 num_alias_rids += 1;
1826 done:
1827 TALLOC_FREE(msg);
1828 *palias_rids = alias_rids;
1829 *pnum_alias_rids = 0;
1830 return NT_STATUS_OK;
1833 static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m,
1834 const struct dom_sid *domain_sid,
1835 int num_rids,
1836 uint32 *rids,
1837 const char **names,
1838 enum lsa_SidType *lsa_attrs)
1840 struct pdb_ads_state *state = talloc_get_type_abort(
1841 m->private_data, struct pdb_ads_state);
1842 const char *attrs[2] = { "sAMAccountType", "sAMAccountName" };
1843 int i, num_mapped;
1845 if (num_rids == 0) {
1846 return NT_STATUS_NONE_MAPPED;
1849 num_mapped = 0;
1851 for (i=0; i<num_rids; i++) {
1852 struct dom_sid sid;
1853 struct tldap_message **msg;
1854 char *sidstr;
1855 uint32_t attr;
1856 int rc;
1858 lsa_attrs[i] = SID_NAME_UNKNOWN;
1860 sid_compose(&sid, domain_sid, rids[i]);
1862 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), &sid);
1863 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1865 rc = pdb_ads_search_fmt(state, state->domaindn,
1866 TLDAP_SCOPE_SUB, attrs,
1867 ARRAY_SIZE(attrs), 0, talloc_tos(),
1868 &msg, "(objectsid=%s)", sidstr);
1869 TALLOC_FREE(sidstr);
1870 if (rc != TLDAP_SUCCESS) {
1871 DEBUG(10, ("ldap_search failed %s\n",
1872 tldap_errstr(talloc_tos(), state->ld, rc)));
1873 continue;
1876 switch talloc_array_length(msg) {
1877 case 0:
1878 DEBUG(10, ("rid %d not found\n", (int)rids[i]));
1879 continue;
1880 case 1:
1881 break;
1882 default:
1883 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1886 names[i] = tldap_talloc_single_attribute(
1887 msg[0], "samAccountName", talloc_tos());
1888 if (names[i] == NULL) {
1889 DEBUG(10, ("no samAccountName\n"));
1890 continue;
1892 if (!tldap_pull_uint32(msg[0], "samAccountType", &attr)) {
1893 DEBUG(10, ("no samAccountType"));
1894 continue;
1896 lsa_attrs[i] = ds_atype_map(attr);
1897 num_mapped += 1;
1900 if (num_mapped == 0) {
1901 return NT_STATUS_NONE_MAPPED;
1903 if (num_mapped < num_rids) {
1904 return STATUS_SOME_UNMAPPED;
1906 return NT_STATUS_OK;
1909 static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m,
1910 const struct dom_sid *domain_sid,
1911 int num_names,
1912 const char **pp_names,
1913 uint32 *rids,
1914 enum lsa_SidType *attrs)
1916 return NT_STATUS_NOT_IMPLEMENTED;
1919 static NTSTATUS pdb_ads_get_account_policy(struct pdb_methods *m,
1920 enum pdb_policy_type type,
1921 uint32_t *value)
1923 return account_policy_get(type, value)
1924 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1927 static NTSTATUS pdb_ads_set_account_policy(struct pdb_methods *m,
1928 enum pdb_policy_type type,
1929 uint32_t value)
1931 return account_policy_set(type, value)
1932 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1935 static NTSTATUS pdb_ads_get_seq_num(struct pdb_methods *m,
1936 time_t *seq_num)
1938 return NT_STATUS_NOT_IMPLEMENTED;
1941 struct pdb_ads_search_state {
1942 uint32_t acct_flags;
1943 struct samr_displayentry *entries;
1944 uint32_t num_entries;
1945 ssize_t array_size;
1946 uint32_t current;
1949 static bool pdb_ads_next_entry(struct pdb_search *search,
1950 struct samr_displayentry *entry)
1952 struct pdb_ads_search_state *state = talloc_get_type_abort(
1953 search->private_data, struct pdb_ads_search_state);
1955 if (state->current == state->num_entries) {
1956 return false;
1959 entry->idx = state->entries[state->current].idx;
1960 entry->rid = state->entries[state->current].rid;
1961 entry->acct_flags = state->entries[state->current].acct_flags;
1963 entry->account_name = talloc_strdup(
1964 search, state->entries[state->current].account_name);
1965 entry->fullname = talloc_strdup(
1966 search, state->entries[state->current].fullname);
1967 entry->description = talloc_strdup(
1968 search, state->entries[state->current].description);
1970 if ((entry->account_name == NULL) || (entry->fullname == NULL)
1971 || (entry->description == NULL)) {
1972 DEBUG(0, ("talloc_strdup failed\n"));
1973 return false;
1976 state->current += 1;
1977 return true;
1980 static void pdb_ads_search_end(struct pdb_search *search)
1982 struct pdb_ads_search_state *state = talloc_get_type_abort(
1983 search->private_data, struct pdb_ads_search_state);
1984 TALLOC_FREE(state);
1987 static bool pdb_ads_search_filter(struct pdb_methods *m,
1988 struct pdb_search *search,
1989 const char *filter,
1990 uint32_t acct_flags,
1991 struct pdb_ads_search_state **pstate)
1993 struct pdb_ads_state *state = talloc_get_type_abort(
1994 m->private_data, struct pdb_ads_state);
1995 struct pdb_ads_search_state *sstate;
1996 const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1997 "userAccountControl", "description" };
1998 struct tldap_message **users;
1999 int i, rc, num_users;
2001 sstate = talloc_zero(search, struct pdb_ads_search_state);
2002 if (sstate == NULL) {
2003 return false;
2005 sstate->acct_flags = acct_flags;
2007 rc = pdb_ads_search_fmt(
2008 state, state->domaindn, TLDAP_SCOPE_SUB,
2009 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &users,
2010 "%s", filter);
2011 if (rc != TLDAP_SUCCESS) {
2012 DEBUG(10, ("ldap_search_ext_s failed: %s\n",
2013 tldap_errstr(talloc_tos(), state->ld, rc)));
2014 return false;
2017 num_users = talloc_array_length(users);
2019 sstate->entries = talloc_array(sstate, struct samr_displayentry,
2020 num_users);
2021 if (sstate->entries == NULL) {
2022 DEBUG(10, ("talloc failed\n"));
2023 return false;
2026 sstate->num_entries = 0;
2028 for (i=0; i<num_users; i++) {
2029 struct samr_displayentry *e;
2030 struct dom_sid sid;
2031 uint32_t ctrl;
2033 e = &sstate->entries[sstate->num_entries];
2035 e->idx = sstate->num_entries;
2036 if (!tldap_pull_binsid(users[i], "objectSid", &sid)) {
2037 DEBUG(10, ("Could not pull sid\n"));
2038 continue;
2040 sid_peek_rid(&sid, &e->rid);
2042 if (tldap_pull_uint32(users[i], "userAccountControl", &ctrl)) {
2044 e->acct_flags = ds_uf2acb(ctrl);
2046 DEBUG(10, ("pdb_ads_search_filter: Found %x, "
2047 "filter %x\n", (int)e->acct_flags,
2048 (int)sstate->acct_flags));
2051 if ((sstate->acct_flags != 0) &&
2052 ((sstate->acct_flags & e->acct_flags) == 0)) {
2053 continue;
2056 if (e->acct_flags & (ACB_WSTRUST|ACB_SVRTRUST)) {
2057 e->acct_flags |= ACB_NORMAL;
2059 } else {
2060 e->acct_flags = ACB_NORMAL;
2063 if (e->rid == DOMAIN_RID_GUEST) {
2065 * Guest is specially crafted in s3. Make
2066 * QueryDisplayInfo match QueryUserInfo
2068 e->account_name = lp_guestaccount();
2069 e->fullname = lp_guestaccount();
2070 e->description = "";
2071 e->acct_flags = ACB_NORMAL;
2072 } else {
2073 e->account_name = tldap_talloc_single_attribute(
2074 users[i], "samAccountName", sstate->entries);
2075 e->fullname = tldap_talloc_single_attribute(
2076 users[i], "displayName", sstate->entries);
2077 e->description = tldap_talloc_single_attribute(
2078 users[i], "description", sstate->entries);
2080 if (e->account_name == NULL) {
2081 return false;
2083 if (e->fullname == NULL) {
2084 e->fullname = "";
2086 if (e->description == NULL) {
2087 e->description = "";
2090 sstate->num_entries += 1;
2091 if (sstate->num_entries >= num_users) {
2092 break;
2096 search->private_data = sstate;
2097 search->next_entry = pdb_ads_next_entry;
2098 search->search_end = pdb_ads_search_end;
2099 *pstate = sstate;
2100 return true;
2103 static bool pdb_ads_search_users(struct pdb_methods *m,
2104 struct pdb_search *search,
2105 uint32 acct_flags)
2107 struct pdb_ads_search_state *sstate;
2108 char *filter;
2109 bool ret;
2111 DEBUG(10, ("pdb_ads_search_users got flags %x\n", acct_flags));
2113 if (acct_flags & ACB_NORMAL) {
2114 filter = talloc_asprintf(
2115 talloc_tos(),
2116 "(&(objectclass=user)(sAMAccountType=%d))",
2117 ATYPE_NORMAL_ACCOUNT);
2118 } else if (acct_flags & ACB_WSTRUST) {
2119 filter = talloc_asprintf(
2120 talloc_tos(),
2121 "(&(objectclass=user)(sAMAccountType=%d))",
2122 ATYPE_WORKSTATION_TRUST);
2123 } else {
2124 filter = talloc_strdup(talloc_tos(), "(objectclass=user)");
2126 if (filter == NULL) {
2127 return false;
2130 ret = pdb_ads_search_filter(m, search, filter, acct_flags, &sstate);
2131 TALLOC_FREE(filter);
2132 if (!ret) {
2133 return false;
2135 return true;
2138 static bool pdb_ads_search_groups(struct pdb_methods *m,
2139 struct pdb_search *search)
2141 struct pdb_ads_search_state *sstate;
2142 char *filter;
2143 bool ret;
2145 filter = talloc_asprintf(talloc_tos(),
2146 "(&(grouptype=%d)(objectclass=group))",
2147 GTYPE_SECURITY_GLOBAL_GROUP);
2148 if (filter == NULL) {
2149 return false;
2151 ret = pdb_ads_search_filter(m, search, filter, 0, &sstate);
2152 TALLOC_FREE(filter);
2153 if (!ret) {
2154 return false;
2156 return true;
2159 static bool pdb_ads_search_aliases(struct pdb_methods *m,
2160 struct pdb_search *search,
2161 const struct dom_sid *sid)
2163 struct pdb_ads_search_state *sstate;
2164 char *filter;
2165 bool ret;
2167 filter = talloc_asprintf(
2168 talloc_tos(), "(&(grouptype=%d)(objectclass=group))",
2169 sid_check_is_builtin(sid)
2170 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2171 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2173 if (filter == NULL) {
2174 return false;
2176 ret = pdb_ads_search_filter(m, search, filter, 0, &sstate);
2177 TALLOC_FREE(filter);
2178 if (!ret) {
2179 return false;
2181 return true;
2184 static bool pdb_ads_uid_to_sid(struct pdb_methods *m, uid_t uid,
2185 struct dom_sid *sid)
2187 struct pdb_ads_state *state = talloc_get_type_abort(
2188 m->private_data, struct pdb_ads_state);
2189 sid_compose(sid, &state->domainsid, uid);
2190 return true;
2193 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
2194 struct dom_sid *sid)
2196 struct pdb_ads_state *state = talloc_get_type_abort(
2197 m->private_data, struct pdb_ads_state);
2198 sid_compose(sid, &state->domainsid, gid);
2199 return true;
2202 static bool pdb_ads_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2203 union unid_t *id, enum lsa_SidType *type)
2205 struct pdb_ads_state *state = talloc_get_type_abort(
2206 m->private_data, struct pdb_ads_state);
2207 const char *attrs[4] = { "objectClass", "samAccountType",
2208 "uidNumber", "gidNumber" };
2209 struct tldap_message **msg;
2210 char *sidstr, *base;
2211 uint32_t atype;
2212 int rc;
2213 bool ret = false;
2215 sidstr = sid_binstring_hex(sid);
2216 if (sidstr == NULL) {
2217 return false;
2219 base = talloc_asprintf(talloc_tos(), "<SID=%s>", sidstr);
2220 SAFE_FREE(sidstr);
2222 rc = pdb_ads_search_fmt(
2223 state, base, TLDAP_SCOPE_BASE,
2224 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &msg,
2225 "(objectclass=*)");
2226 TALLOC_FREE(base);
2228 if (rc != TLDAP_SUCCESS) {
2229 DEBUG(10, ("pdb_ads_search_fmt failed: %s\n",
2230 tldap_errstr(talloc_tos(), state->ld, rc)));
2231 return false;
2233 if (talloc_array_length(msg) != 1) {
2234 DEBUG(10, ("Got %d objects, expected 1\n",
2235 (int)talloc_array_length(msg)));
2236 goto fail;
2238 if (!tldap_pull_uint32(msg[0], "samAccountType", &atype)) {
2239 DEBUG(10, ("samAccountType not found\n"));
2240 goto fail;
2242 if (atype == ATYPE_ACCOUNT) {
2243 uint32_t uid;
2244 *type = SID_NAME_USER;
2245 if (!tldap_pull_uint32(msg[0], "uidNumber", &uid)) {
2246 DEBUG(10, ("Did not find uidNumber\n"));
2247 goto fail;
2249 id->uid = uid;
2250 } else {
2251 uint32_t gid;
2252 *type = SID_NAME_DOM_GRP;
2253 if (!tldap_pull_uint32(msg[0], "gidNumber", &gid)) {
2254 DEBUG(10, ("Did not find gidNumber\n"));
2255 goto fail;
2257 id->gid = gid;
2259 ret = true;
2260 fail:
2261 TALLOC_FREE(msg);
2262 return ret;
2265 static uint32_t pdb_ads_capabilities(struct pdb_methods *m)
2267 return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
2270 static bool pdb_ads_new_rid(struct pdb_methods *m, uint32 *rid)
2272 return false;
2275 static bool pdb_ads_get_trusteddom_pw(struct pdb_methods *m,
2276 const char *domain, char** pwd,
2277 struct dom_sid *sid,
2278 time_t *pass_last_set_time)
2280 return false;
2283 static bool pdb_ads_set_trusteddom_pw(struct pdb_methods *m,
2284 const char* domain, const char* pwd,
2285 const struct dom_sid *sid)
2287 return false;
2290 static bool pdb_ads_del_trusteddom_pw(struct pdb_methods *m,
2291 const char *domain)
2293 return false;
2296 static NTSTATUS pdb_ads_enum_trusteddoms(struct pdb_methods *m,
2297 TALLOC_CTX *mem_ctx,
2298 uint32 *num_domains,
2299 struct trustdom_info ***domains)
2301 *num_domains = 0;
2302 *domains = NULL;
2303 return NT_STATUS_OK;
2306 static void pdb_ads_init_methods(struct pdb_methods *m)
2308 m->name = "ads";
2309 m->get_domain_info = pdb_ads_get_domain_info;
2310 m->getsampwnam = pdb_ads_getsampwnam;
2311 m->getsampwsid = pdb_ads_getsampwsid;
2312 m->create_user = pdb_ads_create_user;
2313 m->delete_user = pdb_ads_delete_user;
2314 m->add_sam_account = pdb_ads_add_sam_account;
2315 m->update_sam_account = pdb_ads_update_sam_account;
2316 m->delete_sam_account = pdb_ads_delete_sam_account;
2317 m->rename_sam_account = pdb_ads_rename_sam_account;
2318 m->update_login_attempts = pdb_ads_update_login_attempts;
2319 m->getgrsid = pdb_ads_getgrsid;
2320 m->getgrgid = pdb_ads_getgrgid;
2321 m->getgrnam = pdb_ads_getgrnam;
2322 m->create_dom_group = pdb_ads_create_dom_group;
2323 m->delete_dom_group = pdb_ads_delete_dom_group;
2324 m->add_group_mapping_entry = pdb_ads_add_group_mapping_entry;
2325 m->update_group_mapping_entry = pdb_ads_update_group_mapping_entry;
2326 m->delete_group_mapping_entry = pdb_ads_delete_group_mapping_entry;
2327 m->enum_group_mapping = pdb_ads_enum_group_mapping;
2328 m->enum_group_members = pdb_ads_enum_group_members;
2329 m->enum_group_memberships = pdb_ads_enum_group_memberships;
2330 m->set_unix_primary_group = pdb_ads_set_unix_primary_group;
2331 m->add_groupmem = pdb_ads_add_groupmem;
2332 m->del_groupmem = pdb_ads_del_groupmem;
2333 m->create_alias = pdb_ads_create_alias;
2334 m->delete_alias = pdb_ads_delete_alias;
2335 m->get_aliasinfo = pdb_default_get_aliasinfo;
2336 m->set_aliasinfo = pdb_ads_set_aliasinfo;
2337 m->add_aliasmem = pdb_ads_add_aliasmem;
2338 m->del_aliasmem = pdb_ads_del_aliasmem;
2339 m->enum_aliasmem = pdb_ads_enum_aliasmem;
2340 m->enum_alias_memberships = pdb_ads_enum_alias_memberships;
2341 m->lookup_rids = pdb_ads_lookup_rids;
2342 m->lookup_names = pdb_ads_lookup_names;
2343 m->get_account_policy = pdb_ads_get_account_policy;
2344 m->set_account_policy = pdb_ads_set_account_policy;
2345 m->get_seq_num = pdb_ads_get_seq_num;
2346 m->search_users = pdb_ads_search_users;
2347 m->search_groups = pdb_ads_search_groups;
2348 m->search_aliases = pdb_ads_search_aliases;
2349 m->uid_to_sid = pdb_ads_uid_to_sid;
2350 m->gid_to_sid = pdb_ads_gid_to_sid;
2351 m->sid_to_id = pdb_ads_sid_to_id;
2352 m->capabilities = pdb_ads_capabilities;
2353 m->new_rid = pdb_ads_new_rid;
2354 m->get_trusteddom_pw = pdb_ads_get_trusteddom_pw;
2355 m->set_trusteddom_pw = pdb_ads_set_trusteddom_pw;
2356 m->del_trusteddom_pw = pdb_ads_del_trusteddom_pw;
2357 m->enum_trusteddoms = pdb_ads_enum_trusteddoms;
2360 static void free_private_data(void **vp)
2362 struct pdb_ads_state *state = talloc_get_type_abort(
2363 *vp, struct pdb_ads_state);
2365 TALLOC_FREE(state->ld);
2366 return;
2370 this is used to catch debug messages from events
2372 static void s3_tldap_debug(void *context, enum tldap_debug_level level,
2373 const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
2375 static void s3_tldap_debug(void *context, enum tldap_debug_level level,
2376 const char *fmt, va_list ap)
2378 int samba_level = -1;
2379 char *s = NULL;
2380 switch (level) {
2381 case TLDAP_DEBUG_FATAL:
2382 samba_level = 0;
2383 break;
2384 case TLDAP_DEBUG_ERROR:
2385 samba_level = 1;
2386 break;
2387 case TLDAP_DEBUG_WARNING:
2388 samba_level = 2;
2389 break;
2390 case TLDAP_DEBUG_TRACE:
2391 samba_level = 11;
2392 break;
2395 if (vasprintf(&s, fmt, ap) == -1) {
2396 return;
2398 DEBUG(samba_level, ("tldap: %s", s));
2399 free(s);
2402 static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state)
2404 NTSTATUS status;
2405 int fd;
2407 if (tldap_connection_ok(state->ld)) {
2408 return state->ld;
2410 TALLOC_FREE(state->ld);
2412 status = open_socket_out(
2413 (struct sockaddr_storage *)(void *)&state->socket_address,
2414 0, 0, &fd);
2415 if (!NT_STATUS_IS_OK(status)) {
2416 DEBUG(10, ("Could not connect to %s: %s\n",
2417 state->socket_address.sun_path, nt_errstr(status)));
2418 return NULL;
2421 set_blocking(fd, false);
2423 state->ld = tldap_context_create(state, fd);
2424 if (state->ld == NULL) {
2425 close(fd);
2426 return NULL;
2428 tldap_set_debug(state->ld, s3_tldap_debug, NULL);
2430 return state->ld;
2433 int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base,
2434 int scope, const char *attrs[], int num_attrs,
2435 int attrsonly,
2436 TALLOC_CTX *mem_ctx, struct tldap_message ***res,
2437 const char *fmt, ...)
2439 struct tldap_context *ld;
2440 va_list ap;
2441 int ret;
2443 ld = pdb_ads_ld(state);
2444 if (ld == NULL) {
2445 return TLDAP_SERVER_DOWN;
2448 va_start(ap, fmt);
2449 ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly,
2450 mem_ctx, res, fmt, ap);
2451 va_end(ap);
2453 if (ret != TLDAP_SERVER_DOWN) {
2454 return ret;
2457 /* retry once */
2458 ld = pdb_ads_ld(state);
2459 if (ld == NULL) {
2460 return TLDAP_SERVER_DOWN;
2463 va_start(ap, fmt);
2464 ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly,
2465 mem_ctx, res, fmt, ap);
2466 va_end(ap);
2467 return ret;
2470 static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state,
2471 const char *location)
2473 const char *domain_attrs[2] = { "objectSid", "objectGUID" };
2474 const char *ncname_attrs[1] = { "netbiosname" };
2475 struct tldap_context *ld;
2476 struct tldap_message *rootdse, **domain, **ncname;
2477 TALLOC_CTX *frame = talloc_stackframe();
2478 NTSTATUS status;
2479 int num_domains;
2480 int rc;
2482 ZERO_STRUCT(state->socket_address);
2483 state->socket_address.sun_family = AF_UNIX;
2484 strlcpy(state->socket_address.sun_path, location,
2485 sizeof(state->socket_address.sun_path));
2487 ld = pdb_ads_ld(state);
2488 if (ld == NULL) {
2489 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2490 goto done;
2493 rc = tldap_fetch_rootdse(ld);
2494 if (rc != TLDAP_SUCCESS) {
2495 DEBUG(10, ("Could not retrieve rootdse: %s\n",
2496 tldap_errstr(talloc_tos(), state->ld, rc)));
2497 status = NT_STATUS_LDAP(rc);
2498 goto done;
2500 rootdse = tldap_rootdse(state->ld);
2502 state->domaindn = tldap_talloc_single_attribute(
2503 rootdse, "defaultNamingContext", state);
2504 if (state->domaindn == NULL) {
2505 DEBUG(10, ("Could not get defaultNamingContext\n"));
2506 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2507 goto done;
2509 DEBUG(10, ("defaultNamingContext = %s\n", state->domaindn));
2511 state->configdn = tldap_talloc_single_attribute(
2512 rootdse, "configurationNamingContext", state);
2513 if (state->configdn == NULL) {
2514 DEBUG(10, ("Could not get configurationNamingContext\n"));
2515 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2516 goto done;
2518 DEBUG(10, ("configurationNamingContext = %s\n", state->configdn));
2521 * Figure out our domain's SID
2523 rc = pdb_ads_search_fmt(
2524 state, state->domaindn, TLDAP_SCOPE_BASE,
2525 domain_attrs, ARRAY_SIZE(domain_attrs), 0,
2526 talloc_tos(), &domain, "(objectclass=*)");
2527 if (rc != TLDAP_SUCCESS) {
2528 DEBUG(10, ("Could not retrieve domain: %s\n",
2529 tldap_errstr(talloc_tos(), state->ld, rc)));
2530 status = NT_STATUS_LDAP(rc);
2531 goto done;
2534 num_domains = talloc_array_length(domain);
2535 if (num_domains != 1) {
2536 DEBUG(10, ("Got %d domains, expected one\n", num_domains));
2537 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2538 goto done;
2540 if (!tldap_pull_binsid(domain[0], "objectSid", &state->domainsid)) {
2541 DEBUG(10, ("Could not retrieve domain SID\n"));
2542 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2543 goto done;
2545 if (!tldap_pull_guid(domain[0], "objectGUID", &state->domainguid)) {
2546 DEBUG(10, ("Could not retrieve domain GUID\n"));
2547 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2548 goto done;
2550 DEBUG(10, ("Domain SID: %s\n", sid_string_dbg(&state->domainsid)));
2553 * Figure out our domain's short name
2555 rc = pdb_ads_search_fmt(
2556 state, state->configdn, TLDAP_SCOPE_SUB,
2557 ncname_attrs, ARRAY_SIZE(ncname_attrs), 0,
2558 talloc_tos(), &ncname, "(ncname=%s)", state->domaindn);
2559 if (rc != TLDAP_SUCCESS) {
2560 DEBUG(10, ("Could not retrieve ncname: %s\n",
2561 tldap_errstr(talloc_tos(), state->ld, rc)));
2562 status = NT_STATUS_LDAP(rc);
2563 goto done;
2565 if (talloc_array_length(ncname) != 1) {
2566 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2567 goto done;
2570 state->netbiosname = tldap_talloc_single_attribute(
2571 ncname[0], "netbiosname", state);
2572 if (state->netbiosname == NULL) {
2573 DEBUG(10, ("Could not get netbiosname\n"));
2574 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2575 goto done;
2577 DEBUG(10, ("netbiosname: %s\n", state->netbiosname));
2579 if (!strequal(lp_workgroup(), state->netbiosname)) {
2580 DEBUG(1, ("ADS is different domain (%s) than ours (%s)\n",
2581 state->netbiosname, lp_workgroup()));
2582 status = NT_STATUS_NO_SUCH_DOMAIN;
2583 goto done;
2586 secrets_store_domain_sid(state->netbiosname, &state->domainsid);
2588 status = NT_STATUS_OK;
2589 done:
2590 TALLOC_FREE(frame);
2591 return status;
2594 static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method,
2595 const char *location)
2597 struct pdb_methods *m;
2598 struct pdb_ads_state *state;
2599 char *tmp = NULL;
2600 NTSTATUS status;
2602 m = talloc(NULL, struct pdb_methods);
2603 if (m == NULL) {
2604 return NT_STATUS_NO_MEMORY;
2606 state = talloc_zero(m, struct pdb_ads_state);
2607 if (state == NULL) {
2608 goto nomem;
2610 m->private_data = state;
2611 m->free_private_data = free_private_data;
2612 pdb_ads_init_methods(m);
2614 if (location == NULL) {
2615 tmp = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi",
2616 lp_private_dir());
2617 location = tmp;
2619 if (location == NULL) {
2620 goto nomem;
2623 status = pdb_ads_connect(state, location);
2624 if (!NT_STATUS_IS_OK(status)) {
2625 DEBUG(10, ("pdb_ads_connect failed: %s\n", nt_errstr(status)));
2626 goto fail;
2629 *pdb_method = m;
2630 return NT_STATUS_OK;
2631 nomem:
2632 status = NT_STATUS_NO_MEMORY;
2633 fail:
2634 TALLOC_FREE(m);
2635 return status;
2638 NTSTATUS pdb_ads_init(void);
2639 NTSTATUS pdb_ads_init(void)
2641 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "ads",
2642 pdb_init_ads);