LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd_util.c (source / functions) Hit Total Coverage
Test: coverage report for vadcx-master-patch-75612 fe003de8 Lines: 517 961 53.8 %
Date: 2024-02-29 22:57:05 Functions: 43 52 82.7 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Winbind daemon for ntdom nss module
       5             : 
       6             :    Copyright (C) Tim Potter 2000-2001
       7             :    Copyright (C) 2001 by Martin Pool <mbp@samba.org>
       8             : 
       9             :    This program is free software; you can redistribute it and/or modify
      10             :    it under the terms of the GNU General Public License as published by
      11             :    the Free Software Foundation; either version 3 of the License, or
      12             :    (at your option) any later version.
      13             : 
      14             :    This program is distributed in the hope that it will be useful,
      15             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      16             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17             :    GNU General Public License for more details.
      18             : 
      19             :    You should have received a copy of the GNU General Public License
      20             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      21             : */
      22             : 
      23             : #include "includes.h"
      24             : #include "winbindd.h"
      25             : #include "lib/util_unixsids.h"
      26             : #include "secrets.h"
      27             : #include "../libcli/security/security.h"
      28             : #include "../libcli/auth/pam_errors.h"
      29             : #include "passdb/machine_sid.h"
      30             : #include "passdb.h"
      31             : #include "source4/lib/messaging/messaging.h"
      32             : #include "librpc/gen_ndr/ndr_lsa.h"
      33             : #include "librpc/gen_ndr/ndr_drsblobs.h"
      34             : #include "auth/credentials/credentials.h"
      35             : #include "libsmb/samlogon_cache.h"
      36             : #include "lib/util/smb_strtox.h"
      37             : #include "lib/util/string_wrappers.h"
      38             : #include "lib/global_contexts.h"
      39             : #include "librpc/gen_ndr/ndr_winbind_c.h"
      40             : 
      41             : #undef DBGC_CLASS
      42             : #define DBGC_CLASS DBGC_WINBIND
      43             : 
      44             : /**
      45             :  * @file winbindd_util.c
      46             :  *
      47             :  * Winbind daemon for NT domain authentication nss module.
      48             :  **/
      49             : 
      50             : /* The list of trusted domains.  Note that the list can be deleted and
      51             :    recreated using the init_domain_list() function so pointers to
      52             :    individual winbindd_domain structures cannot be made.  Keep a copy of
      53             :    the domain name instead. */
      54             : 
      55             : static struct winbindd_domain *_domain_list = NULL;
      56             : 
      57      232619 : struct winbindd_domain *domain_list(void)
      58             : {
      59             :         /* Initialise list */
      60             : 
      61      232619 :         if ((!_domain_list) && (!init_domain_list())) {
      62           0 :                 smb_panic("Init_domain_list failed");
      63             :         }
      64             : 
      65      232619 :         return _domain_list;
      66             : }
      67             : 
      68             : /* Free all entries in the trusted domain list */
      69             : 
      70          45 : static void free_domain_list(void)
      71             : {
      72          45 :         struct winbindd_domain *domain = _domain_list;
      73             : 
      74          45 :         while(domain) {
      75           0 :                 struct winbindd_domain *next = domain->next;
      76             : 
      77           0 :                 DLIST_REMOVE(_domain_list, domain);
      78           0 :                 TALLOC_FREE(domain);
      79           0 :                 domain = next;
      80             :         }
      81          45 : }
      82             : 
      83             : /**
      84             :  * Iterator for winbindd's domain list.
      85             :  * To be used (e.g.) in tevent based loops.
      86             :  */
      87         208 : struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain)
      88             : {
      89         208 :         if (domain == NULL) {
      90          64 :                 domain = domain_list();
      91             :         } else {
      92         144 :                 domain = domain->next;
      93             :         }
      94             : 
      95         376 :         if ((domain != NULL) &&
      96         336 :             (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) &&
      97         168 :             sid_check_is_our_sam(&domain->sid))
      98             :         {
      99          64 :                 domain = domain->next;
     100             :         }
     101             : 
     102         208 :         return domain;
     103             : }
     104             : 
     105         270 : static bool is_internal_domain(const struct dom_sid *sid)
     106             : {
     107         270 :         if (sid == NULL)
     108           0 :                 return False;
     109             : 
     110         270 :         return (sid_check_is_our_sam(sid) || sid_check_is_builtin(sid));
     111             : }
     112             : 
     113             : /* Add a trusted domain to our list of domains.
     114             :    If the domain already exists in the list,
     115             :    return it and don't re-initialize.  */
     116             : 
     117        1541 : static NTSTATUS add_trusted_domain(const char *domain_name,
     118             :                                    const char *dns_name,
     119             :                                    const struct dom_sid *sid,
     120             :                                    uint32_t trust_type,
     121             :                                    uint32_t trust_flags,
     122             :                                    uint32_t trust_attribs,
     123             :                                    enum netr_SchannelType secure_channel_type,
     124             :                                    struct winbindd_domain *routing_domain,
     125             :                                    struct winbindd_domain **_d)
     126             : {
     127        1541 :         struct winbindd_domain *domain = NULL;
     128        1541 :         int role = lp_server_role();
     129           0 :         struct dom_sid_buf buf;
     130             : 
     131        1541 :         if (is_null_sid(sid)) {
     132           0 :                 DBG_ERR("Got null SID for domain [%s]\n", domain_name);
     133           0 :                 return NT_STATUS_INVALID_PARAMETER;
     134             :         }
     135             : 
     136        1541 :         if (secure_channel_type == SEC_CHAN_NULL && !is_allowed_domain(domain_name)) {
     137           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
     138             :         }
     139             : 
     140             :         /*
     141             :          * We can't call domain_list() as this function is called from
     142             :          * init_domain_list() and we'll get stuck in a loop.
     143             :          */
     144        4654 :         for (domain = _domain_list; domain; domain = domain->next) {
     145        4519 :                 if (strequal(domain_name, domain->name)) {
     146        1406 :                         break;
     147             :                 }
     148             :         }
     149             : 
     150        1541 :         if (domain != NULL) {
     151        1406 :                 struct winbindd_domain *check_domain = NULL;
     152             : 
     153        1406 :                 for (check_domain = _domain_list;
     154        7260 :                      check_domain != NULL;
     155        5854 :                      check_domain = check_domain->next)
     156             :                 {
     157        5854 :                         if (check_domain == domain) {
     158        1406 :                                 continue;
     159             :                         }
     160             : 
     161        4448 :                         if (dom_sid_equal(&check_domain->sid, sid)) {
     162           0 :                                 break;
     163             :                         }
     164             :                 }
     165             : 
     166        1406 :                 if (check_domain != NULL) {
     167           0 :                         DBG_ERR("SID [%s] already used by domain [%s], "
     168             :                                 "expected [%s]\n",
     169             :                                 dom_sid_str_buf(sid, &buf),
     170             :                                 check_domain->name,
     171             :                                 domain->name);
     172           0 :                         return NT_STATUS_INVALID_PARAMETER;
     173             :                 }
     174             :         }
     175             : 
     176        1541 :         if ((domain != NULL) && (dns_name != NULL)) {
     177        1160 :                 struct winbindd_domain *check_domain = NULL;
     178             : 
     179        1160 :                 for (check_domain = _domain_list;
     180        6252 :                      check_domain != NULL;
     181        5092 :                      check_domain = check_domain->next)
     182             :                 {
     183        5092 :                         if (check_domain == domain) {
     184        1160 :                                 continue;
     185             :                         }
     186             : 
     187        3932 :                         if (strequal(check_domain->alt_name, dns_name)) {
     188           0 :                                 break;
     189             :                         }
     190             :                 }
     191             : 
     192        1160 :                 if (check_domain != NULL) {
     193           0 :                         DBG_ERR("DNS name [%s] used by domain [%s], "
     194             :                                 "expected [%s]\n",
     195             :                                 dns_name, check_domain->name,
     196             :                                 domain->name);
     197           0 :                         return NT_STATUS_INVALID_PARAMETER;
     198             :                 }
     199             :         }
     200             : 
     201        1541 :         if (domain != NULL) {
     202        1406 :                 *_d = domain;
     203        1406 :                 return NT_STATUS_OK;
     204             :         }
     205             : 
     206             :         /* Create new domain entry */
     207         135 :         domain = talloc_zero(NULL, struct winbindd_domain);
     208         135 :         if (domain == NULL) {
     209           0 :                 return NT_STATUS_NO_MEMORY;
     210             :         }
     211             : 
     212         135 :         domain->children = talloc_zero_array(domain,
     213             :                                              struct winbindd_child,
     214             :                                              lp_winbind_max_domain_connections());
     215         135 :         if (domain->children == NULL) {
     216           0 :                 TALLOC_FREE(domain);
     217           0 :                 return NT_STATUS_NO_MEMORY;
     218             :         }
     219             : 
     220         135 :         domain->queue = tevent_queue_create(domain, "winbind_domain");
     221         135 :         if (domain->queue == NULL) {
     222           0 :                 TALLOC_FREE(domain);
     223           0 :                 return NT_STATUS_NO_MEMORY;
     224             :         }
     225             : 
     226         135 :         domain->binding_handle = wbint_binding_handle(domain, domain, NULL);
     227         135 :         if (domain->binding_handle == NULL) {
     228           0 :                 TALLOC_FREE(domain);
     229           0 :                 return NT_STATUS_NO_MEMORY;
     230             :         }
     231             : 
     232         135 :         domain->name = talloc_strdup(domain, domain_name);
     233         135 :         if (domain->name == NULL) {
     234           0 :                 TALLOC_FREE(domain);
     235           0 :                 return NT_STATUS_NO_MEMORY;
     236             :         }
     237             : 
     238         135 :         if (dns_name != NULL) {
     239          41 :                 domain->alt_name = talloc_strdup(domain, dns_name);
     240          41 :                 if (domain->alt_name == NULL) {
     241           0 :                         TALLOC_FREE(domain);
     242           0 :                         return NT_STATUS_NO_MEMORY;
     243             :                 }
     244             :         }
     245             : 
     246         135 :         domain->backend = NULL;
     247         135 :         domain->internal = is_internal_domain(sid);
     248         135 :         domain->secure_channel_type = secure_channel_type;
     249         135 :         domain->sequence_number = DOM_SEQUENCE_NONE;
     250         135 :         domain->last_seq_check = 0;
     251         135 :         domain->initialized = false;
     252         135 :         domain->online = is_internal_domain(sid);
     253         135 :         domain->domain_flags = trust_flags;
     254         135 :         domain->domain_type = trust_type;
     255         135 :         domain->domain_trust_attribs = trust_attribs;
     256         135 :         domain->secure_channel_type = secure_channel_type;
     257         135 :         domain->routing_domain = routing_domain;
     258         135 :         sid_copy(&domain->sid, sid);
     259             : 
     260             :         /* Is this our primary domain ? */
     261         135 :         if (role == ROLE_DOMAIN_MEMBER) {
     262         103 :                 domain->primary = strequal(domain_name, lp_workgroup());
     263             :         } else {
     264          32 :                 domain->primary = strequal(domain_name, get_global_sam_name());
     265             :         }
     266             : 
     267         135 :         if (domain->primary) {
     268          45 :                 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
     269           0 :                         domain->active_directory = true;
     270             :                 }
     271          45 :                 if (lp_security() == SEC_ADS) {
     272          28 :                         domain->active_directory = true;
     273             :                 }
     274          90 :         } else if (!domain->internal) {
     275          14 :                 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
     276           4 :                         domain->active_directory = true;
     277             :                 }
     278             :         }
     279             : 
     280         135 :         domain->can_do_ncacn_ip_tcp = domain->active_directory;
     281             : 
     282             :         /* Link to domain list */
     283         135 :         DLIST_ADD_END(_domain_list, domain);
     284             : 
     285         135 :         wcache_tdc_add_domain( domain );
     286             : 
     287         135 :         setup_domain_child(domain);
     288             : 
     289         135 :         DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
     290             :                    domain->name, domain->alt_name,
     291             :                    dom_sid_str_buf(&domain->sid, &buf));
     292             : 
     293         135 :         *_d = domain;
     294         135 :         return NT_STATUS_OK;
     295             : }
     296             : 
     297           0 : bool set_routing_domain(struct winbindd_domain *domain,
     298             :                         struct winbindd_domain *routing_domain)
     299             : {
     300           0 :         if (domain->routing_domain == NULL) {
     301           0 :                 domain->routing_domain = routing_domain;
     302           0 :                 return true;
     303             :         }
     304           0 :         if (domain->routing_domain != routing_domain) {
     305           0 :                 return false;
     306             :         }
     307           0 :         return true;
     308             : }
     309             : 
     310        1422 : bool add_trusted_domain_from_auth(uint16_t validation_level,
     311             :                                   struct info3_text *info3,
     312             :                                   struct info6_text *info6)
     313             : {
     314        1422 :         struct winbindd_domain *domain = NULL;
     315           0 :         struct dom_sid domain_sid;
     316        1422 :         const char *dns_domainname = NULL;
     317           0 :         NTSTATUS status;
     318           0 :         bool ok;
     319             : 
     320             :         /*
     321             :          * We got a successful auth from a domain that might not yet be in our
     322             :          * domain list. If we're a member we trust our DC who authenticated the
     323             :          * user from that domain and add the domain to our list on-the-fly. If
     324             :          * we're a DC we rely on configured trusts and don't add on-the-fly.
     325             :          */
     326             : 
     327        1422 :         if (IS_DC) {
     328          26 :                 return true;
     329             :         }
     330             : 
     331        1396 :         ok = dom_sid_parse(info3->dom_sid, &domain_sid);
     332        1396 :         if (!ok) {
     333           0 :                 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
     334           0 :                 return false;
     335             :         }
     336             : 
     337        1396 :         if (validation_level == 6) {
     338        1274 :                 if (!strequal(info6->dns_domainname, "")) {
     339        1150 :                         dns_domainname = info6->dns_domainname;
     340             :                 }
     341             :         }
     342             : 
     343        1396 :         status = add_trusted_domain(info3->logon_dom,
     344             :                                     dns_domainname,
     345             :                                     &domain_sid,
     346             :                                     0,
     347             :                                     NETR_TRUST_FLAG_OUTBOUND,
     348             :                                     0,
     349             :                                     SEC_CHAN_NULL,
     350             :                                     find_default_route_domain(),
     351             :                                     &domain);
     352        1396 :         if (!NT_STATUS_IS_OK(status) &&
     353           0 :             !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
     354             :         {
     355           0 :                 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
     356             :                           info3->logon_dom, info3->dom_sid);
     357           0 :                 return false;
     358             :         }
     359             : 
     360        1396 :         return true;
     361             : }
     362             : 
     363          12 : bool domain_is_forest_root(const struct winbindd_domain *domain)
     364             : {
     365          12 :         const uint32_t fr_flags =
     366             :                 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
     367             : 
     368          12 :         return ((domain->domain_flags & fr_flags) == fr_flags);
     369             : }
     370             : 
     371             : /********************************************************************
     372             :   rescan our domains looking for new trusted domains
     373             : ********************************************************************/
     374             : 
     375             : struct trustdom_state {
     376             :         struct winbindd_domain *domain;
     377             :         struct netr_DomainTrustList trusts;
     378             : };
     379             : 
     380             : static void trustdom_list_done(struct tevent_req *req);
     381             : static void rescan_forest_root_trusts( void );
     382             : static void rescan_forest_trusts( void );
     383             : 
     384           8 : static void add_trusted_domains( struct winbindd_domain *domain )
     385             : {
     386           8 :         struct tevent_context *ev = global_event_context();
     387           0 :         struct trustdom_state *state;
     388           0 :         struct tevent_req *req;
     389           8 :         const char *client_name = NULL;
     390           0 :         pid_t client_pid;
     391             : 
     392           8 :         state = talloc_zero(NULL, struct trustdom_state);
     393           8 :         if (state == NULL) {
     394           0 :                 DEBUG(0, ("talloc failed\n"));
     395           0 :                 return;
     396             :         }
     397           8 :         state->domain = domain;
     398             : 
     399             :         /* Called from timer, not from a real client */
     400           8 :         client_name = getprogname();
     401           8 :         client_pid = getpid();
     402             : 
     403           8 :         req = dcerpc_wbint_ListTrustedDomains_send(state,
     404             :                                                    ev,
     405             :                                                    dom_child_handle(domain),
     406             :                                                    client_name,
     407             :                                                    client_pid,
     408             :                                                    &state->trusts);
     409           8 :         if (req == NULL) {
     410           0 :                 DBG_ERR("dcerpc_wbint_ListTrustedDomains_send failed\n");
     411           0 :                 TALLOC_FREE(state);
     412           0 :                 return;
     413             :         }
     414           8 :         tevent_req_set_callback(req, trustdom_list_done, state);
     415             : }
     416             : 
     417           8 : static void trustdom_list_done(struct tevent_req *req)
     418             : {
     419           8 :         struct trustdom_state *state = tevent_req_callback_data(
     420             :                 req, struct trustdom_state);
     421           8 :         bool within_forest = false;
     422           0 :         NTSTATUS status, result;
     423           0 :         uint32_t i;
     424             : 
     425             :         /*
     426             :          * Only when we enumerate our primary domain
     427             :          * or our forest root domain, we should keep
     428             :          * the NETR_TRUST_FLAG_IN_FOREST flag, in
     429             :          * all other cases we need to clear it as the domain
     430             :          * is not part of our forest.
     431             :          */
     432           8 :         if (state->domain->primary) {
     433           4 :                 within_forest = true;
     434           4 :         } else if (domain_is_forest_root(state->domain)) {
     435           0 :                 within_forest = true;
     436             :         }
     437             : 
     438           8 :         status = dcerpc_wbint_ListTrustedDomains_recv(req, state, &result);
     439           8 :         if (any_nt_status_not_ok(status, result, &status)) {
     440           0 :                 DBG_WARNING("Could not receive trusts for domain %s: %s-%s\n",
     441             :                             state->domain->name, nt_errstr(status),
     442             :                             nt_errstr(result));
     443           0 :                 TALLOC_FREE(state);
     444           0 :                 return;
     445             :         }
     446             : 
     447          28 :         for (i=0; i<state->trusts.count; i++) {
     448          20 :                 struct netr_DomainTrust *trust = &state->trusts.array[i];
     449          20 :                 struct winbindd_domain *domain = NULL;
     450             : 
     451          20 :                 if (!within_forest) {
     452           8 :                         trust->trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
     453             :                 }
     454             : 
     455          20 :                 if (!state->domain->primary) {
     456           8 :                         trust->trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
     457             :                 }
     458             : 
     459             :                 /*
     460             :                  * We always call add_trusted_domain() cause on an existing
     461             :                  * domain structure, it will update the SID if necessary.
     462             :                  * This is important because we need the SID for sibling
     463             :                  * domains.
     464             :                  */
     465          20 :                 status = add_trusted_domain(trust->netbios_name,
     466             :                                             trust->dns_name,
     467          20 :                                             trust->sid,
     468          20 :                                             trust->trust_type,
     469             :                                             trust->trust_flags,
     470             :                                             trust->trust_attributes,
     471             :                                             SEC_CHAN_NULL,
     472             :                                             find_default_route_domain(),
     473             :                                             &domain);
     474          20 :                 if (!NT_STATUS_IS_OK(status) &&
     475           0 :                     !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
     476             :                 {
     477           0 :                         DBG_NOTICE("add_trusted_domain returned %s\n",
     478             :                                    nt_errstr(status));
     479           0 :                         return;
     480             :                 }
     481             :         }
     482             : 
     483             :         /*
     484             :            Cases to consider when scanning trusts:
     485             :            (a) we are calling from a child domain (primary && !forest_root)
     486             :            (b) we are calling from the root of the forest (primary && forest_root)
     487             :            (c) we are calling from a trusted forest domain (!primary
     488             :                && !forest_root)
     489             :         */
     490             : 
     491           8 :         if (state->domain->primary) {
     492             :                 /* If this is our primary domain and we are not in the
     493             :                    forest root, we have to scan the root trusts first */
     494             : 
     495           4 :                 if (!domain_is_forest_root(state->domain))
     496           2 :                         rescan_forest_root_trusts();
     497             :                 else
     498           2 :                         rescan_forest_trusts();
     499             : 
     500           4 :         } else if (domain_is_forest_root(state->domain)) {
     501             :                 /* Once we have done root forest trust search, we can
     502             :                    go on to search the trusted forests */
     503             : 
     504           0 :                 rescan_forest_trusts();
     505             :         }
     506             : 
     507           8 :         TALLOC_FREE(state);
     508             : 
     509           8 :         return;
     510             : }
     511             : 
     512             : /********************************************************************
     513             :  Scan the trusts of our forest root
     514             : ********************************************************************/
     515             : 
     516           2 : static void rescan_forest_root_trusts( void )
     517             : {
     518           2 :         struct winbindd_tdc_domain *dom_list = NULL;
     519           2 :         size_t num_trusts = 0;
     520           0 :         size_t i;
     521           0 :         NTSTATUS status;
     522             : 
     523             :         /* The only transitive trusts supported by Windows 2003 AD are
     524             :            (a) Parent-Child, (b) Tree-Root, and (c) Forest.   The
     525             :            first two are handled in forest and listed by
     526             :            DsEnumerateDomainTrusts().  Forest trusts are not so we
     527             :            have to do that ourselves. */
     528             : 
     529           2 :         if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
     530           0 :                 return;
     531             : 
     532           6 :         for ( i=0; i<num_trusts; i++ ) {
     533           6 :                 struct winbindd_domain *d = NULL;
     534             : 
     535             :                 /* Find the forest root.  Don't necessarily trust
     536             :                    the domain_list() as our primary domain may not
     537             :                    have been initialized. */
     538             : 
     539           6 :                 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
     540           4 :                         continue;
     541             :                 }
     542             : 
     543             :                 /* Here's the forest root */
     544             : 
     545           2 :                 d = find_domain_from_name_noinit( dom_list[i].domain_name );
     546           2 :                 if (d == NULL) {
     547           0 :                         status = add_trusted_domain(dom_list[i].domain_name,
     548           0 :                                                     dom_list[i].dns_name,
     549           0 :                                                     &dom_list[i].sid,
     550           0 :                                                     dom_list[i].trust_type,
     551           0 :                                                     dom_list[i].trust_flags,
     552           0 :                                                     dom_list[i].trust_attribs,
     553             :                                                     SEC_CHAN_NULL,
     554             :                                                     find_default_route_domain(),
     555             :                                                     &d);
     556             : 
     557           0 :                         if (!NT_STATUS_IS_OK(status) &&
     558           0 :                             NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
     559             :                         {
     560           0 :                                 DBG_ERR("add_trusted_domain returned %s\n",
     561             :                                         nt_errstr(status));
     562           0 :                                 return;
     563             :                         }
     564             :                 }
     565           2 :                 if (d == NULL) {
     566           0 :                         continue;
     567             :                 }
     568             : 
     569           2 :                 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
     570             :                           "for domain tree root %s (%s)\n",
     571             :                           d->name, d->alt_name ));
     572             : 
     573           2 :                 d->domain_flags = dom_list[i].trust_flags;
     574           2 :                 d->domain_type  = dom_list[i].trust_type;
     575           2 :                 d->domain_trust_attribs = dom_list[i].trust_attribs;
     576             : 
     577           2 :                 add_trusted_domains( d );
     578             : 
     579           2 :                 break;
     580             :         }
     581             : 
     582           2 :         TALLOC_FREE( dom_list );
     583             : 
     584           2 :         return;
     585             : }
     586             : 
     587             : /********************************************************************
     588             :  scan the transitive forest trusts (not our own)
     589             : ********************************************************************/
     590             : 
     591             : 
     592           2 : static void rescan_forest_trusts( void )
     593             : {
     594           2 :         struct winbindd_domain *d = NULL;
     595           2 :         struct winbindd_tdc_domain *dom_list = NULL;
     596           2 :         size_t num_trusts = 0;
     597           0 :         size_t i;
     598           0 :         NTSTATUS status;
     599             : 
     600             :         /* The only transitive trusts supported by Windows 2003 AD are
     601             :            (a) Parent-Child, (b) Tree-Root, and (c) Forest.   The
     602             :            first two are handled in forest and listed by
     603             :            DsEnumerateDomainTrusts().  Forest trusts are not so we
     604             :            have to do that ourselves. */
     605             : 
     606           2 :         if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
     607           0 :                 return;
     608             : 
     609          12 :         for ( i=0; i<num_trusts; i++ ) {
     610          10 :                 uint32_t flags   = dom_list[i].trust_flags;
     611          10 :                 uint32_t type    = dom_list[i].trust_type;
     612          10 :                 uint32_t attribs = dom_list[i].trust_attribs;
     613             : 
     614          10 :                 d = find_domain_from_name_noinit( dom_list[i].domain_name );
     615             : 
     616             :                 /* ignore our primary and internal domains */
     617             : 
     618          10 :                 if ( d && (d->internal || d->primary ) )
     619           6 :                         continue;
     620             : 
     621           4 :                 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
     622           4 :                      (type == LSA_TRUST_TYPE_UPLEVEL) &&
     623           4 :                      (attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
     624             :                 {
     625             :                         /* add the trusted domain if we don't know
     626             :                            about it */
     627             : 
     628           4 :                         if (d == NULL) {
     629           0 :                                 status = add_trusted_domain(
     630           0 :                                         dom_list[i].domain_name,
     631           0 :                                         dom_list[i].dns_name,
     632           0 :                                         &dom_list[i].sid,
     633             :                                         type,
     634             :                                         flags,
     635             :                                         attribs,
     636             :                                         SEC_CHAN_NULL,
     637             :                                         find_default_route_domain(),
     638             :                                         &d);
     639           0 :                                 if (!NT_STATUS_IS_OK(status) &&
     640           0 :                                     NT_STATUS_EQUAL(status,
     641             :                                                     NT_STATUS_NO_SUCH_DOMAIN))
     642             :                                 {
     643           0 :                                         DBG_ERR("add_trusted_domain: %s\n",
     644             :                                                 nt_errstr(status));
     645           0 :                                         return;
     646             :                                 }
     647             :                         }
     648             : 
     649           4 :                         if (d == NULL) {
     650           0 :                                 continue;
     651             :                         }
     652             : 
     653           4 :                         DEBUG(10,("Following trust path for domain %s (%s)\n",
     654             :                                   d->name, d->alt_name ));
     655           4 :                         add_trusted_domains( d );
     656             :                 }
     657             :         }
     658             : 
     659           2 :         TALLOC_FREE( dom_list );
     660             : 
     661           2 :         return;
     662             : }
     663             : 
     664             : /*********************************************************************
     665             :  The process of updating the trusted domain list is a three step
     666             :  async process:
     667             :  (a) ask our domain
     668             :  (b) ask the root domain in our forest
     669             :  (c) ask a DC in any Win2003 trusted forests
     670             : *********************************************************************/
     671             : 
     672           2 : void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
     673             :                             struct timeval now, void *private_data)
     674             : {
     675           2 :         TALLOC_FREE(te);
     676             : 
     677             :         /* I used to clear the cache here and start over but that
     678             :            caused problems in child processes that needed the
     679             :            trust dom list early on.  Removing it means we
     680             :            could have some trusted domains listed that have been
     681             :            removed from our primary domain's DC until a full
     682             :            restart.  This should be ok since I think this is what
     683             :            Windows does as well. */
     684             : 
     685             :         /* this will only add new domains we didn't already know about
     686             :            in the domain_list()*/
     687             : 
     688           2 :         add_trusted_domains( find_our_domain() );
     689             : 
     690           2 :         te = tevent_add_timer(
     691             :                 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
     692             :                 rescan_trusted_domains, NULL);
     693             :         /*
     694             :          * If te == NULL, there's not much we can do here. Don't fail, the
     695             :          * only thing we miss is new trusted domains.
     696             :          */
     697             : 
     698           2 :         return;
     699             : }
     700             : 
     701             : static void wbd_ping_dc_done(struct tevent_req *subreq);
     702             : 
     703         925 : void winbindd_ping_offline_domains(struct tevent_context *ev,
     704             :                                    struct tevent_timer *te,
     705             :                                    struct timeval now,
     706             :                                    void *private_data)
     707             : {
     708         925 :         struct winbindd_domain *domain = NULL;
     709             : 
     710         925 :         TALLOC_FREE(te);
     711             : 
     712        3376 :         for (domain = domain_list(); domain != NULL; domain = domain->next) {
     713        2455 :                 DBG_DEBUG("Domain %s is %s\n",
     714             :                           domain->name,
     715             :                           domain->online ? "online" : "offline");
     716             : 
     717        2455 :                 if (get_global_winbindd_state_offline()) {
     718           4 :                         DBG_DEBUG("We are globally offline, do nothing.\n");
     719           4 :                         break;
     720             :                 }
     721             : 
     722        2451 :                 if (domain->online ||
     723         148 :                     domain->check_online_event != NULL ||
     724         148 :                     domain->secure_channel_type == SEC_CHAN_NULL) {
     725        2403 :                         continue;
     726             :                 }
     727             : 
     728          48 :                 winbindd_flush_negative_conn_cache(domain);
     729             : 
     730          48 :                 domain->check_online_event =
     731          48 :                         dcerpc_wbint_PingDc_send(domain,
     732             :                                                  ev,
     733             :                                                  dom_child_handle(domain),
     734             :                                                  &domain->ping_dcname);
     735          48 :                 if (domain->check_online_event == NULL) {
     736           0 :                         DBG_WARNING("Failed to schedule ping, no-memory\n");
     737           0 :                         continue;
     738             :                 }
     739             : 
     740          48 :                 tevent_req_set_callback(domain->check_online_event,
     741             :                                         wbd_ping_dc_done, domain);
     742             :         }
     743             : 
     744         925 :         te = tevent_add_timer(ev,
     745             :                               NULL,
     746             :                               timeval_current_ofs(lp_winbind_reconnect_delay(),
     747             :                                                   0),
     748             :                               winbindd_ping_offline_domains,
     749             :                               NULL);
     750         925 :         if (te == NULL) {
     751           0 :                 DBG_ERR("Failed to schedule winbindd_ping_offline_domains()\n");
     752             :         }
     753             : 
     754         925 :         return;
     755             : }
     756             : 
     757          48 : static void wbd_ping_dc_done(struct tevent_req *subreq)
     758             : {
     759           0 :         struct winbindd_domain *domain =
     760          48 :                 tevent_req_callback_data(subreq,
     761             :                 struct winbindd_domain);
     762           0 :         NTSTATUS status, result;
     763             : 
     764          48 :         SMB_ASSERT(subreq == domain->check_online_event);
     765          48 :         domain->check_online_event = NULL;
     766             : 
     767          48 :         status = dcerpc_wbint_PingDc_recv(subreq, domain, &result);
     768          48 :         TALLOC_FREE(subreq);
     769          48 :         if (any_nt_status_not_ok(status, result, &status)) {
     770          23 :                 DBG_WARNING("dcerpc_wbint_PingDc_recv failed for domain: "
     771             :                             "%s - %s\n",
     772             :                             domain->name,
     773             :                             nt_errstr(status));
     774          23 :                 return;
     775             :         }
     776             : 
     777          25 :         DBG_DEBUG("dcerpc_wbint_PingDc_recv() succeeded, "
     778             :                   "domain: %s, dc-name: %s\n",
     779             :                   domain->name,
     780             :                   domain->ping_dcname);
     781             : 
     782          25 :         talloc_free(discard_const(domain->ping_dcname));
     783          25 :         domain->ping_dcname = NULL;
     784             : 
     785          25 :         return;
     786             : }
     787             : 
     788           0 : static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
     789             :                                        void *private_data,
     790             :                                        uint32_t msg_type,
     791             :                                        struct server_id server_id,
     792             :                                        size_t num_fds,
     793             :                                        int *fds,
     794             :                                        DATA_BLOB *data)
     795             : {
     796           0 :         bool ok;
     797             : 
     798           0 :         if (num_fds != 0) {
     799           0 :                 DBG_WARNING("Received %zu fds, ignoring message\n", num_fds);
     800           0 :                 return;
     801             :         }
     802             : 
     803           0 :         DBG_NOTICE("Rescanning trusted domains\n");
     804             : 
     805           0 :         ok = add_trusted_domains_dc();
     806           0 :         if (!ok) {
     807           0 :                 DBG_ERR("Failed to reload trusted domains\n");
     808             :         }
     809             : }
     810             : 
     811             : /*
     812             :  * We did not get the secret when we queried secrets.tdb, so read it
     813             :  * from secrets.tdb and re-sync the databases
     814             :  */
     815           0 : static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
     816             : {
     817           0 :         bool ok;
     818           0 :         struct cli_credentials *creds;
     819           0 :         NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
     820             :                                                          NULL, domain, &creds);
     821           0 :         if (!NT_STATUS_IS_OK(can_migrate)) {
     822           0 :                 DEBUG(0, ("Failed to fetch our own local AD domain join "
     823             :                         "password for winbindd's internal use, both from "
     824             :                         "secrets.tdb and secrets.ldb: %s\n",
     825             :                         nt_errstr(can_migrate)));
     826           0 :                 return false;
     827             :         }
     828             : 
     829             :         /*
     830             :          * NOTE: It is very unlikely we end up here if there is an
     831             :          * oldpass, because a new password is created at
     832             :          * classicupgrade, so this is not a concern.
     833             :          */
     834           0 :         ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
     835             :                    NULL /* oldpass */,
     836             :                    cli_credentials_get_domain(creds),
     837             :                    cli_credentials_get_realm(creds),
     838             :                    cli_credentials_get_salt_principal(creds),
     839             :                    0, /* Supported enc types, unused */
     840           0 :                    &domain->sid,
     841           0 :                    cli_credentials_get_password_last_changed_time(creds),
     842           0 :                    cli_credentials_get_secure_channel_type(creds),
     843             :                    false /* do_delete: Do not delete */);
     844           0 :         TALLOC_FREE(creds);
     845           0 :         if (ok == false) {
     846           0 :                 DEBUG(0, ("Failed to write our own "
     847             :                           "local AD domain join password for "
     848             :                           "winbindd's internal use into secrets.tdb\n"));
     849           0 :                 return false;
     850             :         }
     851           0 :         return true;
     852             : }
     853             : 
     854         100 : bool add_trusted_domains_dc(void)
     855             : {
     856         100 :         struct winbindd_domain *domain =  NULL;
     857         100 :         struct pdb_trusted_domain **domains = NULL;
     858         100 :         uint32_t num_domains = 0;
     859           0 :         uint32_t i;
     860           0 :         NTSTATUS status;
     861             : 
     862         100 :         if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
     863         100 :                 struct trustdom_info **ti = NULL;
     864             : 
     865         100 :                 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
     866         100 :                 if (!NT_STATUS_IS_OK(status)) {
     867           0 :                         DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
     868             :                                 nt_errstr(status));
     869           0 :                         return false;
     870             :                 }
     871             : 
     872         104 :                 for (i = 0; i < num_domains; i++) {
     873           4 :                         status = add_trusted_domain(ti[i]->name,
     874             :                                                     NULL,
     875           4 :                                                     &ti[i]->sid,
     876             :                                                     LSA_TRUST_TYPE_DOWNLEVEL,
     877             :                                                     NETR_TRUST_FLAG_OUTBOUND,
     878             :                                                     0,
     879             :                                                     SEC_CHAN_DOMAIN,
     880             :                                                     NULL,
     881             :                                                     &domain);
     882           4 :                         if (!NT_STATUS_IS_OK(status)) {
     883           0 :                                 DBG_NOTICE("add_trusted_domain returned %s\n",
     884             :                                            nt_errstr(status));
     885           0 :                                 return false;
     886             :                         }
     887             :                 }
     888             : 
     889         100 :                 return true;
     890             :         }
     891             : 
     892           0 :         status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
     893           0 :         if (!NT_STATUS_IS_OK(status)) {
     894           0 :                 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
     895             :                         nt_errstr(status));
     896           0 :                 return false;
     897             :         }
     898             : 
     899           0 :         for (i = 0; i < num_domains; i++) {
     900           0 :                 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
     901           0 :                 uint32_t trust_flags = 0;
     902             : 
     903           0 :                 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
     904           0 :                         sec_chan_type = SEC_CHAN_DNS_DOMAIN;
     905             :                 }
     906             : 
     907           0 :                 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
     908           0 :                         sec_chan_type = SEC_CHAN_NULL;
     909             :                 }
     910             : 
     911           0 :                 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
     912           0 :                         trust_flags |= NETR_TRUST_FLAG_INBOUND;
     913             :                 }
     914           0 :                 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
     915           0 :                         trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
     916             :                 }
     917           0 :                 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
     918           0 :                         trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
     919             :                 }
     920             : 
     921           0 :                 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION) {
     922             :                         /*
     923             :                          * We don't support selective authentication yet.
     924             :                          */
     925           0 :                         DBG_WARNING("Ignoring CROSS_ORGANIZATION trust to "
     926             :                                     "domain[%s/%s]\n",
     927             :                                     domains[i]->netbios_name,
     928             :                                     domains[i]->domain_name);
     929           0 :                         continue;
     930             :                 }
     931             : 
     932           0 :                 status = add_trusted_domain(domains[i]->netbios_name,
     933           0 :                                             domains[i]->domain_name,
     934           0 :                                             &domains[i]->security_identifier,
     935           0 :                                             domains[i]->trust_type,
     936             :                                             trust_flags,
     937           0 :                                             domains[i]->trust_attributes,
     938             :                                             sec_chan_type,
     939             :                                             NULL,
     940             :                                             &domain);
     941           0 :                 if (!NT_STATUS_IS_OK(status)) {
     942           0 :                         DBG_NOTICE("add_trusted_domain returned %s\n",
     943             :                                    nt_errstr(status));
     944           0 :                         return false;
     945             :                 }
     946             : 
     947           0 :                 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
     948           0 :                         domain->active_directory = true;
     949             :                 }
     950           0 :                 domain->domain_type = domains[i]->trust_type;
     951           0 :                 domain->domain_trust_attribs = domains[i]->trust_attributes;
     952             :         }
     953             : 
     954           0 :         for (i = 0; i < num_domains; i++) {
     955           0 :                 struct ForestTrustInfo fti;
     956           0 :                 uint32_t fi;
     957           0 :                 enum ndr_err_code ndr_err;
     958           0 :                 struct winbindd_domain *routing_domain = NULL;
     959             : 
     960           0 :                 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
     961           0 :                         continue;
     962             :                 }
     963             : 
     964           0 :                 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
     965           0 :                         continue;
     966             :                 }
     967             : 
     968           0 :                 if (domains[i]->trust_forest_trust_info.length == 0) {
     969           0 :                         continue;
     970             :                 }
     971             : 
     972           0 :                 routing_domain = find_domain_from_name_noinit(
     973           0 :                         domains[i]->netbios_name);
     974           0 :                 if (routing_domain == NULL) {
     975           0 :                         DBG_ERR("Can't find winbindd domain [%s]\n",
     976             :                                 domains[i]->netbios_name);
     977           0 :                         return false;
     978             :                 }
     979             : 
     980           0 :                 ndr_err = ndr_pull_struct_blob_all(
     981           0 :                         &domains[i]->trust_forest_trust_info,
     982             :                         talloc_tos(), &fti,
     983             :                         (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
     984           0 :                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
     985           0 :                         DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
     986             :                                 domains[i]->netbios_name,
     987             :                                 ndr_map_error2string(ndr_err));
     988           0 :                         return false;
     989             :                 }
     990             : 
     991           0 :                 for (fi = 0; fi < fti.count; fi++) {
     992           0 :                         struct ForestTrustInfoRecord *rec =
     993           0 :                                 &fti.records[fi].record;
     994           0 :                         struct ForestTrustDataDomainInfo *drec = NULL;
     995             : 
     996           0 :                         if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
     997           0 :                                 continue;
     998             :                         }
     999           0 :                         drec = &rec->data.info;
    1000             : 
    1001           0 :                         if (rec->flags & LSA_NB_DISABLED_MASK) {
    1002           0 :                                 continue;
    1003             :                         }
    1004             : 
    1005           0 :                         if (rec->flags & LSA_SID_DISABLED_MASK) {
    1006           0 :                                 continue;
    1007             :                         }
    1008             : 
    1009             :                         /*
    1010             :                          * TODO:
    1011             :                          * also try to find a matching
    1012             :                          * LSA_TLN_DISABLED_MASK ???
    1013             :                          */
    1014             : 
    1015           0 :                         domain = find_domain_from_name_noinit(drec->netbios_name.string);
    1016           0 :                         if (domain != NULL) {
    1017           0 :                                 continue;
    1018             :                         }
    1019             : 
    1020           0 :                         status = add_trusted_domain(drec->netbios_name.string,
    1021             :                                                     drec->dns_name.string,
    1022           0 :                                                     &drec->sid,
    1023             :                                                     LSA_TRUST_TYPE_UPLEVEL,
    1024             :                                                     NETR_TRUST_FLAG_OUTBOUND,
    1025             :                                                     0,
    1026             :                                                     SEC_CHAN_NULL,
    1027             :                                                     routing_domain,
    1028             :                                                     &domain);
    1029           0 :                         if (!NT_STATUS_IS_OK(status)) {
    1030           0 :                                 DBG_NOTICE("add_trusted_domain returned %s\n",
    1031             :                                            nt_errstr(status));
    1032           0 :                                 return false;
    1033             :                         }
    1034           0 :                         if (domain == NULL) {
    1035           0 :                                 continue;
    1036             :                         }
    1037             :                 }
    1038             :         }
    1039             : 
    1040           0 :         return true;
    1041             : }
    1042             : 
    1043             : 
    1044             : /* Look up global info for the winbind daemon */
    1045          45 : bool init_domain_list(void)
    1046             : {
    1047          45 :         int role = lp_server_role();
    1048          45 :         struct pdb_domain_info *pdb_domain_info = NULL;
    1049          45 :         struct winbindd_domain *domain =  NULL;
    1050           0 :         NTSTATUS status;
    1051           0 :         bool ok;
    1052             : 
    1053             :         /* Free existing list */
    1054          45 :         free_domain_list();
    1055             : 
    1056             :         /* BUILTIN domain */
    1057             : 
    1058          45 :         status = add_trusted_domain("BUILTIN",
    1059             :                                     NULL,
    1060             :                                     &global_sid_Builtin,
    1061             :                                     LSA_TRUST_TYPE_DOWNLEVEL,
    1062             :                                     0, /* trust_flags */
    1063             :                                     0, /* trust_attribs */
    1064             :                                     SEC_CHAN_LOCAL,
    1065             :                                     NULL,
    1066             :                                     &domain);
    1067          45 :         if (!NT_STATUS_IS_OK(status)) {
    1068           0 :                 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
    1069             :                         nt_errstr(status));
    1070           0 :                 return false;
    1071             :         }
    1072             : 
    1073             :         /* Local SAM */
    1074             : 
    1075             :         /*
    1076             :          * In case the passdb backend is passdb_dsdb the domain SID comes from
    1077             :          * dsdb, not from secrets.tdb. As we use the domain SID in various
    1078             :          * places, we must ensure the domain SID is migrated from dsdb to
    1079             :          * secrets.tdb before get_global_sam_sid() is called the first time.
    1080             :          *
    1081             :          * The migration is done as part of the passdb_dsdb initialisation,
    1082             :          * calling pdb_get_domain_info() triggers it.
    1083             :          */
    1084          45 :         pdb_domain_info = pdb_get_domain_info(talloc_tos());
    1085             : 
    1086          45 :         if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
    1087           0 :                 uint32_t trust_flags;
    1088           0 :                 bool is_root;
    1089           0 :                 enum netr_SchannelType sec_chan_type;
    1090           0 :                 const char *account_name;
    1091           0 :                 struct samr_Password current_nt_hash;
    1092             : 
    1093           0 :                 if (pdb_domain_info == NULL) {
    1094           0 :                         DEBUG(0, ("Failed to fetch our own local AD "
    1095             :                                 "domain info from sam.ldb\n"));
    1096           0 :                         return false;
    1097             :                 }
    1098             : 
    1099           0 :                 trust_flags = NETR_TRUST_FLAG_PRIMARY;
    1100           0 :                 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
    1101           0 :                 trust_flags |= NETR_TRUST_FLAG_NATIVE;
    1102           0 :                 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
    1103             : 
    1104           0 :                 is_root = strequal(pdb_domain_info->dns_domain,
    1105           0 :                                    pdb_domain_info->dns_forest);
    1106           0 :                 if (is_root) {
    1107           0 :                         trust_flags |= NETR_TRUST_FLAG_TREEROOT;
    1108             :                 }
    1109             : 
    1110           0 :                 status = add_trusted_domain(pdb_domain_info->name,
    1111           0 :                                             pdb_domain_info->dns_domain,
    1112           0 :                                             &pdb_domain_info->sid,
    1113             :                                             LSA_TRUST_TYPE_UPLEVEL,
    1114             :                                             trust_flags,
    1115             :                                             LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
    1116             :                                             SEC_CHAN_BDC,
    1117             :                                             NULL,
    1118             :                                             &domain);
    1119           0 :                 TALLOC_FREE(pdb_domain_info);
    1120           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1121           0 :                         DBG_ERR("Failed to add our own local AD "
    1122             :                                 "domain to winbindd's internal list\n");
    1123           0 :                         return false;
    1124             :                 }
    1125             : 
    1126             :                 /*
    1127             :                  * We need to call this to find out if we are an RODC
    1128             :                  */
    1129           0 :                 ok = get_trust_pw_hash(domain->name,
    1130             :                                        current_nt_hash.hash,
    1131             :                                        &account_name,
    1132             :                                        &sec_chan_type);
    1133           0 :                 if (!ok) {
    1134             :                         /*
    1135             :                          * If get_trust_pw_hash() fails, then try and
    1136             :                          * fetch the password from the more recent of
    1137             :                          * secrets.{ldb,tdb} using the
    1138             :                          * pdb_get_trust_credentials()
    1139             :                          */
    1140           0 :                         ok = migrate_secrets_tdb_to_ldb(domain);
    1141             : 
    1142           0 :                         if (!ok) {
    1143           0 :                                 DEBUG(0, ("Failed to migrate our own "
    1144             :                                           "local AD domain join password for "
    1145             :                                           "winbindd's internal use into "
    1146             :                                           "secrets.tdb\n"));
    1147           0 :                                 return false;
    1148             :                         }
    1149           0 :                         ok = get_trust_pw_hash(domain->name,
    1150             :                                                current_nt_hash.hash,
    1151             :                                                &account_name,
    1152             :                                                &sec_chan_type);
    1153           0 :                         if (!ok) {
    1154           0 :                                 DEBUG(0, ("Failed to find our own just "
    1155             :                                           "written local AD domain join "
    1156             :                                           "password for winbindd's internal "
    1157             :                                           "use in secrets.tdb\n"));
    1158           0 :                                 return false;
    1159             :                         }
    1160             :                 }
    1161             : 
    1162           0 :                 domain->secure_channel_type = sec_chan_type;
    1163           0 :                 if (sec_chan_type == SEC_CHAN_RODC) {
    1164           0 :                         domain->rodc = true;
    1165             :                 }
    1166             : 
    1167             :         } else {
    1168           0 :                 uint32_t trust_flags;
    1169           0 :                 enum netr_SchannelType secure_channel_type;
    1170             : 
    1171          45 :                 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
    1172          45 :                 if (role != ROLE_DOMAIN_MEMBER) {
    1173          14 :                         trust_flags |= NETR_TRUST_FLAG_PRIMARY;
    1174             :                 }
    1175             : 
    1176          45 :                 if (role > ROLE_DOMAIN_MEMBER) {
    1177          14 :                         secure_channel_type = SEC_CHAN_BDC;
    1178             :                 } else {
    1179          31 :                         secure_channel_type = SEC_CHAN_LOCAL;
    1180             :                 }
    1181             : 
    1182          45 :                 if ((pdb_domain_info != NULL) && (role == ROLE_IPA_DC)) {
    1183             :                         /* This is IPA DC that presents itself as
    1184             :                          * an Active Directory domain controller to trusted AD
    1185             :                          * forests but in fact is a classic domain controller.
    1186             :                          */
    1187           0 :                         trust_flags = NETR_TRUST_FLAG_PRIMARY;
    1188           0 :                         trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
    1189           0 :                         trust_flags |= NETR_TRUST_FLAG_NATIVE;
    1190           0 :                         trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
    1191           0 :                         trust_flags |= NETR_TRUST_FLAG_TREEROOT;
    1192           0 :                         status = add_trusted_domain(pdb_domain_info->name,
    1193           0 :                                                     pdb_domain_info->dns_domain,
    1194           0 :                                                     &pdb_domain_info->sid,
    1195             :                                                     LSA_TRUST_TYPE_UPLEVEL,
    1196             :                                                     trust_flags,
    1197             :                                                     LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
    1198             :                                                     secure_channel_type,
    1199             :                                                     NULL,
    1200             :                                                     &domain);
    1201           0 :                         TALLOC_FREE(pdb_domain_info);
    1202             :                 } else {
    1203          45 :                         status = add_trusted_domain(get_global_sam_name(),
    1204             :                                                     NULL,
    1205          45 :                                                     get_global_sam_sid(),
    1206             :                                                     LSA_TRUST_TYPE_DOWNLEVEL,
    1207             :                                                     trust_flags,
    1208             :                                                     0, /* trust_attribs */
    1209             :                                                     secure_channel_type,
    1210             :                                                     NULL,
    1211             :                                                     &domain);
    1212             :                 }
    1213          45 :                 if (!NT_STATUS_IS_OK(status)) {
    1214           0 :                         DBG_ERR("Failed to add local SAM to "
    1215             :                                 "domain to winbindd's internal list\n");
    1216           0 :                         return false;
    1217             :                 }
    1218             :         }
    1219             : 
    1220          45 :         if (IS_DC) {
    1221          14 :                 ok = add_trusted_domains_dc();
    1222          14 :                 if (!ok) {
    1223           0 :                         DBG_ERR("init_domain_list_dc failed\n");
    1224           0 :                         return false;
    1225             :                 }
    1226             :         }
    1227             : 
    1228          45 :         if ( role == ROLE_DOMAIN_MEMBER ) {
    1229           0 :                 struct dom_sid our_sid;
    1230           0 :                 uint32_t trust_type;
    1231             : 
    1232          31 :                 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
    1233           0 :                         DEBUG(0, ("Could not fetch our SID - did we join?\n"));
    1234           0 :                         return False;
    1235             :                 }
    1236             : 
    1237          31 :                 if (lp_realm() != NULL) {
    1238          31 :                         trust_type = LSA_TRUST_TYPE_UPLEVEL;
    1239             :                 } else {
    1240           0 :                         trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
    1241             :                 }
    1242             : 
    1243          31 :                 status = add_trusted_domain(lp_workgroup(),
    1244             :                                             lp_realm(),
    1245             :                                             &our_sid,
    1246             :                                             trust_type,
    1247             :                                             NETR_TRUST_FLAG_PRIMARY|
    1248             :                                             NETR_TRUST_FLAG_OUTBOUND,
    1249             :                                             0, /* trust_attribs */
    1250             :                                             SEC_CHAN_WKSTA,
    1251             :                                             NULL,
    1252             :                                             &domain);
    1253          31 :                 if (!NT_STATUS_IS_OK(status)) {
    1254           0 :                         DBG_ERR("Failed to add local SAM to "
    1255             :                                 "domain to winbindd's internal list\n");
    1256           0 :                         return false;
    1257             :                 }
    1258             :         }
    1259             : 
    1260          45 :         status = imessaging_register(winbind_imessaging_context(), NULL,
    1261             :                                      MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
    1262             :                                      wb_imsg_new_trusted_domain);
    1263          45 :         if (!NT_STATUS_IS_OK(status)) {
    1264           0 :                 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
    1265           0 :                 return false;
    1266             :         }
    1267             : 
    1268          45 :         return True;
    1269             : }
    1270             : 
    1271             : /**
    1272             :  * Given a domain name, return the struct winbindd domain info for it
    1273             :  *
    1274             :  * @note Do *not* pass lp_workgroup() to this function.  domain_list
    1275             :  *       may modify it's value, and free that pointer.  Instead, our local
    1276             :  *       domain may be found by calling find_our_domain().
    1277             :  *       directly.
    1278             :  *
    1279             :  *
    1280             :  * @return The domain structure for the named domain, if it is working.
    1281             :  */
    1282             : 
    1283        9792 : struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
    1284             : {
    1285           0 :         struct winbindd_domain *domain;
    1286             : 
    1287             :         /* Search through list */
    1288             : 
    1289       23628 :         for (domain = domain_list(); domain != NULL; domain = domain->next) {
    1290       20468 :                 if (strequal(domain_name, domain->name)) {
    1291        6632 :                         return domain;
    1292             :                 }
    1293       13836 :                 if (domain->alt_name == NULL) {
    1294       13713 :                         continue;
    1295             :                 }
    1296         123 :                 if (strequal(domain_name, domain->alt_name)) {
    1297           0 :                         return domain;
    1298             :                 }
    1299             :         }
    1300             : 
    1301             :         /* Not found */
    1302             : 
    1303        3160 :         return NULL;
    1304             : }
    1305             : 
    1306             : /**
    1307             :  * Given a domain name, return the struct winbindd domain if it's a direct
    1308             :  * outgoing trust
    1309             :  *
    1310             :  * @return The domain structure for the named domain, if it is a direct outgoing trust
    1311             :  */
    1312          57 : struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
    1313             : {
    1314          57 :         struct winbindd_domain *domain = NULL;
    1315             : 
    1316          57 :         domain = find_domain_from_name_noinit(domain_name);
    1317          57 :         if (domain == NULL) {
    1318           4 :                 return NULL;
    1319             :         }
    1320             : 
    1321          53 :         if (domain->secure_channel_type != SEC_CHAN_NULL) {
    1322          53 :                 return domain;
    1323             :         }
    1324             : 
    1325           0 :         return NULL;
    1326             : }
    1327             : 
    1328          52 : struct winbindd_domain *find_domain_from_name(const char *domain_name)
    1329             : {
    1330           0 :         struct winbindd_domain *domain;
    1331             : 
    1332          52 :         domain = find_domain_from_name_noinit(domain_name);
    1333             : 
    1334          52 :         if (domain == NULL)
    1335           0 :                 return NULL;
    1336             : 
    1337          52 :         if (!domain->initialized)
    1338           0 :                 init_dc_connection(domain, false);
    1339             : 
    1340          52 :         return domain;
    1341             : }
    1342             : 
    1343             : /* Given a domain sid, return the struct winbindd domain info for it */
    1344             : 
    1345       12524 : struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
    1346             : {
    1347           0 :         struct winbindd_domain *domain;
    1348             : 
    1349             :         /* Search through list */
    1350             : 
    1351       27953 :         for (domain = domain_list(); domain != NULL; domain = domain->next) {
    1352       26394 :                 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
    1353       10965 :                         return domain;
    1354             :         }
    1355             : 
    1356             :         /* Not found */
    1357             : 
    1358        1559 :         return NULL;
    1359             : }
    1360             : 
    1361             : /**
    1362             :  * Given a domain sid, return the struct winbindd domain if it's a direct
    1363             :  * outgoing trust
    1364             :  *
    1365             :  * @return The domain structure for the specified domain, if it is a direct outgoing trust
    1366             :  */
    1367           0 : struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
    1368             : {
    1369           0 :         struct winbindd_domain *domain = NULL;
    1370             : 
    1371           0 :         domain = find_domain_from_sid_noinit(sid);
    1372           0 :         if (domain == NULL) {
    1373           0 :                 return NULL;
    1374             :         }
    1375             : 
    1376           0 :         if (domain->secure_channel_type != SEC_CHAN_NULL) {
    1377           0 :                 return domain;
    1378             :         }
    1379             : 
    1380           0 :         return NULL;
    1381             : }
    1382             : 
    1383             : /* Given a domain sid, return the struct winbindd domain info for it */
    1384             : 
    1385        5610 : struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
    1386             : {
    1387           0 :         struct winbindd_domain *domain;
    1388             : 
    1389        5610 :         domain = find_domain_from_sid_noinit(sid);
    1390             : 
    1391        5610 :         if (domain == NULL)
    1392           0 :                 return NULL;
    1393             : 
    1394        5610 :         if (!domain->initialized)
    1395          11 :                 init_dc_connection(domain, false);
    1396             : 
    1397        5610 :         return domain;
    1398             : }
    1399             : 
    1400      209051 : struct winbindd_domain *find_our_domain(void)
    1401             : {
    1402           0 :         struct winbindd_domain *domain;
    1403             : 
    1404             :         /* Search through list */
    1405             : 
    1406      624993 :         for (domain = domain_list(); domain != NULL; domain = domain->next) {
    1407      624993 :                 if (domain->primary)
    1408      209051 :                         return domain;
    1409             :         }
    1410             : 
    1411           0 :         smb_panic("Could not find our domain");
    1412             :         return NULL;
    1413             : }
    1414             : 
    1415        1416 : struct winbindd_domain *find_default_route_domain(void)
    1416             : {
    1417        1416 :         if (!IS_DC) {
    1418        1416 :                 return find_our_domain();
    1419             :         }
    1420           0 :         DBG_DEBUG("Routing logic not yet implemented on a DC\n");
    1421           0 :         return NULL;
    1422             : }
    1423             : 
    1424             : /* Find the appropriate domain to lookup a name or SID */
    1425             : 
    1426       19067 : struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
    1427             : {
    1428           0 :         struct dom_sid_buf buf;
    1429             : 
    1430       19067 :         DBG_DEBUG("SID [%s]\n", dom_sid_str_buf(sid, &buf));
    1431             : 
    1432             :         /*
    1433             :          * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
    1434             :          * by our passdb.
    1435             :          */
    1436             : 
    1437       38134 :         if ( sid_check_is_in_unix_groups(sid) ||
    1438       38134 :              sid_check_is_unix_groups(sid) ||
    1439       38026 :              sid_check_is_in_unix_users(sid) ||
    1440       37918 :              sid_check_is_unix_users(sid) ||
    1441       37918 :              sid_check_is_our_sam(sid) ||
    1442       18959 :              sid_check_is_in_our_sam(sid) )
    1443             :         {
    1444        3210 :                 return find_domain_from_sid(get_global_sam_sid());
    1445             :         }
    1446             : 
    1447       31706 :         if ( sid_check_is_builtin(sid) ||
    1448       31500 :              sid_check_is_in_builtin(sid) ||
    1449       31302 :              sid_check_is_wellknown_domain(sid, NULL) ||
    1450       15651 :              sid_check_is_in_wellknown_domain(sid) )
    1451             :         {
    1452         290 :                 return find_domain_from_sid(&global_sid_Builtin);
    1453             :         }
    1454             : 
    1455       15567 :         if (IS_DC) {
    1456         128 :                 struct winbindd_domain *domain = NULL;
    1457             : 
    1458         128 :                 domain = find_domain_from_sid_noinit(sid);
    1459         128 :                 if (domain == NULL) {
    1460         124 :                         return NULL;
    1461             :                 }
    1462             : 
    1463           4 :                 if (domain->secure_channel_type != SEC_CHAN_NULL) {
    1464           4 :                         return domain;
    1465             :                 }
    1466             : 
    1467           0 :                 return domain->routing_domain;
    1468             :         }
    1469             : 
    1470             :         /* On a member server a query for SID or name can always go to our
    1471             :          * primary DC. */
    1472             : 
    1473       15439 :         DEBUG(10, ("calling find_our_domain\n"));
    1474       15439 :         return find_our_domain();
    1475             : }
    1476             : 
    1477      100270 : struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
    1478             : {
    1479           0 :         bool predefined;
    1480             : 
    1481      200300 :         if ( strequal(domain_name, unix_users_domain_name() ) ||
    1482      100030 :              strequal(domain_name, unix_groups_domain_name() ) )
    1483             :         {
    1484             :                 /*
    1485             :                  * The "Unix User" and "Unix Group" domain are handled by
    1486             :                  * passdb
    1487             :                  */
    1488         368 :                 return find_domain_from_name_noinit( get_global_sam_name() );
    1489             :         }
    1490             : 
    1491      199732 :         if (strequal(domain_name, "BUILTIN") ||
    1492       99830 :             strequal(domain_name, get_global_sam_name())) {
    1493        4477 :                 return find_domain_from_name_noinit(domain_name);
    1494             :         }
    1495             : 
    1496       95425 :         predefined = dom_sid_lookup_is_predefined_domain(domain_name);
    1497       95425 :         if (predefined) {
    1498          98 :                 return find_domain_from_name_noinit(builtin_domain_name());
    1499             :         }
    1500             : 
    1501       95327 :         if (IS_DC) {
    1502           4 :                 struct winbindd_domain *domain = NULL;
    1503             : 
    1504           4 :                 domain = find_domain_from_name_noinit(domain_name);
    1505           4 :                 if (domain == NULL) {
    1506           2 :                         return NULL;
    1507             :                 }
    1508             : 
    1509           2 :                 if (domain->secure_channel_type != SEC_CHAN_NULL) {
    1510           2 :                         return domain;
    1511             :                 }
    1512             : 
    1513           0 :                 return domain->routing_domain;
    1514             :         }
    1515             : 
    1516       95323 :         return find_our_domain();
    1517             : }
    1518             : 
    1519             : /* Is this a domain which we may assume no DOMAIN\ prefix? */
    1520             : 
    1521      109283 : static bool assume_domain(const char *domain)
    1522             : {
    1523             :         /* never assume the domain on a standalone server */
    1524             : 
    1525      109283 :         if ( lp_server_role() == ROLE_STANDALONE )
    1526           0 :                 return False;
    1527             : 
    1528             :         /* domain member servers may possibly assume for the domain name */
    1529             : 
    1530      109283 :         if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
    1531      104687 :                 if ( !strequal(lp_workgroup(), domain) )
    1532         516 :                         return False;
    1533             : 
    1534      104171 :                 if ( lp_winbind_use_default_domain() )
    1535           0 :                         return True;
    1536             :         }
    1537             : 
    1538             :         /* only left with a domain controller */
    1539             : 
    1540      108767 :         if ( strequal(get_global_sam_name(), domain) )  {
    1541        4518 :                 return True;
    1542             :         }
    1543             : 
    1544      104249 :         return False;
    1545             : }
    1546             : 
    1547             : /* Parse a DOMAIN\user or UPN string into a domain, namespace and a user */
    1548       96112 : bool parse_domain_user(TALLOC_CTX *ctx,
    1549             :                        const char *domuser,
    1550             :                        char **pnamespace,
    1551             :                        char **pdomain,
    1552             :                        char **puser)
    1553             : {
    1554       96112 :         char *p = NULL;
    1555       96112 :         char *namespace = NULL;
    1556       96112 :         char *domain = NULL;
    1557       96112 :         char *user = NULL;
    1558             : 
    1559       96112 :         if (strlen(domuser) == 0) {
    1560           0 :                 return false;
    1561             :         }
    1562             : 
    1563       96112 :         p = strchr(domuser, *lp_winbind_separator());
    1564       96112 :         if (p != NULL) {
    1565       95428 :                 user = talloc_strdup(ctx, p + 1);
    1566       95428 :                 if (user == NULL) {
    1567           0 :                         goto fail;
    1568             :                 }
    1569       95428 :                 domain = talloc_strdup(ctx,
    1570             :                                 domuser);
    1571       95428 :                 if (domain == NULL) {
    1572           0 :                         goto fail;
    1573             :                 }
    1574       95428 :                 domain[PTR_DIFF(p, domuser)] = '\0';
    1575       95428 :                 namespace = talloc_strdup(ctx, domain);
    1576       95428 :                 if (namespace == NULL) {
    1577           0 :                         goto fail;
    1578             :                 }
    1579             :         } else {
    1580         684 :                 user = talloc_strdup(ctx, domuser);
    1581         684 :                 if (user == NULL) {
    1582           0 :                         goto fail;
    1583             :                 }
    1584         684 :                 p = strchr(domuser, '@');
    1585         684 :                 if (p != NULL) {
    1586             :                         /* upn */
    1587          10 :                         namespace = talloc_strdup(ctx, p + 1);
    1588          10 :                         if (namespace == NULL) {
    1589           0 :                                 goto fail;
    1590             :                         }
    1591          10 :                         domain = talloc_strdup(ctx, "");
    1592          10 :                         if (domain == NULL) {
    1593           0 :                                 goto fail;
    1594             :                         }
    1595             : 
    1596         674 :                 } else if (assume_domain(lp_workgroup())) {
    1597         530 :                         domain = talloc_strdup(ctx, lp_workgroup());
    1598         530 :                         if (domain == NULL) {
    1599           0 :                                 goto fail;
    1600             :                         }
    1601         530 :                         namespace = talloc_strdup(ctx, domain);
    1602         530 :                         if (namespace == NULL) {
    1603           0 :                                 goto fail;
    1604             :                         }
    1605             :                 } else {
    1606         144 :                         namespace = talloc_strdup(ctx, lp_netbios_name());
    1607         144 :                         if (namespace == NULL) {
    1608           0 :                                 goto fail;
    1609             :                         }
    1610         144 :                         domain = talloc_strdup(ctx, "");
    1611         144 :                         if (domain == NULL) {
    1612           0 :                                 goto fail;
    1613             :                         }
    1614             :                 }
    1615             :         }
    1616             : 
    1617       96112 :         if (!strupper_m(domain)) {
    1618           0 :                 goto fail;
    1619             :         }
    1620             : 
    1621       96112 :         *pnamespace = namespace;
    1622       96112 :         *pdomain = domain;
    1623       96112 :         *puser = user;
    1624       96112 :         return true;
    1625           0 : fail:
    1626           0 :         TALLOC_FREE(user);
    1627           0 :         TALLOC_FREE(domain);
    1628           0 :         TALLOC_FREE(namespace);
    1629           0 :         return false;
    1630             : }
    1631             : 
    1632         543 : bool canonicalize_username(TALLOC_CTX *mem_ctx,
    1633             :                            char **pusername_inout,
    1634             :                            char **pnamespace,
    1635             :                            char **pdomain,
    1636             :                            char **puser)
    1637             : {
    1638           0 :         bool ok;
    1639         543 :         char *namespace = NULL;
    1640         543 :         char *domain = NULL;
    1641         543 :         char *user = NULL;
    1642         543 :         char *username_inout = NULL;
    1643             : 
    1644         543 :         ok = parse_domain_user(mem_ctx,
    1645             :                         *pusername_inout,
    1646             :                         &namespace, &domain, &user);
    1647             : 
    1648         543 :         if (!ok) {
    1649           0 :                 return False;
    1650             :         }
    1651             : 
    1652        1086 :         username_inout = talloc_asprintf(mem_ctx, "%s%c%s",
    1653         543 :                  domain, *lp_winbind_separator(),
    1654             :                  user);
    1655             : 
    1656         543 :         if (username_inout == NULL) {
    1657           0 :                 goto fail;
    1658             :         }
    1659             : 
    1660         543 :         *pnamespace = namespace;
    1661         543 :         *puser = user;
    1662         543 :         *pdomain = domain;
    1663         543 :         *pusername_inout = username_inout;
    1664         543 :         return True;
    1665           0 : fail:
    1666           0 :         TALLOC_FREE(username_inout);
    1667           0 :         TALLOC_FREE(namespace);
    1668           0 :         TALLOC_FREE(domain);
    1669           0 :         TALLOC_FREE(user);
    1670           0 :         return false;
    1671             : }
    1672             : 
    1673             : /*
    1674             :     Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
    1675             :     'winbind separator' options.
    1676             :     This means:
    1677             :         - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
    1678             :         lp_workgroup()
    1679             : 
    1680             :     If we are a PDC or BDC, and this is for our domain, do likewise.
    1681             : 
    1682             :     On an AD DC we always fill DOMAIN\\USERNAME.
    1683             : 
    1684             :     We always canonicalize as UPPERCASE DOMAIN, lowercase username.
    1685             : */
    1686             : /**
    1687             :  * talloc version of fill_domain_username()
    1688             :  * return NULL on talloc failure.
    1689             :  */
    1690      108615 : char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
    1691             :                                   const char *domain,
    1692             :                                   const char *user,
    1693             :                                   bool can_assume)
    1694             : {
    1695           0 :         char *tmp_user, *name;
    1696             : 
    1697      108615 :         if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
    1698           2 :                 can_assume = false;
    1699             :         }
    1700             : 
    1701      108615 :         if (user == NULL) {
    1702           0 :                 return NULL;
    1703             :         }
    1704             : 
    1705      108615 :         tmp_user = talloc_strdup(mem_ctx, user);
    1706      108615 :         if (tmp_user == NULL) {
    1707           0 :                 return NULL;
    1708             :         }
    1709      108615 :         if (!strlower_m(tmp_user)) {
    1710           0 :                 TALLOC_FREE(tmp_user);
    1711           0 :                 return NULL;
    1712             :         }
    1713             : 
    1714      108615 :         if (can_assume && assume_domain(domain)) {
    1715        3988 :                 name = tmp_user;
    1716             :         } else {
    1717      104627 :                 name = talloc_asprintf(mem_ctx, "%s%c%s",
    1718             :                                        domain,
    1719      104627 :                                        *lp_winbind_separator(),
    1720             :                                        tmp_user);
    1721      104627 :                 TALLOC_FREE(tmp_user);
    1722             :         }
    1723             : 
    1724      108615 :         return name;
    1725             : }
    1726             : 
    1727             : /*
    1728             :  * Client list accessor functions
    1729             :  */
    1730             : 
    1731             : static struct winbindd_cli_state *_client_list;
    1732             : static int _num_clients;
    1733             : 
    1734             : /* Return list of all connected clients */
    1735             : 
    1736           0 : struct winbindd_cli_state *winbindd_client_list(void)
    1737             : {
    1738           0 :         return _client_list;
    1739             : }
    1740             : 
    1741             : /* Return list-tail of all connected clients */
    1742             : 
    1743       13458 : struct winbindd_cli_state *winbindd_client_list_tail(void)
    1744             : {
    1745       13458 :         return DLIST_TAIL(_client_list);
    1746             : }
    1747             : 
    1748             : /* Return previous (read:newer) client in list */
    1749             : 
    1750             : struct winbindd_cli_state *
    1751        8791 : winbindd_client_list_prev(struct winbindd_cli_state *cli)
    1752             : {
    1753        8791 :         return DLIST_PREV(cli);
    1754             : }
    1755             : 
    1756             : /* Add a connection to the list */
    1757             : 
    1758        8054 : void winbindd_add_client(struct winbindd_cli_state *cli)
    1759             : {
    1760        8054 :         cli->last_access = time(NULL);
    1761        8054 :         DLIST_ADD(_client_list, cli);
    1762        8054 :         _num_clients++;
    1763        8054 : }
    1764             : 
    1765             : /* Remove a client from the list */
    1766             : 
    1767        8022 : void winbindd_remove_client(struct winbindd_cli_state *cli)
    1768             : {
    1769        8022 :         DLIST_REMOVE(_client_list, cli);
    1770        8022 :         _num_clients--;
    1771        8022 : }
    1772             : 
    1773             : /* Move a client to head or list */
    1774             : 
    1775      245190 : void winbindd_promote_client(struct winbindd_cli_state *cli)
    1776             : {
    1777      245190 :         cli->last_access = time(NULL);
    1778      245190 :         DLIST_PROMOTE(_client_list, cli);
    1779      245190 : }
    1780             : 
    1781             : /* Return number of open clients */
    1782             : 
    1783        8054 : int winbindd_num_clients(void)
    1784             : {
    1785        8054 :         return _num_clients;
    1786             : }
    1787             : 
    1788        2314 : NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
    1789             :                                   const struct dom_sid *user_sid,
    1790             :                                   uint32_t *p_num_groups, struct dom_sid **user_sids)
    1791             : {
    1792        2314 :         struct netr_SamInfo3 *info3 = NULL;
    1793        2314 :         NTSTATUS status = NT_STATUS_NO_MEMORY;
    1794        2314 :         uint32_t num_groups = 0;
    1795             : 
    1796        2314 :         DEBUG(3,(": lookup_usergroups_cached\n"));
    1797             : 
    1798        2314 :         *user_sids = NULL;
    1799        2314 :         *p_num_groups = 0;
    1800             : 
    1801        2314 :         info3 = netsamlogon_cache_get(mem_ctx, user_sid);
    1802             : 
    1803        2314 :         if (info3 == NULL) {
    1804        2252 :                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
    1805             :         }
    1806             : 
    1807             :         /*
    1808             :          * Before bug #7843 the "Domain Local" groups were added with a
    1809             :          * lookupuseraliases call, but this isn't done anymore for our domain
    1810             :          * so we need to resolve resource groups here.
    1811             :          *
    1812             :          * When to use Resource Groups:
    1813             :          * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
    1814             :          */
    1815          62 :         status = sid_array_from_info3(mem_ctx, info3,
    1816             :                                       user_sids,
    1817             :                                       &num_groups,
    1818             :                                       false);
    1819             : 
    1820          62 :         if (!NT_STATUS_IS_OK(status)) {
    1821           0 :                 TALLOC_FREE(info3);
    1822           0 :                 return status;
    1823             :         }
    1824             : 
    1825          62 :         TALLOC_FREE(info3);
    1826          62 :         *p_num_groups = num_groups;
    1827          62 :         status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
    1828             : 
    1829          62 :         DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
    1830             : 
    1831          62 :         return status;
    1832             : }
    1833             : 
    1834             : /*********************************************************************
    1835             :  We use this to remove spaces from user and group names
    1836             : ********************************************************************/
    1837             : 
    1838      101627 : NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
    1839             :                              const char *domain_name,
    1840             :                              const char *name,
    1841             :                              char **normalized)
    1842             : {
    1843      101627 :         struct winbindd_domain *domain = NULL;
    1844           0 :         NTSTATUS nt_status;
    1845             : 
    1846      101627 :         if (!name || !normalized) {
    1847           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1848             :         }
    1849             : 
    1850      101627 :         if (!lp_winbind_normalize_names()) {
    1851      101627 :                 return NT_STATUS_PROCEDURE_NOT_FOUND;
    1852             :         }
    1853             : 
    1854           0 :         domain = find_domain_from_name_noinit(domain_name);
    1855           0 :         if (domain == NULL) {
    1856           0 :                 DBG_ERR("Failed to find domain '%s'\n",       domain_name);
    1857           0 :                 return NT_STATUS_NO_SUCH_DOMAIN;
    1858             :         }
    1859             : 
    1860             :         /* Alias support and whitespace replacement are mutually
    1861             :            exclusive */
    1862             : 
    1863           0 :         nt_status = resolve_username_to_alias(mem_ctx, domain,
    1864             :                                               name, normalized );
    1865           0 :         if (NT_STATUS_IS_OK(nt_status)) {
    1866             :                 /* special return code to let the caller know we
    1867             :                    mapped to an alias */
    1868           0 :                 return NT_STATUS_FILE_RENAMED;
    1869             :         }
    1870             : 
    1871             :         /* check for an unreachable domain */
    1872             : 
    1873           0 :         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
    1874           0 :                 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
    1875             :                          domain->name));
    1876           0 :                 set_domain_offline(domain);
    1877           0 :                 return nt_status;
    1878             :         }
    1879             : 
    1880             :         /* deal with whitespace */
    1881             : 
    1882           0 :         *normalized = talloc_strdup(mem_ctx, name);
    1883           0 :         if (!(*normalized)) {
    1884           0 :                 return NT_STATUS_NO_MEMORY;
    1885             :         }
    1886             : 
    1887           0 :         all_string_sub( *normalized, " ", "_", 0 );
    1888             : 
    1889           0 :         return NT_STATUS_OK;
    1890             : }
    1891             : 
    1892             : /*********************************************************************
    1893             :  We use this to do the inverse of normalize_name_map()
    1894             : ********************************************************************/
    1895             : 
    1896       95918 : NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
    1897             :                               const char *name,
    1898             :                               char **normalized)
    1899             : {
    1900           0 :         NTSTATUS nt_status;
    1901       95918 :         struct winbindd_domain *domain = find_our_domain();
    1902             : 
    1903       95918 :         if (!name || !normalized) {
    1904           0 :                 return NT_STATUS_INVALID_PARAMETER;
    1905             :         }
    1906             : 
    1907       95918 :         if (!lp_winbind_normalize_names()) {
    1908       95918 :                 return NT_STATUS_PROCEDURE_NOT_FOUND;
    1909             :         }
    1910             : 
    1911             :         /* Alias support and whitespace replacement are mutally
    1912             :            exclusive */
    1913             : 
    1914             :         /* When mapping from an alias to a username, we don't know the
    1915             :            domain.  But we only need a domain structure to cache
    1916             :            a successful lookup , so just our own domain structure for
    1917             :            the seqnum. */
    1918             : 
    1919           0 :         nt_status = resolve_alias_to_username(mem_ctx, domain,
    1920             :                                               name, normalized);
    1921           0 :         if (NT_STATUS_IS_OK(nt_status)) {
    1922             :                 /* Special return code to let the caller know we mapped
    1923             :                    from an alias */
    1924           0 :                 return NT_STATUS_FILE_RENAMED;
    1925             :         }
    1926             : 
    1927             :         /* check for an unreachable domain */
    1928             : 
    1929           0 :         if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
    1930           0 :                 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
    1931             :                          domain->name));
    1932           0 :                 set_domain_offline(domain);
    1933           0 :                 return nt_status;
    1934             :         }
    1935             : 
    1936             :         /* deal with whitespace */
    1937             : 
    1938           0 :         *normalized = talloc_strdup(mem_ctx, name);
    1939           0 :         if (!(*normalized)) {
    1940           0 :                 return NT_STATUS_NO_MEMORY;
    1941             :         }
    1942             : 
    1943           0 :         all_string_sub(*normalized, "_", " ", 0);
    1944             : 
    1945           0 :         return NT_STATUS_OK;
    1946             : }
    1947             : 
    1948             : /*********************************************************************
    1949             :  ********************************************************************/
    1950             : 
    1951           0 : bool winbindd_can_contact_domain(struct winbindd_domain *domain)
    1952             : {
    1953           0 :         struct winbindd_tdc_domain *tdc = NULL;
    1954           0 :         TALLOC_CTX *frame = talloc_stackframe();
    1955           0 :         bool ret = false;
    1956             : 
    1957             :         /* We can contact the domain if it is our primary domain */
    1958             : 
    1959           0 :         if (domain->primary) {
    1960           0 :                 ret = true;
    1961           0 :                 goto done;
    1962             :         }
    1963             : 
    1964             :         /* Trust the TDC cache and not the winbindd_domain flags */
    1965             : 
    1966           0 :         if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
    1967           0 :                 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
    1968             :                           domain->name));
    1969           0 :                 ret = false;
    1970           0 :                 goto done;
    1971             :         }
    1972             : 
    1973             :         /* Can always contact a domain that is in out forest */
    1974             : 
    1975           0 :         if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
    1976           0 :                 ret = true;
    1977           0 :                 goto done;
    1978             :         }
    1979             : 
    1980             :         /*
    1981             :          * On a _member_ server, we cannot contact the domain if it
    1982             :          * is running AD and we have no inbound trust.
    1983             :          */
    1984             : 
    1985           0 :         if (!IS_DC &&
    1986           0 :              domain->active_directory &&
    1987           0 :             ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
    1988             :         {
    1989           0 :                 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
    1990             :                            "and we have no inbound trust.\n", domain->name));
    1991           0 :                 goto done;
    1992             :         }
    1993             : 
    1994             :         /* Assume everything else is ok (probably not true but what
    1995             :            can you do?) */
    1996             : 
    1997           0 :         ret = true;
    1998             : 
    1999           0 : done:
    2000           0 :         talloc_destroy(frame);
    2001             : 
    2002           0 :         return ret;
    2003             : }
    2004             : 
    2005             : #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
    2006             : 
    2007             : /*********************************************************************
    2008             :  ********************************************************************/
    2009             : 
    2010           0 : static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
    2011             : {
    2012           0 :         char *var = NULL;
    2013           0 :         char addr[INET6_ADDRSTRLEN];
    2014           0 :         const char *kdc = NULL;
    2015           0 :         int lvl = 11;
    2016             : 
    2017           0 :         if (!domain || !domain->alt_name || !*domain->alt_name) {
    2018           0 :                 return;
    2019             :         }
    2020             : 
    2021           0 :         if (domain->initialized && !domain->active_directory) {
    2022           0 :                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
    2023             :                         domain->alt_name));
    2024           0 :                 return;
    2025             :         }
    2026             : 
    2027           0 :         print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
    2028           0 :         kdc = addr;
    2029           0 :         if (!*kdc) {
    2030           0 :                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
    2031             :                         domain->alt_name));
    2032           0 :                 kdc = domain->dcname;
    2033             :         }
    2034             : 
    2035           0 :         if (!kdc || !*kdc) {
    2036           0 :                 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
    2037             :                         domain->alt_name));
    2038           0 :                 return;
    2039             :         }
    2040             : 
    2041           0 :         var = talloc_asprintf_strupper_m(
    2042             :                 talloc_tos(),
    2043             :                 "%s_%s",
    2044             :                 WINBINDD_LOCATOR_KDC_ADDRESS,
    2045           0 :                 domain->alt_name);
    2046           0 :         if (var == NULL) {
    2047           0 :                 return;
    2048             :         }
    2049             : 
    2050           0 :         DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
    2051             :                 var, kdc));
    2052             : 
    2053           0 :         setenv(var, kdc, 1);
    2054           0 :         TALLOC_FREE(var);
    2055             : }
    2056             : 
    2057             : /*********************************************************************
    2058             :  ********************************************************************/
    2059             : 
    2060           0 : void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
    2061             : {
    2062           0 :         struct winbindd_domain *our_dom = find_our_domain();
    2063             : 
    2064           0 :         winbindd_set_locator_kdc_env(domain);
    2065             : 
    2066           0 :         if (domain != our_dom) {
    2067           0 :                 winbindd_set_locator_kdc_env(our_dom);
    2068             :         }
    2069           0 : }
    2070             : 
    2071             : /*********************************************************************
    2072             :  ********************************************************************/
    2073             : 
    2074           0 : void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
    2075             : {
    2076           0 :         char *var = NULL;
    2077             : 
    2078           0 :         if (!domain || !domain->alt_name || !*domain->alt_name) {
    2079           0 :                 return;
    2080             :         }
    2081             : 
    2082           0 :         var = talloc_asprintf_strupper_m(
    2083             :                 talloc_tos(),
    2084             :                 "%s_%s",
    2085             :                 WINBINDD_LOCATOR_KDC_ADDRESS,
    2086           0 :                 domain->alt_name);
    2087           0 :         if (var == NULL) {
    2088           0 :                 return;
    2089             :         }
    2090             : 
    2091           0 :         unsetenv(var);
    2092           0 :         TALLOC_FREE(var);
    2093             : }
    2094             : #else
    2095             : 
    2096             : void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
    2097             : {
    2098             :         return;
    2099             : }
    2100             : 
    2101             : void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
    2102             : {
    2103             :         return;
    2104             : }
    2105             : 
    2106             : #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
    2107             : 
    2108        4912 : void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
    2109             : {
    2110             :         /*
    2111             :          * Make sure we start with authoritative=true,
    2112             :          * it will only set to false if we don't know the
    2113             :          * domain.
    2114             :          */
    2115        4912 :         resp->data.auth.authoritative = true;
    2116             : 
    2117        4912 :         resp->data.auth.nt_status = NT_STATUS_V(result);
    2118        4912 :         fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
    2119             : 
    2120             :         /* we might have given a more useful error above */
    2121        4912 :         if (*resp->data.auth.error_string == '\0')
    2122        4912 :                 fstrcpy(resp->data.auth.error_string,
    2123             :                         get_friendly_nt_error_msg(result));
    2124        4912 :         resp->data.auth.pam_error = nt_status_to_pam(result);
    2125        4912 : }
    2126             : 
    2127      106045 : bool is_domain_offline(const struct winbindd_domain *domain)
    2128             : {
    2129      106045 :         if (get_global_winbindd_state_offline()) {
    2130           0 :                 return true;
    2131             :         }
    2132      106045 :         return !domain->online;
    2133             : }
    2134             : 
    2135      106045 : bool is_domain_online(const struct winbindd_domain *domain)
    2136             : {
    2137      106045 :         return !is_domain_offline(domain);
    2138             : }
    2139             : 
    2140             : /**
    2141             :  * Parse an char array into a list of sids.
    2142             :  *
    2143             :  * The input sidstr should consist of 0-terminated strings
    2144             :  * representing sids, separated by newline characters '\n'.
    2145             :  * The list is terminated by an empty string, i.e.
    2146             :  * character '\0' directly following a character '\n'
    2147             :  * (or '\0' right at the start of sidstr).
    2148             :  */
    2149        1996 : bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
    2150             :                    struct dom_sid **sids, uint32_t *num_sids)
    2151             : {
    2152           0 :         const char *p;
    2153             : 
    2154        1996 :         p = sidstr;
    2155        1996 :         if (p == NULL)
    2156           0 :                 return False;
    2157             : 
    2158        4777 :         while (p[0] != '\0') {
    2159           0 :                 struct dom_sid sid;
    2160        2781 :                 const char *q = NULL;
    2161             : 
    2162        2781 :                 if (!dom_sid_parse_endp(p, &sid, &q)) {
    2163           0 :                         DEBUG(1, ("Could not parse sid %s\n", p));
    2164           0 :                         return false;
    2165             :                 }
    2166        2781 :                 if (q[0] != '\n') {
    2167           0 :                         DEBUG(1, ("Got invalid sidstr: %s\n", p));
    2168           0 :                         return false;
    2169             :                 }
    2170        2781 :                 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
    2171             :                                                       num_sids)))
    2172             :                 {
    2173           0 :                         return False;
    2174             :                 }
    2175        2781 :                 p = q+1;
    2176             :         }
    2177        1996 :         return True;
    2178             : }
    2179             : 
    2180        1988 : bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
    2181             :                    struct unixid **pxids, uint32_t *pnum_xids)
    2182             : {
    2183           0 :         const char *p;
    2184        1988 :         struct unixid *xids = NULL;
    2185        1988 :         uint32_t num_xids = 0;
    2186             : 
    2187        1988 :         p = xidstr;
    2188        1988 :         if (p == NULL) {
    2189           0 :                 return false;
    2190             :         }
    2191             : 
    2192        4044 :         while (p[0] != '\0') {
    2193           0 :                 struct unixid *tmp;
    2194           0 :                 struct unixid xid;
    2195           0 :                 unsigned long long id;
    2196           0 :                 char *endp;
    2197        2056 :                 int error = 0;
    2198             : 
    2199        2056 :                 switch (p[0]) {
    2200          42 :                 case 'U':
    2201          42 :                         xid = (struct unixid) { .type = ID_TYPE_UID };
    2202          42 :                         break;
    2203        2014 :                 case 'G':
    2204        2014 :                         xid = (struct unixid) { .type = ID_TYPE_GID };
    2205        2014 :                         break;
    2206           0 :                 default:
    2207           0 :                         return false;
    2208             :                 }
    2209             : 
    2210        2056 :                 p += 1;
    2211             : 
    2212        2056 :                 id = smb_strtoull(p, &endp, 10, &error, SMB_STR_STANDARD);
    2213        2056 :                 if (error != 0) {
    2214           0 :                         goto fail;
    2215             :                 }
    2216        2056 :                 if (*endp != '\n') {
    2217           0 :                         goto fail;
    2218             :                 }
    2219        2056 :                 p = endp+1;
    2220             : 
    2221        2056 :                 xid.id = id;
    2222        2056 :                 if ((unsigned long long)xid.id != id) {
    2223           0 :                         goto fail;
    2224             :                 }
    2225             : 
    2226        2056 :                 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
    2227        2056 :                 if (tmp == NULL) {
    2228           0 :                         return 0;
    2229             :                 }
    2230        2056 :                 xids = tmp;
    2231             : 
    2232        2056 :                 xids[num_xids] = xid;
    2233        2056 :                 num_xids += 1;
    2234             :         }
    2235             : 
    2236        1988 :         *pxids = xids;
    2237        1988 :         *pnum_xids = num_xids;
    2238        1988 :         return true;
    2239             : 
    2240           0 : fail:
    2241           0 :         TALLOC_FREE(xids);
    2242           0 :         return false;
    2243             : }

Generated by: LCOV version 1.14