LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd_ads.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 0 740 0.0 %
Date: 2024-02-28 12:06:22 Functions: 0 20 0.0 %

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

Generated by: LCOV version 1.14