s4:kdc: Implement KDC plugin hardware authentication policy
[samba.git] / source3 / winbindd / idmap_ad.c
1 /*
2  * idmap_ad: map between Active Directory and RFC 2307 accounts
3  *
4  * Copyright (C) Volker Lendecke 2015
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 "winbindd.h"
22 #include "libsmb/namequery.h"
23 #include "idmap.h"
24 #include "tldap.h"
25 #include "tldap_util.h"
26 #include "tldap_tls_connect.h"
27 #include "tldap_gensec_bind.h"
28 #include "passdb.h"
29 #include "lib/param/param.h"
30 #include "auth/gensec/gensec.h"
31 #include "librpc/gen_ndr/ndr_netlogon.h"
32 #include "libads/ldap_schema_oids.h"
33 #include "../libds/common/flags.h"
34 #include "libcli/ldap/ldap_ndr.h"
35 #include "libcli/security/dom_sid.h"
36 #include "source3/libads/sitename_cache.h"
37 #include "source3/libads/kerberos_proto.h"
38 #include "source3/librpc/gen_ndr/ads.h"
39 #include "source3/lib/global_contexts.h"
40 #include <ldb.h>
41
42 struct idmap_ad_schema_names;
43
44 struct idmap_ad_context {
45         struct idmap_domain *dom;
46         struct tldap_context *ld;
47         struct idmap_ad_schema_names *schema;
48         const char *default_nc;
49
50         bool unix_primary_group;
51         bool unix_nss_info;
52
53         struct ldb_context *ldb;
54         struct ldb_dn **deny_ous;
55         struct ldb_dn **allow_ous;
56 };
57
58 static NTSTATUS idmap_ad_get_context(struct idmap_domain *dom,
59                                      struct idmap_ad_context **pctx);
60
61 static char *get_schema_path(TALLOC_CTX *mem_ctx, struct tldap_context *ld)
62 {
63         struct tldap_message *rootdse;
64
65         rootdse = tldap_rootdse(ld);
66         if (rootdse == NULL) {
67                 return NULL;
68         }
69
70         return tldap_talloc_single_attribute(rootdse, "schemaNamingContext",
71                                              mem_ctx);
72 }
73
74 static char *get_default_nc(TALLOC_CTX *mem_ctx, struct tldap_context *ld)
75 {
76         struct tldap_message *rootdse;
77
78         rootdse = tldap_rootdse(ld);
79         if (rootdse == NULL) {
80                 return NULL;
81         }
82
83         return tldap_talloc_single_attribute(rootdse, "defaultNamingContext",
84                                              mem_ctx);
85 }
86
87 struct idmap_ad_schema_names {
88         char *name;
89         char *uid;
90         char *gid;
91         char *gecos;
92         char *dir;
93         char *shell;
94 };
95
96 static TLDAPRC get_attrnames_by_oids(struct tldap_context *ld,
97                                      TALLOC_CTX *mem_ctx,
98                                      const char *schema_path,
99                                      size_t num_oids,
100                                      const char **oids,
101                                      char **names)
102 {
103         char *filter;
104         const char *attrs[] = { "lDAPDisplayName", "attributeId" };
105         size_t i;
106         TLDAPRC rc;
107         struct tldap_message **msgs;
108         size_t num_msgs;
109
110         filter = talloc_strdup(mem_ctx, "(|");
111
112         for (i=0; i<num_oids; i++) {
113                 talloc_asprintf_addbuf(&filter, "(attributeId=%s)", oids[i]);
114         }
115         talloc_asprintf_addbuf(&filter, ")");
116
117         if (filter == NULL) {
118                 return TLDAP_NO_MEMORY;
119         }
120
121         rc = tldap_search(ld, schema_path, TLDAP_SCOPE_SUB, filter,
122                           attrs, ARRAY_SIZE(attrs), 0, NULL, 0, NULL, 0,
123                           0, 0, 0, mem_ctx, &msgs);;
124         TALLOC_FREE(filter);
125         if (!TLDAP_RC_IS_SUCCESS(rc)) {
126                 return rc;
127         }
128
129         for (i=0; i<num_oids; i++) {
130                 names[i] = NULL;
131         }
132
133         num_msgs = talloc_array_length(msgs);
134
135         for (i=0; i<num_msgs; i++) {
136                 struct tldap_message *msg = msgs[i];
137                 char *oid;
138                 size_t j;
139
140                 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
141                         /* Could be a TLDAP_RES_SEARCH_REFERENCE */
142                         continue;
143                 }
144
145                 oid = tldap_talloc_single_attribute(
146                         msg, "attributeId", msg);
147                 if (oid == NULL) {
148                         continue;
149                 }
150
151                 for (j=0; j<num_oids; j++) {
152                         if (strequal(oid, oids[j])) {
153                                 break;
154                         }
155                 }
156                 TALLOC_FREE(oid);
157
158                 if (j == num_oids) {
159                         /* not found */
160                         continue;
161                 }
162
163                 names[j] = tldap_talloc_single_attribute(
164                         msg, "lDAPDisplayName", mem_ctx);
165         }
166
167         TALLOC_FREE(msgs);
168         for (i=0; i<num_oids; i++) {
169                 if (names[i] == NULL) {
170                         DBG_ERR("Failed to retrieve schema name for "
171                                 "oid [%s]. Schema mode is incorrect "
172                                 "for this domain.\n", oids[i]);
173                         return TLDAP_FILTER_ERROR;
174                 }
175         }
176
177         return TLDAP_SUCCESS;
178 }
179
180 static TLDAPRC get_posix_schema_names(struct tldap_context *ld,
181                                       const char *schema_mode,
182                                       TALLOC_CTX *mem_ctx,
183                                       struct idmap_ad_schema_names **pschema)
184 {
185         char *schema_path;
186         struct idmap_ad_schema_names *schema;
187         char *names[6];
188         const char *oids_sfu[] = {
189                 ADS_ATTR_SFU_UIDNUMBER_OID,
190                 ADS_ATTR_SFU_GIDNUMBER_OID,
191                 ADS_ATTR_SFU_HOMEDIR_OID,
192                 ADS_ATTR_SFU_SHELL_OID,
193                 ADS_ATTR_SFU_GECOS_OID,
194                 ADS_ATTR_SFU_UID_OID
195         };
196         const char *oids_sfu20[] = {
197                 ADS_ATTR_SFU20_UIDNUMBER_OID,
198                 ADS_ATTR_SFU20_GIDNUMBER_OID,
199                 ADS_ATTR_SFU20_HOMEDIR_OID,
200                 ADS_ATTR_SFU20_SHELL_OID,
201                 ADS_ATTR_SFU20_GECOS_OID,
202                 ADS_ATTR_SFU20_UID_OID
203         };
204         const char *oids_rfc2307[] = {
205                 ADS_ATTR_RFC2307_UIDNUMBER_OID,
206                 ADS_ATTR_RFC2307_GIDNUMBER_OID,
207                 ADS_ATTR_RFC2307_HOMEDIR_OID,
208                 ADS_ATTR_RFC2307_SHELL_OID,
209                 ADS_ATTR_RFC2307_GECOS_OID,
210                 ADS_ATTR_RFC2307_UID_OID
211         };
212         const char **oids;
213
214         TLDAPRC rc;
215
216         schema = talloc(mem_ctx, struct idmap_ad_schema_names);
217         if (schema == NULL) {
218                 return TLDAP_NO_MEMORY;
219         }
220
221         schema_path = get_schema_path(schema, ld);
222         if (schema_path == NULL) {
223                 TALLOC_FREE(schema);
224                 return TLDAP_NO_MEMORY;
225         }
226
227         oids = oids_rfc2307;
228
229         if ((schema_mode != NULL) && (schema_mode[0] != '\0')) {
230                 if (strequal(schema_mode, "sfu")) {
231                         oids = oids_sfu;
232                 } else if (strequal(schema_mode, "sfu20")) {
233                         oids = oids_sfu20;
234                 } else if (strequal(schema_mode, "rfc2307" )) {
235                         oids = oids_rfc2307;
236                 } else {
237                         DBG_WARNING("Unknown schema mode %s\n", schema_mode);
238                 }
239         }
240
241         rc = get_attrnames_by_oids(ld, schema, schema_path, 6, oids, names);
242         TALLOC_FREE(schema_path);
243         if (!TLDAP_RC_IS_SUCCESS(rc)) {
244                 TALLOC_FREE(schema);
245                 return rc;
246         }
247
248         schema->uid = names[0];
249         schema->gid = names[1];
250         schema->dir = names[2];
251         schema->shell = names[3];
252         schema->gecos = names[4];
253         schema->name = names[5];
254
255         *pschema = schema;
256
257         return TLDAP_SUCCESS;
258 }
259
260 static void PRINTF_ATTRIBUTE(3, 0) idmap_ad_tldap_debug(
261         void *log_private,
262         enum tldap_debug_level level,
263         const char *fmt,
264         va_list ap)
265 {
266        int samba_level = -1;
267
268        switch (level) {
269        case TLDAP_DEBUG_FATAL:
270                samba_level = DBGLVL_ERR;
271                break;
272        case TLDAP_DEBUG_ERROR:
273                samba_level = DBGLVL_ERR;
274                break;
275        case TLDAP_DEBUG_WARNING:
276                samba_level = DBGLVL_WARNING;
277                break;
278        case TLDAP_DEBUG_TRACE:
279                samba_level = DBGLVL_DEBUG;
280                break;
281        }
282
283        if (CHECK_DEBUGLVL(samba_level)) {
284                char *s = NULL;
285                int ret;
286
287                ret = vasprintf(&s, fmt, ap);
288                if (ret == -1) {
289                        return;
290                }
291                DEBUG(samba_level, ("idmap_ad_tldap: %s", s));
292                free(s);
293        }
294 }
295
296 static NTSTATUS idmap_ad_get_tldap_ctx(TALLOC_CTX *mem_ctx,
297                                        const char *domname,
298                                        struct tldap_context **pld)
299 {
300         struct netr_DsRGetDCNameInfo *dcinfo;
301         struct sockaddr_storage dcaddr;
302         struct winbindd_domain *creds_domain = NULL;
303         struct cli_credentials *creds;
304         struct loadparm_context *lp_ctx;
305         struct tldap_context *ld;
306         int tcp_port = 389;
307         bool use_tls = false;
308         bool use_starttls = false;
309         int wrap_flags = -1;
310         uint32_t gensec_features = 0;
311         char *sitename = NULL;
312         int fd;
313         NTSTATUS status;
314         bool ok;
315         TLDAPRC rc;
316
317         wrap_flags = lp_client_ldap_sasl_wrapping();
318
319         if (wrap_flags & ADS_AUTH_SASL_LDAPS) {
320                 use_tls = true;
321                 tcp_port = 636;
322         } else if (wrap_flags & ADS_AUTH_SASL_STARTTLS) {
323                 use_tls = true;
324                 use_starttls = true;
325         }
326         if (wrap_flags & ADS_AUTH_SASL_SEAL) {
327                 gensec_features |= GENSEC_FEATURE_SEAL;
328         }
329         if (wrap_flags & ADS_AUTH_SASL_SIGN) {
330                 gensec_features |= GENSEC_FEATURE_SIGN;
331         }
332
333         if (gensec_features != 0) {
334                 gensec_features |= GENSEC_FEATURE_LDAP_STYLE;
335         }
336
337         status = wb_dsgetdcname_gencache_get(mem_ctx, domname, &dcinfo);
338         if (!NT_STATUS_IS_OK(status)) {
339                 DBG_DEBUG("Could not get dcinfo for %s: %s\n", domname,
340                           nt_errstr(status));
341                 return status;
342         }
343
344         if (dcinfo->dc_unc == NULL) {
345                 TALLOC_FREE(dcinfo);
346                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
347         }
348         if (dcinfo->dc_unc[0] == '\\') {
349                 dcinfo->dc_unc += 1;
350         }
351         if (dcinfo->dc_unc[0] == '\\') {
352                 dcinfo->dc_unc += 1;
353         }
354
355         ok = resolve_name(dcinfo->dc_unc, &dcaddr, 0x20, true);
356         if (!ok) {
357                 DBG_DEBUG("Could not resolve name %s\n", dcinfo->dc_unc);
358                 TALLOC_FREE(dcinfo);
359                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
360         }
361
362         sitename = sitename_fetch(talloc_tos(), lp_realm());
363
364         /*
365          * create_local_private_krb5_conf_for_domain() can deal with
366          * sitename==NULL
367          */
368
369         ok = create_local_private_krb5_conf_for_domain(
370                 lp_realm(), lp_workgroup(), sitename, &dcaddr);
371         TALLOC_FREE(sitename);
372         if (!ok) {
373                 DBG_DEBUG("Could not create private krb5.conf\n");
374                 TALLOC_FREE(dcinfo);
375                 return NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
376         }
377
378         status = open_socket_out(&dcaddr, tcp_port, 10000, &fd);
379         if (!NT_STATUS_IS_OK(status)) {
380                 DBG_DEBUG("open_socket_out failed: %s\n", nt_errstr(status));
381                 TALLOC_FREE(dcinfo);
382                 return status;
383         }
384
385         ld = tldap_context_create(dcinfo, fd);
386         if (ld == NULL) {
387                 DBG_DEBUG("tldap_context_create failed\n");
388                 close(fd);
389                 TALLOC_FREE(dcinfo);
390                 return NT_STATUS_NO_MEMORY;
391         }
392         tldap_set_debug(ld, idmap_ad_tldap_debug, NULL);
393
394         /*
395          * Here we use or own machine account as
396          * we run as domain member.
397          */
398         creds_domain = find_our_domain();
399         if (creds_domain == NULL) {
400                 DBG_ERR("find_our_domain() returned NULL\n");
401                 TALLOC_FREE(dcinfo);
402                 return NT_STATUS_INTERNAL_ERROR;
403         }
404         status = winbindd_get_trust_credentials(creds_domain,
405                                                 dcinfo,
406                                                 false, /* netlogon */
407                                                 false, /* ipc_fallback */
408                                                 &creds);
409         if (!NT_STATUS_IS_OK(status)) {
410                 DBG_ERR("winbindd_get_trust_credentials(%s) failed - %s\n",
411                         creds_domain->name, nt_errstr(status));
412                 TALLOC_FREE(dcinfo);
413                 return status;
414         }
415
416         lp_ctx = loadparm_init_s3(dcinfo, loadparm_s3_helpers());
417         if (lp_ctx == NULL) {
418                 DBG_DEBUG("loadparm_init_s3 failed\n");
419                 TALLOC_FREE(dcinfo);
420                 return NT_STATUS_NO_MEMORY;
421         }
422
423         if (use_tls && !tldap_has_tls_tstream(ld)) {
424                 tldap_set_starttls_needed(ld, use_starttls);
425
426                 rc = tldap_tls_connect(ld, lp_ctx, dcinfo->dc_unc);
427                 if (!TLDAP_RC_IS_SUCCESS(rc)) {
428                         DBG_ERR("tldap_gensec_bind(%s) failed: %s\n",
429                                 dcinfo->dc_unc,
430                                 tldap_errstr(dcinfo, ld, rc));
431                         TALLOC_FREE(dcinfo);
432                         return NT_STATUS_LDAP(TLDAP_RC_V(rc));
433                 }
434         }
435
436         rc = tldap_gensec_bind(ld, creds, "ldap", dcinfo->dc_unc, NULL, lp_ctx,
437                                gensec_features);
438         if (!TLDAP_RC_IS_SUCCESS(rc)) {
439                 DBG_DEBUG("tldap_gensec_bind failed: %s\n",
440                           tldap_errstr(dcinfo, ld, rc));
441                 TALLOC_FREE(dcinfo);
442                 return NT_STATUS_LDAP(TLDAP_RC_V(rc));
443         }
444
445         rc = tldap_fetch_rootdse(ld);
446         if (!TLDAP_RC_IS_SUCCESS(rc)) {
447                 DBG_DEBUG("tldap_fetch_rootdse failed: %s\n",
448                           tldap_errstr(dcinfo, ld, rc));
449                 TALLOC_FREE(dcinfo);
450                 return NT_STATUS_LDAP(TLDAP_RC_V(rc));
451         }
452
453         *pld = talloc_move(mem_ctx, &ld);
454         TALLOC_FREE(dcinfo);
455         return NT_STATUS_OK;
456 }
457
458 static int idmap_ad_context_destructor(struct idmap_ad_context *ctx)
459 {
460         if ((ctx->dom != NULL) && (ctx->dom->private_data == ctx)) {
461                 ctx->dom->private_data = NULL;
462         }
463         return 0;
464 }
465
466 static struct ldb_dn **str_list_to_dns(TALLOC_CTX *mem_ctx,
467                                        const char *dbgmsg,
468                                        struct ldb_context *ldb,
469                                        const char **strlist)
470 {
471         size_t i, num_dns = str_list_length(strlist);
472         char *dbgstr = NULL;
473         struct ldb_dn **dns = NULL;
474
475         dns = talloc_array(mem_ctx, struct ldb_dn *, num_dns);
476         if (dns == NULL) {
477                 TALLOC_FREE(dbgstr);
478                 return NULL;
479         }
480
481         dbgstr = talloc_strdup(talloc_tos(), "");
482
483         for (i = 0; i < num_dns; i++) {
484                 dns[i] = ldb_dn_new(dns, ldb, strlist[i]);
485                 if (dns[i] == NULL) {
486                         DBG_WARNING("ldb_dn_new(%s) failed\n", strlist[i]);
487                         TALLOC_FREE(dns);
488                         return NULL;
489                 }
490                 talloc_asprintf_addbuf(
491                         &dbgstr,
492                         "%s ",
493                         ldb_dn_get_extended_linearized(dbgstr, dns[i], 1));
494         }
495
496         DBG_DEBUG("%s %s\n", dbgmsg, dbgstr);
497         TALLOC_FREE(dbgstr);
498
499         return dns;
500 }
501
502 static NTSTATUS idmap_ad_context_create(TALLOC_CTX *mem_ctx,
503                                         struct idmap_domain *dom,
504                                         const char *domname,
505                                         struct idmap_ad_context **pctx)
506 {
507         struct idmap_ad_context *ctx;
508         const char *schema_mode;
509         const char **allow = NULL;
510         const char **deny = NULL;
511         NTSTATUS status;
512         TLDAPRC rc;
513
514         ctx = talloc_zero(mem_ctx, struct idmap_ad_context);
515         if (ctx == NULL) {
516                 return NT_STATUS_NO_MEMORY;
517         }
518         ctx->dom = dom;
519
520         talloc_set_destructor(ctx, idmap_ad_context_destructor);
521
522         status = idmap_ad_get_tldap_ctx(ctx, domname, &ctx->ld);
523         if (!NT_STATUS_IS_OK(status)) {
524                 DBG_DEBUG("idmap_ad_get_tldap_ctx failed: %s\n",
525                           nt_errstr(status));
526                 TALLOC_FREE(ctx);
527                 return status;
528         }
529
530         ctx->default_nc = get_default_nc(ctx, ctx->ld);
531         if (ctx->default_nc == NULL) {
532                 DBG_DEBUG("No default nc\n");
533                 TALLOC_FREE(ctx);
534                 return status;
535         }
536
537         ctx->unix_primary_group = idmap_config_bool(
538                 domname, "unix_primary_group", false);
539         ctx->unix_nss_info = idmap_config_bool(
540                 domname, "unix_nss_info", false);
541
542         schema_mode = idmap_config_const_string(
543                 domname, "schema_mode", "rfc2307");
544
545         rc = get_posix_schema_names(ctx->ld, schema_mode, ctx, &ctx->schema);
546         if (!TLDAP_RC_IS_SUCCESS(rc)) {
547                 DBG_DEBUG("get_posix_schema_names failed: %s\n",
548                           tldap_errstr(ctx, ctx->ld, rc));
549                 TALLOC_FREE(ctx);
550                 return NT_STATUS_LDAP(TLDAP_RC_V(rc));
551         }
552
553         deny = idmap_config_string_list(domname, "deny ous", NULL);
554         allow = idmap_config_string_list(domname, "allow ous", NULL);
555
556         if ((deny != NULL) || (allow != NULL)) {
557                 int ret = ldb_global_init();
558                 if (ret == -1) {
559                         status = map_nt_error_from_unix(errno);
560                         DBG_WARNING("ldb_global_init() failed: %s\n",
561                                     strerror(errno));
562                         TALLOC_FREE(ctx);
563                         return status;
564                 }
565
566                 ctx->ldb = ldb_init(ctx, global_event_context());
567                 if (ctx->ldb == NULL) {
568                         status = map_nt_error_from_unix(errno);
569                         DBG_WARNING("ldb_init() failed: %s\n", strerror(errno));
570                         TALLOC_FREE(ctx);
571                         return status;
572                 }
573         }
574
575         if (deny != NULL) {
576                 ctx->deny_ous = str_list_to_dns(ctx, "Denying", ctx->ldb, deny);
577                 if (ctx->deny_ous == NULL) {
578                         DBG_DEBUG("str_list_to_dns failed\n");
579                         TALLOC_FREE(ctx);
580                         return NT_STATUS_NO_MEMORY;
581                 }
582         }
583
584         if (allow != NULL) {
585                 ctx->allow_ous =
586                         str_list_to_dns(ctx, "Allowing", ctx->ldb, allow);
587                 if (ctx->allow_ous == NULL) {
588                         DBG_DEBUG("str_list_to_dns failed\n");
589                         TALLOC_FREE(ctx);
590                         return NT_STATUS_NO_MEMORY;
591                 }
592         }
593
594         *pctx = ctx;
595         return NT_STATUS_OK;
596 }
597
598 static bool check_dn(struct ldb_dn **dns, struct ldb_dn *dn)
599 {
600         size_t i, num_dns = talloc_array_length(dns);
601
602         for (i = 0; i < num_dns; i++) {
603                 struct ldb_dn *base = dns[i];
604                 int ret = ldb_dn_compare_base(base, dn);
605                 if (ret == 0) {
606                         return true;
607                 }
608         }
609         return false;
610 }
611
612 static bool idmap_ad_dn_filter(struct idmap_domain *dom, const char *dnstr)
613 {
614         struct idmap_ad_context *ctx = NULL;
615         struct ldb_dn *dn = NULL;
616         NTSTATUS status;
617         bool result = false;
618
619         status = idmap_ad_get_context(dom, &ctx);
620         if (!NT_STATUS_IS_OK(status)) {
621                 DBG_DEBUG("idmap_ad_get_context failed: %s\n",
622                           nt_errstr(status));
623                 return false;
624         }
625
626         if ((ctx->allow_ous == NULL) && (ctx->deny_ous == NULL)) {
627                 /*
628                  * Nothing to check
629                  */
630                 return true;
631         }
632
633         dn = ldb_dn_new(talloc_tos(), ctx->ldb, dnstr);
634         if (dn == NULL) {
635                 DBG_DEBUG("ldb_dn_new(%s) failed\n", dnstr);
636                 return false;
637         }
638
639         if (ctx->deny_ous != NULL) {
640                 bool denied = check_dn(ctx->deny_ous, dn);
641                 if (denied) {
642                         DBG_WARNING("Denied %s\n", dnstr);
643                         TALLOC_FREE(dn);
644                         return false;
645                 }
646
647                 if (ctx->allow_ous == NULL) {
648                         /*
649                          * Only a few denied OUs around, allow by
650                          * default
651                          */
652                         result = true;
653                 }
654         }
655
656         if (ctx->allow_ous != NULL) {
657                 bool allowed = check_dn(ctx->allow_ous, dn);
658                 if (allowed) {
659                         return true;
660                 }
661                 DBG_WARNING("Did not allow %s\n", dnstr);
662         }
663
664         return result;
665 }
666
667 static NTSTATUS idmap_ad_query_user(struct idmap_domain *domain,
668                                     struct wbint_userinfo *info)
669 {
670         struct idmap_ad_context *ctx;
671         TLDAPRC rc;
672         NTSTATUS status;
673         char *sidstr, *filter;
674         const char *attrs[4];
675         size_t i, num_msgs;
676         struct tldap_message **msgs;
677
678         status = idmap_ad_get_context(domain, &ctx);
679         if (!NT_STATUS_IS_OK(status)) {
680                 return status;
681         }
682
683         if (!(ctx->unix_primary_group || ctx->unix_nss_info)) {
684                 return NT_STATUS_OK;
685         }
686
687         attrs[0] = ctx->schema->gid;
688         attrs[1] = ctx->schema->gecos;
689         attrs[2] = ctx->schema->dir;
690         attrs[3] = ctx->schema->shell;
691
692         sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), &info->user_sid);
693         if (sidstr == NULL) {
694                 return NT_STATUS_NO_MEMORY;
695         }
696
697         filter = talloc_asprintf(talloc_tos(), "(objectsid=%s)", sidstr);
698         TALLOC_FREE(sidstr);
699         if (filter == NULL) {
700                 return NT_STATUS_NO_MEMORY;
701         }
702
703         DBG_DEBUG("Filter: [%s]\n", filter);
704
705         rc = tldap_search(ctx->ld, ctx->default_nc, TLDAP_SCOPE_SUB, filter,
706                           attrs, ARRAY_SIZE(attrs), 0, NULL, 0, NULL, 0,
707                           0, 0, 0, talloc_tos(), &msgs);
708         if (!TLDAP_RC_IS_SUCCESS(rc)) {
709                 return NT_STATUS_LDAP(TLDAP_RC_V(rc));
710         }
711
712         TALLOC_FREE(filter);
713
714         num_msgs = talloc_array_length(msgs);
715
716         for (i=0; i<num_msgs; i++) {
717                 struct tldap_message *msg = msgs[i];
718                 char *dn = NULL;
719                 bool ok;
720
721                 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
722                         continue;
723                 }
724                 ok = tldap_entry_dn(msg, &dn);
725                 if (!ok) {
726                         continue;
727                 }
728                 ok = idmap_ad_dn_filter(domain, dn);
729                 if (!ok) {
730                         DBG_DEBUG("%s filtered out\n", dn);
731                         continue;
732                 }
733
734                 if (ctx->unix_primary_group) {
735                         uint32_t gid;
736
737                         ok = tldap_pull_uint32(msg, ctx->schema->gid, &gid);
738                         if (ok) {
739                                 DBG_DEBUG("Setting primary group "
740                                           "to %"PRIu32" from attr %s\n",
741                                           gid, ctx->schema->gid);
742                                 info->primary_gid = gid;
743                         }
744                 }
745
746                 if (ctx->unix_nss_info) {
747                         char *attr;
748
749                         attr = tldap_talloc_single_attribute(
750                                 msg, ctx->schema->dir, talloc_tos());
751                         if (attr != NULL) {
752                                 info->homedir = talloc_move(info, &attr);
753                         }
754                         TALLOC_FREE(attr);
755
756                         attr = tldap_talloc_single_attribute(
757                                 msg, ctx->schema->shell, talloc_tos());
758                         if (attr != NULL) {
759                                 info->shell = talloc_move(info, &attr);
760                         }
761                         TALLOC_FREE(attr);
762
763                         attr = tldap_talloc_single_attribute(
764                                 msg, ctx->schema->gecos, talloc_tos());
765                         if (attr != NULL) {
766                                 info->full_name = talloc_move(info, &attr);
767                         }
768                         TALLOC_FREE(attr);
769                 }
770         }
771
772         return NT_STATUS_OK;
773 }
774
775 static NTSTATUS idmap_ad_query_user_retry(struct idmap_domain *domain,
776                                           struct wbint_userinfo *info)
777 {
778         const NTSTATUS status_server_down =
779                 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN));
780         NTSTATUS status;
781
782         status = idmap_ad_query_user(domain, info);
783
784         if (NT_STATUS_EQUAL(status, status_server_down)) {
785                 TALLOC_FREE(domain->private_data);
786                 status = idmap_ad_query_user(domain, info);
787         }
788
789         return status;
790 }
791
792 static NTSTATUS idmap_ad_initialize(struct idmap_domain *dom)
793 {
794         dom->query_user = idmap_ad_query_user_retry;
795         dom->private_data = NULL;
796         return NT_STATUS_OK;
797 }
798
799 static NTSTATUS idmap_ad_get_context(struct idmap_domain *dom,
800                                      struct idmap_ad_context **pctx)
801 {
802         struct idmap_ad_context *ctx = NULL;
803         NTSTATUS status;
804
805         if (IS_AD_DC) {
806                 /*
807                  * Make sure we never try to use LDAP against
808                  * a trusted domain as AD_DC.
809                  *
810                  * This shouldn't be called currently,
811                  * but you never know what happens in future.
812                  */
813                 return NT_STATUS_REQUEST_NOT_ACCEPTED;
814         }
815
816         if (dom->private_data != NULL) {
817                 *pctx = talloc_get_type_abort(dom->private_data,
818                                               struct idmap_ad_context);
819                 return NT_STATUS_OK;
820         }
821
822         status = idmap_ad_context_create(dom, dom, dom->name, &ctx);
823         if (!NT_STATUS_IS_OK(status)) {
824                 DBG_DEBUG("idmap_ad_context_create failed: %s\n",
825                           nt_errstr(status));
826                 return status;
827         }
828
829         dom->private_data = ctx;
830         *pctx = ctx;
831         return NT_STATUS_OK;
832 }
833
834 static NTSTATUS idmap_ad_unixids_to_sids(struct idmap_domain *dom,
835                                          struct id_map **ids)
836 {
837         struct idmap_ad_context *ctx;
838         TLDAPRC rc;
839         NTSTATUS status;
840         struct tldap_message **msgs;
841
842         size_t i, num_msgs;
843         char *u_filter, *g_filter, *filter;
844
845         const char *attrs[] = {
846                 "sAMAccountType",
847                 "objectSid",
848                 NULL, /* attr_uidnumber */
849                 NULL, /* attr_gidnumber */
850         };
851
852         status = idmap_ad_get_context(dom, &ctx);
853         if (!NT_STATUS_IS_OK(status)) {
854                 return status;
855         }
856
857         attrs[2] = ctx->schema->uid;
858         attrs[3] = ctx->schema->gid;
859
860         u_filter = talloc_strdup(talloc_tos(), "");
861         if (u_filter == NULL) {
862                 return NT_STATUS_NO_MEMORY;
863         }
864
865         g_filter = talloc_strdup(talloc_tos(), "");
866         if (g_filter == NULL) {
867                 return NT_STATUS_NO_MEMORY;
868         }
869
870         for (i=0; ids[i] != NULL; i++) {
871                 struct id_map *id = ids[i];
872
873                 id->status = ID_UNKNOWN;
874
875                 switch (id->xid.type) {
876                     case ID_TYPE_UID: {
877                             u_filter = talloc_asprintf_append_buffer(
878                                     u_filter, "(%s=%ju)", ctx->schema->uid,
879                                     (uintmax_t)id->xid.id);
880                             if (u_filter == NULL) {
881                                     return NT_STATUS_NO_MEMORY;
882                             }
883                             break;
884                     }
885
886                     case ID_TYPE_GID: {
887                             g_filter = talloc_asprintf_append_buffer(
888                                     g_filter, "(%s=%ju)", ctx->schema->gid,
889                                     (uintmax_t)id->xid.id);
890                             if (g_filter == NULL) {
891                                     return NT_STATUS_NO_MEMORY;
892                             }
893                             break;
894                     }
895
896                     default:
897                             DBG_WARNING("Unknown id type: %u\n",
898                                         (unsigned)id->xid.type);
899                             break;
900                 }
901         }
902
903         filter = talloc_strdup(talloc_tos(), "(|");
904         if (filter == NULL) {
905                 return NT_STATUS_NO_MEMORY;
906         }
907
908         if (*u_filter != '\0') {
909                 filter = talloc_asprintf_append_buffer(
910                         filter,
911                         "(&(|(sAMAccountType=%d)(sAMAccountType=%d)"
912                         "(sAMAccountType=%d))(|%s))",
913                         ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST,
914                         ATYPE_INTERDOMAIN_TRUST, u_filter);
915                 if (filter == NULL) {
916                         return NT_STATUS_NO_MEMORY;
917                 }
918         }
919         TALLOC_FREE(u_filter);
920
921         if (*g_filter != '\0') {
922                 filter = talloc_asprintf_append_buffer(
923                         filter,
924                         "(&(|(sAMAccountType=%d)(sAMAccountType=%d))(|%s))",
925                         ATYPE_SECURITY_GLOBAL_GROUP,
926                         ATYPE_SECURITY_LOCAL_GROUP,
927                         g_filter);
928                 if (filter == NULL) {
929                         return NT_STATUS_NO_MEMORY;
930                 }
931         }
932         TALLOC_FREE(g_filter);
933
934         filter = talloc_asprintf_append_buffer(filter, ")");
935         if (filter == NULL) {
936                 return NT_STATUS_NO_MEMORY;
937         }
938
939         DBG_DEBUG("Filter: [%s]\n", filter);
940
941         rc = tldap_search(ctx->ld, ctx->default_nc, TLDAP_SCOPE_SUB, filter,
942                           attrs, ARRAY_SIZE(attrs), 0, NULL, 0, NULL, 0,
943                           0, 0, 0, talloc_tos(), &msgs);
944         if (!TLDAP_RC_IS_SUCCESS(rc)) {
945                 return NT_STATUS_LDAP(TLDAP_RC_V(rc));
946         }
947
948         TALLOC_FREE(filter);
949
950         num_msgs = talloc_array_length(msgs);
951
952         for (i=0; i<num_msgs; i++) {
953                 struct tldap_message *msg = msgs[i];
954                 char *dn;
955                 struct id_map *map;
956                 struct dom_sid sid;
957                 size_t j;
958                 bool ok;
959                 uint32_t atype, xid;
960                 enum id_type type;
961                 struct dom_sid_buf sidbuf;
962
963                 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
964                         continue;
965                 }
966
967                 ok = tldap_entry_dn(msg, &dn);
968                 if (!ok) {
969                         DBG_DEBUG("No dn found in msg %zu\n", i);
970                         continue;
971                 }
972
973                 ok = idmap_ad_dn_filter(dom, dn);
974                 if (!ok) {
975                         DBG_DEBUG("%s filtered out\n", dn);
976                         continue;
977                 }
978
979                 ok = tldap_pull_uint32(msg, "sAMAccountType", &atype);
980                 if (!ok) {
981                         DBG_DEBUG("No atype in object %s\n", dn);
982                         continue;
983                 }
984
985                 switch (atype & 0xF0000000) {
986                     case ATYPE_SECURITY_GLOBAL_GROUP:
987                     case ATYPE_SECURITY_LOCAL_GROUP:
988                             type = ID_TYPE_GID;
989                             break;
990                     case ATYPE_NORMAL_ACCOUNT:
991                     case ATYPE_WORKSTATION_TRUST:
992                     case ATYPE_INTERDOMAIN_TRUST:
993                             type = ID_TYPE_UID;
994                             break;
995                     default:
996                             DBG_WARNING("unrecognized SAM account type %08x\n",
997                                         atype);
998                         continue;
999                 }
1000
1001                 ok = tldap_pull_uint32(msg, (type == ID_TYPE_UID) ?
1002                                        ctx->schema->uid : ctx->schema->gid,
1003                                        &xid);
1004                 if (!ok) {
1005                         DBG_WARNING("No unix id in object %s\n", dn);
1006                         continue;
1007                 }
1008
1009                 ok = tldap_pull_binsid(msg, "objectSid", &sid);
1010                 if (!ok) {
1011                         DBG_DEBUG("No objectSid in object %s\n", dn);
1012                         continue;
1013                 }
1014
1015                 map = NULL;
1016                 for (j=0; ids[j]; j++) {
1017                         if ((type == ids[j]->xid.type) &&
1018                             (xid == ids[j]->xid.id)) {
1019                                 map = ids[j];
1020                                 break;
1021                         }
1022                 }
1023                 if (map == NULL) {
1024                         DBG_DEBUG("Got unexpected sid %s from object %s\n",
1025                                   dom_sid_str_buf(&sid, &sidbuf),
1026                                   dn);
1027                         continue;
1028                 }
1029
1030                 sid_copy(map->sid, &sid);
1031                 map->status = ID_MAPPED;
1032
1033                 DBG_DEBUG("Mapped %s -> %ju (%d)\n",
1034                           dom_sid_str_buf(map->sid, &sidbuf),
1035                           (uintmax_t)map->xid.id, map->xid.type);
1036         }
1037
1038         TALLOC_FREE(msgs);
1039
1040         return NT_STATUS_OK;
1041 }
1042
1043 static NTSTATUS idmap_ad_sids_to_unixids(struct idmap_domain *dom,
1044                                          struct id_map **ids)
1045 {
1046         struct idmap_ad_context *ctx;
1047         TLDAPRC rc;
1048         NTSTATUS status;
1049         struct tldap_message **msgs;
1050
1051         char *filter;
1052         size_t i, num_msgs;
1053
1054         const char *attrs[] = {
1055                 "sAMAccountType",
1056                 "objectSid",
1057                 NULL, /* attr_uidnumber */
1058                 NULL, /* attr_gidnumber */
1059         };
1060
1061         status = idmap_ad_get_context(dom, &ctx);
1062         if (!NT_STATUS_IS_OK(status)) {
1063                 return status;
1064         }
1065
1066         attrs[2] = ctx->schema->uid;
1067         attrs[3] = ctx->schema->gid;
1068
1069         filter = talloc_asprintf(
1070                 talloc_tos(),
1071                 "(&(|(sAMAccountType=%d)(sAMAccountType=%d)(sAMAccountType=%d)"
1072                 "(sAMAccountType=%d)(sAMAccountType=%d))(|",
1073                 ATYPE_NORMAL_ACCOUNT, ATYPE_WORKSTATION_TRUST,
1074                 ATYPE_INTERDOMAIN_TRUST, ATYPE_SECURITY_GLOBAL_GROUP,
1075                 ATYPE_SECURITY_LOCAL_GROUP);
1076         if (filter == NULL) {
1077                 return NT_STATUS_NO_MEMORY;
1078         }
1079
1080         for (i=0; ids[i]; i++) {
1081                 char *sidstr;
1082
1083                 ids[i]->status = ID_UNKNOWN;
1084
1085                 sidstr = ldap_encode_ndr_dom_sid(talloc_tos(), ids[i]->sid);
1086                 if (sidstr == NULL) {
1087                         return NT_STATUS_NO_MEMORY;
1088                 }
1089
1090                 filter = talloc_asprintf_append_buffer(
1091                         filter, "(objectSid=%s)", sidstr);
1092                 TALLOC_FREE(sidstr);
1093                 if (filter == NULL) {
1094                         return NT_STATUS_NO_MEMORY;
1095                 }
1096         }
1097
1098         filter = talloc_asprintf_append_buffer(filter, "))");
1099         if (filter == NULL) {
1100                 return NT_STATUS_NO_MEMORY;
1101         }
1102
1103         DBG_DEBUG("Filter: [%s]\n", filter);
1104
1105         rc = tldap_search(ctx->ld, ctx->default_nc, TLDAP_SCOPE_SUB, filter,
1106                           attrs, ARRAY_SIZE(attrs), 0, NULL, 0, NULL, 0,
1107                           0, 0, 0, talloc_tos(), &msgs);
1108         if (!TLDAP_RC_IS_SUCCESS(rc)) {
1109                 return NT_STATUS_LDAP(TLDAP_RC_V(rc));
1110         }
1111
1112         TALLOC_FREE(filter);
1113
1114         num_msgs = talloc_array_length(msgs);
1115
1116         for (i=0; i<num_msgs; i++) {
1117                 struct tldap_message *msg = msgs[i];
1118                 char *dn;
1119                 struct id_map *map;
1120                 struct dom_sid sid;
1121                 size_t j;
1122                 bool ok;
1123                 uint64_t account_type, xid;
1124                 enum id_type type;
1125                 struct dom_sid_buf buf;
1126
1127                 if (tldap_msg_type(msg) != TLDAP_RES_SEARCH_ENTRY) {
1128                         continue;
1129                 }
1130
1131                 ok = tldap_entry_dn(msg, &dn);
1132                 if (!ok) {
1133                         DBG_DEBUG("No dn found in msg %zu\n", i);
1134                         continue;
1135                 }
1136
1137                 ok = idmap_ad_dn_filter(dom, dn);
1138                 if (!ok) {
1139                         DBG_DEBUG("%s filtered out\n", dn);
1140                         continue;
1141                 }
1142
1143                 ok = tldap_pull_binsid(msg, "objectSid", &sid);
1144                 if (!ok) {
1145                         DBG_DEBUG("No objectSid in object %s\n", dn);
1146                         continue;
1147                 }
1148
1149                 map = NULL;
1150                 for (j=0; ids[j]; j++) {
1151                         if (dom_sid_equal(&sid, ids[j]->sid)) {
1152                                 map = ids[j];
1153                                 break;
1154                         }
1155                 }
1156                 if (map == NULL) {
1157                         DBG_DEBUG("Got unexpected sid %s from object %s\n",
1158                                   dom_sid_str_buf(&sid, &buf),
1159                                   dn);
1160                         continue;
1161                 }
1162
1163                 ok = tldap_pull_uint64(msg, "sAMAccountType", &account_type);
1164                 if (!ok) {
1165                         DBG_DEBUG("No sAMAccountType in %s\n", dn);
1166                         continue;
1167                 }
1168
1169                 switch (account_type & 0xF0000000) {
1170                 case ATYPE_SECURITY_GLOBAL_GROUP:
1171                 case ATYPE_SECURITY_LOCAL_GROUP:
1172                         type = ID_TYPE_GID;
1173                         break;
1174                 case ATYPE_NORMAL_ACCOUNT:
1175                 case ATYPE_WORKSTATION_TRUST:
1176                 case ATYPE_INTERDOMAIN_TRUST:
1177                         type = ID_TYPE_UID;
1178                         break;
1179                 default:
1180                         DBG_WARNING("unrecognized SAM account type %"PRIu64"\n",
1181                                     account_type);
1182                         continue;
1183                 }
1184
1185                 ok = tldap_pull_uint64(msg,
1186                                        type == ID_TYPE_UID ?
1187                                        ctx->schema->uid : ctx->schema->gid,
1188                                        &xid);
1189                 if (!ok) {
1190                         DBG_DEBUG("No xid in %s\n", dn);
1191                         continue;
1192                 }
1193
1194                 /* mapped */
1195                 map->xid.type = type;
1196                 map->xid.id = xid;
1197                 map->status = ID_MAPPED;
1198
1199                 DEBUG(10, ("Mapped %s -> %lu (%d)\n",
1200                            dom_sid_str_buf(map->sid, &buf),
1201                            (unsigned long)map->xid.id, map->xid.type));
1202         }
1203
1204         TALLOC_FREE(msgs);
1205
1206         return NT_STATUS_OK;
1207 }
1208
1209 static NTSTATUS idmap_ad_unixids_to_sids_retry(struct idmap_domain *dom,
1210                                                struct id_map **ids)
1211 {
1212         const NTSTATUS status_server_down =
1213                 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN));
1214         NTSTATUS status;
1215
1216         status = idmap_ad_unixids_to_sids(dom, ids);
1217
1218         if (NT_STATUS_EQUAL(status, status_server_down)) {
1219                 TALLOC_FREE(dom->private_data);
1220                 status = idmap_ad_unixids_to_sids(dom, ids);
1221         }
1222
1223         return status;
1224 }
1225
1226 static NTSTATUS idmap_ad_sids_to_unixids_retry(struct idmap_domain *dom,
1227                                                struct id_map **ids)
1228 {
1229         const NTSTATUS status_server_down =
1230                 NT_STATUS_LDAP(TLDAP_RC_V(TLDAP_SERVER_DOWN));
1231         NTSTATUS status;
1232
1233         status = idmap_ad_sids_to_unixids(dom, ids);
1234
1235         if (NT_STATUS_EQUAL(status, status_server_down)) {
1236                 TALLOC_FREE(dom->private_data);
1237                 status = idmap_ad_sids_to_unixids(dom, ids);
1238         }
1239
1240         return status;
1241 }
1242
1243 static const struct idmap_methods ad_methods = {
1244         .init            = idmap_ad_initialize,
1245         .unixids_to_sids = idmap_ad_unixids_to_sids_retry,
1246         .sids_to_unixids = idmap_ad_sids_to_unixids_retry,
1247 };
1248
1249 static_decl_idmap;
1250 NTSTATUS idmap_ad_init(TALLOC_CTX *ctx)
1251 {
1252         NTSTATUS status;
1253
1254         status = smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION,
1255                                     "ad", &ad_methods);
1256         if (!NT_STATUS_IS_OK(status)) {
1257                 return status;
1258         }
1259
1260         status = idmap_ad_nss_init(ctx);
1261         if (!NT_STATUS_IS_OK(status)) {
1262                 return status;
1263         }
1264
1265         return NT_STATUS_OK;
1266 }