If there are no mods, don't bother the ldap server
[metze/samba/wip.git] / source3 / passdb / pdb_ads.c
1 /*
2    Unix SMB/CIFS implementation.
3    pdb_ldap with ads schema
4    Copyright (C) Volker Lendecke 2009
5
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.
10
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.
15
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/>.
18 */
19
20 #include "includes.h"
21
22 struct pdb_ads_state {
23         struct tldap_context *ld;
24         struct dom_sid domainsid;
25         char *domaindn;
26         char *configdn;
27         char *netbiosname;
28 };
29
30 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
31                                     struct samu *sam_acct,
32                                     const DOM_SID *sid);
33 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
34                                DOM_SID *sid);
35 static bool pdb_ads_dnblob2sid(struct tldap_context *ld, DATA_BLOB *dnblob,
36                                struct dom_sid *psid);
37 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
38                                const struct dom_sid *sid,
39                                TALLOC_CTX *mem_ctx, char **pdn);
40
41 static bool pdb_ads_pull_time(struct tldap_message *msg, const char *attr,
42                               time_t *ptime)
43 {
44         uint64_t tmp;
45
46         if (!tldap_pull_uint64(msg, attr, &tmp)) {
47                 return false;
48         }
49         *ptime = uint64s_nt_time_to_unix_abs(&tmp);
50         return true;
51 }
52
53 static gid_t pdb_ads_sid2gid(const struct dom_sid *sid)
54 {
55         uint32_t rid;
56         sid_peek_rid(sid, &rid);
57         return rid;
58 }
59
60 struct pdb_ads_samu_private {
61         char *dn;
62         struct tldap_message *ldapmsg;
63 };
64
65 static struct samu *pdb_ads_init_guest(TALLOC_CTX *mem_ctx,
66                                        struct pdb_methods *m)
67 {
68         struct pdb_ads_state *state = talloc_get_type_abort(
69                 m->private_data, struct pdb_ads_state);
70         struct dom_sid guest_sid;
71         struct samu *guest;
72         NTSTATUS status;
73
74         sid_compose(&guest_sid, &state->domainsid, DOMAIN_USER_RID_GUEST);
75
76         guest = samu_new(mem_ctx);
77         if (guest == NULL) {
78                 return NULL;
79         }
80
81         status = pdb_ads_getsampwsid(m, guest, &guest_sid);
82         if (!NT_STATUS_IS_OK(status)) {
83                 DEBUG(10, ("Could not init guest account: %s\n",
84                            nt_errstr(status)));
85                 TALLOC_FREE(guest);
86                 return NULL;
87         }
88         return guest;
89 }
90
91 static struct pdb_ads_samu_private *pdb_ads_get_samu_private(
92         struct pdb_methods *m, struct samu *sam)
93 {
94         struct pdb_ads_samu_private *result;
95         uint32_t rid;
96
97         result = (struct pdb_ads_samu_private *)
98                 pdb_get_backend_private_data(sam, m);
99
100         if (result != NULL) {
101                 return talloc_get_type_abort(
102                         result, struct pdb_ads_samu_private);
103         }
104
105         /*
106          * This is now a weirdness of the passdb API. For the guest user we
107          * are not asked first.
108          */
109         sid_peek_rid(pdb_get_user_sid(sam), &rid);
110
111         if (rid == DOMAIN_USER_RID_GUEST) {
112                 struct samu *guest = pdb_ads_init_guest(talloc_tos(), m);
113
114                 if (guest == NULL) {
115                         return NULL;
116                 }
117                 result = talloc_get_type_abort(
118                         pdb_get_backend_private_data(guest, m),
119                         struct pdb_ads_samu_private);
120                 pdb_set_backend_private_data(
121                         sam, talloc_move(sam, &result), NULL, m, PDB_SET);
122                 TALLOC_FREE(guest);
123                 return talloc_get_type_abort(
124                         pdb_get_backend_private_data(sam, m),
125                         struct pdb_ads_samu_private);
126         }
127
128         return NULL;
129 }
130
131 static NTSTATUS pdb_ads_init_sam_from_ads(struct pdb_methods *m,
132                                           struct samu *sam,
133                                           struct tldap_message *entry)
134 {
135         struct pdb_ads_state *state = talloc_get_type_abort(
136                 m->private_data, struct pdb_ads_state);
137         TALLOC_CTX *frame = talloc_stackframe();
138         struct pdb_ads_samu_private *priv;
139         NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
140         char *str;
141         time_t tmp_time;
142         struct dom_sid sid;
143         uint64_t n;
144         DATA_BLOB blob;
145
146         priv = talloc(sam, struct pdb_ads_samu_private);
147         if (priv == NULL) {
148                 return NT_STATUS_NO_MEMORY;
149         }
150         if (!tldap_entry_dn(entry, &priv->dn)) {
151                 TALLOC_FREE(priv);
152                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
153         }
154
155         str = tldap_talloc_single_attribute(entry, "samAccountName", sam);
156         if (str == NULL) {
157                 DEBUG(10, ("no samAccountName\n"));
158                 goto fail;
159         }
160         pdb_set_username(sam, str, PDB_SET);
161
162         if (pdb_ads_pull_time(entry, "lastLogon", &tmp_time)) {
163                 pdb_set_logon_time(sam, tmp_time, PDB_SET);
164         }
165         if (pdb_ads_pull_time(entry, "lastLogoff", &tmp_time)) {
166                 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
167         }
168         if (pdb_ads_pull_time(entry, "pwdLastSet", &tmp_time)) {
169                 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
170         }
171         if (pdb_ads_pull_time(entry, "accountExpires", &tmp_time)) {
172                 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
173         }
174
175         str = tldap_talloc_single_attribute(entry, "displayName",
176                                             talloc_tos());
177         if (str != NULL) {
178                 pdb_set_fullname(sam, str, PDB_SET);
179         }
180
181         str = tldap_talloc_single_attribute(entry, "homeDirectory",
182                                             talloc_tos());
183         if (str != NULL) {
184                 pdb_set_homedir(sam, str, PDB_SET);
185         }
186
187         str = tldap_talloc_single_attribute(entry, "homeDrive", talloc_tos());
188         if (str != NULL) {
189                 pdb_set_dir_drive(sam, str, PDB_SET);
190         }
191
192         str = tldap_talloc_single_attribute(entry, "scriptPath", talloc_tos());
193         if (str != NULL) {
194                 pdb_set_logon_script(sam, str, PDB_SET);
195         }
196
197         str = tldap_talloc_single_attribute(entry, "profilePath",
198                                             talloc_tos());
199         if (str != NULL) {
200                 pdb_set_profile_path(sam, str, PDB_SET);
201         }
202
203         str = tldap_talloc_single_attribute(entry, "profilePath",
204                                             talloc_tos());
205         if (str != NULL) {
206                 pdb_set_profile_path(sam, str, PDB_SET);
207         }
208
209         if (!tldap_pull_binsid(entry, "objectSid", &sid)) {
210                 DEBUG(10, ("Could not pull SID\n"));
211                 goto fail;
212         }
213         pdb_set_user_sid(sam, &sid, PDB_SET);
214
215         if (!tldap_pull_uint64(entry, "userAccountControl", &n)) {
216                 DEBUG(10, ("Could not pull userAccountControl\n"));
217                 goto fail;
218         }
219         pdb_set_acct_ctrl(sam, ads_uf2acb(n), PDB_SET);
220
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;
226                 }
227                 pdb_set_nt_passwd(sam, blob.data, PDB_SET);
228         }
229
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;
235                 }
236                 pdb_set_lanman_passwd(sam, blob.data, PDB_SET);
237         }
238
239         if (tldap_pull_uint64(entry, "primaryGroupID", &n)) {
240                 sid_compose(&sid, &state->domainsid, n);
241                 pdb_set_group_sid(sam, &sid, PDB_SET);
242
243         }
244
245         priv->ldapmsg = talloc_move(priv, &entry);
246         pdb_set_backend_private_data(sam, priv, NULL, m, PDB_SET);
247
248         status = NT_STATUS_OK;
249 fail:
250         TALLOC_FREE(frame);
251         return status;
252 }
253
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)
259 {
260         bool ret = true;
261
262         /* TODO: All fields :-) */
263
264         ret &= tldap_make_mod_fmt(
265                 existing, mem_ctx, pnum_mods, pmods, "displayName",
266                 "%s", pdb_get_fullname(sam));
267
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));
271
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));
275
276         ret &= tldap_make_mod_fmt(
277                 existing, mem_ctx, pnum_mods, pmods, "userAccountControl",
278                 "%d", ads_acb2uf(pdb_get_acct_ctrl(sam)));
279
280         ret &= tldap_make_mod_fmt(
281                 existing, mem_ctx, pnum_mods, pmods, "homeDirectory",
282                 "%s", pdb_get_homedir(sam));
283
284         ret &= tldap_make_mod_fmt(
285                 existing, mem_ctx, pnum_mods, pmods, "homeDrive",
286                 "%s", pdb_get_dir_drive(sam));
287
288         ret &= tldap_make_mod_fmt(
289                 existing, mem_ctx, pnum_mods, pmods, "scriptPath",
290                 "%s", pdb_get_logon_script(sam));
291
292         ret &= tldap_make_mod_fmt(
293                 existing, mem_ctx, pnum_mods, pmods, "profilePath",
294                 "%s", pdb_get_profile_path(sam));
295
296         return ret;
297 }
298
299 static NTSTATUS pdb_ads_getsampwfilter(struct pdb_methods *m,
300                                        struct pdb_ads_state *state,
301                                        struct samu *sam_acct,
302                                        const char *filter)
303 {
304         const char * attrs[] = {
305                 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
306                 "sAMAccountName", "displayName", "homeDirectory",
307                 "homeDrive", "scriptPath", "profilePath", "description",
308                 "userWorkstations", "comment", "userParameters", "objectSid",
309                 "primaryGroupID", "userAccountControl", "logonHours",
310                 "badPwdCount", "logonCount", "countryCode", "codePage",
311                 "unicodePwd", "dBCSPwd" };
312         struct tldap_message **users;
313         int rc, count;
314
315         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
316                               attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
317                               &users, "%s", filter);
318         if (rc != TLDAP_SUCCESS) {
319                 DEBUG(10, ("ldap_search failed %s\n",
320                            tldap_errstr(debug_ctx(), state->ld, rc)));
321                 return NT_STATUS_LDAP(rc);
322         }
323
324         count = talloc_array_length(users);
325         if (count != 1) {
326                 DEBUG(10, ("Expected 1 user, got %d\n", count));
327                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
328         }
329
330         return pdb_ads_init_sam_from_ads(m, sam_acct, users[0]);
331 }
332
333 static NTSTATUS pdb_ads_getsampwnam(struct pdb_methods *m,
334                                     struct samu *sam_acct,
335                                     const char *username)
336 {
337         struct pdb_ads_state *state = talloc_get_type_abort(
338                 m->private_data, struct pdb_ads_state);
339         char *filter;
340
341         filter = talloc_asprintf(
342                 talloc_tos(), "(&(samaccountname=%s)(objectclass=user))",
343                 username);
344         NT_STATUS_HAVE_NO_MEMORY(filter);
345
346         return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
347 }
348
349 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
350                                     struct samu *sam_acct,
351                                     const DOM_SID *sid)
352 {
353         struct pdb_ads_state *state = talloc_get_type_abort(
354                 m->private_data, struct pdb_ads_state);
355         char *sidstr, *filter;
356
357         sidstr = sid_binstring(talloc_tos(), sid);
358         NT_STATUS_HAVE_NO_MEMORY(sidstr);
359
360         filter = talloc_asprintf(
361                 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
362         TALLOC_FREE(sidstr);
363         NT_STATUS_HAVE_NO_MEMORY(filter);
364
365         return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
366 }
367
368 static NTSTATUS pdb_ads_create_user(struct pdb_methods *m,
369                                     TALLOC_CTX *tmp_ctx,
370                                     const char *name, uint32 acct_flags,
371                                     uint32 *rid)
372 {
373         struct pdb_ads_state *state = talloc_get_type_abort(
374                 m->private_data, struct pdb_ads_state);
375         const char *attrs[1] = { "objectSid" };
376         struct tldap_mod *mods = NULL;
377         int num_mods = 0;
378         struct tldap_message **user;
379         struct dom_sid sid;
380         char *dn;
381         int rc;
382         bool ok;
383
384         dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
385                              state->domaindn);
386         if (dn == NULL) {
387                 return NT_STATUS_NO_MEMORY;
388         }
389
390         /* TODO: Create machines etc */
391
392         ok = true;
393         ok &= tldap_make_mod_fmt(
394                 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "user");
395         ok &= tldap_make_mod_fmt(
396                 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
397                 name);
398         if (!ok) {
399                 return NT_STATUS_NO_MEMORY;
400         }
401
402         rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL);
403         if (rc != TLDAP_SUCCESS) {
404                 DEBUG(10, ("ldap_add failed %s\n",
405                            tldap_errstr(debug_ctx(), state->ld, rc)));
406                 TALLOC_FREE(dn);
407                 return NT_STATUS_LDAP(rc);
408         }
409
410         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
411                               attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &user,
412                              "(&(objectclass=user)(samaccountname=%s))",
413                              name);
414         if (rc != TLDAP_SUCCESS) {
415                 DEBUG(10, ("Could not find just created user %s: %s\n",
416                            name, tldap_errstr(debug_ctx(), state->ld, rc)));
417                 TALLOC_FREE(dn);
418                 return NT_STATUS_LDAP(rc);
419         }
420
421         if (talloc_array_length(user) != 1) {
422                 DEBUG(10, ("Got %d users, expected one\n",
423                            (int)talloc_array_length(user)));
424                 TALLOC_FREE(dn);
425                 return NT_STATUS_LDAP(rc);
426         }
427
428         if (!tldap_pull_binsid(user[0], "objectSid", &sid)) {
429                 DEBUG(10, ("Could not fetch objectSid from user %s\n",
430                            name));
431                 TALLOC_FREE(dn);
432                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
433         }
434
435         sid_peek_rid(&sid, rid);
436         TALLOC_FREE(dn);
437         return NT_STATUS_OK;
438 }
439
440 static NTSTATUS pdb_ads_delete_user(struct pdb_methods *m,
441                                     TALLOC_CTX *tmp_ctx,
442                                     struct samu *sam)
443 {
444         struct pdb_ads_state *state = talloc_get_type_abort(
445                 m->private_data, struct pdb_ads_state);
446         struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam);
447         int rc;
448
449         rc = tldap_delete(state->ld, priv->dn, NULL, NULL);
450         if (rc != TLDAP_SUCCESS) {
451                 DEBUG(10, ("ldap_delete for %s failed: %s\n", priv->dn,
452                            tldap_errstr(debug_ctx(), state->ld, rc)));
453                 return NT_STATUS_LDAP(rc);
454         }
455         return NT_STATUS_OK;
456 }
457
458 static NTSTATUS pdb_ads_add_sam_account(struct pdb_methods *m,
459                                         struct samu *sampass)
460 {
461         return NT_STATUS_NOT_IMPLEMENTED;
462 }
463
464 static NTSTATUS pdb_ads_update_sam_account(struct pdb_methods *m,
465                                            struct samu *sam)
466 {
467         struct pdb_ads_state *state = talloc_get_type_abort(
468                 m->private_data, struct pdb_ads_state);
469         struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam);
470         struct tldap_mod *mods = NULL;
471         int rc, num_mods = 0;
472
473         if (!pdb_ads_init_ads_from_sam(state, priv->ldapmsg, talloc_tos(),
474                                        &num_mods, &mods, sam)) {
475                 return NT_STATUS_NO_MEMORY;
476         }
477
478         if (num_mods == 0) {
479                 /* Nothing to do, just return success */
480                 return NT_STATUS_OK;
481         }
482
483         rc = tldap_modify(state->ld, priv->dn, num_mods, mods, NULL, NULL);
484         if (rc != TLDAP_SUCCESS) {
485                 DEBUG(10, ("ldap_modify for %s failed: %s\n", priv->dn,
486                            tldap_errstr(debug_ctx(), state->ld, rc)));
487                 return NT_STATUS_LDAP(rc);
488         }
489
490         TALLOC_FREE(mods);
491
492         return NT_STATUS_OK;
493 }
494
495 static NTSTATUS pdb_ads_delete_sam_account(struct pdb_methods *m,
496                                            struct samu *username)
497 {
498         return NT_STATUS_NOT_IMPLEMENTED;
499 }
500
501 static NTSTATUS pdb_ads_rename_sam_account(struct pdb_methods *m,
502                                            struct samu *oldname,
503                                            const char *newname)
504 {
505         return NT_STATUS_NOT_IMPLEMENTED;
506 }
507
508 static NTSTATUS pdb_ads_update_login_attempts(struct pdb_methods *m,
509                                               struct samu *sam_acct,
510                                               bool success)
511 {
512         return NT_STATUS_NOT_IMPLEMENTED;
513 }
514
515 static NTSTATUS pdb_ads_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
516                                     const char *filter)
517 {
518         struct pdb_ads_state *state = talloc_get_type_abort(
519                 m->private_data, struct pdb_ads_state);
520         const char *attrs[4] = { "objectSid", "description", "samAccountName",
521                                  "groupType" };
522         char *str;
523         struct tldap_message **group;
524         uint32_t grouptype;
525         int rc;
526
527         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
528                               attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
529                               &group, "%s", filter);
530         if (rc != TLDAP_SUCCESS) {
531                 DEBUG(10, ("ldap_search failed %s\n",
532                            tldap_errstr(debug_ctx(), state->ld, rc)));
533                 return NT_STATUS_LDAP(rc);
534         }
535         if (talloc_array_length(group) != 1) {
536                 DEBUG(10, ("Expected 1 user, got %d\n",
537                            (int)talloc_array_length(group)));
538                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
539         }
540
541         if (!tldap_pull_binsid(group[0], "objectSid", &map->sid)) {
542                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
543         }
544         map->gid = pdb_ads_sid2gid(&map->sid);
545
546         if (!tldap_pull_uint32(group[0], "groupType", &grouptype)) {
547                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
548         }
549         switch (grouptype) {
550         case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
551         case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
552                 map->sid_name_use = SID_NAME_ALIAS;
553                 break;
554         case GTYPE_SECURITY_GLOBAL_GROUP:
555                 map->sid_name_use = SID_NAME_DOM_GRP;
556                 break;
557         default:
558                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
559         }
560
561         str = tldap_talloc_single_attribute(group[0], "samAccountName",
562                                             talloc_tos());
563         if (str == NULL) {
564                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
565         }
566         fstrcpy(map->nt_name, str);
567         TALLOC_FREE(str);
568
569         str = tldap_talloc_single_attribute(group[0], "description",
570                                             talloc_tos());
571         if (str != NULL) {
572                 fstrcpy(map->comment, str);
573                 TALLOC_FREE(str);
574         } else {
575                 map->comment[0] = '\0';
576         }
577
578         TALLOC_FREE(group);
579         return NT_STATUS_OK;
580 }
581
582 static NTSTATUS pdb_ads_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
583                                  DOM_SID sid)
584 {
585         char *filter;
586         NTSTATUS status;
587
588         filter = talloc_asprintf(talloc_tos(),
589                                  "(&(objectsid=%s)(objectclass=group))",
590                                  sid_string_talloc(talloc_tos(), &sid));
591         if (filter == NULL) {
592                 return NT_STATUS_NO_MEMORY;
593         }
594
595         status = pdb_ads_getgrfilter(m, map, filter);
596         TALLOC_FREE(filter);
597         return status;
598 }
599
600 static NTSTATUS pdb_ads_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
601                                  gid_t gid)
602 {
603         struct dom_sid sid;
604         pdb_ads_gid_to_sid(m, gid, &sid);
605         return pdb_ads_getgrsid(m, map, sid);
606 }
607
608 static NTSTATUS pdb_ads_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
609                                  const char *name)
610 {
611         char *filter;
612         NTSTATUS status;
613
614         filter = talloc_asprintf(talloc_tos(),
615                                  "(&(samaccountname=%s)(objectclass=group))",
616                                  name);
617         if (filter == NULL) {
618                 return NT_STATUS_NO_MEMORY;
619         }
620
621         status = pdb_ads_getgrfilter(m, map, filter);
622         TALLOC_FREE(filter);
623         return status;
624 }
625
626 static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m,
627                                          TALLOC_CTX *mem_ctx, const char *name,
628                                          uint32 *rid)
629 {
630         TALLOC_CTX *frame = talloc_stackframe();
631         struct pdb_ads_state *state = talloc_get_type_abort(
632                 m->private_data, struct pdb_ads_state);
633         const char *attrs[1] = { "objectSid" };
634         int num_mods = 0;
635         struct tldap_mod *mods = NULL;
636         struct tldap_message **alias;
637         struct dom_sid sid;
638         char *dn;
639         int rc;
640         bool ok = true;
641
642         dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
643                              state->domaindn);
644         if (dn == NULL) {
645                 TALLOC_FREE(frame);
646                 return NT_STATUS_NO_MEMORY;
647         }
648
649         ok &= tldap_make_mod_fmt(
650                 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
651                 name);
652         ok &= tldap_make_mod_fmt(
653                 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "group");
654         ok &= tldap_make_mod_fmt(
655                 NULL, talloc_tos(), &num_mods, &mods, "groupType",
656                 "%d", (int)GTYPE_SECURITY_GLOBAL_GROUP);
657
658         if (!ok) {
659                 TALLOC_FREE(frame);
660                 return NT_STATUS_NO_MEMORY;
661         }
662
663         rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL);
664         if (rc != TLDAP_SUCCESS) {
665                 DEBUG(10, ("ldap_add failed %s\n",
666                            tldap_errstr(debug_ctx(), state->ld, rc)));
667                 TALLOC_FREE(frame);
668                 return NT_STATUS_LDAP(rc);
669         }
670
671         rc = tldap_search_fmt(
672                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
673                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
674                 "(&(objectclass=group)(samaccountname=%s))", name);
675         if (rc != TLDAP_SUCCESS) {
676                 DEBUG(10, ("Could not find just created alias %s: %s\n",
677                            name, tldap_errstr(debug_ctx(), state->ld, rc)));
678                 TALLOC_FREE(frame);
679                 return NT_STATUS_LDAP(rc);
680         }
681
682         if (talloc_array_length(alias) != 1) {
683                 DEBUG(10, ("Got %d alias, expected one\n",
684                            (int)talloc_array_length(alias)));
685                 TALLOC_FREE(frame);
686                 return NT_STATUS_LDAP(rc);
687         }
688
689         if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
690                 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
691                            name));
692                 TALLOC_FREE(frame);
693                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
694         }
695
696         sid_peek_rid(&sid, rid);
697         TALLOC_FREE(frame);
698         return NT_STATUS_OK;
699 }
700
701 static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m,
702                                          TALLOC_CTX *mem_ctx, uint32 rid)
703 {
704         struct pdb_ads_state *state = talloc_get_type_abort(
705                 m->private_data, struct pdb_ads_state);
706         struct dom_sid sid;
707         char *sidstr;
708         struct tldap_message **msg;
709         char *dn;
710         int rc;
711
712         sid_compose(&sid, &state->domainsid, rid);
713
714         sidstr = sid_binstring(talloc_tos(), &sid);
715         NT_STATUS_HAVE_NO_MEMORY(sidstr);
716
717         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
718                               NULL, 0, 0, talloc_tos(), &msg,
719                               ("(&(objectSid=%s)(objectClass=group))"),
720                               sidstr);
721         TALLOC_FREE(sidstr);
722         if (rc != TLDAP_SUCCESS) {
723                 DEBUG(10, ("ldap_search failed %s\n",
724                            tldap_errstr(debug_ctx(), state->ld, rc)));
725                 return NT_STATUS_LDAP(rc);
726         }
727
728         switch talloc_array_length(msg) {
729         case 0:
730                 return NT_STATUS_NO_SUCH_GROUP;
731         case 1:
732                 break;
733         default:
734                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
735         }
736
737         if (!tldap_entry_dn(msg[0], &dn)) {
738                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
739         }
740
741         rc = tldap_delete(state->ld, dn, NULL, NULL);
742         if (rc != TLDAP_SUCCESS) {
743                 DEBUG(10, ("ldap_delete failed: %s\n",
744                            tldap_errstr(debug_ctx(), state->ld, rc)));
745                 TALLOC_FREE(dn);
746                 return NT_STATUS_LDAP(rc);
747         }
748
749         TALLOC_FREE(msg);
750         return NT_STATUS_OK;
751 }
752
753 static NTSTATUS pdb_ads_add_group_mapping_entry(struct pdb_methods *m,
754                                                 GROUP_MAP *map)
755 {
756         return NT_STATUS_NOT_IMPLEMENTED;
757 }
758
759 static NTSTATUS pdb_ads_update_group_mapping_entry(struct pdb_methods *m,
760                                                    GROUP_MAP *map)
761 {
762         return NT_STATUS_NOT_IMPLEMENTED;
763 }
764
765 static NTSTATUS pdb_ads_delete_group_mapping_entry(struct pdb_methods *m,
766                                                    DOM_SID sid)
767 {
768         return NT_STATUS_NOT_IMPLEMENTED;
769 }
770
771 static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m,
772                                            const DOM_SID *sid,
773                                            enum lsa_SidType sid_name_use,
774                                            GROUP_MAP **pp_rmap,
775                                            size_t *p_num_entries,
776                                            bool unix_only)
777 {
778         return NT_STATUS_NOT_IMPLEMENTED;
779 }
780
781 static NTSTATUS pdb_ads_enum_group_members(struct pdb_methods *m,
782                                            TALLOC_CTX *mem_ctx,
783                                            const DOM_SID *group,
784                                            uint32 **pmembers,
785                                            size_t *pnum_members)
786 {
787         struct pdb_ads_state *state = talloc_get_type_abort(
788                 m->private_data, struct pdb_ads_state);
789         const char *attrs[1] = { "member" };
790         char *sidstr;
791         struct tldap_message **msg;
792         int i, rc, num_members;
793         DATA_BLOB *blobs;
794         uint32_t *members;
795
796         sidstr = sid_binstring(talloc_tos(), group);
797         NT_STATUS_HAVE_NO_MEMORY(sidstr);
798
799         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
800                               attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &msg,
801                               "(objectsid=%s)", sidstr);
802         TALLOC_FREE(sidstr);
803         if (rc != TLDAP_SUCCESS) {
804                 DEBUG(10, ("ldap_search failed %s\n",
805                            tldap_errstr(debug_ctx(), state->ld, rc)));
806                 return NT_STATUS_LDAP(rc);
807         }
808         switch talloc_array_length(msg) {
809         case 0:
810                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
811                 break;
812         case 1:
813                 break;
814         default:
815                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
816                 break;
817         }
818
819         if (!tldap_entry_values(msg[0], "member", &num_members, &blobs)) {
820                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
821         }
822
823         members = talloc_array(mem_ctx, uint32_t, num_members);
824         if (members == NULL) {
825                 return NT_STATUS_NO_MEMORY;
826         }
827
828         for (i=0; i<num_members; i++) {
829                 struct dom_sid sid;
830                 if (!pdb_ads_dnblob2sid(state->ld, &blobs[i], &sid)
831                     || !sid_peek_rid(&sid, &members[i])) {
832                         TALLOC_FREE(members);
833                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
834                 }
835         }
836
837         *pmembers = members;
838         *pnum_members = num_members;
839         return NT_STATUS_OK;
840 }
841
842 static NTSTATUS pdb_ads_enum_group_memberships(struct pdb_methods *m,
843                                                TALLOC_CTX *mem_ctx,
844                                                struct samu *user,
845                                                DOM_SID **pp_sids,
846                                                gid_t **pp_gids,
847                                                size_t *p_num_groups)
848 {
849         struct pdb_ads_state *state = talloc_get_type_abort(
850                 m->private_data, struct pdb_ads_state);
851         struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(
852                 m, user);
853         const char *attrs[1] = { "objectSid" };
854         struct tldap_message **groups;
855         int i, rc, count;
856         size_t num_groups;
857         struct dom_sid *group_sids;
858         gid_t *gids;
859
860         rc = tldap_search_fmt(
861                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
862                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &groups,
863                 "(&(member=%s)(grouptype=%d)(objectclass=group))",
864                 priv->dn, GTYPE_SECURITY_GLOBAL_GROUP);
865         if (rc != TLDAP_SUCCESS) {
866                 DEBUG(10, ("ldap_search failed %s\n",
867                            tldap_errstr(debug_ctx(), state->ld, rc)));
868                 return NT_STATUS_LDAP(rc);
869         }
870
871         count = talloc_array_length(groups);
872
873         group_sids = talloc_array(mem_ctx, struct dom_sid, count);
874         if (group_sids == NULL) {
875                 return NT_STATUS_NO_MEMORY;
876         }
877         gids = talloc_array(mem_ctx, gid_t, count);
878         if (gids == NULL) {
879                 TALLOC_FREE(group_sids);
880                 return NT_STATUS_NO_MEMORY;
881         }
882         num_groups = 0;
883
884         for (i=0; i<count; i++) {
885                 if (!tldap_pull_binsid(groups[i], "objectSid",
886                                        &group_sids[num_groups])) {
887                         continue;
888                 }
889                 gids[num_groups] = pdb_ads_sid2gid(&group_sids[num_groups]);
890
891                 num_groups += 1;
892                 if (num_groups == count) {
893                         break;
894                 }
895         }
896
897         *pp_sids = group_sids;
898         *pp_gids = gids;
899         *p_num_groups = num_groups;
900         return NT_STATUS_OK;
901 }
902
903 static NTSTATUS pdb_ads_set_unix_primary_group(struct pdb_methods *m,
904                                                TALLOC_CTX *mem_ctx,
905                                                struct samu *user)
906 {
907         return NT_STATUS_NOT_IMPLEMENTED;
908 }
909
910 static NTSTATUS pdb_ads_mod_groupmem(struct pdb_methods *m,
911                                      TALLOC_CTX *mem_ctx,
912                                      uint32 grouprid, uint32 memberrid,
913                                      int mod_op)
914 {
915         struct pdb_ads_state *state = talloc_get_type_abort(
916                 m->private_data, struct pdb_ads_state);
917         TALLOC_CTX *frame = talloc_stackframe();
918         struct dom_sid groupsid, membersid;
919         char *groupdn, *memberdn;
920         struct tldap_mod *mods;
921         int rc;
922         NTSTATUS status;
923
924         sid_compose(&groupsid, &state->domainsid, grouprid);
925         sid_compose(&membersid, &state->domainsid, memberrid);
926
927         status = pdb_ads_sid2dn(state, &groupsid, talloc_tos(), &groupdn);
928         if (!NT_STATUS_IS_OK(status)) {
929                 TALLOC_FREE(frame);
930                 return NT_STATUS_NO_SUCH_GROUP;
931         }
932         status = pdb_ads_sid2dn(state, &membersid, talloc_tos(), &memberdn);
933         if (!NT_STATUS_IS_OK(status)) {
934                 TALLOC_FREE(frame);
935                 return NT_STATUS_NO_SUCH_USER;
936         }
937
938         mods = NULL;
939
940         if (!tldap_add_mod_str(talloc_tos(), &mods, mod_op,
941                                "member", memberdn)) {
942                 TALLOC_FREE(frame);
943                 return NT_STATUS_NO_MEMORY;
944         }
945
946         rc = tldap_modify(state->ld, groupdn, 1, mods, NULL, NULL);
947         TALLOC_FREE(frame);
948         if (rc != TLDAP_SUCCESS) {
949                 DEBUG(10, ("ldap_modify failed: %s\n",
950                            tldap_errstr(debug_ctx(), state->ld, rc)));
951                 if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) {
952                         return NT_STATUS_MEMBER_IN_GROUP;
953                 }
954                 if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
955                         return NT_STATUS_MEMBER_NOT_IN_GROUP;
956                 }
957                 return NT_STATUS_LDAP(rc);
958         }
959
960         return NT_STATUS_OK;
961 }
962
963 static NTSTATUS pdb_ads_add_groupmem(struct pdb_methods *m,
964                                      TALLOC_CTX *mem_ctx,
965                                      uint32 group_rid, uint32 member_rid)
966 {
967         return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
968                                     TLDAP_MOD_ADD);
969 }
970
971 static NTSTATUS pdb_ads_del_groupmem(struct pdb_methods *m,
972                                      TALLOC_CTX *mem_ctx,
973                                      uint32 group_rid, uint32 member_rid)
974 {
975         return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
976                                     TLDAP_MOD_DELETE);
977 }
978
979 static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m,
980                                      const char *name, uint32 *rid)
981 {
982         TALLOC_CTX *frame = talloc_stackframe();
983         struct pdb_ads_state *state = talloc_get_type_abort(
984                 m->private_data, struct pdb_ads_state);
985         const char *attrs[1] = { "objectSid" };
986         int num_mods = 0;
987         struct tldap_mod *mods = NULL;
988         struct tldap_message **alias;
989         struct dom_sid sid;
990         char *dn;
991         int rc;
992         bool ok = true;
993
994         dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
995                              state->domaindn);
996         if (dn == NULL) {
997                 TALLOC_FREE(frame);
998                 return NT_STATUS_NO_MEMORY;
999         }
1000
1001         ok &= tldap_make_mod_fmt(
1002                 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
1003                 name);
1004         ok &= tldap_make_mod_fmt(
1005                 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "group");
1006         ok &= tldap_make_mod_fmt(
1007                 NULL, talloc_tos(), &num_mods, &mods, "groupType",
1008                 "%d", (int)GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1009
1010         if (!ok) {
1011                 TALLOC_FREE(frame);
1012                 return NT_STATUS_NO_MEMORY;
1013         }
1014
1015         rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL);
1016         if (rc != TLDAP_SUCCESS) {
1017                 DEBUG(10, ("ldap_add failed %s\n",
1018                            tldap_errstr(debug_ctx(), state->ld, rc)));
1019                 TALLOC_FREE(frame);
1020                 return NT_STATUS_LDAP(rc);
1021         }
1022
1023         rc = tldap_search_fmt(
1024                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1025                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
1026                 "(&(objectclass=group)(samaccountname=%s))", name);
1027         if (rc != TLDAP_SUCCESS) {
1028                 DEBUG(10, ("Could not find just created alias %s: %s\n",
1029                            name, tldap_errstr(debug_ctx(), state->ld, rc)));
1030                 TALLOC_FREE(frame);
1031                 return NT_STATUS_LDAP(rc);
1032         }
1033
1034         if (talloc_array_length(alias) != 1) {
1035                 DEBUG(10, ("Got %d alias, expected one\n",
1036                            (int)talloc_array_length(alias)));
1037                 TALLOC_FREE(frame);
1038                 return NT_STATUS_LDAP(rc);
1039         }
1040
1041         if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
1042                 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
1043                            name));
1044                 TALLOC_FREE(frame);
1045                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1046         }
1047
1048         sid_peek_rid(&sid, rid);
1049         TALLOC_FREE(frame);
1050         return NT_STATUS_OK;
1051 }
1052
1053 static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m,
1054                                      const DOM_SID *sid)
1055 {
1056         struct pdb_ads_state *state = talloc_get_type_abort(
1057                 m->private_data, struct pdb_ads_state);
1058         struct tldap_message **alias;
1059         char *sidstr, *dn;
1060         int rc;
1061
1062         sidstr = sid_binstring(talloc_tos(), sid);
1063         if (sidstr == NULL) {
1064                 return NT_STATUS_NO_MEMORY;
1065         }
1066
1067         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1068                               NULL, 0, 0, talloc_tos(), &alias,
1069                               "(&(objectSid=%s)(objectclass=group)"
1070                               "(|(grouptype=%d)(grouptype=%d)))",
1071                               sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1072                               GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1073         TALLOC_FREE(sidstr);
1074         if (rc != TLDAP_SUCCESS) {
1075                 DEBUG(10, ("ldap_search failed: %s\n",
1076                            tldap_errstr(debug_ctx(), state->ld, rc)));
1077                 TALLOC_FREE(dn);
1078                 return NT_STATUS_LDAP(rc);
1079         }
1080         if (talloc_array_length(alias) != 1) {
1081                 DEBUG(10, ("Expected 1 alias, got %d\n",
1082                            (int)talloc_array_length(alias)));
1083                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1084         }
1085         if (!tldap_entry_dn(alias[0], &dn)) {
1086                 DEBUG(10, ("Could not get DN for alias %s\n",
1087                            sid_string_dbg(sid)));
1088                 return NT_STATUS_INTERNAL_ERROR;
1089         }
1090
1091         rc = tldap_delete(state->ld, dn, NULL, NULL);
1092         if (rc != TLDAP_SUCCESS) {
1093                 DEBUG(10, ("ldap_delete failed: %s\n",
1094                            tldap_errstr(debug_ctx(), state->ld, rc)));
1095                 TALLOC_FREE(dn);
1096                 return NT_STATUS_LDAP(rc);
1097         }
1098
1099         return NT_STATUS_OK;
1100 }
1101
1102 static NTSTATUS pdb_ads_get_aliasinfo(struct pdb_methods *m,
1103                                       const DOM_SID *sid,
1104                                       struct acct_info *info)
1105 {
1106         return NT_STATUS_NOT_IMPLEMENTED;
1107 }
1108
1109 static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m,
1110                                       const DOM_SID *sid,
1111                                       struct acct_info *info)
1112 {
1113         return NT_STATUS_NOT_IMPLEMENTED;
1114 }
1115
1116 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
1117                                const struct dom_sid *sid,
1118                                TALLOC_CTX *mem_ctx, char **pdn)
1119 {
1120         struct tldap_message **msg;
1121         char *sidstr, *dn;
1122         int rc;
1123
1124         sidstr = sid_binstring(talloc_tos(), sid);
1125         NT_STATUS_HAVE_NO_MEMORY(sidstr);
1126
1127         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1128                               NULL, 0, 0, talloc_tos(), &msg,
1129                               "(objectsid=%s)", sidstr);
1130         TALLOC_FREE(sidstr);
1131         if (rc != TLDAP_SUCCESS) {
1132                 DEBUG(10, ("ldap_search failed %s\n",
1133                            tldap_errstr(debug_ctx(), state->ld, rc)));
1134                 return NT_STATUS_LDAP(rc);
1135         }
1136
1137         switch talloc_array_length(msg) {
1138         case 0:
1139                 return NT_STATUS_NOT_FOUND;
1140         case 1:
1141                 break;
1142         default:
1143                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1144         }
1145
1146         if (!tldap_entry_dn(msg[0], &dn)) {
1147                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1148         }
1149
1150         dn = talloc_strdup(mem_ctx, dn);
1151         if (dn == NULL) {
1152                 return NT_STATUS_NO_MEMORY;
1153         }
1154         TALLOC_FREE(msg);
1155
1156         *pdn = dn;
1157         return NT_STATUS_OK;
1158 }
1159
1160 static NTSTATUS pdb_ads_mod_aliasmem(struct pdb_methods *m,
1161                                      const DOM_SID *alias,
1162                                      const DOM_SID *member,
1163                                      int mod_op)
1164 {
1165         struct pdb_ads_state *state = talloc_get_type_abort(
1166                 m->private_data, struct pdb_ads_state);
1167         TALLOC_CTX *frame = talloc_stackframe();
1168         struct tldap_mod *mods;
1169         int rc;
1170         char *aliasdn, *memberdn;
1171         NTSTATUS status;
1172
1173         status = pdb_ads_sid2dn(state, alias, talloc_tos(), &aliasdn);
1174         if (!NT_STATUS_IS_OK(status)) {
1175                 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1176                            sid_string_dbg(alias), nt_errstr(status)));
1177                 TALLOC_FREE(frame);
1178                 return NT_STATUS_NO_SUCH_ALIAS;
1179         }
1180         status = pdb_ads_sid2dn(state, member, talloc_tos(), &memberdn);
1181         if (!NT_STATUS_IS_OK(status)) {
1182                 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1183                            sid_string_dbg(member), nt_errstr(status)));
1184                 TALLOC_FREE(frame);
1185                 return status;
1186         }
1187
1188         mods = NULL;
1189
1190         if (!tldap_add_mod_str(talloc_tos(), &mods, mod_op,
1191                                "member", memberdn)) {
1192                 TALLOC_FREE(frame);
1193                 return NT_STATUS_NO_MEMORY;
1194         }
1195
1196         rc = tldap_modify(state->ld, aliasdn, 1, mods, NULL, NULL);
1197         TALLOC_FREE(frame);
1198         if (rc != TLDAP_SUCCESS) {
1199                 DEBUG(10, ("ldap_modify failed: %s\n",
1200                            tldap_errstr(debug_ctx(), state->ld, rc)));
1201                 if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) {
1202                         return NT_STATUS_MEMBER_IN_ALIAS;
1203                 }
1204                 if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
1205                         return NT_STATUS_MEMBER_NOT_IN_ALIAS;
1206                 }
1207                 return NT_STATUS_LDAP(rc);
1208         }
1209
1210         return NT_STATUS_OK;
1211 }
1212
1213 static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
1214                                      const DOM_SID *alias,
1215                                      const DOM_SID *member)
1216 {
1217         return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_ADD);
1218 }
1219
1220 static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
1221                                      const DOM_SID *alias,
1222                                      const DOM_SID *member)
1223 {
1224         return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_DELETE);
1225 }
1226
1227 static bool pdb_ads_dnblob2sid(struct tldap_context *ld, DATA_BLOB *dnblob,
1228                                struct dom_sid *psid)
1229 {
1230         const char *attrs[1] = { "objectSid" };
1231         struct tldap_message **msg;
1232         char *dn;
1233         size_t len;
1234         int rc;
1235         bool ret;
1236
1237         if (!convert_string_talloc(talloc_tos(), CH_UTF8, CH_UNIX,
1238                                    dnblob->data, dnblob->length, &dn, &len,
1239                                    false)) {
1240                 return false;
1241         }
1242         rc = tldap_search_fmt(ld, dn, TLDAP_SCOPE_BASE,
1243                               attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1244                               &msg, "(objectclass=*)");
1245         TALLOC_FREE(dn);
1246         if (talloc_array_length(msg) != 1) {
1247                 DEBUG(10, ("Got %d objects, expected one\n",
1248                            (int)talloc_array_length(msg)));
1249                 TALLOC_FREE(msg);
1250                 return false;
1251         }
1252
1253         ret = tldap_pull_binsid(msg[0], "objectSid", psid);
1254         TALLOC_FREE(msg);
1255         return ret;
1256 }
1257
1258 static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
1259                                       const DOM_SID *alias,
1260                                       TALLOC_CTX *mem_ctx,
1261                                       DOM_SID **pmembers,
1262                                       size_t *pnum_members)
1263 {
1264         struct pdb_ads_state *state = talloc_get_type_abort(
1265                 m->private_data, struct pdb_ads_state);
1266         const char *attrs[1] = { "member" };
1267         char *sidstr;
1268         struct tldap_message **msg;
1269         int i, rc, num_members;
1270         DATA_BLOB *blobs;
1271         struct dom_sid *members;
1272
1273         sidstr = sid_binstring(talloc_tos(), alias);
1274         NT_STATUS_HAVE_NO_MEMORY(sidstr);
1275
1276         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1277                               attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &msg,
1278                               "(objectsid=%s)", sidstr);
1279         TALLOC_FREE(sidstr);
1280         if (rc != TLDAP_SUCCESS) {
1281                 DEBUG(10, ("ldap_search failed %s\n",
1282                            tldap_errstr(debug_ctx(), state->ld, rc)));
1283                 return NT_STATUS_LDAP(rc);
1284         }
1285         switch talloc_array_length(msg) {
1286         case 0:
1287                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1288                 break;
1289         case 1:
1290                 break;
1291         default:
1292                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1293                 break;
1294         }
1295
1296         if (!tldap_entry_values(msg[0], "member", &num_members, &blobs)) {
1297                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1298         }
1299
1300         members = talloc_array(mem_ctx, struct dom_sid, num_members);
1301         if (members == NULL) {
1302                 return NT_STATUS_NO_MEMORY;
1303         }
1304
1305         for (i=0; i<num_members; i++) {
1306                 if (!pdb_ads_dnblob2sid(state->ld, &blobs[i], &members[i])) {
1307                         TALLOC_FREE(members);
1308                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1309                 }
1310         }
1311
1312         *pmembers = members;
1313         *pnum_members = num_members;
1314         return NT_STATUS_OK;
1315 }
1316
1317 static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,
1318                                                TALLOC_CTX *mem_ctx,
1319                                                const DOM_SID *domain_sid,
1320                                                const DOM_SID *members,
1321                                                size_t num_members,
1322                                                uint32 **pp_alias_rids,
1323                                                size_t *p_num_alias_rids)
1324 {
1325         return NT_STATUS_NOT_IMPLEMENTED;
1326 }
1327
1328 static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m,
1329                                     const DOM_SID *domain_sid,
1330                                     int num_rids,
1331                                     uint32 *rids,
1332                                     const char **pp_names,
1333                                     enum lsa_SidType *attrs)
1334 {
1335         return NT_STATUS_NOT_IMPLEMENTED;
1336 }
1337
1338 static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m,
1339                                      const DOM_SID *domain_sid,
1340                                      int num_names,
1341                                      const char **pp_names,
1342                                      uint32 *rids,
1343                                      enum lsa_SidType *attrs)
1344 {
1345         return NT_STATUS_NOT_IMPLEMENTED;
1346 }
1347
1348 static NTSTATUS pdb_ads_get_account_policy(struct pdb_methods *m,
1349                                            int policy_index, uint32 *value)
1350 {
1351         return account_policy_get(policy_index, value)
1352                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1353 }
1354
1355 static NTSTATUS pdb_ads_set_account_policy(struct pdb_methods *m,
1356                                            int policy_index, uint32 value)
1357 {
1358         return account_policy_set(policy_index, value)
1359                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1360 }
1361
1362 static NTSTATUS pdb_ads_get_seq_num(struct pdb_methods *m,
1363                                     time_t *seq_num)
1364 {
1365         return NT_STATUS_NOT_IMPLEMENTED;
1366 }
1367
1368 struct pdb_ads_search_state {
1369         uint32_t acct_flags;
1370         struct samr_displayentry *entries;
1371         uint32_t num_entries;
1372         ssize_t array_size;
1373         uint32_t current;
1374 };
1375
1376 static bool pdb_ads_next_entry(struct pdb_search *search,
1377                                struct samr_displayentry *entry)
1378 {
1379         struct pdb_ads_search_state *state = talloc_get_type_abort(
1380                 search->private_data, struct pdb_ads_search_state);
1381
1382         if (state->current == state->num_entries) {
1383                 return false;
1384         }
1385
1386         entry->idx = state->entries[state->current].idx;
1387         entry->rid = state->entries[state->current].rid;
1388         entry->acct_flags = state->entries[state->current].acct_flags;
1389
1390         entry->account_name = talloc_strdup(
1391                 search, state->entries[state->current].account_name);
1392         entry->fullname = talloc_strdup(
1393                 search, state->entries[state->current].fullname);
1394         entry->description = talloc_strdup(
1395                 search, state->entries[state->current].description);
1396
1397         if ((entry->account_name == NULL) || (entry->fullname == NULL)
1398             || (entry->description == NULL)) {
1399                 DEBUG(0, ("talloc_strdup failed\n"));
1400                 return false;
1401         }
1402
1403         state->current += 1;
1404         return true;
1405 }
1406
1407 static void pdb_ads_search_end(struct pdb_search *search)
1408 {
1409         struct pdb_ads_search_state *state = talloc_get_type_abort(
1410                 search->private_data, struct pdb_ads_search_state);
1411         TALLOC_FREE(state);
1412 }
1413
1414 static bool pdb_ads_search_filter(struct pdb_methods *m,
1415                                   struct pdb_search *search,
1416                                   const char *filter,
1417                                   struct pdb_ads_search_state **pstate)
1418 {
1419         struct pdb_ads_state *state = talloc_get_type_abort(
1420                 m->private_data, struct pdb_ads_state);
1421         struct pdb_ads_search_state *sstate;
1422         const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1423                                  "userAccountControl", "description" };
1424         struct tldap_message **users;
1425         int i, rc, num_users;
1426
1427         sstate = talloc_zero(search, struct pdb_ads_search_state);
1428         if (sstate == NULL) {
1429                 return false;
1430         }
1431
1432         rc = tldap_search_fmt(
1433                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1434                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &users,
1435                 "%s", filter);
1436         if (rc != TLDAP_SUCCESS) {
1437                 DEBUG(10, ("ldap_search_ext_s failed: %s\n",
1438                            tldap_errstr(debug_ctx(), state->ld, rc)));
1439                 return false;
1440         }
1441
1442         num_users = talloc_array_length(users);
1443
1444         sstate->entries = talloc_array(sstate, struct samr_displayentry,
1445                                        num_users);
1446         if (sstate->entries == NULL) {
1447                 DEBUG(10, ("talloc failed\n"));
1448                 return false;
1449         }
1450
1451         sstate->num_entries = 0;
1452
1453         for (i=0; i<num_users; i++) {
1454                 struct samr_displayentry *e;
1455                 struct dom_sid sid;
1456
1457                 e = &sstate->entries[sstate->num_entries];
1458
1459                 e->idx = sstate->num_entries;
1460                 if (!tldap_pull_binsid(users[i], "objectSid", &sid)) {
1461                         DEBUG(10, ("Could not pull sid\n"));
1462                         continue;
1463                 }
1464                 sid_peek_rid(&sid, &e->rid);
1465                 e->acct_flags = ACB_NORMAL;
1466                 e->account_name = tldap_talloc_single_attribute(
1467                         users[i], "samAccountName", sstate->entries);
1468                 if (e->account_name == NULL) {
1469                         return false;
1470                 }
1471                 e->fullname = tldap_talloc_single_attribute(
1472                         users[i], "displayName", sstate->entries);
1473                 if (e->fullname == NULL) {
1474                         e->fullname = "";
1475                 }
1476                 e->description = tldap_talloc_single_attribute(
1477                         users[i], "description", sstate->entries);
1478                 if (e->description == NULL) {
1479                         e->description = "";
1480                 }
1481
1482                 sstate->num_entries += 1;
1483                 if (sstate->num_entries >= num_users) {
1484                         break;
1485                 }
1486         }
1487
1488         search->private_data = sstate;
1489         search->next_entry = pdb_ads_next_entry;
1490         search->search_end = pdb_ads_search_end;
1491         *pstate = sstate;
1492         return true;
1493 }
1494
1495 static bool pdb_ads_search_users(struct pdb_methods *m,
1496                                  struct pdb_search *search,
1497                                  uint32 acct_flags)
1498 {
1499         struct pdb_ads_search_state *sstate;
1500         bool ret;
1501
1502         ret = pdb_ads_search_filter(m, search, "(objectclass=user)", &sstate);
1503         if (!ret) {
1504                 return false;
1505         }
1506         sstate->acct_flags = acct_flags;
1507         return true;
1508 }
1509
1510 static bool pdb_ads_search_groups(struct pdb_methods *m,
1511                                   struct pdb_search *search)
1512 {
1513         struct pdb_ads_search_state *sstate;
1514         char *filter;
1515         bool ret;
1516
1517         filter = talloc_asprintf(talloc_tos(),
1518                                  "(&(grouptype=%d)(objectclass=group))",
1519                                  GTYPE_SECURITY_GLOBAL_GROUP);
1520         if (filter == NULL) {
1521                 return false;
1522         }
1523         ret = pdb_ads_search_filter(m, search, filter, &sstate);
1524         TALLOC_FREE(filter);
1525         if (!ret) {
1526                 return false;
1527         }
1528         sstate->acct_flags = 0;
1529         return true;
1530 }
1531
1532 static bool pdb_ads_search_aliases(struct pdb_methods *m,
1533                                    struct pdb_search *search,
1534                                    const DOM_SID *sid)
1535 {
1536         struct pdb_ads_search_state *sstate;
1537         char *filter;
1538         bool ret;
1539
1540         filter = talloc_asprintf(
1541                 talloc_tos(), "(&(grouptype=%d)(objectclass=group))",
1542                 sid_check_is_builtin(sid)
1543                 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
1544                 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1545
1546         if (filter == NULL) {
1547                 return false;
1548         }
1549         ret = pdb_ads_search_filter(m, search, filter, &sstate);
1550         TALLOC_FREE(filter);
1551         if (!ret) {
1552                 return false;
1553         }
1554         sstate->acct_flags = 0;
1555         return true;
1556 }
1557
1558 static bool pdb_ads_uid_to_rid(struct pdb_methods *m, uid_t uid,
1559                                uint32 *rid)
1560 {
1561         return false;
1562 }
1563
1564 static bool pdb_ads_uid_to_sid(struct pdb_methods *m, uid_t uid,
1565                                DOM_SID *sid)
1566 {
1567         struct pdb_ads_state *state = talloc_get_type_abort(
1568                 m->private_data, struct pdb_ads_state);
1569         sid_compose(sid, &state->domainsid, uid);
1570         return true;
1571 }
1572
1573 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
1574                                DOM_SID *sid)
1575 {
1576         struct pdb_ads_state *state = talloc_get_type_abort(
1577                 m->private_data, struct pdb_ads_state);
1578         sid_compose(sid, &state->domainsid, gid);
1579         return true;
1580 }
1581
1582 static bool pdb_ads_sid_to_id(struct pdb_methods *m, const DOM_SID *sid,
1583                               union unid_t *id, enum lsa_SidType *type)
1584 {
1585         struct pdb_ads_state *state = talloc_get_type_abort(
1586                 m->private_data, struct pdb_ads_state);
1587         struct tldap_message **msg;
1588         char *sidstr;
1589         uint32_t rid;
1590         int rc;
1591
1592         /*
1593          * This is a big, big hack: Just hard-code the rid as uid/gid.
1594          */
1595
1596         sid_peek_rid(sid, &rid);
1597
1598         sidstr = sid_binstring(talloc_tos(), sid);
1599         if (sidstr == NULL) {
1600                 return false;
1601         }
1602
1603         rc = tldap_search_fmt(
1604                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1605                 NULL, 0, 0, talloc_tos(), &msg,
1606                 "(&(objectsid=%s)(objectclass=user))", sidstr);
1607         if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
1608                 id->uid = rid;
1609                 *type = SID_NAME_USER;
1610                 TALLOC_FREE(sidstr);
1611                 return true;
1612         }
1613
1614         rc = tldap_search_fmt(
1615                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1616                 NULL, 0, 0, talloc_tos(), &msg,
1617                 "(&(objectsid=%s)(objectclass=group))", sidstr);
1618         if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
1619                 id->gid = rid;
1620                 *type = SID_NAME_DOM_GRP;
1621                 TALLOC_FREE(sidstr);
1622                 return true;
1623         }
1624
1625         TALLOC_FREE(sidstr);
1626         return false;
1627 }
1628
1629 static bool pdb_ads_rid_algorithm(struct pdb_methods *m)
1630 {
1631         return false;
1632 }
1633
1634 static bool pdb_ads_new_rid(struct pdb_methods *m, uint32 *rid)
1635 {
1636         return false;
1637 }
1638
1639 static bool pdb_ads_get_trusteddom_pw(struct pdb_methods *m,
1640                                       const char *domain, char** pwd,
1641                                       DOM_SID *sid,
1642                                       time_t *pass_last_set_time)
1643 {
1644         return false;
1645 }
1646
1647 static bool pdb_ads_set_trusteddom_pw(struct pdb_methods *m,
1648                                       const char* domain, const char* pwd,
1649                                       const DOM_SID *sid)
1650 {
1651         return false;
1652 }
1653
1654 static bool pdb_ads_del_trusteddom_pw(struct pdb_methods *m,
1655                                       const char *domain)
1656 {
1657         return false;
1658 }
1659
1660 static NTSTATUS pdb_ads_enum_trusteddoms(struct pdb_methods *m,
1661                                          TALLOC_CTX *mem_ctx,
1662                                          uint32 *num_domains,
1663                                          struct trustdom_info ***domains)
1664 {
1665         return NT_STATUS_NOT_IMPLEMENTED;
1666 }
1667
1668 static void pdb_ads_init_methods(struct pdb_methods *m)
1669 {
1670         m->name = "ads";
1671         m->getsampwnam = pdb_ads_getsampwnam;
1672         m->getsampwsid = pdb_ads_getsampwsid;
1673         m->create_user = pdb_ads_create_user;
1674         m->delete_user = pdb_ads_delete_user;
1675         m->add_sam_account = pdb_ads_add_sam_account;
1676         m->update_sam_account = pdb_ads_update_sam_account;
1677         m->delete_sam_account = pdb_ads_delete_sam_account;
1678         m->rename_sam_account = pdb_ads_rename_sam_account;
1679         m->update_login_attempts = pdb_ads_update_login_attempts;
1680         m->getgrsid = pdb_ads_getgrsid;
1681         m->getgrgid = pdb_ads_getgrgid;
1682         m->getgrnam = pdb_ads_getgrnam;
1683         m->create_dom_group = pdb_ads_create_dom_group;
1684         m->delete_dom_group = pdb_ads_delete_dom_group;
1685         m->add_group_mapping_entry = pdb_ads_add_group_mapping_entry;
1686         m->update_group_mapping_entry = pdb_ads_update_group_mapping_entry;
1687         m->delete_group_mapping_entry = pdb_ads_delete_group_mapping_entry;
1688         m->enum_group_mapping = pdb_ads_enum_group_mapping;
1689         m->enum_group_members = pdb_ads_enum_group_members;
1690         m->enum_group_memberships = pdb_ads_enum_group_memberships;
1691         m->set_unix_primary_group = pdb_ads_set_unix_primary_group;
1692         m->add_groupmem = pdb_ads_add_groupmem;
1693         m->del_groupmem = pdb_ads_del_groupmem;
1694         m->create_alias = pdb_ads_create_alias;
1695         m->delete_alias = pdb_ads_delete_alias;
1696         m->get_aliasinfo = pdb_ads_get_aliasinfo;
1697         m->set_aliasinfo = pdb_ads_set_aliasinfo;
1698         m->add_aliasmem = pdb_ads_add_aliasmem;
1699         m->del_aliasmem = pdb_ads_del_aliasmem;
1700         m->enum_aliasmem = pdb_ads_enum_aliasmem;
1701         m->enum_alias_memberships = pdb_ads_enum_alias_memberships;
1702         m->lookup_rids = pdb_ads_lookup_rids;
1703         m->lookup_names = pdb_ads_lookup_names;
1704         m->get_account_policy = pdb_ads_get_account_policy;
1705         m->set_account_policy = pdb_ads_set_account_policy;
1706         m->get_seq_num = pdb_ads_get_seq_num;
1707         m->search_users = pdb_ads_search_users;
1708         m->search_groups = pdb_ads_search_groups;
1709         m->search_aliases = pdb_ads_search_aliases;
1710         m->uid_to_rid = pdb_ads_uid_to_rid;
1711         m->uid_to_sid = pdb_ads_uid_to_sid;
1712         m->gid_to_sid = pdb_ads_gid_to_sid;
1713         m->sid_to_id = pdb_ads_sid_to_id;
1714         m->rid_algorithm = pdb_ads_rid_algorithm;
1715         m->new_rid = pdb_ads_new_rid;
1716         m->get_trusteddom_pw = pdb_ads_get_trusteddom_pw;
1717         m->set_trusteddom_pw = pdb_ads_set_trusteddom_pw;
1718         m->del_trusteddom_pw = pdb_ads_del_trusteddom_pw;
1719         m->enum_trusteddoms = pdb_ads_enum_trusteddoms;
1720 }
1721
1722 static void free_private_data(void **vp)
1723 {
1724         struct pdb_ads_state *state = talloc_get_type_abort(
1725                 *vp, struct pdb_ads_state);
1726
1727         TALLOC_FREE(state->ld);
1728         return;
1729 }
1730
1731 static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state,
1732                                 const char *location)
1733 {
1734         const char *rootdse_attrs[2] = {
1735                 "defaultNamingContext", "configurationNamingContext" };
1736         const char *domain_attrs[1] = { "objectSid" };
1737         const char *ncname_attrs[1] = { "netbiosname" };
1738         struct tldap_message **rootdse, **domain, **ncname;
1739         TALLOC_CTX *frame = talloc_stackframe();
1740         struct sockaddr_un sunaddr;
1741         NTSTATUS status;
1742         int num_domains;
1743         int fd, rc;
1744
1745         ZERO_STRUCT(sunaddr);
1746         sunaddr.sun_family = AF_UNIX;
1747         strncpy(sunaddr.sun_path, location, sizeof(sunaddr.sun_path) - 1);
1748
1749         status = open_socket_out((struct sockaddr_storage *)(void *)&sunaddr,
1750                                  0, 0, &fd);
1751         if (!NT_STATUS_IS_OK(status)) {
1752                 DEBUG(10, ("Could not connect to %s: %s\n", location,
1753                            nt_errstr(status)));
1754                 goto done;
1755         }
1756
1757         state->ld = tldap_context_create(state, fd);
1758         if (state->ld == NULL) {
1759                 close(fd);
1760                 status = NT_STATUS_NO_MEMORY;
1761                 goto done;
1762         }
1763
1764         rc = tldap_search_fmt(
1765                 state->ld, "", TLDAP_SCOPE_BASE,
1766                 rootdse_attrs, ARRAY_SIZE(rootdse_attrs), 0,
1767                 talloc_tos(), &rootdse, "(objectclass=*)");
1768         if (rc != TLDAP_SUCCESS) {
1769                 DEBUG(10, ("Could not retrieve rootdse: %s\n",
1770                            tldap_errstr(debug_ctx(), state->ld, rc)));
1771                 status = NT_STATUS_LDAP(rc);
1772                 goto done;
1773         }
1774         if (talloc_array_length(rootdse) != 1) {
1775                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1776                 goto done;
1777         }
1778
1779         state->domaindn = tldap_talloc_single_attribute(
1780                 rootdse[0], "defaultNamingContext", state);
1781         if (state->domaindn == NULL) {
1782                 DEBUG(10, ("Could not get defaultNamingContext\n"));
1783                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1784                 goto done;
1785         }
1786         DEBUG(10, ("defaultNamingContext = %s\n", state->domaindn));
1787
1788         state->configdn = tldap_talloc_single_attribute(
1789                 rootdse[0], "configurationNamingContext", state);
1790         if (state->domaindn == NULL) {
1791                 DEBUG(10, ("Could not get configurationNamingContext\n"));
1792                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1793                 goto done;
1794         }
1795         DEBUG(10, ("configurationNamingContext = %s\n", state->configdn));
1796
1797         /*
1798          * Figure out our domain's SID
1799          */
1800         rc = tldap_search_fmt(
1801                 state->ld, state->domaindn, TLDAP_SCOPE_BASE,
1802                 domain_attrs, ARRAY_SIZE(domain_attrs), 0,
1803                 talloc_tos(), &domain, "(objectclass=*)");
1804         if (rc != TLDAP_SUCCESS) {
1805                 DEBUG(10, ("Could not retrieve domain: %s\n",
1806                            tldap_errstr(debug_ctx(), state->ld, rc)));
1807                 status = NT_STATUS_LDAP(rc);
1808                 goto done;
1809         }
1810
1811         num_domains = talloc_array_length(domain);
1812         if (num_domains != 1) {
1813                 DEBUG(10, ("Got %d domains, expected one\n", num_domains));
1814                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1815                 goto done;
1816         }
1817         if (!tldap_pull_binsid(domain[0], "objectSid", &state->domainsid)) {
1818                 DEBUG(10, ("Could not retrieve domain SID\n"));
1819                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1820                 goto done;
1821         }
1822         DEBUG(10, ("Domain SID: %s\n", sid_string_dbg(&state->domainsid)));
1823
1824         /*
1825          * Figure out our domain's short name
1826          */
1827         rc = tldap_search_fmt(
1828                 state->ld, state->configdn, TLDAP_SCOPE_SUB,
1829                 ncname_attrs, ARRAY_SIZE(ncname_attrs), 0,
1830                 talloc_tos(), &ncname, "(ncname=%s)", state->domaindn);
1831         if (rc != TLDAP_SUCCESS) {
1832                 DEBUG(10, ("Could not retrieve ncname: %s\n",
1833                            tldap_errstr(debug_ctx(), state->ld, rc)));
1834                 status = NT_STATUS_LDAP(rc);
1835                 goto done;
1836         }
1837         if (talloc_array_length(ncname) != 1) {
1838                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1839                 goto done;
1840         }
1841
1842         state->netbiosname = tldap_talloc_single_attribute(
1843                 ncname[0], "netbiosname", state);
1844         if (state->netbiosname == NULL) {
1845                 DEBUG(10, ("Could not get netbiosname\n"));
1846                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1847                 goto done;
1848         }
1849         DEBUG(10, ("netbiosname: %s\n", state->netbiosname));
1850
1851         if (!strequal(lp_workgroup(), state->netbiosname)) {
1852                 DEBUG(1, ("ADS is different domain (%s) than ours (%s)\n",
1853                           state->netbiosname, lp_workgroup()));
1854                 status = NT_STATUS_NO_SUCH_DOMAIN;
1855                 goto done;
1856         }
1857
1858         secrets_store_domain_sid(state->netbiosname, &state->domainsid);
1859
1860         status = NT_STATUS_OK;
1861 done:
1862         TALLOC_FREE(frame);
1863         return status;
1864 }
1865
1866 static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method,
1867                              const char *location)
1868 {
1869         struct pdb_methods *m;
1870         struct pdb_ads_state *state;
1871         char *tmp = NULL;
1872         NTSTATUS status;
1873
1874         m = talloc(talloc_autofree_context(), struct pdb_methods);
1875         if (m == NULL) {
1876                 return NT_STATUS_NO_MEMORY;
1877         }
1878         state = talloc(m, struct pdb_ads_state);
1879         if (state == NULL) {
1880                 goto nomem;
1881         }
1882         m->private_data = state;
1883         m->free_private_data = free_private_data;
1884         pdb_ads_init_methods(m);
1885
1886         if (location == NULL) {
1887                 tmp = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi",
1888                                       lp_private_dir());
1889                 location = tmp;
1890         }
1891         if (location == NULL) {
1892                 goto nomem;
1893         }
1894
1895         status = pdb_ads_connect(state, location);
1896         if (!NT_STATUS_IS_OK(status)) {
1897                 DEBUG(10, ("pdb_ads_connect failed: %s\n", nt_errstr(status)));
1898                 goto fail;
1899         }
1900
1901         *pdb_method = m;
1902         return NT_STATUS_OK;
1903 nomem:
1904         status = NT_STATUS_NO_MEMORY;
1905 fail:
1906         TALLOC_FREE(m);
1907         return status;
1908 }
1909
1910 NTSTATUS pdb_ads_init(void);
1911 NTSTATUS pdb_ads_init(void)
1912 {
1913         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "ads",
1914                                    pdb_init_ads);
1915 }