LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd_ads.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 0 680 0.0 %
Date: 2024-06-13 04:01:37 Functions: 0 19 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             :                 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 acount 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             :         ADS_STRUCT *ads;
     104             :         ADS_STATUS status;
     105             :         struct sockaddr_storage dc_ss;
     106             :         fstring dc_name;
     107             :         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 :         TALLOC_FREE(ads->auth.password);
     129           0 :         TALLOC_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             :         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 nam 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             :         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             :         int count;
     371           0 :         uint32_t *rids = NULL;
     372             :         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             :                 struct dom_sid user_sid;
     417             :                 uint32_t atype;
     418             :                 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             :                         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             :         int i, count;
     473             :         ADS_STATUS rc;
     474           0 :         LDAPMessage *res = NULL;
     475           0 :         LDAPMessage *msg = NULL;
     476           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     477             :         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)(&(groupType:dn:%s:=%d)(!(groupType:dn:%s:=%d))))",
     513             :                                  ADS_LDAP_MATCHING_RULE_BIT_AND, GROUP_TYPE_SECURITY_ENABLED,
     514             :                                  ADS_LDAP_MATCHING_RULE_BIT_AND,
     515             :                                  enum_dom_local_groups ? GROUP_TYPE_BUILTIN_LOCAL_GROUP : GROUP_TYPE_RESOURCE_GROUP);
     516             : 
     517           0 :         if (filter == NULL) {
     518           0 :                 status = NT_STATUS_NO_MEMORY;
     519           0 :                 goto done;
     520             :         }
     521             : 
     522           0 :         rc = ads_cached_connection(domain, &ads);
     523           0 :         if (!ADS_ERR_OK(rc)) {
     524           0 :                 domain->last_status = NT_STATUS_SERVER_DISABLED;
     525           0 :                 goto done;
     526             :         }
     527             : 
     528           0 :         rc = ads_search_retry(ads, &res, filter, attrs);
     529           0 :         if (!ADS_ERR_OK(rc)) {
     530           0 :                 status = ads_ntstatus(rc);
     531           0 :                 DEBUG(1,("enum_dom_groups ads_search: %s\n", ads_errstr(rc)));
     532           0 :                 goto done;
     533           0 :         } else if (!res) {
     534           0 :                 DEBUG(1,("enum_dom_groups ads_search returned NULL res\n"));
     535           0 :                 goto done;
     536             :         }
     537             : 
     538           0 :         count = ads_count_replies(ads, res);
     539           0 :         if (count == 0) {
     540           0 :                 DEBUG(1,("enum_dom_groups: No groups found\n"));
     541           0 :                 goto done;
     542             :         }
     543             : 
     544           0 :         (*info) = talloc_zero_array(mem_ctx, struct wb_acct_info, count);
     545           0 :         if (!*info) {
     546           0 :                 status = NT_STATUS_NO_MEMORY;
     547           0 :                 goto done;
     548             :         }
     549             : 
     550           0 :         i = 0;
     551             : 
     552           0 :         for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
     553             :                 char *name, *gecos;
     554             :                 struct dom_sid sid;
     555             :                 uint32_t rid;
     556             : 
     557           0 :                 name = ads_pull_username(ads, (*info), msg);
     558           0 :                 gecos = ads_pull_string(ads, (*info), msg, "name");
     559           0 :                 if (!ads_pull_sid(ads, msg, "objectSid", &sid)) {
     560           0 :                         DEBUG(1,("No sid for %s !?\n", name));
     561           0 :                         continue;
     562             :                 }
     563             : 
     564           0 :                 if (!sid_peek_check_rid(&domain->sid, &sid, &rid)) {
     565           0 :                         DEBUG(1,("No rid for %s !?\n", name));
     566           0 :                         continue;
     567             :                 }
     568             : 
     569           0 :                 (*info)[i].acct_name = name;
     570           0 :                 (*info)[i].acct_desc = gecos;
     571           0 :                 (*info)[i].rid = rid;
     572           0 :                 i++;
     573             :         }
     574             : 
     575           0 :         (*num_entries) = i;
     576             : 
     577           0 :         status = NT_STATUS_OK;
     578             : 
     579           0 :         DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*num_entries)));
     580             : 
     581           0 : done:
     582           0 :         if (res)
     583           0 :                 ads_msgfree(ads, res);
     584             : 
     585           0 :         return status;
     586             : }
     587             : 
     588             : /* list all domain local groups */
     589           0 : static NTSTATUS enum_local_groups(struct winbindd_domain *domain,
     590             :                                 TALLOC_CTX *mem_ctx,
     591             :                                 uint32_t *num_entries,
     592             :                                 struct wb_acct_info **info)
     593             : {
     594             :         /*
     595             :          * This is a stub function only as we returned the domain
     596             :          * local groups in enum_dom_groups() if the domain->native field
     597             :          * was true.  This is a simple performance optimization when
     598             :          * using LDAP.
     599             :          *
     600             :          * if we ever need to enumerate domain local groups separately,
     601             :          * then this optimization in enum_dom_groups() will need
     602             :          * to be split out
     603             :          */
     604           0 :         *num_entries = 0;
     605             : 
     606           0 :         return NT_STATUS_OK;
     607             : }
     608             : 
     609             : /* convert a single name to a sid in a domain - use rpc methods */
     610           0 : static NTSTATUS name_to_sid(struct winbindd_domain *domain,
     611             :                             TALLOC_CTX *mem_ctx,
     612             :                             const char *domain_name,
     613             :                             const char *name,
     614             :                             uint32_t flags,
     615             :                             const char **pdom_name,
     616             :                             struct dom_sid *sid,
     617             :                             enum lsa_SidType *type)
     618             : {
     619           0 :         return msrpc_methods.name_to_sid(domain, mem_ctx, domain_name, name,
     620             :                                          flags, pdom_name, sid, type);
     621             : }
     622             : 
     623             : /* convert a domain SID to a user or group name - use rpc methods */
     624           0 : static NTSTATUS sid_to_name(struct winbindd_domain *domain,
     625             :                             TALLOC_CTX *mem_ctx,
     626             :                             const struct dom_sid *sid,
     627             :                             char **domain_name,
     628             :                             char **name,
     629             :                             enum lsa_SidType *type)
     630             : {
     631           0 :         return msrpc_methods.sid_to_name(domain, mem_ctx, sid,
     632             :                                          domain_name, name, type);
     633             : }
     634             : 
     635             : /* convert a list of rids to names - use rpc methods */
     636           0 : static NTSTATUS rids_to_names(struct winbindd_domain *domain,
     637             :                               TALLOC_CTX *mem_ctx,
     638             :                               const struct dom_sid *sid,
     639             :                               uint32_t *rids,
     640             :                               size_t num_rids,
     641             :                               char **domain_name,
     642             :                               char ***names,
     643             :                               enum lsa_SidType **types)
     644             : {
     645           0 :         return msrpc_methods.rids_to_names(domain, mem_ctx, sid,
     646             :                                            rids, num_rids,
     647             :                                            domain_name, names, types);
     648             : }
     649             : 
     650             : /* Lookup groups a user is a member of - alternate method, for when
     651             :    tokenGroups are not available. */
     652           0 : static NTSTATUS lookup_usergroups_member(struct winbindd_domain *domain,
     653             :                                          TALLOC_CTX *mem_ctx,
     654             :                                          const char *user_dn,
     655             :                                          struct dom_sid *primary_group,
     656             :                                          uint32_t *p_num_groups, struct dom_sid **user_sids)
     657             : {
     658             :         ADS_STATUS rc;
     659           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     660             :         int count;
     661           0 :         LDAPMessage *res = NULL;
     662           0 :         LDAPMessage *msg = NULL;
     663             :         char *ldap_exp;
     664           0 :         ADS_STRUCT *ads = NULL;
     665           0 :         const char *group_attrs[] = {"objectSid", NULL};
     666             :         char *escaped_dn;
     667           0 :         uint32_t num_groups = 0;
     668             : 
     669           0 :         DEBUG(3,("ads: lookup_usergroups_member\n"));
     670             : 
     671           0 :         if ( !winbindd_can_contact_domain( domain ) ) {
     672           0 :                 DEBUG(10,("lookup_usergroups_members: No incoming trust for domain %s\n",
     673             :                           domain->name));
     674           0 :                 return NT_STATUS_OK;
     675             :         }
     676             : 
     677           0 :         rc = ads_cached_connection(domain, &ads);
     678           0 :         if (!ADS_ERR_OK(rc)) {
     679           0 :                 domain->last_status = NT_STATUS_SERVER_DISABLED;
     680           0 :                 goto done;
     681             :         }
     682             : 
     683           0 :         if (!(escaped_dn = escape_ldap_string(talloc_tos(), user_dn))) {
     684           0 :                 status = NT_STATUS_NO_MEMORY;
     685           0 :                 goto done;
     686             :         }
     687             : 
     688           0 :         ldap_exp = talloc_asprintf(mem_ctx,
     689             :                 "(&(member=%s)(objectCategory=group)(groupType:dn:%s:=%d))",
     690             :                 escaped_dn,
     691             :                 ADS_LDAP_MATCHING_RULE_BIT_AND,
     692             :                 GROUP_TYPE_SECURITY_ENABLED);
     693           0 :         if (!ldap_exp) {
     694           0 :                 DEBUG(1,("lookup_usergroups(dn=%s) asprintf failed!\n", user_dn));
     695           0 :                 TALLOC_FREE(escaped_dn);
     696           0 :                 status = NT_STATUS_NO_MEMORY;
     697           0 :                 goto done;
     698             :         }
     699             : 
     700           0 :         TALLOC_FREE(escaped_dn);
     701             : 
     702           0 :         rc = ads_search_retry(ads, &res, ldap_exp, group_attrs);
     703             : 
     704           0 :         if (!ADS_ERR_OK(rc)) {
     705           0 :                 DEBUG(1,("lookup_usergroups ads_search member=%s: %s\n", user_dn, ads_errstr(rc)));
     706           0 :                 return ads_ntstatus(rc);
     707           0 :         } else if (!res) {
     708           0 :                 DEBUG(1,("lookup_usergroups ads_search returned NULL res\n"));
     709           0 :                 return NT_STATUS_INTERNAL_ERROR;
     710             :         }
     711             : 
     712             : 
     713           0 :         count = ads_count_replies(ads, res);
     714             : 
     715           0 :         *user_sids = NULL;
     716           0 :         num_groups = 0;
     717             : 
     718             :         /* always add the primary group to the sid array */
     719           0 :         status = add_sid_to_array(mem_ctx, primary_group, user_sids,
     720             :                                   &num_groups);
     721           0 :         if (!NT_STATUS_IS_OK(status)) {
     722           0 :                 goto done;
     723             :         }
     724             : 
     725           0 :         if (count > 0) {
     726           0 :                 for (msg = ads_first_entry(ads, res); msg;
     727           0 :                      msg = ads_next_entry(ads, msg)) {
     728             :                         struct dom_sid group_sid;
     729             : 
     730           0 :                         if (!ads_pull_sid(ads, msg, "objectSid", &group_sid)) {
     731           0 :                                 DEBUG(1,("No sid for this group ?!?\n"));
     732           0 :                                 continue;
     733             :                         }
     734             : 
     735             :                         /* ignore Builtin groups from ADS - Guenther */
     736           0 :                         if (sid_check_is_in_builtin(&group_sid)) {
     737           0 :                                 continue;
     738             :                         }
     739             : 
     740           0 :                         status = add_sid_to_array(mem_ctx, &group_sid,
     741             :                                                   user_sids, &num_groups);
     742           0 :                         if (!NT_STATUS_IS_OK(status)) {
     743           0 :                                 goto done;
     744             :                         }
     745             :                 }
     746             : 
     747             :         }
     748             : 
     749           0 :         *p_num_groups = num_groups;
     750           0 :         status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
     751             : 
     752           0 :         DEBUG(3,("ads lookup_usergroups (member) succeeded for dn=%s\n", user_dn));
     753           0 : done:
     754           0 :         if (res)
     755           0 :                 ads_msgfree(ads, res);
     756             : 
     757           0 :         return status;
     758             : }
     759             : 
     760             : /* Lookup groups a user is a member of - alternate method, for when
     761             :    tokenGroups are not available. */
     762           0 : static NTSTATUS lookup_usergroups_memberof(struct winbindd_domain *domain,
     763             :                                            TALLOC_CTX *mem_ctx,
     764             :                                            const char *user_dn,
     765             :                                            struct dom_sid *primary_group,
     766             :                                            uint32_t *p_num_groups,
     767             :                                            struct dom_sid **user_sids)
     768             : {
     769             :         ADS_STATUS rc;
     770           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     771           0 :         ADS_STRUCT *ads = NULL;
     772           0 :         const char *attrs[] = {"memberOf", NULL};
     773           0 :         uint32_t num_groups = 0;
     774           0 :         struct dom_sid *group_sids = NULL;
     775             :         size_t i;
     776           0 :         char **strings = NULL;
     777           0 :         size_t num_strings = 0, num_sids = 0;
     778             : 
     779             : 
     780           0 :         DEBUG(3,("ads: lookup_usergroups_memberof\n"));
     781             : 
     782           0 :         if ( !winbindd_can_contact_domain( domain ) ) {
     783           0 :                 DEBUG(10,("lookup_usergroups_memberof: No incoming trust for "
     784             :                           "domain %s\n", domain->name));
     785           0 :                 return NT_STATUS_OK;
     786             :         }
     787             : 
     788           0 :         rc = ads_cached_connection(domain, &ads);
     789           0 :         if (!ADS_ERR_OK(rc)) {
     790           0 :                 domain->last_status = NT_STATUS_SERVER_DISABLED;
     791           0 :                 return NT_STATUS_UNSUCCESSFUL;
     792             :         }
     793             : 
     794           0 :         rc = ads_search_retry_extended_dn_ranged(ads, mem_ctx, user_dn, attrs,
     795             :                                                  ADS_EXTENDED_DN_HEX_STRING,
     796             :                                                  &strings, &num_strings);
     797             : 
     798           0 :         if (!ADS_ERR_OK(rc)) {
     799           0 :                 DEBUG(1,("lookup_usergroups_memberof ads_search "
     800             :                         "member=%s: %s\n", user_dn, ads_errstr(rc)));
     801           0 :                 return ads_ntstatus(rc);
     802             :         }
     803             : 
     804           0 :         *user_sids = NULL;
     805           0 :         num_groups = 0;
     806             : 
     807             :         /* always add the primary group to the sid array */
     808           0 :         status = add_sid_to_array(mem_ctx, primary_group, user_sids,
     809             :                                   &num_groups);
     810           0 :         if (!NT_STATUS_IS_OK(status)) {
     811           0 :                 goto done;
     812             :         }
     813             : 
     814           0 :         group_sids = talloc_zero_array(mem_ctx, struct dom_sid, num_strings + 1);
     815           0 :         if (!group_sids) {
     816           0 :                 status = NT_STATUS_NO_MEMORY;
     817           0 :                 goto done;
     818             :         }
     819             : 
     820           0 :         for (i=0; i<num_strings; i++) {
     821           0 :                 rc = ads_get_sid_from_extended_dn(mem_ctx, strings[i],
     822             :                                                   ADS_EXTENDED_DN_HEX_STRING,
     823           0 :                                                   &(group_sids)[i]);
     824           0 :                 if (!ADS_ERR_OK(rc)) {
     825             :                         /* ignore members without SIDs */
     826           0 :                         if (NT_STATUS_EQUAL(ads_ntstatus(rc),
     827             :                             NT_STATUS_NOT_FOUND)) {
     828           0 :                                 continue;
     829             :                         }
     830             :                         else {
     831           0 :                                 status = ads_ntstatus(rc);
     832           0 :                                 goto done;
     833             :                         }
     834             :                 }
     835           0 :                 num_sids++;
     836             :         }
     837             : 
     838           0 :         if (i == 0) {
     839           0 :                 DEBUG(1,("No memberOf for this user?!?\n"));
     840           0 :                 status = NT_STATUS_NO_MEMORY;
     841           0 :                 goto done;
     842             :         }
     843             : 
     844           0 :         for (i=0; i<num_sids; i++) {
     845             : 
     846             :                 /* ignore Builtin groups from ADS - Guenther */
     847           0 :                 if (sid_check_is_in_builtin(&group_sids[i])) {
     848           0 :                         continue;
     849             :                 }
     850             : 
     851           0 :                 status = add_sid_to_array(mem_ctx, &group_sids[i], user_sids,
     852             :                                           &num_groups);
     853           0 :                 if (!NT_STATUS_IS_OK(status)) {
     854           0 :                         goto done;
     855             :                 }
     856             : 
     857             :         }
     858             : 
     859           0 :         *p_num_groups = num_groups;
     860           0 :         status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
     861             : 
     862           0 :         DEBUG(3,("ads lookup_usergroups (memberof) succeeded for dn=%s\n",
     863             :                 user_dn));
     864             : 
     865           0 : done:
     866           0 :         TALLOC_FREE(strings);
     867           0 :         TALLOC_FREE(group_sids);
     868             : 
     869           0 :         return status;
     870             : }
     871             : 
     872             : 
     873             : /* Lookup groups a user is a member of. */
     874           0 : static NTSTATUS lookup_usergroups(struct winbindd_domain *domain,
     875             :                                   TALLOC_CTX *mem_ctx,
     876             :                                   const struct dom_sid *sid,
     877             :                                   uint32_t *p_num_groups, struct dom_sid **user_sids)
     878             : {
     879           0 :         ADS_STRUCT *ads = NULL;
     880           0 :         const char *attrs[] = {"tokenGroups", "primaryGroupID", NULL};
     881             :         ADS_STATUS rc;
     882             :         int count;
     883           0 :         LDAPMessage *msg = NULL;
     884           0 :         char *user_dn = NULL;
     885             :         struct dom_sid *sids;
     886             :         int i;
     887             :         struct dom_sid primary_group;
     888             :         uint32_t primary_group_rid;
     889           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
     890           0 :         uint32_t num_groups = 0;
     891             :         struct dom_sid_buf buf;
     892             : 
     893           0 :         DEBUG(3,("ads: lookup_usergroups\n"));
     894           0 :         *p_num_groups = 0;
     895             : 
     896           0 :         status = lookup_usergroups_cached(mem_ctx, sid,
     897             :                                           p_num_groups, user_sids);
     898           0 :         if (NT_STATUS_IS_OK(status)) {
     899           0 :                 return NT_STATUS_OK;
     900             :         }
     901             : 
     902           0 :         if ( !winbindd_can_contact_domain( domain ) ) {
     903           0 :                 DEBUG(10,("lookup_usergroups: No incoming trust for domain %s\n",
     904             :                           domain->name));
     905             : 
     906             :                 /* Tell the cache manager not to remember this one */
     907             : 
     908           0 :                 return NT_STATUS_SYNCHRONIZATION_REQUIRED;
     909             :         }
     910             : 
     911           0 :         rc = ads_cached_connection(domain, &ads);
     912           0 :         if (!ADS_ERR_OK(rc)) {
     913           0 :                 domain->last_status = NT_STATUS_SERVER_DISABLED;
     914           0 :                 status = NT_STATUS_SERVER_DISABLED;
     915           0 :                 goto done;
     916             :         }
     917             : 
     918           0 :         rc = ads_search_retry_sid(ads, &msg, sid, attrs);
     919             : 
     920           0 :         if (!ADS_ERR_OK(rc)) {
     921           0 :                 status = ads_ntstatus(rc);
     922           0 :                 DEBUG(1, ("lookup_usergroups(sid=%s) ads_search tokenGroups: "
     923             :                           "%s\n",
     924             :                           dom_sid_str_buf(sid, &buf),
     925             :                           ads_errstr(rc)));
     926           0 :                 goto done;
     927             :         }
     928             : 
     929           0 :         count = ads_count_replies(ads, msg);
     930           0 :         if (count != 1) {
     931           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     932           0 :                 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: "
     933             :                          "invalid number of results (count=%d)\n",
     934             :                          dom_sid_str_buf(sid, &buf),
     935             :                          count));
     936           0 :                 goto done;
     937             :         }
     938             : 
     939           0 :         if (!msg) {
     940           0 :                 DEBUG(1,("lookup_usergroups(sid=%s) ads_search tokenGroups: NULL msg\n",
     941             :                          dom_sid_str_buf(sid, &buf)));
     942           0 :                 status = NT_STATUS_UNSUCCESSFUL;
     943           0 :                 goto done;
     944             :         }
     945             : 
     946           0 :         user_dn = ads_get_dn(ads, mem_ctx, msg);
     947           0 :         if (user_dn == NULL) {
     948           0 :                 status = NT_STATUS_NO_MEMORY;
     949           0 :                 goto done;
     950             :         }
     951             : 
     952           0 :         if (!ads_pull_uint32(ads, msg, "primaryGroupID", &primary_group_rid)) {
     953           0 :                 DEBUG(1,("%s: No primary group for sid=%s !?\n",
     954             :                          domain->name,
     955             :                          dom_sid_str_buf(sid, &buf)));
     956           0 :                 goto done;
     957             :         }
     958             : 
     959           0 :         sid_compose(&primary_group, &domain->sid, primary_group_rid);
     960             : 
     961           0 :         count = ads_pull_sids(ads, mem_ctx, msg, "tokenGroups", &sids);
     962             : 
     963             :         /* there must always be at least one group in the token,
     964             :            unless we are talking to a buggy Win2k server */
     965             : 
     966             :         /* actually this only happens when the machine account has no read
     967             :          * permissions on the tokenGroup attribute - gd */
     968             : 
     969           0 :         if (count == 0) {
     970             : 
     971             :                 /* no tokenGroups */
     972             : 
     973             :                 /* lookup what groups this user is a member of by DN search on
     974             :                  * "memberOf" */
     975             : 
     976           0 :                 status = lookup_usergroups_memberof(domain, mem_ctx, user_dn,
     977             :                                                     &primary_group,
     978             :                                                     &num_groups, user_sids);
     979           0 :                 *p_num_groups = num_groups;
     980           0 :                 if (NT_STATUS_IS_OK(status)) {
     981           0 :                         goto done;
     982             :                 }
     983             : 
     984             :                 /* lookup what groups this user is a member of by DN search on
     985             :                  * "member" */
     986             : 
     987           0 :                 status = lookup_usergroups_member(domain, mem_ctx, user_dn,
     988             :                                                   &primary_group,
     989             :                                                   &num_groups, user_sids);
     990           0 :                 *p_num_groups = num_groups;
     991           0 :                 goto done;
     992             :         }
     993             : 
     994           0 :         *user_sids = NULL;
     995           0 :         num_groups = 0;
     996             : 
     997           0 :         status = add_sid_to_array(mem_ctx, &primary_group, user_sids,
     998             :                                   &num_groups);
     999           0 :         if (!NT_STATUS_IS_OK(status)) {
    1000           0 :                 goto done;
    1001             :         }
    1002             : 
    1003           0 :         for (i=0;i<count;i++) {
    1004             : 
    1005             :                 /* ignore Builtin groups from ADS - Guenther */
    1006           0 :                 if (sid_check_is_in_builtin(&sids[i])) {
    1007           0 :                         continue;
    1008             :                 }
    1009             : 
    1010           0 :                 status = add_sid_to_array_unique(mem_ctx, &sids[i],
    1011             :                                                  user_sids, &num_groups);
    1012           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1013           0 :                         goto done;
    1014             :                 }
    1015             :         }
    1016             : 
    1017           0 :         *p_num_groups = (uint32_t)num_groups;
    1018           0 :         status = (*user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
    1019             : 
    1020           0 :         DEBUG(3,("ads lookup_usergroups (tokenGroups) succeeded for sid=%s\n",
    1021             :                  dom_sid_str_buf(sid, &buf)));
    1022           0 : done:
    1023           0 :         TALLOC_FREE(user_dn);
    1024           0 :         ads_msgfree(ads, msg);
    1025           0 :         return status;
    1026             : }
    1027             : 
    1028             : /* Lookup aliases a user is member of - use rpc methods */
    1029           0 : static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
    1030             :                                    TALLOC_CTX *mem_ctx,
    1031             :                                    uint32_t num_sids, const struct dom_sid *sids,
    1032             :                                    uint32_t *num_aliases, uint32_t **alias_rids)
    1033             : {
    1034           0 :         return msrpc_methods.lookup_useraliases(domain, mem_ctx, num_sids, sids,
    1035             :                                                 num_aliases, alias_rids);
    1036             : }
    1037             : 
    1038           0 : static NTSTATUS add_primary_group_members(
    1039             :         ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, uint32_t rid,
    1040             :         char ***all_members, size_t *num_all_members)
    1041             : {
    1042             :         char *filter;
    1043           0 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    1044             :         ADS_STATUS rc;
    1045           0 :         const char *attrs[] = { "dn", NULL };
    1046           0 :         LDAPMessage *res = NULL;
    1047             :         LDAPMessage *msg;
    1048             :         char **members;
    1049             :         size_t num_members;
    1050             :         ads_control args;
    1051             : 
    1052           0 :         filter = talloc_asprintf(
    1053             :                 mem_ctx, "(&(objectCategory=user)(primaryGroupID=%u))",
    1054             :                 (unsigned)rid);
    1055           0 :         if (filter == NULL) {
    1056           0 :                 goto done;
    1057             :         }
    1058             : 
    1059           0 :         args.control = ADS_EXTENDED_DN_OID;
    1060           0 :         args.val = ADS_EXTENDED_DN_HEX_STRING;
    1061           0 :         args.critical = True;
    1062             : 
    1063           0 :         rc = ads_do_search_all_args(ads, ads->config.bind_path,
    1064             :                                     LDAP_SCOPE_SUBTREE, filter, attrs, &args,
    1065             :                                     &res);
    1066             : 
    1067           0 :         if (!ADS_ERR_OK(rc)) {
    1068           0 :                 status = ads_ntstatus(rc);
    1069           0 :                 DEBUG(1,("%s: ads_search: %s\n", __func__, ads_errstr(rc)));
    1070           0 :                 goto done;
    1071             :         }
    1072           0 :         if (res == NULL) {
    1073           0 :                 DEBUG(1,("%s: ads_search returned NULL res\n", __func__));
    1074           0 :                 goto done;
    1075             :         }
    1076             : 
    1077           0 :         num_members = ads_count_replies(ads, res);
    1078             : 
    1079           0 :         DEBUG(10, ("%s: Got %ju primary group members\n", __func__,
    1080             :                    (uintmax_t)num_members));
    1081             : 
    1082           0 :         if (num_members == 0) {
    1083           0 :                 status = NT_STATUS_OK;
    1084           0 :                 goto done;
    1085             :         }
    1086             : 
    1087           0 :         members = talloc_realloc(mem_ctx, *all_members, char *,
    1088             :                                  *num_all_members + num_members);
    1089           0 :         if (members == NULL) {
    1090           0 :                 DEBUG(1, ("%s: talloc_realloc failed\n", __func__));
    1091           0 :                 goto done;
    1092             :         }
    1093           0 :         *all_members = members;
    1094             : 
    1095           0 :         for (msg = ads_first_entry(ads, res); msg != NULL;
    1096           0 :              msg = ads_next_entry(ads, msg)) {
    1097             :                 char *dn;
    1098             : 
    1099           0 :                 dn = ads_get_dn(ads, members, msg);
    1100           0 :                 if (dn == NULL) {
    1101           0 :                         DEBUG(1, ("%s: ads_get_dn failed\n", __func__));
    1102           0 :                         continue;
    1103             :                 }
    1104             : 
    1105           0 :                 members[*num_all_members] = dn;
    1106           0 :                 *num_all_members += 1;
    1107             :         }
    1108             : 
    1109           0 :         status = NT_STATUS_OK;
    1110           0 : done:
    1111           0 :         if (res != NULL) {
    1112           0 :                 ads_msgfree(ads, res);
    1113             :         }
    1114           0 :         TALLOC_FREE(filter);
    1115           0 :         return status;
    1116             : }
    1117             : 
    1118             : /*
    1119             :   find the members of a group, given a group rid and domain
    1120             :  */
    1121           0 : static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
    1122             :                                 TALLOC_CTX *mem_ctx,
    1123             :                                 const struct dom_sid *group_sid,
    1124             :                                 enum lsa_SidType type,
    1125             :                                 uint32_t *num_names,
    1126             :                                 struct dom_sid **sid_mem, char ***names,
    1127             :                                 uint32_t **name_types)
    1128             : {
    1129             :         ADS_STATUS rc;
    1130           0 :         ADS_STRUCT *ads = NULL;
    1131             :         char *ldap_exp;
    1132           0 :         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
    1133             :         char *sidbinstr;
    1134           0 :         char **members = NULL;
    1135             :         size_t i;
    1136           0 :         size_t num_members = 0;
    1137             :         ads_control args;
    1138           0 :         struct dom_sid *sid_mem_nocache = NULL;
    1139           0 :         char **names_nocache = NULL;
    1140           0 :         enum lsa_SidType *name_types_nocache = NULL;
    1141           0 :         char **domains_nocache = NULL;     /* only needed for rpccli_lsa_lookup_sids */
    1142           0 :         uint32_t num_nocache = 0;
    1143           0 :         TALLOC_CTX *tmp_ctx = NULL;
    1144             :         uint32_t rid;
    1145             :         struct dom_sid_buf buf;
    1146             : 
    1147           0 :         DEBUG(10,("ads: lookup_groupmem %s sid=%s\n", domain->name,
    1148             :                   dom_sid_str_buf(group_sid, &buf)));
    1149             : 
    1150           0 :         *num_names = 0;
    1151             : 
    1152           0 :         tmp_ctx = talloc_new(mem_ctx);
    1153           0 :         if (!tmp_ctx) {
    1154           0 :                 DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
    1155           0 :                 status = NT_STATUS_NO_MEMORY;
    1156           0 :                 goto done;
    1157             :         }
    1158             : 
    1159           0 :         if (!sid_peek_rid(group_sid, &rid)) {
    1160           0 :                 DEBUG(1, ("%s: sid_peek_rid failed\n", __func__));
    1161           0 :                 status = NT_STATUS_INVALID_PARAMETER;
    1162           0 :                 goto done;
    1163             :         }
    1164             : 
    1165           0 :         if ( !winbindd_can_contact_domain( domain ) ) {
    1166           0 :                 DEBUG(10,("lookup_groupmem: No incoming trust for domain %s\n",
    1167             :                           domain->name));
    1168           0 :                 return NT_STATUS_OK;
    1169             :         }
    1170             : 
    1171           0 :         rc = ads_cached_connection(domain, &ads);
    1172           0 :         if (!ADS_ERR_OK(rc)) {
    1173           0 :                 domain->last_status = NT_STATUS_SERVER_DISABLED;
    1174           0 :                 goto done;
    1175             :         }
    1176             : 
    1177           0 :         if ((sidbinstr = ldap_encode_ndr_dom_sid(talloc_tos(), group_sid)) == NULL) {
    1178           0 :                 status = NT_STATUS_NO_MEMORY;
    1179           0 :                 goto done;
    1180             :         }
    1181             : 
    1182             :         /* search for all members of the group */
    1183           0 :         ldap_exp = talloc_asprintf(tmp_ctx, "(objectSid=%s)", sidbinstr);
    1184           0 :         TALLOC_FREE(sidbinstr);
    1185           0 :         if (ldap_exp == NULL) {
    1186           0 :                 DEBUG(1, ("ads: lookup_groupmem: talloc_asprintf for ldap_exp failed!\n"));
    1187           0 :                 status = NT_STATUS_NO_MEMORY;
    1188           0 :                 goto done;
    1189             :         }
    1190             : 
    1191           0 :         args.control = ADS_EXTENDED_DN_OID;
    1192           0 :         args.val = ADS_EXTENDED_DN_HEX_STRING;
    1193           0 :         args.critical = True;
    1194             : 
    1195           0 :         rc = ads_ranged_search(ads, tmp_ctx, LDAP_SCOPE_SUBTREE, ads->config.bind_path,
    1196             :                                ldap_exp, &args, "member", &members, &num_members);
    1197             : 
    1198           0 :         if (!ADS_ERR_OK(rc)) {
    1199           0 :                 DEBUG(0,("ads_ranged_search failed with: %s\n", ads_errstr(rc)));
    1200           0 :                 status = NT_STATUS_UNSUCCESSFUL;
    1201           0 :                 goto done;
    1202             :         }
    1203             : 
    1204           0 :         DEBUG(10, ("ads lookup_groupmem: got %d sids via extended dn call\n", (int)num_members));
    1205             : 
    1206           0 :         status = add_primary_group_members(ads, mem_ctx, rid,
    1207             :                                            &members, &num_members);
    1208           0 :         if (!NT_STATUS_IS_OK(status)) {
    1209           0 :                 DEBUG(10, ("%s: add_primary_group_members failed: %s\n",
    1210             :                            __func__, nt_errstr(status)));
    1211           0 :                 goto done;
    1212             :         }
    1213             : 
    1214           0 :         DEBUG(10, ("%s: Got %d sids after adding primary group members\n",
    1215             :                    __func__, (int)num_members));
    1216             : 
    1217             :         /* Now that we have a list of sids, we need to get the
    1218             :          * lists of names and name_types belonging to these sids.
    1219             :          * even though conceptually not quite clean,  we use the
    1220             :          * RPC call lsa_lookup_sids for this since it can handle a
    1221             :          * list of sids. ldap calls can just resolve one sid at a time.
    1222             :          *
    1223             :          * At this stage, the sids are still hidden in the exetended dn
    1224             :          * member output format. We actually do a little better than
    1225             :          * stated above: In extracting the sids from the member strings,
    1226             :          * we try to resolve as many sids as possible from the
    1227             :          * cache. Only the rest is passed to the lsa_lookup_sids call. */
    1228             : 
    1229           0 :         if (num_members) {
    1230           0 :                 (*sid_mem) = talloc_zero_array(mem_ctx, struct dom_sid, num_members);
    1231           0 :                 (*names) = talloc_zero_array(mem_ctx, char *, num_members);
    1232           0 :                 (*name_types) = talloc_zero_array(mem_ctx, uint32_t, num_members);
    1233           0 :                 (sid_mem_nocache) = talloc_zero_array(tmp_ctx, struct dom_sid, num_members);
    1234             : 
    1235           0 :                 if ((members == NULL) || (*sid_mem == NULL) ||
    1236           0 :                     (*names == NULL) || (*name_types == NULL) ||
    1237             :                     (sid_mem_nocache == NULL))
    1238             :                 {
    1239           0 :                         DEBUG(1, ("ads: lookup_groupmem: talloc failed\n"));
    1240           0 :                         status = NT_STATUS_NO_MEMORY;
    1241           0 :                         goto done;
    1242             :                 }
    1243             :         }
    1244             :         else {
    1245           0 :                 (*sid_mem) = NULL;
    1246           0 :                 (*names) = NULL;
    1247           0 :                 (*name_types) = NULL;
    1248             :         }
    1249             : 
    1250           0 :         for (i=0; i<num_members; i++) {
    1251             :                 enum lsa_SidType name_type;
    1252             :                 char *name, *domain_name;
    1253             :                 struct dom_sid sid;
    1254             : 
    1255           0 :                 rc = ads_get_sid_from_extended_dn(tmp_ctx, members[i], args.val,
    1256             :                     &sid);
    1257           0 :                 if (!ADS_ERR_OK(rc)) {
    1258           0 :                         if (NT_STATUS_EQUAL(ads_ntstatus(rc),
    1259             :                             NT_STATUS_NOT_FOUND)) {
    1260             :                                 /* Group members can be objects, like Exchange
    1261             :                                  * Public Folders, that don't have a SID.  Skip
    1262             :                                  * them. */
    1263           0 :                                 continue;
    1264             :                         }
    1265             :                         else {
    1266           0 :                                 status = ads_ntstatus(rc);
    1267           0 :                                 goto done;
    1268             :                         }
    1269             :                 }
    1270           0 :                 if (lookup_cached_sid(mem_ctx, &sid, &domain_name, &name,
    1271             :                     &name_type)) {
    1272           0 :                         DEBUG(10,("ads: lookup_groupmem: got sid %s from "
    1273             :                                   "cache\n",
    1274             :                                   dom_sid_str_buf(&sid, &buf)));
    1275           0 :                         sid_copy(&(*sid_mem)[*num_names], &sid);
    1276           0 :                         (*names)[*num_names] = fill_domain_username_talloc(
    1277             :                                                         *names,
    1278             :                                                         domain_name,
    1279             :                                                         name,
    1280             :                                                         true);
    1281             : 
    1282           0 :                         (*name_types)[*num_names] = name_type;
    1283           0 :                         (*num_names)++;
    1284             :                 }
    1285             :                 else {
    1286           0 :                         DEBUG(10, ("ads: lookup_groupmem: sid %s not found in "
    1287             :                                    "cache\n",
    1288             :                                    dom_sid_str_buf(&sid, &buf)));
    1289           0 :                         sid_copy(&(sid_mem_nocache)[num_nocache], &sid);
    1290           0 :                         num_nocache++;
    1291             :                 }
    1292             :         }
    1293             : 
    1294           0 :         DEBUG(10, ("ads: lookup_groupmem: %d sids found in cache, "
    1295             :                   "%d left for lsa_lookupsids\n", *num_names, num_nocache));
    1296             : 
    1297             :         /* handle sids not resolved from cache by lsa_lookup_sids */
    1298           0 :         if (num_nocache > 0) {
    1299             : 
    1300           0 :                 status = winbindd_lookup_sids(tmp_ctx,
    1301             :                                               domain,
    1302             :                                               num_nocache,
    1303             :                                               sid_mem_nocache,
    1304             :                                               &domains_nocache,
    1305             :                                               &names_nocache,
    1306             :                                               &name_types_nocache);
    1307             : 
    1308           0 :                 if (!(NT_STATUS_IS_OK(status) ||
    1309           0 :                       NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED) ||
    1310           0 :                       NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)))
    1311             :                 {
    1312           0 :                         DEBUG(1, ("lsa_lookupsids call failed with %s "
    1313             :                                   "- retrying...\n", nt_errstr(status)));
    1314             : 
    1315           0 :                         status = winbindd_lookup_sids(tmp_ctx,
    1316             :                                                       domain,
    1317             :                                                       num_nocache,
    1318             :                                                       sid_mem_nocache,
    1319             :                                                       &domains_nocache,
    1320             :                                                       &names_nocache,
    1321             :                                                       &name_types_nocache);
    1322             :                 }
    1323             : 
    1324           0 :                 if (NT_STATUS_IS_OK(status) ||
    1325           0 :                     NT_STATUS_EQUAL(status, STATUS_SOME_UNMAPPED))
    1326             :                 {
    1327             :                         /* Copy the entries over from the "_nocache" arrays
    1328             :                          * to the result arrays, skipping the gaps the
    1329             :                          * lookup_sids call left. */
    1330           0 :                         for (i=0; i < num_nocache; i++) {
    1331           0 :                                 if (((names_nocache)[i] != NULL) &&
    1332           0 :                                     ((name_types_nocache)[i] != SID_NAME_UNKNOWN))
    1333             :                                 {
    1334           0 :                                         sid_copy(&(*sid_mem)[*num_names],
    1335           0 :                                                  &sid_mem_nocache[i]);
    1336           0 :                                         (*names)[*num_names] =
    1337           0 :                                                 fill_domain_username_talloc(
    1338             :                                                         *names,
    1339           0 :                                                         domains_nocache[i],
    1340           0 :                                                         names_nocache[i],
    1341             :                                                         true);
    1342           0 :                                         (*name_types)[*num_names] = name_types_nocache[i];
    1343           0 :                                         (*num_names)++;
    1344             :                                 }
    1345             :                         }
    1346             :                 }
    1347           0 :                 else if (NT_STATUS_EQUAL(status, NT_STATUS_NONE_MAPPED)) {
    1348           0 :                         DEBUG(10, ("lookup_groupmem: lsa_lookup_sids could "
    1349             :                                    "not map any SIDs at all.\n"));
    1350             :                         /* Don't handle this as an error here.
    1351             :                          * There is nothing left to do with respect to the
    1352             :                          * overall result... */
    1353             :                 }
    1354           0 :                 else if (!NT_STATUS_IS_OK(status)) {
    1355           0 :                         DEBUG(10, ("lookup_groupmem: Error looking up %d "
    1356             :                                    "sids via rpc_lsa_lookup_sids: %s\n",
    1357             :                                    (int)num_members, nt_errstr(status)));
    1358           0 :                         goto done;
    1359             :                 }
    1360             :         }
    1361             : 
    1362           0 :         status = NT_STATUS_OK;
    1363           0 :         DEBUG(3,("ads lookup_groupmem for sid=%s succeeded\n",
    1364             :                  dom_sid_str_buf(group_sid, &buf)));
    1365             : 
    1366           0 : done:
    1367             : 
    1368           0 :         TALLOC_FREE(tmp_ctx);
    1369             : 
    1370           0 :         return status;
    1371             : }
    1372             : 
    1373             : /* find the lockout policy of a domain - use rpc methods */
    1374           0 : static NTSTATUS lockout_policy(struct winbindd_domain *domain,
    1375             :                                TALLOC_CTX *mem_ctx,
    1376             :                                struct samr_DomInfo12 *policy)
    1377             : {
    1378           0 :         return msrpc_methods.lockout_policy(domain, mem_ctx, policy);
    1379             : }
    1380             : 
    1381             : /* find the password policy of a domain - use rpc methods */
    1382           0 : static NTSTATUS password_policy(struct winbindd_domain *domain,
    1383             :                                 TALLOC_CTX *mem_ctx,
    1384             :                                 struct samr_DomInfo1 *policy)
    1385             : {
    1386           0 :         return msrpc_methods.password_policy(domain, mem_ctx, policy);
    1387             : }
    1388             : 
    1389             : /* get a list of trusted domains */
    1390           0 : static NTSTATUS trusted_domains(struct winbindd_domain *domain,
    1391             :                                 TALLOC_CTX *mem_ctx,
    1392             :                                 struct netr_DomainTrustList *trusts)
    1393             : {
    1394           0 :         NTSTATUS                result = NT_STATUS_UNSUCCESSFUL;
    1395             :         WERROR werr;
    1396             :         uint32_t                i;
    1397             :         uint32_t                flags;
    1398             :         struct rpc_pipe_client *cli;
    1399             :         int ret_count;
    1400             :         struct dcerpc_binding_handle *b;
    1401             : 
    1402           0 :         DEBUG(3,("ads: trusted_domains\n"));
    1403             : 
    1404           0 :         ZERO_STRUCTP(trusts);
    1405             : 
    1406             :         /* If this is our primary domain or a root in our forest,
    1407             :            query for all trusts.  If not, then just look for domain
    1408             :            trusts in the target forest */
    1409             : 
    1410           0 :         if (domain->primary || domain_is_forest_root(domain)) {
    1411           0 :                 flags = NETR_TRUST_FLAG_OUTBOUND |
    1412             :                         NETR_TRUST_FLAG_INBOUND |
    1413             :                         NETR_TRUST_FLAG_IN_FOREST;
    1414             :         } else {
    1415           0 :                 flags = NETR_TRUST_FLAG_IN_FOREST;
    1416             :         }
    1417             : 
    1418           0 :         result = cm_connect_netlogon(domain, &cli);
    1419             : 
    1420           0 :         if (!NT_STATUS_IS_OK(result)) {
    1421           0 :                 DEBUG(5, ("trusted_domains: Could not open a connection to %s "
    1422             :                           "for PIPE_NETLOGON (%s)\n",
    1423             :                           domain->name, nt_errstr(result)));
    1424           0 :                 return NT_STATUS_UNSUCCESSFUL;
    1425             :         }
    1426             : 
    1427           0 :         b = cli->binding_handle;
    1428             : 
    1429           0 :         result = dcerpc_netr_DsrEnumerateDomainTrusts(b, mem_ctx,
    1430           0 :                                                       cli->desthost,
    1431             :                                                       flags,
    1432             :                                                       trusts,
    1433             :                                                       &werr);
    1434           0 :         if (!NT_STATUS_IS_OK(result)) {
    1435           0 :                 return result;
    1436             :         }
    1437             : 
    1438           0 :         if (!W_ERROR_IS_OK(werr)) {
    1439           0 :                 return werror_to_ntstatus(werr);
    1440             :         }
    1441           0 :         if (trusts->count == 0) {
    1442           0 :                 return NT_STATUS_OK;
    1443             :         }
    1444             : 
    1445             :         /* Copy across names and sids */
    1446             : 
    1447           0 :         ret_count = 0;
    1448           0 :         for (i = 0; i < trusts->count; i++) {
    1449           0 :                 struct netr_DomainTrust *trust = &trusts->array[i];
    1450             :                 struct winbindd_domain d;
    1451             : 
    1452           0 :                 ZERO_STRUCT(d);
    1453             : 
    1454             :                 /*
    1455             :                  * drop external trusts if this is not our primary
    1456             :                  * domain.  This means that the returned number of
    1457             :                  * domains may be less that the ones actually trusted
    1458             :                  * by the DC.
    1459             :                  */
    1460             : 
    1461           0 :                 if ((trust->trust_attributes
    1462           0 :                      & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) &&
    1463           0 :                     !domain->primary )
    1464             :                 {
    1465           0 :                         DEBUG(10,("trusted_domains: Skipping external trusted "
    1466             :                                   "domain %s because it is outside of our "
    1467             :                                   "primary domain\n",
    1468             :                                   trust->netbios_name));
    1469           0 :                         continue;
    1470             :                 }
    1471             : 
    1472             :                 /* add to the trusted domain cache */
    1473             : 
    1474           0 :                 d.name = discard_const_p(char, trust->netbios_name);
    1475           0 :                 d.alt_name = discard_const_p(char, trust->dns_name);
    1476             : 
    1477           0 :                 if (trust->sid) {
    1478           0 :                         sid_copy(&d.sid, trust->sid);
    1479             :                 } else {
    1480           0 :                         sid_copy(&d.sid, &global_sid_NULL);
    1481             :                 }
    1482             : 
    1483           0 :                 if ( domain->primary ) {
    1484           0 :                         DEBUG(10,("trusted_domains(ads):  Searching "
    1485             :                                   "trusted domain list of %s and storing "
    1486             :                                   "trust flags for domain %s\n",
    1487             :                                   domain->name, d.alt_name));
    1488             : 
    1489           0 :                         d.domain_flags = trust->trust_flags;
    1490           0 :                         d.domain_type = trust->trust_type;
    1491           0 :                         d.domain_trust_attribs = trust->trust_attributes;
    1492             : 
    1493           0 :                         wcache_tdc_add_domain( &d );
    1494           0 :                         ret_count++;
    1495           0 :                 } else if (domain_is_forest_root(domain)) {
    1496             :                         /* Check if we already have this record. If
    1497             :                          * we are following our forest root that is not
    1498             :                          * our primary domain, we want to keep trust
    1499             :                          * flags from the perspective of our primary
    1500             :                          * domain not our forest root. */
    1501           0 :                         struct winbindd_tdc_domain *exist = NULL;
    1502             : 
    1503           0 :                         exist = wcache_tdc_fetch_domain(
    1504             :                                 talloc_tos(), trust->netbios_name);
    1505           0 :                         if (!exist) {
    1506           0 :                                 DEBUG(10,("trusted_domains(ads):  Searching "
    1507             :                                           "trusted domain list of %s and "
    1508             :                                           "storing trust flags for domain "
    1509             :                                           "%s\n", domain->name, d.alt_name));
    1510           0 :                                 d.domain_flags = trust->trust_flags;
    1511           0 :                                 d.domain_type = trust->trust_type;
    1512           0 :                                 d.domain_trust_attribs =
    1513           0 :                                         trust->trust_attributes;
    1514             : 
    1515           0 :                                 wcache_tdc_add_domain( &d );
    1516           0 :                                 ret_count++;
    1517             :                         }
    1518           0 :                         TALLOC_FREE(exist);
    1519             :                 } else {
    1520             :                         /* This gets a little tricky.  If we are
    1521             :                            following a transitive forest trust, then
    1522             :                            innerit the flags, type, and attribs from
    1523             :                            the domain we queried to make sure we don't
    1524             :                            record the view of the trust from the wrong
    1525             :                            side.  Always view it from the side of our
    1526             :                            primary domain.   --jerry */
    1527           0 :                         struct winbindd_tdc_domain *parent = NULL;
    1528             : 
    1529           0 :                         DEBUG(10,("trusted_domains(ads):  Searching "
    1530             :                                   "trusted domain list of %s and inheriting "
    1531             :                                   "trust flags for domain %s\n",
    1532             :                                   domain->name, d.alt_name));
    1533             : 
    1534           0 :                         parent = wcache_tdc_fetch_domain(talloc_tos(),
    1535           0 :                                                          domain->name);
    1536           0 :                         if (parent) {
    1537           0 :                                 d.domain_flags = parent->trust_flags;
    1538           0 :                                 d.domain_type  = parent->trust_type;
    1539           0 :                                 d.domain_trust_attribs = parent->trust_attribs;
    1540             :                         } else {
    1541           0 :                                 d.domain_flags = domain->domain_flags;
    1542           0 :                                 d.domain_type  = domain->domain_type;
    1543           0 :                                 d.domain_trust_attribs =
    1544           0 :                                         domain->domain_trust_attribs;
    1545             :                         }
    1546           0 :                         TALLOC_FREE(parent);
    1547             : 
    1548             :                         /*
    1549             :                          * We need to pass the modified properties
    1550             :                          * to the caller.
    1551             :                          */
    1552           0 :                         trust->trust_flags = d.domain_flags;
    1553           0 :                         trust->trust_type = d.domain_type;
    1554           0 :                         trust->trust_attributes = d.domain_trust_attribs;
    1555             : 
    1556           0 :                         wcache_tdc_add_domain( &d );
    1557           0 :                         ret_count++;
    1558             :                 }
    1559             :         }
    1560           0 :         return result;
    1561             : }
    1562             : 
    1563             : /* the ADS backend methods are exposed via this structure */
    1564             : struct winbindd_methods ads_methods = {
    1565             :         True,
    1566             :         query_user_list,
    1567             :         enum_dom_groups,
    1568             :         enum_local_groups,
    1569             :         name_to_sid,
    1570             :         sid_to_name,
    1571             :         rids_to_names,
    1572             :         lookup_usergroups,
    1573             :         lookup_useraliases,
    1574             :         lookup_groupmem,
    1575             :         lockout_policy,
    1576             :         password_policy,
    1577             :         trusted_domains,
    1578             : };
    1579             : 
    1580             : #endif

Generated by: LCOV version 1.13