3746da3a4fe802a34fc06e103012cb31a5a52da6
[obnox/samba/samba-obnox.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 #include "passdb.h"
22 #include "tldap.h"
23 #include "tldap_util.h"
24 #include "../libds/common/flags.h"
25 #include "secrets.h"
26 #include "../librpc/gen_ndr/samr.h"
27 #include "../libcli/ldap/ldap_ndr.h"
28 #include "../libcli/security/security.h"
29 #include "../libds/common/flag_mapping.h"
30
31 struct pdb_ads_state {
32         struct sockaddr_un socket_address;
33         struct tldap_context *ld;
34         struct dom_sid domainsid;
35         struct GUID domainguid;
36         char *domaindn;
37         char *configdn;
38         char *netbiosname;
39 };
40
41 struct pdb_ads_samu_private {
42         char *dn;
43         struct tldap_message *ldapmsg;
44 };
45
46 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
47                                struct dom_sid *sid);
48 static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
49                                struct dom_sid *psid);
50 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
51                                const struct dom_sid *sid,
52                                TALLOC_CTX *mem_ctx, char **pdn);
53 static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state);
54 static int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base,
55                               int scope, const char *attrs[], int num_attrs,
56                               int attrsonly,
57                               TALLOC_CTX *mem_ctx, struct tldap_message ***res,
58                               const char *fmt, ...);
59 static NTSTATUS pdb_ads_getsamupriv(struct pdb_ads_state *state,
60                                     const char *filter,
61                                     TALLOC_CTX *mem_ctx,
62                                     struct pdb_ads_samu_private **presult);
63
64 static bool pdb_ads_pull_time(struct tldap_message *msg, const char *attr,
65                               time_t *ptime)
66 {
67         uint64_t tmp;
68
69         if (!tldap_pull_uint64(msg, attr, &tmp)) {
70                 return false;
71         }
72         *ptime = nt_time_to_unix(tmp);
73         return true;
74 }
75
76 static gid_t pdb_ads_sid2gid(const struct dom_sid *sid)
77 {
78         uint32_t rid;
79         sid_peek_rid(sid, &rid);
80         return rid;
81 }
82
83 static char *pdb_ads_domaindn2dns(TALLOC_CTX *mem_ctx, char *dn)
84 {
85         char *result, *p;
86
87         result = talloc_string_sub2(mem_ctx, dn, "DC=", "", false, false,
88                                     true);
89         if (result == NULL) {
90                 return NULL;
91         }
92
93         while ((p = strchr_m(result, ',')) != NULL) {
94                 *p = '.';
95         }
96
97         return result;
98 }
99
100 static struct pdb_domain_info *pdb_ads_get_domain_info(
101         struct pdb_methods *m, TALLOC_CTX *mem_ctx)
102 {
103         struct pdb_ads_state *state = talloc_get_type_abort(
104                 m->private_data, struct pdb_ads_state);
105         struct pdb_domain_info *info;
106         struct tldap_message *rootdse;
107         char *tmp;
108
109         info = talloc(mem_ctx, struct pdb_domain_info);
110         if (info == NULL) {
111                 return NULL;
112         }
113         info->name = talloc_strdup(info, state->netbiosname);
114         if (info->name == NULL) {
115                 goto fail;
116         }
117         info->dns_domain = pdb_ads_domaindn2dns(info, state->domaindn);
118         if (info->dns_domain == NULL) {
119                 goto fail;
120         }
121
122         rootdse = tldap_rootdse(state->ld);
123         tmp = tldap_talloc_single_attribute(rootdse, "rootDomainNamingContext",
124                                             talloc_tos());
125         if (tmp == NULL) {
126                 goto fail;
127         }
128         info->dns_forest = pdb_ads_domaindn2dns(info, tmp);
129         TALLOC_FREE(tmp);
130         if (info->dns_forest == NULL) {
131                 goto fail;
132         }
133         info->sid = state->domainsid;
134         info->guid = state->domainguid;
135         return info;
136
137 fail:
138         TALLOC_FREE(info);
139         return NULL;
140 }
141
142 static struct pdb_ads_samu_private *pdb_ads_get_samu_private(
143         struct pdb_methods *m, struct samu *sam)
144 {
145         struct pdb_ads_state *state = talloc_get_type_abort(
146                 m->private_data, struct pdb_ads_state);
147         struct pdb_ads_samu_private *result;
148         char *sidstr, *filter;
149         NTSTATUS status;
150
151         result = (struct pdb_ads_samu_private *)
152                 pdb_get_backend_private_data(sam, m);
153
154         if (result != NULL) {
155                 return talloc_get_type_abort(
156                         result, struct pdb_ads_samu_private);
157         }
158
159         sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), pdb_get_user_sid(sam));
160         if (sidstr == NULL) {
161                 return NULL;
162         }
163
164         filter = talloc_asprintf(
165                 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
166         TALLOC_FREE(sidstr);
167         if (filter == NULL) {
168                 return NULL;
169         }
170
171         status = pdb_ads_getsamupriv(state, filter, sam, &result);
172         TALLOC_FREE(filter);
173         if (!NT_STATUS_IS_OK(status)) {
174                 return NULL;
175         }
176
177         return result;
178 }
179
180 static NTSTATUS pdb_ads_init_sam_from_priv(struct pdb_methods *m,
181                                            struct samu *sam,
182                                            struct pdb_ads_samu_private *priv)
183 {
184         struct pdb_ads_state *state = talloc_get_type_abort(
185                 m->private_data, struct pdb_ads_state);
186         TALLOC_CTX *frame = talloc_stackframe();
187         NTSTATUS status = NT_STATUS_INTERNAL_DB_CORRUPTION;
188         struct tldap_message *entry = priv->ldapmsg;
189         char *str;
190         time_t tmp_time;
191         struct dom_sid sid;
192         uint64_t n;
193         uint32_t i;
194         DATA_BLOB blob;
195
196         str = tldap_talloc_single_attribute(entry, "samAccountName", sam);
197         if (str == NULL) {
198                 DEBUG(10, ("no samAccountName\n"));
199                 goto fail;
200         }
201         pdb_set_username(sam, str, PDB_SET);
202
203         if (pdb_ads_pull_time(entry, "lastLogon", &tmp_time)) {
204                 pdb_set_logon_time(sam, tmp_time, PDB_SET);
205         }
206         if (pdb_ads_pull_time(entry, "lastLogoff", &tmp_time)) {
207                 pdb_set_logoff_time(sam, tmp_time, PDB_SET);
208         }
209         if (pdb_ads_pull_time(entry, "pwdLastSet", &tmp_time)) {
210                 pdb_set_pass_last_set_time(sam, tmp_time, PDB_SET);
211         }
212         if (pdb_ads_pull_time(entry, "accountExpires", &tmp_time)) {
213                 pdb_set_kickoff_time(sam, tmp_time, PDB_SET);
214         }
215
216         str = tldap_talloc_single_attribute(entry, "displayName",
217                                             talloc_tos());
218         if (str != NULL) {
219                 pdb_set_fullname(sam, str, PDB_SET);
220         }
221
222         str = tldap_talloc_single_attribute(entry, "homeDirectory",
223                                             talloc_tos());
224         if (str != NULL) {
225                 pdb_set_homedir(sam, str, PDB_SET);
226         }
227
228         str = tldap_talloc_single_attribute(entry, "homeDrive", talloc_tos());
229         if (str != NULL) {
230                 pdb_set_dir_drive(sam, str, PDB_SET);
231         }
232
233         str = tldap_talloc_single_attribute(entry, "scriptPath", talloc_tos());
234         if (str != NULL) {
235                 pdb_set_logon_script(sam, str, PDB_SET);
236         }
237
238         str = tldap_talloc_single_attribute(entry, "profilePath",
239                                             talloc_tos());
240         if (str != NULL) {
241                 pdb_set_profile_path(sam, str, PDB_SET);
242         }
243
244         str = tldap_talloc_single_attribute(entry, "profilePath",
245                                             talloc_tos());
246         if (str != NULL) {
247                 pdb_set_profile_path(sam, str, PDB_SET);
248         }
249
250         str = tldap_talloc_single_attribute(entry, "comment",
251                                             talloc_tos());
252         if (str != NULL) {
253                 pdb_set_comment(sam, str, PDB_SET);
254         }
255
256         str = tldap_talloc_single_attribute(entry, "description",
257                                             talloc_tos());
258         if (str != NULL) {
259                 pdb_set_acct_desc(sam, str, PDB_SET);
260         }
261
262         str = tldap_talloc_single_attribute(entry, "userWorkstations",
263                                             talloc_tos());
264         if (str != NULL) {
265                 pdb_set_workstations(sam, str, PDB_SET);
266         }
267
268         str = tldap_talloc_single_attribute(entry, "userParameters",
269                                             talloc_tos());
270         if (str != NULL) {
271                 pdb_set_munged_dial(sam, str, PDB_SET);
272         }
273
274         if (!tldap_pull_binsid(entry, "objectSid", &sid)) {
275                 DEBUG(10, ("Could not pull SID\n"));
276                 goto fail;
277         }
278         pdb_set_user_sid(sam, &sid, PDB_SET);
279
280         if (!tldap_pull_uint64(entry, "userAccountControl", &n)) {
281                 DEBUG(10, ("Could not pull userAccountControl\n"));
282                 goto fail;
283         }
284         pdb_set_acct_ctrl(sam, ds_uf2acb(n), PDB_SET);
285
286         if (tldap_get_single_valueblob(entry, "unicodePwd", &blob)) {
287                 if (blob.length != NT_HASH_LEN) {
288                         DEBUG(0, ("Got NT hash of length %d, expected %d\n",
289                                   (int)blob.length, NT_HASH_LEN));
290                         goto fail;
291                 }
292                 pdb_set_nt_passwd(sam, blob.data, PDB_SET);
293         }
294
295         if (tldap_get_single_valueblob(entry, "dBCSPwd", &blob)) {
296                 if (blob.length != LM_HASH_LEN) {
297                         DEBUG(0, ("Got LM hash of length %d, expected %d\n",
298                                   (int)blob.length, LM_HASH_LEN));
299                         goto fail;
300                 }
301                 pdb_set_lanman_passwd(sam, blob.data, PDB_SET);
302         }
303
304         if (tldap_pull_uint64(entry, "primaryGroupID", &n)) {
305                 sid_compose(&sid, &state->domainsid, n);
306                 pdb_set_group_sid(sam, &sid, PDB_SET);
307
308         }
309
310         if (tldap_pull_uint32(entry, "countryCode", &i)) {
311                 pdb_set_country_code(sam, i, PDB_SET);
312         }
313
314         if (tldap_pull_uint32(entry, "codePage", &i)) {
315                 pdb_set_code_page(sam, i, PDB_SET);
316         }
317
318         if (tldap_get_single_valueblob(entry, "logonHours", &blob)) {
319
320                 if (blob.length > MAX_HOURS_LEN) {
321                         status = NT_STATUS_INVALID_PARAMETER;
322                         goto fail;
323                 }
324                 pdb_set_logon_divs(sam, blob.length * 8, PDB_SET);
325                 pdb_set_hours_len(sam, blob.length, PDB_SET);
326                 pdb_set_hours(sam, blob.data, blob.length, PDB_SET);
327
328         } else {
329                 uint8_t hours[21];
330                 pdb_set_logon_divs(sam, sizeof(hours)/8, PDB_SET);
331                 pdb_set_hours_len(sam, sizeof(hours), PDB_SET);
332                 memset(hours, 0xff, sizeof(hours));
333                 pdb_set_hours(sam, hours, sizeof(hours), PDB_SET);
334         }
335
336         status = NT_STATUS_OK;
337 fail:
338         TALLOC_FREE(frame);
339         return status;
340 }
341
342 static bool pdb_ads_make_time_mod(struct tldap_message *existing,
343                                   TALLOC_CTX *mem_ctx,
344                                   struct tldap_mod **pmods, int *pnum_mods,
345                                   const char *attrib, time_t t)
346 {
347         uint64_t nt_time;
348
349         unix_to_nt_time(&nt_time, t);
350
351         return tldap_make_mod_fmt(
352                 existing, mem_ctx, pmods, pnum_mods, attrib,
353                 "%llu", nt_time);
354 }
355
356 static bool pdb_ads_init_ads_from_sam(struct pdb_ads_state *state,
357                                       struct tldap_message *existing,
358                                       TALLOC_CTX *mem_ctx,
359                                       struct tldap_mod **pmods, int *pnum_mods,
360                                       struct samu *sam)
361 {
362         bool ret = true;
363         DATA_BLOB blob;
364         const char *pw;
365
366         /* TODO: All fields :-) */
367
368         ret &= tldap_make_mod_fmt(
369                 existing, mem_ctx, pmods, pnum_mods, "displayName",
370                 "%s", pdb_get_fullname(sam));
371
372         pw = pdb_get_plaintext_passwd(sam);
373
374         /*
375          * If we have the plain text pw, this is probably about to be
376          * set. Is this true always?
377          */
378         if (pw != NULL) {
379                 char *pw_quote;
380                 uint8_t *pw_utf16;
381                 size_t pw_utf16_len;
382
383                 pw_quote = talloc_asprintf(talloc_tos(), "\"%s\"", pw);
384                 if (pw_quote == NULL) {
385                         ret = false;
386                         goto fail;
387                 }
388
389                 ret &= convert_string_talloc(talloc_tos(),
390                                              CH_UNIX, CH_UTF16LE,
391                                              pw_quote, strlen(pw_quote),
392                                              &pw_utf16, &pw_utf16_len);
393                 if (!ret) {
394                         goto fail;
395                 }
396                 blob = data_blob_const(pw_utf16, pw_utf16_len);
397
398                 ret &= tldap_add_mod_blobs(mem_ctx, pmods, pnum_mods,
399                                            TLDAP_MOD_REPLACE,
400                                            "unicodePwd", &blob, 1);
401                 TALLOC_FREE(pw_utf16);
402                 TALLOC_FREE(pw_quote);
403         }
404
405         ret &= tldap_make_mod_fmt(
406                 existing, mem_ctx, pmods, pnum_mods, "userAccountControl",
407                 "%d", ds_acb2uf(pdb_get_acct_ctrl(sam)));
408
409         ret &= tldap_make_mod_fmt(
410                 existing, mem_ctx, pmods, pnum_mods, "homeDirectory",
411                 "%s", pdb_get_homedir(sam));
412
413         ret &= tldap_make_mod_fmt(
414                 existing, mem_ctx, pmods, pnum_mods, "homeDrive",
415                 "%s", pdb_get_dir_drive(sam));
416
417         ret &= tldap_make_mod_fmt(
418                 existing, mem_ctx, pmods, pnum_mods, "scriptPath",
419                 "%s", pdb_get_logon_script(sam));
420
421         ret &= tldap_make_mod_fmt(
422                 existing, mem_ctx, pmods, pnum_mods, "profilePath",
423                 "%s", pdb_get_profile_path(sam));
424
425         ret &= tldap_make_mod_fmt(
426                 existing, mem_ctx, pmods, pnum_mods, "comment",
427                 "%s", pdb_get_comment(sam));
428
429         ret &= tldap_make_mod_fmt(
430                 existing, mem_ctx, pmods, pnum_mods, "description",
431                 "%s", pdb_get_acct_desc(sam));
432
433         ret &= tldap_make_mod_fmt(
434                 existing, mem_ctx, pmods, pnum_mods, "userWorkstations",
435                 "%s", pdb_get_workstations(sam));
436
437         ret &= tldap_make_mod_fmt(
438                 existing, mem_ctx, pmods, pnum_mods, "userParameters",
439                 "%s", pdb_get_munged_dial(sam));
440
441         ret &= tldap_make_mod_fmt(
442                 existing, mem_ctx, pmods, pnum_mods, "countryCode",
443                 "%i", (int)pdb_get_country_code(sam));
444
445         ret &= tldap_make_mod_fmt(
446                 existing, mem_ctx, pmods, pnum_mods, "codePage",
447                 "%i", (int)pdb_get_code_page(sam));
448
449         ret &= pdb_ads_make_time_mod(
450                 existing, mem_ctx, pmods, pnum_mods, "accountExpires",
451                 (int)pdb_get_kickoff_time(sam));
452
453         ret &= tldap_make_mod_blob(
454                 existing, mem_ctx, pmods, pnum_mods, "logonHours",
455                 data_blob_const(pdb_get_hours(sam), pdb_get_hours_len(sam)));
456
457 fail:
458         return ret;
459 }
460
461 static NTSTATUS pdb_ads_getsamupriv(struct pdb_ads_state *state,
462                                     const char *filter,
463                                     TALLOC_CTX *mem_ctx,
464                                     struct pdb_ads_samu_private **presult)
465 {
466         const char * attrs[] = {
467                 "lastLogon", "lastLogoff", "pwdLastSet", "accountExpires",
468                 "sAMAccountName", "displayName", "homeDirectory",
469                 "homeDrive", "scriptPath", "profilePath", "description",
470                 "userWorkstations", "comment", "userParameters", "objectSid",
471                 "primaryGroupID", "userAccountControl", "logonHours",
472                 "badPwdCount", "logonCount", "countryCode", "codePage",
473                 "unicodePwd", "dBCSPwd" };
474         struct tldap_message **users;
475         int rc, count;
476         struct pdb_ads_samu_private *result;
477
478         result = talloc(mem_ctx, struct pdb_ads_samu_private);
479         if (result == NULL) {
480                 return NT_STATUS_NO_MEMORY;
481         }
482
483         rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
484                                 attrs, ARRAY_SIZE(attrs), 0, result,
485                                 &users, "%s", filter);
486         if (rc != TLDAP_SUCCESS) {
487                 DEBUG(10, ("ldap_search failed %s\n",
488                            tldap_errstr(talloc_tos(), state->ld, rc)));
489                 TALLOC_FREE(result);
490                 return NT_STATUS_LDAP(rc);
491         }
492
493         count = talloc_array_length(users);
494         if (count != 1) {
495                 DEBUG(10, ("Expected 1 user, got %d\n", count));
496                 TALLOC_FREE(result);
497                 return NT_STATUS_NO_SUCH_USER;
498         }
499
500         result->ldapmsg = users[0];
501         if (!tldap_entry_dn(result->ldapmsg, &result->dn)) {
502                 DEBUG(10, ("Could not extract dn\n"));
503                 TALLOC_FREE(result);
504                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
505         }
506
507         *presult = result;
508         return NT_STATUS_OK;
509 }
510
511 static NTSTATUS pdb_ads_getsampwfilter(struct pdb_methods *m,
512                                        struct pdb_ads_state *state,
513                                        struct samu *sam_acct,
514                                        const char *filter)
515 {
516         struct pdb_ads_samu_private *priv;
517         NTSTATUS status;
518
519         status = pdb_ads_getsamupriv(state, filter, sam_acct, &priv);
520         if (!NT_STATUS_IS_OK(status)) {
521                 DEBUG(10, ("pdb_ads_getsamupriv failed: %s\n",
522                            nt_errstr(status)));
523                 return status;
524         }
525
526         status = pdb_ads_init_sam_from_priv(m, sam_acct, priv);
527         if (!NT_STATUS_IS_OK(status)) {
528                 DEBUG(10, ("pdb_ads_init_sam_from_priv failed: %s\n",
529                            nt_errstr(status)));
530                 TALLOC_FREE(priv);
531                 return status;
532         }
533
534         pdb_set_backend_private_data(sam_acct, priv, NULL, m, PDB_SET);
535         return NT_STATUS_OK;
536 }
537
538 static NTSTATUS pdb_ads_getsampwnam(struct pdb_methods *m,
539                                     struct samu *sam_acct,
540                                     const char *username)
541 {
542         struct pdb_ads_state *state = talloc_get_type_abort(
543                 m->private_data, struct pdb_ads_state);
544         char *filter;
545
546         filter = talloc_asprintf(
547                 talloc_tos(), "(&(samaccountname=%s)(objectclass=user))",
548                 username);
549         NT_STATUS_HAVE_NO_MEMORY(filter);
550
551         return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
552 }
553
554 static NTSTATUS pdb_ads_getsampwsid(struct pdb_methods *m,
555                                     struct samu *sam_acct,
556                                     const struct dom_sid *sid)
557 {
558         struct pdb_ads_state *state = talloc_get_type_abort(
559                 m->private_data, struct pdb_ads_state);
560         char *sidstr, *filter;
561
562         sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
563         NT_STATUS_HAVE_NO_MEMORY(sidstr);
564
565         filter = talloc_asprintf(
566                 talloc_tos(), "(&(objectsid=%s)(objectclass=user))", sidstr);
567         TALLOC_FREE(sidstr);
568         NT_STATUS_HAVE_NO_MEMORY(filter);
569
570         return pdb_ads_getsampwfilter(m, state, sam_acct, filter);
571 }
572
573 static NTSTATUS pdb_ads_create_user(struct pdb_methods *m,
574                                     TALLOC_CTX *tmp_ctx,
575                                     const char *name, uint32 acct_flags,
576                                     uint32 *rid)
577 {
578         struct pdb_ads_state *state = talloc_get_type_abort(
579                 m->private_data, struct pdb_ads_state);
580         struct tldap_context *ld;
581         const char *attrs[1] = { "objectSid" };
582         struct tldap_mod *mods = NULL;
583         int num_mods = 0;
584         struct tldap_message **user;
585         struct dom_sid sid;
586         char *dn;
587         int rc;
588         bool ok;
589
590         dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
591                              state->domaindn);
592         if (dn == NULL) {
593                 return NT_STATUS_NO_MEMORY;
594         }
595
596         ld = pdb_ads_ld(state);
597         if (ld == NULL) {
598                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
599         }
600
601         /* TODO: Create machines etc */
602
603         ok = true;
604         ok &= tldap_make_mod_fmt(
605                 NULL, talloc_tos(), &mods, &num_mods, "objectClass", "user");
606         ok &= tldap_make_mod_fmt(
607                 NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
608                 name);
609         if (!ok) {
610                 return NT_STATUS_NO_MEMORY;
611         }
612
613
614         rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
615         if (rc != TLDAP_SUCCESS) {
616                 DEBUG(10, ("ldap_add failed %s\n",
617                            tldap_errstr(talloc_tos(), ld, rc)));
618                 TALLOC_FREE(dn);
619                 return NT_STATUS_LDAP(rc);
620         }
621
622         rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
623                                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
624                                 &user,
625                                 "(&(objectclass=user)(samaccountname=%s))",
626                                 name);
627         if (rc != TLDAP_SUCCESS) {
628                 DEBUG(10, ("Could not find just created user %s: %s\n",
629                            name, tldap_errstr(talloc_tos(), state->ld, rc)));
630                 TALLOC_FREE(dn);
631                 return NT_STATUS_LDAP(rc);
632         }
633
634         if (talloc_array_length(user) != 1) {
635                 DEBUG(10, ("Got %d users, expected one\n",
636                            (int)talloc_array_length(user)));
637                 TALLOC_FREE(dn);
638                 return NT_STATUS_LDAP(rc);
639         }
640
641         if (!tldap_pull_binsid(user[0], "objectSid", &sid)) {
642                 DEBUG(10, ("Could not fetch objectSid from user %s\n",
643                            name));
644                 TALLOC_FREE(dn);
645                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
646         }
647
648         sid_peek_rid(&sid, rid);
649         TALLOC_FREE(dn);
650         return NT_STATUS_OK;
651 }
652
653 static NTSTATUS pdb_ads_delete_user(struct pdb_methods *m,
654                                     TALLOC_CTX *tmp_ctx,
655                                     struct samu *sam)
656 {
657         struct pdb_ads_state *state = talloc_get_type_abort(
658                 m->private_data, struct pdb_ads_state);
659         NTSTATUS status;
660         struct tldap_context *ld;
661         char *dn;
662         int rc;
663
664         ld = pdb_ads_ld(state);
665         if (ld == NULL) {
666                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
667         }
668
669         status = pdb_ads_sid2dn(state, pdb_get_user_sid(sam), talloc_tos(),
670                                 &dn);
671         if (!NT_STATUS_IS_OK(status)) {
672                 return status;
673         }
674
675         rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
676         TALLOC_FREE(dn);
677         if (rc != TLDAP_SUCCESS) {
678                 DEBUG(10, ("ldap_delete for %s failed: %s\n", dn,
679                            tldap_errstr(talloc_tos(), ld, rc)));
680                 return NT_STATUS_LDAP(rc);
681         }
682         return NT_STATUS_OK;
683 }
684
685 static NTSTATUS pdb_ads_add_sam_account(struct pdb_methods *m,
686                                         struct samu *sampass)
687 {
688         return NT_STATUS_NOT_IMPLEMENTED;
689 }
690
691 static NTSTATUS pdb_ads_update_sam_account(struct pdb_methods *m,
692                                            struct samu *sam)
693 {
694         struct pdb_ads_state *state = talloc_get_type_abort(
695                 m->private_data, struct pdb_ads_state);
696         struct pdb_ads_samu_private *priv = pdb_ads_get_samu_private(m, sam);
697         struct tldap_context *ld;
698         struct tldap_mod *mods = NULL;
699         int rc, num_mods = 0;
700
701         ld = pdb_ads_ld(state);
702         if (ld == NULL) {
703                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
704         }
705
706         if (!pdb_ads_init_ads_from_sam(state, priv->ldapmsg, talloc_tos(),
707                                        &mods, &num_mods, sam)) {
708                 return NT_STATUS_NO_MEMORY;
709         }
710
711         if (num_mods == 0) {
712                 /* Nothing to do, just return success */
713                 return NT_STATUS_OK;
714         }
715
716         rc = tldap_modify(ld, priv->dn, mods, num_mods, NULL, 0,
717                           NULL, 0);
718         TALLOC_FREE(mods);
719         if (rc != TLDAP_SUCCESS) {
720                 DEBUG(10, ("ldap_modify for %s failed: %s\n", priv->dn,
721                            tldap_errstr(talloc_tos(), ld, rc)));
722                 return NT_STATUS_LDAP(rc);
723         }
724
725         return NT_STATUS_OK;
726 }
727
728 static NTSTATUS pdb_ads_delete_sam_account(struct pdb_methods *m,
729                                            struct samu *username)
730 {
731         return NT_STATUS_NOT_IMPLEMENTED;
732 }
733
734 static NTSTATUS pdb_ads_rename_sam_account(struct pdb_methods *m,
735                                            struct samu *oldname,
736                                            const char *newname)
737 {
738         return NT_STATUS_NOT_IMPLEMENTED;
739 }
740
741 static NTSTATUS pdb_ads_update_login_attempts(struct pdb_methods *m,
742                                               struct samu *sam_acct,
743                                               bool success)
744 {
745         return NT_STATUS_NOT_IMPLEMENTED;
746 }
747
748 static NTSTATUS pdb_ads_getgrfilter(struct pdb_methods *m, GROUP_MAP *map,
749                                     const char *filter,
750                                     TALLOC_CTX *mem_ctx,
751                                     struct tldap_message **pmsg)
752 {
753         struct pdb_ads_state *state = talloc_get_type_abort(
754                 m->private_data, struct pdb_ads_state);
755         const char *attrs[4] = { "objectSid", "description", "samAccountName",
756                                  "groupType" };
757         char *str;
758         struct tldap_message **group;
759         uint32_t grouptype;
760         int rc;
761
762         rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
763                                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
764                                 &group, "%s", filter);
765         if (rc != TLDAP_SUCCESS) {
766                 DEBUG(10, ("ldap_search failed %s\n",
767                            tldap_errstr(talloc_tos(), state->ld, rc)));
768                 return NT_STATUS_LDAP(rc);
769         }
770         if (talloc_array_length(group) != 1) {
771                 DEBUG(10, ("Expected 1 group, got %d\n",
772                            (int)talloc_array_length(group)));
773                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
774         }
775
776         if (!tldap_pull_binsid(group[0], "objectSid", &map->sid)) {
777                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
778         }
779         map->gid = pdb_ads_sid2gid(&map->sid);
780
781         if (!tldap_pull_uint32(group[0], "groupType", &grouptype)) {
782                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
783         }
784         switch (grouptype) {
785         case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
786         case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
787                 map->sid_name_use = SID_NAME_ALIAS;
788                 break;
789         case GTYPE_SECURITY_GLOBAL_GROUP:
790                 map->sid_name_use = SID_NAME_DOM_GRP;
791                 break;
792         default:
793                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
794         }
795
796         str = tldap_talloc_single_attribute(group[0], "samAccountName",
797                                             talloc_tos());
798         if (str == NULL) {
799                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
800         }
801         fstrcpy(map->nt_name, str);
802         TALLOC_FREE(str);
803
804         str = tldap_talloc_single_attribute(group[0], "description",
805                                             talloc_tos());
806         if (str != NULL) {
807                 fstrcpy(map->comment, str);
808                 TALLOC_FREE(str);
809         } else {
810                 map->comment[0] = '\0';
811         }
812
813         if (pmsg != NULL) {
814                 *pmsg = talloc_move(mem_ctx, &group[0]);
815         }
816         TALLOC_FREE(group);
817         return NT_STATUS_OK;
818 }
819
820 static NTSTATUS pdb_ads_getgrsid(struct pdb_methods *m, GROUP_MAP *map,
821                                  struct dom_sid sid)
822 {
823         char *filter;
824         NTSTATUS status;
825
826         filter = talloc_asprintf(talloc_tos(),
827                                  "(&(objectsid=%s)(objectclass=group))",
828                                  sid_string_talloc(talloc_tos(), &sid));
829         if (filter == NULL) {
830                 return NT_STATUS_NO_MEMORY;
831         }
832
833         status = pdb_ads_getgrfilter(m, map, filter, NULL, NULL);
834         TALLOC_FREE(filter);
835         return status;
836 }
837
838 static NTSTATUS pdb_ads_getgrgid(struct pdb_methods *m, GROUP_MAP *map,
839                                  gid_t gid)
840 {
841         struct dom_sid sid;
842         pdb_ads_gid_to_sid(m, gid, &sid);
843         return pdb_ads_getgrsid(m, map, sid);
844 }
845
846 static NTSTATUS pdb_ads_getgrnam(struct pdb_methods *m, GROUP_MAP *map,
847                                  const char *name)
848 {
849         char *filter;
850         NTSTATUS status;
851
852         filter = talloc_asprintf(talloc_tos(),
853                                  "(&(samaccountname=%s)(objectclass=group))",
854                                  name);
855         if (filter == NULL) {
856                 return NT_STATUS_NO_MEMORY;
857         }
858
859         status = pdb_ads_getgrfilter(m, map, filter, NULL, NULL);
860         TALLOC_FREE(filter);
861         return status;
862 }
863
864 static NTSTATUS pdb_ads_create_dom_group(struct pdb_methods *m,
865                                          TALLOC_CTX *mem_ctx, const char *name,
866                                          uint32 *rid)
867 {
868         TALLOC_CTX *frame = talloc_stackframe();
869         struct pdb_ads_state *state = talloc_get_type_abort(
870                 m->private_data, struct pdb_ads_state);
871         struct tldap_context *ld;
872         const char *attrs[1] = { "objectSid" };
873         int num_mods = 0;
874         struct tldap_mod *mods = NULL;
875         struct tldap_message **alias;
876         struct dom_sid sid;
877         char *dn;
878         int rc;
879         bool ok = true;
880
881         ld = pdb_ads_ld(state);
882         if (ld == NULL) {
883                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
884         }
885
886         dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
887                              state->domaindn);
888         if (dn == NULL) {
889                 TALLOC_FREE(frame);
890                 return NT_STATUS_NO_MEMORY;
891         }
892
893         ok &= tldap_make_mod_fmt(
894                 NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
895                 name);
896         ok &= tldap_make_mod_fmt(
897                 NULL, talloc_tos(), &mods, &num_mods, "objectClass", "group");
898         ok &= tldap_make_mod_fmt(
899                 NULL, talloc_tos(), &mods, &num_mods, "groupType",
900                 "%d", (int)GTYPE_SECURITY_GLOBAL_GROUP);
901
902         if (!ok) {
903                 TALLOC_FREE(frame);
904                 return NT_STATUS_NO_MEMORY;
905         }
906
907         rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
908         if (rc != TLDAP_SUCCESS) {
909                 DEBUG(10, ("ldap_add failed %s\n",
910                            tldap_errstr(talloc_tos(), state->ld, rc)));
911                 TALLOC_FREE(frame);
912                 return NT_STATUS_LDAP(rc);
913         }
914
915         rc = pdb_ads_search_fmt(
916                 state, state->domaindn, TLDAP_SCOPE_SUB,
917                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
918                 "(&(objectclass=group)(samaccountname=%s))", name);
919         if (rc != TLDAP_SUCCESS) {
920                 DEBUG(10, ("Could not find just created alias %s: %s\n",
921                            name, tldap_errstr(talloc_tos(), state->ld, rc)));
922                 TALLOC_FREE(frame);
923                 return NT_STATUS_LDAP(rc);
924         }
925
926         if (talloc_array_length(alias) != 1) {
927                 DEBUG(10, ("Got %d alias, expected one\n",
928                            (int)talloc_array_length(alias)));
929                 TALLOC_FREE(frame);
930                 return NT_STATUS_LDAP(rc);
931         }
932
933         if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
934                 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
935                            name));
936                 TALLOC_FREE(frame);
937                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
938         }
939
940         sid_peek_rid(&sid, rid);
941         TALLOC_FREE(frame);
942         return NT_STATUS_OK;
943 }
944
945 static NTSTATUS pdb_ads_delete_dom_group(struct pdb_methods *m,
946                                          TALLOC_CTX *mem_ctx, uint32 rid)
947 {
948         struct pdb_ads_state *state = talloc_get_type_abort(
949                 m->private_data, struct pdb_ads_state);
950         struct tldap_context *ld;
951         struct dom_sid sid;
952         char *sidstr;
953         struct tldap_message **msg;
954         char *dn;
955         int rc;
956
957         sid_compose(&sid, &state->domainsid, rid);
958
959         sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), &sid);
960         NT_STATUS_HAVE_NO_MEMORY(sidstr);
961
962         rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
963                                 NULL, 0, 0, talloc_tos(), &msg,
964                                 ("(&(objectSid=%s)(objectClass=group))"),
965                                 sidstr);
966         TALLOC_FREE(sidstr);
967         if (rc != TLDAP_SUCCESS) {
968                 DEBUG(10, ("ldap_search failed %s\n",
969                            tldap_errstr(talloc_tos(), state->ld, rc)));
970                 return NT_STATUS_LDAP(rc);
971         }
972
973         switch talloc_array_length(msg) {
974         case 0:
975                 return NT_STATUS_NO_SUCH_GROUP;
976         case 1:
977                 break;
978         default:
979                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
980         }
981
982         if (!tldap_entry_dn(msg[0], &dn)) {
983                 TALLOC_FREE(msg);
984                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
985         }
986
987         ld = pdb_ads_ld(state);
988         if (ld == NULL) {
989                 TALLOC_FREE(msg);
990                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
991         }
992
993         rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
994         TALLOC_FREE(msg);
995         if (rc != TLDAP_SUCCESS) {
996                 DEBUG(10, ("ldap_delete failed: %s\n",
997                            tldap_errstr(talloc_tos(), state->ld, rc)));
998                 return NT_STATUS_LDAP(rc);
999         }
1000
1001         return NT_STATUS_OK;
1002 }
1003
1004 static NTSTATUS pdb_ads_add_group_mapping_entry(struct pdb_methods *m,
1005                                                 GROUP_MAP *map)
1006 {
1007         return NT_STATUS_NOT_IMPLEMENTED;
1008 }
1009
1010 static NTSTATUS pdb_ads_update_group_mapping_entry(struct pdb_methods *m,
1011                                                    GROUP_MAP *map)
1012 {
1013         struct pdb_ads_state *state = talloc_get_type_abort(
1014                 m->private_data, struct pdb_ads_state);
1015         struct tldap_context *ld;
1016         struct tldap_mod *mods = NULL;
1017         char *filter;
1018         struct tldap_message *existing;
1019         char *dn;
1020         GROUP_MAP existing_map;
1021         int rc, num_mods = 0;
1022         bool ret;
1023         NTSTATUS status;
1024
1025         ld = pdb_ads_ld(state);
1026         if (ld == NULL) {
1027                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1028         }
1029
1030         filter = talloc_asprintf(talloc_tos(),
1031                                  "(&(objectsid=%s)(objectclass=group))",
1032                                  sid_string_talloc(talloc_tos(), &map->sid));
1033         if (filter == NULL) {
1034                 return NT_STATUS_NO_MEMORY;
1035         }
1036         status = pdb_ads_getgrfilter(m, &existing_map, filter,
1037                                      talloc_tos(), &existing);
1038         TALLOC_FREE(filter);
1039
1040         if (!tldap_entry_dn(existing, &dn)) {
1041                 return NT_STATUS_LDAP(TLDAP_DECODING_ERROR);
1042         }
1043
1044         ret = true;
1045
1046         ret &= tldap_make_mod_fmt(
1047                 existing, talloc_tos(), &mods, &num_mods, "description",
1048                 "%s", map->comment);
1049         ret &= tldap_make_mod_fmt(
1050                 existing, talloc_tos(), &mods, &num_mods, "samaccountname",
1051                 "%s", map->nt_name);
1052
1053         if (!ret) {
1054                 return NT_STATUS_NO_MEMORY;
1055         }
1056
1057         if (num_mods == 0) {
1058                 TALLOC_FREE(existing);
1059                 return NT_STATUS_OK;
1060         }
1061
1062         rc = tldap_modify(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
1063         if (rc != TLDAP_SUCCESS) {
1064                 DEBUG(10, ("ldap_modify for %s failed: %s\n", dn,
1065                            tldap_errstr(talloc_tos(), ld, rc)));
1066                 TALLOC_FREE(existing);
1067                 return NT_STATUS_LDAP(rc);
1068         }
1069         TALLOC_FREE(existing);
1070         return NT_STATUS_OK;
1071 }
1072
1073 static NTSTATUS pdb_ads_delete_group_mapping_entry(struct pdb_methods *m,
1074                                                    struct dom_sid sid)
1075 {
1076         return NT_STATUS_NOT_IMPLEMENTED;
1077 }
1078
1079 static NTSTATUS pdb_ads_enum_group_mapping(struct pdb_methods *m,
1080                                            const struct dom_sid *sid,
1081                                            enum lsa_SidType sid_name_use,
1082                                            GROUP_MAP **pp_rmap,
1083                                            size_t *p_num_entries,
1084                                            bool unix_only)
1085 {
1086         return NT_STATUS_NOT_IMPLEMENTED;
1087 }
1088
1089 static NTSTATUS pdb_ads_enum_group_members(struct pdb_methods *m,
1090                                            TALLOC_CTX *mem_ctx,
1091                                            const struct dom_sid *group,
1092                                            uint32 **pmembers,
1093                                            size_t *pnum_members)
1094 {
1095         struct pdb_ads_state *state = talloc_get_type_abort(
1096                 m->private_data, struct pdb_ads_state);
1097         const char *attrs[1] = { "member" };
1098         char *sidstr;
1099         struct tldap_message **msg;
1100         int i, rc, num_members;
1101         DATA_BLOB *blobs;
1102         uint32_t *members;
1103
1104         sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), group);
1105         NT_STATUS_HAVE_NO_MEMORY(sidstr);
1106
1107         rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1108                                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1109                                 &msg, "(objectsid=%s)", sidstr);
1110         TALLOC_FREE(sidstr);
1111         if (rc != TLDAP_SUCCESS) {
1112                 DEBUG(10, ("ldap_search failed %s\n",
1113                            tldap_errstr(talloc_tos(), state->ld, rc)));
1114                 return NT_STATUS_LDAP(rc);
1115         }
1116         switch talloc_array_length(msg) {
1117         case 0:
1118                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1119                 break;
1120         case 1:
1121                 break;
1122         default:
1123                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1124                 break;
1125         }
1126
1127         if (!tldap_entry_values(msg[0], "member", &blobs, &num_members)) {
1128                 *pmembers = NULL;
1129                 *pnum_members = 0;
1130                 return NT_STATUS_OK;
1131         }
1132
1133         members = talloc_array(mem_ctx, uint32_t, num_members);
1134         if (members == NULL) {
1135                 return NT_STATUS_NO_MEMORY;
1136         }
1137
1138         for (i=0; i<num_members; i++) {
1139                 struct dom_sid sid;
1140                 if (!pdb_ads_dnblob2sid(state, &blobs[i], &sid)
1141                     || !sid_peek_rid(&sid, &members[i])) {
1142                         TALLOC_FREE(members);
1143                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1144                 }
1145         }
1146
1147         *pmembers = members;
1148         *pnum_members = num_members;
1149         return NT_STATUS_OK;
1150 }
1151
1152 static NTSTATUS pdb_ads_enum_group_memberships(struct pdb_methods *m,
1153                                                TALLOC_CTX *mem_ctx,
1154                                                struct samu *user,
1155                                                struct dom_sid **pp_sids,
1156                                                gid_t **pp_gids,
1157                                                uint32_t *p_num_groups)
1158 {
1159         struct pdb_ads_state *state = talloc_get_type_abort(
1160                 m->private_data, struct pdb_ads_state);
1161         struct pdb_ads_samu_private *priv;
1162         const char *attrs[1] = { "objectSid" };
1163         struct tldap_message **groups;
1164         int i, rc, count;
1165         size_t num_groups;
1166         struct dom_sid *group_sids;
1167         gid_t *gids;
1168
1169         priv = pdb_ads_get_samu_private(m, user);
1170         if (priv != NULL) {
1171                 rc = pdb_ads_search_fmt(
1172                         state, state->domaindn, TLDAP_SCOPE_SUB,
1173                         attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &groups,
1174                         "(&(member=%s)(grouptype=%d)(objectclass=group))",
1175                         priv->dn, GTYPE_SECURITY_GLOBAL_GROUP);
1176                 if (rc != TLDAP_SUCCESS) {
1177                         DEBUG(10, ("ldap_search failed %s\n",
1178                                    tldap_errstr(talloc_tos(), state->ld, rc)));
1179                         return NT_STATUS_LDAP(rc);
1180                 }
1181                 count = talloc_array_length(groups);
1182         } else {
1183                 /*
1184                  * This happens for artificial samu users
1185                  */
1186                 DEBUG(10, ("Could not get pdb_ads_samu_private\n"));
1187                 count = 0;
1188         }
1189
1190         group_sids = talloc_array(mem_ctx, struct dom_sid, count+1);
1191         if (group_sids == NULL) {
1192                 return NT_STATUS_NO_MEMORY;
1193         }
1194         gids = talloc_array(mem_ctx, gid_t, count+1);
1195         if (gids == NULL) {
1196                 TALLOC_FREE(group_sids);
1197                 return NT_STATUS_NO_MEMORY;
1198         }
1199
1200         sid_copy(&group_sids[0], pdb_get_group_sid(user));
1201         if (!sid_to_gid(&group_sids[0], &gids[0])) {
1202                 TALLOC_FREE(gids);
1203                 TALLOC_FREE(group_sids);
1204                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1205         }
1206         num_groups = 1;
1207
1208         for (i=0; i<count; i++) {
1209                 if (!tldap_pull_binsid(groups[i], "objectSid",
1210                                        &group_sids[num_groups])) {
1211                         continue;
1212                 }
1213                 gids[num_groups] = pdb_ads_sid2gid(&group_sids[num_groups]);
1214
1215                 num_groups += 1;
1216                 if (num_groups == count) {
1217                         break;
1218                 }
1219         }
1220
1221         *pp_sids = group_sids;
1222         *pp_gids = gids;
1223         *p_num_groups = num_groups;
1224         return NT_STATUS_OK;
1225 }
1226
1227 static NTSTATUS pdb_ads_set_unix_primary_group(struct pdb_methods *m,
1228                                                TALLOC_CTX *mem_ctx,
1229                                                struct samu *user)
1230 {
1231         return NT_STATUS_NOT_IMPLEMENTED;
1232 }
1233
1234 static NTSTATUS pdb_ads_mod_groupmem(struct pdb_methods *m,
1235                                      TALLOC_CTX *mem_ctx,
1236                                      uint32 grouprid, uint32 memberrid,
1237                                      int mod_op)
1238 {
1239         struct pdb_ads_state *state = talloc_get_type_abort(
1240                 m->private_data, struct pdb_ads_state);
1241         TALLOC_CTX *frame = talloc_stackframe();
1242         struct tldap_context *ld;
1243         struct dom_sid groupsid, membersid;
1244         char *groupdn, *memberdn;
1245         struct tldap_mod *mods;
1246         int num_mods;
1247         int rc;
1248         NTSTATUS status;
1249
1250         ld = pdb_ads_ld(state);
1251         if (ld == NULL) {
1252                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1253         }
1254
1255         sid_compose(&groupsid, &state->domainsid, grouprid);
1256         sid_compose(&membersid, &state->domainsid, memberrid);
1257
1258         status = pdb_ads_sid2dn(state, &groupsid, talloc_tos(), &groupdn);
1259         if (!NT_STATUS_IS_OK(status)) {
1260                 TALLOC_FREE(frame);
1261                 return NT_STATUS_NO_SUCH_GROUP;
1262         }
1263         status = pdb_ads_sid2dn(state, &membersid, talloc_tos(), &memberdn);
1264         if (!NT_STATUS_IS_OK(status)) {
1265                 TALLOC_FREE(frame);
1266                 return NT_STATUS_NO_SUCH_USER;
1267         }
1268
1269         mods = NULL;
1270         num_mods = 0;
1271
1272         if (!tldap_add_mod_str(talloc_tos(), &mods, &num_mods, mod_op,
1273                                "member", memberdn)) {
1274                 TALLOC_FREE(frame);
1275                 return NT_STATUS_NO_MEMORY;
1276         }
1277
1278         rc = tldap_modify(ld, groupdn, mods, num_mods, NULL, 0, NULL, 0);
1279         TALLOC_FREE(frame);
1280         if (rc != TLDAP_SUCCESS) {
1281                 DEBUG(10, ("ldap_modify failed: %s\n",
1282                            tldap_errstr(talloc_tos(), state->ld, rc)));
1283                 if ((mod_op == TLDAP_MOD_ADD) &&
1284                     (rc == TLDAP_ALREADY_EXISTS)) {
1285                         return NT_STATUS_MEMBER_IN_GROUP;
1286                 }
1287                 if ((mod_op == TLDAP_MOD_DELETE) &&
1288                     (rc == TLDAP_UNWILLING_TO_PERFORM)) {
1289                         return NT_STATUS_MEMBER_NOT_IN_GROUP;
1290                 }
1291                 return NT_STATUS_LDAP(rc);
1292         }
1293
1294         return NT_STATUS_OK;
1295 }
1296
1297 static NTSTATUS pdb_ads_add_groupmem(struct pdb_methods *m,
1298                                      TALLOC_CTX *mem_ctx,
1299                                      uint32 group_rid, uint32 member_rid)
1300 {
1301         return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1302                                     TLDAP_MOD_ADD);
1303 }
1304
1305 static NTSTATUS pdb_ads_del_groupmem(struct pdb_methods *m,
1306                                      TALLOC_CTX *mem_ctx,
1307                                      uint32 group_rid, uint32 member_rid)
1308 {
1309         return pdb_ads_mod_groupmem(m, mem_ctx, group_rid, member_rid,
1310                                     TLDAP_MOD_DELETE);
1311 }
1312
1313 static NTSTATUS pdb_ads_create_alias(struct pdb_methods *m,
1314                                      const char *name, uint32 *rid)
1315 {
1316         TALLOC_CTX *frame = talloc_stackframe();
1317         struct pdb_ads_state *state = talloc_get_type_abort(
1318                 m->private_data, struct pdb_ads_state);
1319         struct tldap_context *ld;
1320         const char *attrs[1] = { "objectSid" };
1321         int num_mods = 0;
1322         struct tldap_mod *mods = NULL;
1323         struct tldap_message **alias;
1324         struct dom_sid sid;
1325         char *dn;
1326         int rc;
1327         bool ok = true;
1328
1329         ld = pdb_ads_ld(state);
1330         if (ld == NULL) {
1331                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1332         }
1333
1334         dn = talloc_asprintf(talloc_tos(), "cn=%s,cn=users,%s", name,
1335                              state->domaindn);
1336         if (dn == NULL) {
1337                 TALLOC_FREE(frame);
1338                 return NT_STATUS_NO_MEMORY;
1339         }
1340
1341         ok &= tldap_make_mod_fmt(
1342                 NULL, talloc_tos(), &mods, &num_mods, "samAccountName", "%s",
1343                 name);
1344         ok &= tldap_make_mod_fmt(
1345                 NULL, talloc_tos(), &mods, &num_mods, "objectClass", "group");
1346         ok &= tldap_make_mod_fmt(
1347                 NULL, talloc_tos(), &mods, &num_mods, "groupType",
1348                 "%d", (int)GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1349
1350         if (!ok) {
1351                 TALLOC_FREE(frame);
1352                 return NT_STATUS_NO_MEMORY;
1353         }
1354
1355         rc = tldap_add(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
1356         if (rc != TLDAP_SUCCESS) {
1357                 DEBUG(10, ("ldap_add failed %s\n",
1358                            tldap_errstr(talloc_tos(), state->ld, rc)));
1359                 TALLOC_FREE(frame);
1360                 return NT_STATUS_LDAP(rc);
1361         }
1362
1363         rc = pdb_ads_search_fmt(
1364                 state, state->domaindn, TLDAP_SCOPE_SUB,
1365                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &alias,
1366                 "(&(objectclass=group)(samaccountname=%s))", name);
1367         if (rc != TLDAP_SUCCESS) {
1368                 DEBUG(10, ("Could not find just created alias %s: %s\n",
1369                            name, tldap_errstr(talloc_tos(), state->ld, rc)));
1370                 TALLOC_FREE(frame);
1371                 return NT_STATUS_LDAP(rc);
1372         }
1373
1374         if (talloc_array_length(alias) != 1) {
1375                 DEBUG(10, ("Got %d alias, expected one\n",
1376                            (int)talloc_array_length(alias)));
1377                 TALLOC_FREE(frame);
1378                 return NT_STATUS_LDAP(rc);
1379         }
1380
1381         if (!tldap_pull_binsid(alias[0], "objectSid", &sid)) {
1382                 DEBUG(10, ("Could not fetch objectSid from alias %s\n",
1383                            name));
1384                 TALLOC_FREE(frame);
1385                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1386         }
1387
1388         sid_peek_rid(&sid, rid);
1389         TALLOC_FREE(frame);
1390         return NT_STATUS_OK;
1391 }
1392
1393 static NTSTATUS pdb_ads_delete_alias(struct pdb_methods *m,
1394                                      const struct dom_sid *sid)
1395 {
1396         struct pdb_ads_state *state = talloc_get_type_abort(
1397                 m->private_data, struct pdb_ads_state);
1398         struct tldap_context *ld;
1399         struct tldap_message **alias;
1400         char *sidstr, *dn = NULL;
1401         int rc;
1402
1403         ld = pdb_ads_ld(state);
1404         if (ld == NULL) {
1405                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1406         }
1407
1408         sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
1409         if (sidstr == NULL) {
1410                 return NT_STATUS_NO_MEMORY;
1411         }
1412
1413         rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1414                                 NULL, 0, 0, talloc_tos(), &alias,
1415                                 "(&(objectSid=%s)(objectclass=group)"
1416                                 "(|(grouptype=%d)(grouptype=%d)))",
1417                                 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1418                                 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1419         TALLOC_FREE(sidstr);
1420         if (rc != TLDAP_SUCCESS) {
1421                 DEBUG(10, ("ldap_search failed: %s\n",
1422                            tldap_errstr(talloc_tos(), state->ld, rc)));
1423                 return NT_STATUS_LDAP(rc);
1424         }
1425         if (talloc_array_length(alias) != 1) {
1426                 DEBUG(10, ("Expected 1 alias, got %d\n",
1427                            (int)talloc_array_length(alias)));
1428                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1429         }
1430         if (!tldap_entry_dn(alias[0], &dn)) {
1431                 DEBUG(10, ("Could not get DN for alias %s\n",
1432                            sid_string_dbg(sid)));
1433                 return NT_STATUS_INTERNAL_ERROR;
1434         }
1435
1436         rc = tldap_delete(ld, dn, NULL, 0, NULL, 0);
1437         if (rc != TLDAP_SUCCESS) {
1438                 DEBUG(10, ("ldap_delete failed: %s\n",
1439                            tldap_errstr(talloc_tos(), state->ld, rc)));
1440                 return NT_STATUS_LDAP(rc);
1441         }
1442
1443         return NT_STATUS_OK;
1444 }
1445
1446 static NTSTATUS pdb_ads_set_aliasinfo(struct pdb_methods *m,
1447                                       const struct dom_sid *sid,
1448                                       struct acct_info *info)
1449 {
1450         struct pdb_ads_state *state = talloc_get_type_abort(
1451                 m->private_data, struct pdb_ads_state);
1452         struct tldap_context *ld;
1453         const char *attrs[3] = { "objectSid", "description",
1454                                  "samAccountName" };
1455         struct tldap_message **msg;
1456         char *sidstr, *dn;
1457         int rc;
1458         struct tldap_mod *mods;
1459         int num_mods;
1460         bool ok;
1461
1462         ld = pdb_ads_ld(state);
1463         if (ld == NULL) {
1464                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1465         }
1466
1467         sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
1468         NT_STATUS_HAVE_NO_MEMORY(sidstr);
1469
1470         rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1471                                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1472                                 &msg, "(&(objectSid=%s)(objectclass=group)"
1473                                 "(|(grouptype=%d)(grouptype=%d)))",
1474                                 sidstr, GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1475                                 GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1476         TALLOC_FREE(sidstr);
1477         if (rc != TLDAP_SUCCESS) {
1478                 DEBUG(10, ("ldap_search failed %s\n",
1479                            tldap_errstr(talloc_tos(), state->ld, rc)));
1480                 return NT_STATUS_LDAP(rc);
1481         }
1482         switch talloc_array_length(msg) {
1483         case 0:
1484                 return NT_STATUS_NO_SUCH_ALIAS;
1485         case 1:
1486                 break;
1487         default:
1488                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1489         }
1490
1491         if (!tldap_entry_dn(msg[0], &dn)) {
1492                 TALLOC_FREE(msg);
1493                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1494         }
1495
1496         mods = NULL;
1497         num_mods = 0;
1498         ok = true;
1499
1500         ok &= tldap_make_mod_fmt(
1501                 msg[0], msg, &mods, &num_mods, "description",
1502                 "%s", info->acct_desc);
1503         ok &= tldap_make_mod_fmt(
1504                 msg[0], msg, &mods, &num_mods, "samAccountName",
1505                 "%s", info->acct_name);
1506         if (!ok) {
1507                 TALLOC_FREE(msg);
1508                 return NT_STATUS_NO_MEMORY;
1509         }
1510         if (num_mods == 0) {
1511                 /* no change */
1512                 TALLOC_FREE(msg);
1513                 return NT_STATUS_OK;
1514         }
1515
1516         rc = tldap_modify(ld, dn, mods, num_mods, NULL, 0, NULL, 0);
1517         TALLOC_FREE(msg);
1518         if (rc != TLDAP_SUCCESS) {
1519                 DEBUG(10, ("ldap_modify failed: %s\n",
1520                            tldap_errstr(talloc_tos(), state->ld, rc)));
1521                 return NT_STATUS_LDAP(rc);
1522         }
1523         return NT_STATUS_OK;
1524 }
1525
1526 static NTSTATUS pdb_ads_sid2dn(struct pdb_ads_state *state,
1527                                const struct dom_sid *sid,
1528                                TALLOC_CTX *mem_ctx, char **pdn)
1529 {
1530         struct tldap_message **msg;
1531         char *sidstr, *dn;
1532         int rc;
1533
1534         sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), sid);
1535         NT_STATUS_HAVE_NO_MEMORY(sidstr);
1536
1537         rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1538                                 NULL, 0, 0, talloc_tos(), &msg,
1539                                 "(objectsid=%s)", sidstr);
1540         TALLOC_FREE(sidstr);
1541         if (rc != TLDAP_SUCCESS) {
1542                 DEBUG(10, ("ldap_search failed %s\n",
1543                            tldap_errstr(talloc_tos(), state->ld, rc)));
1544                 return NT_STATUS_LDAP(rc);
1545         }
1546
1547         switch talloc_array_length(msg) {
1548         case 0:
1549                 return NT_STATUS_NOT_FOUND;
1550         case 1:
1551                 break;
1552         default:
1553                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1554         }
1555
1556         if (!tldap_entry_dn(msg[0], &dn)) {
1557                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1558         }
1559
1560         dn = talloc_strdup(mem_ctx, dn);
1561         if (dn == NULL) {
1562                 return NT_STATUS_NO_MEMORY;
1563         }
1564         TALLOC_FREE(msg);
1565
1566         *pdn = dn;
1567         return NT_STATUS_OK;
1568 }
1569
1570 static NTSTATUS pdb_ads_mod_aliasmem(struct pdb_methods *m,
1571                                      const struct dom_sid *alias,
1572                                      const struct dom_sid *member,
1573                                      int mod_op)
1574 {
1575         struct pdb_ads_state *state = talloc_get_type_abort(
1576                 m->private_data, struct pdb_ads_state);
1577         struct tldap_context *ld;
1578         TALLOC_CTX *frame = talloc_stackframe();
1579         struct tldap_mod *mods;
1580         int num_mods;
1581         int rc;
1582         char *aliasdn, *memberdn;
1583         NTSTATUS status;
1584
1585         ld = pdb_ads_ld(state);
1586         if (ld == NULL) {
1587                 return NT_STATUS_LDAP(TLDAP_SERVER_DOWN);
1588         }
1589
1590         status = pdb_ads_sid2dn(state, alias, talloc_tos(), &aliasdn);
1591         if (!NT_STATUS_IS_OK(status)) {
1592                 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1593                            sid_string_dbg(alias), nt_errstr(status)));
1594                 TALLOC_FREE(frame);
1595                 return NT_STATUS_NO_SUCH_ALIAS;
1596         }
1597         status = pdb_ads_sid2dn(state, member, talloc_tos(), &memberdn);
1598         if (!NT_STATUS_IS_OK(status)) {
1599                 DEBUG(10, ("pdb_ads_sid2dn (%s) failed: %s\n",
1600                            sid_string_dbg(member), nt_errstr(status)));
1601                 TALLOC_FREE(frame);
1602                 return status;
1603         }
1604
1605         mods = NULL;
1606         num_mods = 0;
1607
1608         if (!tldap_add_mod_str(talloc_tos(), &mods, &num_mods, mod_op,
1609                                "member", memberdn)) {
1610                 TALLOC_FREE(frame);
1611                 return NT_STATUS_NO_MEMORY;
1612         }
1613
1614         rc = tldap_modify(ld, aliasdn, mods, num_mods, NULL, 0, NULL, 0);
1615         TALLOC_FREE(frame);
1616         if (rc != TLDAP_SUCCESS) {
1617                 DEBUG(10, ("ldap_modify failed: %s\n",
1618                            tldap_errstr(talloc_tos(), state->ld, rc)));
1619                 if (rc == TLDAP_TYPE_OR_VALUE_EXISTS) {
1620                         return NT_STATUS_MEMBER_IN_ALIAS;
1621                 }
1622                 if (rc == TLDAP_NO_SUCH_ATTRIBUTE) {
1623                         return NT_STATUS_MEMBER_NOT_IN_ALIAS;
1624                 }
1625                 return NT_STATUS_LDAP(rc);
1626         }
1627
1628         return NT_STATUS_OK;
1629 }
1630
1631 static NTSTATUS pdb_ads_add_aliasmem(struct pdb_methods *m,
1632                                      const struct dom_sid *alias,
1633                                      const struct dom_sid *member)
1634 {
1635         return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_ADD);
1636 }
1637
1638 static NTSTATUS pdb_ads_del_aliasmem(struct pdb_methods *m,
1639                                      const struct dom_sid *alias,
1640                                      const struct dom_sid *member)
1641 {
1642         return pdb_ads_mod_aliasmem(m, alias, member, TLDAP_MOD_DELETE);
1643 }
1644
1645 static bool pdb_ads_dnblob2sid(struct pdb_ads_state *state, DATA_BLOB *dnblob,
1646                                struct dom_sid *psid)
1647 {
1648         const char *attrs[1] = { "objectSid" };
1649         struct tldap_message **msg;
1650         char *dn;
1651         size_t len;
1652         int rc;
1653         bool ret;
1654
1655         if (!convert_string_talloc(talloc_tos(), CH_UTF8, CH_UNIX,
1656                                    dnblob->data, dnblob->length, &dn, &len)) {
1657                 return false;
1658         }
1659         rc = pdb_ads_search_fmt(state, dn, TLDAP_SCOPE_BASE,
1660                                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1661                                 &msg, "(objectclass=*)");
1662         TALLOC_FREE(dn);
1663         if (talloc_array_length(msg) != 1) {
1664                 DEBUG(10, ("Got %d objects, expected one\n",
1665                            (int)talloc_array_length(msg)));
1666                 TALLOC_FREE(msg);
1667                 return false;
1668         }
1669
1670         ret = tldap_pull_binsid(msg[0], "objectSid", psid);
1671         TALLOC_FREE(msg);
1672         return ret;
1673 }
1674
1675 static NTSTATUS pdb_ads_enum_aliasmem(struct pdb_methods *m,
1676                                       const struct dom_sid *alias,
1677                                       TALLOC_CTX *mem_ctx,
1678                                       struct dom_sid **pmembers,
1679                                       size_t *pnum_members)
1680 {
1681         struct pdb_ads_state *state = talloc_get_type_abort(
1682                 m->private_data, struct pdb_ads_state);
1683         const char *attrs[1] = { "member" };
1684         char *sidstr;
1685         struct tldap_message **msg;
1686         int i, rc, num_members;
1687         DATA_BLOB *blobs;
1688         struct dom_sid *members;
1689
1690         sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), alias);
1691         NT_STATUS_HAVE_NO_MEMORY(sidstr);
1692
1693         rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1694                                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1695                                 &msg, "(objectsid=%s)", sidstr);
1696         TALLOC_FREE(sidstr);
1697         if (rc != TLDAP_SUCCESS) {
1698                 DEBUG(10, ("ldap_search failed %s\n",
1699                            tldap_errstr(talloc_tos(), state->ld, rc)));
1700                 return NT_STATUS_LDAP(rc);
1701         }
1702         switch talloc_array_length(msg) {
1703         case 0:
1704                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1705                 break;
1706         case 1:
1707                 break;
1708         default:
1709                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1710                 break;
1711         }
1712
1713         if (!tldap_entry_values(msg[0], "member", &blobs, &num_members)) {
1714                 *pmembers = NULL;
1715                 *pnum_members = 0;
1716                 return NT_STATUS_OK;
1717         }
1718
1719         members = talloc_array(mem_ctx, struct dom_sid, num_members);
1720         if (members == NULL) {
1721                 return NT_STATUS_NO_MEMORY;
1722         }
1723
1724         for (i=0; i<num_members; i++) {
1725                 if (!pdb_ads_dnblob2sid(state, &blobs[i], &members[i])) {
1726                         TALLOC_FREE(members);
1727                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1728                 }
1729         }
1730
1731         *pmembers = members;
1732         *pnum_members = num_members;
1733         return NT_STATUS_OK;
1734 }
1735
1736 static NTSTATUS pdb_ads_enum_alias_memberships(struct pdb_methods *m,
1737                                                TALLOC_CTX *mem_ctx,
1738                                                const struct dom_sid *domain_sid,
1739                                                const struct dom_sid *members,
1740                                                size_t num_members,
1741                                                uint32_t **palias_rids,
1742                                                size_t *pnum_alias_rids)
1743 {
1744         struct pdb_ads_state *state = talloc_get_type_abort(
1745                 m->private_data, struct pdb_ads_state);
1746         const char *attrs[1] = { "objectSid" };
1747         struct tldap_message **msg = NULL;
1748         uint32_t *alias_rids = NULL;
1749         size_t num_alias_rids = 0;
1750         int i, rc, count;
1751         bool got_members = false;
1752         char *filter;
1753         NTSTATUS status;
1754
1755         /*
1756          * TODO: Get the filter right so that we only get the aliases from
1757          * either the SAM or BUILTIN
1758          */
1759
1760         filter = talloc_asprintf(talloc_tos(),
1761                                  "(&(|(grouptype=%d)(grouptype=%d))"
1762                                  "(objectclass=group)(|",
1763                                  GTYPE_SECURITY_BUILTIN_LOCAL_GROUP,
1764                                  GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
1765         if (filter == NULL) {
1766                 return NT_STATUS_NO_MEMORY;
1767         }
1768
1769         for (i=0; i<num_members; i++) {
1770                 char *dn;
1771
1772                 status = pdb_ads_sid2dn(state, &members[i], talloc_tos(), &dn);
1773                 if (!NT_STATUS_IS_OK(status)) {
1774                         DEBUG(10, ("pdb_ads_sid2dn failed for %s: %s\n",
1775                                    sid_string_dbg(&members[i]),
1776                                    nt_errstr(status)));
1777                         continue;
1778                 }
1779                 filter = talloc_asprintf_append_buffer(
1780                         filter, "(member=%s)", dn);
1781                 TALLOC_FREE(dn);
1782                 if (filter == NULL) {
1783                         return NT_STATUS_NO_MEMORY;
1784                 }
1785                 got_members = true;
1786         }
1787
1788         if (!got_members) {
1789                 goto done;
1790         }
1791
1792         rc = pdb_ads_search_fmt(state, state->domaindn, TLDAP_SCOPE_SUB,
1793                                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(),
1794                                 &msg, "%s))", filter);
1795         TALLOC_FREE(filter);
1796         if (rc != TLDAP_SUCCESS) {
1797                 DEBUG(10, ("tldap_search failed %s\n",
1798                            tldap_errstr(talloc_tos(), state->ld, rc)));
1799                 return NT_STATUS_LDAP(rc);
1800         }
1801
1802         count = talloc_array_length(msg);
1803         if (count == 0) {
1804                 goto done;
1805         }
1806
1807         alias_rids = talloc_array(mem_ctx, uint32_t, count);
1808         if (alias_rids == NULL) {
1809                 TALLOC_FREE(msg);
1810                 return NT_STATUS_NO_MEMORY;
1811         }
1812
1813         for (i=0; i<count; i++) {
1814                 struct dom_sid sid;
1815
1816                 if (!tldap_pull_binsid(msg[i], "objectSid", &sid)) {
1817                         DEBUG(10, ("Could not pull SID for member %d\n", i));
1818                         continue;
1819                 }
1820                 if (sid_peek_check_rid(domain_sid, &sid,
1821                                        &alias_rids[num_alias_rids])) {
1822                         num_alias_rids += 1;
1823                 }
1824         }
1825 done:
1826         TALLOC_FREE(msg);
1827         *palias_rids = alias_rids;
1828         *pnum_alias_rids = 0;
1829         return NT_STATUS_OK;
1830 }
1831
1832 static NTSTATUS pdb_ads_lookup_rids(struct pdb_methods *m,
1833                                     const struct dom_sid *domain_sid,
1834                                     int num_rids,
1835                                     uint32 *rids,
1836                                     const char **names,
1837                                     enum lsa_SidType *lsa_attrs)
1838 {
1839         struct pdb_ads_state *state = talloc_get_type_abort(
1840                 m->private_data, struct pdb_ads_state);
1841         const char *attrs[2] = { "sAMAccountType", "sAMAccountName" };
1842         int i, num_mapped;
1843
1844         if (num_rids == 0) {
1845                 return NT_STATUS_NONE_MAPPED;
1846         }
1847
1848         num_mapped = 0;
1849
1850         for (i=0; i<num_rids; i++) {
1851                 struct dom_sid sid;
1852                 struct tldap_message **msg;
1853                 char *sidstr;
1854                 uint32_t attr;
1855                 int rc;
1856
1857                 lsa_attrs[i] = SID_NAME_UNKNOWN;
1858
1859                 sid_compose(&sid, domain_sid, rids[i]);
1860
1861                 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), &sid);
1862                 NT_STATUS_HAVE_NO_MEMORY(sidstr);
1863
1864                 rc = pdb_ads_search_fmt(state, state->domaindn,
1865                                         TLDAP_SCOPE_SUB, attrs,
1866                                         ARRAY_SIZE(attrs), 0, talloc_tos(),
1867                                         &msg, "(objectsid=%s)", sidstr);
1868                 TALLOC_FREE(sidstr);
1869                 if (rc != TLDAP_SUCCESS) {
1870                         DEBUG(10, ("ldap_search failed %s\n",
1871                                    tldap_errstr(talloc_tos(), state->ld, rc)));
1872                         continue;
1873                 }
1874
1875                 switch talloc_array_length(msg) {
1876                 case 0:
1877                         DEBUG(10, ("rid %d not found\n", (int)rids[i]));
1878                         continue;
1879                 case 1:
1880                         break;
1881                 default:
1882                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1883                 }
1884
1885                 names[i] = tldap_talloc_single_attribute(
1886                         msg[0], "samAccountName", talloc_tos());
1887                 if (names[i] == NULL) {
1888                         DEBUG(10, ("no samAccountName\n"));
1889                         continue;
1890                 }
1891                 if (!tldap_pull_uint32(msg[0], "samAccountType", &attr)) {
1892                         DEBUG(10, ("no samAccountType"));
1893                         continue;
1894                 }
1895                 lsa_attrs[i] = ds_atype_map(attr);
1896                 num_mapped += 1;
1897         }
1898
1899         if (num_mapped == 0) {
1900                 return NT_STATUS_NONE_MAPPED;
1901         }
1902         if (num_mapped < num_rids) {
1903                 return STATUS_SOME_UNMAPPED;
1904         }
1905         return NT_STATUS_OK;
1906 }
1907
1908 static NTSTATUS pdb_ads_lookup_names(struct pdb_methods *m,
1909                                      const struct dom_sid *domain_sid,
1910                                      int num_names,
1911                                      const char **pp_names,
1912                                      uint32 *rids,
1913                                      enum lsa_SidType *attrs)
1914 {
1915         return NT_STATUS_NOT_IMPLEMENTED;
1916 }
1917
1918 static NTSTATUS pdb_ads_get_account_policy(struct pdb_methods *m,
1919                                            enum pdb_policy_type type,
1920                                            uint32_t *value)
1921 {
1922         return account_policy_get(type, value)
1923                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1924 }
1925
1926 static NTSTATUS pdb_ads_set_account_policy(struct pdb_methods *m,
1927                                            enum pdb_policy_type type,
1928                                            uint32_t value)
1929 {
1930         return account_policy_set(type, value)
1931                 ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
1932 }
1933
1934 static NTSTATUS pdb_ads_get_seq_num(struct pdb_methods *m,
1935                                     time_t *seq_num)
1936 {
1937         return NT_STATUS_NOT_IMPLEMENTED;
1938 }
1939
1940 struct pdb_ads_search_state {
1941         uint32_t acct_flags;
1942         struct samr_displayentry *entries;
1943         uint32_t num_entries;
1944         ssize_t array_size;
1945         uint32_t current;
1946 };
1947
1948 static bool pdb_ads_next_entry(struct pdb_search *search,
1949                                struct samr_displayentry *entry)
1950 {
1951         struct pdb_ads_search_state *state = talloc_get_type_abort(
1952                 search->private_data, struct pdb_ads_search_state);
1953
1954         if (state->current == state->num_entries) {
1955                 return false;
1956         }
1957
1958         entry->idx = state->entries[state->current].idx;
1959         entry->rid = state->entries[state->current].rid;
1960         entry->acct_flags = state->entries[state->current].acct_flags;
1961
1962         entry->account_name = talloc_strdup(
1963                 search, state->entries[state->current].account_name);
1964         entry->fullname = talloc_strdup(
1965                 search, state->entries[state->current].fullname);
1966         entry->description = talloc_strdup(
1967                 search, state->entries[state->current].description);
1968
1969         if ((entry->account_name == NULL) || (entry->fullname == NULL)
1970             || (entry->description == NULL)) {
1971                 DEBUG(0, ("talloc_strdup failed\n"));
1972                 return false;
1973         }
1974
1975         state->current += 1;
1976         return true;
1977 }
1978
1979 static void pdb_ads_search_end(struct pdb_search *search)
1980 {
1981         struct pdb_ads_search_state *state = talloc_get_type_abort(
1982                 search->private_data, struct pdb_ads_search_state);
1983         TALLOC_FREE(state);
1984 }
1985
1986 static bool pdb_ads_search_filter(struct pdb_methods *m,
1987                                   struct pdb_search *search,
1988                                   const char *filter,
1989                                   uint32_t acct_flags,
1990                                   struct pdb_ads_search_state **pstate)
1991 {
1992         struct pdb_ads_state *state = talloc_get_type_abort(
1993                 m->private_data, struct pdb_ads_state);
1994         struct pdb_ads_search_state *sstate;
1995         const char * attrs[] = { "objectSid", "sAMAccountName", "displayName",
1996                                  "userAccountControl", "description" };
1997         struct tldap_message **users;
1998         int i, rc, num_users;
1999
2000         sstate = talloc_zero(search, struct pdb_ads_search_state);
2001         if (sstate == NULL) {
2002                 return false;
2003         }
2004         sstate->acct_flags = acct_flags;
2005
2006         rc = pdb_ads_search_fmt(
2007                 state, state->domaindn, TLDAP_SCOPE_SUB,
2008                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &users,
2009                 "%s", filter);
2010         if (rc != TLDAP_SUCCESS) {
2011                 DEBUG(10, ("ldap_search_ext_s failed: %s\n",
2012                            tldap_errstr(talloc_tos(), state->ld, rc)));
2013                 return false;
2014         }
2015
2016         num_users = talloc_array_length(users);
2017
2018         sstate->entries = talloc_array(sstate, struct samr_displayentry,
2019                                        num_users);
2020         if (sstate->entries == NULL) {
2021                 DEBUG(10, ("talloc failed\n"));
2022                 return false;
2023         }
2024
2025         sstate->num_entries = 0;
2026
2027         for (i=0; i<num_users; i++) {
2028                 struct samr_displayentry *e;
2029                 struct dom_sid sid;
2030                 uint32_t ctrl;
2031
2032                 e = &sstate->entries[sstate->num_entries];
2033
2034                 e->idx = sstate->num_entries;
2035                 if (!tldap_pull_binsid(users[i], "objectSid", &sid)) {
2036                         DEBUG(10, ("Could not pull sid\n"));
2037                         continue;
2038                 }
2039                 sid_peek_rid(&sid, &e->rid);
2040
2041                 if (tldap_pull_uint32(users[i], "userAccountControl", &ctrl)) {
2042
2043                         e->acct_flags = ds_uf2acb(ctrl);
2044
2045                         DEBUG(10, ("pdb_ads_search_filter: Found %x, "
2046                                    "filter %x\n", (int)e->acct_flags,
2047                                    (int)sstate->acct_flags));
2048
2049
2050                         if ((sstate->acct_flags != 0) &&
2051                             ((sstate->acct_flags & e->acct_flags) == 0)) {
2052                                 continue;
2053                         }
2054
2055                         if (e->acct_flags & (ACB_WSTRUST|ACB_SVRTRUST)) {
2056                                 e->acct_flags |= ACB_NORMAL;
2057                         }
2058                 } else {
2059                         e->acct_flags = ACB_NORMAL;
2060                 }
2061
2062                 if (e->rid == DOMAIN_RID_GUEST) {
2063                         /*
2064                          * Guest is specially crafted in s3. Make
2065                          * QueryDisplayInfo match QueryUserInfo
2066                          */
2067                         e->account_name = lp_guestaccount();
2068                         e->fullname = lp_guestaccount();
2069                         e->description = "";
2070                         e->acct_flags = ACB_NORMAL;
2071                 } else {
2072                         e->account_name = tldap_talloc_single_attribute(
2073                                 users[i], "samAccountName", sstate->entries);
2074                         e->fullname = tldap_talloc_single_attribute(
2075                                 users[i], "displayName", sstate->entries);
2076                         e->description = tldap_talloc_single_attribute(
2077                                 users[i], "description", sstate->entries);
2078                 }
2079                 if (e->account_name == NULL) {
2080                         return false;
2081                 }
2082                 if (e->fullname == NULL) {
2083                         e->fullname = "";
2084                 }
2085                 if (e->description == NULL) {
2086                         e->description = "";
2087                 }
2088
2089                 sstate->num_entries += 1;
2090                 if (sstate->num_entries >= num_users) {
2091                         break;
2092                 }
2093         }
2094
2095         search->private_data = sstate;
2096         search->next_entry = pdb_ads_next_entry;
2097         search->search_end = pdb_ads_search_end;
2098         *pstate = sstate;
2099         return true;
2100 }
2101
2102 static bool pdb_ads_search_users(struct pdb_methods *m,
2103                                  struct pdb_search *search,
2104                                  uint32 acct_flags)
2105 {
2106         struct pdb_ads_search_state *sstate;
2107         char *filter;
2108         bool ret;
2109
2110         DEBUG(10, ("pdb_ads_search_users got flags %x\n", acct_flags));
2111
2112         if (acct_flags & ACB_NORMAL) {
2113                 filter = talloc_asprintf(
2114                         talloc_tos(),
2115                         "(&(objectclass=user)(sAMAccountType=%d))",
2116                         ATYPE_NORMAL_ACCOUNT);
2117         } else if (acct_flags & ACB_WSTRUST) {
2118                 filter = talloc_asprintf(
2119                         talloc_tos(),
2120                         "(&(objectclass=user)(sAMAccountType=%d))",
2121                         ATYPE_WORKSTATION_TRUST);
2122         } else {
2123                 filter = talloc_strdup(talloc_tos(), "(objectclass=user)");
2124         }
2125         if (filter == NULL) {
2126                 return false;
2127         }
2128
2129         ret = pdb_ads_search_filter(m, search, filter, acct_flags, &sstate);
2130         TALLOC_FREE(filter);
2131         if (!ret) {
2132                 return false;
2133         }
2134         return true;
2135 }
2136
2137 static bool pdb_ads_search_groups(struct pdb_methods *m,
2138                                   struct pdb_search *search)
2139 {
2140         struct pdb_ads_search_state *sstate;
2141         char *filter;
2142         bool ret;
2143
2144         filter = talloc_asprintf(talloc_tos(),
2145                                  "(&(grouptype=%d)(objectclass=group))",
2146                                  GTYPE_SECURITY_GLOBAL_GROUP);
2147         if (filter == NULL) {
2148                 return false;
2149         }
2150         ret = pdb_ads_search_filter(m, search, filter, 0, &sstate);
2151         TALLOC_FREE(filter);
2152         if (!ret) {
2153                 return false;
2154         }
2155         return true;
2156 }
2157
2158 static bool pdb_ads_search_aliases(struct pdb_methods *m,
2159                                    struct pdb_search *search,
2160                                    const struct dom_sid *sid)
2161 {
2162         struct pdb_ads_search_state *sstate;
2163         char *filter;
2164         bool ret;
2165
2166         filter = talloc_asprintf(
2167                 talloc_tos(), "(&(grouptype=%d)(objectclass=group))",
2168                 sid_check_is_builtin(sid)
2169                 ? GTYPE_SECURITY_BUILTIN_LOCAL_GROUP
2170                 : GTYPE_SECURITY_DOMAIN_LOCAL_GROUP);
2171
2172         if (filter == NULL) {
2173                 return false;
2174         }
2175         ret = pdb_ads_search_filter(m, search, filter, 0, &sstate);
2176         TALLOC_FREE(filter);
2177         if (!ret) {
2178                 return false;
2179         }
2180         return true;
2181 }
2182
2183 static bool pdb_ads_uid_to_sid(struct pdb_methods *m, uid_t uid,
2184                                struct dom_sid *sid)
2185 {
2186         struct pdb_ads_state *state = talloc_get_type_abort(
2187                 m->private_data, struct pdb_ads_state);
2188         sid_compose(sid, &state->domainsid, uid);
2189         return true;
2190 }
2191
2192 static bool pdb_ads_gid_to_sid(struct pdb_methods *m, gid_t gid,
2193                                struct dom_sid *sid)
2194 {
2195         struct pdb_ads_state *state = talloc_get_type_abort(
2196                 m->private_data, struct pdb_ads_state);
2197         sid_compose(sid, &state->domainsid, gid);
2198         return true;
2199 }
2200
2201 static bool pdb_ads_sid_to_id(struct pdb_methods *m, const struct dom_sid *sid,
2202                               union unid_t *id, enum lsa_SidType *type)
2203 {
2204         struct pdb_ads_state *state = talloc_get_type_abort(
2205                 m->private_data, struct pdb_ads_state);
2206         const char *attrs[4] = { "objectClass", "samAccountType",
2207                                  "uidNumber", "gidNumber" };
2208         struct tldap_message **msg;
2209         char *sidstr, *base;
2210         uint32_t atype;
2211         int rc;
2212         bool ret = false;
2213
2214         sidstr = sid_binstring_hex(sid);
2215         if (sidstr == NULL) {
2216                 return false;
2217         }
2218         base = talloc_asprintf(talloc_tos(), "<SID=%s>", sidstr);
2219         SAFE_FREE(sidstr);
2220
2221         rc = pdb_ads_search_fmt(
2222                 state, base, TLDAP_SCOPE_BASE,
2223                 attrs, ARRAY_SIZE(attrs), 0, talloc_tos(), &msg,
2224                 "(objectclass=*)");
2225         TALLOC_FREE(base);
2226
2227         if (rc != TLDAP_SUCCESS) {
2228                 DEBUG(10, ("pdb_ads_search_fmt failed: %s\n",
2229                            tldap_errstr(talloc_tos(), state->ld, rc)));
2230                 return false;
2231         }
2232         if (talloc_array_length(msg) != 1) {
2233                 DEBUG(10, ("Got %d objects, expected 1\n",
2234                            (int)talloc_array_length(msg)));
2235                 goto fail;
2236         }
2237         if (!tldap_pull_uint32(msg[0], "samAccountType", &atype)) {
2238                 DEBUG(10, ("samAccountType not found\n"));
2239                 goto fail;
2240         }
2241         if (atype == ATYPE_ACCOUNT) {
2242                 uint32_t uid;
2243                 *type = SID_NAME_USER;
2244                 if (!tldap_pull_uint32(msg[0], "uidNumber", &uid)) {
2245                         DEBUG(10, ("Did not find uidNumber\n"));
2246                         goto fail;
2247                 }
2248                 id->uid = uid;
2249         } else {
2250                 uint32_t gid;
2251                 *type = SID_NAME_DOM_GRP;
2252                 if (!tldap_pull_uint32(msg[0], "gidNumber", &gid)) {
2253                         DEBUG(10, ("Did not find gidNumber\n"));
2254                         goto fail;
2255                 }
2256                 id->gid = gid;
2257         }
2258         ret = true;
2259 fail:
2260         TALLOC_FREE(msg);
2261         return ret;
2262 }
2263
2264 static uint32_t pdb_ads_capabilities(struct pdb_methods *m)
2265 {
2266         return PDB_CAP_STORE_RIDS | PDB_CAP_ADS;
2267 }
2268
2269 static bool pdb_ads_new_rid(struct pdb_methods *m, uint32 *rid)
2270 {
2271         return false;
2272 }
2273
2274 static bool pdb_ads_get_trusteddom_pw(struct pdb_methods *m,
2275                                       const char *domain, char** pwd,
2276                                       struct dom_sid *sid,
2277                                       time_t *pass_last_set_time)
2278 {
2279         return false;
2280 }
2281
2282 static bool pdb_ads_set_trusteddom_pw(struct pdb_methods *m,
2283                                       const char* domain, const char* pwd,
2284                                       const struct dom_sid *sid)
2285 {
2286         return false;
2287 }
2288
2289 static bool pdb_ads_del_trusteddom_pw(struct pdb_methods *m,
2290                                       const char *domain)
2291 {
2292         return false;
2293 }
2294
2295 static NTSTATUS pdb_ads_enum_trusteddoms(struct pdb_methods *m,
2296                                          TALLOC_CTX *mem_ctx,
2297                                          uint32 *num_domains,
2298                                          struct trustdom_info ***domains)
2299 {
2300         *num_domains = 0;
2301         *domains = NULL;
2302         return NT_STATUS_OK;
2303 }
2304
2305 static void pdb_ads_init_methods(struct pdb_methods *m)
2306 {
2307         m->name = "ads";
2308         m->get_domain_info = pdb_ads_get_domain_info;
2309         m->getsampwnam = pdb_ads_getsampwnam;
2310         m->getsampwsid = pdb_ads_getsampwsid;
2311         m->create_user = pdb_ads_create_user;
2312         m->delete_user = pdb_ads_delete_user;
2313         m->add_sam_account = pdb_ads_add_sam_account;
2314         m->update_sam_account = pdb_ads_update_sam_account;
2315         m->delete_sam_account = pdb_ads_delete_sam_account;
2316         m->rename_sam_account = pdb_ads_rename_sam_account;
2317         m->update_login_attempts = pdb_ads_update_login_attempts;
2318         m->getgrsid = pdb_ads_getgrsid;
2319         m->getgrgid = pdb_ads_getgrgid;
2320         m->getgrnam = pdb_ads_getgrnam;
2321         m->create_dom_group = pdb_ads_create_dom_group;
2322         m->delete_dom_group = pdb_ads_delete_dom_group;
2323         m->add_group_mapping_entry = pdb_ads_add_group_mapping_entry;
2324         m->update_group_mapping_entry = pdb_ads_update_group_mapping_entry;
2325         m->delete_group_mapping_entry = pdb_ads_delete_group_mapping_entry;
2326         m->enum_group_mapping = pdb_ads_enum_group_mapping;
2327         m->enum_group_members = pdb_ads_enum_group_members;
2328         m->enum_group_memberships = pdb_ads_enum_group_memberships;
2329         m->set_unix_primary_group = pdb_ads_set_unix_primary_group;
2330         m->add_groupmem = pdb_ads_add_groupmem;
2331         m->del_groupmem = pdb_ads_del_groupmem;
2332         m->create_alias = pdb_ads_create_alias;
2333         m->delete_alias = pdb_ads_delete_alias;
2334         m->get_aliasinfo = pdb_default_get_aliasinfo;
2335         m->set_aliasinfo = pdb_ads_set_aliasinfo;
2336         m->add_aliasmem = pdb_ads_add_aliasmem;
2337         m->del_aliasmem = pdb_ads_del_aliasmem;
2338         m->enum_aliasmem = pdb_ads_enum_aliasmem;
2339         m->enum_alias_memberships = pdb_ads_enum_alias_memberships;
2340         m->lookup_rids = pdb_ads_lookup_rids;
2341         m->lookup_names = pdb_ads_lookup_names;
2342         m->get_account_policy = pdb_ads_get_account_policy;
2343         m->set_account_policy = pdb_ads_set_account_policy;
2344         m->get_seq_num = pdb_ads_get_seq_num;
2345         m->search_users = pdb_ads_search_users;
2346         m->search_groups = pdb_ads_search_groups;
2347         m->search_aliases = pdb_ads_search_aliases;
2348         m->uid_to_sid = pdb_ads_uid_to_sid;
2349         m->gid_to_sid = pdb_ads_gid_to_sid;
2350         m->sid_to_id = pdb_ads_sid_to_id;
2351         m->capabilities = pdb_ads_capabilities;
2352         m->new_rid = pdb_ads_new_rid;
2353         m->get_trusteddom_pw = pdb_ads_get_trusteddom_pw;
2354         m->set_trusteddom_pw = pdb_ads_set_trusteddom_pw;
2355         m->del_trusteddom_pw = pdb_ads_del_trusteddom_pw;
2356         m->enum_trusteddoms = pdb_ads_enum_trusteddoms;
2357 }
2358
2359 static void free_private_data(void **vp)
2360 {
2361         struct pdb_ads_state *state = talloc_get_type_abort(
2362                 *vp, struct pdb_ads_state);
2363
2364         TALLOC_FREE(state->ld);
2365         return;
2366 }
2367
2368 /*
2369   this is used to catch debug messages from events
2370 */
2371 static void s3_tldap_debug(void *context, enum tldap_debug_level level,
2372                            const char *fmt, va_list ap)  PRINTF_ATTRIBUTE(3,0);
2373
2374 static void s3_tldap_debug(void *context, enum tldap_debug_level level,
2375                            const char *fmt, va_list ap)
2376 {
2377         int samba_level = -1;
2378         char *s = NULL;
2379         switch (level) {
2380         case TLDAP_DEBUG_FATAL:
2381                 samba_level = 0;
2382                 break;
2383         case TLDAP_DEBUG_ERROR:
2384                 samba_level = 1;
2385                 break;
2386         case TLDAP_DEBUG_WARNING:
2387                 samba_level = 2;
2388                 break;
2389         case TLDAP_DEBUG_TRACE:
2390                 samba_level = 11;
2391                 break;
2392
2393         };
2394         if (vasprintf(&s, fmt, ap) == -1) {
2395                 return;
2396         }
2397         DEBUG(samba_level, ("tldap: %s", s));
2398         free(s);
2399 }
2400
2401 static struct tldap_context *pdb_ads_ld(struct pdb_ads_state *state)
2402 {
2403         NTSTATUS status;
2404         int fd;
2405
2406         if (tldap_connection_ok(state->ld)) {
2407                 return state->ld;
2408         }
2409         TALLOC_FREE(state->ld);
2410
2411         status = open_socket_out(
2412                 (struct sockaddr_storage *)(void *)&state->socket_address,
2413                 0, 0, &fd);
2414         if (!NT_STATUS_IS_OK(status)) {
2415                 DEBUG(10, ("Could not connect to %s: %s\n",
2416                            state->socket_address.sun_path, nt_errstr(status)));
2417                 return NULL;
2418         }
2419
2420         set_blocking(fd, false);
2421
2422         state->ld = tldap_context_create(state, fd);
2423         if (state->ld == NULL) {
2424                 close(fd);
2425                 return NULL;
2426         }
2427         tldap_set_debug(state->ld, s3_tldap_debug, NULL);
2428
2429         return state->ld;
2430 }
2431
2432 int pdb_ads_search_fmt(struct pdb_ads_state *state, const char *base,
2433                        int scope, const char *attrs[], int num_attrs,
2434                        int attrsonly,
2435                        TALLOC_CTX *mem_ctx, struct tldap_message ***res,
2436                        const char *fmt, ...)
2437 {
2438         struct tldap_context *ld;
2439         va_list ap;
2440         int ret;
2441
2442         ld = pdb_ads_ld(state);
2443         if (ld == NULL) {
2444                 return TLDAP_SERVER_DOWN;
2445         }
2446
2447         va_start(ap, fmt);
2448         ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly,
2449                               mem_ctx, res, fmt, ap);
2450         va_end(ap);
2451
2452         if (ret != TLDAP_SERVER_DOWN) {
2453                 return ret;
2454         }
2455
2456         /* retry once */
2457         ld = pdb_ads_ld(state);
2458         if (ld == NULL) {
2459                 return TLDAP_SERVER_DOWN;
2460         }
2461
2462         va_start(ap, fmt);
2463         ret = tldap_search_va(ld, base, scope, attrs, num_attrs, attrsonly,
2464                               mem_ctx, res, fmt, ap);
2465         va_end(ap);
2466         return ret;
2467 }
2468
2469 static NTSTATUS pdb_ads_connect(struct pdb_ads_state *state,
2470                                 const char *location)
2471 {
2472         const char *domain_attrs[2] = { "objectSid", "objectGUID" };
2473         const char *ncname_attrs[1] = { "netbiosname" };
2474         struct tldap_context *ld;
2475         struct tldap_message *rootdse, **domain, **ncname;
2476         TALLOC_CTX *frame = talloc_stackframe();
2477         NTSTATUS status;
2478         int num_domains;
2479         int rc;
2480
2481         ZERO_STRUCT(state->socket_address);
2482         state->socket_address.sun_family = AF_UNIX;
2483         strlcpy(state->socket_address.sun_path, location,
2484                 sizeof(state->socket_address.sun_path));
2485
2486         ld = pdb_ads_ld(state);
2487         if (ld == NULL) {
2488                 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
2489                 goto done;
2490         }
2491
2492         rc = tldap_fetch_rootdse(ld);
2493         if (rc != TLDAP_SUCCESS) {
2494                 DEBUG(10, ("Could not retrieve rootdse: %s\n",
2495                            tldap_errstr(talloc_tos(), state->ld, rc)));
2496                 status = NT_STATUS_LDAP(rc);
2497                 goto done;
2498         }
2499         rootdse = tldap_rootdse(state->ld);
2500
2501         state->domaindn = tldap_talloc_single_attribute(
2502                 rootdse, "defaultNamingContext", state);
2503         if (state->domaindn == NULL) {
2504                 DEBUG(10, ("Could not get defaultNamingContext\n"));
2505                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2506                 goto done;
2507         }
2508         DEBUG(10, ("defaultNamingContext = %s\n", state->domaindn));
2509
2510         state->configdn = tldap_talloc_single_attribute(
2511                 rootdse, "configurationNamingContext", state);
2512         if (state->configdn == NULL) {
2513                 DEBUG(10, ("Could not get configurationNamingContext\n"));
2514                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2515                 goto done;
2516         }
2517         DEBUG(10, ("configurationNamingContext = %s\n", state->configdn));
2518
2519         /*
2520          * Figure out our domain's SID
2521          */
2522         rc = pdb_ads_search_fmt(
2523                 state, state->domaindn, TLDAP_SCOPE_BASE,
2524                 domain_attrs, ARRAY_SIZE(domain_attrs), 0,
2525                 talloc_tos(), &domain, "(objectclass=*)");
2526         if (rc != TLDAP_SUCCESS) {
2527                 DEBUG(10, ("Could not retrieve domain: %s\n",
2528                            tldap_errstr(talloc_tos(), state->ld, rc)));
2529                 status = NT_STATUS_LDAP(rc);
2530                 goto done;
2531         }
2532
2533         num_domains = talloc_array_length(domain);
2534         if (num_domains != 1) {
2535                 DEBUG(10, ("Got %d domains, expected one\n", num_domains));
2536                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2537                 goto done;
2538         }
2539         if (!tldap_pull_binsid(domain[0], "objectSid", &state->domainsid)) {
2540                 DEBUG(10, ("Could not retrieve domain SID\n"));
2541                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2542                 goto done;
2543         }
2544         if (!tldap_pull_guid(domain[0], "objectGUID", &state->domainguid)) {
2545                 DEBUG(10, ("Could not retrieve domain GUID\n"));
2546                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2547                 goto done;
2548         }
2549         DEBUG(10, ("Domain SID: %s\n", sid_string_dbg(&state->domainsid)));
2550
2551         /*
2552          * Figure out our domain's short name
2553          */
2554         rc = pdb_ads_search_fmt(
2555                 state, state->configdn, TLDAP_SCOPE_SUB,
2556                 ncname_attrs, ARRAY_SIZE(ncname_attrs), 0,
2557                 talloc_tos(), &ncname, "(ncname=%s)", state->domaindn);
2558         if (rc != TLDAP_SUCCESS) {
2559                 DEBUG(10, ("Could not retrieve ncname: %s\n",
2560                            tldap_errstr(talloc_tos(), state->ld, rc)));
2561                 status = NT_STATUS_LDAP(rc);
2562                 goto done;
2563         }
2564         if (talloc_array_length(ncname) != 1) {
2565                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2566                 goto done;
2567         }
2568
2569         state->netbiosname = tldap_talloc_single_attribute(
2570                 ncname[0], "netbiosname", state);
2571         if (state->netbiosname == NULL) {
2572                 DEBUG(10, ("Could not get netbiosname\n"));
2573                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
2574                 goto done;
2575         }
2576         DEBUG(10, ("netbiosname: %s\n", state->netbiosname));
2577
2578         if (!strequal(lp_workgroup(), state->netbiosname)) {
2579                 DEBUG(1, ("ADS is different domain (%s) than ours (%s)\n",
2580                           state->netbiosname, lp_workgroup()));
2581                 status = NT_STATUS_NO_SUCH_DOMAIN;
2582                 goto done;
2583         }
2584
2585         secrets_store_domain_sid(state->netbiosname, &state->domainsid);
2586
2587         status = NT_STATUS_OK;
2588 done:
2589         TALLOC_FREE(frame);
2590         return status;
2591 }
2592
2593 static NTSTATUS pdb_init_ads(struct pdb_methods **pdb_method,
2594                              const char *location)
2595 {
2596         struct pdb_methods *m;
2597         struct pdb_ads_state *state;
2598         char *tmp = NULL;
2599         NTSTATUS status;
2600
2601         m = talloc(NULL, struct pdb_methods);
2602         if (m == NULL) {
2603                 return NT_STATUS_NO_MEMORY;
2604         }
2605         state = talloc_zero(m, struct pdb_ads_state);
2606         if (state == NULL) {
2607                 goto nomem;
2608         }
2609         m->private_data = state;
2610         m->free_private_data = free_private_data;
2611         pdb_ads_init_methods(m);
2612
2613         if (location == NULL) {
2614                 tmp = talloc_asprintf(talloc_tos(), "/%s/ldap_priv/ldapi",
2615                                       lp_private_dir());
2616                 location = tmp;
2617         }
2618         if (location == NULL) {
2619                 goto nomem;
2620         }
2621
2622         status = pdb_ads_connect(state, location);
2623         if (!NT_STATUS_IS_OK(status)) {
2624                 DEBUG(10, ("pdb_ads_connect failed: %s\n", nt_errstr(status)));
2625                 goto fail;
2626         }
2627
2628         *pdb_method = m;
2629         return NT_STATUS_OK;
2630 nomem:
2631         status = NT_STATUS_NO_MEMORY;
2632 fail:
2633         TALLOC_FREE(m);
2634         return status;
2635 }
2636
2637 NTSTATUS pdb_ads_init(void);
2638 NTSTATUS pdb_ads_init(void)
2639 {
2640         return smb_register_passdb(PASSDB_INTERFACE_VERSION, "ads",
2641                                    pdb_init_ads);
2642 }