s3-passdb: Fix typo in comment.
[Samba.git] / source3 / passdb / pdb_ads.c
blob722bfacfb17531efe6740f9581a29b88630d3a7f
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 "tldap.h"
22 #include "tldap_util.h"
24 struct pdb_ads_state {
25 struct sockaddr_un socket_address;
26 struct tldap_context *ld;
27 struct dom_sid domainsid;
28 struct GUID domainguid;
29 char *domaindn;
30 char *configdn;
31 char *netbiosname;
34 struct pdb_ads_samu_private {
35 char *dn;
36 struct tldap_message *ldapmsg;
39 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
40 struct samu *sam_acct,
41 const struct dom_sid *sid);
42 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
43 struct dom_sid *sid);
44 static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
45 struct dom_sid *psid);
46 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
47 const struct dom_sid *sid,
48 TALLOC_CTX *mem_ctx, char **pdn);
49 static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state);
50 static int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base,
51 int scope, const char *attrs[], int num_attrs,
52 int attrsonly,
53 TALLOC_CTX *mem_ctx, struct tldap_message ***res,
54 const char *fmt, ...);
55 static NTSTATUS pdb_ads_getsamupriv(struct pdb_ads_state *state,
56 const char *filter,
57 TALLOC_CTX *mem_ctx,
58 struct pdb_ads_samu_private **presult);
60 static bool pdb_ads_pull_time(struct tldap_message *msg, const char *attr,
61 time_t *ptime)
63 uint64_t tmp;
65 if (!tldap_pull_uint64(msg, attr, &tmp)) {
66 return false;
68 *ptime = uint64s_nt_time_to_unix_abs(&tmp);
69 return true;
72 static gid_t pdb_ads_sid2gid(const struct dom_sid *sid)
74 uint32_t rid;
75 sid_peek_rid(sid, &rid);
76 return rid;
79 static char *pdb_ads_domaindn2dns(TALLOC_CTX *mem_ctx, char *dn)
81 char *result, *p;
83 result = talloc_string_sub2(mem_ctx, dn, "DC=", "", false, false,
84 true);
85 if (result == NULL) {
86 return NULL;
89 while ((p = strchr_m(result, ',')) != NULL) {
90 *p = '.';
93 return result;
96 static struct pdb_domain_info *pdb_ads_get_domain_info(
97 struct pdb_methods *m, TALLOC_CTX *mem_ctx)
99 struct pdb_ads_state *state = talloc_get_type_abort(
100 m->private_data, struct pdb_ads_state);
101 struct pdb_domain_info *info;
102 struct tldap_message *rootdse;
103 char *tmp;
105 info = talloc(mem_ctx, struct pdb_domain_info);
106 if (info == NULL) {
107 return NULL;
109 info->name = talloc_strdup(info, state->netbiosname);
110 if (info->name == NULL) {
111 goto fail;
113 info->dns_domain = pdb_ads_domaindn2dns(info, state->domaindn);
114 if (info->dns_domain == NULL) {
115 goto fail;
118 rootdse = tldap_rootdse(state->ld);
119 tmp = tldap_talloc_single_attribute(rootdse, "rootDomainNamingContext",
120 talloc_tos());
121 if (tmp == NULL) {
122 goto fail;
124 info->dns_forest = pdb_ads_domaindn2dns(info, tmp);
125 TALLOC_FREE(tmp);
126 if (info->dns_forest == NULL) {
127 goto fail;
129 info->sid = state->domainsid;
130 info->guid = state->domainguid;
131 return info;
133 fail:
134 TALLOC_FREE(info);
135 return NULL;
138 static struct pdb_ads_samu_private *pdb_ads_get_samu_private(
139 struct pdb_methods *m, struct samu *sam)
141 struct pdb_ads_state *state = talloc_get_type_abort(
142 m->private_data, struct pdb_ads_state);
143 struct pdb_ads_samu_private *result;
144 char *sidstr, *filter;
145 NTSTATUS status;
147 result = (struct pdb_ads_samu_private *)
148 pdb_get_backend_private_data(sam, m);
150 if (result != NULL) {
151 return talloc_get_type_abort(
152 result, struct pdb_ads_samu_private);
155 sidstr = sid_binstring(talloc_tos(), pdb_get_user_sid(sam));
156 if (sidstr == NULL) {
157 return NULL;
160 filter = talloc_asprintf(
161 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
162 TALLOC_FREE(sidstr);
163 if (filter == NULL) {
164 return NULL;
167 status = pdb_ads_getsamupriv(state, filter, sam, &result);
168 TALLOC_FREE(filter);
169 if (!NT_STATUS_IS_OK(status)) {
170 return NULL;
173 return result;
176 static NTSTATUS pdb_ads_init_sam_from_priv(struct pdb_methods *m,
177 struct samu *sam,
178 struct pdb_ads_samu_private *priv)
180 struct pdb_ads_state *state = talloc_get_type_abort(
181 m->private_data, struct pdb_ads_state);
182 TALLOC_CTX *frame = talloc_stackframe();
183 NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
184 struct tldap_message *entry = priv->ldapmsg;
185 char *str;
186 time_t tmp_time;
187 struct dom_sid sid;
188 uint64_t n;
189 DATA_BLOB blob;
191 str = tldap_talloc_single_attribute(entry, "samAccountName", sam);
192 if (str == NULL) {
193 DEBUG(10, ("no samAccountName\n"));
194 goto fail;
196 pdb_set_username(sam, str, PDB_SET);
198 if (pdb_ads_pull_time(entry, "lastLogon", &tmp_time)) {
199 pdb_set_logon_time(sam, tmp_time, PDB_SET);
201 if (pdb_ads_pull_time(entry, "lastLogoff", &tmp_time)) {
202 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
204 if (pdb_ads_pull_time(entry, "pwdLastSet", &tmp_time)) {
205 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
207 if (pdb_ads_pull_time(entry, "accountExpires", &tmp_time)) {
208 pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
211 str = tldap_talloc_single_attribute(entry, "displayName",
212 talloc_tos());
213 if (str != NULL) {
214 pdb_set_fullname(sam, str, PDB_SET);
217 str = tldap_talloc_single_attribute(entry, "homeDirectory",
218 talloc_tos());
219 if (str != NULL) {
220 pdb_set_homedir(sam, str, PDB_SET);
223 str = tldap_talloc_single_attribute(entry, "homeDrive", talloc_tos());
224 if (str != NULL) {
225 pdb_set_dir_drive(sam, str, PDB_SET);
228 str = tldap_talloc_single_attribute(entry, "scriptPath", talloc_tos());
229 if (str != NULL) {
230 pdb_set_logon_script(sam, str, PDB_SET);
233 str = tldap_talloc_single_attribute(entry, "profilePath",
234 talloc_tos());
235 if (str != NULL) {
236 pdb_set_profile_path(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 if (!tldap_pull_binsid(entry, "objectSid", &sid)) {
246 DEBUG(10, ("Could not pull SID\n"));
247 goto fail;
249 pdb_set_user_sid(sam, &sid, PDB_SET);
251 if (!tldap_pull_uint64(entry, "userAccountControl", &n)) {
252 DEBUG(10, ("Could not pull userAccountControl\n"));
253 goto fail;
255 pdb_set_acct_ctrl(sam, ds_uf2acb(n), PDB_SET);
257 if (tldap_get_single_valueblob(entry, "unicodePwd", &blob)) {
258 if (blob.length != NT_HASH_LEN) {
259 DEBUG(0, ("Got NT hash of length %d, expected %d\n",
260 (int)blob.length, NT_HASH_LEN));
261 goto fail;
263 pdb_set_nt_passwd(sam, blob.data, PDB_SET);
266 if (tldap_get_single_valueblob(entry, "dBCSPwd", &blob)) {
267 if (blob.length != LM_HASH_LEN) {
268 DEBUG(0, ("Got LM hash of length %d, expected %d\n",
269 (int)blob.length, LM_HASH_LEN));
270 goto fail;
272 pdb_set_lanman_passwd(sam, blob.data, PDB_SET);
275 if (tldap_pull_uint64(entry, "primaryGroupID", &n)) {
276 sid_compose(&sid, &state->domainsid, n);
277 pdb_set_group_sid(sam, &sid, PDB_SET);
280 status = NT_STATUS_OK;
281 fail:
282 TALLOC_FREE(frame);
283 return status;
286 static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state,
287 struct tldap_message *existing,
288 TALLOC_CTX *mem_ctx,
289 int *pnum_mods, struct tldap_mod **pmods,
290 struct samu *sam)
292 bool ret = true;
293 DATA_BLOB blob;
295 /* TODO: All fields :-) */
297 ret &= tldap_make_mod_fmt(
298 existing, mem_ctx, pnum_mods, pmods, "displayName",
299 "%s", pdb_get_fullname(sam));
301 blob = data_blob_const(pdb_get_nt_passwd(sam), NT_HASH_LEN);
302 if (blob.data != NULL) {
303 ret &= tldap_add_mod_blobs(mem_ctx, pmods, TLDAP_MOD_REPLACE,
304 "unicodePwd", 1, &blob);
307 blob = data_blob_const(pdb_get_lanman_passwd(sam), NT_HASH_LEN);
308 if (blob.data != NULL) {
309 ret &= tldap_add_mod_blobs(mem_ctx, pmods, TLDAP_MOD_REPLACE,
310 "dBCSPwd", 1, &blob);
313 ret &= tldap_make_mod_fmt(
314 existing, mem_ctx, pnum_mods, pmods, "userAccountControl",
315 "%d", ds_acb2uf(pdb_get_acct_ctrl(sam)));
317 ret &= tldap_make_mod_fmt(
318 existing, mem_ctx, pnum_mods, pmods, "homeDirectory",
319 "%s", pdb_get_homedir(sam));
321 ret &= tldap_make_mod_fmt(
322 existing, mem_ctx, pnum_mods, pmods, "homeDrive",
323 "%s", pdb_get_dir_drive(sam));
325 ret &= tldap_make_mod_fmt(
326 existing, mem_ctx, pnum_mods, pmods, "scriptPath",
327 "%s", pdb_get_logon_script(sam));
329 ret &= tldap_make_mod_fmt(
330 existing, mem_ctx, pnum_mods, pmods, "profilePath",
331 "%s", pdb_get_profile_path(sam));
333 return ret;
336 static NTSTATUS pdb_ads_getsamupriv(struct pdb_ads_state *state,
337 const char *filter,
338 TALLOC_CTX *mem_ctx,
339 struct pdb_ads_samu_private **presult)
341 const char * attrs[] = {
342 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
343 "sAMAccountName", "displayName", "homeDirectory",
344 "homeDrive", "scriptPath", "profilePath", "description",
345 "userWorkstations", "comment", "userParameters", "objectSid",
346 "primaryGroupID", "userAccountControl", "logonHours",
347 "badPwdCount", "logonCount", "countryCode", "codePage",
348 "unicodePwd", "dBCSPwd" };
349 struct tldap_message **users;
350 int rc, count;
351 struct pdb_ads_samu_private *result;
353 result = talloc(mem_ctx, struct pdb_ads_samu_private);
354 if (result == NULL) {
355 return NT_STATUS_NO_MEMORY;
358 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
359 attrs, ARRAY_SIZE(attrs), 0, result,
360 &users, "%s", filter);
361 if (rc != TLDAP_SUCCESS) {
362 DEBUG(10, ("ldap_search failed %s\n",
363 tldap_errstr(talloc_tos(), state->ld, rc)));
364 TALLOC_FREE(result);
365 return NT_STATUS_LDAP(rc);
368 count = talloc_array_length(users);
369 if (count != 1) {
370 DEBUG(10, ("Expected 1 user, got %d\n", count));
371 TALLOC_FREE(result);
372 return NT_STATUS_INTERNAL_DB_CORRUPTION;
375 result->ldapmsg = users[0];
376 if (!tldap_entry_dn(result->ldapmsg, &result->dn)) {
377 DEBUG(10, ("Could not extract dn\n"));
378 TALLOC_FREE(result);
379 return NT_STATUS_INTERNAL_DB_CORRUPTION;
382 *presult = result;
383 return NT_STATUS_OK;
386 static NTSTATUS pdb_ads_getsampwfilter(struct pdb_methods *m,
387 struct pdb_ads_state *state,
388 struct samu *sam_acct,
389 const char *filter)
391 struct pdb_ads_samu_private *priv;
392 NTSTATUS status;
394 status = pdb_ads_getsamupriv(state, filter, sam_acct, &priv);
395 if (!NT_STATUS_IS_OK(status)) {
396 DEBUG(10, ("pdb_ads_getsamupriv failed: %s\n",
397 nt_errstr(status)));
398 return status;
401 status = pdb_ads_init_sam_from_priv(m, sam_acct, priv);
402 if (!NT_STATUS_IS_OK(status)) {
403 DEBUG(10, ("pdb_ads_init_sam_from_priv failed: %s\n",
404 nt_errstr(status)));
405 TALLOC_FREE(priv);
406 return status;
409 pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
410 return NT_STATUS_OK;
413 static NTSTATUS pdb_ads_getsampwnam(struct pdb_methods *m,
414 struct samu *sam_acct,
415 const char *username)
417 struct pdb_ads_state *state = talloc_get_type_abort(
418 m->private_data, struct pdb_ads_state);
419 char *filter;
421 filter = talloc_asprintf(
422 talloc_tos(), "(&(samaccountname=%s)(objectclass=user))",
423 username);
424 NT_STATUS_HAVE_NO_MEMORY(filter);
426 return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
429 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
430 struct samu *sam_acct,
431 const struct dom_sid *sid)
433 struct pdb_ads_state *state = talloc_get_type_abort(
434 m->private_data, struct pdb_ads_state);
435 char *sidstr, *filter;
437 sidstr = sid_binstring(talloc_tos(), sid);
438 NT_STATUS_HAVE_NO_MEMORY(sidstr);
440 filter = talloc_asprintf(
441 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
442 TALLOC_FREE(sidstr);
443 NT_STATUS_HAVE_NO_MEMORY(filter);
445 return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
448 static NTSTATUS pdb_ads_create_user(struct pdb_methods *m,
449 TALLOC_CTX *tmp_ctx,
450 const char *name, uint32 acct_flags,
451 uint32 *rid)
453 struct pdb_ads_state *state = talloc_get_type_abort(
454 m->private_data, struct pdb_ads_state);
455 struct tldap_context *ld;
456 const char *attrs[1] = { "objectSid" };
457 struct tldap_mod *mods = NULL;
458 int num_mods = 0;
459 struct tldap_message **user;
460 struct dom_sid sid;
461 char *dn;
462 int rc;
463 bool ok;
465 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
466 state->domaindn);
467 if (dn == NULL) {
468 return NT_STATUS_NO_MEMORY;
471 ld = pdb_ads_ld(state);
472 if (ld == NULL) {
473 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
476 /* TODO: Create machines etc */
478 ok = true;
479 ok &= tldap_make_mod_fmt(
480 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "user");
481 ok &= tldap_make_mod_fmt(
482 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
483 name);
484 if (!ok) {
485 return NT_STATUS_NO_MEMORY;
489 rc = tldap_add(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
490 if (rc != TLDAP_SUCCESS) {
491 DEBUG(10, ("ldap_add failed %s\n",
492 tldap_errstr(talloc_tos(), ld, rc)));
493 TALLOC_FREE(dn);
494 return NT_STATUS_LDAP(rc);
497 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
498 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
499 &user,
500 "(&(objectclass=user)(samaccountname=%s))",
501 name);
502 if (rc != TLDAP_SUCCESS) {
503 DEBUG(10, ("Could not find just created user %s: %s\n",
504 name, tldap_errstr(talloc_tos(), state->ld, rc)));
505 TALLOC_FREE(dn);
506 return NT_STATUS_LDAP(rc);
509 if (talloc_array_length(user) != 1) {
510 DEBUG(10, ("Got %d users, expected one\n",
511 (int)talloc_array_length(user)));
512 TALLOC_FREE(dn);
513 return NT_STATUS_LDAP(rc);
516 if (!tldap_pull_binsid(user[0], "objectSid", &sid)) {
517 DEBUG(10, ("Could not fetch objectSid from user %s\n",
518 name));
519 TALLOC_FREE(dn);
520 return NT_STATUS_INTERNAL_DB_CORRUPTION;
523 sid_peek_rid(&sid, rid);
524 TALLOC_FREE(dn);
525 return NT_STATUS_OK;
528 static NTSTATUS pdb_ads_delete_user(struct pdb_methods *m,
529 TALLOC_CTX *tmp_ctx,
530 struct samu *sam)
532 struct pdb_ads_state *state = talloc_get_type_abort(
533 m->private_data, struct pdb_ads_state);
534 NTSTATUS status;
535 struct tldap_context *ld;
536 char *dn;
537 int rc;
539 ld = pdb_ads_ld(state);
540 if (ld == NULL) {
541 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
544 status = pdb_ads_sid2dn(state, pdb_get_user_sid(sam), talloc_tos(),
545 &dn);
546 if (!NT_STATUS_IS_OK(status)) {
547 return status;
550 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
551 TALLOC_FREE(dn);
552 if (rc != TLDAP_SUCCESS) {
553 DEBUG(10, ("ldap_delete for %s failed: %s\n", dn,
554 tldap_errstr(talloc_tos(), ld, rc)));
555 return NT_STATUS_LDAP(rc);
557 return NT_STATUS_OK;
560 static NTSTATUS pdb_ads_add_sam_account(struct pdb_methods *m,
561 struct samu *sampass)
563 return NT_STATUS_NOT_IMPLEMENTED;
566 static NTSTATUS pdb_ads_update_sam_account(struct pdb_methods *m,
567 struct samu *sam)
569 struct pdb_ads_state *state = talloc_get_type_abort(
570 m->private_data, struct pdb_ads_state);
571 struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam);
572 struct tldap_context *ld;
573 struct tldap_mod *mods = NULL;
574 int rc, num_mods = 0;
576 ld = pdb_ads_ld(state);
577 if (ld == NULL) {
578 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
581 if (!pdb_ads_init_ads_from_sam(state, priv->ldapmsg, talloc_tos(),
582 &num_mods, &mods, sam)) {
583 return NT_STATUS_NO_MEMORY;
586 if (num_mods == 0) {
587 /* Nothing to do, just return success */
588 return NT_STATUS_OK;
591 rc = tldap_modify(ld, priv->dn, num_mods, mods, NULL, 0,
592 NULL, 0);
593 TALLOC_FREE(mods);
594 if (rc != TLDAP_SUCCESS) {
595 DEBUG(10, ("ldap_modify for %s failed: %s\n", priv->dn,
596 tldap_errstr(talloc_tos(), ld, rc)));
597 return NT_STATUS_LDAP(rc);
600 return NT_STATUS_OK;
603 static NTSTATUS pdb_ads_delete_sam_account(struct pdb_methods *m,
604 struct samu *username)
606 return NT_STATUS_NOT_IMPLEMENTED;
609 static NTSTATUS pdb_ads_rename_sam_account(struct pdb_methods *m,
610 struct samu *oldname,
611 const char *newname)
613 return NT_STATUS_NOT_IMPLEMENTED;
616 static NTSTATUS pdb_ads_update_login_attempts(struct pdb_methods *m,
617 struct samu *sam_acct,
618 bool success)
620 return NT_STATUS_NOT_IMPLEMENTED;
623 static NTSTATUS pdb_ads_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
624 const char *filter)
626 struct pdb_ads_state *state = talloc_get_type_abort(
627 m->private_data, struct pdb_ads_state);
628 const char *attrs[4] = { "objectSid", "description", "samAccountName",
629 "groupType" };
630 char *str;
631 struct tldap_message **group;
632 uint32_t grouptype;
633 int rc;
635 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
636 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
637 &group, "%s", filter);
638 if (rc != TLDAP_SUCCESS) {
639 DEBUG(10, ("ldap_search failed %s\n",
640 tldap_errstr(talloc_tos(), state->ld, rc)));
641 return NT_STATUS_LDAP(rc);
643 if (talloc_array_length(group) != 1) {
644 DEBUG(10, ("Expected 1 user, got %d\n",
645 (int)talloc_array_length(group)));
646 return NT_STATUS_INTERNAL_DB_CORRUPTION;
649 if (!tldap_pull_binsid(group[0], "objectSid", &map->sid)) {
650 return NT_STATUS_INTERNAL_DB_CORRUPTION;
652 map->gid = pdb_ads_sid2gid(&map->sid);
654 if (!tldap_pull_uint32(group[0], "groupType", &grouptype)) {
655 return NT_STATUS_INTERNAL_DB_CORRUPTION;
657 switch (grouptype) {
658 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
659 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
660 map->sid_name_use = SID_NAME_ALIAS;
661 break;
662 case GTYPE_SECURITY_GLOBAL_GROUP:
663 map->sid_name_use = SID_NAME_DOM_GRP;
664 break;
665 default:
666 return NT_STATUS_INTERNAL_DB_CORRUPTION;
669 str = tldap_talloc_single_attribute(group[0], "samAccountName",
670 talloc_tos());
671 if (str == NULL) {
672 return NT_STATUS_INTERNAL_DB_CORRUPTION;
674 fstrcpy(map->nt_name, str);
675 TALLOC_FREE(str);
677 str = tldap_talloc_single_attribute(group[0], "description",
678 talloc_tos());
679 if (str != NULL) {
680 fstrcpy(map->comment, str);
681 TALLOC_FREE(str);
682 } else {
683 map->comment[0] = '\0';
686 TALLOC_FREE(group);
687 return NT_STATUS_OK;
690 static NTSTATUS pdb_ads_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
691 struct dom_sid sid)
693 char *filter;
694 NTSTATUS status;
696 filter = talloc_asprintf(talloc_tos(),
697 "(&(objectsid=%s)(objectclass=group))",
698 sid_string_talloc(talloc_tos(), &sid));
699 if (filter == NULL) {
700 return NT_STATUS_NO_MEMORY;
703 status = pdb_ads_getgrfilter(m, map, filter);
704 TALLOC_FREE(filter);
705 return status;
708 static NTSTATUS pdb_ads_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
709 gid_t gid)
711 struct dom_sid sid;
712 pdb_ads_gid_to_sid(m, gid, &sid);
713 return pdb_ads_getgrsid(m, map, sid);
716 static NTSTATUS pdb_ads_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
717 const char *name)
719 char *filter;
720 NTSTATUS status;
722 filter = talloc_asprintf(talloc_tos(),
723 "(&(samaccountname=%s)(objectclass=group))",
724 name);
725 if (filter == NULL) {
726 return NT_STATUS_NO_MEMORY;
729 status = pdb_ads_getgrfilter(m, map, filter);
730 TALLOC_FREE(filter);
731 return status;
734 static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m,
735 TALLOC_CTX *mem_ctx, const char *name,
736 uint32 *rid)
738 TALLOC_CTX *frame = talloc_stackframe();
739 struct pdb_ads_state *state = talloc_get_type_abort(
740 m->private_data, struct pdb_ads_state);
741 struct tldap_context *ld;
742 const char *attrs[1] = { "objectSid" };
743 int num_mods = 0;
744 struct tldap_mod *mods = NULL;
745 struct tldap_message **alias;
746 struct dom_sid sid;
747 char *dn;
748 int rc;
749 bool ok = true;
751 ld = pdb_ads_ld(state);
752 if (ld == NULL) {
753 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
756 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
757 state->domaindn);
758 if (dn == NULL) {
759 TALLOC_FREE(frame);
760 return NT_STATUS_NO_MEMORY;
763 ok &= tldap_make_mod_fmt(
764 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
765 name);
766 ok &= tldap_make_mod_fmt(
767 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "group");
768 ok &= tldap_make_mod_fmt(
769 NULL, talloc_tos(), &num_mods, &mods, "groupType",
770 "%d", (int)GTYPE_SECURITY_GLOBAL_GROUP);
772 if (!ok) {
773 TALLOC_FREE(frame);
774 return NT_STATUS_NO_MEMORY;
777 rc = tldap_add(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
778 if (rc != TLDAP_SUCCESS) {
779 DEBUG(10, ("ldap_add failed %s\n",
780 tldap_errstr(talloc_tos(), state->ld, rc)));
781 TALLOC_FREE(frame);
782 return NT_STATUS_LDAP(rc);
785 rc = pdb_ads_search_fmt(
786 state, state->domaindn, TLDAP_SCOPE_SUB,
787 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
788 "(&(objectclass=group)(samaccountname=%s))", name);
789 if (rc != TLDAP_SUCCESS) {
790 DEBUG(10, ("Could not find just created alias %s: %s\n",
791 name, tldap_errstr(talloc_tos(), state->ld, rc)));
792 TALLOC_FREE(frame);
793 return NT_STATUS_LDAP(rc);
796 if (talloc_array_length(alias) != 1) {
797 DEBUG(10, ("Got %d alias, expected one\n",
798 (int)talloc_array_length(alias)));
799 TALLOC_FREE(frame);
800 return NT_STATUS_LDAP(rc);
803 if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
804 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
805 name));
806 TALLOC_FREE(frame);
807 return NT_STATUS_INTERNAL_DB_CORRUPTION;
810 sid_peek_rid(&sid, rid);
811 TALLOC_FREE(frame);
812 return NT_STATUS_OK;
815 static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m,
816 TALLOC_CTX *mem_ctx, uint32 rid)
818 struct pdb_ads_state *state = talloc_get_type_abort(
819 m->private_data, struct pdb_ads_state);
820 struct tldap_context *ld;
821 struct dom_sid sid;
822 char *sidstr;
823 struct tldap_message **msg;
824 char *dn;
825 int rc;
827 sid_compose(&sid, &state->domainsid, rid);
829 sidstr = sid_binstring(talloc_tos(), &sid);
830 NT_STATUS_HAVE_NO_MEMORY(sidstr);
832 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
833 NULL, 0, 0, talloc_tos(), &msg,
834 ("(&(objectSid=%s)(objectClass=group))"),
835 sidstr);
836 TALLOC_FREE(sidstr);
837 if (rc != TLDAP_SUCCESS) {
838 DEBUG(10, ("ldap_search failed %s\n",
839 tldap_errstr(talloc_tos(), state->ld, rc)));
840 return NT_STATUS_LDAP(rc);
843 switch talloc_array_length(msg) {
844 case 0:
845 return NT_STATUS_NO_SUCH_GROUP;
846 case 1:
847 break;
848 default:
849 return NT_STATUS_INTERNAL_DB_CORRUPTION;
852 if (!tldap_entry_dn(msg[0], &dn)) {
853 TALLOC_FREE(msg);
854 return NT_STATUS_INTERNAL_DB_CORRUPTION;
857 ld = pdb_ads_ld(state);
858 if (ld == NULL) {
859 TALLOC_FREE(msg);
860 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
863 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
864 TALLOC_FREE(msg);
865 if (rc != TLDAP_SUCCESS) {
866 DEBUG(10, ("ldap_delete failed: %s\n",
867 tldap_errstr(talloc_tos(), state->ld, rc)));
868 return NT_STATUS_LDAP(rc);
871 return NT_STATUS_OK;
874 static NTSTATUS pdb_ads_add_group_mapping_entry(struct pdb_methods *m,
875 GROUP_MAP *map)
877 return NT_STATUS_NOT_IMPLEMENTED;
880 static NTSTATUS pdb_ads_update_group_mapping_entry(struct pdb_methods *m,
881 GROUP_MAP *map)
883 return NT_STATUS_NOT_IMPLEMENTED;
886 static NTSTATUS pdb_ads_delete_group_mapping_entry(struct pdb_methods *m,
887 struct dom_sid sid)
889 return NT_STATUS_NOT_IMPLEMENTED;
892 static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m,
893 const struct dom_sid *sid,
894 enum lsa_SidType sid_name_use,
895 GROUP_MAP **pp_rmap,
896 size_t *p_num_entries,
897 bool unix_only)
899 return NT_STATUS_NOT_IMPLEMENTED;
902 static NTSTATUS pdb_ads_enum_group_members(struct pdb_methods *m,
903 TALLOC_CTX *mem_ctx,
904 const struct dom_sid *group,
905 uint32 **pmembers,
906 size_t *pnum_members)
908 struct pdb_ads_state *state = talloc_get_type_abort(
909 m->private_data, struct pdb_ads_state);
910 const char *attrs[1] = { "member" };
911 char *sidstr;
912 struct tldap_message **msg;
913 int i, rc, num_members;
914 DATA_BLOB *blobs;
915 uint32_t *members;
917 sidstr = sid_binstring(talloc_tos(), group);
918 NT_STATUS_HAVE_NO_MEMORY(sidstr);
920 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
921 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
922 &msg, "(objectsid=%s)", sidstr);
923 TALLOC_FREE(sidstr);
924 if (rc != TLDAP_SUCCESS) {
925 DEBUG(10, ("ldap_search failed %s\n",
926 tldap_errstr(talloc_tos(), state->ld, rc)));
927 return NT_STATUS_LDAP(rc);
929 switch talloc_array_length(msg) {
930 case 0:
931 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
932 break;
933 case 1:
934 break;
935 default:
936 return NT_STATUS_INTERNAL_DB_CORRUPTION;
937 break;
940 if (!tldap_entry_values(msg[0], "member", &num_members, &blobs)) {
941 return NT_STATUS_INTERNAL_DB_CORRUPTION;
944 members = talloc_array(mem_ctx, uint32_t, num_members);
945 if (members == NULL) {
946 return NT_STATUS_NO_MEMORY;
949 for (i=0; i<num_members; i++) {
950 struct dom_sid sid;
951 if (!pdb_ads_dnblob2sid(state, &blobs[i], &sid)
952 || !sid_peek_rid(&sid, &members[i])) {
953 TALLOC_FREE(members);
954 return NT_STATUS_INTERNAL_DB_CORRUPTION;
958 *pmembers = members;
959 *pnum_members = num_members;
960 return NT_STATUS_OK;
963 static NTSTATUS pdb_ads_enum_group_memberships(struct pdb_methods *m,
964 TALLOC_CTX *mem_ctx,
965 struct samu *user,
966 struct dom_sid **pp_sids,
967 gid_t **pp_gids,
968 size_t *p_num_groups)
970 struct pdb_ads_state *state = talloc_get_type_abort(
971 m->private_data, struct pdb_ads_state);
972 struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(
973 m, user);
974 const char *attrs[1] = { "objectSid" };
975 struct tldap_message **groups;
976 int i, rc, count;
977 size_t num_groups;
978 struct dom_sid *group_sids;
979 gid_t *gids;
981 rc = pdb_ads_search_fmt(
982 state, state->domaindn, TLDAP_SCOPE_SUB,
983 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &groups,
984 "(&(member=%s)(grouptype=%d)(objectclass=group))",
985 priv->dn, GTYPE_SECURITY_GLOBAL_GROUP);
986 if (rc != TLDAP_SUCCESS) {
987 DEBUG(10, ("ldap_search failed %s\n",
988 tldap_errstr(talloc_tos(), state->ld, rc)));
989 return NT_STATUS_LDAP(rc);
992 count = talloc_array_length(groups);
994 group_sids = talloc_array(mem_ctx, struct dom_sid, count);
995 if (group_sids == NULL) {
996 return NT_STATUS_NO_MEMORY;
998 gids = talloc_array(mem_ctx, gid_t, count);
999 if (gids == NULL) {
1000 TALLOC_FREE(group_sids);
1001 return NT_STATUS_NO_MEMORY;
1003 num_groups = 0;
1005 for (i=0; i<count; i++) {
1006 if (!tldap_pull_binsid(groups[i], "objectSid",
1007 &group_sids[num_groups])) {
1008 continue;
1010 gids[num_groups] = pdb_ads_sid2gid(&group_sids[num_groups]);
1012 num_groups += 1;
1013 if (num_groups == count) {
1014 break;
1018 *pp_sids = group_sids;
1019 *pp_gids = gids;
1020 *p_num_groups = num_groups;
1021 return NT_STATUS_OK;
1024 static NTSTATUS pdb_ads_set_unix_primary_group(struct pdb_methods *m,
1025 TALLOC_CTX *mem_ctx,
1026 struct samu *user)
1028 return NT_STATUS_NOT_IMPLEMENTED;
1031 static NTSTATUS pdb_ads_mod_groupmem(struct pdb_methods *m,
1032 TALLOC_CTX *mem_ctx,
1033 uint32 grouprid, uint32 memberrid,
1034 int mod_op)
1036 struct pdb_ads_state *state = talloc_get_type_abort(
1037 m->private_data, struct pdb_ads_state);
1038 TALLOC_CTX *frame = talloc_stackframe();
1039 struct tldap_context *ld;
1040 struct dom_sid groupsid, membersid;
1041 char *groupdn, *memberdn;
1042 struct tldap_mod *mods;
1043 int rc;
1044 NTSTATUS status;
1046 ld = pdb_ads_ld(state);
1047 if (ld == NULL) {
1048 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1051 sid_compose(&groupsid, &state->domainsid, grouprid);
1052 sid_compose(&membersid, &state->domainsid, memberrid);
1054 status = pdb_ads_sid2dn(state, &groupsid, talloc_tos(), &groupdn);
1055 if (!NT_STATUS_IS_OK(status)) {
1056 TALLOC_FREE(frame);
1057 return NT_STATUS_NO_SUCH_GROUP;
1059 status = pdb_ads_sid2dn(state, &membersid, talloc_tos(), &memberdn);
1060 if (!NT_STATUS_IS_OK(status)) {
1061 TALLOC_FREE(frame);
1062 return NT_STATUS_NO_SUCH_USER;
1065 mods = NULL;
1067 if (!tldap_add_mod_str(talloc_tos(), &mods, mod_op,
1068 "member", memberdn)) {
1069 TALLOC_FREE(frame);
1070 return NT_STATUS_NO_MEMORY;
1073 rc = tldap_modify(ld, groupdn, 1, mods, NULL, 0, NULL, 0);
1074 TALLOC_FREE(frame);
1075 if (rc != TLDAP_SUCCESS) {
1076 DEBUG(10, ("ldap_modify failed: %s\n",
1077 tldap_errstr(talloc_tos(), state->ld, rc)));
1078 if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) {
1079 return NT_STATUS_MEMBER_IN_GROUP;
1081 if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
1082 return NT_STATUS_MEMBER_NOT_IN_GROUP;
1084 return NT_STATUS_LDAP(rc);
1087 return NT_STATUS_OK;
1090 static NTSTATUS pdb_ads_add_groupmem(struct pdb_methods *m,
1091 TALLOC_CTX *mem_ctx,
1092 uint32 group_rid, uint32 member_rid)
1094 return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1095 TLDAP_MOD_ADD);
1098 static NTSTATUS pdb_ads_del_groupmem(struct pdb_methods *m,
1099 TALLOC_CTX *mem_ctx,
1100 uint32 group_rid, uint32 member_rid)
1102 return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1103 TLDAP_MOD_DELETE);
1106 static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m,
1107 const char *name, uint32 *rid)
1109 TALLOC_CTX *frame = talloc_stackframe();
1110 struct pdb_ads_state *state = talloc_get_type_abort(
1111 m->private_data, struct pdb_ads_state);
1112 struct tldap_context *ld;
1113 const char *attrs[1] = { "objectSid" };
1114 int num_mods = 0;
1115 struct tldap_mod *mods = NULL;
1116 struct tldap_message **alias;
1117 struct dom_sid sid;
1118 char *dn;
1119 int rc;
1120 bool ok = true;
1122 ld = pdb_ads_ld(state);
1123 if (ld == NULL) {
1124 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1127 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
1128 state->domaindn);
1129 if (dn == NULL) {
1130 TALLOC_FREE(frame);
1131 return NT_STATUS_NO_MEMORY;
1134 ok &= tldap_make_mod_fmt(
1135 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
1136 name);
1137 ok &= tldap_make_mod_fmt(
1138 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "group");
1139 ok &= tldap_make_mod_fmt(
1140 NULL, talloc_tos(), &num_mods, &mods, "groupType",
1141 "%d", (int)GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1143 if (!ok) {
1144 TALLOC_FREE(frame);
1145 return NT_STATUS_NO_MEMORY;
1148 rc = tldap_add(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
1149 if (rc != TLDAP_SUCCESS) {
1150 DEBUG(10, ("ldap_add failed %s\n",
1151 tldap_errstr(talloc_tos(), state->ld, rc)));
1152 TALLOC_FREE(frame);
1153 return NT_STATUS_LDAP(rc);
1156 rc = pdb_ads_search_fmt(
1157 state, state->domaindn, TLDAP_SCOPE_SUB,
1158 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
1159 "(&(objectclass=group)(samaccountname=%s))", name);
1160 if (rc != TLDAP_SUCCESS) {
1161 DEBUG(10, ("Could not find just created alias %s: %s\n",
1162 name, tldap_errstr(talloc_tos(), state->ld, rc)));
1163 TALLOC_FREE(frame);
1164 return NT_STATUS_LDAP(rc);
1167 if (talloc_array_length(alias) != 1) {
1168 DEBUG(10, ("Got %d alias, expected one\n",
1169 (int)talloc_array_length(alias)));
1170 TALLOC_FREE(frame);
1171 return NT_STATUS_LDAP(rc);
1174 if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
1175 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
1176 name));
1177 TALLOC_FREE(frame);
1178 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1181 sid_peek_rid(&sid, rid);
1182 TALLOC_FREE(frame);
1183 return NT_STATUS_OK;
1186 static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m,
1187 const struct dom_sid *sid)
1189 struct pdb_ads_state *state = talloc_get_type_abort(
1190 m->private_data, struct pdb_ads_state);
1191 struct tldap_context *ld;
1192 struct tldap_message **alias;
1193 char *sidstr, *dn;
1194 int rc;
1196 ld = pdb_ads_ld(state);
1197 if (ld == NULL) {
1198 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1201 sidstr = sid_binstring(talloc_tos(), sid);
1202 if (sidstr == NULL) {
1203 return NT_STATUS_NO_MEMORY;
1206 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1207 NULL, 0, 0, talloc_tos(), &alias,
1208 "(&(objectSid=%s)(objectclass=group)"
1209 "(|(grouptype=%d)(grouptype=%d)))",
1210 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1211 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1212 TALLOC_FREE(sidstr);
1213 if (rc != TLDAP_SUCCESS) {
1214 DEBUG(10, ("ldap_search failed: %s\n",
1215 tldap_errstr(talloc_tos(), state->ld, rc)));
1216 TALLOC_FREE(dn);
1217 return NT_STATUS_LDAP(rc);
1219 if (talloc_array_length(alias) != 1) {
1220 DEBUG(10, ("Expected 1 alias, got %d\n",
1221 (int)talloc_array_length(alias)));
1222 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1224 if (!tldap_entry_dn(alias[0], &dn)) {
1225 DEBUG(10, ("Could not get DN for alias %s\n",
1226 sid_string_dbg(sid)));
1227 return NT_STATUS_INTERNAL_ERROR;
1230 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
1231 if (rc != TLDAP_SUCCESS) {
1232 DEBUG(10, ("ldap_delete failed: %s\n",
1233 tldap_errstr(talloc_tos(), state->ld, rc)));
1234 TALLOC_FREE(dn);
1235 return NT_STATUS_LDAP(rc);
1238 return NT_STATUS_OK;
1241 static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m,
1242 const struct dom_sid *sid,
1243 struct acct_info *info)
1245 struct pdb_ads_state *state = talloc_get_type_abort(
1246 m->private_data, struct pdb_ads_state);
1247 struct tldap_context *ld;
1248 const char *attrs[3] = { "objectSid", "description",
1249 "samAccountName" };
1250 struct tldap_message **msg;
1251 char *sidstr, *dn;
1252 int rc;
1253 struct tldap_mod *mods;
1254 int num_mods;
1255 bool ok;
1257 ld = pdb_ads_ld(state);
1258 if (ld == NULL) {
1259 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1262 sidstr = sid_binstring(talloc_tos(), sid);
1263 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1265 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1266 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1267 &msg, "(&(objectSid=%s)(objectclass=group)"
1268 "(|(grouptype=%d)(grouptype=%d)))",
1269 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1270 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1271 TALLOC_FREE(sidstr);
1272 if (rc != TLDAP_SUCCESS) {
1273 DEBUG(10, ("ldap_search failed %s\n",
1274 tldap_errstr(talloc_tos(), state->ld, rc)));
1275 return NT_STATUS_LDAP(rc);
1277 switch talloc_array_length(msg) {
1278 case 0:
1279 return NT_STATUS_NO_SUCH_ALIAS;
1280 case 1:
1281 break;
1282 default:
1283 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1286 if (!tldap_entry_dn(msg[0], &dn)) {
1287 TALLOC_FREE(msg);
1288 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1291 mods = NULL;
1292 num_mods = 0;
1293 ok = true;
1295 ok &= tldap_make_mod_fmt(
1296 msg[0], msg, &num_mods, &mods, "description",
1297 "%s", info->acct_desc);
1298 ok &= tldap_make_mod_fmt(
1299 msg[0], msg, &num_mods, &mods, "samAccountName",
1300 "%s", info->acct_name);
1301 if (!ok) {
1302 TALLOC_FREE(msg);
1303 return NT_STATUS_NO_MEMORY;
1305 if (num_mods == 0) {
1306 /* no change */
1307 TALLOC_FREE(msg);
1308 return NT_STATUS_OK;
1311 rc = tldap_modify(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
1312 TALLOC_FREE(msg);
1313 if (rc != TLDAP_SUCCESS) {
1314 DEBUG(10, ("ldap_modify failed: %s\n",
1315 tldap_errstr(talloc_tos(), state->ld, rc)));
1316 return NT_STATUS_LDAP(rc);
1318 return NT_STATUS_OK;
1321 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
1322 const struct dom_sid *sid,
1323 TALLOC_CTX *mem_ctx, char **pdn)
1325 struct tldap_message **msg;
1326 char *sidstr, *dn;
1327 int rc;
1329 sidstr = sid_binstring(talloc_tos(), sid);
1330 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1332 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1333 NULL, 0, 0, talloc_tos(), &msg,
1334 "(objectsid=%s)", sidstr);
1335 TALLOC_FREE(sidstr);
1336 if (rc != TLDAP_SUCCESS) {
1337 DEBUG(10, ("ldap_search failed %s\n",
1338 tldap_errstr(talloc_tos(), state->ld, rc)));
1339 return NT_STATUS_LDAP(rc);
1342 switch talloc_array_length(msg) {
1343 case 0:
1344 return NT_STATUS_NOT_FOUND;
1345 case 1:
1346 break;
1347 default:
1348 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1351 if (!tldap_entry_dn(msg[0], &dn)) {
1352 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1355 dn = talloc_strdup(mem_ctx, dn);
1356 if (dn == NULL) {
1357 return NT_STATUS_NO_MEMORY;
1359 TALLOC_FREE(msg);
1361 *pdn = dn;
1362 return NT_STATUS_OK;
1365 static NTSTATUS pdb_ads_mod_aliasmem(struct pdb_methods *m,
1366 const struct dom_sid *alias,
1367 const struct dom_sid *member,
1368 int mod_op)
1370 struct pdb_ads_state *state = talloc_get_type_abort(
1371 m->private_data, struct pdb_ads_state);
1372 struct tldap_context *ld;
1373 TALLOC_CTX *frame = talloc_stackframe();
1374 struct tldap_mod *mods;
1375 int rc;
1376 char *aliasdn, *memberdn;
1377 NTSTATUS status;
1379 ld = pdb_ads_ld(state);
1380 if (ld == NULL) {
1381 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1384 status = pdb_ads_sid2dn(state, alias, talloc_tos(), &aliasdn);
1385 if (!NT_STATUS_IS_OK(status)) {
1386 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1387 sid_string_dbg(alias), nt_errstr(status)));
1388 TALLOC_FREE(frame);
1389 return NT_STATUS_NO_SUCH_ALIAS;
1391 status = pdb_ads_sid2dn(state, member, talloc_tos(), &memberdn);
1392 if (!NT_STATUS_IS_OK(status)) {
1393 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1394 sid_string_dbg(member), nt_errstr(status)));
1395 TALLOC_FREE(frame);
1396 return status;
1399 mods = NULL;
1401 if (!tldap_add_mod_str(talloc_tos(), &mods, mod_op,
1402 "member", memberdn)) {
1403 TALLOC_FREE(frame);
1404 return NT_STATUS_NO_MEMORY;
1407 rc = tldap_modify(ld, aliasdn, 1, mods, NULL, 0, NULL, 0);
1408 TALLOC_FREE(frame);
1409 if (rc != TLDAP_SUCCESS) {
1410 DEBUG(10, ("ldap_modify failed: %s\n",
1411 tldap_errstr(talloc_tos(), state->ld, rc)));
1412 if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) {
1413 return NT_STATUS_MEMBER_IN_ALIAS;
1415 if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
1416 return NT_STATUS_MEMBER_NOT_IN_ALIAS;
1418 return NT_STATUS_LDAP(rc);
1421 return NT_STATUS_OK;
1424 static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
1425 const struct dom_sid *alias,
1426 const struct dom_sid *member)
1428 return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_ADD);
1431 static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
1432 const struct dom_sid *alias,
1433 const struct dom_sid *member)
1435 return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_DELETE);
1438 static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
1439 struct dom_sid *psid)
1441 const char *attrs[1] = { "objectSid" };
1442 struct tldap_message **msg;
1443 char *dn;
1444 size_t len;
1445 int rc;
1446 bool ret;
1448 if (!convert_string_talloc(talloc_tos(), CH_UTF8, CH_UNIX,
1449 dnblob->data, dnblob->length, &dn, &len,
1450 false)) {
1451 return false;
1453 rc = pdb_ads_search_fmt(state, dn, TLDAP_SCOPE_BASE,
1454 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1455 &msg, "(objectclass=*)");
1456 TALLOC_FREE(dn);
1457 if (talloc_array_length(msg) != 1) {
1458 DEBUG(10, ("Got %d objects, expected one\n",
1459 (int)talloc_array_length(msg)));
1460 TALLOC_FREE(msg);
1461 return false;
1464 ret = tldap_pull_binsid(msg[0], "objectSid", psid);
1465 TALLOC_FREE(msg);
1466 return ret;
1469 static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
1470 const struct dom_sid *alias,
1471 TALLOC_CTX *mem_ctx,
1472 struct dom_sid **pmembers,
1473 size_t *pnum_members)
1475 struct pdb_ads_state *state = talloc_get_type_abort(
1476 m->private_data, struct pdb_ads_state);
1477 const char *attrs[1] = { "member" };
1478 char *sidstr;
1479 struct tldap_message **msg;
1480 int i, rc, num_members;
1481 DATA_BLOB *blobs;
1482 struct dom_sid *members;
1484 sidstr = sid_binstring(talloc_tos(), alias);
1485 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1487 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1488 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1489 &msg, "(objectsid=%s)", sidstr);
1490 TALLOC_FREE(sidstr);
1491 if (rc != TLDAP_SUCCESS) {
1492 DEBUG(10, ("ldap_search failed %s\n",
1493 tldap_errstr(talloc_tos(), state->ld, rc)));
1494 return NT_STATUS_LDAP(rc);
1496 switch talloc_array_length(msg) {
1497 case 0:
1498 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1499 break;
1500 case 1:
1501 break;
1502 default:
1503 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1504 break;
1507 if (!tldap_entry_values(msg[0], "member", &num_members, &blobs)) {
1508 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1511 members = talloc_array(mem_ctx, struct dom_sid, num_members);
1512 if (members == NULL) {
1513 return NT_STATUS_NO_MEMORY;
1516 for (i=0; i<num_members; i++) {
1517 if (!pdb_ads_dnblob2sid(state, &blobs[i], &members[i])) {
1518 TALLOC_FREE(members);
1519 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1523 *pmembers = members;
1524 *pnum_members = num_members;
1525 return NT_STATUS_OK;
1528 static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,
1529 TALLOC_CTX *mem_ctx,
1530 const struct dom_sid *domain_sid,
1531 const struct dom_sid *members,
1532 size_t num_members,
1533 uint32_t **palias_rids,
1534 size_t *pnum_alias_rids)
1536 struct pdb_ads_state *state = talloc_get_type_abort(
1537 m->private_data, struct pdb_ads_state);
1538 const char *attrs[1] = { "objectSid" };
1539 struct tldap_message **msg;
1540 uint32_t *alias_rids = NULL;
1541 size_t num_alias_rids = 0;
1542 int i, rc, count;
1543 bool got_members = false;
1544 char *filter;
1545 NTSTATUS status;
1548 * TODO: Get the filter right so that we only get the aliases from
1549 * either the SAM or BUILTIN
1552 filter = talloc_asprintf(talloc_tos(),
1553 "(&(|(grouptype=%d)(grouptype=%d))"
1554 "(objectclass=group)(|",
1555 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1556 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1557 if (filter == NULL) {
1558 return NT_STATUS_NO_MEMORY;
1561 for (i=0; i<num_members; i++) {
1562 char *dn;
1564 status = pdb_ads_sid2dn(state, &members[i], talloc_tos(), &dn);
1565 if (!NT_STATUS_IS_OK(status)) {
1566 DEBUG(10, ("pdb_ads_sid2dn failed for %s: %s\n",
1567 sid_string_dbg(&members[i]),
1568 nt_errstr(status)));
1569 continue;
1571 filter = talloc_asprintf_append_buffer(
1572 filter, "(member=%s)", dn);
1573 TALLOC_FREE(dn);
1574 if (filter == NULL) {
1575 return NT_STATUS_NO_MEMORY;
1577 got_members = true;
1580 if (!got_members) {
1581 goto done;
1584 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1585 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1586 &msg, "%s))", filter);
1587 TALLOC_FREE(filter);
1588 if (rc != TLDAP_SUCCESS) {
1589 DEBUG(10, ("tldap_search failed %s\n",
1590 tldap_errstr(talloc_tos(), state->ld, rc)));
1591 return NT_STATUS_LDAP(rc);
1594 count = talloc_array_length(msg);
1595 if (count == 0) {
1596 goto done;
1599 alias_rids = talloc_array(mem_ctx, uint32_t, count);
1600 if (alias_rids == NULL) {
1601 TALLOC_FREE(msg);
1602 return NT_STATUS_NO_MEMORY;
1605 for (i=0; i<count; i++) {
1606 struct dom_sid sid;
1608 if (!tldap_pull_binsid(msg[i], "objectSid", &sid)) {
1609 DEBUG(10, ("Could not pull SID for member %d\n", i));
1610 continue;
1612 if (sid_peek_check_rid(domain_sid, &sid,
1613 &alias_rids[num_alias_rids])) {
1614 num_alias_rids += 1;
1617 done:
1618 TALLOC_FREE(msg);
1619 *palias_rids = alias_rids;
1620 *pnum_alias_rids = 0;
1621 return NT_STATUS_OK;
1624 static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m,
1625 const struct dom_sid *domain_sid,
1626 int num_rids,
1627 uint32 *rids,
1628 const char **names,
1629 enum lsa_SidType *lsa_attrs)
1631 struct pdb_ads_state *state = talloc_get_type_abort(
1632 m->private_data, struct pdb_ads_state);
1633 const char *attrs[2] = { "sAMAccountType", "sAMAccountName" };
1634 int i, num_mapped;
1636 if (num_rids == 0) {
1637 return NT_STATUS_NONE_MAPPED;
1640 num_mapped = 0;
1642 for (i=0; i<num_rids; i++) {
1643 struct dom_sid sid;
1644 struct tldap_message **msg;
1645 char *sidstr;
1646 uint32_t attr;
1647 int rc;
1649 lsa_attrs[i] = SID_NAME_UNKNOWN;
1651 sid_compose(&sid, domain_sid, rids[i]);
1653 sidstr = sid_binstring(talloc_tos(), &sid);
1654 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1656 rc = pdb_ads_search_fmt(state, state->domaindn,
1657 TLDAP_SCOPE_SUB, attrs,
1658 ARRAY_SIZE(attrs), 0, talloc_tos(),
1659 &msg, "(objectsid=%s)", sidstr);
1660 TALLOC_FREE(sidstr);
1661 if (rc != TLDAP_SUCCESS) {
1662 DEBUG(10, ("ldap_search failed %s\n",
1663 tldap_errstr(talloc_tos(), state->ld, rc)));
1664 continue;
1667 switch talloc_array_length(msg) {
1668 case 0:
1669 DEBUG(10, ("rid %d not found\n", (int)rids[i]));
1670 continue;
1671 case 1:
1672 break;
1673 default:
1674 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1677 names[i] = tldap_talloc_single_attribute(
1678 msg[0], "samAccountName", talloc_tos());
1679 if (names[i] == NULL) {
1680 DEBUG(10, ("no samAccountName\n"));
1681 continue;
1683 if (!tldap_pull_uint32(msg[0], "samAccountType", &attr)) {
1684 DEBUG(10, ("no samAccountType"));
1685 continue;
1687 lsa_attrs[i] = ds_atype_map(attr);
1688 num_mapped += 1;
1691 if (num_mapped == 0) {
1692 return NT_STATUS_NONE_MAPPED;
1694 if (num_mapped < num_rids) {
1695 return STATUS_SOME_UNMAPPED;
1697 return NT_STATUS_OK;
1700 static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m,
1701 const struct dom_sid *domain_sid,
1702 int num_names,
1703 const char **pp_names,
1704 uint32 *rids,
1705 enum lsa_SidType *attrs)
1707 return NT_STATUS_NOT_IMPLEMENTED;
1710 static NTSTATUS pdb_ads_get_account_policy(struct pdb_methods *m,
1711 enum pdb_policy_type type,
1712 uint32_t *value)
1714 return account_policy_get(type, value)
1715 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1718 static NTSTATUS pdb_ads_set_account_policy(struct pdb_methods *m,
1719 enum pdb_policy_type type,
1720 uint32_t value)
1722 return account_policy_set(type, value)
1723 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1726 static NTSTATUS pdb_ads_get_seq_num(struct pdb_methods *m,
1727 time_t *seq_num)
1729 return NT_STATUS_NOT_IMPLEMENTED;
1732 struct pdb_ads_search_state {
1733 uint32_t acct_flags;
1734 struct samr_displayentry *entries;
1735 uint32_t num_entries;
1736 ssize_t array_size;
1737 uint32_t current;
1740 static bool pdb_ads_next_entry(struct pdb_search *search,
1741 struct samr_displayentry *entry)
1743 struct pdb_ads_search_state *state = talloc_get_type_abort(
1744 search->private_data, struct pdb_ads_search_state);
1746 if (state->current == state->num_entries) {
1747 return false;
1750 entry->idx = state->entries[state->current].idx;
1751 entry->rid = state->entries[state->current].rid;
1752 entry->acct_flags = state->entries[state->current].acct_flags;
1754 entry->account_name = talloc_strdup(
1755 search, state->entries[state->current].account_name);
1756 entry->fullname = talloc_strdup(
1757 search, state->entries[state->current].fullname);
1758 entry->description = talloc_strdup(
1759 search, state->entries[state->current].description);
1761 if ((entry->account_name == NULL) || (entry->fullname == NULL)
1762 || (entry->description == NULL)) {
1763 DEBUG(0, ("talloc_strdup failed\n"));
1764 return false;
1767 state->current += 1;
1768 return true;
1771 static void pdb_ads_search_end(struct pdb_search *search)
1773 struct pdb_ads_search_state *state = talloc_get_type_abort(
1774 search->private_data, struct pdb_ads_search_state);
1775 TALLOC_FREE(state);
1778 static bool pdb_ads_search_filter(struct pdb_methods *m,
1779 struct pdb_search *search,
1780 const char *filter,
1781 struct pdb_ads_search_state **pstate)
1783 struct pdb_ads_state *state = talloc_get_type_abort(
1784 m->private_data, struct pdb_ads_state);
1785 struct pdb_ads_search_state *sstate;
1786 const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1787 "userAccountControl", "description" };
1788 struct tldap_message **users;
1789 int i, rc, num_users;
1791 sstate = talloc_zero(search, struct pdb_ads_search_state);
1792 if (sstate == NULL) {
1793 return false;
1796 rc = pdb_ads_search_fmt(
1797 state, state->domaindn, TLDAP_SCOPE_SUB,
1798 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &users,
1799 "%s", filter);
1800 if (rc != TLDAP_SUCCESS) {
1801 DEBUG(10, ("ldap_search_ext_s failed: %s\n",
1802 tldap_errstr(talloc_tos(), state->ld, rc)));
1803 return false;
1806 num_users = talloc_array_length(users);
1808 sstate->entries = talloc_array(sstate, struct samr_displayentry,
1809 num_users);
1810 if (sstate->entries == NULL) {
1811 DEBUG(10, ("talloc failed\n"));
1812 return false;
1815 sstate->num_entries = 0;
1817 for (i=0; i<num_users; i++) {
1818 struct samr_displayentry *e;
1819 struct dom_sid sid;
1821 e = &sstate->entries[sstate->num_entries];
1823 e->idx = sstate->num_entries;
1824 if (!tldap_pull_binsid(users[i], "objectSid", &sid)) {
1825 DEBUG(10, ("Could not pull sid\n"));
1826 continue;
1828 sid_peek_rid(&sid, &e->rid);
1829 e->acct_flags = ACB_NORMAL;
1830 e->account_name = tldap_talloc_single_attribute(
1831 users[i], "samAccountName", sstate->entries);
1832 if (e->account_name == NULL) {
1833 return false;
1835 e->fullname = tldap_talloc_single_attribute(
1836 users[i], "displayName", sstate->entries);
1837 if (e->fullname == NULL) {
1838 e->fullname = "";
1840 e->description = tldap_talloc_single_attribute(
1841 users[i], "description", sstate->entries);
1842 if (e->description == NULL) {
1843 e->description = "";
1846 sstate->num_entries += 1;
1847 if (sstate->num_entries >= num_users) {
1848 break;
1852 search->private_data = sstate;
1853 search->next_entry = pdb_ads_next_entry;
1854 search->search_end = pdb_ads_search_end;
1855 *pstate = sstate;
1856 return true;
1859 static bool pdb_ads_search_users(struct pdb_methods *m,
1860 struct pdb_search *search,
1861 uint32 acct_flags)
1863 struct pdb_ads_search_state *sstate;
1864 bool ret;
1866 ret = pdb_ads_search_filter(m, search, "(objectclass=user)", &sstate);
1867 if (!ret) {
1868 return false;
1870 sstate->acct_flags = acct_flags;
1871 return true;
1874 static bool pdb_ads_search_groups(struct pdb_methods *m,
1875 struct pdb_search *search)
1877 struct pdb_ads_search_state *sstate;
1878 char *filter;
1879 bool ret;
1881 filter = talloc_asprintf(talloc_tos(),
1882 "(&(grouptype=%d)(objectclass=group))",
1883 GTYPE_SECURITY_GLOBAL_GROUP);
1884 if (filter == NULL) {
1885 return false;
1887 ret = pdb_ads_search_filter(m, search, filter, &sstate);
1888 TALLOC_FREE(filter);
1889 if (!ret) {
1890 return false;
1892 sstate->acct_flags = 0;
1893 return true;
1896 static bool pdb_ads_search_aliases(struct pdb_methods *m,
1897 struct pdb_search *search,
1898 const struct dom_sid *sid)
1900 struct pdb_ads_search_state *sstate;
1901 char *filter;
1902 bool ret;
1904 filter = talloc_asprintf(
1905 talloc_tos(), "(&(grouptype=%d)(objectclass=group))",
1906 sid_check_is_builtin(sid)
1907 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
1908 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1910 if (filter == NULL) {
1911 return false;
1913 ret = pdb_ads_search_filter(m, search, filter, &sstate);
1914 TALLOC_FREE(filter);
1915 if (!ret) {
1916 return false;
1918 sstate->acct_flags = 0;
1919 return true;
1922 static bool pdb_ads_uid_to_sid(struct pdb_methods *m, uid_t uid,
1923 struct dom_sid *sid)
1925 struct pdb_ads_state *state = talloc_get_type_abort(
1926 m->private_data, struct pdb_ads_state);
1927 sid_compose(sid, &state->domainsid, uid);
1928 return true;
1931 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
1932 struct dom_sid *sid)
1934 struct pdb_ads_state *state = talloc_get_type_abort(
1935 m->private_data, struct pdb_ads_state);
1936 sid_compose(sid, &state->domainsid, gid);
1937 return true;
1940 static bool pdb_ads_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
1941 union unid_t *id, enum lsa_SidType *type)
1943 struct pdb_ads_state *state = talloc_get_type_abort(
1944 m->private_data, struct pdb_ads_state);
1945 struct tldap_message **msg;
1946 char *sidstr;
1947 uint32_t rid;
1948 int rc;
1951 * This is a big, big hack: Just hard-code the rid as uid/gid.
1954 sid_peek_rid(sid, &rid);
1956 sidstr = sid_binstring(talloc_tos(), sid);
1957 if (sidstr == NULL) {
1958 return false;
1961 rc = pdb_ads_search_fmt(
1962 state, state->domaindn, TLDAP_SCOPE_SUB,
1963 NULL, 0, 0, talloc_tos(), &msg,
1964 "(&(objectsid=%s)(objectclass=user))", sidstr);
1965 if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
1966 id->uid = rid;
1967 *type = SID_NAME_USER;
1968 TALLOC_FREE(sidstr);
1969 return true;
1972 rc = pdb_ads_search_fmt(
1973 state, state->domaindn, TLDAP_SCOPE_SUB,
1974 NULL, 0, 0, talloc_tos(), &msg,
1975 "(&(objectsid=%s)(objectclass=group))", sidstr);
1976 if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
1977 id->gid = rid;
1978 *type = SID_NAME_DOM_GRP;
1979 TALLOC_FREE(sidstr);
1980 return true;
1983 TALLOC_FREE(sidstr);
1984 return false;
1987 static uint32_t pdb_ads_capabilities(struct pdb_methods *m)
1989 return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
1992 static bool pdb_ads_new_rid(struct pdb_methods *m, uint32 *rid)
1994 return false;
1997 static bool pdb_ads_get_trusteddom_pw(struct pdb_methods *m,
1998 const char *domain, char** pwd,
1999 struct dom_sid *sid,
2000 time_t *pass_last_set_time)
2002 return false;
2005 static bool pdb_ads_set_trusteddom_pw(struct pdb_methods *m,
2006 const char* domain, const char* pwd,
2007 const struct dom_sid *sid)
2009 return false;
2012 static bool pdb_ads_del_trusteddom_pw(struct pdb_methods *m,
2013 const char *domain)
2015 return false;
2018 static NTSTATUS pdb_ads_enum_trusteddoms(struct pdb_methods *m,
2019 TALLOC_CTX *mem_ctx,
2020 uint32 *num_domains,
2021 struct trustdom_info ***domains)
2023 *num_domains = 0;
2024 *domains = NULL;
2025 return NT_STATUS_OK;
2028 static void pdb_ads_init_methods(struct pdb_methods *m)
2030 m->name = "ads";
2031 m->get_domain_info = pdb_ads_get_domain_info;
2032 m->getsampwnam = pdb_ads_getsampwnam;
2033 m->getsampwsid = pdb_ads_getsampwsid;
2034 m->create_user = pdb_ads_create_user;
2035 m->delete_user = pdb_ads_delete_user;
2036 m->add_sam_account = pdb_ads_add_sam_account;
2037 m->update_sam_account = pdb_ads_update_sam_account;
2038 m->delete_sam_account = pdb_ads_delete_sam_account;
2039 m->rename_sam_account = pdb_ads_rename_sam_account;
2040 m->update_login_attempts = pdb_ads_update_login_attempts;
2041 m->getgrsid = pdb_ads_getgrsid;
2042 m->getgrgid = pdb_ads_getgrgid;
2043 m->getgrnam = pdb_ads_getgrnam;
2044 m->create_dom_group = pdb_ads_create_dom_group;
2045 m->delete_dom_group = pdb_ads_delete_dom_group;
2046 m->add_group_mapping_entry = pdb_ads_add_group_mapping_entry;
2047 m->update_group_mapping_entry = pdb_ads_update_group_mapping_entry;
2048 m->delete_group_mapping_entry = pdb_ads_delete_group_mapping_entry;
2049 m->enum_group_mapping = pdb_ads_enum_group_mapping;
2050 m->enum_group_members = pdb_ads_enum_group_members;
2051 m->enum_group_memberships = pdb_ads_enum_group_memberships;
2052 m->set_unix_primary_group = pdb_ads_set_unix_primary_group;
2053 m->add_groupmem = pdb_ads_add_groupmem;
2054 m->del_groupmem = pdb_ads_del_groupmem;
2055 m->create_alias = pdb_ads_create_alias;
2056 m->delete_alias = pdb_ads_delete_alias;
2057 m->get_aliasinfo = pdb_default_get_aliasinfo;
2058 m->set_aliasinfo = pdb_ads_set_aliasinfo;
2059 m->add_aliasmem = pdb_ads_add_aliasmem;
2060 m->del_aliasmem = pdb_ads_del_aliasmem;
2061 m->enum_aliasmem = pdb_ads_enum_aliasmem;
2062 m->enum_alias_memberships = pdb_ads_enum_alias_memberships;
2063 m->lookup_rids = pdb_ads_lookup_rids;
2064 m->lookup_names = pdb_ads_lookup_names;
2065 m->get_account_policy = pdb_ads_get_account_policy;
2066 m->set_account_policy = pdb_ads_set_account_policy;
2067 m->get_seq_num = pdb_ads_get_seq_num;
2068 m->search_users = pdb_ads_search_users;
2069 m->search_groups = pdb_ads_search_groups;
2070 m->search_aliases = pdb_ads_search_aliases;
2071 m->uid_to_sid = pdb_ads_uid_to_sid;
2072 m->gid_to_sid = pdb_ads_gid_to_sid;
2073 m->sid_to_id = pdb_ads_sid_to_id;
2074 m->capabilities = pdb_ads_capabilities;
2075 m->new_rid = pdb_ads_new_rid;
2076 m->get_trusteddom_pw = pdb_ads_get_trusteddom_pw;
2077 m->set_trusteddom_pw = pdb_ads_set_trusteddom_pw;
2078 m->del_trusteddom_pw = pdb_ads_del_trusteddom_pw;
2079 m->enum_trusteddoms = pdb_ads_enum_trusteddoms;
2082 static void free_private_data(void **vp)
2084 struct pdb_ads_state *state = talloc_get_type_abort(
2085 *vp, struct pdb_ads_state);
2087 TALLOC_FREE(state->ld);
2088 return;
2092 this is used to catch debug messages from events
2094 static void s3_tldap_debug(void *context, enum tldap_debug_level level,
2095 const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
2097 static void s3_tldap_debug(void *context, enum tldap_debug_level level,
2098 const char *fmt, va_list ap)
2100 int samba_level = -1;
2101 char *s = NULL;
2102 switch (level) {
2103 case TLDAP_DEBUG_FATAL:
2104 samba_level = 0;
2105 break;
2106 case TLDAP_DEBUG_ERROR:
2107 samba_level = 1;
2108 break;
2109 case TLDAP_DEBUG_WARNING:
2110 samba_level = 2;
2111 break;
2112 case TLDAP_DEBUG_TRACE:
2113 samba_level = 11;
2114 break;
2117 if (vasprintf(&s, fmt, ap) == -1) {
2118 return;
2120 DEBUG(samba_level, ("tldap: %s", s));
2121 free(s);
2124 static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state)
2126 NTSTATUS status;
2127 int fd;
2129 if (tldap_connection_ok(state->ld)) {
2130 return state->ld;
2132 TALLOC_FREE(state->ld);
2134 status = open_socket_out(
2135 (struct sockaddr_storage *)(void *)&state->socket_address,
2136 0, 0, &fd);
2137 if (!NT_STATUS_IS_OK(status)) {
2138 DEBUG(10, ("Could not connect to %s: %s\n",
2139 state->socket_address.sun_path, nt_errstr(status)));
2140 return NULL;
2143 set_blocking(fd, false);
2145 state->ld = tldap_context_create(state, fd);
2146 if (state->ld == NULL) {
2147 close(fd);
2148 return NULL;
2150 tldap_set_debug(state->ld, s3_tldap_debug, NULL);
2152 return state->ld;
2155 int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base,
2156 int scope, const char *attrs[], int num_attrs,
2157 int attrsonly,
2158 TALLOC_CTX *mem_ctx, struct tldap_message ***res,
2159 const char *fmt, ...)
2161 struct tldap_context *ld;
2162 va_list ap;
2163 int ret;
2165 ld = pdb_ads_ld(state);
2166 if (ld == NULL) {
2167 return TLDAP_SERVER_DOWN;
2170 va_start(ap, fmt);
2171 ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly,
2172 mem_ctx, res, fmt, ap);
2173 va_end(ap);
2175 if (ret != TLDAP_SERVER_DOWN) {
2176 return ret;
2179 /* retry once */
2180 ld = pdb_ads_ld(state);
2181 if (ld == NULL) {
2182 return TLDAP_SERVER_DOWN;
2185 va_start(ap, fmt);
2186 ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly,
2187 mem_ctx, res, fmt, ap);
2188 va_end(ap);
2189 return ret;
2192 static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state,
2193 const char *location)
2195 const char *domain_attrs[2] = { "objectSid", "objectGUID" };
2196 const char *ncname_attrs[1] = { "netbiosname" };
2197 struct tldap_context *ld;
2198 struct tldap_message *rootdse, **domain, **ncname;
2199 TALLOC_CTX *frame = talloc_stackframe();
2200 NTSTATUS status;
2201 int num_domains;
2202 int rc;
2204 ZERO_STRUCT(state->socket_address);
2205 state->socket_address.sun_family = AF_UNIX;
2206 strncpy(state->socket_address.sun_path, location,
2207 sizeof(state->socket_address.sun_path) - 1);
2209 ld = pdb_ads_ld(state);
2210 if (ld == NULL) {
2211 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2212 goto done;
2215 rc = tldap_fetch_rootdse(ld);
2216 if (rc != TLDAP_SUCCESS) {
2217 DEBUG(10, ("Could not retrieve rootdse: %s\n",
2218 tldap_errstr(talloc_tos(), state->ld, rc)));
2219 status = NT_STATUS_LDAP(rc);
2220 goto done;
2222 rootdse = tldap_rootdse(state->ld);
2224 state->domaindn = tldap_talloc_single_attribute(
2225 rootdse, "defaultNamingContext", state);
2226 if (state->domaindn == NULL) {
2227 DEBUG(10, ("Could not get defaultNamingContext\n"));
2228 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2229 goto done;
2231 DEBUG(10, ("defaultNamingContext = %s\n", state->domaindn));
2233 state->configdn = tldap_talloc_single_attribute(
2234 rootdse, "configurationNamingContext", state);
2235 if (state->domaindn == NULL) {
2236 DEBUG(10, ("Could not get configurationNamingContext\n"));
2237 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2238 goto done;
2240 DEBUG(10, ("configurationNamingContext = %s\n", state->configdn));
2243 * Figure out our domain's SID
2245 rc = pdb_ads_search_fmt(
2246 state, state->domaindn, TLDAP_SCOPE_BASE,
2247 domain_attrs, ARRAY_SIZE(domain_attrs), 0,
2248 talloc_tos(), &domain, "(objectclass=*)");
2249 if (rc != TLDAP_SUCCESS) {
2250 DEBUG(10, ("Could not retrieve domain: %s\n",
2251 tldap_errstr(talloc_tos(), state->ld, rc)));
2252 status = NT_STATUS_LDAP(rc);
2253 goto done;
2256 num_domains = talloc_array_length(domain);
2257 if (num_domains != 1) {
2258 DEBUG(10, ("Got %d domains, expected one\n", num_domains));
2259 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2260 goto done;
2262 if (!tldap_pull_binsid(domain[0], "objectSid", &state->domainsid)) {
2263 DEBUG(10, ("Could not retrieve domain SID\n"));
2264 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2265 goto done;
2267 if (!tldap_pull_guid(domain[0], "objectGUID", &state->domainguid)) {
2268 DEBUG(10, ("Could not retrieve domain GUID\n"));
2269 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2270 goto done;
2272 DEBUG(10, ("Domain SID: %s\n", sid_string_dbg(&state->domainsid)));
2275 * Figure out our domain's short name
2277 rc = pdb_ads_search_fmt(
2278 state, state->configdn, TLDAP_SCOPE_SUB,
2279 ncname_attrs, ARRAY_SIZE(ncname_attrs), 0,
2280 talloc_tos(), &ncname, "(ncname=%s)", state->domaindn);
2281 if (rc != TLDAP_SUCCESS) {
2282 DEBUG(10, ("Could not retrieve ncname: %s\n",
2283 tldap_errstr(talloc_tos(), state->ld, rc)));
2284 status = NT_STATUS_LDAP(rc);
2285 goto done;
2287 if (talloc_array_length(ncname) != 1) {
2288 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2289 goto done;
2292 state->netbiosname = tldap_talloc_single_attribute(
2293 ncname[0], "netbiosname", state);
2294 if (state->netbiosname == NULL) {
2295 DEBUG(10, ("Could not get netbiosname\n"));
2296 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2297 goto done;
2299 DEBUG(10, ("netbiosname: %s\n", state->netbiosname));
2301 if (!strequal(lp_workgroup(), state->netbiosname)) {
2302 DEBUG(1, ("ADS is different domain (%s) than ours (%s)\n",
2303 state->netbiosname, lp_workgroup()));
2304 status = NT_STATUS_NO_SUCH_DOMAIN;
2305 goto done;
2308 secrets_store_domain_sid(state->netbiosname, &state->domainsid);
2310 status = NT_STATUS_OK;
2311 done:
2312 TALLOC_FREE(frame);
2313 return status;
2316 static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method,
2317 const char *location)
2319 struct pdb_methods *m;
2320 struct pdb_ads_state *state;
2321 char *tmp = NULL;
2322 NTSTATUS status;
2324 m = talloc(talloc_autofree_context(), struct pdb_methods);
2325 if (m == NULL) {
2326 return NT_STATUS_NO_MEMORY;
2328 state = talloc_zero(m, struct pdb_ads_state);
2329 if (state == NULL) {
2330 goto nomem;
2332 m->private_data = state;
2333 m->free_private_data = free_private_data;
2334 pdb_ads_init_methods(m);
2336 if (location == NULL) {
2337 tmp = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi",
2338 lp_private_dir());
2339 location = tmp;
2341 if (location == NULL) {
2342 goto nomem;
2345 status = pdb_ads_connect(state, location);
2346 if (!NT_STATUS_IS_OK(status)) {
2347 DEBUG(10, ("pdb_ads_connect failed: %s\n", nt_errstr(status)));
2348 goto fail;
2351 *pdb_method = m;
2352 return NT_STATUS_OK;
2353 nomem:
2354 status = NT_STATUS_NO_MEMORY;
2355 fail:
2356 TALLOC_FREE(m);
2357 return status;
2360 NTSTATUS pdb_ads_init(void);
2361 NTSTATUS pdb_ads_init(void)
2363 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "ads",
2364 pdb_init_ads);