s3:idmap_ad: use range from idmap_domain in idmap_ad_sids_to_unixids()
[Samba/gebeck_regimport.git] / source3 / passdb / pdb_ads.c
blob9eb5b6067e2f2e46e3a14620729c0e6afd3ebbf5
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"
23 #include "../libds/common/flags.h"
24 #include "secrets.h"
25 #include "../librpc/gen_ndr/samr.h"
27 struct pdb_ads_state {
28 struct sockaddr_un socket_address;
29 struct tldap_context *ld;
30 struct dom_sid domainsid;
31 struct GUID domainguid;
32 char *domaindn;
33 char *configdn;
34 char *netbiosname;
37 struct pdb_ads_samu_private {
38 char *dn;
39 struct tldap_message *ldapmsg;
42 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
43 struct samu *sam_acct,
44 const struct dom_sid *sid);
45 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
46 struct dom_sid *sid);
47 static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
48 struct dom_sid *psid);
49 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
50 const struct dom_sid *sid,
51 TALLOC_CTX *mem_ctx, char **pdn);
52 static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state);
53 static int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base,
54 int scope, const char *attrs[], int num_attrs,
55 int attrsonly,
56 TALLOC_CTX *mem_ctx, struct tldap_message ***res,
57 const char *fmt, ...);
58 static NTSTATUS pdb_ads_getsamupriv(struct pdb_ads_state *state,
59 const char *filter,
60 TALLOC_CTX *mem_ctx,
61 struct pdb_ads_samu_private **presult);
63 static bool pdb_ads_pull_time(struct tldap_message *msg, const char *attr,
64 time_t *ptime)
66 uint64_t tmp;
68 if (!tldap_pull_uint64(msg, attr, &tmp)) {
69 return false;
71 *ptime = uint64s_nt_time_to_unix_abs(&tmp);
72 return true;
75 static gid_t pdb_ads_sid2gid(const struct dom_sid *sid)
77 uint32_t rid;
78 sid_peek_rid(sid, &rid);
79 return rid;
82 static char *pdb_ads_domaindn2dns(TALLOC_CTX *mem_ctx, char *dn)
84 char *result, *p;
86 result = talloc_string_sub2(mem_ctx, dn, "DC=", "", false, false,
87 true);
88 if (result == NULL) {
89 return NULL;
92 while ((p = strchr_m(result, ',')) != NULL) {
93 *p = '.';
96 return result;
99 static struct pdb_domain_info *pdb_ads_get_domain_info(
100 struct pdb_methods *m, TALLOC_CTX *mem_ctx)
102 struct pdb_ads_state *state = talloc_get_type_abort(
103 m->private_data, struct pdb_ads_state);
104 struct pdb_domain_info *info;
105 struct tldap_message *rootdse;
106 char *tmp;
108 info = talloc(mem_ctx, struct pdb_domain_info);
109 if (info == NULL) {
110 return NULL;
112 info->name = talloc_strdup(info, state->netbiosname);
113 if (info->name == NULL) {
114 goto fail;
116 info->dns_domain = pdb_ads_domaindn2dns(info, state->domaindn);
117 if (info->dns_domain == NULL) {
118 goto fail;
121 rootdse = tldap_rootdse(state->ld);
122 tmp = tldap_talloc_single_attribute(rootdse, "rootDomainNamingContext",
123 talloc_tos());
124 if (tmp == NULL) {
125 goto fail;
127 info->dns_forest = pdb_ads_domaindn2dns(info, tmp);
128 TALLOC_FREE(tmp);
129 if (info->dns_forest == NULL) {
130 goto fail;
132 info->sid = state->domainsid;
133 info->guid = state->domainguid;
134 return info;
136 fail:
137 TALLOC_FREE(info);
138 return NULL;
141 static struct pdb_ads_samu_private *pdb_ads_get_samu_private(
142 struct pdb_methods *m, struct samu *sam)
144 struct pdb_ads_state *state = talloc_get_type_abort(
145 m->private_data, struct pdb_ads_state);
146 struct pdb_ads_samu_private *result;
147 char *sidstr, *filter;
148 NTSTATUS status;
150 result = (struct pdb_ads_samu_private *)
151 pdb_get_backend_private_data(sam, m);
153 if (result != NULL) {
154 return talloc_get_type_abort(
155 result, struct pdb_ads_samu_private);
158 sidstr = sid_binstring(talloc_tos(), pdb_get_user_sid(sam));
159 if (sidstr == NULL) {
160 return NULL;
163 filter = talloc_asprintf(
164 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
165 TALLOC_FREE(sidstr);
166 if (filter == NULL) {
167 return NULL;
170 status = pdb_ads_getsamupriv(state, filter, sam, &result);
171 TALLOC_FREE(filter);
172 if (!NT_STATUS_IS_OK(status)) {
173 return NULL;
176 return result;
179 static NTSTATUS pdb_ads_init_sam_from_priv(struct pdb_methods *m,
180 struct samu *sam,
181 struct pdb_ads_samu_private *priv)
183 struct pdb_ads_state *state = talloc_get_type_abort(
184 m->private_data, struct pdb_ads_state);
185 TALLOC_CTX *frame = talloc_stackframe();
186 NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
187 struct tldap_message *entry = priv->ldapmsg;
188 char *str;
189 time_t tmp_time;
190 struct dom_sid sid;
191 uint64_t n;
192 DATA_BLOB blob;
194 str = tldap_talloc_single_attribute(entry, "samAccountName", sam);
195 if (str == NULL) {
196 DEBUG(10, ("no samAccountName\n"));
197 goto fail;
199 pdb_set_username(sam, str, PDB_SET);
201 if (pdb_ads_pull_time(entry, "lastLogon", &tmp_time)) {
202 pdb_set_logon_time(sam, tmp_time, PDB_SET);
204 if (pdb_ads_pull_time(entry, "lastLogoff", &tmp_time)) {
205 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
207 if (pdb_ads_pull_time(entry, "pwdLastSet", &tmp_time)) {
208 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
210 if (pdb_ads_pull_time(entry, "accountExpires", &tmp_time)) {
211 pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
214 str = tldap_talloc_single_attribute(entry, "displayName",
215 talloc_tos());
216 if (str != NULL) {
217 pdb_set_fullname(sam, str, PDB_SET);
220 str = tldap_talloc_single_attribute(entry, "homeDirectory",
221 talloc_tos());
222 if (str != NULL) {
223 pdb_set_homedir(sam, str, PDB_SET);
226 str = tldap_talloc_single_attribute(entry, "homeDrive", talloc_tos());
227 if (str != NULL) {
228 pdb_set_dir_drive(sam, str, PDB_SET);
231 str = tldap_talloc_single_attribute(entry, "scriptPath", talloc_tos());
232 if (str != NULL) {
233 pdb_set_logon_script(sam, str, PDB_SET);
236 str = tldap_talloc_single_attribute(entry, "profilePath",
237 talloc_tos());
238 if (str != NULL) {
239 pdb_set_profile_path(sam, str, PDB_SET);
242 str = tldap_talloc_single_attribute(entry, "profilePath",
243 talloc_tos());
244 if (str != NULL) {
245 pdb_set_profile_path(sam, str, PDB_SET);
248 if (!tldap_pull_binsid(entry, "objectSid", &sid)) {
249 DEBUG(10, ("Could not pull SID\n"));
250 goto fail;
252 pdb_set_user_sid(sam, &sid, PDB_SET);
254 if (!tldap_pull_uint64(entry, "userAccountControl", &n)) {
255 DEBUG(10, ("Could not pull userAccountControl\n"));
256 goto fail;
258 pdb_set_acct_ctrl(sam, ds_uf2acb(n), PDB_SET);
260 if (tldap_get_single_valueblob(entry, "unicodePwd", &blob)) {
261 if (blob.length != NT_HASH_LEN) {
262 DEBUG(0, ("Got NT hash of length %d, expected %d\n",
263 (int)blob.length, NT_HASH_LEN));
264 goto fail;
266 pdb_set_nt_passwd(sam, blob.data, PDB_SET);
269 if (tldap_get_single_valueblob(entry, "dBCSPwd", &blob)) {
270 if (blob.length != LM_HASH_LEN) {
271 DEBUG(0, ("Got LM hash of length %d, expected %d\n",
272 (int)blob.length, LM_HASH_LEN));
273 goto fail;
275 pdb_set_lanman_passwd(sam, blob.data, PDB_SET);
278 if (tldap_pull_uint64(entry, "primaryGroupID", &n)) {
279 sid_compose(&sid, &state->domainsid, n);
280 pdb_set_group_sid(sam, &sid, PDB_SET);
283 status = NT_STATUS_OK;
284 fail:
285 TALLOC_FREE(frame);
286 return status;
289 static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state,
290 struct tldap_message *existing,
291 TALLOC_CTX *mem_ctx,
292 int *pnum_mods, struct tldap_mod **pmods,
293 struct samu *sam)
295 bool ret = true;
296 DATA_BLOB blob;
298 /* TODO: All fields :-) */
300 ret &= tldap_make_mod_fmt(
301 existing, mem_ctx, pnum_mods, pmods, "displayName",
302 "%s", pdb_get_fullname(sam));
304 blob = data_blob_const(pdb_get_nt_passwd(sam), NT_HASH_LEN);
305 if (blob.data != NULL) {
306 ret &= tldap_add_mod_blobs(mem_ctx, pmods, TLDAP_MOD_REPLACE,
307 "unicodePwd", 1, &blob);
310 blob = data_blob_const(pdb_get_lanman_passwd(sam), NT_HASH_LEN);
311 if (blob.data != NULL) {
312 ret &= tldap_add_mod_blobs(mem_ctx, pmods, TLDAP_MOD_REPLACE,
313 "dBCSPwd", 1, &blob);
316 ret &= tldap_make_mod_fmt(
317 existing, mem_ctx, pnum_mods, pmods, "userAccountControl",
318 "%d", ds_acb2uf(pdb_get_acct_ctrl(sam)));
320 ret &= tldap_make_mod_fmt(
321 existing, mem_ctx, pnum_mods, pmods, "homeDirectory",
322 "%s", pdb_get_homedir(sam));
324 ret &= tldap_make_mod_fmt(
325 existing, mem_ctx, pnum_mods, pmods, "homeDrive",
326 "%s", pdb_get_dir_drive(sam));
328 ret &= tldap_make_mod_fmt(
329 existing, mem_ctx, pnum_mods, pmods, "scriptPath",
330 "%s", pdb_get_logon_script(sam));
332 ret &= tldap_make_mod_fmt(
333 existing, mem_ctx, pnum_mods, pmods, "profilePath",
334 "%s", pdb_get_profile_path(sam));
336 return ret;
339 static NTSTATUS pdb_ads_getsamupriv(struct pdb_ads_state *state,
340 const char *filter,
341 TALLOC_CTX *mem_ctx,
342 struct pdb_ads_samu_private **presult)
344 const char * attrs[] = {
345 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
346 "sAMAccountName", "displayName", "homeDirectory",
347 "homeDrive", "scriptPath", "profilePath", "description",
348 "userWorkstations", "comment", "userParameters", "objectSid",
349 "primaryGroupID", "userAccountControl", "logonHours",
350 "badPwdCount", "logonCount", "countryCode", "codePage",
351 "unicodePwd", "dBCSPwd" };
352 struct tldap_message **users;
353 int rc, count;
354 struct pdb_ads_samu_private *result;
356 result = talloc(mem_ctx, struct pdb_ads_samu_private);
357 if (result == NULL) {
358 return NT_STATUS_NO_MEMORY;
361 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
362 attrs, ARRAY_SIZE(attrs), 0, result,
363 &users, "%s", filter);
364 if (rc != TLDAP_SUCCESS) {
365 DEBUG(10, ("ldap_search failed %s\n",
366 tldap_errstr(talloc_tos(), state->ld, rc)));
367 TALLOC_FREE(result);
368 return NT_STATUS_LDAP(rc);
371 count = talloc_array_length(users);
372 if (count != 1) {
373 DEBUG(10, ("Expected 1 user, got %d\n", count));
374 TALLOC_FREE(result);
375 return NT_STATUS_INTERNAL_DB_CORRUPTION;
378 result->ldapmsg = users[0];
379 if (!tldap_entry_dn(result->ldapmsg, &result->dn)) {
380 DEBUG(10, ("Could not extract dn\n"));
381 TALLOC_FREE(result);
382 return NT_STATUS_INTERNAL_DB_CORRUPTION;
385 *presult = result;
386 return NT_STATUS_OK;
389 static NTSTATUS pdb_ads_getsampwfilter(struct pdb_methods *m,
390 struct pdb_ads_state *state,
391 struct samu *sam_acct,
392 const char *filter)
394 struct pdb_ads_samu_private *priv;
395 NTSTATUS status;
397 status = pdb_ads_getsamupriv(state, filter, sam_acct, &priv);
398 if (!NT_STATUS_IS_OK(status)) {
399 DEBUG(10, ("pdb_ads_getsamupriv failed: %s\n",
400 nt_errstr(status)));
401 return status;
404 status = pdb_ads_init_sam_from_priv(m, sam_acct, priv);
405 if (!NT_STATUS_IS_OK(status)) {
406 DEBUG(10, ("pdb_ads_init_sam_from_priv failed: %s\n",
407 nt_errstr(status)));
408 TALLOC_FREE(priv);
409 return status;
412 pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
413 return NT_STATUS_OK;
416 static NTSTATUS pdb_ads_getsampwnam(struct pdb_methods *m,
417 struct samu *sam_acct,
418 const char *username)
420 struct pdb_ads_state *state = talloc_get_type_abort(
421 m->private_data, struct pdb_ads_state);
422 char *filter;
424 filter = talloc_asprintf(
425 talloc_tos(), "(&(samaccountname=%s)(objectclass=user))",
426 username);
427 NT_STATUS_HAVE_NO_MEMORY(filter);
429 return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
432 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
433 struct samu *sam_acct,
434 const struct dom_sid *sid)
436 struct pdb_ads_state *state = talloc_get_type_abort(
437 m->private_data, struct pdb_ads_state);
438 char *sidstr, *filter;
440 sidstr = sid_binstring(talloc_tos(), sid);
441 NT_STATUS_HAVE_NO_MEMORY(sidstr);
443 filter = talloc_asprintf(
444 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
445 TALLOC_FREE(sidstr);
446 NT_STATUS_HAVE_NO_MEMORY(filter);
448 return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
451 static NTSTATUS pdb_ads_create_user(struct pdb_methods *m,
452 TALLOC_CTX *tmp_ctx,
453 const char *name, uint32 acct_flags,
454 uint32 *rid)
456 struct pdb_ads_state *state = talloc_get_type_abort(
457 m->private_data, struct pdb_ads_state);
458 struct tldap_context *ld;
459 const char *attrs[1] = { "objectSid" };
460 struct tldap_mod *mods = NULL;
461 int num_mods = 0;
462 struct tldap_message **user;
463 struct dom_sid sid;
464 char *dn;
465 int rc;
466 bool ok;
468 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
469 state->domaindn);
470 if (dn == NULL) {
471 return NT_STATUS_NO_MEMORY;
474 ld = pdb_ads_ld(state);
475 if (ld == NULL) {
476 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
479 /* TODO: Create machines etc */
481 ok = true;
482 ok &= tldap_make_mod_fmt(
483 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "user");
484 ok &= tldap_make_mod_fmt(
485 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
486 name);
487 if (!ok) {
488 return NT_STATUS_NO_MEMORY;
492 rc = tldap_add(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
493 if (rc != TLDAP_SUCCESS) {
494 DEBUG(10, ("ldap_add failed %s\n",
495 tldap_errstr(talloc_tos(), ld, rc)));
496 TALLOC_FREE(dn);
497 return NT_STATUS_LDAP(rc);
500 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
501 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
502 &user,
503 "(&(objectclass=user)(samaccountname=%s))",
504 name);
505 if (rc != TLDAP_SUCCESS) {
506 DEBUG(10, ("Could not find just created user %s: %s\n",
507 name, tldap_errstr(talloc_tos(), state->ld, rc)));
508 TALLOC_FREE(dn);
509 return NT_STATUS_LDAP(rc);
512 if (talloc_array_length(user) != 1) {
513 DEBUG(10, ("Got %d users, expected one\n",
514 (int)talloc_array_length(user)));
515 TALLOC_FREE(dn);
516 return NT_STATUS_LDAP(rc);
519 if (!tldap_pull_binsid(user[0], "objectSid", &sid)) {
520 DEBUG(10, ("Could not fetch objectSid from user %s\n",
521 name));
522 TALLOC_FREE(dn);
523 return NT_STATUS_INTERNAL_DB_CORRUPTION;
526 sid_peek_rid(&sid, rid);
527 TALLOC_FREE(dn);
528 return NT_STATUS_OK;
531 static NTSTATUS pdb_ads_delete_user(struct pdb_methods *m,
532 TALLOC_CTX *tmp_ctx,
533 struct samu *sam)
535 struct pdb_ads_state *state = talloc_get_type_abort(
536 m->private_data, struct pdb_ads_state);
537 NTSTATUS status;
538 struct tldap_context *ld;
539 char *dn;
540 int rc;
542 ld = pdb_ads_ld(state);
543 if (ld == NULL) {
544 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
547 status = pdb_ads_sid2dn(state, pdb_get_user_sid(sam), talloc_tos(),
548 &dn);
549 if (!NT_STATUS_IS_OK(status)) {
550 return status;
553 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
554 TALLOC_FREE(dn);
555 if (rc != TLDAP_SUCCESS) {
556 DEBUG(10, ("ldap_delete for %s failed: %s\n", dn,
557 tldap_errstr(talloc_tos(), ld, rc)));
558 return NT_STATUS_LDAP(rc);
560 return NT_STATUS_OK;
563 static NTSTATUS pdb_ads_add_sam_account(struct pdb_methods *m,
564 struct samu *sampass)
566 return NT_STATUS_NOT_IMPLEMENTED;
569 static NTSTATUS pdb_ads_update_sam_account(struct pdb_methods *m,
570 struct samu *sam)
572 struct pdb_ads_state *state = talloc_get_type_abort(
573 m->private_data, struct pdb_ads_state);
574 struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam);
575 struct tldap_context *ld;
576 struct tldap_mod *mods = NULL;
577 int rc, num_mods = 0;
579 ld = pdb_ads_ld(state);
580 if (ld == NULL) {
581 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
584 if (!pdb_ads_init_ads_from_sam(state, priv->ldapmsg, talloc_tos(),
585 &num_mods, &mods, sam)) {
586 return NT_STATUS_NO_MEMORY;
589 if (num_mods == 0) {
590 /* Nothing to do, just return success */
591 return NT_STATUS_OK;
594 rc = tldap_modify(ld, priv->dn, num_mods, mods, NULL, 0,
595 NULL, 0);
596 TALLOC_FREE(mods);
597 if (rc != TLDAP_SUCCESS) {
598 DEBUG(10, ("ldap_modify for %s failed: %s\n", priv->dn,
599 tldap_errstr(talloc_tos(), ld, rc)));
600 return NT_STATUS_LDAP(rc);
603 return NT_STATUS_OK;
606 static NTSTATUS pdb_ads_delete_sam_account(struct pdb_methods *m,
607 struct samu *username)
609 return NT_STATUS_NOT_IMPLEMENTED;
612 static NTSTATUS pdb_ads_rename_sam_account(struct pdb_methods *m,
613 struct samu *oldname,
614 const char *newname)
616 return NT_STATUS_NOT_IMPLEMENTED;
619 static NTSTATUS pdb_ads_update_login_attempts(struct pdb_methods *m,
620 struct samu *sam_acct,
621 bool success)
623 return NT_STATUS_NOT_IMPLEMENTED;
626 static NTSTATUS pdb_ads_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
627 const char *filter)
629 struct pdb_ads_state *state = talloc_get_type_abort(
630 m->private_data, struct pdb_ads_state);
631 const char *attrs[4] = { "objectSid", "description", "samAccountName",
632 "groupType" };
633 char *str;
634 struct tldap_message **group;
635 uint32_t grouptype;
636 int rc;
638 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
639 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
640 &group, "%s", filter);
641 if (rc != TLDAP_SUCCESS) {
642 DEBUG(10, ("ldap_search failed %s\n",
643 tldap_errstr(talloc_tos(), state->ld, rc)));
644 return NT_STATUS_LDAP(rc);
646 if (talloc_array_length(group) != 1) {
647 DEBUG(10, ("Expected 1 user, got %d\n",
648 (int)talloc_array_length(group)));
649 return NT_STATUS_INTERNAL_DB_CORRUPTION;
652 if (!tldap_pull_binsid(group[0], "objectSid", &map->sid)) {
653 return NT_STATUS_INTERNAL_DB_CORRUPTION;
655 map->gid = pdb_ads_sid2gid(&map->sid);
657 if (!tldap_pull_uint32(group[0], "groupType", &grouptype)) {
658 return NT_STATUS_INTERNAL_DB_CORRUPTION;
660 switch (grouptype) {
661 case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
662 case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
663 map->sid_name_use = SID_NAME_ALIAS;
664 break;
665 case GTYPE_SECURITY_GLOBAL_GROUP:
666 map->sid_name_use = SID_NAME_DOM_GRP;
667 break;
668 default:
669 return NT_STATUS_INTERNAL_DB_CORRUPTION;
672 str = tldap_talloc_single_attribute(group[0], "samAccountName",
673 talloc_tos());
674 if (str == NULL) {
675 return NT_STATUS_INTERNAL_DB_CORRUPTION;
677 fstrcpy(map->nt_name, str);
678 TALLOC_FREE(str);
680 str = tldap_talloc_single_attribute(group[0], "description",
681 talloc_tos());
682 if (str != NULL) {
683 fstrcpy(map->comment, str);
684 TALLOC_FREE(str);
685 } else {
686 map->comment[0] = '\0';
689 TALLOC_FREE(group);
690 return NT_STATUS_OK;
693 static NTSTATUS pdb_ads_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
694 struct dom_sid sid)
696 char *filter;
697 NTSTATUS status;
699 filter = talloc_asprintf(talloc_tos(),
700 "(&(objectsid=%s)(objectclass=group))",
701 sid_string_talloc(talloc_tos(), &sid));
702 if (filter == NULL) {
703 return NT_STATUS_NO_MEMORY;
706 status = pdb_ads_getgrfilter(m, map, filter);
707 TALLOC_FREE(filter);
708 return status;
711 static NTSTATUS pdb_ads_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
712 gid_t gid)
714 struct dom_sid sid;
715 pdb_ads_gid_to_sid(m, gid, &sid);
716 return pdb_ads_getgrsid(m, map, sid);
719 static NTSTATUS pdb_ads_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
720 const char *name)
722 char *filter;
723 NTSTATUS status;
725 filter = talloc_asprintf(talloc_tos(),
726 "(&(samaccountname=%s)(objectclass=group))",
727 name);
728 if (filter == NULL) {
729 return NT_STATUS_NO_MEMORY;
732 status = pdb_ads_getgrfilter(m, map, filter);
733 TALLOC_FREE(filter);
734 return status;
737 static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m,
738 TALLOC_CTX *mem_ctx, const char *name,
739 uint32 *rid)
741 TALLOC_CTX *frame = talloc_stackframe();
742 struct pdb_ads_state *state = talloc_get_type_abort(
743 m->private_data, struct pdb_ads_state);
744 struct tldap_context *ld;
745 const char *attrs[1] = { "objectSid" };
746 int num_mods = 0;
747 struct tldap_mod *mods = NULL;
748 struct tldap_message **alias;
749 struct dom_sid sid;
750 char *dn;
751 int rc;
752 bool ok = true;
754 ld = pdb_ads_ld(state);
755 if (ld == NULL) {
756 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
759 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
760 state->domaindn);
761 if (dn == NULL) {
762 TALLOC_FREE(frame);
763 return NT_STATUS_NO_MEMORY;
766 ok &= tldap_make_mod_fmt(
767 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
768 name);
769 ok &= tldap_make_mod_fmt(
770 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "group");
771 ok &= tldap_make_mod_fmt(
772 NULL, talloc_tos(), &num_mods, &mods, "groupType",
773 "%d", (int)GTYPE_SECURITY_GLOBAL_GROUP);
775 if (!ok) {
776 TALLOC_FREE(frame);
777 return NT_STATUS_NO_MEMORY;
780 rc = tldap_add(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
781 if (rc != TLDAP_SUCCESS) {
782 DEBUG(10, ("ldap_add failed %s\n",
783 tldap_errstr(talloc_tos(), state->ld, rc)));
784 TALLOC_FREE(frame);
785 return NT_STATUS_LDAP(rc);
788 rc = pdb_ads_search_fmt(
789 state, state->domaindn, TLDAP_SCOPE_SUB,
790 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
791 "(&(objectclass=group)(samaccountname=%s))", name);
792 if (rc != TLDAP_SUCCESS) {
793 DEBUG(10, ("Could not find just created alias %s: %s\n",
794 name, tldap_errstr(talloc_tos(), state->ld, rc)));
795 TALLOC_FREE(frame);
796 return NT_STATUS_LDAP(rc);
799 if (talloc_array_length(alias) != 1) {
800 DEBUG(10, ("Got %d alias, expected one\n",
801 (int)talloc_array_length(alias)));
802 TALLOC_FREE(frame);
803 return NT_STATUS_LDAP(rc);
806 if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
807 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
808 name));
809 TALLOC_FREE(frame);
810 return NT_STATUS_INTERNAL_DB_CORRUPTION;
813 sid_peek_rid(&sid, rid);
814 TALLOC_FREE(frame);
815 return NT_STATUS_OK;
818 static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m,
819 TALLOC_CTX *mem_ctx, uint32 rid)
821 struct pdb_ads_state *state = talloc_get_type_abort(
822 m->private_data, struct pdb_ads_state);
823 struct tldap_context *ld;
824 struct dom_sid sid;
825 char *sidstr;
826 struct tldap_message **msg;
827 char *dn;
828 int rc;
830 sid_compose(&sid, &state->domainsid, rid);
832 sidstr = sid_binstring(talloc_tos(), &sid);
833 NT_STATUS_HAVE_NO_MEMORY(sidstr);
835 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
836 NULL, 0, 0, talloc_tos(), &msg,
837 ("(&(objectSid=%s)(objectClass=group))"),
838 sidstr);
839 TALLOC_FREE(sidstr);
840 if (rc != TLDAP_SUCCESS) {
841 DEBUG(10, ("ldap_search failed %s\n",
842 tldap_errstr(talloc_tos(), state->ld, rc)));
843 return NT_STATUS_LDAP(rc);
846 switch talloc_array_length(msg) {
847 case 0:
848 return NT_STATUS_NO_SUCH_GROUP;
849 case 1:
850 break;
851 default:
852 return NT_STATUS_INTERNAL_DB_CORRUPTION;
855 if (!tldap_entry_dn(msg[0], &dn)) {
856 TALLOC_FREE(msg);
857 return NT_STATUS_INTERNAL_DB_CORRUPTION;
860 ld = pdb_ads_ld(state);
861 if (ld == NULL) {
862 TALLOC_FREE(msg);
863 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
866 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
867 TALLOC_FREE(msg);
868 if (rc != TLDAP_SUCCESS) {
869 DEBUG(10, ("ldap_delete failed: %s\n",
870 tldap_errstr(talloc_tos(), state->ld, rc)));
871 return NT_STATUS_LDAP(rc);
874 return NT_STATUS_OK;
877 static NTSTATUS pdb_ads_add_group_mapping_entry(struct pdb_methods *m,
878 GROUP_MAP *map)
880 return NT_STATUS_NOT_IMPLEMENTED;
883 static NTSTATUS pdb_ads_update_group_mapping_entry(struct pdb_methods *m,
884 GROUP_MAP *map)
886 return NT_STATUS_NOT_IMPLEMENTED;
889 static NTSTATUS pdb_ads_delete_group_mapping_entry(struct pdb_methods *m,
890 struct dom_sid sid)
892 return NT_STATUS_NOT_IMPLEMENTED;
895 static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m,
896 const struct dom_sid *sid,
897 enum lsa_SidType sid_name_use,
898 GROUP_MAP **pp_rmap,
899 size_t *p_num_entries,
900 bool unix_only)
902 return NT_STATUS_NOT_IMPLEMENTED;
905 static NTSTATUS pdb_ads_enum_group_members(struct pdb_methods *m,
906 TALLOC_CTX *mem_ctx,
907 const struct dom_sid *group,
908 uint32 **pmembers,
909 size_t *pnum_members)
911 struct pdb_ads_state *state = talloc_get_type_abort(
912 m->private_data, struct pdb_ads_state);
913 const char *attrs[1] = { "member" };
914 char *sidstr;
915 struct tldap_message **msg;
916 int i, rc, num_members;
917 DATA_BLOB *blobs;
918 uint32_t *members;
920 sidstr = sid_binstring(talloc_tos(), group);
921 NT_STATUS_HAVE_NO_MEMORY(sidstr);
923 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
924 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
925 &msg, "(objectsid=%s)", sidstr);
926 TALLOC_FREE(sidstr);
927 if (rc != TLDAP_SUCCESS) {
928 DEBUG(10, ("ldap_search failed %s\n",
929 tldap_errstr(talloc_tos(), state->ld, rc)));
930 return NT_STATUS_LDAP(rc);
932 switch talloc_array_length(msg) {
933 case 0:
934 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
935 break;
936 case 1:
937 break;
938 default:
939 return NT_STATUS_INTERNAL_DB_CORRUPTION;
940 break;
943 if (!tldap_entry_values(msg[0], "member", &num_members, &blobs)) {
944 return NT_STATUS_INTERNAL_DB_CORRUPTION;
947 members = talloc_array(mem_ctx, uint32_t, num_members);
948 if (members == NULL) {
949 return NT_STATUS_NO_MEMORY;
952 for (i=0; i<num_members; i++) {
953 struct dom_sid sid;
954 if (!pdb_ads_dnblob2sid(state, &blobs[i], &sid)
955 || !sid_peek_rid(&sid, &members[i])) {
956 TALLOC_FREE(members);
957 return NT_STATUS_INTERNAL_DB_CORRUPTION;
961 *pmembers = members;
962 *pnum_members = num_members;
963 return NT_STATUS_OK;
966 static NTSTATUS pdb_ads_enum_group_memberships(struct pdb_methods *m,
967 TALLOC_CTX *mem_ctx,
968 struct samu *user,
969 struct dom_sid **pp_sids,
970 gid_t **pp_gids,
971 size_t *p_num_groups)
973 struct pdb_ads_state *state = talloc_get_type_abort(
974 m->private_data, struct pdb_ads_state);
975 struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(
976 m, user);
977 const char *attrs[1] = { "objectSid" };
978 struct tldap_message **groups;
979 int i, rc, count;
980 size_t num_groups;
981 struct dom_sid *group_sids;
982 gid_t *gids;
984 rc = pdb_ads_search_fmt(
985 state, state->domaindn, TLDAP_SCOPE_SUB,
986 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &groups,
987 "(&(member=%s)(grouptype=%d)(objectclass=group))",
988 priv->dn, GTYPE_SECURITY_GLOBAL_GROUP);
989 if (rc != TLDAP_SUCCESS) {
990 DEBUG(10, ("ldap_search failed %s\n",
991 tldap_errstr(talloc_tos(), state->ld, rc)));
992 return NT_STATUS_LDAP(rc);
995 count = talloc_array_length(groups);
997 group_sids = talloc_array(mem_ctx, struct dom_sid, count);
998 if (group_sids == NULL) {
999 return NT_STATUS_NO_MEMORY;
1001 gids = talloc_array(mem_ctx, gid_t, count);
1002 if (gids == NULL) {
1003 TALLOC_FREE(group_sids);
1004 return NT_STATUS_NO_MEMORY;
1006 num_groups = 0;
1008 for (i=0; i<count; i++) {
1009 if (!tldap_pull_binsid(groups[i], "objectSid",
1010 &group_sids[num_groups])) {
1011 continue;
1013 gids[num_groups] = pdb_ads_sid2gid(&group_sids[num_groups]);
1015 num_groups += 1;
1016 if (num_groups == count) {
1017 break;
1021 *pp_sids = group_sids;
1022 *pp_gids = gids;
1023 *p_num_groups = num_groups;
1024 return NT_STATUS_OK;
1027 static NTSTATUS pdb_ads_set_unix_primary_group(struct pdb_methods *m,
1028 TALLOC_CTX *mem_ctx,
1029 struct samu *user)
1031 return NT_STATUS_NOT_IMPLEMENTED;
1034 static NTSTATUS pdb_ads_mod_groupmem(struct pdb_methods *m,
1035 TALLOC_CTX *mem_ctx,
1036 uint32 grouprid, uint32 memberrid,
1037 int mod_op)
1039 struct pdb_ads_state *state = talloc_get_type_abort(
1040 m->private_data, struct pdb_ads_state);
1041 TALLOC_CTX *frame = talloc_stackframe();
1042 struct tldap_context *ld;
1043 struct dom_sid groupsid, membersid;
1044 char *groupdn, *memberdn;
1045 struct tldap_mod *mods;
1046 int rc;
1047 NTSTATUS status;
1049 ld = pdb_ads_ld(state);
1050 if (ld == NULL) {
1051 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1054 sid_compose(&groupsid, &state->domainsid, grouprid);
1055 sid_compose(&membersid, &state->domainsid, memberrid);
1057 status = pdb_ads_sid2dn(state, &groupsid, talloc_tos(), &groupdn);
1058 if (!NT_STATUS_IS_OK(status)) {
1059 TALLOC_FREE(frame);
1060 return NT_STATUS_NO_SUCH_GROUP;
1062 status = pdb_ads_sid2dn(state, &membersid, talloc_tos(), &memberdn);
1063 if (!NT_STATUS_IS_OK(status)) {
1064 TALLOC_FREE(frame);
1065 return NT_STATUS_NO_SUCH_USER;
1068 mods = NULL;
1070 if (!tldap_add_mod_str(talloc_tos(), &mods, mod_op,
1071 "member", memberdn)) {
1072 TALLOC_FREE(frame);
1073 return NT_STATUS_NO_MEMORY;
1076 rc = tldap_modify(ld, groupdn, 1, mods, NULL, 0, NULL, 0);
1077 TALLOC_FREE(frame);
1078 if (rc != TLDAP_SUCCESS) {
1079 DEBUG(10, ("ldap_modify failed: %s\n",
1080 tldap_errstr(talloc_tos(), state->ld, rc)));
1081 if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) {
1082 return NT_STATUS_MEMBER_IN_GROUP;
1084 if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
1085 return NT_STATUS_MEMBER_NOT_IN_GROUP;
1087 return NT_STATUS_LDAP(rc);
1090 return NT_STATUS_OK;
1093 static NTSTATUS pdb_ads_add_groupmem(struct pdb_methods *m,
1094 TALLOC_CTX *mem_ctx,
1095 uint32 group_rid, uint32 member_rid)
1097 return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1098 TLDAP_MOD_ADD);
1101 static NTSTATUS pdb_ads_del_groupmem(struct pdb_methods *m,
1102 TALLOC_CTX *mem_ctx,
1103 uint32 group_rid, uint32 member_rid)
1105 return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1106 TLDAP_MOD_DELETE);
1109 static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m,
1110 const char *name, uint32 *rid)
1112 TALLOC_CTX *frame = talloc_stackframe();
1113 struct pdb_ads_state *state = talloc_get_type_abort(
1114 m->private_data, struct pdb_ads_state);
1115 struct tldap_context *ld;
1116 const char *attrs[1] = { "objectSid" };
1117 int num_mods = 0;
1118 struct tldap_mod *mods = NULL;
1119 struct tldap_message **alias;
1120 struct dom_sid sid;
1121 char *dn;
1122 int rc;
1123 bool ok = true;
1125 ld = pdb_ads_ld(state);
1126 if (ld == NULL) {
1127 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1130 dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
1131 state->domaindn);
1132 if (dn == NULL) {
1133 TALLOC_FREE(frame);
1134 return NT_STATUS_NO_MEMORY;
1137 ok &= tldap_make_mod_fmt(
1138 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
1139 name);
1140 ok &= tldap_make_mod_fmt(
1141 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "group");
1142 ok &= tldap_make_mod_fmt(
1143 NULL, talloc_tos(), &num_mods, &mods, "groupType",
1144 "%d", (int)GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1146 if (!ok) {
1147 TALLOC_FREE(frame);
1148 return NT_STATUS_NO_MEMORY;
1151 rc = tldap_add(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
1152 if (rc != TLDAP_SUCCESS) {
1153 DEBUG(10, ("ldap_add failed %s\n",
1154 tldap_errstr(talloc_tos(), state->ld, rc)));
1155 TALLOC_FREE(frame);
1156 return NT_STATUS_LDAP(rc);
1159 rc = pdb_ads_search_fmt(
1160 state, state->domaindn, TLDAP_SCOPE_SUB,
1161 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
1162 "(&(objectclass=group)(samaccountname=%s))", name);
1163 if (rc != TLDAP_SUCCESS) {
1164 DEBUG(10, ("Could not find just created alias %s: %s\n",
1165 name, tldap_errstr(talloc_tos(), state->ld, rc)));
1166 TALLOC_FREE(frame);
1167 return NT_STATUS_LDAP(rc);
1170 if (talloc_array_length(alias) != 1) {
1171 DEBUG(10, ("Got %d alias, expected one\n",
1172 (int)talloc_array_length(alias)));
1173 TALLOC_FREE(frame);
1174 return NT_STATUS_LDAP(rc);
1177 if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
1178 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
1179 name));
1180 TALLOC_FREE(frame);
1181 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1184 sid_peek_rid(&sid, rid);
1185 TALLOC_FREE(frame);
1186 return NT_STATUS_OK;
1189 static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m,
1190 const struct dom_sid *sid)
1192 struct pdb_ads_state *state = talloc_get_type_abort(
1193 m->private_data, struct pdb_ads_state);
1194 struct tldap_context *ld;
1195 struct tldap_message **alias;
1196 char *sidstr, *dn = NULL;
1197 int rc;
1199 ld = pdb_ads_ld(state);
1200 if (ld == NULL) {
1201 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1204 sidstr = sid_binstring(talloc_tos(), sid);
1205 if (sidstr == NULL) {
1206 return NT_STATUS_NO_MEMORY;
1209 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1210 NULL, 0, 0, talloc_tos(), &alias,
1211 "(&(objectSid=%s)(objectclass=group)"
1212 "(|(grouptype=%d)(grouptype=%d)))",
1213 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1214 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1215 TALLOC_FREE(sidstr);
1216 if (rc != TLDAP_SUCCESS) {
1217 DEBUG(10, ("ldap_search failed: %s\n",
1218 tldap_errstr(talloc_tos(), state->ld, rc)));
1219 return NT_STATUS_LDAP(rc);
1221 if (talloc_array_length(alias) != 1) {
1222 DEBUG(10, ("Expected 1 alias, got %d\n",
1223 (int)talloc_array_length(alias)));
1224 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1226 if (!tldap_entry_dn(alias[0], &dn)) {
1227 DEBUG(10, ("Could not get DN for alias %s\n",
1228 sid_string_dbg(sid)));
1229 return NT_STATUS_INTERNAL_ERROR;
1232 rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
1233 if (rc != TLDAP_SUCCESS) {
1234 DEBUG(10, ("ldap_delete failed: %s\n",
1235 tldap_errstr(talloc_tos(), state->ld, rc)));
1236 return NT_STATUS_LDAP(rc);
1239 return NT_STATUS_OK;
1242 static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m,
1243 const struct dom_sid *sid,
1244 struct acct_info *info)
1246 struct pdb_ads_state *state = talloc_get_type_abort(
1247 m->private_data, struct pdb_ads_state);
1248 struct tldap_context *ld;
1249 const char *attrs[3] = { "objectSid", "description",
1250 "samAccountName" };
1251 struct tldap_message **msg;
1252 char *sidstr, *dn;
1253 int rc;
1254 struct tldap_mod *mods;
1255 int num_mods;
1256 bool ok;
1258 ld = pdb_ads_ld(state);
1259 if (ld == NULL) {
1260 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1263 sidstr = sid_binstring(talloc_tos(), sid);
1264 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1266 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1267 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1268 &msg, "(&(objectSid=%s)(objectclass=group)"
1269 "(|(grouptype=%d)(grouptype=%d)))",
1270 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1271 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1272 TALLOC_FREE(sidstr);
1273 if (rc != TLDAP_SUCCESS) {
1274 DEBUG(10, ("ldap_search failed %s\n",
1275 tldap_errstr(talloc_tos(), state->ld, rc)));
1276 return NT_STATUS_LDAP(rc);
1278 switch talloc_array_length(msg) {
1279 case 0:
1280 return NT_STATUS_NO_SUCH_ALIAS;
1281 case 1:
1282 break;
1283 default:
1284 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1287 if (!tldap_entry_dn(msg[0], &dn)) {
1288 TALLOC_FREE(msg);
1289 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1292 mods = NULL;
1293 num_mods = 0;
1294 ok = true;
1296 ok &= tldap_make_mod_fmt(
1297 msg[0], msg, &num_mods, &mods, "description",
1298 "%s", info->acct_desc);
1299 ok &= tldap_make_mod_fmt(
1300 msg[0], msg, &num_mods, &mods, "samAccountName",
1301 "%s", info->acct_name);
1302 if (!ok) {
1303 TALLOC_FREE(msg);
1304 return NT_STATUS_NO_MEMORY;
1306 if (num_mods == 0) {
1307 /* no change */
1308 TALLOC_FREE(msg);
1309 return NT_STATUS_OK;
1312 rc = tldap_modify(ld, dn, num_mods, mods, NULL, 0, NULL, 0);
1313 TALLOC_FREE(msg);
1314 if (rc != TLDAP_SUCCESS) {
1315 DEBUG(10, ("ldap_modify failed: %s\n",
1316 tldap_errstr(talloc_tos(), state->ld, rc)));
1317 return NT_STATUS_LDAP(rc);
1319 return NT_STATUS_OK;
1322 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
1323 const struct dom_sid *sid,
1324 TALLOC_CTX *mem_ctx, char **pdn)
1326 struct tldap_message **msg;
1327 char *sidstr, *dn;
1328 int rc;
1330 sidstr = sid_binstring(talloc_tos(), sid);
1331 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1333 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1334 NULL, 0, 0, talloc_tos(), &msg,
1335 "(objectsid=%s)", sidstr);
1336 TALLOC_FREE(sidstr);
1337 if (rc != TLDAP_SUCCESS) {
1338 DEBUG(10, ("ldap_search failed %s\n",
1339 tldap_errstr(talloc_tos(), state->ld, rc)));
1340 return NT_STATUS_LDAP(rc);
1343 switch talloc_array_length(msg) {
1344 case 0:
1345 return NT_STATUS_NOT_FOUND;
1346 case 1:
1347 break;
1348 default:
1349 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1352 if (!tldap_entry_dn(msg[0], &dn)) {
1353 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1356 dn = talloc_strdup(mem_ctx, dn);
1357 if (dn == NULL) {
1358 return NT_STATUS_NO_MEMORY;
1360 TALLOC_FREE(msg);
1362 *pdn = dn;
1363 return NT_STATUS_OK;
1366 static NTSTATUS pdb_ads_mod_aliasmem(struct pdb_methods *m,
1367 const struct dom_sid *alias,
1368 const struct dom_sid *member,
1369 int mod_op)
1371 struct pdb_ads_state *state = talloc_get_type_abort(
1372 m->private_data, struct pdb_ads_state);
1373 struct tldap_context *ld;
1374 TALLOC_CTX *frame = talloc_stackframe();
1375 struct tldap_mod *mods;
1376 int rc;
1377 char *aliasdn, *memberdn;
1378 NTSTATUS status;
1380 ld = pdb_ads_ld(state);
1381 if (ld == NULL) {
1382 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1385 status = pdb_ads_sid2dn(state, alias, talloc_tos(), &aliasdn);
1386 if (!NT_STATUS_IS_OK(status)) {
1387 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1388 sid_string_dbg(alias), nt_errstr(status)));
1389 TALLOC_FREE(frame);
1390 return NT_STATUS_NO_SUCH_ALIAS;
1392 status = pdb_ads_sid2dn(state, member, talloc_tos(), &memberdn);
1393 if (!NT_STATUS_IS_OK(status)) {
1394 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1395 sid_string_dbg(member), nt_errstr(status)));
1396 TALLOC_FREE(frame);
1397 return status;
1400 mods = NULL;
1402 if (!tldap_add_mod_str(talloc_tos(), &mods, mod_op,
1403 "member", memberdn)) {
1404 TALLOC_FREE(frame);
1405 return NT_STATUS_NO_MEMORY;
1408 rc = tldap_modify(ld, aliasdn, 1, mods, NULL, 0, NULL, 0);
1409 TALLOC_FREE(frame);
1410 if (rc != TLDAP_SUCCESS) {
1411 DEBUG(10, ("ldap_modify failed: %s\n",
1412 tldap_errstr(talloc_tos(), state->ld, rc)));
1413 if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) {
1414 return NT_STATUS_MEMBER_IN_ALIAS;
1416 if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
1417 return NT_STATUS_MEMBER_NOT_IN_ALIAS;
1419 return NT_STATUS_LDAP(rc);
1422 return NT_STATUS_OK;
1425 static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
1426 const struct dom_sid *alias,
1427 const struct dom_sid *member)
1429 return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_ADD);
1432 static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
1433 const struct dom_sid *alias,
1434 const struct dom_sid *member)
1436 return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_DELETE);
1439 static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
1440 struct dom_sid *psid)
1442 const char *attrs[1] = { "objectSid" };
1443 struct tldap_message **msg;
1444 char *dn;
1445 size_t len;
1446 int rc;
1447 bool ret;
1449 if (!convert_string_talloc(talloc_tos(), CH_UTF8, CH_UNIX,
1450 dnblob->data, dnblob->length, &dn, &len,
1451 false)) {
1452 return false;
1454 rc = pdb_ads_search_fmt(state, dn, TLDAP_SCOPE_BASE,
1455 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1456 &msg, "(objectclass=*)");
1457 TALLOC_FREE(dn);
1458 if (talloc_array_length(msg) != 1) {
1459 DEBUG(10, ("Got %d objects, expected one\n",
1460 (int)talloc_array_length(msg)));
1461 TALLOC_FREE(msg);
1462 return false;
1465 ret = tldap_pull_binsid(msg[0], "objectSid", psid);
1466 TALLOC_FREE(msg);
1467 return ret;
1470 static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
1471 const struct dom_sid *alias,
1472 TALLOC_CTX *mem_ctx,
1473 struct dom_sid **pmembers,
1474 size_t *pnum_members)
1476 struct pdb_ads_state *state = talloc_get_type_abort(
1477 m->private_data, struct pdb_ads_state);
1478 const char *attrs[1] = { "member" };
1479 char *sidstr;
1480 struct tldap_message **msg;
1481 int i, rc, num_members;
1482 DATA_BLOB *blobs;
1483 struct dom_sid *members;
1485 sidstr = sid_binstring(talloc_tos(), alias);
1486 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1488 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1489 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1490 &msg, "(objectsid=%s)", sidstr);
1491 TALLOC_FREE(sidstr);
1492 if (rc != TLDAP_SUCCESS) {
1493 DEBUG(10, ("ldap_search failed %s\n",
1494 tldap_errstr(talloc_tos(), state->ld, rc)));
1495 return NT_STATUS_LDAP(rc);
1497 switch talloc_array_length(msg) {
1498 case 0:
1499 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1500 break;
1501 case 1:
1502 break;
1503 default:
1504 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1505 break;
1508 if (!tldap_entry_values(msg[0], "member", &num_members, &blobs)) {
1509 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1512 members = talloc_array(mem_ctx, struct dom_sid, num_members);
1513 if (members == NULL) {
1514 return NT_STATUS_NO_MEMORY;
1517 for (i=0; i<num_members; i++) {
1518 if (!pdb_ads_dnblob2sid(state, &blobs[i], &members[i])) {
1519 TALLOC_FREE(members);
1520 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1524 *pmembers = members;
1525 *pnum_members = num_members;
1526 return NT_STATUS_OK;
1529 static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,
1530 TALLOC_CTX *mem_ctx,
1531 const struct dom_sid *domain_sid,
1532 const struct dom_sid *members,
1533 size_t num_members,
1534 uint32_t **palias_rids,
1535 size_t *pnum_alias_rids)
1537 struct pdb_ads_state *state = talloc_get_type_abort(
1538 m->private_data, struct pdb_ads_state);
1539 const char *attrs[1] = { "objectSid" };
1540 struct tldap_message **msg = NULL;
1541 uint32_t *alias_rids = NULL;
1542 size_t num_alias_rids = 0;
1543 int i, rc, count;
1544 bool got_members = false;
1545 char *filter;
1546 NTSTATUS status;
1549 * TODO: Get the filter right so that we only get the aliases from
1550 * either the SAM or BUILTIN
1553 filter = talloc_asprintf(talloc_tos(),
1554 "(&(|(grouptype=%d)(grouptype=%d))"
1555 "(objectclass=group)(|",
1556 GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1557 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1558 if (filter == NULL) {
1559 return NT_STATUS_NO_MEMORY;
1562 for (i=0; i<num_members; i++) {
1563 char *dn;
1565 status = pdb_ads_sid2dn(state, &members[i], talloc_tos(), &dn);
1566 if (!NT_STATUS_IS_OK(status)) {
1567 DEBUG(10, ("pdb_ads_sid2dn failed for %s: %s\n",
1568 sid_string_dbg(&members[i]),
1569 nt_errstr(status)));
1570 continue;
1572 filter = talloc_asprintf_append_buffer(
1573 filter, "(member=%s)", dn);
1574 TALLOC_FREE(dn);
1575 if (filter == NULL) {
1576 return NT_STATUS_NO_MEMORY;
1578 got_members = true;
1581 if (!got_members) {
1582 goto done;
1585 rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1586 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1587 &msg, "%s))", filter);
1588 TALLOC_FREE(filter);
1589 if (rc != TLDAP_SUCCESS) {
1590 DEBUG(10, ("tldap_search failed %s\n",
1591 tldap_errstr(talloc_tos(), state->ld, rc)));
1592 return NT_STATUS_LDAP(rc);
1595 count = talloc_array_length(msg);
1596 if (count == 0) {
1597 goto done;
1600 alias_rids = talloc_array(mem_ctx, uint32_t, count);
1601 if (alias_rids == NULL) {
1602 TALLOC_FREE(msg);
1603 return NT_STATUS_NO_MEMORY;
1606 for (i=0; i<count; i++) {
1607 struct dom_sid sid;
1609 if (!tldap_pull_binsid(msg[i], "objectSid", &sid)) {
1610 DEBUG(10, ("Could not pull SID for member %d\n", i));
1611 continue;
1613 if (sid_peek_check_rid(domain_sid, &sid,
1614 &alias_rids[num_alias_rids])) {
1615 num_alias_rids += 1;
1618 done:
1619 TALLOC_FREE(msg);
1620 *palias_rids = alias_rids;
1621 *pnum_alias_rids = 0;
1622 return NT_STATUS_OK;
1625 static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m,
1626 const struct dom_sid *domain_sid,
1627 int num_rids,
1628 uint32 *rids,
1629 const char **names,
1630 enum lsa_SidType *lsa_attrs)
1632 struct pdb_ads_state *state = talloc_get_type_abort(
1633 m->private_data, struct pdb_ads_state);
1634 const char *attrs[2] = { "sAMAccountType", "sAMAccountName" };
1635 int i, num_mapped;
1637 if (num_rids == 0) {
1638 return NT_STATUS_NONE_MAPPED;
1641 num_mapped = 0;
1643 for (i=0; i<num_rids; i++) {
1644 struct dom_sid sid;
1645 struct tldap_message **msg;
1646 char *sidstr;
1647 uint32_t attr;
1648 int rc;
1650 lsa_attrs[i] = SID_NAME_UNKNOWN;
1652 sid_compose(&sid, domain_sid, rids[i]);
1654 sidstr = sid_binstring(talloc_tos(), &sid);
1655 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1657 rc = pdb_ads_search_fmt(state, state->domaindn,
1658 TLDAP_SCOPE_SUB, attrs,
1659 ARRAY_SIZE(attrs), 0, talloc_tos(),
1660 &msg, "(objectsid=%s)", sidstr);
1661 TALLOC_FREE(sidstr);
1662 if (rc != TLDAP_SUCCESS) {
1663 DEBUG(10, ("ldap_search failed %s\n",
1664 tldap_errstr(talloc_tos(), state->ld, rc)));
1665 continue;
1668 switch talloc_array_length(msg) {
1669 case 0:
1670 DEBUG(10, ("rid %d not found\n", (int)rids[i]));
1671 continue;
1672 case 1:
1673 break;
1674 default:
1675 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1678 names[i] = tldap_talloc_single_attribute(
1679 msg[0], "samAccountName", talloc_tos());
1680 if (names[i] == NULL) {
1681 DEBUG(10, ("no samAccountName\n"));
1682 continue;
1684 if (!tldap_pull_uint32(msg[0], "samAccountType", &attr)) {
1685 DEBUG(10, ("no samAccountType"));
1686 continue;
1688 lsa_attrs[i] = ds_atype_map(attr);
1689 num_mapped += 1;
1692 if (num_mapped == 0) {
1693 return NT_STATUS_NONE_MAPPED;
1695 if (num_mapped < num_rids) {
1696 return STATUS_SOME_UNMAPPED;
1698 return NT_STATUS_OK;
1701 static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m,
1702 const struct dom_sid *domain_sid,
1703 int num_names,
1704 const char **pp_names,
1705 uint32 *rids,
1706 enum lsa_SidType *attrs)
1708 return NT_STATUS_NOT_IMPLEMENTED;
1711 static NTSTATUS pdb_ads_get_account_policy(struct pdb_methods *m,
1712 enum pdb_policy_type type,
1713 uint32_t *value)
1715 return account_policy_get(type, value)
1716 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1719 static NTSTATUS pdb_ads_set_account_policy(struct pdb_methods *m,
1720 enum pdb_policy_type type,
1721 uint32_t value)
1723 return account_policy_set(type, value)
1724 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1727 static NTSTATUS pdb_ads_get_seq_num(struct pdb_methods *m,
1728 time_t *seq_num)
1730 return NT_STATUS_NOT_IMPLEMENTED;
1733 struct pdb_ads_search_state {
1734 uint32_t acct_flags;
1735 struct samr_displayentry *entries;
1736 uint32_t num_entries;
1737 ssize_t array_size;
1738 uint32_t current;
1741 static bool pdb_ads_next_entry(struct pdb_search *search,
1742 struct samr_displayentry *entry)
1744 struct pdb_ads_search_state *state = talloc_get_type_abort(
1745 search->private_data, struct pdb_ads_search_state);
1747 if (state->current == state->num_entries) {
1748 return false;
1751 entry->idx = state->entries[state->current].idx;
1752 entry->rid = state->entries[state->current].rid;
1753 entry->acct_flags = state->entries[state->current].acct_flags;
1755 entry->account_name = talloc_strdup(
1756 search, state->entries[state->current].account_name);
1757 entry->fullname = talloc_strdup(
1758 search, state->entries[state->current].fullname);
1759 entry->description = talloc_strdup(
1760 search, state->entries[state->current].description);
1762 if ((entry->account_name == NULL) || (entry->fullname == NULL)
1763 || (entry->description == NULL)) {
1764 DEBUG(0, ("talloc_strdup failed\n"));
1765 return false;
1768 state->current += 1;
1769 return true;
1772 static void pdb_ads_search_end(struct pdb_search *search)
1774 struct pdb_ads_search_state *state = talloc_get_type_abort(
1775 search->private_data, struct pdb_ads_search_state);
1776 TALLOC_FREE(state);
1779 static bool pdb_ads_search_filter(struct pdb_methods *m,
1780 struct pdb_search *search,
1781 const char *filter,
1782 struct pdb_ads_search_state **pstate)
1784 struct pdb_ads_state *state = talloc_get_type_abort(
1785 m->private_data, struct pdb_ads_state);
1786 struct pdb_ads_search_state *sstate;
1787 const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1788 "userAccountControl", "description" };
1789 struct tldap_message **users;
1790 int i, rc, num_users;
1792 sstate = talloc_zero(search, struct pdb_ads_search_state);
1793 if (sstate == NULL) {
1794 return false;
1797 rc = pdb_ads_search_fmt(
1798 state, state->domaindn, TLDAP_SCOPE_SUB,
1799 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &users,
1800 "%s", filter);
1801 if (rc != TLDAP_SUCCESS) {
1802 DEBUG(10, ("ldap_search_ext_s failed: %s\n",
1803 tldap_errstr(talloc_tos(), state->ld, rc)));
1804 return false;
1807 num_users = talloc_array_length(users);
1809 sstate->entries = talloc_array(sstate, struct samr_displayentry,
1810 num_users);
1811 if (sstate->entries == NULL) {
1812 DEBUG(10, ("talloc failed\n"));
1813 return false;
1816 sstate->num_entries = 0;
1818 for (i=0; i<num_users; i++) {
1819 struct samr_displayentry *e;
1820 struct dom_sid sid;
1822 e = &sstate->entries[sstate->num_entries];
1824 e->idx = sstate->num_entries;
1825 if (!tldap_pull_binsid(users[i], "objectSid", &sid)) {
1826 DEBUG(10, ("Could not pull sid\n"));
1827 continue;
1829 sid_peek_rid(&sid, &e->rid);
1830 e->acct_flags = ACB_NORMAL;
1831 e->account_name = tldap_talloc_single_attribute(
1832 users[i], "samAccountName", sstate->entries);
1833 if (e->account_name == NULL) {
1834 return false;
1836 e->fullname = tldap_talloc_single_attribute(
1837 users[i], "displayName", sstate->entries);
1838 if (e->fullname == NULL) {
1839 e->fullname = "";
1841 e->description = tldap_talloc_single_attribute(
1842 users[i], "description", sstate->entries);
1843 if (e->description == NULL) {
1844 e->description = "";
1847 sstate->num_entries += 1;
1848 if (sstate->num_entries >= num_users) {
1849 break;
1853 search->private_data = sstate;
1854 search->next_entry = pdb_ads_next_entry;
1855 search->search_end = pdb_ads_search_end;
1856 *pstate = sstate;
1857 return true;
1860 static bool pdb_ads_search_users(struct pdb_methods *m,
1861 struct pdb_search *search,
1862 uint32 acct_flags)
1864 struct pdb_ads_search_state *sstate;
1865 bool ret;
1867 ret = pdb_ads_search_filter(m, search, "(objectclass=user)", &sstate);
1868 if (!ret) {
1869 return false;
1871 sstate->acct_flags = acct_flags;
1872 return true;
1875 static bool pdb_ads_search_groups(struct pdb_methods *m,
1876 struct pdb_search *search)
1878 struct pdb_ads_search_state *sstate;
1879 char *filter;
1880 bool ret;
1882 filter = talloc_asprintf(talloc_tos(),
1883 "(&(grouptype=%d)(objectclass=group))",
1884 GTYPE_SECURITY_GLOBAL_GROUP);
1885 if (filter == NULL) {
1886 return false;
1888 ret = pdb_ads_search_filter(m, search, filter, &sstate);
1889 TALLOC_FREE(filter);
1890 if (!ret) {
1891 return false;
1893 sstate->acct_flags = 0;
1894 return true;
1897 static bool pdb_ads_search_aliases(struct pdb_methods *m,
1898 struct pdb_search *search,
1899 const struct dom_sid *sid)
1901 struct pdb_ads_search_state *sstate;
1902 char *filter;
1903 bool ret;
1905 filter = talloc_asprintf(
1906 talloc_tos(), "(&(grouptype=%d)(objectclass=group))",
1907 sid_check_is_builtin(sid)
1908 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
1909 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1911 if (filter == NULL) {
1912 return false;
1914 ret = pdb_ads_search_filter(m, search, filter, &sstate);
1915 TALLOC_FREE(filter);
1916 if (!ret) {
1917 return false;
1919 sstate->acct_flags = 0;
1920 return true;
1923 static bool pdb_ads_uid_to_sid(struct pdb_methods *m, uid_t uid,
1924 struct dom_sid *sid)
1926 struct pdb_ads_state *state = talloc_get_type_abort(
1927 m->private_data, struct pdb_ads_state);
1928 sid_compose(sid, &state->domainsid, uid);
1929 return true;
1932 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
1933 struct dom_sid *sid)
1935 struct pdb_ads_state *state = talloc_get_type_abort(
1936 m->private_data, struct pdb_ads_state);
1937 sid_compose(sid, &state->domainsid, gid);
1938 return true;
1941 static bool pdb_ads_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
1942 union unid_t *id, enum lsa_SidType *type)
1944 struct pdb_ads_state *state = talloc_get_type_abort(
1945 m->private_data, struct pdb_ads_state);
1946 struct tldap_message **msg;
1947 char *sidstr;
1948 uint32_t rid;
1949 int rc;
1952 * This is a big, big hack: Just hard-code the rid as uid/gid.
1955 sid_peek_rid(sid, &rid);
1957 sidstr = sid_binstring(talloc_tos(), sid);
1958 if (sidstr == NULL) {
1959 return false;
1962 rc = pdb_ads_search_fmt(
1963 state, state->domaindn, TLDAP_SCOPE_SUB,
1964 NULL, 0, 0, talloc_tos(), &msg,
1965 "(&(objectsid=%s)(objectclass=user))", sidstr);
1966 if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
1967 id->uid = rid;
1968 *type = SID_NAME_USER;
1969 TALLOC_FREE(sidstr);
1970 return true;
1973 rc = pdb_ads_search_fmt(
1974 state, state->domaindn, TLDAP_SCOPE_SUB,
1975 NULL, 0, 0, talloc_tos(), &msg,
1976 "(&(objectsid=%s)(objectclass=group))", sidstr);
1977 if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
1978 id->gid = rid;
1979 *type = SID_NAME_DOM_GRP;
1980 TALLOC_FREE(sidstr);
1981 return true;
1984 TALLOC_FREE(sidstr);
1985 return false;
1988 static uint32_t pdb_ads_capabilities(struct pdb_methods *m)
1990 return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
1993 static bool pdb_ads_new_rid(struct pdb_methods *m, uint32 *rid)
1995 return false;
1998 static bool pdb_ads_get_trusteddom_pw(struct pdb_methods *m,
1999 const char *domain, char** pwd,
2000 struct dom_sid *sid,
2001 time_t *pass_last_set_time)
2003 return false;
2006 static bool pdb_ads_set_trusteddom_pw(struct pdb_methods *m,
2007 const char* domain, const char* pwd,
2008 const struct dom_sid *sid)
2010 return false;
2013 static bool pdb_ads_del_trusteddom_pw(struct pdb_methods *m,
2014 const char *domain)
2016 return false;
2019 static NTSTATUS pdb_ads_enum_trusteddoms(struct pdb_methods *m,
2020 TALLOC_CTX *mem_ctx,
2021 uint32 *num_domains,
2022 struct trustdom_info ***domains)
2024 *num_domains = 0;
2025 *domains = NULL;
2026 return NT_STATUS_OK;
2029 static void pdb_ads_init_methods(struct pdb_methods *m)
2031 m->name = "ads";
2032 m->get_domain_info = pdb_ads_get_domain_info;
2033 m->getsampwnam = pdb_ads_getsampwnam;
2034 m->getsampwsid = pdb_ads_getsampwsid;
2035 m->create_user = pdb_ads_create_user;
2036 m->delete_user = pdb_ads_delete_user;
2037 m->add_sam_account = pdb_ads_add_sam_account;
2038 m->update_sam_account = pdb_ads_update_sam_account;
2039 m->delete_sam_account = pdb_ads_delete_sam_account;
2040 m->rename_sam_account = pdb_ads_rename_sam_account;
2041 m->update_login_attempts = pdb_ads_update_login_attempts;
2042 m->getgrsid = pdb_ads_getgrsid;
2043 m->getgrgid = pdb_ads_getgrgid;
2044 m->getgrnam = pdb_ads_getgrnam;
2045 m->create_dom_group = pdb_ads_create_dom_group;
2046 m->delete_dom_group = pdb_ads_delete_dom_group;
2047 m->add_group_mapping_entry = pdb_ads_add_group_mapping_entry;
2048 m->update_group_mapping_entry = pdb_ads_update_group_mapping_entry;
2049 m->delete_group_mapping_entry = pdb_ads_delete_group_mapping_entry;
2050 m->enum_group_mapping = pdb_ads_enum_group_mapping;
2051 m->enum_group_members = pdb_ads_enum_group_members;
2052 m->enum_group_memberships = pdb_ads_enum_group_memberships;
2053 m->set_unix_primary_group = pdb_ads_set_unix_primary_group;
2054 m->add_groupmem = pdb_ads_add_groupmem;
2055 m->del_groupmem = pdb_ads_del_groupmem;
2056 m->create_alias = pdb_ads_create_alias;
2057 m->delete_alias = pdb_ads_delete_alias;
2058 m->get_aliasinfo = pdb_default_get_aliasinfo;
2059 m->set_aliasinfo = pdb_ads_set_aliasinfo;
2060 m->add_aliasmem = pdb_ads_add_aliasmem;
2061 m->del_aliasmem = pdb_ads_del_aliasmem;
2062 m->enum_aliasmem = pdb_ads_enum_aliasmem;
2063 m->enum_alias_memberships = pdb_ads_enum_alias_memberships;
2064 m->lookup_rids = pdb_ads_lookup_rids;
2065 m->lookup_names = pdb_ads_lookup_names;
2066 m->get_account_policy = pdb_ads_get_account_policy;
2067 m->set_account_policy = pdb_ads_set_account_policy;
2068 m->get_seq_num = pdb_ads_get_seq_num;
2069 m->search_users = pdb_ads_search_users;
2070 m->search_groups = pdb_ads_search_groups;
2071 m->search_aliases = pdb_ads_search_aliases;
2072 m->uid_to_sid = pdb_ads_uid_to_sid;
2073 m->gid_to_sid = pdb_ads_gid_to_sid;
2074 m->sid_to_id = pdb_ads_sid_to_id;
2075 m->capabilities = pdb_ads_capabilities;
2076 m->new_rid = pdb_ads_new_rid;
2077 m->get_trusteddom_pw = pdb_ads_get_trusteddom_pw;
2078 m->set_trusteddom_pw = pdb_ads_set_trusteddom_pw;
2079 m->del_trusteddom_pw = pdb_ads_del_trusteddom_pw;
2080 m->enum_trusteddoms = pdb_ads_enum_trusteddoms;
2083 static void free_private_data(void **vp)
2085 struct pdb_ads_state *state = talloc_get_type_abort(
2086 *vp, struct pdb_ads_state);
2088 TALLOC_FREE(state->ld);
2089 return;
2093 this is used to catch debug messages from events
2095 static void s3_tldap_debug(void *context, enum tldap_debug_level level,
2096 const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
2098 static void s3_tldap_debug(void *context, enum tldap_debug_level level,
2099 const char *fmt, va_list ap)
2101 int samba_level = -1;
2102 char *s = NULL;
2103 switch (level) {
2104 case TLDAP_DEBUG_FATAL:
2105 samba_level = 0;
2106 break;
2107 case TLDAP_DEBUG_ERROR:
2108 samba_level = 1;
2109 break;
2110 case TLDAP_DEBUG_WARNING:
2111 samba_level = 2;
2112 break;
2113 case TLDAP_DEBUG_TRACE:
2114 samba_level = 11;
2115 break;
2118 if (vasprintf(&s, fmt, ap) == -1) {
2119 return;
2121 DEBUG(samba_level, ("tldap: %s", s));
2122 free(s);
2125 static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state)
2127 NTSTATUS status;
2128 int fd;
2130 if (tldap_connection_ok(state->ld)) {
2131 return state->ld;
2133 TALLOC_FREE(state->ld);
2135 status = open_socket_out(
2136 (struct sockaddr_storage *)(void *)&state->socket_address,
2137 0, 0, &fd);
2138 if (!NT_STATUS_IS_OK(status)) {
2139 DEBUG(10, ("Could not connect to %s: %s\n",
2140 state->socket_address.sun_path, nt_errstr(status)));
2141 return NULL;
2144 set_blocking(fd, false);
2146 state->ld = tldap_context_create(state, fd);
2147 if (state->ld == NULL) {
2148 close(fd);
2149 return NULL;
2151 tldap_set_debug(state->ld, s3_tldap_debug, NULL);
2153 return state->ld;
2156 int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base,
2157 int scope, const char *attrs[], int num_attrs,
2158 int attrsonly,
2159 TALLOC_CTX *mem_ctx, struct tldap_message ***res,
2160 const char *fmt, ...)
2162 struct tldap_context *ld;
2163 va_list ap;
2164 int ret;
2166 ld = pdb_ads_ld(state);
2167 if (ld == NULL) {
2168 return TLDAP_SERVER_DOWN;
2171 va_start(ap, fmt);
2172 ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly,
2173 mem_ctx, res, fmt, ap);
2174 va_end(ap);
2176 if (ret != TLDAP_SERVER_DOWN) {
2177 return ret;
2180 /* retry once */
2181 ld = pdb_ads_ld(state);
2182 if (ld == NULL) {
2183 return TLDAP_SERVER_DOWN;
2186 va_start(ap, fmt);
2187 ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly,
2188 mem_ctx, res, fmt, ap);
2189 va_end(ap);
2190 return ret;
2193 static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state,
2194 const char *location)
2196 const char *domain_attrs[2] = { "objectSid", "objectGUID" };
2197 const char *ncname_attrs[1] = { "netbiosname" };
2198 struct tldap_context *ld;
2199 struct tldap_message *rootdse, **domain, **ncname;
2200 TALLOC_CTX *frame = talloc_stackframe();
2201 NTSTATUS status;
2202 int num_domains;
2203 int rc;
2205 ZERO_STRUCT(state->socket_address);
2206 state->socket_address.sun_family = AF_UNIX;
2207 strncpy(state->socket_address.sun_path, location,
2208 sizeof(state->socket_address.sun_path) - 1);
2210 ld = pdb_ads_ld(state);
2211 if (ld == NULL) {
2212 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2213 goto done;
2216 rc = tldap_fetch_rootdse(ld);
2217 if (rc != TLDAP_SUCCESS) {
2218 DEBUG(10, ("Could not retrieve rootdse: %s\n",
2219 tldap_errstr(talloc_tos(), state->ld, rc)));
2220 status = NT_STATUS_LDAP(rc);
2221 goto done;
2223 rootdse = tldap_rootdse(state->ld);
2225 state->domaindn = tldap_talloc_single_attribute(
2226 rootdse, "defaultNamingContext", state);
2227 if (state->domaindn == NULL) {
2228 DEBUG(10, ("Could not get defaultNamingContext\n"));
2229 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2230 goto done;
2232 DEBUG(10, ("defaultNamingContext = %s\n", state->domaindn));
2234 state->configdn = tldap_talloc_single_attribute(
2235 rootdse, "configurationNamingContext", state);
2236 if (state->domaindn == NULL) {
2237 DEBUG(10, ("Could not get configurationNamingContext\n"));
2238 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2239 goto done;
2241 DEBUG(10, ("configurationNamingContext = %s\n", state->configdn));
2244 * Figure out our domain's SID
2246 rc = pdb_ads_search_fmt(
2247 state, state->domaindn, TLDAP_SCOPE_BASE,
2248 domain_attrs, ARRAY_SIZE(domain_attrs), 0,
2249 talloc_tos(), &domain, "(objectclass=*)");
2250 if (rc != TLDAP_SUCCESS) {
2251 DEBUG(10, ("Could not retrieve domain: %s\n",
2252 tldap_errstr(talloc_tos(), state->ld, rc)));
2253 status = NT_STATUS_LDAP(rc);
2254 goto done;
2257 num_domains = talloc_array_length(domain);
2258 if (num_domains != 1) {
2259 DEBUG(10, ("Got %d domains, expected one\n", num_domains));
2260 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2261 goto done;
2263 if (!tldap_pull_binsid(domain[0], "objectSid", &state->domainsid)) {
2264 DEBUG(10, ("Could not retrieve domain SID\n"));
2265 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2266 goto done;
2268 if (!tldap_pull_guid(domain[0], "objectGUID", &state->domainguid)) {
2269 DEBUG(10, ("Could not retrieve domain GUID\n"));
2270 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2271 goto done;
2273 DEBUG(10, ("Domain SID: %s\n", sid_string_dbg(&state->domainsid)));
2276 * Figure out our domain's short name
2278 rc = pdb_ads_search_fmt(
2279 state, state->configdn, TLDAP_SCOPE_SUB,
2280 ncname_attrs, ARRAY_SIZE(ncname_attrs), 0,
2281 talloc_tos(), &ncname, "(ncname=%s)", state->domaindn);
2282 if (rc != TLDAP_SUCCESS) {
2283 DEBUG(10, ("Could not retrieve ncname: %s\n",
2284 tldap_errstr(talloc_tos(), state->ld, rc)));
2285 status = NT_STATUS_LDAP(rc);
2286 goto done;
2288 if (talloc_array_length(ncname) != 1) {
2289 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2290 goto done;
2293 state->netbiosname = tldap_talloc_single_attribute(
2294 ncname[0], "netbiosname", state);
2295 if (state->netbiosname == NULL) {
2296 DEBUG(10, ("Could not get netbiosname\n"));
2297 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2298 goto done;
2300 DEBUG(10, ("netbiosname: %s\n", state->netbiosname));
2302 if (!strequal(lp_workgroup(), state->netbiosname)) {
2303 DEBUG(1, ("ADS is different domain (%s) than ours (%s)\n",
2304 state->netbiosname, lp_workgroup()));
2305 status = NT_STATUS_NO_SUCH_DOMAIN;
2306 goto done;
2309 secrets_store_domain_sid(state->netbiosname, &state->domainsid);
2311 status = NT_STATUS_OK;
2312 done:
2313 TALLOC_FREE(frame);
2314 return status;
2317 static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method,
2318 const char *location)
2320 struct pdb_methods *m;
2321 struct pdb_ads_state *state;
2322 char *tmp = NULL;
2323 NTSTATUS status;
2325 m = talloc(talloc_autofree_context(), struct pdb_methods);
2326 if (m == NULL) {
2327 return NT_STATUS_NO_MEMORY;
2329 state = talloc_zero(m, struct pdb_ads_state);
2330 if (state == NULL) {
2331 goto nomem;
2333 m->private_data = state;
2334 m->free_private_data = free_private_data;
2335 pdb_ads_init_methods(m);
2337 if (location == NULL) {
2338 tmp = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi",
2339 lp_private_dir());
2340 location = tmp;
2342 if (location == NULL) {
2343 goto nomem;
2346 status = pdb_ads_connect(state, location);
2347 if (!NT_STATUS_IS_OK(status)) {
2348 DEBUG(10, ("pdb_ads_connect failed: %s\n", nt_errstr(status)));
2349 goto fail;
2352 *pdb_method = m;
2353 return NT_STATUS_OK;
2354 nomem:
2355 status = NT_STATUS_NO_MEMORY;
2356 fail:
2357 TALLOC_FREE(m);
2358 return status;
2361 NTSTATUS pdb_ads_init(void);
2362 NTSTATUS pdb_ads_init(void)
2364 return smb_register_passdb(PASSDB_INTERFACE_VERSION, "ads",
2365 pdb_init_ads);