9471f1ae712b3aa9294cf1a3cbbecacdfb99174d
[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                 "%s", 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         struct pdb_ads_state *state = talloc_get_type_abort(
882                 m->private_data, struct pdb_ads_state);
883         struct tldap_message **alias;
884         char *sidstr, *dn;
885         int rc;
886
887         sidstr = sid_binstring(talloc_tos(), sid);
888         if (sidstr == NULL) {
889                 return NT_STATUS_NO_MEMORY;
890         }
891
892         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
893                               NULL, 0, 0, talloc_tos(), &alias,
894                               "(&(objectSid=%s)(objectclass=group)"
895                               "(|(grouptype=%d)(grouptype=%d)))",
896                               sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
897                               GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
898         TALLOC_FREE(sidstr);
899         if (rc != TLDAP_SUCCESS) {
900                 DEBUG(10, ("ldap_search failed: %s\n",
901                            tldap_errstr(debug_ctx(), state->ld, rc)));
902                 TALLOC_FREE(dn);
903                 return NT_STATUS_LDAP(rc);
904         }
905         if (talloc_array_length(alias) != 1) {
906                 DEBUG(10, ("Expected 1 alias, got %d\n",
907                            talloc_array_length(alias)));
908                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
909         }
910         if (!tldap_entry_dn(alias[0], &dn)) {
911                 DEBUG(10, ("Could not get DN for alias %s\n",
912                            sid_string_dbg(sid)));
913                 return NT_STATUS_INTERNAL_ERROR;
914         }
915
916         rc = tldap_delete(state->ld, dn, NULL, NULL);
917         if (rc != TLDAP_SUCCESS) {
918                 DEBUG(10, ("ldap_delete failed: %s\n",
919                            tldap_errstr(debug_ctx(), state->ld, rc)));
920                 TALLOC_FREE(dn);
921                 return NT_STATUS_LDAP(rc);
922         }
923
924         return NT_STATUS_OK;
925 }
926
927 static NTSTATUS pdb_ads_get_aliasinfo(struct pdb_methods *m,
928                                       const DOM_SID *sid,
929                                       struct acct_info *info)
930 {
931         return NT_STATUS_NOT_IMPLEMENTED;
932 }
933
934 static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m,
935                                       const DOM_SID *sid,
936                                       struct acct_info *info)
937 {
938         return NT_STATUS_NOT_IMPLEMENTED;
939 }
940
941 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
942                                const struct dom_sid *sid,
943                                TALLOC_CTX *mem_ctx, char **pdn)
944 {
945         struct tldap_message **msg;
946         char *sidstr, *dn;
947         int rc;
948
949         sidstr = sid_binstring(talloc_tos(), sid);
950         NT_STATUS_HAVE_NO_MEMORY(sidstr);
951
952         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
953                               NULL, 0, 0, talloc_tos(), &msg,
954                               "(objectsid=%s)", sidstr);
955         TALLOC_FREE(sidstr);
956         if (rc != TLDAP_SUCCESS) {
957                 DEBUG(10, ("ldap_search failed %s\n",
958                            tldap_errstr(debug_ctx(), state->ld, rc)));
959                 return NT_STATUS_LDAP(rc);
960         }
961
962         switch talloc_array_length(msg) {
963         case 0:
964                 return NT_STATUS_NOT_FOUND;
965         case 1:
966                 break;
967         default:
968                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
969         }
970
971         if (!tldap_entry_dn(msg[0], &dn)) {
972                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
973         }
974
975         dn = talloc_strdup(mem_ctx, dn);
976         if (dn == NULL) {
977                 return NT_STATUS_NO_MEMORY;
978         }
979         TALLOC_FREE(msg);
980
981         *pdn = dn;
982         return NT_STATUS_OK;
983 }
984
985 static NTSTATUS pdb_ads_mod_aliasmem(struct pdb_methods *m,
986                                      const DOM_SID *alias,
987                                      const DOM_SID *member,
988                                      int mod_op)
989 {
990         struct pdb_ads_state *state = talloc_get_type_abort(
991                 m->private_data, struct pdb_ads_state);
992         TALLOC_CTX *frame = talloc_stackframe();
993         struct tldap_mod *mods;
994         int rc;
995         char *aliasdn, *memberdn;
996         NTSTATUS status;
997
998         status = pdb_ads_sid2dn(state, alias, talloc_tos(), &aliasdn);
999         if (!NT_STATUS_IS_OK(status)) {
1000                 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1001                            sid_string_dbg(alias), nt_errstr(status)));
1002                 TALLOC_FREE(frame);
1003                 return NT_STATUS_NO_SUCH_ALIAS;
1004         }
1005         status = pdb_ads_sid2dn(state, member, talloc_tos(), &memberdn);
1006         if (!NT_STATUS_IS_OK(status)) {
1007                 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1008                            sid_string_dbg(member), nt_errstr(status)));
1009                 TALLOC_FREE(frame);
1010                 return status;
1011         }
1012
1013         mods = NULL;
1014
1015         if (!tldap_add_mod_str(talloc_tos(), &mods, mod_op,
1016                                "member", memberdn)) {
1017                 TALLOC_FREE(frame);
1018                 return NT_STATUS_NO_MEMORY;
1019         }
1020
1021         rc = tldap_modify(state->ld, aliasdn, 1, mods, NULL, NULL);
1022         TALLOC_FREE(frame);
1023         if (rc != TLDAP_SUCCESS) {
1024                 DEBUG(10, ("ldap_modify failed: %s\n",
1025                            tldap_errstr(debug_ctx(), state->ld, rc)));
1026                 if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) {
1027                         return NT_STATUS_MEMBER_IN_ALIAS;
1028                 }
1029                 if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
1030                         return NT_STATUS_MEMBER_NOT_IN_ALIAS;
1031                 }
1032                 return NT_STATUS_LDAP(rc);
1033         }
1034
1035         return NT_STATUS_OK;
1036 }
1037
1038 static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
1039                                      const DOM_SID *alias,
1040                                      const DOM_SID *member)
1041 {
1042         return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_ADD);
1043 }
1044
1045 static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
1046                                      const DOM_SID *alias,
1047                                      const DOM_SID *member)
1048 {
1049         return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_DELETE);
1050 }
1051
1052 static bool pdb_ads_dnblob2sid(struct tldap_context *ld, DATA_BLOB *dnblob,
1053                                struct dom_sid *psid)
1054 {
1055         const char *attrs[1] = { "objectSid" };
1056         struct tldap_message **msg;
1057         char *dn;
1058         size_t len;
1059         int rc;
1060         bool ret;
1061
1062         if (!convert_string_talloc(talloc_tos(), CH_UTF8, CH_UNIX,
1063                                    dnblob->data, dnblob->length, &dn, &len,
1064                                    false)) {
1065                 return false;
1066         }
1067         rc = tldap_search_fmt(ld, dn, TLDAP_SCOPE_BASE,
1068                               attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1069                               &msg, "(objectclass=*)");
1070         TALLOC_FREE(dn);
1071         if (talloc_array_length(msg) != 1) {
1072                 DEBUG(10, ("Got %d objects, expected one\n",
1073                            (int)talloc_array_length(msg)));
1074                 TALLOC_FREE(msg);
1075                 return false;
1076         }
1077
1078         ret = tldap_pull_binsid(msg[0], "objectSid", psid);
1079         TALLOC_FREE(msg);
1080         return ret;
1081 }
1082
1083 static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
1084                                       const DOM_SID *alias,
1085                                       TALLOC_CTX *mem_ctx,
1086                                       DOM_SID **pmembers,
1087                                       size_t *pnum_members)
1088 {
1089         struct pdb_ads_state *state = talloc_get_type_abort(
1090                 m->private_data, struct pdb_ads_state);
1091         const char *attrs[1] = { "member" };
1092         char *sidstr;
1093         struct tldap_message **msg;
1094         int i, rc, num_members;
1095         DATA_BLOB *blobs;
1096         struct dom_sid *members;
1097
1098         sidstr = sid_binstring(talloc_tos(), alias);
1099         NT_STATUS_HAVE_NO_MEMORY(sidstr);
1100
1101         rc = tldap_search_fmt(state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1102                               attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &msg,
1103                               "(objectsid=%s)", sidstr);
1104         TALLOC_FREE(sidstr);
1105         if (rc != TLDAP_SUCCESS) {
1106                 DEBUG(10, ("ldap_search failed %s\n",
1107                            tldap_errstr(debug_ctx(), state->ld, rc)));
1108                 return NT_STATUS_LDAP(rc);
1109         }
1110         switch talloc_array_length(msg) {
1111         case 0:
1112                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1113                 break;
1114         case 1:
1115                 break;
1116         default:
1117                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1118                 break;
1119         }
1120
1121         if (!tldap_entry_values(msg[0], "member", &num_members, &blobs)) {
1122                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1123         }
1124
1125         members = talloc_array(mem_ctx, struct dom_sid, num_members);
1126         if (members == NULL) {
1127                 return NT_STATUS_NO_MEMORY;
1128         }
1129
1130         for (i=0; i<num_members; i++) {
1131                 if (!pdb_ads_dnblob2sid(state->ld, &blobs[i], &members[i])) {
1132                         TALLOC_FREE(members);
1133                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1134                 }
1135         }
1136
1137         *pmembers = members;
1138         *pnum_members = num_members;
1139         return NT_STATUS_OK;
1140 }
1141
1142 static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,
1143                                                TALLOC_CTX *mem_ctx,
1144                                                const DOM_SID *domain_sid,
1145                                                const DOM_SID *members,
1146                                                size_t num_members,
1147                                                uint32 **pp_alias_rids,
1148                                                size_t *p_num_alias_rids)
1149 {
1150         return NT_STATUS_NOT_IMPLEMENTED;
1151 }
1152
1153 static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m,
1154                                     const DOM_SID *domain_sid,
1155                                     int num_rids,
1156                                     uint32 *rids,
1157                                     const char **pp_names,
1158                                     enum lsa_SidType *attrs)
1159 {
1160         return NT_STATUS_NOT_IMPLEMENTED;
1161 }
1162
1163 static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m,
1164                                      const DOM_SID *domain_sid,
1165                                      int num_names,
1166                                      const char **pp_names,
1167                                      uint32 *rids,
1168                                      enum lsa_SidType *attrs)
1169 {
1170         return NT_STATUS_NOT_IMPLEMENTED;
1171 }
1172
1173 static NTSTATUS pdb_ads_get_account_policy(struct pdb_methods *m,
1174                                            int policy_index, uint32 *value)
1175 {
1176         return account_policy_get(policy_index, value)
1177                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1178 }
1179
1180 static NTSTATUS pdb_ads_set_account_policy(struct pdb_methods *m,
1181                                            int policy_index, uint32 value)
1182 {
1183         return account_policy_set(policy_index, value)
1184                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1185 }
1186
1187 static NTSTATUS pdb_ads_get_seq_num(struct pdb_methods *m,
1188                                     time_t *seq_num)
1189 {
1190         return NT_STATUS_NOT_IMPLEMENTED;
1191 }
1192
1193 struct pdb_ads_search_state {
1194         uint32_t acct_flags;
1195         struct samr_displayentry *entries;
1196         uint32_t num_entries;
1197         ssize_t array_size;
1198         uint32_t current;
1199 };
1200
1201 static bool pdb_ads_next_entry(struct pdb_search *search,
1202                                struct samr_displayentry *entry)
1203 {
1204         struct pdb_ads_search_state *state = talloc_get_type_abort(
1205                 search->private_data, struct pdb_ads_search_state);
1206
1207         if (state->current == state->num_entries) {
1208                 return false;
1209         }
1210
1211         entry->idx = state->entries[state->current].idx;
1212         entry->rid = state->entries[state->current].rid;
1213         entry->acct_flags = state->entries[state->current].acct_flags;
1214
1215         entry->account_name = talloc_strdup(
1216                 search, state->entries[state->current].account_name);
1217         entry->fullname = talloc_strdup(
1218                 search, state->entries[state->current].fullname);
1219         entry->description = talloc_strdup(
1220                 search, state->entries[state->current].description);
1221
1222         if ((entry->account_name == NULL) || (entry->fullname == NULL)
1223             || (entry->description == NULL)) {
1224                 DEBUG(0, ("talloc_strdup failed\n"));
1225                 return false;
1226         }
1227
1228         state->current += 1;
1229         return true;
1230 }
1231
1232 static void pdb_ads_search_end(struct pdb_search *search)
1233 {
1234         struct pdb_ads_search_state *state = talloc_get_type_abort(
1235                 search->private_data, struct pdb_ads_search_state);
1236         TALLOC_FREE(state);
1237 }
1238
1239 static bool pdb_ads_search_filter(struct pdb_methods *m,
1240                                   struct pdb_search *search,
1241                                   const char *filter,
1242                                   struct pdb_ads_search_state **pstate)
1243 {
1244         struct pdb_ads_state *state = talloc_get_type_abort(
1245                 m->private_data, struct pdb_ads_state);
1246         struct pdb_ads_search_state *sstate;
1247         const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1248                                  "userAccountControl", "description" };
1249         struct tldap_message **users;
1250         int i, rc, num_users;
1251
1252         sstate = talloc_zero(search, struct pdb_ads_search_state);
1253         if (sstate == NULL) {
1254                 return false;
1255         }
1256
1257         rc = tldap_search_fmt(
1258                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1259                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &users,
1260                 "%s", filter);
1261         if (rc != TLDAP_SUCCESS) {
1262                 DEBUG(10, ("ldap_search_ext_s failed: %s\n",
1263                            tldap_errstr(debug_ctx(), state->ld, rc)));
1264                 return false;
1265         }
1266
1267         num_users = talloc_array_length(users);
1268
1269         sstate->entries = talloc_array(sstate, struct samr_displayentry,
1270                                        num_users);
1271         if (sstate->entries == NULL) {
1272                 DEBUG(10, ("talloc failed\n"));
1273                 return false;
1274         }
1275
1276         sstate->num_entries = 0;
1277
1278         for (i=0; i<num_users; i++) {
1279                 struct samr_displayentry *e;
1280                 struct dom_sid sid;
1281
1282                 e = &sstate->entries[sstate->num_entries];
1283
1284                 e->idx = sstate->num_entries;
1285                 if (!tldap_pull_binsid(users[i], "objectSid", &sid)) {
1286                         DEBUG(10, ("Could not pull sid\n"));
1287                         continue;
1288                 }
1289                 sid_peek_rid(&sid, &e->rid);
1290                 e->acct_flags = ACB_NORMAL;
1291                 e->account_name = tldap_talloc_single_attribute(
1292                         users[i], "samAccountName", sstate->entries);
1293                 if (e->account_name == NULL) {
1294                         return false;
1295                 }
1296                 e->fullname = tldap_talloc_single_attribute(
1297                         users[i], "displayName", sstate->entries);
1298                 if (e->fullname == NULL) {
1299                         e->fullname = "";
1300                 }
1301                 e->description = tldap_talloc_single_attribute(
1302                         users[i], "description", sstate->entries);
1303                 if (e->description == NULL) {
1304                         e->description = "";
1305                 }
1306
1307                 sstate->num_entries += 1;
1308                 if (sstate->num_entries >= num_users) {
1309                         break;
1310                 }
1311         }
1312
1313         search->private_data = sstate;
1314         search->next_entry = pdb_ads_next_entry;
1315         search->search_end = pdb_ads_search_end;
1316         *pstate = sstate;
1317         return true;
1318 }
1319
1320 static bool pdb_ads_search_users(struct pdb_methods *m,
1321                                  struct pdb_search *search,
1322                                  uint32 acct_flags)
1323 {
1324         struct pdb_ads_search_state *sstate;
1325         bool ret;
1326
1327         ret = pdb_ads_search_filter(m, search, "(objectclass=user)", &sstate);
1328         if (!ret) {
1329                 return false;
1330         }
1331         sstate->acct_flags = acct_flags;
1332         return true;
1333 }
1334
1335 static bool pdb_ads_search_groups(struct pdb_methods *m,
1336                                   struct pdb_search *search)
1337 {
1338         struct pdb_ads_search_state *sstate;
1339         char *filter;
1340         bool ret;
1341
1342         filter = talloc_asprintf(talloc_tos(),
1343                                  "(&(grouptype=%d)(objectclass=group))",
1344                                  GTYPE_SECURITY_GLOBAL_GROUP);
1345         if (filter == NULL) {
1346                 return false;
1347         }
1348         ret = pdb_ads_search_filter(m, search, filter, &sstate);
1349         TALLOC_FREE(filter);
1350         if (!ret) {
1351                 return false;
1352         }
1353         sstate->acct_flags = 0;
1354         return true;
1355 }
1356
1357 static bool pdb_ads_search_aliases(struct pdb_methods *m,
1358                                    struct pdb_search *search,
1359                                    const DOM_SID *sid)
1360 {
1361         struct pdb_ads_search_state *sstate;
1362         char *filter;
1363         bool ret;
1364
1365         filter = talloc_asprintf(
1366                 talloc_tos(), "(&(grouptype=%d)(objectclass=group))",
1367                 sid_check_is_builtin(sid)
1368                 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
1369                 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1370
1371         if (filter == NULL) {
1372                 return false;
1373         }
1374         ret = pdb_ads_search_filter(m, search, filter, &sstate);
1375         TALLOC_FREE(filter);
1376         if (!ret) {
1377                 return false;
1378         }
1379         sstate->acct_flags = 0;
1380         return true;
1381 }
1382
1383 static bool pdb_ads_uid_to_rid(struct pdb_methods *m, uid_t uid,
1384                                uint32 *rid)
1385 {
1386         return false;
1387 }
1388
1389 static bool pdb_ads_uid_to_sid(struct pdb_methods *m, uid_t uid,
1390                                DOM_SID *sid)
1391 {
1392         struct pdb_ads_state *state = talloc_get_type_abort(
1393                 m->private_data, struct pdb_ads_state);
1394         sid_compose(sid, &state->domainsid, uid);
1395         return true;
1396 }
1397
1398 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
1399                                DOM_SID *sid)
1400 {
1401         struct pdb_ads_state *state = talloc_get_type_abort(
1402                 m->private_data, struct pdb_ads_state);
1403         sid_compose(sid, &state->domainsid, gid);
1404         return true;
1405 }
1406
1407 static bool pdb_ads_sid_to_id(struct pdb_methods *m, const DOM_SID *sid,
1408                               union unid_t *id, enum lsa_SidType *type)
1409 {
1410         struct pdb_ads_state *state = talloc_get_type_abort(
1411                 m->private_data, struct pdb_ads_state);
1412         struct tldap_message **msg;
1413         char *sidstr;
1414         uint32_t rid;
1415         int rc;
1416
1417         /*
1418          * This is a big, big hack: Just hard-code the rid as uid/gid.
1419          */
1420
1421         sid_peek_rid(sid, &rid);
1422
1423         sidstr = sid_binstring(talloc_tos(), sid);
1424         if (sidstr == NULL) {
1425                 return false;
1426         }
1427
1428         rc = tldap_search_fmt(
1429                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1430                 NULL, 0, 0, talloc_tos(), &msg,
1431                 "(&(objectsid=%s)(objectclass=user))", sidstr);
1432         if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
1433                 id->uid = rid;
1434                 *type = SID_NAME_USER;
1435                 TALLOC_FREE(sidstr);
1436                 return true;
1437         }
1438
1439         rc = tldap_search_fmt(
1440                 state->ld, state->domaindn, TLDAP_SCOPE_SUB,
1441                 NULL, 0, 0, talloc_tos(), &msg,
1442                 "(&(objectsid=%s)(objectclass=group))", sidstr);
1443         if ((rc == TLDAP_SUCCESS) && (talloc_array_length(msg) > 0)) {
1444                 id->gid = rid;
1445                 *type = SID_NAME_DOM_GRP;
1446                 TALLOC_FREE(sidstr);
1447                 return true;
1448         }
1449
1450         TALLOC_FREE(sidstr);
1451         return false;
1452 }
1453
1454 static bool pdb_ads_rid_algorithm(struct pdb_methods *m)
1455 {
1456         return false;
1457 }
1458
1459 static bool pdb_ads_new_rid(struct pdb_methods *m, uint32 *rid)
1460 {
1461         return false;
1462 }
1463
1464 static bool pdb_ads_get_trusteddom_pw(struct pdb_methods *m,
1465                                       const char *domain, char** pwd,
1466                                       DOM_SID *sid,
1467                                       time_t *pass_last_set_time)
1468 {
1469         return false;
1470 }
1471
1472 static bool pdb_ads_set_trusteddom_pw(struct pdb_methods *m,
1473                                       const char* domain, const char* pwd,
1474                                       const DOM_SID *sid)
1475 {
1476         return false;
1477 }
1478
1479 static bool pdb_ads_del_trusteddom_pw(struct pdb_methods *m,
1480                                       const char *domain)
1481 {
1482         return false;
1483 }
1484
1485 static NTSTATUS pdb_ads_enum_trusteddoms(struct pdb_methods *m,
1486                                          TALLOC_CTX *mem_ctx,
1487                                          uint32 *num_domains,
1488                                          struct trustdom_info ***domains)
1489 {
1490         return NT_STATUS_NOT_IMPLEMENTED;
1491 }
1492
1493 static void pdb_ads_init_methods(struct pdb_methods *m)
1494 {
1495         m->name = "ads";
1496         m->getsampwnam = pdb_ads_getsampwnam;
1497         m->getsampwsid = pdb_ads_getsampwsid;
1498         m->create_user = pdb_ads_create_user;
1499         m->delete_user = pdb_ads_delete_user;
1500         m->add_sam_account = pdb_ads_add_sam_account;
1501         m->update_sam_account = pdb_ads_update_sam_account;
1502         m->delete_sam_account = pdb_ads_delete_sam_account;
1503         m->rename_sam_account = pdb_ads_rename_sam_account;
1504         m->update_login_attempts = pdb_ads_update_login_attempts;
1505         m->getgrsid = pdb_ads_getgrsid;
1506         m->getgrgid = pdb_ads_getgrgid;
1507         m->getgrnam = pdb_ads_getgrnam;
1508         m->create_dom_group = pdb_ads_create_dom_group;
1509         m->delete_dom_group = pdb_ads_delete_dom_group;
1510         m->add_group_mapping_entry = pdb_ads_add_group_mapping_entry;
1511         m->update_group_mapping_entry = pdb_ads_update_group_mapping_entry;
1512         m->delete_group_mapping_entry = pdb_ads_delete_group_mapping_entry;
1513         m->enum_group_mapping = pdb_ads_enum_group_mapping;
1514         m->enum_group_members = pdb_ads_enum_group_members;
1515         m->enum_group_memberships = pdb_ads_enum_group_memberships;
1516         m->set_unix_primary_group = pdb_ads_set_unix_primary_group;
1517         m->add_groupmem = pdb_ads_add_groupmem;
1518         m->del_groupmem = pdb_ads_del_groupmem;
1519         m->create_alias = pdb_ads_create_alias;
1520         m->delete_alias = pdb_ads_delete_alias;
1521         m->get_aliasinfo = pdb_ads_get_aliasinfo;
1522         m->set_aliasinfo = pdb_ads_set_aliasinfo;
1523         m->add_aliasmem = pdb_ads_add_aliasmem;
1524         m->del_aliasmem = pdb_ads_del_aliasmem;
1525         m->enum_aliasmem = pdb_ads_enum_aliasmem;
1526         m->enum_alias_memberships = pdb_ads_enum_alias_memberships;
1527         m->lookup_rids = pdb_ads_lookup_rids;
1528         m->lookup_names = pdb_ads_lookup_names;
1529         m->get_account_policy = pdb_ads_get_account_policy;
1530         m->set_account_policy = pdb_ads_set_account_policy;
1531         m->get_seq_num = pdb_ads_get_seq_num;
1532         m->search_users = pdb_ads_search_users;
1533         m->search_groups = pdb_ads_search_groups;
1534         m->search_aliases = pdb_ads_search_aliases;
1535         m->uid_to_rid = pdb_ads_uid_to_rid;
1536         m->uid_to_sid = pdb_ads_uid_to_sid;
1537         m->gid_to_sid = pdb_ads_gid_to_sid;
1538         m->sid_to_id = pdb_ads_sid_to_id;
1539         m->rid_algorithm = pdb_ads_rid_algorithm;
1540         m->new_rid = pdb_ads_new_rid;
1541         m->get_trusteddom_pw = pdb_ads_get_trusteddom_pw;
1542         m->set_trusteddom_pw = pdb_ads_set_trusteddom_pw;
1543         m->del_trusteddom_pw = pdb_ads_del_trusteddom_pw;
1544         m->enum_trusteddoms = pdb_ads_enum_trusteddoms;
1545 }
1546
1547 static void free_private_data(void **vp)
1548 {
1549         struct pdb_ads_state *state = talloc_get_type_abort(
1550                 *vp, struct pdb_ads_state);
1551
1552         TALLOC_FREE(state->ld);
1553         return;
1554 }
1555
1556 static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state,
1557                                 const char *location)
1558 {
1559         const char *rootdse_attrs[2] = {
1560                 "defaultNamingContext", "configurationNamingContext" };
1561         const char *domain_attrs[1] = { "objectSid" };
1562         const char *ncname_attrs[1] = { "netbiosname" };
1563         struct tldap_message **rootdse, **domain, **ncname;
1564         TALLOC_CTX *frame = talloc_stackframe();
1565         struct sockaddr_un sunaddr;
1566         NTSTATUS status;
1567         int num_domains;
1568         int fd, rc;
1569
1570         ZERO_STRUCT(sunaddr);
1571         sunaddr.sun_family = AF_UNIX;
1572         strncpy(sunaddr.sun_path, location, sizeof(sunaddr.sun_path) - 1);
1573
1574         status = open_socket_out((struct sockaddr_storage *)(void *)&sunaddr,
1575                                  0, 0, &fd);
1576         if (!NT_STATUS_IS_OK(status)) {
1577                 DEBUG(10, ("Could not connect to %s: %s\n", location,
1578                            nt_errstr(status)));
1579                 goto done;
1580         }
1581
1582         state->ld = tldap_context_create(state, fd);
1583         if (state->ld == NULL) {
1584                 close(fd);
1585                 status = NT_STATUS_NO_MEMORY;
1586                 goto done;
1587         }
1588
1589         rc = tldap_search_fmt(
1590                 state->ld, "", TLDAP_SCOPE_BASE,
1591                 rootdse_attrs, ARRAY_SIZE(rootdse_attrs), 0,
1592                 talloc_tos(), &rootdse, "(objectclass=*)");
1593         if (rc != TLDAP_SUCCESS) {
1594                 DEBUG(10, ("Could not retrieve rootdse: %s\n",
1595                            tldap_errstr(debug_ctx(), state->ld, rc)));
1596                 status = NT_STATUS_LDAP(rc);
1597                 goto done;
1598         }
1599         if (talloc_array_length(rootdse) != 1) {
1600                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1601                 goto done;
1602         }
1603
1604         state->domaindn = tldap_talloc_single_attribute(
1605                 rootdse[0], "defaultNamingContext", state);
1606         if (state->domaindn == NULL) {
1607                 DEBUG(10, ("Could not get defaultNamingContext\n"));
1608                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1609                 goto done;
1610         }
1611         DEBUG(10, ("defaultNamingContext = %s\n", state->domaindn));
1612
1613         state->configdn = tldap_talloc_single_attribute(
1614                 rootdse[0], "configurationNamingContext", state);
1615         if (state->domaindn == NULL) {
1616                 DEBUG(10, ("Could not get configurationNamingContext\n"));
1617                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1618                 goto done;
1619         }
1620         DEBUG(10, ("configurationNamingContext = %s\n", state->configdn));
1621
1622         /*
1623          * Figure out our domain's SID
1624          */
1625         rc = tldap_search_fmt(
1626                 state->ld, state->domaindn, TLDAP_SCOPE_BASE,
1627                 domain_attrs, ARRAY_SIZE(domain_attrs), 0,
1628                 talloc_tos(), &domain, "(objectclass=*)");
1629         if (rc != TLDAP_SUCCESS) {
1630                 DEBUG(10, ("Could not retrieve domain: %s\n",
1631                            tldap_errstr(debug_ctx(), state->ld, rc)));
1632                 status = NT_STATUS_LDAP(rc);
1633                 goto done;
1634         }
1635
1636         num_domains = talloc_array_length(domain);
1637         if (num_domains != 1) {
1638                 DEBUG(10, ("Got %d domains, expected one\n", num_domains));
1639                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1640                 goto done;
1641         }
1642         if (!tldap_pull_binsid(domain[0], "objectSid", &state->domainsid)) {
1643                 DEBUG(10, ("Could not retrieve domain SID\n"));
1644                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1645                 goto done;
1646         }
1647         DEBUG(10, ("Domain SID: %s\n", sid_string_dbg(&state->domainsid)));
1648
1649         /*
1650          * Figure out our domain's short name
1651          */
1652         rc = tldap_search_fmt(
1653                 state->ld, state->configdn, TLDAP_SCOPE_SUB,
1654                 ncname_attrs, ARRAY_SIZE(ncname_attrs), 0,
1655                 talloc_tos(), &ncname, "(ncname=%s)", state->domaindn);
1656         if (rc != TLDAP_SUCCESS) {
1657                 DEBUG(10, ("Could not retrieve ncname: %s\n",
1658                            tldap_errstr(debug_ctx(), state->ld, rc)));
1659                 status = NT_STATUS_LDAP(rc);
1660                 goto done;
1661         }
1662         if (talloc_array_length(ncname) != 1) {
1663                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1664                 goto done;
1665         }
1666
1667         state->netbiosname = tldap_talloc_single_attribute(
1668                 ncname[0], "netbiosname", state);
1669         if (state->netbiosname == NULL) {
1670                 DEBUG(10, ("Could not get netbiosname\n"));
1671                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1672                 goto done;
1673         }
1674         DEBUG(10, ("netbiosname: %s\n", state->netbiosname));
1675
1676         if (!strequal(lp_workgroup(), state->netbiosname)) {
1677                 DEBUG(1, ("ADS is different domain (%s) than ours (%s)\n",
1678                           state->netbiosname, lp_workgroup()));
1679                 status = NT_STATUS_NO_SUCH_DOMAIN;
1680                 goto done;
1681         }
1682
1683         secrets_store_domain_sid(state->netbiosname, &state->domainsid);
1684
1685         status = NT_STATUS_OK;
1686 done:
1687         TALLOC_FREE(frame);
1688         return status;
1689 }
1690
1691 static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method,
1692                              const char *location)
1693 {
1694         struct pdb_methods *m;
1695         struct pdb_ads_state *state;
1696         char *tmp = NULL;
1697         NTSTATUS status;
1698
1699         m = talloc(talloc_autofree_context(), struct pdb_methods);
1700         if (m == NULL) {
1701                 return NT_STATUS_NO_MEMORY;
1702         }
1703         state = talloc(m, struct pdb_ads_state);
1704         if (state == NULL) {
1705                 goto nomem;
1706         }
1707         m->private_data = state;
1708         m->free_private_data = free_private_data;
1709         pdb_ads_init_methods(m);
1710
1711         if (location == NULL) {
1712                 tmp = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi",
1713                                       lp_private_dir());
1714                 location = tmp;
1715         }
1716         if (location == NULL) {
1717                 goto nomem;
1718         }
1719
1720         status = pdb_ads_connect(state, location);
1721         if (!NT_STATUS_IS_OK(status)) {
1722                 DEBUG(10, ("pdb_ads_connect failed: %s\n", nt_errstr(status)));
1723                 goto fail;
1724         }
1725
1726         *pdb_method = m;
1727         return NT_STATUS_OK;
1728 nomem:
1729         status = NT_STATUS_NO_MEMORY;
1730 fail:
1731         TALLOC_FREE(m);
1732         return status;
1733 }
1734
1735 NTSTATUS pdb_ads_init(void);
1736 NTSTATUS pdb_ads_init(void)
1737 {
1738         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "ads",
1739                                    pdb_init_ads);
1740 }