Make "net sam list" work for groups, aliases and builtins
[Samba.git] / source3 / passdb / pdb_ads.c
blob3c5cd442ff8f5d8603806718e1a7aaabc63ed7a1
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"
22 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
23 struct samu *sam_acct,
24 const DOM_SID *sid);
26 struct pdb_ads_state {
27 struct tldap_context *ld;
28 struct dom_sid domainsid;
29 char *domaindn;
30 char *configdn;
31 char *netbiosname;
34 static bool pdb_ads_pull_time(struct tldap_message *msg, const char *attr,
35 time_t *ptime)
37 uint64_t tmp;
39 if (!tldap_pull_uint64(msg, attr, &tmp)) {
40 return false;
42 *ptime = uint64s_nt_time_to_unix_abs(&tmp);
43 return true;
46 static gid_t pdb_ads_sid2gid(const struct dom_sid *sid)
48 uint32_t rid;
49 sid_peek_rid(sid, &rid);
50 return rid;
53 struct pdb_ads_samu_private {
54 char *dn;
55 struct tldap_message *ldapmsg;
58 static struct samu *pdb_ads_init_guest(TALLOC_CTX *mem_ctx,
59 struct pdb_methods *m)
61 struct pdb_ads_state *state = talloc_get_type_abort(
62 m->private_data, struct pdb_ads_state);
63 struct dom_sid guest_sid;
64 struct samu *guest;
65 NTSTATUS status;
67 sid_compose(&guest_sid, &state->domainsid, DOMAIN_USER_RID_GUEST);
69 guest = samu_new(mem_ctx);
70 if (guest == NULL) {
71 return NULL;
74 status = pdb_ads_getsampwsid(m, guest, &guest_sid);
75 if (!NT_STATUS_IS_OK(status)) {
76 DEBUG(10, ("Could not init guest account: %s\n",
77 nt_errstr(status)));
78 TALLOC_FREE(guest);
79 return NULL;
81 return guest;
84 static struct pdb_ads_samu_private *pdb_ads_get_samu_private(
85 struct pdb_methods *m, struct samu *sam)
87 struct pdb_ads_samu_private *result;
88 uint32_t rid;
90 result = (struct pdb_ads_samu_private *)
91 pdb_get_backend_private_data(sam, m);
93 if (result != NULL) {
94 return talloc_get_type_abort(
95 result, struct pdb_ads_samu_private);
99 * This is now a weirdness of the passdb API. For the guest user we
100 * are not asked first.
102 sid_peek_rid(pdb_get_user_sid(sam), &rid);
104 if (rid == DOMAIN_USER_RID_GUEST) {
105 struct samu *guest = pdb_ads_init_guest(talloc_tos(), m);
107 if (guest == NULL) {
108 return NULL;
110 result = talloc_get_type_abort(
111 pdb_get_backend_private_data(guest, m),
112 struct pdb_ads_samu_private);
113 pdb_set_backend_private_data(
114 sam, talloc_move(sam, &result), NULL, m, PDB_SET);
115 TALLOC_FREE(guest);
116 return talloc_get_type_abort(
117 pdb_get_backend_private_data(sam, m),
118 struct pdb_ads_samu_private);
121 return NULL;
124 static NTSTATUS pdb_ads_init_sam_from_ads(struct pdb_methods *m,
125 struct samu *sam,
126 struct tldap_message *entry)
128 struct pdb_ads_state *state = talloc_get_type_abort(
129 m->private_data, struct pdb_ads_state);
130 TALLOC_CTX *frame = talloc_stackframe();
131 struct pdb_ads_samu_private *priv;
132 NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
133 char *str;
134 time_t tmp_time;
135 struct dom_sid sid;
136 uint64_t n;
137 DATA_BLOB blob;
139 priv = talloc(sam, struct pdb_ads_samu_private);
140 if (priv == NULL) {
141 return NT_STATUS_NO_MEMORY;
143 if (!tldap_entry_dn(entry, &priv->dn)) {
144 TALLOC_FREE(priv);
145 return NT_STATUS_INTERNAL_DB_CORRUPTION;
148 str = tldap_talloc_single_attribute(entry, "samAccountName", sam);
149 if (str == NULL) {
150 DEBUG(10, ("no samAccountName\n"));
151 goto fail;
153 pdb_set_username(sam, str, PDB_SET);
154 TALLOC_FREE(str);
156 if (pdb_ads_pull_time(entry, "lastLogon", &tmp_time)) {
157 pdb_set_logon_time(sam, tmp_time, PDB_SET);
159 if (pdb_ads_pull_time(entry, "lastLogoff", &tmp_time)) {
160 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
162 if (pdb_ads_pull_time(entry, "pwdLastSet", &tmp_time)) {
163 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
165 if (pdb_ads_pull_time(entry, "accountExpires", &tmp_time)) {
166 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
169 str = tldap_talloc_single_attribute(entry, "samAccoutName",
170 talloc_tos());
171 if (str != NULL) {
172 pdb_set_username(sam, str, PDB_SET);
175 str = tldap_talloc_single_attribute(entry, "displayName",
176 talloc_tos());
177 if (str != NULL) {
178 pdb_set_fullname(sam, str, PDB_SET);
181 str = tldap_talloc_single_attribute(entry, "homeDirectory",
182 talloc_tos());
183 if (str != NULL) {
184 pdb_set_homedir(sam, str, PDB_SET);
187 str = tldap_talloc_single_attribute(entry, "homeDrive", talloc_tos());
188 if (str != NULL) {
189 pdb_set_dir_drive(sam, str, PDB_SET);
192 str = tldap_talloc_single_attribute(entry, "scriptPath", talloc_tos());
193 if (str != NULL) {
194 pdb_set_logon_script(sam, str, PDB_SET);
197 str = tldap_talloc_single_attribute(entry, "profilePath",
198 talloc_tos());
199 if (str != NULL) {
200 pdb_set_profile_path(sam, str, PDB_SET);
203 str = tldap_talloc_single_attribute(entry, "profilePath",
204 talloc_tos());
205 if (str != NULL) {
206 pdb_set_profile_path(sam, str, PDB_SET);
209 if (!tldap_pull_binsid(entry, "objectSid", &sid)) {
210 DEBUG(10, ("Could not pull SID\n"));
211 goto fail;
213 pdb_set_user_sid(sam, &sid, PDB_SET);
215 if (!tldap_pull_uint64(entry, "userAccountControl", &n)) {
216 DEBUG(10, ("Could not pull userAccountControl\n"));
217 goto fail;
219 pdb_set_acct_ctrl(sam, ads_uf2acb(n), PDB_SET);
221 if (tldap_get_single_valueblob(entry, "unicodePwd", &blob)) {
222 if (blob.length != NT_HASH_LEN) {
223 DEBUG(0, ("Got NT hash of length %d, expected %d\n",
224 (int)blob.length, NT_HASH_LEN));
225 goto fail;
227 pdb_set_nt_passwd(sam, blob.data, PDB_SET);
230 if (tldap_get_single_valueblob(entry, "dBCSPwd", &blob)) {
231 if (blob.length != LM_HASH_LEN) {
232 DEBUG(0, ("Got LM hash of length %d, expected %d\n",
233 (int)blob.length, LM_HASH_LEN));
234 goto fail;
236 pdb_set_lanman_passwd(sam, blob.data, PDB_SET);
239 if (tldap_pull_uint64(entry, "primaryGroupID", &n)) {
240 sid_compose(&sid, &state->domainsid, n);
241 pdb_set_group_sid(sam, &sid, PDB_SET);
245 priv->ldapmsg = talloc_move(priv, &entry);
246 pdb_set_backend_private_data(sam, priv, NULL, m, PDB_SET);
248 status = NT_STATUS_OK;
249 fail:
250 TALLOC_FREE(frame);
251 return status;
254 static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state,
255 struct tldap_message *existing,
256 TALLOC_CTX *mem_ctx,
257 int *pnum_mods, struct tldap_mod **pmods,
258 struct samu *sam)
260 bool ret = true;
262 /* TODO: All fields :-) */
264 ret &= tldap_make_mod_fmt(
265 existing, mem_ctx, pnum_mods, pmods, "displayName",
266 pdb_get_fullname(sam));
268 ret &= tldap_make_mod_blob(
269 existing, mem_ctx, pnum_mods, pmods, "unicodePwd",
270 data_blob_const(pdb_get_nt_passwd(sam), NT_HASH_LEN));
272 ret &= tldap_make_mod_blob(
273 existing, mem_ctx, pnum_mods, pmods, "dBCSPwd",
274 data_blob_const(pdb_get_lanman_passwd(sam), NT_HASH_LEN));
276 return ret;
279 static NTSTATUS pdb_ads_getsampwfilter(struct pdb_methods *m,
280 struct pdb_ads_state *state,
281 struct samu *sam_acct,
282 const char *filter)
284 const char * attrs[] = {
285 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
286 "sAMAccountName", "displayName", "homeDirectory",
287 "homeDrive", "scriptPath", "profilePath", "description",
288 "userWorkstations", "comment", "userParameters", "objectSid",
289 "primaryGroupID", "userAccountControl", "logonHours",
290 "badPwdCount", "logonCount", "countryCode", "codePage",
291 "unicodePwd", "dBCSPwd" };
292 struct tldap_message **users;
293 int rc, count;
295 rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
296 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
297 &users, filter);
298 if (rc != TLDAP_SUCCESS) {
299 DEBUG(10, ("ldap_search failed %s\n",
300 tldap_errstr(debug_ctx(), state->ld, rc)));
301 return NT_STATUS_LDAP(rc);
304 count = talloc_array_length(users);
305 if (count != 1) {
306 DEBUG(10, ("Expected 1 user, got %d\n", count));
307 return NT_STATUS_INTERNAL_DB_CORRUPTION;
310 return pdb_ads_init_sam_from_ads(m, sam_acct, users[0]);
313 static NTSTATUS pdb_ads_getsampwnam(struct pdb_methods *m,
314 struct samu *sam_acct,
315 const char *username)
317 struct pdb_ads_state *state = talloc_get_type_abort(
318 m->private_data, struct pdb_ads_state);
319 char *filter;
321 filter = talloc_asprintf(
322 talloc_tos(), "(&(samaccountname=%s)(objectclass=user))",
323 username);
324 NT_STATUS_HAVE_NO_MEMORY(filter);
326 return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
329 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
330 struct samu *sam_acct,
331 const DOM_SID *sid)
333 struct pdb_ads_state *state = talloc_get_type_abort(
334 m->private_data, struct pdb_ads_state);
335 char *sidstr, *filter;
337 sidstr = sid_binstring(talloc_tos(), sid);
338 NT_STATUS_HAVE_NO_MEMORY(sidstr);
340 filter = talloc_asprintf(
341 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
342 TALLOC_FREE(sidstr);
343 NT_STATUS_HAVE_NO_MEMORY(filter);
345 return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
348 static NTSTATUS pdb_ads_create_user(struct pdb_methods *m,
349 TALLOC_CTX *tmp_ctx,
350 const char *name, uint32 acct_flags,
351 uint32 *rid)
353 struct pdb_ads_state *state = talloc_get_type_abort(
354 m->private_data, struct pdb_ads_state);
355 const char *attrs[1] = { "objectSid" };
356 struct tldap_mod *mods = NULL;
357 int num_mods = 0;
358 struct tldap_message **user;
359 struct dom_sid sid;
360 char *dn;
361 int rc;
362 bool ok;
364 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
365 state->domaindn);
366 if (dn == NULL) {
367 return NT_STATUS_NO_MEMORY;
370 /* TODO: Create machines etc */
372 ok = true;
373 ok &= tldap_make_mod_fmt(
374 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "user");
375 ok &= tldap_make_mod_fmt(
376 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
377 name);
378 if (!ok) {
379 return NT_STATUS_NO_MEMORY;
382 rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL);
383 if (rc != TLDAP_SUCCESS) {
384 DEBUG(10, ("ldap_add failed %s\n",
385 tldap_errstr(debug_ctx(), state->ld, rc)));
386 TALLOC_FREE(dn);
387 return NT_STATUS_LDAP(rc);
390 rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
391 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &user,
392 "(&(objectclass=user)(samaccountname=%s))",
393 name);
394 if (rc != TLDAP_SUCCESS) {
395 DEBUG(10, ("Could not find just created user %s: %s\n",
396 name, tldap_errstr(debug_ctx(), state->ld, rc)));
397 TALLOC_FREE(dn);
398 return NT_STATUS_LDAP(rc);
401 if (talloc_array_length(user) != 1) {
402 DEBUG(10, ("Got %d users, expected one\n",
403 (int)talloc_array_length(user)));
404 TALLOC_FREE(dn);
405 return NT_STATUS_LDAP(rc);
408 if (!tldap_pull_binsid(user[0], "objectSid", &sid)) {
409 DEBUG(10, ("Could not fetch objectSid from user %s\n",
410 name));
411 TALLOC_FREE(dn);
412 return NT_STATUS_INTERNAL_DB_CORRUPTION;
415 sid_peek_rid(&sid, rid);
416 TALLOC_FREE(dn);
417 return NT_STATUS_OK;
420 static NTSTATUS pdb_ads_delete_user(struct pdb_methods *m,
421 TALLOC_CTX *tmp_ctx,
422 struct samu *sam)
424 struct pdb_ads_state *state = talloc_get_type_abort(
425 m->private_data, struct pdb_ads_state);
426 struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam);
427 int rc;
429 rc = tldap_delete(state->ld, priv->dn, NULL, NULL);
430 if (rc != TLDAP_SUCCESS) {
431 DEBUG(10, ("ldap_delete for %s failed: %s\n", priv->dn,
432 tldap_errstr(debug_ctx(), state->ld, rc)));
433 return NT_STATUS_LDAP(rc);
435 return NT_STATUS_OK;
438 static NTSTATUS pdb_ads_add_sam_account(struct pdb_methods *m,
439 struct samu *sampass)
441 return NT_STATUS_NOT_IMPLEMENTED;
444 static NTSTATUS pdb_ads_update_sam_account(struct pdb_methods *m,
445 struct samu *sam)
447 struct pdb_ads_state *state = talloc_get_type_abort(
448 m->private_data, struct pdb_ads_state);
449 struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam);
450 struct tldap_mod *mods = NULL;
451 int rc, num_mods = 0;
453 if (!pdb_ads_init_ads_from_sam(state, priv->ldapmsg, talloc_tos(),
454 &num_mods, &mods, sam)) {
455 return NT_STATUS_NO_MEMORY;
458 rc = tldap_modify(state->ld, priv->dn, num_mods, mods, NULL, NULL);
459 if (rc != TLDAP_SUCCESS) {
460 DEBUG(10, ("ldap_modify for %s failed: %s\n", priv->dn,
461 tldap_errstr(debug_ctx(), state->ld, rc)));
462 return NT_STATUS_LDAP(rc);
465 TALLOC_FREE(mods);
467 return NT_STATUS_OK;
470 static NTSTATUS pdb_ads_delete_sam_account(struct pdb_methods *m,
471 struct samu *username)
473 return NT_STATUS_NOT_IMPLEMENTED;
476 static NTSTATUS pdb_ads_rename_sam_account(struct pdb_methods *m,
477 struct samu *oldname,
478 const char *newname)
480 return NT_STATUS_NOT_IMPLEMENTED;
483 static NTSTATUS pdb_ads_update_login_attempts(struct pdb_methods *m,
484 struct samu *sam_acct,
485 bool success)
487 return NT_STATUS_NOT_IMPLEMENTED;
490 static NTSTATUS pdb_ads_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
491 DOM_SID sid)
493 return NT_STATUS_NOT_IMPLEMENTED;
496 static NTSTATUS pdb_ads_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
497 gid_t gid)
499 return NT_STATUS_NOT_IMPLEMENTED;
502 static NTSTATUS pdb_ads_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
503 const char *name)
505 return NT_STATUS_NOT_IMPLEMENTED;
508 static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m,
509 TALLOC_CTX *mem_ctx, const char *name,
510 uint32 *rid)
512 return NT_STATUS_NOT_IMPLEMENTED;
515 static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m,
516 TALLOC_CTX *mem_ctx, uint32 rid)
518 return NT_STATUS_NOT_IMPLEMENTED;
521 static NTSTATUS pdb_ads_add_group_mapping_entry(struct pdb_methods *m,
522 GROUP_MAP *map)
524 return NT_STATUS_NOT_IMPLEMENTED;
527 static NTSTATUS pdb_ads_update_group_mapping_entry(struct pdb_methods *m,
528 GROUP_MAP *map)
530 return NT_STATUS_NOT_IMPLEMENTED;
533 static NTSTATUS pdb_ads_delete_group_mapping_entry(struct pdb_methods *m,
534 DOM_SID sid)
536 return NT_STATUS_NOT_IMPLEMENTED;
539 static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m,
540 const DOM_SID *sid,
541 enum lsa_SidType sid_name_use,
542 GROUP_MAP **pp_rmap,
543 size_t *p_num_entries,
544 bool unix_only)
546 return NT_STATUS_NOT_IMPLEMENTED;
549 static NTSTATUS pdb_ads_enum_group_members(struct pdb_methods *m,
550 TALLOC_CTX *mem_ctx,
551 const DOM_SID *group,
552 uint32 **pp_member_rids,
553 size_t *p_num_members)
555 return NT_STATUS_NOT_IMPLEMENTED;
558 static NTSTATUS pdb_ads_enum_group_memberships(struct pdb_methods *m,
559 TALLOC_CTX *mem_ctx,
560 struct samu *user,
561 DOM_SID **pp_sids,
562 gid_t **pp_gids,
563 size_t *p_num_groups)
565 struct pdb_ads_state *state = talloc_get_type_abort(
566 m->private_data, struct pdb_ads_state);
567 struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(
568 m, user);
569 const char *attrs[1] = { "objectSid" };
570 struct tldap_message **groups;
571 int i, rc, count;
572 size_t num_groups;
573 struct dom_sid *group_sids;
574 gid_t *gids;
576 rc = tldap_search_fmt(
577 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
578 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &groups,
579 "(&(member=%s)(grouptype=%d)(objectclass=group))",
580 priv->dn, GTYPE_SECURITY_GLOBAL_GROUP);
581 if (rc != TLDAP_SUCCESS) {
582 DEBUG(10, ("ldap_search failed %s\n",
583 tldap_errstr(debug_ctx(), state->ld, rc)));
584 return NT_STATUS_LDAP(rc);
587 count = talloc_array_length(groups);
589 group_sids = talloc_array(mem_ctx, struct dom_sid, count);
590 if (group_sids == NULL) {
591 return NT_STATUS_NO_MEMORY;
593 gids = talloc_array(mem_ctx, gid_t, count);
594 if (gids == NULL) {
595 TALLOC_FREE(group_sids);
596 return NT_STATUS_NO_MEMORY;
598 num_groups = 0;
600 for (i=0; i<count; i++) {
601 if (!tldap_pull_binsid(groups[i], "objectSid",
602 &group_sids[num_groups])) {
603 continue;
605 gids[num_groups] = pdb_ads_sid2gid(&group_sids[num_groups]);
607 num_groups += 1;
608 if (num_groups == count) {
609 break;
613 *pp_sids = group_sids;
614 *pp_gids = gids;
615 *p_num_groups = num_groups;
616 return NT_STATUS_OK;
619 static NTSTATUS pdb_ads_set_unix_primary_group(struct pdb_methods *m,
620 TALLOC_CTX *mem_ctx,
621 struct samu *user)
623 return NT_STATUS_NOT_IMPLEMENTED;
626 static NTSTATUS pdb_ads_add_groupmem(struct pdb_methods *m,
627 TALLOC_CTX *mem_ctx,
628 uint32 group_rid, uint32 member_rid)
630 return NT_STATUS_NOT_IMPLEMENTED;
633 static NTSTATUS pdb_ads_del_groupmem(struct pdb_methods *m,
634 TALLOC_CTX *mem_ctx,
635 uint32 group_rid, uint32 member_rid)
637 return NT_STATUS_NOT_IMPLEMENTED;
640 static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m,
641 const char *name, uint32 *rid)
643 TALLOC_CTX *frame = talloc_stackframe();
644 struct pdb_ads_state *state = talloc_get_type_abort(
645 m->private_data, struct pdb_ads_state);
646 const char *attrs[1] = { "objectSid" };
647 int num_mods = 0;
648 struct tldap_mod *mods = NULL;
649 struct tldap_message **alias;
650 struct dom_sid sid;
651 char *dn;
652 int rc;
653 bool ok = true;
655 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
656 state->domaindn);
657 if (dn == NULL) {
658 TALLOC_FREE(frame);
659 return NT_STATUS_NO_MEMORY;
662 ok &= tldap_make_mod_fmt(
663 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
664 name);
665 ok &= tldap_make_mod_fmt(
666 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "group");
667 ok &= tldap_make_mod_fmt(
668 NULL, talloc_tos(), &num_mods, &mods, "groupType",
669 "%d", (int)GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
671 if (!ok) {
672 TALLOC_FREE(frame);
673 return NT_STATUS_NO_MEMORY;
676 rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL);
677 if (rc != TLDAP_SUCCESS) {
678 DEBUG(10, ("ldap_add failed %s\n",
679 tldap_errstr(debug_ctx(), state->ld, rc)));
680 TALLOC_FREE(frame);
681 return NT_STATUS_LDAP(rc);
684 rc = tldap_search_fmt(
685 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
686 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
687 "(&(objectclass=group)(samaccountname=%s))", name);
688 if (rc != TLDAP_SUCCESS) {
689 DEBUG(10, ("Could not find just created alias %s: %s\n",
690 name, tldap_errstr(debug_ctx(), state->ld, rc)));
691 TALLOC_FREE(frame);
692 return NT_STATUS_LDAP(rc);
695 if (talloc_array_length(alias) != 1) {
696 DEBUG(10, ("Got %d alias, expected one\n",
697 (int)talloc_array_length(alias)));
698 TALLOC_FREE(frame);
699 return NT_STATUS_LDAP(rc);
702 if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
703 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
704 name));
705 TALLOC_FREE(frame);
706 return NT_STATUS_INTERNAL_DB_CORRUPTION;
709 sid_peek_rid(&sid, rid);
710 TALLOC_FREE(frame);
711 return NT_STATUS_OK;
714 static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m,
715 const DOM_SID *sid)
717 return NT_STATUS_NOT_IMPLEMENTED;
720 static NTSTATUS pdb_ads_get_aliasinfo(struct pdb_methods *m,
721 const DOM_SID *sid,
722 struct acct_info *info)
724 return NT_STATUS_NOT_IMPLEMENTED;
727 static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m,
728 const DOM_SID *sid,
729 struct acct_info *info)
731 return NT_STATUS_NOT_IMPLEMENTED;
734 static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
735 const DOM_SID *alias,
736 const DOM_SID *member)
738 return NT_STATUS_NOT_IMPLEMENTED;
741 static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
742 const DOM_SID *alias,
743 const DOM_SID *member)
745 return NT_STATUS_NOT_IMPLEMENTED;
748 static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
749 const DOM_SID *alias, DOM_SID **members,
750 size_t *p_num_members)
752 return NT_STATUS_NOT_IMPLEMENTED;
755 static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,
756 TALLOC_CTX *mem_ctx,
757 const DOM_SID *domain_sid,
758 const DOM_SID *members,
759 size_t num_members,
760 uint32 **pp_alias_rids,
761 size_t *p_num_alias_rids)
763 return NT_STATUS_NOT_IMPLEMENTED;
766 static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m,
767 const DOM_SID *domain_sid,
768 int num_rids,
769 uint32 *rids,
770 const char **pp_names,
771 enum lsa_SidType *attrs)
773 return NT_STATUS_NOT_IMPLEMENTED;
776 static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m,
777 const DOM_SID *domain_sid,
778 int num_names,
779 const char **pp_names,
780 uint32 *rids,
781 enum lsa_SidType *attrs)
783 return NT_STATUS_NOT_IMPLEMENTED;
786 static NTSTATUS pdb_ads_get_account_policy(struct pdb_methods *m,
787 int policy_index, uint32 *value)
789 return account_policy_get(policy_index, value)
790 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
793 static NTSTATUS pdb_ads_set_account_policy(struct pdb_methods *m,
794 int policy_index, uint32 value)
796 return account_policy_set(policy_index, value)
797 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
800 static NTSTATUS pdb_ads_get_seq_num(struct pdb_methods *m,
801 time_t *seq_num)
803 return NT_STATUS_NOT_IMPLEMENTED;
806 struct pdb_ads_search_state {
807 uint32_t acct_flags;
808 struct samr_displayentry *entries;
809 uint32_t num_entries;
810 ssize_t array_size;
811 uint32_t current;
814 static bool pdb_ads_next_entry(struct pdb_search *search,
815 struct samr_displayentry *entry)
817 struct pdb_ads_search_state *state = talloc_get_type_abort(
818 search->private_data, struct pdb_ads_search_state);
820 if (state->current == state->num_entries) {
821 return false;
824 entry->idx = state->entries[state->current].idx;
825 entry->rid = state->entries[state->current].rid;
826 entry->acct_flags = state->entries[state->current].acct_flags;
828 entry->account_name = talloc_strdup(
829 search, state->entries[state->current].account_name);
830 entry->fullname = talloc_strdup(
831 search, state->entries[state->current].fullname);
832 entry->description = talloc_strdup(
833 search, state->entries[state->current].description);
835 if ((entry->account_name == NULL) || (entry->fullname == NULL)
836 || (entry->description == NULL)) {
837 DEBUG(0, ("talloc_strdup failed\n"));
838 return false;
841 state->current += 1;
842 return true;
845 static void pdb_ads_search_end(struct pdb_search *search)
847 struct pdb_ads_search_state *state = talloc_get_type_abort(
848 search->private_data, struct pdb_ads_search_state);
849 TALLOC_FREE(state);
852 static bool pdb_ads_search_filter(struct pdb_methods *m,
853 struct pdb_search *search,
854 const char *filter,
855 struct pdb_ads_search_state **pstate)
857 struct pdb_ads_state *state = talloc_get_type_abort(
858 m->private_data, struct pdb_ads_state);
859 struct pdb_ads_search_state *sstate;
860 const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
861 "userAccountControl", "description" };
862 struct tldap_message **users;
863 int i, rc, num_users;
865 sstate = talloc_zero(search, struct pdb_ads_search_state);
866 if (sstate == NULL) {
867 return false;
870 rc = tldap_search_fmt(
871 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
872 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &users,
873 "%s", filter);
874 if (rc != TLDAP_SUCCESS) {
875 DEBUG(10, ("ldap_search_ext_s failed: %s\n",
876 tldap_errstr(debug_ctx(), state->ld, rc)));
877 return false;
880 num_users = talloc_array_length(users);
882 sstate->entries = talloc_array(sstate, struct samr_displayentry,
883 num_users);
884 if (sstate->entries == NULL) {
885 DEBUG(10, ("talloc failed\n"));
886 return false;
889 sstate->num_entries = 0;
891 for (i=0; i<num_users; i++) {
892 struct samr_displayentry *e;
893 struct dom_sid sid;
895 e = &sstate->entries[sstate->num_entries];
897 e->idx = sstate->num_entries;
898 if (!tldap_pull_binsid(users[i], "objectSid", &sid)) {
899 DEBUG(10, ("Could not pull sid\n"));
900 continue;
902 sid_peek_rid(&sid, &e->rid);
903 e->acct_flags = ACB_NORMAL;
904 e->account_name = tldap_talloc_single_attribute(
905 users[i], "samAccountName", sstate->entries);
906 if (e->account_name == NULL) {
907 return false;
909 e->fullname = tldap_talloc_single_attribute(
910 users[i], "displayName", sstate->entries);
911 if (e->fullname == NULL) {
912 e->fullname = "";
914 e->description = tldap_talloc_single_attribute(
915 users[i], "description", sstate->entries);
916 if (e->description == NULL) {
917 e->description = "";
920 sstate->num_entries += 1;
921 if (sstate->num_entries >= num_users) {
922 break;
926 search->private_data = sstate;
927 search->next_entry = pdb_ads_next_entry;
928 search->search_end = pdb_ads_search_end;
929 *pstate = sstate;
930 return true;
933 static bool pdb_ads_search_users(struct pdb_methods *m,
934 struct pdb_search *search,
935 uint32 acct_flags)
937 struct pdb_ads_search_state *sstate;
938 bool ret;
940 ret = pdb_ads_search_filter(m, search, "(objectclass=user)", &sstate);
941 if (!ret) {
942 return false;
944 sstate->acct_flags = acct_flags;
945 return true;
948 static bool pdb_ads_search_groups(struct pdb_methods *m,
949 struct pdb_search *search)
951 struct pdb_ads_search_state *sstate;
952 char *filter;
953 bool ret;
955 filter = talloc_asprintf(talloc_tos(),
956 "(&(grouptype=%d)(objectclass=group))",
957 GTYPE_SECURITY_GLOBAL_GROUP);
958 if (filter == NULL) {
959 return false;
961 ret = pdb_ads_search_filter(m, search, filter, &sstate);
962 TALLOC_FREE(filter);
963 if (!ret) {
964 return false;
966 sstate->acct_flags = 0;
967 return true;
970 static bool pdb_ads_search_aliases(struct pdb_methods *m,
971 struct pdb_search *search,
972 const DOM_SID *sid)
974 struct pdb_ads_search_state *sstate;
975 char *filter;
976 bool ret;
978 filter = talloc_asprintf(
979 talloc_tos(), "(&(grouptype=%d)(objectclass=group))",
980 sid_check_is_builtin(sid)
981 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
982 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
984 if (filter == NULL) {
985 return false;
987 ret = pdb_ads_search_filter(m, search, filter, &sstate);
988 TALLOC_FREE(filter);
989 if (!ret) {
990 return false;
992 sstate->acct_flags = 0;
993 return true;
996 static bool pdb_ads_uid_to_rid(struct pdb_methods *m, uid_t uid,
997 uint32 *rid)
999 return false;
1002 static bool pdb_ads_uid_to_sid(struct pdb_methods *m, uid_t uid,
1003 DOM_SID *sid)
1005 return false;
1008 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
1009 DOM_SID *sid)
1011 return false;
1014 static bool pdb_ads_sid_to_id(struct pdb_methods *m, const DOM_SID *sid,
1015 union unid_t *id, enum lsa_SidType *type)
1017 struct pdb_ads_state *state = talloc_get_type_abort(
1018 m->private_data, struct pdb_ads_state);
1019 struct tldap_message **msg;
1020 char *sidstr;
1021 uint32_t rid;
1022 int rc;
1025 * This is a big, big hack: Just hard-code the rid as uid/gid.
1028 sid_peek_rid(sid, &rid);
1030 sidstr = sid_binstring(talloc_tos(), sid);
1031 if (sidstr == NULL) {
1032 return false;
1035 rc = tldap_search_fmt(
1036 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1037 NULL, 0, 0, talloc_tos(), &msg,
1038 "(&(objectsid=%s)(objectclass=user))", sidstr);
1039 if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
1040 id->uid = rid;
1041 *type = SID_NAME_USER;
1042 TALLOC_FREE(sidstr);
1043 return true;
1046 rc = tldap_search_fmt(
1047 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1048 NULL, 0, 0, talloc_tos(), &msg,
1049 "(&(objectsid=%s)(objectclass=group))", sidstr);
1050 if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
1051 id->gid = rid;
1052 *type = SID_NAME_DOM_GRP;
1053 TALLOC_FREE(sidstr);
1054 return true;
1057 TALLOC_FREE(sidstr);
1058 return false;
1061 static bool pdb_ads_rid_algorithm(struct pdb_methods *m)
1063 return false;
1066 static bool pdb_ads_new_rid(struct pdb_methods *m, uint32 *rid)
1068 return false;
1071 static bool pdb_ads_get_trusteddom_pw(struct pdb_methods *m,
1072 const char *domain, char** pwd,
1073 DOM_SID *sid,
1074 time_t *pass_last_set_time)
1076 return false;
1079 static bool pdb_ads_set_trusteddom_pw(struct pdb_methods *m,
1080 const char* domain, const char* pwd,
1081 const DOM_SID *sid)
1083 return false;
1086 static bool pdb_ads_del_trusteddom_pw(struct pdb_methods *m,
1087 const char *domain)
1089 return false;
1092 static NTSTATUS pdb_ads_enum_trusteddoms(struct pdb_methods *m,
1093 TALLOC_CTX *mem_ctx,
1094 uint32 *num_domains,
1095 struct trustdom_info ***domains)
1097 return NT_STATUS_NOT_IMPLEMENTED;
1100 static void pdb_ads_init_methods(struct pdb_methods *m)
1102 m->name = "ads";
1103 m->getsampwnam = pdb_ads_getsampwnam;
1104 m->getsampwsid = pdb_ads_getsampwsid;
1105 m->create_user = pdb_ads_create_user;
1106 m->delete_user = pdb_ads_delete_user;
1107 m->add_sam_account = pdb_ads_add_sam_account;
1108 m->update_sam_account = pdb_ads_update_sam_account;
1109 m->delete_sam_account = pdb_ads_delete_sam_account;
1110 m->rename_sam_account = pdb_ads_rename_sam_account;
1111 m->update_login_attempts = pdb_ads_update_login_attempts;
1112 m->getgrsid = pdb_ads_getgrsid;
1113 m->getgrgid = pdb_ads_getgrgid;
1114 m->getgrnam = pdb_ads_getgrnam;
1115 m->create_dom_group = pdb_ads_create_dom_group;
1116 m->delete_dom_group = pdb_ads_delete_dom_group;
1117 m->add_group_mapping_entry = pdb_ads_add_group_mapping_entry;
1118 m->update_group_mapping_entry = pdb_ads_update_group_mapping_entry;
1119 m->delete_group_mapping_entry = pdb_ads_delete_group_mapping_entry;
1120 m->enum_group_mapping = pdb_ads_enum_group_mapping;
1121 m->enum_group_members = pdb_ads_enum_group_members;
1122 m->enum_group_memberships = pdb_ads_enum_group_memberships;
1123 m->set_unix_primary_group = pdb_ads_set_unix_primary_group;
1124 m->add_groupmem = pdb_ads_add_groupmem;
1125 m->del_groupmem = pdb_ads_del_groupmem;
1126 m->create_alias = pdb_ads_create_alias;
1127 m->delete_alias = pdb_ads_delete_alias;
1128 m->get_aliasinfo = pdb_ads_get_aliasinfo;
1129 m->set_aliasinfo = pdb_ads_set_aliasinfo;
1130 m->add_aliasmem = pdb_ads_add_aliasmem;
1131 m->del_aliasmem = pdb_ads_del_aliasmem;
1132 m->enum_aliasmem = pdb_ads_enum_aliasmem;
1133 m->enum_alias_memberships = pdb_ads_enum_alias_memberships;
1134 m->lookup_rids = pdb_ads_lookup_rids;
1135 m->lookup_names = pdb_ads_lookup_names;
1136 m->get_account_policy = pdb_ads_get_account_policy;
1137 m->set_account_policy = pdb_ads_set_account_policy;
1138 m->get_seq_num = pdb_ads_get_seq_num;
1139 m->search_users = pdb_ads_search_users;
1140 m->search_groups = pdb_ads_search_groups;
1141 m->search_aliases = pdb_ads_search_aliases;
1142 m->uid_to_rid = pdb_ads_uid_to_rid;
1143 m->uid_to_sid = pdb_ads_uid_to_sid;
1144 m->gid_to_sid = pdb_ads_gid_to_sid;
1145 m->sid_to_id = pdb_ads_sid_to_id;
1146 m->rid_algorithm = pdb_ads_rid_algorithm;
1147 m->new_rid = pdb_ads_new_rid;
1148 m->get_trusteddom_pw = pdb_ads_get_trusteddom_pw;
1149 m->set_trusteddom_pw = pdb_ads_set_trusteddom_pw;
1150 m->del_trusteddom_pw = pdb_ads_del_trusteddom_pw;
1151 m->enum_trusteddoms = pdb_ads_enum_trusteddoms;
1154 static void free_private_data(void **vp)
1156 struct pdb_ads_state *state = talloc_get_type_abort(
1157 *vp, struct pdb_ads_state);
1159 TALLOC_FREE(state->ld);
1160 return;
1163 static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state,
1164 const char *location)
1166 const char *rootdse_attrs[2] = {
1167 "defaultNamingContext", "configurationNamingContext" };
1168 const char *domain_attrs[1] = { "objectSid" };
1169 const char *ncname_attrs[1] = { "netbiosname" };
1170 struct tldap_message **rootdse, **domain, **ncname;
1171 TALLOC_CTX *frame = talloc_stackframe();
1172 struct sockaddr_un sunaddr;
1173 NTSTATUS status;
1174 int num_domains;
1175 int fd, rc;
1177 ZERO_STRUCT(sunaddr);
1178 sunaddr.sun_family = AF_UNIX;
1179 strncpy(sunaddr.sun_path, location, sizeof(sunaddr.sun_path) - 1);
1181 status = open_socket_out((struct sockaddr_storage *)(void *)&sunaddr,
1182 0, 0, &fd);
1183 if (!NT_STATUS_IS_OK(status)) {
1184 DEBUG(10, ("Could not connect to %s: %s\n", location,
1185 nt_errstr(status)));
1186 goto done;
1189 state->ld = tldap_context_create(state, fd);
1190 if (state->ld == NULL) {
1191 close(fd);
1192 status = NT_STATUS_NO_MEMORY;
1193 goto done;
1196 rc = tldap_search_fmt(
1197 state->ld, "", TLDAP_SCOPE_BASE,
1198 rootdse_attrs, ARRAY_SIZE(rootdse_attrs), 0,
1199 talloc_tos(), &rootdse, "(objectclass=*)");
1200 if (rc != TLDAP_SUCCESS) {
1201 DEBUG(10, ("Could not retrieve rootdse: %s\n",
1202 tldap_errstr(debug_ctx(), state->ld, rc)));
1203 status = NT_STATUS_LDAP(rc);
1204 goto done;
1206 if (talloc_array_length(rootdse) != 1) {
1207 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1208 goto done;
1211 state->domaindn = tldap_talloc_single_attribute(
1212 rootdse[0], "defaultNamingContext", state);
1213 if (state->domaindn == NULL) {
1214 DEBUG(10, ("Could not get defaultNamingContext\n"));
1215 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1216 goto done;
1218 DEBUG(10, ("defaultNamingContext = %s\n", state->domaindn));
1220 state->configdn = tldap_talloc_single_attribute(
1221 rootdse[0], "configurationNamingContext", state);
1222 if (state->domaindn == NULL) {
1223 DEBUG(10, ("Could not get configurationNamingContext\n"));
1224 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1225 goto done;
1227 DEBUG(10, ("configurationNamingContext = %s\n", state->configdn));
1230 * Figure out our domain's SID
1232 rc = tldap_search_fmt(
1233 state->ld, state->domaindn, TLDAP_SCOPE_BASE,
1234 domain_attrs, ARRAY_SIZE(domain_attrs), 0,
1235 talloc_tos(), &domain, "(objectclass=*)");
1236 if (rc != TLDAP_SUCCESS) {
1237 DEBUG(10, ("Could not retrieve domain: %s\n",
1238 tldap_errstr(debug_ctx(), state->ld, rc)));
1239 status = NT_STATUS_LDAP(rc);
1240 goto done;
1243 num_domains = talloc_array_length(domain);
1244 if (num_domains != 1) {
1245 DEBUG(10, ("Got %d domains, expected one\n", num_domains));
1246 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1247 goto done;
1249 if (!tldap_pull_binsid(domain[0], "objectSid", &state->domainsid)) {
1250 DEBUG(10, ("Could not retrieve domain SID\n"));
1251 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1252 goto done;
1254 DEBUG(10, ("Domain SID: %s\n", sid_string_dbg(&state->domainsid)));
1257 * Figure out our domain's short name
1259 rc = tldap_search_fmt(
1260 state->ld, state->configdn, TLDAP_SCOPE_SUB,
1261 ncname_attrs, ARRAY_SIZE(ncname_attrs), 0,
1262 talloc_tos(), &ncname, "(ncname=%s)", state->domaindn);
1263 if (rc != TLDAP_SUCCESS) {
1264 DEBUG(10, ("Could not retrieve ncname: %s\n",
1265 tldap_errstr(debug_ctx(), state->ld, rc)));
1266 status = NT_STATUS_LDAP(rc);
1267 goto done;
1269 if (talloc_array_length(ncname) != 1) {
1270 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1271 goto done;
1274 state->netbiosname = tldap_talloc_single_attribute(
1275 ncname[0], "netbiosname", state);
1276 if (state->netbiosname == NULL) {
1277 DEBUG(10, ("Could not get netbiosname\n"));
1278 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1279 goto done;
1281 DEBUG(10, ("netbiosname: %s\n", state->netbiosname));
1283 if (!strequal(lp_workgroup(), state->netbiosname)) {
1284 DEBUG(1, ("ADS is different domain (%s) than ours (%s)\n",
1285 state->netbiosname, lp_workgroup()));
1286 status = NT_STATUS_NO_SUCH_DOMAIN;
1287 goto done;
1290 secrets_store_domain_sid(state->netbiosname, &state->domainsid);
1292 status = NT_STATUS_OK;
1293 done:
1294 TALLOC_FREE(frame);
1295 return status;
1298 static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method,
1299 const char *location)
1301 struct pdb_methods *m;
1302 struct pdb_ads_state *state;
1303 char *tmp = NULL;
1304 NTSTATUS status;
1306 m = talloc(talloc_autofree_context(), struct pdb_methods);
1307 if (m == NULL) {
1308 return NT_STATUS_NO_MEMORY;
1310 state = talloc(m, struct pdb_ads_state);
1311 if (state == NULL) {
1312 goto nomem;
1314 m->private_data = state;
1315 m->free_private_data = free_private_data;
1316 pdb_ads_init_methods(m);
1318 if (location == NULL) {
1319 tmp = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi",
1320 lp_private_dir());
1321 location = tmp;
1323 if (location == NULL) {
1324 goto nomem;
1327 status = pdb_ads_connect(state, location);
1328 if (!NT_STATUS_IS_OK(status)) {
1329 DEBUG(10, ("pdb_ads_connect failed: %s\n", nt_errstr(status)));
1330 goto fail;
1333 *pdb_method = m;
1334 return NT_STATUS_OK;
1335 nomem:
1336 status = NT_STATUS_NO_MEMORY;
1337 fail:
1338 TALLOC_FREE(m);
1339 return status;
1342 NTSTATUS pdb_ads_init(void);
1343 NTSTATUS pdb_ads_init(void)
1345 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "ads",
1346 pdb_init_ads);