LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd_ads.c (source / functions) Hit Total Coverage
Test: coverage report for support-claim-type-attributes 6b5c566e Lines: 0 739 0.0 %
Date: 2023-11-21 12:31:41 Functions: 0 20 0.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Winbind ADS backend functions
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2001
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2003
       8             :    Copyright (C) Gerald (Jerry) Carter 2004
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             : 
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             : 
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include "winbindd.h"
      26             : #include "winbindd_ads.h"
      27             : #include "libsmb/namequery.h"
      28             : #include "rpc_client/rpc_client.h"
      29             : #include "../librpc/gen_ndr/ndr_netlogon_c.h"
      30             : #include "../libds/common/flags.h"
      31             : #include "ads.h"
      32             : #include "../libcli/ldap/ldap_ndr.h"
      33             : #include "../libcli/security/security.h"
      34             : #include "../libds/common/flag_mapping.h"
      35             : #include "libsmb/samlogon_cache.h"
      36             : #include "passdb.h"
      37             : #include "auth/credentials/credentials.h"
      38             : 
      39             : #ifdef HAVE_ADS
      40             : 
      41             : #undef DBGC_CLASS
      42             : #define DBGC_CLASS DBGC_WINBIND
      43             : 
      44             : extern struct winbindd_methods reconnect_methods;
      45             : extern struct winbindd_methods msrpc_methods;
      46             : 
      47             : #define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache"
      48             : 
      49             : /**
      50             :  * Check if cached connection can be reused. If the connection cannot
      51             :  * be reused the ADS_STRUCT is freed and the pointer is set to NULL.
      52             :  */
      53           0 : static void ads_cached_connection_reuse(ADS_STRUCT **adsp)
      54             : {
      55             : 
      56           0 :         ADS_STRUCT *ads = *adsp;
      57             : 
      58           0 :         if (ads != NULL) {
      59           0 :                 time_t expire;
      60           0 :                 time_t now = time(NULL);
      61             : 
      62           0 :                 expire = MIN(ads->auth.tgt_expire, ads->auth.tgs_expire);
      63             : 
      64           0 :                 DEBUG(7, ("Current tickets expire in %d seconds (at %d, time "
      65             :                           "is now %d)\n", (uint32_t)expire - (uint32_t)now,
      66             :                           (uint32_t) expire, (uint32_t) now));
      67             : 
      68           0 :                 if ( ads->config.realm && (expire > now)) {
      69           0 :                         return;
      70             :                 } else {
      71             :                         /* we own this ADS_STRUCT so make sure it goes away */
      72           0 :                         DEBUG(7,("Deleting expired krb5 credential cache\n"));
      73           0 :                         TALLOC_FREE(ads);
      74           0 :                         ads_kdestroy(WINBIND_CCACHE_NAME);
      75           0 :                         *adsp = NULL;
      76             :                 }
      77             :         }
      78             : }
      79             : 
      80             : /**
      81             :  * @brief Establish a connection to a DC
      82             :  *
      83             :  * @param[out]   adsp             ADS_STRUCT that will be created
      84             :  * @param[in]    target_realm     Realm of domain to connect to
      85             :  * @param[in]    target_dom_name  'workgroup' name of domain to connect to
      86             :  * @param[in]    ldap_server      DNS name of server to connect to
      87             :  * @param[in]    password         Our machine account secret
      88             :  * @param[in]    auth_realm       Realm of local domain for creating krb token
      89             :  * @param[in]    renewable        Renewable ticket time
      90             :  *
      91             :  * @return ADS_STATUS
      92             :  */
      93           0 : static ADS_STATUS ads_cached_connection_connect(const char *target_realm,
      94             :                                                 const char *target_dom_name,
      95             :                                                 const char *ldap_server,
      96             :                                                 char *password,
      97             :                                                 char *auth_realm,
      98             :                                                 time_t renewable,
      99             :                                                 TALLOC_CTX *mem_ctx,
     100             :                                                 ADS_STRUCT **adsp)
     101             : {
     102           0 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     103           0 :         ADS_STRUCT *ads;
     104           0 :         ADS_STATUS status;
     105           0 :         struct sockaddr_storage dc_ss;
     106           0 :         fstring dc_name;
     107           0 :         enum credentials_use_kerberos krb5_state;
     108             : 
     109           0 :         if (auth_realm == NULL) {
     110           0 :                 TALLOC_FREE(tmp_ctx);
     111           0 :                 return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
     112             :         }
     113             : 
     114             :         /* we don't want this to affect the users ccache */
     115           0 :         setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1);
     116             : 
     117           0 :         ads = ads_init(tmp_ctx,
     118             :                        target_realm,
     119             :                        target_dom_name,
     120             :                        ldap_server,
     121             :                        ADS_SASL_SEAL);
     122           0 :         if (!ads) {
     123           0 :                 DEBUG(1,("ads_init for domain %s failed\n", target_dom_name));
     124           0 :                 status = ADS_ERROR(LDAP_NO_MEMORY);
     125           0 :                 goto out;
     126             :         }
     127             : 
     128           0 :         ADS_TALLOC_CONST_FREE(ads->auth.password);
     129           0 :         ADS_TALLOC_CONST_FREE(ads->auth.realm);
     130             : 
     131           0 :         ads->auth.renewable = renewable;
     132           0 :         ads->auth.password = talloc_strdup(ads, password);
     133           0 :         if (ads->auth.password == NULL) {
     134           0 :                 status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
     135           0 :                 goto out;
     136             :         }
     137             : 
     138             :         /* In FIPS mode, client use kerberos is forced to required. */
     139           0 :         krb5_state = lp_client_use_kerberos();
     140           0 :         switch (krb5_state) {
     141           0 :         case CRED_USE_KERBEROS_REQUIRED:
     142           0 :                 ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
     143           0 :                 ads->auth.flags &= ~ADS_AUTH_ALLOW_NTLMSSP;
     144           0 :                 break;
     145           0 :         case CRED_USE_KERBEROS_DESIRED:
     146           0 :                 ads->auth.flags &= ~ADS_AUTH_DISABLE_KERBEROS;
     147           0 :                 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
     148           0 :                 break;
     149           0 :         case CRED_USE_KERBEROS_DISABLED:
     150           0 :                 ads->auth.flags |= ADS_AUTH_DISABLE_KERBEROS;
     151           0 :                 ads->auth.flags |= ADS_AUTH_ALLOW_NTLMSSP;
     152           0 :                 break;
     153             :         }
     154             : 
     155           0 :         ads->auth.realm = talloc_asprintf_strupper_m(ads, "%s", auth_realm);
     156           0 :         if (ads->auth.realm == NULL) {
     157           0 :                 status = ADS_ERROR_NT(NT_STATUS_INTERNAL_ERROR);
     158           0 :                 goto out;
     159             :         }
     160             : 
     161             :         /* Setup the server affinity cache.  We don't reaally care
     162             :            about the name.  Just setup affinity and the KRB5_CONFIG
     163             :            file. */
     164           0 :         get_dc_name(ads->server.workgroup, ads->server.realm, dc_name, &dc_ss);
     165             : 
     166           0 :         status = ads_connect(ads);
     167           0 :         if (!ADS_ERR_OK(status)) {
     168           0 :                 DEBUG(1,("ads_connect for domain %s failed: %s\n",
     169             :                          target_dom_name, ads_errstr(status)));
     170           0 :                 goto out;
     171             :         }
     172             : 
     173           0 :         *adsp = talloc_move(mem_ctx, &ads);
     174           0 : out:
     175           0 :         TALLOC_FREE(tmp_ctx);
     176           0 :         return status;
     177             : }
     178             : 
     179           0 : ADS_STATUS ads_idmap_cached_connection(const char *dom_name,
     180             :                                        TALLOC_CTX *mem_ctx,
     181             :                                        ADS_STRUCT **adsp)
     182             : {
     183           0 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     184           0 :         char *ldap_server = NULL;
     185           0 :         char *realm = NULL;
     186           0 :         char *password = NULL;
     187           0 :         struct winbindd_domain *wb_dom = NULL;
     188           0 :         ADS_STATUS status;
     189             : 
     190           0 :         if (IS_AD_DC) {
     191             :                 /*
     192             :                  * Make sure we never try to use LDAP against
     193             :                  * a trusted domain as AD DC.
     194             :                  */
     195           0 :                 TALLOC_FREE(tmp_ctx);
     196           0 :                 return ADS_ERROR_NT(NT_STATUS_REQUEST_NOT_ACCEPTED);
     197             :         }
     198             : 
     199           0 :         ads_cached_connection_reuse(adsp);
     200           0 :         if (*adsp != NULL) {
     201           0 :                 TALLOC_FREE(tmp_ctx);
     202           0 :                 return ADS_SUCCESS;
     203             :         }
     204             : 
     205             :         /*
     206             :          * At this point we only have the NetBIOS domain name.
     207             :          * Check if we can get server name and realm from SAF cache
     208             :          * and the domain list.
     209             :          */
     210           0 :         ldap_server = saf_fetch(tmp_ctx, dom_name);
     211             : 
     212           0 :         DBG_DEBUG("ldap_server from saf cache: '%s'\n",
     213             :                    ldap_server ? ldap_server : "");
     214             : 
     215           0 :         wb_dom = find_domain_from_name(dom_name);
     216           0 :         if (wb_dom == NULL) {
     217           0 :                 DBG_DEBUG("could not find domain '%s'\n", dom_name);
     218           0 :                 status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
     219           0 :                 goto out;
     220             :         }
     221             : 
     222           0 :         DBG_DEBUG("find_domain_from_name found realm '%s' for "
     223             :                   " domain '%s'\n", wb_dom->alt_name, dom_name);
     224             : 
     225           0 :         if (!get_trust_pw_clear(dom_name, &password, NULL, NULL)) {
     226           0 :                 status = ADS_ERROR_NT(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
     227           0 :                 goto out;
     228             :         }
     229             : 
     230           0 :         if (IS_DC) {
     231           0 :                 SMB_ASSERT(wb_dom->alt_name != NULL);
     232           0 :                 realm = talloc_strdup(tmp_ctx, wb_dom->alt_name);
     233             :         } else {
     234           0 :                 struct winbindd_domain *our_domain = wb_dom;
     235             : 
     236             :                 /* always give preference to the alt_name in our
     237             :                    primary domain if possible */
     238             : 
     239           0 :                 if (!wb_dom->primary) {
     240           0 :                         our_domain = find_our_domain();
     241             :                 }
     242             : 
     243           0 :                 if (our_domain->alt_name != NULL) {
     244           0 :                         realm = talloc_strdup(tmp_ctx, our_domain->alt_name);
     245             :                 } else {
     246           0 :                         realm = talloc_strdup(tmp_ctx, lp_realm());
     247             :                 }
     248             :         }
     249             : 
     250           0 :         if (realm == NULL) {
     251           0 :                 status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
     252           0 :                 goto out;
     253             :         }
     254             : 
     255           0 :         status = ads_cached_connection_connect(
     256           0 :                 wb_dom->alt_name,    /* realm to connect to. */
     257             :                 dom_name,               /* 'workgroup' name for ads_init */
     258             :                 ldap_server,            /* DNS name to connect to. */
     259             :                 password,               /* password for auth realm. */
     260             :                 realm,                  /* realm used for krb5 ticket. */
     261             :                 0,                      /* renewable ticket time. */
     262             :                 mem_ctx,                /* memory context for ads struct */
     263             :                 adsp);                  /* Returns ads struct. */
     264             : 
     265           0 : out:
     266           0 :         TALLOC_FREE(tmp_ctx);
     267           0 :         SAFE_FREE(password);
     268             : 
     269           0 :         return status;
     270             : }
     271             : 
     272             : /*
     273             :   return our ads connections structure for a domain. We keep the connection
     274             :   open to make things faster
     275             : */
     276           0 : static ADS_STATUS ads_cached_connection(struct winbindd_domain *domain,
     277             :                                         ADS_STRUCT **adsp)
     278             : {
     279           0 :         TALLOC_CTX *tmp_ctx = talloc_stackframe();
     280           0 :         ADS_STATUS status;
     281           0 :         char *password = NULL;
     282           0 :         char *realm = NULL;
     283             : 
     284           0 :         if (IS_AD_DC) {
     285             :                 /*
     286             :                  * Make sure we never try to use LDAP against
     287             :                  * a trusted domain as AD DC.
     288             :                  */
     289           0 :                 TALLOC_FREE(tmp_ctx);
     290           0 :                 return ADS_ERROR_NT(NT_STATUS_REQUEST_NOT_ACCEPTED);
     291             :         }
     292             : 
     293           0 :         DBG_DEBUG("ads_cached_connection\n");
     294             : 
     295           0 :         ads_cached_connection_reuse(&domain->backend_data.ads_conn);
     296           0 :         if (domain->backend_data.ads_conn != NULL) {
     297           0 :                 *adsp = domain->backend_data.ads_conn;
     298           0 :                 TALLOC_FREE(tmp_ctx);
     299           0 :                 return ADS_SUCCESS;
     300             :         }
     301             : 
     302             :         /* the machine acct password might have change - fetch it every time */
     303             : 
     304           0 :         if (!get_trust_pw_clear(domain->name, &password, NULL, NULL)) {
     305           0 :                 status = ADS_ERROR_NT(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
     306           0 :                 goto out;
     307             :         }
     308             : 
     309           0 :         if ( IS_DC ) {
     310           0 :                 SMB_ASSERT(domain->alt_name != NULL);
     311           0 :                 realm = talloc_strdup(tmp_ctx, domain->alt_name);
     312             :         } else {
     313           0 :                 struct winbindd_domain *our_domain = domain;
     314             : 
     315             : 
     316             :                 /* always give preference to the alt_name in our
     317             :                    primary domain if possible */
     318             : 
     319           0 :                 if ( !domain->primary )
     320           0 :                         our_domain = find_our_domain();
     321             : 
     322           0 :                 if (our_domain->alt_name != NULL) {
     323           0 :                         realm = talloc_strdup(tmp_ctx, our_domain->alt_name );
     324             :                 } else {
     325           0 :                         realm = talloc_strdup(tmp_ctx, lp_realm() );
     326             :                 }
     327             :         }
     328             : 
     329           0 :         if (realm == NULL) {
     330           0 :                 status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
     331           0 :                 goto out;
     332             :         }
     333             : 
     334           0 :         status = ads_cached_connection_connect(
     335           0 :                                         domain->alt_name,
     336           0 :                                         domain->name, NULL,
     337             :                                         password,
     338             :                                         realm,
     339             :                                         WINBINDD_PAM_AUTH_KRB5_RENEW_TIME,
     340             :                                         domain,
     341           0 :                                         &domain->backend_data.ads_conn);
     342           0 :         if (!ADS_ERR_OK(status)) {
     343             :                 /* if we get ECONNREFUSED then it might be a NT4
     344             :                    server, fall back to MSRPC */
     345           0 :                 if (status.error_type == ENUM_ADS_ERROR_SYSTEM &&
     346           0 :                     status.err.rc == ECONNREFUSED) {
     347             :                         /* 'reconnect_methods' is the MS-RPC backend. */
     348           0 :                         DBG_NOTICE("Trying MSRPC methods for domain '%s'\n",
     349             :                                    domain->name);
     350           0 :                         domain->backend = &reconnect_methods;
     351             :                 }
     352           0 :                 goto out;
     353             :         }
     354             : 
     355           0 :         *adsp = domain->backend_data.ads_conn;
     356           0 : out:
     357           0 :         TALLOC_FREE(tmp_ctx);
     358           0 :         SAFE_FREE(password);
     359             : 
     360           0 :         return status;
     361             : }
     362             : 
     363             : /* Query display info for a realm. This is the basic user list fn */
     364           0 : static NTSTATUS query_user_list(struct winbindd_domain *domain,
     365             :                                TALLOC_CTX *mem_ctx,
     366             :                                uint32_t **prids)
     367             : {
     368           0 :         ADS_STRUCT *ads = NULL;
     369           0 :         const char *attrs[] = { "sAMAccountType", "objectSid", NULL };
     370           0 :         int count;
     371           0 :         uint32_t *rids = NULL;
     372           0 :         ADS_STATUS rc;
     373           0 :         LDAPMessage *res = NULL;
     374           0 :         LDAPMessage *msg = NULL;
     375           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     376             : 
     377           0 :         DEBUG(3,("ads: query_user_list\n"));
     378             : 
     379           0 :         if ( !winbindd_can_contact_domain( domain ) ) {
     380           0 :                 DEBUG(10,("query_user_list: No incoming trust for domain %s\n",
     381             :                           domain->name));
     382           0 :                 return NT_STATUS_OK;
     383             :         }
     384             : 
     385           0 :         rc = ads_cached_connection(domain, &ads);
     386           0 :         if (!ADS_ERR_OK(rc)) {
     387           0 :                 domain->last_status = NT_STATUS_SERVER_DISABLED;
     388           0 :                 goto done;
     389             :         }
     390             : 
     391           0 :         rc = ads_search_retry(ads, &res, "(objectCategory=user)", attrs);
     392           0 :         if (!ADS_ERR_OK(rc)) {
     393           0 :                 DEBUG(1,("query_user_list ads_search: %s\n", ads_errstr(rc)));
     394           0 :                 status = ads_ntstatus(rc);
     395           0 :                 goto done;
     396           0 :         } else if (!res) {
     397           0 :                 DEBUG(1,("query_user_list ads_search returned NULL res\n"));
     398           0 :                 goto done;
     399             :         }
     400             : 
     401           0 :         count = ads_count_replies(ads, res);
     402           0 :         if (count == 0) {
     403           0 :                 DEBUG(1,("query_user_list: No users found\n"));
     404           0 :                 goto done;
     405             :         }
     406             : 
     407           0 :         rids = talloc_zero_array(mem_ctx, uint32_t, count);
     408           0 :         if (rids == NULL) {
     409           0 :                 status = NT_STATUS_NO_MEMORY;
     410           0 :                 goto done;
     411             :         }
     412             : 
     413           0 :         count = 0;
     414             : 
     415           0 :         for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
     416           0 :                 struct dom_sid user_sid;
     417           0 :                 uint32_t atype;
     418           0 :                 bool ok;
     419             : 
     420           0 :                 ok = ads_pull_uint32(ads, msg, "sAMAccountType", &atype);
     421           0 :                 if (!ok) {
     422           0 :                         DBG_INFO("Object lacks sAMAccountType attribute\n");
     423           0 :                         continue;
     424             :                 }
     425           0 :                 if (ds_atype_map(atype) != SID_NAME_USER) {
     426           0 :                         DBG_INFO("Not a user account? atype=0x%x\n", atype);
     427           0 :                         continue;
     428             :                 }
     429             : 
     430           0 :                 if (!ads_pull_sid(ads, msg, "objectSid", &user_sid)) {
     431           0 :                         char *dn = ads_get_dn(ads, talloc_tos(), msg);
     432           0 :                         DBG_INFO("No sid for %s !?\n", dn);
     433           0 :                         TALLOC_FREE(dn);
     434           0 :                         continue;
     435             :                 }
     436             : 
     437           0 :                 if (!dom_sid_in_domain(&domain->sid, &user_sid)) {
     438           0 :                         struct dom_sid_buf sidstr, domstr;
     439           0 :                         DBG_WARNING("Got sid %s in domain %s\n",
     440             :                                     dom_sid_str_buf(&user_sid, &sidstr),
     441             :                                     dom_sid_str_buf(&domain->sid, &domstr));
     442           0 :                         continue;
     443             :                 }
     444             : 
     445           0 :                 sid_split_rid(&user_sid, &rids[count]);
     446           0 :                 count += 1;
     447             :         }
     448             : 
     449           0 :         rids = talloc_realloc(mem_ctx, rids, uint32_t, count);
     450           0 :         if (prids != NULL) {
     451           0 :                 *prids = rids;
     452             :         }
     453             : 
     454           0 :         status = NT_STATUS_OK;
     455             : 
     456           0 :         DBG_NOTICE("ads query_user_list gave %d entries\n", count);
     457             : 
     458           0 : done:
     459           0 :         ads_msgfree(ads, res);
     460           0 :         return status;
     461             : }
     462             : 
     463             : /* list all domain groups */
     464           0 : static NTSTATUS enum_dom_groups(struct winbindd_domain *domain,
     465             :                                 TALLOC_CTX *mem_ctx,
     466             :                                 uint32_t *num_entries,
     467             :                                 struct wb_acct_info **info)
     468             : {
     469           0 :         ADS_STRUCT *ads = NULL;
     470           0 :         const char *attrs[] = {"userPrincipalName", "sAMAccountName",
     471             :                                "name", "objectSid", NULL};
     472           0 :         int i, count;
     473           0 :         ADS_STATUS rc;
     474           0 :         LDAPMessage *res = NULL;
     475           0 :         LDAPMessage *msg = NULL;
     476           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     477           0 :         const char *filter;
     478           0 :         bool enum_dom_local_groups = False;
     479             : 
     480           0 :         *num_entries = 0;
     481             : 
     482           0 :         DEBUG(3,("ads: enum_dom_groups\n"));
     483             : 
     484           0 :         if ( !winbindd_can_contact_domain( domain ) ) {
     485           0 :                 DEBUG(10,("enum_dom_groups: No incoming trust for domain %s\n",
     486             :                           domain->name));
     487           0 :                 return NT_STATUS_OK;
     488             :         }
     489             : 
     490             :         /* only grab domain local groups for our domain */
     491           0 :         if ( domain->active_directory && strequal(lp_realm(), domain->alt_name)  ) {
     492           0 :                 enum_dom_local_groups = True;
     493             :         }
     494             : 
     495             :         /* Workaround ADS LDAP bug present in MS W2K3 SP0 and W2K SP4 w/o
     496             :          * rollup-fixes:
     497             :          *
     498             :          * According to Section 5.1(4) of RFC 2251 if a value of a type is it's
     499             :          * default value, it MUST be absent. In case of extensible matching the
     500             :          * "dnattr" boolean defaults to FALSE and so it must be only be present
     501             :          * when set to TRUE.
     502             :          *
     503             :          * When it is set to FALSE and the OpenLDAP lib (correctly) encodes a
     504             :          * filter using bitwise matching rule then the buggy AD fails to decode
     505             :          * the extensible match. As a workaround set it to TRUE and thereby add
     506             :          * the dnAttributes "dn" field to cope with those older AD versions.
     507             :          * It should not harm and won't put any additional load on the AD since
     508             :          * none of the dn components have a bitmask-attribute.
     509             :          *
     510             :          * Thanks to Ralf Haferkamp for input and testing - Guenther */
     511             : 
     512           0 :         filter = talloc_asprintf(mem_ctx, "(&(objectCategory=group)"
     513             :                                  "(&(groupType:dn:"ADS_LDAP_MATCHING_RULE_BIT_AND":=%d)"
     514             :                                  "(!(groupType:dn:"ADS_LDAP_MATCHING_RULE_BIT_AND":=%d))))",
     515             :                                 GROUP_TYPE_SECURITY_ENABLED,
     516             :                                  enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP);
     517             : 
     518           0 :         if (filter == NULL) {
     519           0 :                 status = NT_STATUS_NO_MEMORY;
     520           0 :                 goto done;
     521             :         }
     522             : 
     523           0 :         rc = ads_cached_connection(domain, &ads);
     524           0 :         if (!ADS_ERR_OK(rc)) {
     525           0 :                 domain->last_status = NT_STATUS_SERVER_DISABLED;
     526           0 :                 goto done;
     527             :         }
     528             : 
     529           0 :         rc = ads_search_retry(ads, &res, filter, attrs);
     530           0 :         if (!ADS_ERR_OK(rc)) {
     531           0 :                 status = ads_ntstatus(rc);
     532           0 :                 DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
     533           0 :                 goto done;
     534           0 :         } else if (!res) {
     535           0 :                 DEBUG(1,("enum_dom_groups ads_search returned NULL res\n"));
     536           0 :                 goto done;
     537             :         }
     538             : 
     539           0 :         count = ads_count_replies(ads, res);
     540           0 :         if (count == 0) {
     541           0 :                 DEBUG(1,("enum_dom_groups: No groups found\n"));
     542           0 :                 goto done;
     543             :         }
     544             : 
     545           0 :         (*info) = talloc_zero_array(mem_ctx, struct wb_acct_info, count);
     546           0 :         if (!*info) {
     547           0 :                 status = NT_STATUS_NO_MEMORY;
     548           0 :                 goto done;
     549             :         }
     550             : 
     551           0 :         i = 0;
     552             : 
     553           0 :         for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
     554           0 :                 char *name, *gecos;
     555           0 :                 struct dom_sid sid;
     556           0 :                 uint32_t rid;
     557             : 
     558           0 :                 name = ads_pull_username(ads, (*info), msg);
     559           0 :                 gecos = ads_pull_string(ads, (*info), msg, "name");
     560           0 :                 if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
     561           0 :                         DEBUG(1,("No sid for %s !?\n", name));
     562           0 :                         continue;
     563             :                 }
     564             : 
     565           0 :                 if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
     566           0 :                         DEBUG(1,("No rid for %s !?\n", name));
     567           0 :                         continue;
     568             :                 }
     569             : 
     570           0 :                 (*info)[i].acct_name = name;
     571           0 :                 (*info)[i].acct_desc = gecos;
     572           0 :                 (*info)[i].rid = rid;
     573           0 :                 i++;
     574             :         }
     575             : 
     576           0 :         (*num_entries) = i;
     577             : 
     578           0 :         status = NT_STATUS_OK;
     579             : 
     580           0 :         DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));
     581             : 
     582           0 : done:
     583           0 :         if (res)
     584           0 :                 ads_msgfree(ads, res);
     585             : 
     586           0 :         return status;
     587             : }
     588             : 
     589             : /* list all domain local groups */
     590           0 : static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
     591             :                                 TALLOC_CTX *mem_ctx,
     592             :                                 uint32_t *num_entries,
     593             :                                 struct wb_acct_info **info)
     594             : {
     595             :         /*
     596             :          * This is a stub function only as we returned the domain
     597             :          * local groups in enum_dom_groups() if the domain->native field
     598             :          * was true.  This is a simple performance optimization when
     599             :          * using LDAP.
     600             :          *
     601             :          * if we ever need to enumerate domain local groups separately,
     602             :          * then this optimization in enum_dom_groups() will need
     603             :          * to be split out
     604             :          */
     605           0 :         *num_entries = 0;
     606             : 
     607           0 :         return NT_STATUS_OK;
     608             : }
     609             : 
     610             : /* convert a single name to a sid in a domain - use rpc methods */
     611           0 : static NTSTATUS name_to_sid(struct winbindd_domain *domain,
     612             :                             TALLOC_CTX *mem_ctx,
     613             :                             const char *domain_name,
     614             :                             const char *name,
     615             :                             uint32_t flags,
     616             :                             const char **pdom_name,
     617             :                             struct dom_sid *sid,
     618             :                             enum lsa_SidType *type)
     619             : {
     620           0 :         return msrpc_methods.name_to_sid(domain, mem_ctx, domain_name, name,
     621             :                                          flags, pdom_name, sid, type);
     622             : }
     623             : 
     624             : /* convert a domain SID to a user or group name - use rpc methods */
     625           0 : static NTSTATUS sid_to_name(struct winbindd_domain *domain,
     626             :                             TALLOC_CTX *mem_ctx,
     627             :                             const struct dom_sid *sid,
     628             :                             char **domain_name,
     629             :                             char **name,
     630             :                             enum lsa_SidType *type)
     631             : {
     632           0 :         return msrpc_methods.sid_to_name(domain, mem_ctx, sid,
     633             :                                          domain_name, name, type);
     634             : }
     635             : 
     636             : /* convert a list of rids to names - use rpc methods */
     637           0 : static NTSTATUS rids_to_names(struct winbindd_domain *domain,
     638             :                               TALLOC_CTX *mem_ctx,
     639             :                               const struct dom_sid *sid,
     640             :                               uint32_t *rids,
     641             :                               size_t num_rids,
     642             :                               char **domain_name,
     643             :                               char ***names,
     644             :                               enum lsa_SidType **types)
     645             : {
     646           0 :         return msrpc_methods.rids_to_names(domain, mem_ctx, sid,
     647             :                                            rids, num_rids,
     648             :                                            domain_name, names, types);
     649             : }
     650             : 
     651             : /* Lookup groups a user is a member of - alternate method, for when
     652             :    tokenGroups are not available. */
     653           0 : static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
     654             :                                          TALLOC_CTX *mem_ctx,
     655             :                                          const char *user_dn,
     656             :                                          struct dom_sid *primary_group,
     657             :                                          uint32_t *p_num_groups, struct dom_sid **user_sids)
     658             : {
     659           0 :         ADS_STATUS rc;
     660           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     661           0 :         int count;
     662           0 :         LDAPMessage *res = NULL;
     663           0 :         LDAPMessage *msg = NULL;
     664           0 :         char *ldap_exp;
     665           0 :         ADS_STRUCT *ads = NULL;
     666           0 :         const char *group_attrs[] = {"objectSid", NULL};
     667           0 :         char *escaped_dn;
     668           0 :         uint32_t num_groups = 0;
     669             : 
     670           0 :         DEBUG(3,("ads: lookup_usergroups_member\n"));
     671             : 
     672           0 :         if ( !winbindd_can_contact_domain( domain ) ) {
     673           0 :                 DEBUG(10,("lookup_usergroups_members: No incoming trust for domain %s\n",
     674             :                           domain->name));
     675           0 :                 return NT_STATUS_OK;
     676             :         }
     677             : 
     678           0 :         rc = ads_cached_connection(domain, &ads);
     679           0 :         if (!ADS_ERR_OK(rc)) {
     680           0 :                 domain->last_status = NT_STATUS_SERVER_DISABLED;
     681           0 :                 goto done;
     682             :         }
     683             : 
     684           0 :         if (!(escaped_dn = escape_ldap_string(talloc_tos(), user_dn))) {
     685           0 :                 status = NT_STATUS_NO_MEMORY;
     686           0 :                 goto done;
     687             :         }
     688             : 
     689           0 :         ldap_exp = talloc_asprintf(mem_ctx,
     690             :                 "(&(member=%s)(objectCategory=group)"
     691             :                 "(groupType:dn:"ADS_LDAP_MATCHING_RULE_BIT_AND":=%d))",
     692             :                 escaped_dn,
     693             :                 GROUP_TYPE_SECURITY_ENABLED);
     694           0 :         if (!ldap_exp) {
     695           0 :                 DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
     696           0 :                 TALLOC_FREE(escaped_dn);
     697           0 :                 status = NT_STATUS_NO_MEMORY;
     698           0 :                 goto done;
     699             :         }
     700             : 
     701           0 :         TALLOC_FREE(escaped_dn);
     702             : 
     703           0 :         rc = ads_search_retry(ads, &res, ldap_exp, group_attrs);
     704             : 
     705           0 :         if (!ADS_ERR_OK(rc)) {
     706           0 :                 DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
     707           0 :                 return ads_ntstatus(rc);
     708           0 :         } else if (!res) {
     709           0 :                 DEBUG(1,("lookup_usergroups ads_search returned NULL res\n"));
     710           0 :                 return NT_STATUS_INTERNAL_ERROR;
     711             :         }
     712             : 
     713             : 
     714           0 :         count = ads_count_replies(ads, res);
     715             : 
     716           0 :         *user_sids = NULL;
     717           0 :         num_groups = 0;
     718             : 
     719             :         /* always add the primary group to the sid array */
     720           0 :         status = add_sid_to_array(mem_ctx, primary_group, user_sids,
     721             :                                   &num_groups);
     722           0 :         if (!NT_STATUS_IS_OK(status)) {
     723           0 :                 goto done;
     724             :         }
     725             : 
     726           0 :         if (count > 0) {
     727           0 :                 for (msg = ads_first_entry(ads, res); msg;
     728           0 :                      msg = ads_next_entry(ads, msg)) {
     729           0 :                         struct dom_sid group_sid;
     730             : 
     731           0 :                         if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) {
     732           0 :                                 DEBUG(1,("No sid for this group ?!?\n"));
     733           0 :                                 continue;
     734             :                         }
     735             : 
     736             :                         /* ignore Builtin groups from ADS - Guenther */
     737           0 :                         if (sid_check_is_in_builtin(&group_sid)) {
     738           0 :                                 continue;
     739             :                         }
     740             : 
     741           0 :                         status = add_sid_to_array(mem_ctx, &group_sid,
     742             :                                                   user_sids, &num_groups);
     743           0 :                         if (!NT_STATUS_IS_OK(status)) {
     744           0 :                                 goto done;
     745             :                         }
     746             :                 }
     747             : 
     748             :         }
     749             : 
     750           0 :         *p_num_groups = num_groups;
     751           0 :         status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
     752             : 
     753           0 :         DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn));
     754           0 : done:
     755           0 :         if (res)
     756           0 :                 ads_msgfree(ads, res);
     757             : 
     758           0 :         return status;
     759             : }
     760             : 
     761             : /* Lookup groups a user is a member of - alternate method, for when
     762             :    tokenGroups are not available. */
     763           0 : static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
     764             :                                            TALLOC_CTX *mem_ctx,
     765             :                                            const char *user_dn,
     766             :                                            struct dom_sid *primary_group,
     767             :                                            uint32_t *p_num_groups,
     768             :                                            struct dom_sid **user_sids)
     769             : {
     770           0 :         ADS_STATUS rc;
     771           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     772           0 :         ADS_STRUCT *ads = NULL;
     773           0 :         const char *attrs[] = {"memberOf", NULL};
     774           0 :         uint32_t num_groups = 0;
     775           0 :         struct dom_sid *group_sids = NULL;
     776           0 :         size_t i;
     777           0 :         char **strings = NULL;
     778           0 :         size_t num_strings = 0, num_sids = 0;
     779             : 
     780             : 
     781           0 :         DEBUG(3,("ads: lookup_usergroups_memberof\n"));
     782             : 
     783           0 :         if ( !winbindd_can_contact_domain( domain ) ) {
     784           0 :                 DEBUG(10,("lookup_usergroups_memberof: No incoming trust for "
     785             :                           "domain %s\n", domain->name));
     786           0 :                 return NT_STATUS_OK;
     787             :         }
     788             : 
     789           0 :         rc = ads_cached_connection(domain, &ads);
     790           0 :         if (!ADS_ERR_OK(rc)) {
     791           0 :                 domain->last_status = NT_STATUS_SERVER_DISABLED;
     792           0 :                 return NT_STATUS_UNSUCCESSFUL;
     793             :         }
     794             : 
     795           0 :         rc = ads_search_retry_extended_dn_ranged(ads, mem_ctx, user_dn, attrs,
     796             :                                                  ADS_EXTENDED_DN_HEX_STRING,
     797             :                                                  &strings, &num_strings);
     798             : 
     799           0 :         if (!ADS_ERR_OK(rc)) {
     800           0 :                 DEBUG(1,("lookup_usergroups_memberof ads_search "
     801             :                         "member=%s: %s\n", user_dn, ads_errstr(rc)));
     802           0 :                 return ads_ntstatus(rc);
     803             :         }
     804             : 
     805           0 :         *user_sids = NULL;
     806           0 :         num_groups = 0;
     807             : 
     808             :         /* always add the primary group to the sid array */
     809           0 :         status = add_sid_to_array(mem_ctx, primary_group, user_sids,
     810             :                                   &num_groups);
     811           0 :         if (!NT_STATUS_IS_OK(status)) {
     812           0 :                 goto done;
     813             :         }
     814             : 
     815           0 :         group_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_strings + 1);
     816           0 :         if (!group_sids) {
     817           0 :                 status = NT_STATUS_NO_MEMORY;
     818           0 :                 goto done;
     819             :         }
     820             : 
     821           0 :         for (i=0; i<num_strings; i++) {
     822           0 :                 rc = ads_get_sid_from_extended_dn(mem_ctx, strings[i],
     823             :                                                   ADS_EXTENDED_DN_HEX_STRING,
     824           0 :                                                   &(group_sids)[i]);
     825           0 :                 if (!ADS_ERR_OK(rc)) {
     826             :                         /* ignore members without SIDs */
     827           0 :                         if (NT_STATUS_EQUAL(ads_ntstatus(rc),
     828             :                             NT_STATUS_NOT_FOUND)) {
     829           0 :                                 continue;
     830             :                         }
     831             :                         else {
     832           0 :                                 status = ads_ntstatus(rc);
     833           0 :                                 goto done;
     834             :                         }
     835             :                 }
     836           0 :                 num_sids++;
     837             :         }
     838             : 
     839           0 :         if (i == 0) {
     840           0 :                 DEBUG(1,("No memberOf for this user?!?\n"));
     841           0 :                 status = NT_STATUS_NO_MEMORY;
     842           0 :                 goto done;
     843             :         }
     844             : 
     845           0 :         for (i=0; i<num_sids; i++) {
     846             : 
     847             :                 /* ignore Builtin groups from ADS - Guenther */
     848           0 :                 if (sid_check_is_in_builtin(&group_sids[i])) {
     849           0 :                         continue;
     850             :                 }
     851             : 
     852           0 :                 status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
     853             :                                           &num_groups);
     854           0 :                 if (!NT_STATUS_IS_OK(status)) {
     855           0 :                         goto done;
     856             :                 }
     857             : 
     858             :         }
     859             : 
     860           0 :         *p_num_groups = num_groups;
     861           0 :         status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
     862             : 
     863           0 :         DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n",
     864             :                 user_dn));
     865             : 
     866           0 : done:
     867           0 :         TALLOC_FREE(strings);
     868           0 :         TALLOC_FREE(group_sids);
     869             : 
     870           0 :         return status;
     871             : }
     872             : 
     873             : 
     874             : /* Lookup groups a user is a member of. */
     875           0 : static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
     876             :                                   TALLOC_CTX *mem_ctx,
     877             :                                   const struct dom_sid *sid,
     878             :                                   uint32_t *p_num_groups, struct dom_sid **user_sids)
     879             : {
     880           0 :         ADS_STRUCT *ads = NULL;
     881           0 :         const char *attrs[] = {"tokenGroups", "primaryGroupID", NULL};
     882           0 :         ADS_STATUS rc;
     883           0 :         int count;
     884           0 :         LDAPMessage *msg = NULL;
     885           0 :         char *user_dn = NULL;
     886           0 :         struct dom_sid *sids;
     887           0 :         int i;
     888           0 :         struct dom_sid primary_group;
     889           0 :         uint32_t primary_group_rid;
     890           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     891           0 :         uint32_t num_groups = 0;
     892           0 :         struct dom_sid_buf buf;
     893             : 
     894           0 :         DEBUG(3,("ads: lookup_usergroups\n"));
     895           0 :         *p_num_groups = 0;
     896             : 
     897           0 :         status = lookup_usergroups_cached(mem_ctx, sid,
     898             :                                           p_num_groups, user_sids);
     899           0 :         if (NT_STATUS_IS_OK(status)) {
     900           0 :                 return NT_STATUS_OK;
     901             :         }
     902             : 
     903           0 :         if ( !winbindd_can_contact_domain( domain ) ) {
     904           0 :                 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
     905             :                           domain->name));
     906             : 
     907             :                 /* Tell the cache manager not to remember this one */
     908             : 
     909           0 :                 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
     910             :         }
     911             : 
     912           0 :         rc = ads_cached_connection(domain, &ads);
     913           0 :         if (!ADS_ERR_OK(rc)) {
     914           0 :                 domain->last_status = NT_STATUS_SERVER_DISABLED;
     915           0 :                 status = NT_STATUS_SERVER_DISABLED;
     916           0 :                 goto done;
     917             :         }
     918             : 
     919           0 :         rc = ads_search_retry_sid(ads, &msg, sid, attrs);
     920             : 
     921           0 :         if (!ADS_ERR_OK(rc)) {
     922           0 :                 status = ads_ntstatus(rc);
     923           0 :                 DEBUG(1, ("lookup_usergroups(sid=%s) ads_search tokenGroups: "
     924             :                           "%s\n",
     925             :                           dom_sid_str_buf(sid, &buf),
     926             :                           ads_errstr(rc)));
     927           0 :                 goto done;
     928             :         }
     929             : 
     930           0 :         count = ads_count_replies(ads, msg);
     931           0 :         if (count != 1) {
     932           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     933           0 :                 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
     934             :                          "invalid number of results (count=%d)\n",
     935             :                          dom_sid_str_buf(sid, &buf),
     936             :                          count));
     937           0 :                 goto done;
     938             :         }
     939             : 
     940           0 :         if (!msg) {
     941           0 :                 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
     942             :                          dom_sid_str_buf(sid, &buf)));
     943           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     944           0 :                 goto done;
     945             :         }
     946             : 
     947           0 :         user_dn = ads_get_dn(ads, mem_ctx, msg);
     948           0 :         if (user_dn == NULL) {
     949           0 :                 status = NT_STATUS_NO_MEMORY;
     950           0 :                 goto done;
     951             :         }
     952             : 
     953           0 :         if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
     954           0 :                 DEBUG(1,("%s: No primary group for sid=%s !?\n",
     955             :                          domain->name,
     956             :                          dom_sid_str_buf(sid, &buf)));
     957           0 :                 goto done;
     958             :         }
     959             : 
     960           0 :         sid_compose(&primary_group, &domain->sid, primary_group_rid);
     961             : 
     962           0 :         count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids);
     963             : 
     964             :         /* there must always be at least one group in the token,
     965             :            unless we are talking to a buggy Win2k server */
     966             : 
     967             :         /* actually this only happens when the machine account has no read
     968             :          * permissions on the tokenGroup attribute - gd */
     969             : 
     970           0 :         if (count == 0) {
     971             : 
     972             :                 /* no tokenGroups */
     973             : 
     974             :                 /* lookup what groups this user is a member of by DN search on
     975             :                  * "memberOf" */
     976             : 
     977           0 :                 status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
     978             :                                                     &primary_group,
     979             :                                                     &num_groups, user_sids);
     980           0 :                 *p_num_groups = num_groups;
     981           0 :                 if (NT_STATUS_IS_OK(status)) {
     982           0 :                         goto done;
     983             :                 }
     984             : 
     985             :                 /* lookup what groups this user is a member of by DN search on
     986             :                  * "member" */
     987             : 
     988           0 :                 status = lookup_usergroups_member(domain, mem_ctx, user_dn,
     989             :                                                   &primary_group,
     990             :                                                   &num_groups, user_sids);
     991           0 :                 *p_num_groups = num_groups;
     992           0 :                 goto done;
     993             :         }
     994             : 
     995           0 :         *user_sids = NULL;
     996           0 :         num_groups = 0;
     997             : 
     998           0 :         status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
     999             :                                   &num_groups);
    1000           0 :         if (!NT_STATUS_IS_OK(status)) {
    1001           0 :                 goto done;
    1002             :         }
    1003             : 
    1004           0 :         for (i=0;i<count;i++) {
    1005             : 
    1006             :                 /* ignore Builtin groups from ADS - Guenther */
    1007           0 :                 if (sid_check_is_in_builtin(&sids[i])) {
    1008           0 :                         continue;
    1009             :                 }
    1010             : 
    1011           0 :                 status = add_sid_to_array_unique(mem_ctx, &sids[i],
    1012             :                                                  user_sids, &num_groups);
    1013           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1014           0 :                         goto done;
    1015             :                 }
    1016             :         }
    1017             : 
    1018           0 :         *p_num_groups = (uint32_t)num_groups;
    1019           0 :         status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
    1020             : 
    1021           0 :         DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
    1022             :                  dom_sid_str_buf(sid, &buf)));
    1023           0 : done:
    1024           0 :         TALLOC_FREE(user_dn);
    1025           0 :         ads_msgfree(ads, msg);
    1026           0 :         return status;
    1027             : }
    1028             : 
    1029             : /* Lookup aliases a user is member of - use rpc methods */
    1030           0 : static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
    1031             :                                    TALLOC_CTX *mem_ctx,
    1032             :                                    uint32_t num_sids, const struct dom_sid *sids,
    1033             :                                    uint32_t *num_aliases, uint32_t **alias_rids)
    1034             : {
    1035           0 :         return msrpc_methods.lookup_useraliases(domain, mem_ctx, num_sids, sids,
    1036             :                                                 num_aliases, alias_rids);
    1037             : }
    1038             : 
    1039           0 : static NTSTATUS add_primary_group_members(
    1040             :         ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, uint32_t rid,
    1041             :         char ***all_members, size_t *num_all_members)
    1042             : {
    1043           0 :         char *filter;
    1044           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    1045           0 :         ADS_STATUS rc;
    1046           0 :         const char *attrs[] = { "dn", NULL };
    1047           0 :         LDAPMessage *res = NULL;
    1048           0 :         LDAPMessage *msg;
    1049           0 :         char **members;
    1050           0 :         size_t num_members;
    1051           0 :         ads_control args;
    1052             : 
    1053           0 :         filter = talloc_asprintf(
    1054             :                 mem_ctx, "(&(objectCategory=user)(primaryGroupID=%u))",
    1055             :                 (unsigned)rid);
    1056           0 :         if (filter == NULL) {
    1057           0 :                 goto done;
    1058             :         }
    1059             : 
    1060           0 :         args.control = ADS_EXTENDED_DN_OID;
    1061           0 :         args.val = ADS_EXTENDED_DN_HEX_STRING;
    1062           0 :         args.critical = True;
    1063             : 
    1064           0 :         rc = ads_do_search_all_args(ads, ads->config.bind_path,
    1065             :                                     LDAP_SCOPE_SUBTREE, filter, attrs, &args,
    1066             :                                     &res);
    1067             : 
    1068           0 :         if (!ADS_ERR_OK(rc)) {
    1069           0 :                 status = ads_ntstatus(rc);
    1070           0 :                 DEBUG(1,("%s: ads_search: %s\n", __func__, ads_errstr(rc)));
    1071           0 :                 goto done;
    1072             :         }
    1073           0 :         if (res == NULL) {
    1074           0 :                 DEBUG(1,("%s: ads_search returned NULL res\n", __func__));
    1075           0 :                 goto done;
    1076             :         }
    1077             : 
    1078           0 :         num_members = ads_count_replies(ads, res);
    1079             : 
    1080           0 :         DEBUG(10, ("%s: Got %ju primary group members\n", __func__,
    1081             :                    (uintmax_t)num_members));
    1082             : 
    1083           0 :         if (num_members == 0) {
    1084           0 :                 status = NT_STATUS_OK;
    1085           0 :                 goto done;
    1086             :         }
    1087             : 
    1088           0 :         members = talloc_realloc(mem_ctx, *all_members, char *,
    1089             :                                  *num_all_members + num_members);
    1090           0 :         if (members == NULL) {
    1091           0 :                 DEBUG(1, ("%s: talloc_realloc failed\n", __func__));
    1092           0 :                 goto done;
    1093             :         }
    1094           0 :         *all_members = members;
    1095             : 
    1096           0 :         for (msg = ads_first_entry(ads, res); msg != NULL;
    1097           0 :              msg = ads_next_entry(ads, msg)) {
    1098           0 :                 char *dn;
    1099             : 
    1100           0 :                 dn = ads_get_dn(ads, members, msg);
    1101           0 :                 if (dn == NULL) {
    1102           0 :                         DEBUG(1, ("%s: ads_get_dn failed\n", __func__));
    1103           0 :                         continue;
    1104             :                 }
    1105             : 
    1106           0 :                 members[*num_all_members] = dn;
    1107           0 :                 *num_all_members += 1;
    1108             :         }
    1109             : 
    1110           0 :         status = NT_STATUS_OK;
    1111           0 : done:
    1112           0 :         if (res != NULL) {
    1113           0 :                 ads_msgfree(ads, res);
    1114             :         }
    1115           0 :         TALLOC_FREE(filter);
    1116           0 :         return status;
    1117             : }
    1118             : 
    1119             : /*
    1120             :   find the members of a group, given a group rid and domain
    1121             :  */
    1122           0 : static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
    1123             :                                 TALLOC_CTX *mem_ctx,
    1124             :                                 const struct dom_sid *group_sid,
    1125             :                                 enum lsa_SidType type,
    1126             :                                 uint32_t *num_names,
    1127             :                                 struct dom_sid **sid_mem, char ***names,
    1128             :                                 uint32_t **name_types)
    1129             : {
    1130           0 :         ADS_STATUS rc;
    1131           0 :         ADS_STRUCT *ads = NULL;
    1132           0 :         char *ldap_exp;
    1133           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
    1134           0 :         char *sidbinstr;
    1135           0 :         char **members = NULL;
    1136           0 :         size_t i;
    1137           0 :         size_t num_members = 0;
    1138           0 :         ads_control args;
    1139           0 :         struct dom_sid *sid_mem_nocache = NULL;
    1140           0 :         char **names_nocache = NULL;
    1141           0 :         enum lsa_SidType *name_types_nocache = NULL;
    1142           0 :         char **domains_nocache = NULL;     /* only needed for rpccli_lsa_lookup_sids */
    1143           0 :         uint32_t num_nocache = 0;
    1144           0 :         TALLOC_CTX *tmp_ctx = NULL;
    1145           0 :         uint32_t rid;
    1146           0 :         struct dom_sid_buf buf;
    1147             : 
    1148           0 :         DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name,
    1149             :                   dom_sid_str_buf(group_sid, &buf)));
    1150             : 
    1151           0 :         *num_names = 0;
    1152             : 
    1153           0 :         tmp_ctx = talloc_new(mem_ctx);
    1154           0 :         if (!tmp_ctx) {
    1155           0 :                 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
    1156           0 :                 status = NT_STATUS_NO_MEMORY;
    1157           0 :                 goto done;
    1158             :         }
    1159             : 
    1160           0 :         if (!sid_peek_rid(group_sid, &rid)) {
    1161           0 :                 DEBUG(1, ("%s: sid_peek_rid failed\n", __func__));
    1162           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    1163           0 :                 goto done;
    1164             :         }
    1165             : 
    1166           0 :         if ( !winbindd_can_contact_domain( domain ) ) {
    1167           0 :                 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
    1168             :                           domain->name));
    1169           0 :                 return NT_STATUS_OK;
    1170             :         }
    1171             : 
    1172           0 :         rc = ads_cached_connection(domain, &ads);
    1173           0 :         if (!ADS_ERR_OK(rc)) {
    1174           0 :                 domain->last_status = NT_STATUS_SERVER_DISABLED;
    1175           0 :                 goto done;
    1176             :         }
    1177             : 
    1178           0 :         if ((sidbinstr = ldap_encode_ndr_dom_sid(talloc_tos(), group_sid)) == NULL) {
    1179           0 :                 status = NT_STATUS_NO_MEMORY;
    1180           0 :                 goto done;
    1181             :         }
    1182             : 
    1183             :         /* search for all members of the group */
    1184           0 :         ldap_exp = talloc_asprintf(tmp_ctx, "(objectSid=%s)", sidbinstr);
    1185           0 :         TALLOC_FREE(sidbinstr);
    1186           0 :         if (ldap_exp == NULL) {
    1187           0 :                 DEBUG(1, ("ads: lookup_groupmem: talloc_asprintf for ldap_exp failed!\n"));
    1188           0 :                 status = NT_STATUS_NO_MEMORY;
    1189           0 :                 goto done;
    1190             :         }
    1191             : 
    1192           0 :         args.control = ADS_EXTENDED_DN_OID;
    1193           0 :         args.val = ADS_EXTENDED_DN_HEX_STRING;
    1194           0 :         args.critical = True;
    1195             : 
    1196           0 :         rc = ads_ranged_search(ads, tmp_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path,
    1197             :                                ldap_exp, &args, "member", &members, &num_members);
    1198             : 
    1199           0 :         if (!ADS_ERR_OK(rc)) {
    1200           0 :                 DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc)));
    1201           0 :                 status = NT_STATUS_UNSUCCESSFUL;
    1202           0 :                 goto done;
    1203             :         }
    1204             : 
    1205           0 :         DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members));
    1206             : 
    1207           0 :         status = add_primary_group_members(ads, mem_ctx, rid,
    1208             :                                            &members, &num_members);
    1209           0 :         if (!NT_STATUS_IS_OK(status)) {
    1210           0 :                 DEBUG(10, ("%s: add_primary_group_members failed: %s\n",
    1211             :                            __func__, nt_errstr(status)));
    1212           0 :                 goto done;
    1213             :         }
    1214             : 
    1215           0 :         DEBUG(10, ("%s: Got %d sids after adding primary group members\n",
    1216             :                    __func__, (int)num_members));
    1217             : 
    1218             :         /* Now that we have a list of sids, we need to get the
    1219             :          * lists of names and name_types belonging to these sids.
    1220             :          * even though conceptually not quite clean,  we use the
    1221             :          * RPC call lsa_lookup_sids for this since it can handle a
    1222             :          * list of sids. ldap calls can just resolve one sid at a time.
    1223             :          *
    1224             :          * At this stage, the sids are still hidden in the exetended dn
    1225             :          * member output format. We actually do a little better than
    1226             :          * stated above: In extracting the sids from the member strings,
    1227             :          * we try to resolve as many sids as possible from the
    1228             :          * cache. Only the rest is passed to the lsa_lookup_sids call. */
    1229             : 
    1230           0 :         if (num_members) {
    1231           0 :                 (*sid_mem) = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
    1232           0 :                 (*names) = talloc_zero_array(mem_ctx, char *, num_members);
    1233           0 :                 (*name_types) = talloc_zero_array(mem_ctx, uint32_t, num_members);
    1234           0 :                 (sid_mem_nocache) = talloc_zero_array(tmp_ctx, struct dom_sid, num_members);
    1235             : 
    1236           0 :                 if ((members == NULL) || (*sid_mem == NULL) ||
    1237           0 :                     (*names == NULL) || (*name_types == NULL) ||
    1238             :                     (sid_mem_nocache == NULL))
    1239             :                 {
    1240           0 :                         DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
    1241           0 :                         status = NT_STATUS_NO_MEMORY;
    1242           0 :                         goto done;
    1243             :                 }
    1244             :         }
    1245             :         else {
    1246           0 :                 (*sid_mem) = NULL;
    1247           0 :                 (*names) = NULL;
    1248           0 :                 (*name_types) = NULL;
    1249             :         }
    1250             : 
    1251           0 :         for (i=0; i<num_members; i++) {
    1252           0 :                 enum lsa_SidType name_type;
    1253           0 :                 char *name, *domain_name;
    1254           0 :                 struct dom_sid sid;
    1255             : 
    1256           0 :                 rc = ads_get_sid_from_extended_dn(tmp_ctx, members[i], args.val,
    1257             :                     &sid);
    1258           0 :                 if (!ADS_ERR_OK(rc)) {
    1259           0 :                         if (NT_STATUS_EQUAL(ads_ntstatus(rc),
    1260             :                             NT_STATUS_NOT_FOUND)) {
    1261             :                                 /* Group members can be objects, like Exchange
    1262             :                                  * Public Folders, that don't have a SID.  Skip
    1263             :                                  * them. */
    1264           0 :                                 continue;
    1265             :                         }
    1266             :                         else {
    1267           0 :                                 status = ads_ntstatus(rc);
    1268           0 :                                 goto done;
    1269             :                         }
    1270             :                 }
    1271           0 :                 if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name,
    1272             :                     &name_type)) {
    1273           0 :                         DEBUG(10,("ads: lookup_groupmem: got sid %s from "
    1274             :                                   "cache\n",
    1275             :                                   dom_sid_str_buf(&sid, &buf)));
    1276           0 :                         sid_copy(&(*sid_mem)[*num_names], &sid);
    1277           0 :                         (*names)[*num_names] = fill_domain_username_talloc(
    1278             :                                                         *names,
    1279             :                                                         domain_name,
    1280             :                                                         name,
    1281             :                                                         true);
    1282             : 
    1283           0 :                         (*name_types)[*num_names] = name_type;
    1284           0 :                         (*num_names)++;
    1285             :                 }
    1286             :                 else {
    1287           0 :                         DEBUG(10, ("ads: lookup_groupmem: sid %s not found in "
    1288             :                                    "cache\n",
    1289             :                                    dom_sid_str_buf(&sid, &buf)));
    1290           0 :                         sid_copy(&(sid_mem_nocache)[num_nocache], &sid);
    1291           0 :                         num_nocache++;
    1292             :                 }
    1293             :         }
    1294             : 
    1295           0 :         DEBUG(10, ("ads: lookup_groupmem: %d sids found in cache, "
    1296             :                   "%d left for lsa_lookupsids\n", *num_names, num_nocache));
    1297             : 
    1298             :         /* handle sids not resolved from cache by lsa_lookup_sids */
    1299           0 :         if (num_nocache > 0) {
    1300             : 
    1301           0 :                 status = winbindd_lookup_sids(tmp_ctx,
    1302             :                                               domain,
    1303             :                                               num_nocache,
    1304             :                                               sid_mem_nocache,
    1305             :                                               &domains_nocache,
    1306             :                                               &names_nocache,
    1307             :                                               &name_types_nocache);
    1308             : 
    1309           0 :                 if (!(NT_STATUS_IS_OK(status) ||
    1310           0 :                       NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED) ||
    1311           0 :                       NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)))
    1312             :                 {
    1313           0 :                         DEBUG(1, ("lsa_lookupsids call failed with %s "
    1314             :                                   "- retrying...\n", nt_errstr(status)));
    1315             : 
    1316           0 :                         status = winbindd_lookup_sids(tmp_ctx,
    1317             :                                                       domain,
    1318             :                                                       num_nocache,
    1319             :                                                       sid_mem_nocache,
    1320             :                                                       &domains_nocache,
    1321             :                                                       &names_nocache,
    1322             :                                                       &name_types_nocache);
    1323             :                 }
    1324             : 
    1325           0 :                 if (NT_STATUS_IS_OK(status) ||
    1326           0 :                     NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED))
    1327             :                 {
    1328             :                         /* Copy the entries over from the "_nocache" arrays
    1329             :                          * to the result arrays, skipping the gaps the
    1330             :                          * lookup_sids call left. */
    1331           0 :                         for (i=0; i < num_nocache; i++) {
    1332           0 :                                 if (((names_nocache)[i] != NULL) &&
    1333           0 :                                     ((name_types_nocache)[i] != SID_NAME_UNKNOWN))
    1334             :                                 {
    1335           0 :                                         sid_copy(&(*sid_mem)[*num_names],
    1336           0 :                                                  &sid_mem_nocache[i]);
    1337           0 :                                         (*names)[*num_names] =
    1338           0 :                                                 fill_domain_username_talloc(
    1339             :                                                         *names,
    1340           0 :                                                         domains_nocache[i],
    1341           0 :                                                         names_nocache[i],
    1342             :                                                         true);
    1343           0 :                                         (*name_types)[*num_names] = name_types_nocache[i];
    1344           0 :                                         (*num_names)++;
    1345             :                                 }
    1346             :                         }
    1347             :                 }
    1348           0 :                 else if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
    1349           0 :                         DEBUG(10, ("lookup_groupmem: lsa_lookup_sids could "
    1350             :                                    "not map any SIDs at all.\n"));
    1351             :                         /* Don't handle this as an error here.
    1352             :                          * There is nothing left to do with respect to the
    1353             :                          * overall result... */
    1354             :                 }
    1355           0 :                 else if (!NT_STATUS_IS_OK(status)) {
    1356           0 :                         DEBUG(10, ("lookup_groupmem: Error looking up %d "
    1357             :                                    "sids via rpc_lsa_lookup_sids: %s\n",
    1358             :                                    (int)num_members, nt_errstr(status)));
    1359           0 :                         goto done;
    1360             :                 }
    1361             :         }
    1362             : 
    1363           0 :         status = NT_STATUS_OK;
    1364           0 :         DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n",
    1365             :                  dom_sid_str_buf(group_sid, &buf)));
    1366             : 
    1367           0 : done:
    1368             : 
    1369           0 :         TALLOC_FREE(tmp_ctx);
    1370             : 
    1371           0 :         return status;
    1372             : }
    1373             : 
    1374           0 : static NTSTATUS lookup_aliasmem(struct winbindd_domain *domain,
    1375             :                                 TALLOC_CTX *mem_ctx,
    1376             :                                 const struct dom_sid *sid,
    1377             :                                 enum lsa_SidType type,
    1378             :                                 uint32_t *num_sids,
    1379             :                                 struct dom_sid **sids)
    1380             : {
    1381           0 :         char **names = NULL;
    1382           0 :         uint32_t *name_types = NULL;
    1383           0 :         struct dom_sid_buf buf;
    1384             : 
    1385           0 :         DBG_DEBUG("ads: lookup_aliasmem %s sid=%s\n",
    1386             :                   domain->name,
    1387             :                   dom_sid_str_buf(sid, &buf));
    1388             :         /* Search for alias and group membership uses the same LDAP command. */
    1389           0 :         return lookup_groupmem(domain,
    1390             :                                mem_ctx,
    1391             :                                sid,
    1392             :                                type,
    1393             :                                num_sids,
    1394             :                                sids,
    1395             :                                &names,
    1396             :                                &name_types);
    1397             : }
    1398             : 
    1399             : /* find the lockout policy of a domain - use rpc methods */
    1400           0 : static NTSTATUS lockout_policy(struct winbindd_domain *domain,
    1401             :                                TALLOC_CTX *mem_ctx,
    1402             :                                struct samr_DomInfo12 *policy)
    1403             : {
    1404           0 :         return msrpc_methods.lockout_policy(domain, mem_ctx, policy);
    1405             : }
    1406             : 
    1407             : /* find the password policy of a domain - use rpc methods */
    1408           0 : static NTSTATUS password_policy(struct winbindd_domain *domain,
    1409             :                                 TALLOC_CTX *mem_ctx,
    1410             :                                 struct samr_DomInfo1 *policy)
    1411             : {
    1412           0 :         return msrpc_methods.password_policy(domain, mem_ctx, policy);
    1413             : }
    1414             : 
    1415             : /* get a list of trusted domains */
    1416           0 : static NTSTATUS trusted_domains(struct winbindd_domain *domain,
    1417             :                                 TALLOC_CTX *mem_ctx,
    1418             :                                 struct netr_DomainTrustList *trusts)
    1419             : {
    1420           0 :         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
    1421           0 :         WERROR werr;
    1422           0 :         uint32_t                i;
    1423           0 :         uint32_t                flags;
    1424           0 :         struct rpc_pipe_client *cli;
    1425           0 :         struct dcerpc_binding_handle *b;
    1426             : 
    1427           0 :         DEBUG(3,("ads: trusted_domains\n"));
    1428             : 
    1429           0 :         ZERO_STRUCTP(trusts);
    1430             : 
    1431             :         /* If this is our primary domain or a root in our forest,
    1432             :            query for all trusts.  If not, then just look for domain
    1433             :            trusts in the target forest */
    1434             : 
    1435           0 :         if (domain->primary || domain_is_forest_root(domain)) {
    1436           0 :                 flags = NETR_TRUST_FLAG_OUTBOUND |
    1437             :                         NETR_TRUST_FLAG_INBOUND |
    1438             :                         NETR_TRUST_FLAG_IN_FOREST;
    1439             :         } else {
    1440           0 :                 flags = NETR_TRUST_FLAG_IN_FOREST;
    1441             :         }
    1442             : 
    1443           0 :         result = cm_connect_netlogon(domain, &cli);
    1444             : 
    1445           0 :         if (!NT_STATUS_IS_OK(result)) {
    1446           0 :                 DEBUG(5, ("trusted_domains: Could not open a connection to %s "
    1447             :                           "for PIPE_NETLOGON (%s)\n",
    1448             :                           domain->name, nt_errstr(result)));
    1449           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1450             :         }
    1451             : 
    1452           0 :         b = cli->binding_handle;
    1453             : 
    1454           0 :         result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
    1455           0 :                                                       cli->desthost,
    1456             :                                                       flags,
    1457             :                                                       trusts,
    1458             :                                                       &werr);
    1459           0 :         if (!NT_STATUS_IS_OK(result)) {
    1460           0 :                 return result;
    1461             :         }
    1462             : 
    1463           0 :         if (!W_ERROR_IS_OK(werr)) {
    1464           0 :                 return werror_to_ntstatus(werr);
    1465             :         }
    1466           0 :         if (trusts->count == 0) {
    1467           0 :                 return NT_STATUS_OK;
    1468             :         }
    1469             : 
    1470             :         /* Copy across names and sids */
    1471             : 
    1472           0 :         for (i = 0; i < trusts->count; i++) {
    1473           0 :                 struct netr_DomainTrust *trust = &trusts->array[i];
    1474           0 :                 struct winbindd_domain d;
    1475             : 
    1476           0 :                 ZERO_STRUCT(d);
    1477             : 
    1478             :                 /*
    1479             :                  * drop external trusts if this is not our primary
    1480             :                  * domain.  This means that the returned number of
    1481             :                  * domains may be less that the ones actually trusted
    1482             :                  * by the DC.
    1483             :                  */
    1484             : 
    1485           0 :                 if ((trust->trust_attributes
    1486           0 :                      & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
    1487           0 :                     !domain->primary )
    1488             :                 {
    1489           0 :                         DEBUG(10,("trusted_domains: Skipping external trusted "
    1490             :                                   "domain %s because it is outside of our "
    1491             :                                   "primary domain\n",
    1492             :                                   trust->netbios_name));
    1493           0 :                         continue;
    1494             :                 }
    1495             : 
    1496             :                 /* add to the trusted domain cache */
    1497             : 
    1498           0 :                 d.name = discard_const_p(char, trust->netbios_name);
    1499           0 :                 d.alt_name = discard_const_p(char, trust->dns_name);
    1500             : 
    1501           0 :                 if (trust->sid) {
    1502           0 :                         sid_copy(&d.sid, trust->sid);
    1503             :                 } else {
    1504           0 :                         sid_copy(&d.sid, &global_sid_NULL);
    1505             :                 }
    1506             : 
    1507           0 :                 if ( domain->primary ) {
    1508           0 :                         DEBUG(10,("trusted_domains(ads):  Searching "
    1509             :                                   "trusted domain list of %s and storing "
    1510             :                                   "trust flags for domain %s\n",
    1511             :                                   domain->name, d.alt_name));
    1512             : 
    1513           0 :                         d.domain_flags = trust->trust_flags;
    1514           0 :                         d.domain_type = trust->trust_type;
    1515           0 :                         d.domain_trust_attribs = trust->trust_attributes;
    1516             : 
    1517           0 :                         wcache_tdc_add_domain( &d );
    1518           0 :                 } else if (domain_is_forest_root(domain)) {
    1519             :                         /* Check if we already have this record. If
    1520             :                          * we are following our forest root that is not
    1521             :                          * our primary domain, we want to keep trust
    1522             :                          * flags from the perspective of our primary
    1523             :                          * domain not our forest root. */
    1524           0 :                         struct winbindd_tdc_domain *exist = NULL;
    1525             : 
    1526           0 :                         exist = wcache_tdc_fetch_domain(
    1527             :                                 talloc_tos(), trust->netbios_name);
    1528           0 :                         if (!exist) {
    1529           0 :                                 DEBUG(10,("trusted_domains(ads):  Searching "
    1530             :                                           "trusted domain list of %s and "
    1531             :                                           "storing trust flags for domain "
    1532             :                                           "%s\n", domain->name, d.alt_name));
    1533           0 :                                 d.domain_flags = trust->trust_flags;
    1534           0 :                                 d.domain_type = trust->trust_type;
    1535           0 :                                 d.domain_trust_attribs =
    1536           0 :                                         trust->trust_attributes;
    1537             : 
    1538           0 :                                 wcache_tdc_add_domain( &d );
    1539             :                         }
    1540           0 :                         TALLOC_FREE(exist);
    1541             :                 } else {
    1542             :                         /* This gets a little tricky.  If we are
    1543             :                            following a transitive forest trust, then
    1544             :                            innerit the flags, type, and attribs from
    1545             :                            the domain we queried to make sure we don't
    1546             :                            record the view of the trust from the wrong
    1547             :                            side.  Always view it from the side of our
    1548             :                            primary domain.   --jerry */
    1549           0 :                         struct winbindd_tdc_domain *parent = NULL;
    1550             : 
    1551           0 :                         DEBUG(10,("trusted_domains(ads):  Searching "
    1552             :                                   "trusted domain list of %s and inheriting "
    1553             :                                   "trust flags for domain %s\n",
    1554             :                                   domain->name, d.alt_name));
    1555             : 
    1556           0 :                         parent = wcache_tdc_fetch_domain(talloc_tos(),
    1557           0 :                                                          domain->name);
    1558           0 :                         if (parent) {
    1559           0 :                                 d.domain_flags = parent->trust_flags;
    1560           0 :                                 d.domain_type  = parent->trust_type;
    1561           0 :                                 d.domain_trust_attribs = parent->trust_attribs;
    1562             :                         } else {
    1563           0 :                                 d.domain_flags = domain->domain_flags;
    1564           0 :                                 d.domain_type  = domain->domain_type;
    1565           0 :                                 d.domain_trust_attribs =
    1566           0 :                                         domain->domain_trust_attribs;
    1567             :                         }
    1568           0 :                         TALLOC_FREE(parent);
    1569             : 
    1570             :                         /*
    1571             :                          * We need to pass the modified properties
    1572             :                          * to the caller.
    1573             :                          */
    1574           0 :                         trust->trust_flags = d.domain_flags;
    1575           0 :                         trust->trust_type = d.domain_type;
    1576           0 :                         trust->trust_attributes = d.domain_trust_attribs;
    1577             : 
    1578           0 :                         wcache_tdc_add_domain( &d );
    1579             :                 }
    1580             :         }
    1581           0 :         return result;
    1582             : }
    1583             : 
    1584             : /* the ADS backend methods are exposed via this structure */
    1585             : struct winbindd_methods ads_methods = {
    1586             :         True,
    1587             :         query_user_list,
    1588             :         enum_dom_groups,
    1589             :         enum_local_groups,
    1590             :         name_to_sid,
    1591             :         sid_to_name,
    1592             :         rids_to_names,
    1593             :         lookup_usergroups,
    1594             :         lookup_useraliases,
    1595             :         lookup_groupmem,
    1596             :         lookup_aliasmem,
    1597             :         lockout_policy,
    1598             :         password_policy,
    1599             :         trusted_domains,
    1600             : };
    1601             : 
    1602             : #endif

Generated by: LCOV version 1.14