Implement pdb_ads_create_dom_group()
[ira/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 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
23                                     struct samu *sam_acct,
24                                     const DOM_SID *sid);
25 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
26                                DOM_SID *sid);
27
28
29 struct pdb_ads_state {
30         struct tldap_context *ld;
31         struct dom_sid domainsid;
32         char *domaindn;
33         char *configdn;
34         char *netbiosname;
35 };
36
37 static bool pdb_ads_pull_time(struct tldap_message *msg, const char *attr,
38                               time_t *ptime)
39 {
40         uint64_t tmp;
41
42         if (!tldap_pull_uint64(msg, attr, &tmp)) {
43                 return false;
44         }
45         *ptime = uint64s_nt_time_to_unix_abs(&tmp);
46         return true;
47 }
48
49 static gid_t pdb_ads_sid2gid(const struct dom_sid *sid)
50 {
51         uint32_t rid;
52         sid_peek_rid(sid, &rid);
53         return rid;
54 }
55
56 struct pdb_ads_samu_private {
57         char *dn;
58         struct tldap_message *ldapmsg;
59 };
60
61 static struct samu *pdb_ads_init_guest(TALLOC_CTX *mem_ctx,
62                                        struct pdb_methods *m)
63 {
64         struct pdb_ads_state *state = talloc_get_type_abort(
65                 m->private_data, struct pdb_ads_state);
66         struct dom_sid guest_sid;
67         struct samu *guest;
68         NTSTATUS status;
69
70         sid_compose(&guest_sid, &state->domainsid, DOMAIN_USER_RID_GUEST);
71
72         guest = samu_new(mem_ctx);
73         if (guest == NULL) {
74                 return NULL;
75         }
76
77         status = pdb_ads_getsampwsid(m, guest, &guest_sid);
78         if (!NT_STATUS_IS_OK(status)) {
79                 DEBUG(10, ("Could not init guest account: %s\n",
80                            nt_errstr(status)));
81                 TALLOC_FREE(guest);
82                 return NULL;
83         }
84         return guest;
85 }
86
87 static struct pdb_ads_samu_private *pdb_ads_get_samu_private(
88         struct pdb_methods *m, struct samu *sam)
89 {
90         struct pdb_ads_samu_private *result;
91         uint32_t rid;
92
93         result = (struct pdb_ads_samu_private *)
94                 pdb_get_backend_private_data(sam, m);
95
96         if (result != NULL) {
97                 return talloc_get_type_abort(
98                         result, struct pdb_ads_samu_private);
99         }
100
101         /*
102          * This is now a weirdness of the passdb API. For the guest user we
103          * are not asked first.
104          */
105         sid_peek_rid(pdb_get_user_sid(sam), &rid);
106
107         if (rid == DOMAIN_USER_RID_GUEST) {
108                 struct samu *guest = pdb_ads_init_guest(talloc_tos(), m);
109
110                 if (guest == NULL) {
111                         return NULL;
112                 }
113                 result = talloc_get_type_abort(
114                         pdb_get_backend_private_data(guest, m),
115                         struct pdb_ads_samu_private);
116                 pdb_set_backend_private_data(
117                         sam, talloc_move(sam, &result), NULL, m, PDB_SET);
118                 TALLOC_FREE(guest);
119                 return talloc_get_type_abort(
120                         pdb_get_backend_private_data(sam, m),
121                         struct pdb_ads_samu_private);
122         }
123
124         return NULL;
125 }
126
127 static NTSTATUS pdb_ads_init_sam_from_ads(struct pdb_methods *m,
128                                           struct samu *sam,
129                                           struct tldap_message *entry)
130 {
131         struct pdb_ads_state *state = talloc_get_type_abort(
132                 m->private_data, struct pdb_ads_state);
133         TALLOC_CTX *frame = talloc_stackframe();
134         struct pdb_ads_samu_private *priv;
135         NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
136         char *str;
137         time_t tmp_time;
138         struct dom_sid sid;
139         uint64_t n;
140         DATA_BLOB blob;
141
142         priv = talloc(sam, struct pdb_ads_samu_private);
143         if (priv == NULL) {
144                 return NT_STATUS_NO_MEMORY;
145         }
146         if (!tldap_entry_dn(entry, &priv->dn)) {
147                 TALLOC_FREE(priv);
148                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
149         }
150
151         str = tldap_talloc_single_attribute(entry, "samAccountName", sam);
152         if (str == NULL) {
153                 DEBUG(10, ("no samAccountName\n"));
154                 goto fail;
155         }
156         pdb_set_username(sam, str, PDB_SET);
157         TALLOC_FREE(str);
158
159         if (pdb_ads_pull_time(entry, "lastLogon", &tmp_time)) {
160                 pdb_set_logon_time(sam, tmp_time, PDB_SET);
161         }
162         if (pdb_ads_pull_time(entry, "lastLogoff", &tmp_time)) {
163                 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
164         }
165         if (pdb_ads_pull_time(entry, "pwdLastSet", &tmp_time)) {
166                 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
167         }
168         if (pdb_ads_pull_time(entry, "accountExpires", &tmp_time)) {
169                 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
170         }
171
172         str = tldap_talloc_single_attribute(entry, "samAccoutName",
173                                             talloc_tos());
174         if (str != NULL) {
175                 pdb_set_username(sam, str, PDB_SET);
176         }
177
178         str = tldap_talloc_single_attribute(entry, "displayName",
179                                             talloc_tos());
180         if (str != NULL) {
181                 pdb_set_fullname(sam, str, PDB_SET);
182         }
183
184         str = tldap_talloc_single_attribute(entry, "homeDirectory",
185                                             talloc_tos());
186         if (str != NULL) {
187                 pdb_set_homedir(sam, str, PDB_SET);
188         }
189
190         str = tldap_talloc_single_attribute(entry, "homeDrive", talloc_tos());
191         if (str != NULL) {
192                 pdb_set_dir_drive(sam, str, PDB_SET);
193         }
194
195         str = tldap_talloc_single_attribute(entry, "scriptPath", talloc_tos());
196         if (str != NULL) {
197                 pdb_set_logon_script(sam, str, PDB_SET);
198         }
199
200         str = tldap_talloc_single_attribute(entry, "profilePath",
201                                             talloc_tos());
202         if (str != NULL) {
203                 pdb_set_profile_path(sam, str, PDB_SET);
204         }
205
206         str = tldap_talloc_single_attribute(entry, "profilePath",
207                                             talloc_tos());
208         if (str != NULL) {
209                 pdb_set_profile_path(sam, str, PDB_SET);
210         }
211
212         if (!tldap_pull_binsid(entry, "objectSid", &sid)) {
213                 DEBUG(10, ("Could not pull SID\n"));
214                 goto fail;
215         }
216         pdb_set_user_sid(sam, &sid, PDB_SET);
217
218         if (!tldap_pull_uint64(entry, "userAccountControl", &n)) {
219                 DEBUG(10, ("Could not pull userAccountControl\n"));
220                 goto fail;
221         }
222         pdb_set_acct_ctrl(sam, ads_uf2acb(n), PDB_SET);
223
224         if (tldap_get_single_valueblob(entry, "unicodePwd", &blob)) {
225                 if (blob.length != NT_HASH_LEN) {
226                         DEBUG(0, ("Got NT hash of length %d, expected %d\n",
227                                   (int)blob.length, NT_HASH_LEN));
228                         goto fail;
229                 }
230                 pdb_set_nt_passwd(sam, blob.data, PDB_SET);
231         }
232
233         if (tldap_get_single_valueblob(entry, "dBCSPwd", &blob)) {
234                 if (blob.length != LM_HASH_LEN) {
235                         DEBUG(0, ("Got LM hash of length %d, expected %d\n",
236                                   (int)blob.length, LM_HASH_LEN));
237                         goto fail;
238                 }
239                 pdb_set_lanman_passwd(sam, blob.data, PDB_SET);
240         }
241
242         if (tldap_pull_uint64(entry, "primaryGroupID", &n)) {
243                 sid_compose(&sid, &state->domainsid, n);
244                 pdb_set_group_sid(sam, &sid, PDB_SET);
245
246         }
247
248         priv->ldapmsg = talloc_move(priv, &entry);
249         pdb_set_backend_private_data(sam, priv, NULL, m, PDB_SET);
250
251         status = NT_STATUS_OK;
252 fail:
253         TALLOC_FREE(frame);
254         return status;
255 }
256
257 static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state,
258                                       struct tldap_message *existing,
259                                       TALLOC_CTX *mem_ctx,
260                                       int *pnum_mods, struct tldap_mod **pmods,
261                                       struct samu *sam)
262 {
263         bool ret = true;
264
265         /* TODO: All fields :-) */
266
267         ret &= tldap_make_mod_fmt(
268                 existing, mem_ctx, pnum_mods, pmods, "displayName",
269                 pdb_get_fullname(sam));
270
271         ret &= tldap_make_mod_blob(
272                 existing, mem_ctx, pnum_mods, pmods, "unicodePwd",
273                 data_blob_const(pdb_get_nt_passwd(sam), NT_HASH_LEN));
274
275         ret &= tldap_make_mod_blob(
276                 existing, mem_ctx, pnum_mods, pmods, "dBCSPwd",
277                 data_blob_const(pdb_get_lanman_passwd(sam), NT_HASH_LEN));
278
279         return ret;
280 }
281
282 static NTSTATUS pdb_ads_getsampwfilter(struct pdb_methods *m,
283                                        struct pdb_ads_state *state,
284                                        struct samu *sam_acct,
285                                        const char *filter)
286 {
287         const char * attrs[] = {
288                 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
289                 "sAMAccountName", "displayName", "homeDirectory",
290                 "homeDrive", "scriptPath", "profilePath", "description",
291                 "userWorkstations", "comment", "userParameters", "objectSid",
292                 "primaryGroupID", "userAccountControl", "logonHours",
293                 "badPwdCount", "logonCount", "countryCode", "codePage",
294                 "unicodePwd", "dBCSPwd" };
295         struct tldap_message **users;
296         int rc, count;
297
298         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
299                               attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
300                               &users, "%s", filter);
301         if (rc != TLDAP_SUCCESS) {
302                 DEBUG(10, ("ldap_search failed %s\n",
303                            tldap_errstr(debug_ctx(), state->ld, rc)));
304                 return NT_STATUS_LDAP(rc);
305         }
306
307         count = talloc_array_length(users);
308         if (count != 1) {
309                 DEBUG(10, ("Expected 1 user, got %d\n", count));
310                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
311         }
312
313         return pdb_ads_init_sam_from_ads(m, sam_acct, users[0]);
314 }
315
316 static NTSTATUS pdb_ads_getsampwnam(struct pdb_methods *m,
317                                     struct samu *sam_acct,
318                                     const char *username)
319 {
320         struct pdb_ads_state *state = talloc_get_type_abort(
321                 m->private_data, struct pdb_ads_state);
322         char *filter;
323
324         filter = talloc_asprintf(
325                 talloc_tos(), "(&(samaccountname=%s)(objectclass=user))",
326                 username);
327         NT_STATUS_HAVE_NO_MEMORY(filter);
328
329         return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
330 }
331
332 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
333                                     struct samu *sam_acct,
334                                     const DOM_SID *sid)
335 {
336         struct pdb_ads_state *state = talloc_get_type_abort(
337                 m->private_data, struct pdb_ads_state);
338         char *sidstr, *filter;
339
340         sidstr = sid_binstring(talloc_tos(), sid);
341         NT_STATUS_HAVE_NO_MEMORY(sidstr);
342
343         filter = talloc_asprintf(
344                 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
345         TALLOC_FREE(sidstr);
346         NT_STATUS_HAVE_NO_MEMORY(filter);
347
348         return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
349 }
350
351 static NTSTATUS pdb_ads_create_user(struct pdb_methods *m,
352                                     TALLOC_CTX *tmp_ctx,
353                                     const char *name, uint32 acct_flags,
354                                     uint32 *rid)
355 {
356         struct pdb_ads_state *state = talloc_get_type_abort(
357                 m->private_data, struct pdb_ads_state);
358         const char *attrs[1] = { "objectSid" };
359         struct tldap_mod *mods = NULL;
360         int num_mods = 0;
361         struct tldap_message **user;
362         struct dom_sid sid;
363         char *dn;
364         int rc;
365         bool ok;
366
367         dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
368                              state->domaindn);
369         if (dn == NULL) {
370                 return NT_STATUS_NO_MEMORY;
371         }
372
373         /* TODO: Create machines etc */
374
375         ok = true;
376         ok &= tldap_make_mod_fmt(
377                 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "user");
378         ok &= tldap_make_mod_fmt(
379                 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
380                 name);
381         if (!ok) {
382                 return NT_STATUS_NO_MEMORY;
383         }
384
385         rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL);
386         if (rc != TLDAP_SUCCESS) {
387                 DEBUG(10, ("ldap_add failed %s\n",
388                            tldap_errstr(debug_ctx(), state->ld, rc)));
389                 TALLOC_FREE(dn);
390                 return NT_STATUS_LDAP(rc);
391         }
392
393         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
394                               attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &user,
395                              "(&(objectclass=user)(samaccountname=%s))",
396                              name);
397         if (rc != TLDAP_SUCCESS) {
398                 DEBUG(10, ("Could not find just created user %s: %s\n",
399                            name, tldap_errstr(debug_ctx(), state->ld, rc)));
400                 TALLOC_FREE(dn);
401                 return NT_STATUS_LDAP(rc);
402         }
403
404         if (talloc_array_length(user) != 1) {
405                 DEBUG(10, ("Got %d users, expected one\n",
406                            (int)talloc_array_length(user)));
407                 TALLOC_FREE(dn);
408                 return NT_STATUS_LDAP(rc);
409         }
410
411         if (!tldap_pull_binsid(user[0], "objectSid", &sid)) {
412                 DEBUG(10, ("Could not fetch objectSid from user %s\n",
413                            name));
414                 TALLOC_FREE(dn);
415                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
416         }
417
418         sid_peek_rid(&sid, rid);
419         TALLOC_FREE(dn);
420         return NT_STATUS_OK;
421 }
422
423 static NTSTATUS pdb_ads_delete_user(struct pdb_methods *m,
424                                     TALLOC_CTX *tmp_ctx,
425                                     struct samu *sam)
426 {
427         struct pdb_ads_state *state = talloc_get_type_abort(
428                 m->private_data, struct pdb_ads_state);
429         struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam);
430         int rc;
431
432         rc = tldap_delete(state->ld, priv->dn, NULL, NULL);
433         if (rc != TLDAP_SUCCESS) {
434                 DEBUG(10, ("ldap_delete for %s failed: %s\n", priv->dn,
435                            tldap_errstr(debug_ctx(), state->ld, rc)));
436                 return NT_STATUS_LDAP(rc);
437         }
438         return NT_STATUS_OK;
439 }
440
441 static NTSTATUS pdb_ads_add_sam_account(struct pdb_methods *m,
442                                         struct samu *sampass)
443 {
444         return NT_STATUS_NOT_IMPLEMENTED;
445 }
446
447 static NTSTATUS pdb_ads_update_sam_account(struct pdb_methods *m,
448                                            struct samu *sam)
449 {
450         struct pdb_ads_state *state = talloc_get_type_abort(
451                 m->private_data, struct pdb_ads_state);
452         struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam);
453         struct tldap_mod *mods = NULL;
454         int rc, num_mods = 0;
455
456         if (!pdb_ads_init_ads_from_sam(state, priv->ldapmsg, talloc_tos(),
457                                        &num_mods, &mods, sam)) {
458                 return NT_STATUS_NO_MEMORY;
459         }
460
461         rc = tldap_modify(state->ld, priv->dn, num_mods, mods, NULL, NULL);
462         if (rc != TLDAP_SUCCESS) {
463                 DEBUG(10, ("ldap_modify for %s failed: %s\n", priv->dn,
464                            tldap_errstr(debug_ctx(), state->ld, rc)));
465                 return NT_STATUS_LDAP(rc);
466         }
467
468         TALLOC_FREE(mods);
469
470         return NT_STATUS_OK;
471 }
472
473 static NTSTATUS pdb_ads_delete_sam_account(struct pdb_methods *m,
474                                            struct samu *username)
475 {
476         return NT_STATUS_NOT_IMPLEMENTED;
477 }
478
479 static NTSTATUS pdb_ads_rename_sam_account(struct pdb_methods *m,
480                                            struct samu *oldname,
481                                            const char *newname)
482 {
483         return NT_STATUS_NOT_IMPLEMENTED;
484 }
485
486 static NTSTATUS pdb_ads_update_login_attempts(struct pdb_methods *m,
487                                               struct samu *sam_acct,
488                                               bool success)
489 {
490         return NT_STATUS_NOT_IMPLEMENTED;
491 }
492
493 static NTSTATUS pdb_ads_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
494                                     const char *filter)
495 {
496         struct pdb_ads_state *state = talloc_get_type_abort(
497                 m->private_data, struct pdb_ads_state);
498         const char *attrs[4] = { "objectSid", "description", "samAccountName",
499                                  "groupType" };
500         char *str;
501         struct tldap_message **group;
502         uint32_t grouptype;
503         int rc;
504
505         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
506                               attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
507                               &group, "%s", filter);
508         if (rc != TLDAP_SUCCESS) {
509                 DEBUG(10, ("ldap_search failed %s\n",
510                            tldap_errstr(debug_ctx(), state->ld, rc)));
511                 return NT_STATUS_LDAP(rc);
512         }
513         if (talloc_array_length(group) != 1) {
514                 DEBUG(10, ("Expected 1 user, got %d\n",
515                            talloc_array_length(group)));
516                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
517         }
518
519         if (!tldap_pull_binsid(group[0], "objectSid", &map->sid)) {
520                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
521         }
522         map->gid = pdb_ads_sid2gid(&map->sid);
523
524         if (!tldap_pull_uint32(group[0], "groupType", &grouptype)) {
525                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
526         }
527         switch (grouptype) {
528         case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
529         case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
530                 map->sid_name_use = SID_NAME_ALIAS;
531                 break;
532         case GTYPE_SECURITY_GLOBAL_GROUP:
533                 map->sid_name_use = SID_NAME_DOM_GRP;
534                 break;
535         default:
536                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
537         }
538
539         str = tldap_talloc_single_attribute(group[0], "samAccountName",
540                                             talloc_tos());
541         if (str == NULL) {
542                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
543         }
544         fstrcpy(map->nt_name, str);
545         TALLOC_FREE(str);
546
547         str = tldap_talloc_single_attribute(group[0], "description",
548                                             talloc_tos());
549         if (str != NULL) {
550                 fstrcpy(map->comment, str);
551                 TALLOC_FREE(str);
552         } else {
553                 map->comment[0] = '\0';
554         }
555
556         TALLOC_FREE(group);
557         return NT_STATUS_OK;
558 }
559
560 static NTSTATUS pdb_ads_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
561                                  DOM_SID sid)
562 {
563         char *filter;
564         NTSTATUS status;
565
566         filter = talloc_asprintf(talloc_tos(),
567                                  "(&(objectsid=%s)(objectclass=group))",
568                                  sid_string_talloc(talloc_tos(), &sid));
569         if (filter == NULL) {
570                 return NT_STATUS_NO_MEMORY;
571         }
572
573         status = pdb_ads_getgrfilter(m, map, filter);
574         TALLOC_FREE(filter);
575         return status;
576 }
577
578 static NTSTATUS pdb_ads_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
579                                  gid_t gid)
580 {
581         struct dom_sid sid;
582         pdb_ads_gid_to_sid(m, gid, &sid);
583         return pdb_ads_getgrsid(m, map, sid);
584 }
585
586 static NTSTATUS pdb_ads_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
587                                  const char *name)
588 {
589         char *filter;
590         NTSTATUS status;
591
592         filter = talloc_asprintf(talloc_tos(),
593                                  "(&(samaccountname=%s)(objectclass=group))",
594                                  name);
595         if (filter == NULL) {
596                 return NT_STATUS_NO_MEMORY;
597         }
598
599         status = pdb_ads_getgrfilter(m, map, filter);
600         TALLOC_FREE(filter);
601         return status;
602 }
603
604 static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m,
605                                          TALLOC_CTX *mem_ctx, const char *name,
606                                          uint32 *rid)
607 {
608         TALLOC_CTX *frame = talloc_stackframe();
609         struct pdb_ads_state *state = talloc_get_type_abort(
610                 m->private_data, struct pdb_ads_state);
611         const char *attrs[1] = { "objectSid" };
612         int num_mods = 0;
613         struct tldap_mod *mods = NULL;
614         struct tldap_message **alias;
615         struct dom_sid sid;
616         char *dn;
617         int rc;
618         bool ok = true;
619
620         dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
621                              state->domaindn);
622         if (dn == NULL) {
623                 TALLOC_FREE(frame);
624                 return NT_STATUS_NO_MEMORY;
625         }
626
627         ok &= tldap_make_mod_fmt(
628                 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
629                 name);
630         ok &= tldap_make_mod_fmt(
631                 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "group");
632         ok &= tldap_make_mod_fmt(
633                 NULL, talloc_tos(), &num_mods, &mods, "groupType",
634                 "%d", (int)GTYPE_SECURITY_GLOBAL_GROUP);
635
636         if (!ok) {
637                 TALLOC_FREE(frame);
638                 return NT_STATUS_NO_MEMORY;
639         }
640
641         rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL);
642         if (rc != TLDAP_SUCCESS) {
643                 DEBUG(10, ("ldap_add failed %s\n",
644                            tldap_errstr(debug_ctx(), state->ld, rc)));
645                 TALLOC_FREE(frame);
646                 return NT_STATUS_LDAP(rc);
647         }
648
649         rc = tldap_search_fmt(
650                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
651                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
652                 "(&(objectclass=group)(samaccountname=%s))", name);
653         if (rc != TLDAP_SUCCESS) {
654                 DEBUG(10, ("Could not find just created alias %s: %s\n",
655                            name, tldap_errstr(debug_ctx(), state->ld, rc)));
656                 TALLOC_FREE(frame);
657                 return NT_STATUS_LDAP(rc);
658         }
659
660         if (talloc_array_length(alias) != 1) {
661                 DEBUG(10, ("Got %d alias, expected one\n",
662                            (int)talloc_array_length(alias)));
663                 TALLOC_FREE(frame);
664                 return NT_STATUS_LDAP(rc);
665         }
666
667         if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
668                 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
669                            name));
670                 TALLOC_FREE(frame);
671                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
672         }
673
674         sid_peek_rid(&sid, rid);
675         TALLOC_FREE(frame);
676         return NT_STATUS_OK;
677 }
678
679 static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m,
680                                          TALLOC_CTX *mem_ctx, uint32 rid)
681 {
682         return NT_STATUS_NOT_IMPLEMENTED;
683 }
684
685 static NTSTATUS pdb_ads_add_group_mapping_entry(struct pdb_methods *m,
686                                                 GROUP_MAP *map)
687 {
688         return NT_STATUS_NOT_IMPLEMENTED;
689 }
690
691 static NTSTATUS pdb_ads_update_group_mapping_entry(struct pdb_methods *m,
692                                                    GROUP_MAP *map)
693 {
694         return NT_STATUS_NOT_IMPLEMENTED;
695 }
696
697 static NTSTATUS pdb_ads_delete_group_mapping_entry(struct pdb_methods *m,
698                                                    DOM_SID sid)
699 {
700         return NT_STATUS_NOT_IMPLEMENTED;
701 }
702
703 static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m,
704                                            const DOM_SID *sid,
705                                            enum lsa_SidType sid_name_use,
706                                            GROUP_MAP **pp_rmap,
707                                            size_t *p_num_entries,
708                                            bool unix_only)
709 {
710         return NT_STATUS_NOT_IMPLEMENTED;
711 }
712
713 static NTSTATUS pdb_ads_enum_group_members(struct pdb_methods *m,
714                                            TALLOC_CTX *mem_ctx,
715                                            const DOM_SID *group,
716                                            uint32 **pp_member_rids,
717                                            size_t *p_num_members)
718 {
719         return NT_STATUS_NOT_IMPLEMENTED;
720 }
721
722 static NTSTATUS pdb_ads_enum_group_memberships(struct pdb_methods *m,
723                                                TALLOC_CTX *mem_ctx,
724                                                struct samu *user,
725                                                DOM_SID **pp_sids,
726                                                gid_t **pp_gids,
727                                                size_t *p_num_groups)
728 {
729         struct pdb_ads_state *state = talloc_get_type_abort(
730                 m->private_data, struct pdb_ads_state);
731         struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(
732                 m, user);
733         const char *attrs[1] = { "objectSid" };
734         struct tldap_message **groups;
735         int i, rc, count;
736         size_t num_groups;
737         struct dom_sid *group_sids;
738         gid_t *gids;
739
740         rc = tldap_search_fmt(
741                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
742                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &groups,
743                 "(&(member=%s)(grouptype=%d)(objectclass=group))",
744                 priv->dn, GTYPE_SECURITY_GLOBAL_GROUP);
745         if (rc != TLDAP_SUCCESS) {
746                 DEBUG(10, ("ldap_search failed %s\n",
747                            tldap_errstr(debug_ctx(), state->ld, rc)));
748                 return NT_STATUS_LDAP(rc);
749         }
750
751         count = talloc_array_length(groups);
752
753         group_sids = talloc_array(mem_ctx, struct dom_sid, count);
754         if (group_sids == NULL) {
755                 return NT_STATUS_NO_MEMORY;
756         }
757         gids = talloc_array(mem_ctx, gid_t, count);
758         if (gids == NULL) {
759                 TALLOC_FREE(group_sids);
760                 return NT_STATUS_NO_MEMORY;
761         }
762         num_groups = 0;
763
764         for (i=0; i<count; i++) {
765                 if (!tldap_pull_binsid(groups[i], "objectSid",
766                                        &group_sids[num_groups])) {
767                         continue;
768                 }
769                 gids[num_groups] = pdb_ads_sid2gid(&group_sids[num_groups]);
770
771                 num_groups += 1;
772                 if (num_groups == count) {
773                         break;
774                 }
775         }
776
777         *pp_sids = group_sids;
778         *pp_gids = gids;
779         *p_num_groups = num_groups;
780         return NT_STATUS_OK;
781 }
782
783 static NTSTATUS pdb_ads_set_unix_primary_group(struct pdb_methods *m,
784                                                TALLOC_CTX *mem_ctx,
785                                                struct samu *user)
786 {
787         return NT_STATUS_NOT_IMPLEMENTED;
788 }
789
790 static NTSTATUS pdb_ads_add_groupmem(struct pdb_methods *m,
791                                      TALLOC_CTX *mem_ctx,
792                                      uint32 group_rid, uint32 member_rid)
793 {
794         return NT_STATUS_NOT_IMPLEMENTED;
795 }
796
797 static NTSTATUS pdb_ads_del_groupmem(struct pdb_methods *m,
798                                      TALLOC_CTX *mem_ctx,
799                                      uint32 group_rid, uint32 member_rid)
800 {
801         return NT_STATUS_NOT_IMPLEMENTED;
802 }
803
804 static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m,
805                                      const char *name, uint32 *rid)
806 {
807         TALLOC_CTX *frame = talloc_stackframe();
808         struct pdb_ads_state *state = talloc_get_type_abort(
809                 m->private_data, struct pdb_ads_state);
810         const char *attrs[1] = { "objectSid" };
811         int num_mods = 0;
812         struct tldap_mod *mods = NULL;
813         struct tldap_message **alias;
814         struct dom_sid sid;
815         char *dn;
816         int rc;
817         bool ok = true;
818
819         dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
820                              state->domaindn);
821         if (dn == NULL) {
822                 TALLOC_FREE(frame);
823                 return NT_STATUS_NO_MEMORY;
824         }
825
826         ok &= tldap_make_mod_fmt(
827                 NULL, talloc_tos(), &num_mods, &mods, "samAccountName", "%s",
828                 name);
829         ok &= tldap_make_mod_fmt(
830                 NULL, talloc_tos(), &num_mods, &mods, "objectClass", "group");
831         ok &= tldap_make_mod_fmt(
832                 NULL, talloc_tos(), &num_mods, &mods, "groupType",
833                 "%d", (int)GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
834
835         if (!ok) {
836                 TALLOC_FREE(frame);
837                 return NT_STATUS_NO_MEMORY;
838         }
839
840         rc = tldap_add(state->ld, dn, num_mods, mods, NULL, NULL);
841         if (rc != TLDAP_SUCCESS) {
842                 DEBUG(10, ("ldap_add failed %s\n",
843                            tldap_errstr(debug_ctx(), state->ld, rc)));
844                 TALLOC_FREE(frame);
845                 return NT_STATUS_LDAP(rc);
846         }
847
848         rc = tldap_search_fmt(
849                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
850                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
851                 "(&(objectclass=group)(samaccountname=%s))", name);
852         if (rc != TLDAP_SUCCESS) {
853                 DEBUG(10, ("Could not find just created alias %s: %s\n",
854                            name, tldap_errstr(debug_ctx(), state->ld, rc)));
855                 TALLOC_FREE(frame);
856                 return NT_STATUS_LDAP(rc);
857         }
858
859         if (talloc_array_length(alias) != 1) {
860                 DEBUG(10, ("Got %d alias, expected one\n",
861                            (int)talloc_array_length(alias)));
862                 TALLOC_FREE(frame);
863                 return NT_STATUS_LDAP(rc);
864         }
865
866         if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
867                 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
868                            name));
869                 TALLOC_FREE(frame);
870                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
871         }
872
873         sid_peek_rid(&sid, rid);
874         TALLOC_FREE(frame);
875         return NT_STATUS_OK;
876 }
877
878 static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m,
879                                      const DOM_SID *sid)
880 {
881         return NT_STATUS_NOT_IMPLEMENTED;
882 }
883
884 static NTSTATUS pdb_ads_get_aliasinfo(struct pdb_methods *m,
885                                       const DOM_SID *sid,
886                                       struct acct_info *info)
887 {
888         return NT_STATUS_NOT_IMPLEMENTED;
889 }
890
891 static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m,
892                                       const DOM_SID *sid,
893                                       struct acct_info *info)
894 {
895         return NT_STATUS_NOT_IMPLEMENTED;
896 }
897
898 static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
899                                      const DOM_SID *alias,
900                                      const DOM_SID *member)
901 {
902         return NT_STATUS_NOT_IMPLEMENTED;
903 }
904
905 static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
906                                      const DOM_SID *alias,
907                                      const DOM_SID *member)
908 {
909         return NT_STATUS_NOT_IMPLEMENTED;
910 }
911
912 static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
913                                       const DOM_SID *alias, DOM_SID **members,
914                                       size_t *p_num_members)
915 {
916         return NT_STATUS_NOT_IMPLEMENTED;
917 }
918
919 static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,
920                                                TALLOC_CTX *mem_ctx,
921                                                const DOM_SID *domain_sid,
922                                                const DOM_SID *members,
923                                                size_t num_members,
924                                                uint32 **pp_alias_rids,
925                                                size_t *p_num_alias_rids)
926 {
927         return NT_STATUS_NOT_IMPLEMENTED;
928 }
929
930 static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m,
931                                     const DOM_SID *domain_sid,
932                                     int num_rids,
933                                     uint32 *rids,
934                                     const char **pp_names,
935                                     enum lsa_SidType *attrs)
936 {
937         return NT_STATUS_NOT_IMPLEMENTED;
938 }
939
940 static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m,
941                                      const DOM_SID *domain_sid,
942                                      int num_names,
943                                      const char **pp_names,
944                                      uint32 *rids,
945                                      enum lsa_SidType *attrs)
946 {
947         return NT_STATUS_NOT_IMPLEMENTED;
948 }
949
950 static NTSTATUS pdb_ads_get_account_policy(struct pdb_methods *m,
951                                            int policy_index, uint32 *value)
952 {
953         return account_policy_get(policy_index, value)
954                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
955 }
956
957 static NTSTATUS pdb_ads_set_account_policy(struct pdb_methods *m,
958                                            int policy_index, uint32 value)
959 {
960         return account_policy_set(policy_index, value)
961                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
962 }
963
964 static NTSTATUS pdb_ads_get_seq_num(struct pdb_methods *m,
965                                     time_t *seq_num)
966 {
967         return NT_STATUS_NOT_IMPLEMENTED;
968 }
969
970 struct pdb_ads_search_state {
971         uint32_t acct_flags;
972         struct samr_displayentry *entries;
973         uint32_t num_entries;
974         ssize_t array_size;
975         uint32_t current;
976 };
977
978 static bool pdb_ads_next_entry(struct pdb_search *search,
979                                struct samr_displayentry *entry)
980 {
981         struct pdb_ads_search_state *state = talloc_get_type_abort(
982                 search->private_data, struct pdb_ads_search_state);
983
984         if (state->current == state->num_entries) {
985                 return false;
986         }
987
988         entry->idx = state->entries[state->current].idx;
989         entry->rid = state->entries[state->current].rid;
990         entry->acct_flags = state->entries[state->current].acct_flags;
991
992         entry->account_name = talloc_strdup(
993                 search, state->entries[state->current].account_name);
994         entry->fullname = talloc_strdup(
995                 search, state->entries[state->current].fullname);
996         entry->description = talloc_strdup(
997                 search, state->entries[state->current].description);
998
999         if ((entry->account_name == NULL) || (entry->fullname == NULL)
1000             || (entry->description == NULL)) {
1001                 DEBUG(0, ("talloc_strdup failed\n"));
1002                 return false;
1003         }
1004
1005         state->current += 1;
1006         return true;
1007 }
1008
1009 static void pdb_ads_search_end(struct pdb_search *search)
1010 {
1011         struct pdb_ads_search_state *state = talloc_get_type_abort(
1012                 search->private_data, struct pdb_ads_search_state);
1013         TALLOC_FREE(state);
1014 }
1015
1016 static bool pdb_ads_search_filter(struct pdb_methods *m,
1017                                   struct pdb_search *search,
1018                                   const char *filter,
1019                                   struct pdb_ads_search_state **pstate)
1020 {
1021         struct pdb_ads_state *state = talloc_get_type_abort(
1022                 m->private_data, struct pdb_ads_state);
1023         struct pdb_ads_search_state *sstate;
1024         const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1025                                  "userAccountControl", "description" };
1026         struct tldap_message **users;
1027         int i, rc, num_users;
1028
1029         sstate = talloc_zero(search, struct pdb_ads_search_state);
1030         if (sstate == NULL) {
1031                 return false;
1032         }
1033
1034         rc = tldap_search_fmt(
1035                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1036                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &users,
1037                 "%s", filter);
1038         if (rc != TLDAP_SUCCESS) {
1039                 DEBUG(10, ("ldap_search_ext_s failed: %s\n",
1040                            tldap_errstr(debug_ctx(), state->ld, rc)));
1041                 return false;
1042         }
1043
1044         num_users = talloc_array_length(users);
1045
1046         sstate->entries = talloc_array(sstate, struct samr_displayentry,
1047                                        num_users);
1048         if (sstate->entries == NULL) {
1049                 DEBUG(10, ("talloc failed\n"));
1050                 return false;
1051         }
1052
1053         sstate->num_entries = 0;
1054
1055         for (i=0; i<num_users; i++) {
1056                 struct samr_displayentry *e;
1057                 struct dom_sid sid;
1058
1059                 e = &sstate->entries[sstate->num_entries];
1060
1061                 e->idx = sstate->num_entries;
1062                 if (!tldap_pull_binsid(users[i], "objectSid", &sid)) {
1063                         DEBUG(10, ("Could not pull sid\n"));
1064                         continue;
1065                 }
1066                 sid_peek_rid(&sid, &e->rid);
1067                 e->acct_flags = ACB_NORMAL;
1068                 e->account_name = tldap_talloc_single_attribute(
1069                         users[i], "samAccountName", sstate->entries);
1070                 if (e->account_name == NULL) {
1071                         return false;
1072                 }
1073                 e->fullname = tldap_talloc_single_attribute(
1074                         users[i], "displayName", sstate->entries);
1075                 if (e->fullname == NULL) {
1076                         e->fullname = "";
1077                 }
1078                 e->description = tldap_talloc_single_attribute(
1079                         users[i], "description", sstate->entries);
1080                 if (e->description == NULL) {
1081                         e->description = "";
1082                 }
1083
1084                 sstate->num_entries += 1;
1085                 if (sstate->num_entries >= num_users) {
1086                         break;
1087                 }
1088         }
1089
1090         search->private_data = sstate;
1091         search->next_entry = pdb_ads_next_entry;
1092         search->search_end = pdb_ads_search_end;
1093         *pstate = sstate;
1094         return true;
1095 }
1096
1097 static bool pdb_ads_search_users(struct pdb_methods *m,
1098                                  struct pdb_search *search,
1099                                  uint32 acct_flags)
1100 {
1101         struct pdb_ads_search_state *sstate;
1102         bool ret;
1103
1104         ret = pdb_ads_search_filter(m, search, "(objectclass=user)", &sstate);
1105         if (!ret) {
1106                 return false;
1107         }
1108         sstate->acct_flags = acct_flags;
1109         return true;
1110 }
1111
1112 static bool pdb_ads_search_groups(struct pdb_methods *m,
1113                                   struct pdb_search *search)
1114 {
1115         struct pdb_ads_search_state *sstate;
1116         char *filter;
1117         bool ret;
1118
1119         filter = talloc_asprintf(talloc_tos(),
1120                                  "(&(grouptype=%d)(objectclass=group))",
1121                                  GTYPE_SECURITY_GLOBAL_GROUP);
1122         if (filter == NULL) {
1123                 return false;
1124         }
1125         ret = pdb_ads_search_filter(m, search, filter, &sstate);
1126         TALLOC_FREE(filter);
1127         if (!ret) {
1128                 return false;
1129         }
1130         sstate->acct_flags = 0;
1131         return true;
1132 }
1133
1134 static bool pdb_ads_search_aliases(struct pdb_methods *m,
1135                                    struct pdb_search *search,
1136                                    const DOM_SID *sid)
1137 {
1138         struct pdb_ads_search_state *sstate;
1139         char *filter;
1140         bool ret;
1141
1142         filter = talloc_asprintf(
1143                 talloc_tos(), "(&(grouptype=%d)(objectclass=group))",
1144                 sid_check_is_builtin(sid)
1145                 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
1146                 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1147
1148         if (filter == NULL) {
1149                 return false;
1150         }
1151         ret = pdb_ads_search_filter(m, search, filter, &sstate);
1152         TALLOC_FREE(filter);
1153         if (!ret) {
1154                 return false;
1155         }
1156         sstate->acct_flags = 0;
1157         return true;
1158 }
1159
1160 static bool pdb_ads_uid_to_rid(struct pdb_methods *m, uid_t uid,
1161                                uint32 *rid)
1162 {
1163         return false;
1164 }
1165
1166 static bool pdb_ads_uid_to_sid(struct pdb_methods *m, uid_t uid,
1167                                DOM_SID *sid)
1168 {
1169         struct pdb_ads_state *state = talloc_get_type_abort(
1170                 m->private_data, struct pdb_ads_state);
1171         sid_compose(sid, &state->domainsid, uid);
1172         return true;
1173 }
1174
1175 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
1176                                DOM_SID *sid)
1177 {
1178         struct pdb_ads_state *state = talloc_get_type_abort(
1179                 m->private_data, struct pdb_ads_state);
1180         sid_compose(sid, &state->domainsid, gid);
1181         return true;
1182 }
1183
1184 static bool pdb_ads_sid_to_id(struct pdb_methods *m, const DOM_SID *sid,
1185                               union unid_t *id, enum lsa_SidType *type)
1186 {
1187         struct pdb_ads_state *state = talloc_get_type_abort(
1188                 m->private_data, struct pdb_ads_state);
1189         struct tldap_message **msg;
1190         char *sidstr;
1191         uint32_t rid;
1192         int rc;
1193
1194         /*
1195          * This is a big, big hack: Just hard-code the rid as uid/gid.
1196          */
1197
1198         sid_peek_rid(sid, &rid);
1199
1200         sidstr = sid_binstring(talloc_tos(), sid);
1201         if (sidstr == NULL) {
1202                 return false;
1203         }
1204
1205         rc = tldap_search_fmt(
1206                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1207                 NULL, 0, 0, talloc_tos(), &msg,
1208                 "(&(objectsid=%s)(objectclass=user))", sidstr);
1209         if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
1210                 id->uid = rid;
1211                 *type = SID_NAME_USER;
1212                 TALLOC_FREE(sidstr);
1213                 return true;
1214         }
1215
1216         rc = tldap_search_fmt(
1217                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1218                 NULL, 0, 0, talloc_tos(), &msg,
1219                 "(&(objectsid=%s)(objectclass=group))", sidstr);
1220         if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
1221                 id->gid = rid;
1222                 *type = SID_NAME_DOM_GRP;
1223                 TALLOC_FREE(sidstr);
1224                 return true;
1225         }
1226
1227         TALLOC_FREE(sidstr);
1228         return false;
1229 }
1230
1231 static bool pdb_ads_rid_algorithm(struct pdb_methods *m)
1232 {
1233         return false;
1234 }
1235
1236 static bool pdb_ads_new_rid(struct pdb_methods *m, uint32 *rid)
1237 {
1238         return false;
1239 }
1240
1241 static bool pdb_ads_get_trusteddom_pw(struct pdb_methods *m,
1242                                       const char *domain, char** pwd,
1243                                       DOM_SID *sid,
1244                                       time_t *pass_last_set_time)
1245 {
1246         return false;
1247 }
1248
1249 static bool pdb_ads_set_trusteddom_pw(struct pdb_methods *m,
1250                                       const char* domain, const char* pwd,
1251                                       const DOM_SID *sid)
1252 {
1253         return false;
1254 }
1255
1256 static bool pdb_ads_del_trusteddom_pw(struct pdb_methods *m,
1257                                       const char *domain)
1258 {
1259         return false;
1260 }
1261
1262 static NTSTATUS pdb_ads_enum_trusteddoms(struct pdb_methods *m,
1263                                          TALLOC_CTX *mem_ctx,
1264                                          uint32 *num_domains,
1265                                          struct trustdom_info ***domains)
1266 {
1267         return NT_STATUS_NOT_IMPLEMENTED;
1268 }
1269
1270 static void pdb_ads_init_methods(struct pdb_methods *m)
1271 {
1272         m->name = "ads";
1273         m->getsampwnam = pdb_ads_getsampwnam;
1274         m->getsampwsid = pdb_ads_getsampwsid;
1275         m->create_user = pdb_ads_create_user;
1276         m->delete_user = pdb_ads_delete_user;
1277         m->add_sam_account = pdb_ads_add_sam_account;
1278         m->update_sam_account = pdb_ads_update_sam_account;
1279         m->delete_sam_account = pdb_ads_delete_sam_account;
1280         m->rename_sam_account = pdb_ads_rename_sam_account;
1281         m->update_login_attempts = pdb_ads_update_login_attempts;
1282         m->getgrsid = pdb_ads_getgrsid;
1283         m->getgrgid = pdb_ads_getgrgid;
1284         m->getgrnam = pdb_ads_getgrnam;
1285         m->create_dom_group = pdb_ads_create_dom_group;
1286         m->delete_dom_group = pdb_ads_delete_dom_group;
1287         m->add_group_mapping_entry = pdb_ads_add_group_mapping_entry;
1288         m->update_group_mapping_entry = pdb_ads_update_group_mapping_entry;
1289         m->delete_group_mapping_entry = pdb_ads_delete_group_mapping_entry;
1290         m->enum_group_mapping = pdb_ads_enum_group_mapping;
1291         m->enum_group_members = pdb_ads_enum_group_members;
1292         m->enum_group_memberships = pdb_ads_enum_group_memberships;
1293         m->set_unix_primary_group = pdb_ads_set_unix_primary_group;
1294         m->add_groupmem = pdb_ads_add_groupmem;
1295         m->del_groupmem = pdb_ads_del_groupmem;
1296         m->create_alias = pdb_ads_create_alias;
1297         m->delete_alias = pdb_ads_delete_alias;
1298         m->get_aliasinfo = pdb_ads_get_aliasinfo;
1299         m->set_aliasinfo = pdb_ads_set_aliasinfo;
1300         m->add_aliasmem = pdb_ads_add_aliasmem;
1301         m->del_aliasmem = pdb_ads_del_aliasmem;
1302         m->enum_aliasmem = pdb_ads_enum_aliasmem;
1303         m->enum_alias_memberships = pdb_ads_enum_alias_memberships;
1304         m->lookup_rids = pdb_ads_lookup_rids;
1305         m->lookup_names = pdb_ads_lookup_names;
1306         m->get_account_policy = pdb_ads_get_account_policy;
1307         m->set_account_policy = pdb_ads_set_account_policy;
1308         m->get_seq_num = pdb_ads_get_seq_num;
1309         m->search_users = pdb_ads_search_users;
1310         m->search_groups = pdb_ads_search_groups;
1311         m->search_aliases = pdb_ads_search_aliases;
1312         m->uid_to_rid = pdb_ads_uid_to_rid;
1313         m->uid_to_sid = pdb_ads_uid_to_sid;
1314         m->gid_to_sid = pdb_ads_gid_to_sid;
1315         m->sid_to_id = pdb_ads_sid_to_id;
1316         m->rid_algorithm = pdb_ads_rid_algorithm;
1317         m->new_rid = pdb_ads_new_rid;
1318         m->get_trusteddom_pw = pdb_ads_get_trusteddom_pw;
1319         m->set_trusteddom_pw = pdb_ads_set_trusteddom_pw;
1320         m->del_trusteddom_pw = pdb_ads_del_trusteddom_pw;
1321         m->enum_trusteddoms = pdb_ads_enum_trusteddoms;
1322 }
1323
1324 static void free_private_data(void **vp)
1325 {
1326         struct pdb_ads_state *state = talloc_get_type_abort(
1327                 *vp, struct pdb_ads_state);
1328
1329         TALLOC_FREE(state->ld);
1330         return;
1331 }
1332
1333 static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state,
1334                                 const char *location)
1335 {
1336         const char *rootdse_attrs[2] = {
1337                 "defaultNamingContext", "configurationNamingContext" };
1338         const char *domain_attrs[1] = { "objectSid" };
1339         const char *ncname_attrs[1] = { "netbiosname" };
1340         struct tldap_message **rootdse, **domain, **ncname;
1341         TALLOC_CTX *frame = talloc_stackframe();
1342         struct sockaddr_un sunaddr;
1343         NTSTATUS status;
1344         int num_domains;
1345         int fd, rc;
1346
1347         ZERO_STRUCT(sunaddr);
1348         sunaddr.sun_family = AF_UNIX;
1349         strncpy(sunaddr.sun_path, location, sizeof(sunaddr.sun_path) - 1);
1350
1351         status = open_socket_out((struct sockaddr_storage *)(void *)&sunaddr,
1352                                  0, 0, &fd);
1353         if (!NT_STATUS_IS_OK(status)) {
1354                 DEBUG(10, ("Could not connect to %s: %s\n", location,
1355                            nt_errstr(status)));
1356                 goto done;
1357         }
1358
1359         state->ld = tldap_context_create(state, fd);
1360         if (state->ld == NULL) {
1361                 close(fd);
1362                 status = NT_STATUS_NO_MEMORY;
1363                 goto done;
1364         }
1365
1366         rc = tldap_search_fmt(
1367                 state->ld, "", TLDAP_SCOPE_BASE,
1368                 rootdse_attrs, ARRAY_SIZE(rootdse_attrs), 0,
1369                 talloc_tos(), &rootdse, "(objectclass=*)");
1370         if (rc != TLDAP_SUCCESS) {
1371                 DEBUG(10, ("Could not retrieve rootdse: %s\n",
1372                            tldap_errstr(debug_ctx(), state->ld, rc)));
1373                 status = NT_STATUS_LDAP(rc);
1374                 goto done;
1375         }
1376         if (talloc_array_length(rootdse) != 1) {
1377                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1378                 goto done;
1379         }
1380
1381         state->domaindn = tldap_talloc_single_attribute(
1382                 rootdse[0], "defaultNamingContext", state);
1383         if (state->domaindn == NULL) {
1384                 DEBUG(10, ("Could not get defaultNamingContext\n"));
1385                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1386                 goto done;
1387         }
1388         DEBUG(10, ("defaultNamingContext = %s\n", state->domaindn));
1389
1390         state->configdn = tldap_talloc_single_attribute(
1391                 rootdse[0], "configurationNamingContext", state);
1392         if (state->domaindn == NULL) {
1393                 DEBUG(10, ("Could not get configurationNamingContext\n"));
1394                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1395                 goto done;
1396         }
1397         DEBUG(10, ("configurationNamingContext = %s\n", state->configdn));
1398
1399         /*
1400          * Figure out our domain's SID
1401          */
1402         rc = tldap_search_fmt(
1403                 state->ld, state->domaindn, TLDAP_SCOPE_BASE,
1404                 domain_attrs, ARRAY_SIZE(domain_attrs), 0,
1405                 talloc_tos(), &domain, "(objectclass=*)");
1406         if (rc != TLDAP_SUCCESS) {
1407                 DEBUG(10, ("Could not retrieve domain: %s\n",
1408                            tldap_errstr(debug_ctx(), state->ld, rc)));
1409                 status = NT_STATUS_LDAP(rc);
1410                 goto done;
1411         }
1412
1413         num_domains = talloc_array_length(domain);
1414         if (num_domains != 1) {
1415                 DEBUG(10, ("Got %d domains, expected one\n", num_domains));
1416                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1417                 goto done;
1418         }
1419         if (!tldap_pull_binsid(domain[0], "objectSid", &state->domainsid)) {
1420                 DEBUG(10, ("Could not retrieve domain SID\n"));
1421                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1422                 goto done;
1423         }
1424         DEBUG(10, ("Domain SID: %s\n", sid_string_dbg(&state->domainsid)));
1425
1426         /*
1427          * Figure out our domain's short name
1428          */
1429         rc = tldap_search_fmt(
1430                 state->ld, state->configdn, TLDAP_SCOPE_SUB,
1431                 ncname_attrs, ARRAY_SIZE(ncname_attrs), 0,
1432                 talloc_tos(), &ncname, "(ncname=%s)", state->domaindn);
1433         if (rc != TLDAP_SUCCESS) {
1434                 DEBUG(10, ("Could not retrieve ncname: %s\n",
1435                            tldap_errstr(debug_ctx(), state->ld, rc)));
1436                 status = NT_STATUS_LDAP(rc);
1437                 goto done;
1438         }
1439         if (talloc_array_length(ncname) != 1) {
1440                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1441                 goto done;
1442         }
1443
1444         state->netbiosname = tldap_talloc_single_attribute(
1445                 ncname[0], "netbiosname", state);
1446         if (state->netbiosname == NULL) {
1447                 DEBUG(10, ("Could not get netbiosname\n"));
1448                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1449                 goto done;
1450         }
1451         DEBUG(10, ("netbiosname: %s\n", state->netbiosname));
1452
1453         if (!strequal(lp_workgroup(), state->netbiosname)) {
1454                 DEBUG(1, ("ADS is different domain (%s) than ours (%s)\n",
1455                           state->netbiosname, lp_workgroup()));
1456                 status = NT_STATUS_NO_SUCH_DOMAIN;
1457                 goto done;
1458         }
1459
1460         secrets_store_domain_sid(state->netbiosname, &state->domainsid);
1461
1462         status = NT_STATUS_OK;
1463 done:
1464         TALLOC_FREE(frame);
1465         return status;
1466 }
1467
1468 static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method,
1469                              const char *location)
1470 {
1471         struct pdb_methods *m;
1472         struct pdb_ads_state *state;
1473         char *tmp = NULL;
1474         NTSTATUS status;
1475
1476         m = talloc(talloc_autofree_context(), struct pdb_methods);
1477         if (m == NULL) {
1478                 return NT_STATUS_NO_MEMORY;
1479         }
1480         state = talloc(m, struct pdb_ads_state);
1481         if (state == NULL) {
1482                 goto nomem;
1483         }
1484         m->private_data = state;
1485         m->free_private_data = free_private_data;
1486         pdb_ads_init_methods(m);
1487
1488         if (location == NULL) {
1489                 tmp = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi",
1490                                       lp_private_dir());
1491                 location = tmp;
1492         }
1493         if (location == NULL) {
1494                 goto nomem;
1495         }
1496
1497         status = pdb_ads_connect(state, location);
1498         if (!NT_STATUS_IS_OK(status)) {
1499                 DEBUG(10, ("pdb_ads_connect failed: %s\n", nt_errstr(status)));
1500                 goto fail;
1501         }
1502
1503         *pdb_method = m;
1504         return NT_STATUS_OK;
1505 nomem:
1506         status = NT_STATUS_NO_MEMORY;
1507 fail:
1508         TALLOC_FREE(m);
1509         return status;
1510 }
1511
1512 NTSTATUS pdb_ads_init(void);
1513 NTSTATUS pdb_ads_init(void)
1514 {
1515         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "ads",
1516                                    pdb_init_ads);
1517 }