LCOV - code coverage report
Current view: top level - source3/winbindd - winbindd_misc.c (source / functions) Hit Total Coverage
Test: coverage report for fix-15632 9995c5c2 Lines: 155 254 61.0 %
Date: 2024-04-13 12:30:31 Functions: 16 17 94.1 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Winbind daemon - miscellaneous other functions
       5             : 
       6             :    Copyright (C) Tim Potter      2000
       7             :    Copyright (C) Andrew Bartlett 2002
       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 "libcli/security/dom_sid.h"
      26             : #include "lib/util/string_wrappers.h"
      27             : 
      28             : #undef DBGC_CLASS
      29             : #define DBGC_CLASS DBGC_WINBIND
      30             : 
      31         256 : static char *get_trust_type_string(TALLOC_CTX *mem_ctx,
      32             :                                    struct winbindd_tdc_domain *tdc,
      33             :                                    struct winbindd_domain *domain)
      34             : {
      35         256 :         enum netr_SchannelType secure_channel_type = SEC_CHAN_NULL;
      36         256 :         char *s = NULL;
      37             : 
      38         256 :         if (domain != NULL) {
      39         256 :                 secure_channel_type = domain->secure_channel_type;
      40             :         }
      41             : 
      42         256 :         switch (secure_channel_type) {
      43          60 :         case SEC_CHAN_NULL: {
      44          60 :                 if (domain == NULL) {
      45           0 :                         DBG_ERR("Missing domain [%s]\n",
      46             :                                 tdc->domain_name);
      47           0 :                         return NULL;
      48             :                 }
      49          60 :                 if (domain->routing_domain == NULL) {
      50           0 :                         DBG_ERR("Missing routing for domain [%s]\n",
      51             :                                 tdc->domain_name);
      52           0 :                         return NULL;
      53             :                 }
      54          60 :                 s = talloc_asprintf(mem_ctx, "Routed (via %s)",
      55          60 :                                     domain->routing_domain->name);
      56          60 :                 if (s == NULL) {
      57           0 :                         return NULL;
      58             :                 }
      59          60 :                 break;
      60             :         }
      61             : 
      62         126 :         case SEC_CHAN_LOCAL:
      63         126 :                 s = talloc_strdup(mem_ctx, "Local");
      64         126 :                 if (s == NULL) {
      65           0 :                         return NULL;
      66             :                 }
      67         126 :                 break;
      68             : 
      69          56 :         case SEC_CHAN_WKSTA:
      70          56 :                 s = talloc_strdup(mem_ctx, "Workstation");
      71          56 :                 if (s == NULL) {
      72           0 :                         return NULL;
      73             :                 }
      74          56 :                 break;
      75             : 
      76          14 :         case SEC_CHAN_BDC: {
      77          14 :                 int role = lp_server_role();
      78             : 
      79          14 :                 if (role == ROLE_DOMAIN_PDC || role == ROLE_IPA_DC) {
      80          14 :                         s = talloc_strdup(mem_ctx, "PDC");
      81          14 :                         if (s == NULL) {
      82           0 :                                 return NULL;
      83             :                         }
      84          14 :                         break;
      85             :                 }
      86             : 
      87           0 :                 if (role == ROLE_DOMAIN_BDC) {
      88           0 :                         s = talloc_strdup(mem_ctx, "BDC");
      89           0 :                         if (s == NULL) {
      90           0 :                                 return NULL;
      91             :                         }
      92           0 :                         break;
      93             :                 }
      94             : 
      95           0 :                 s = talloc_strdup(mem_ctx, "RWDC");
      96           0 :                 if (s == NULL) {
      97           0 :                         return NULL;
      98             :                 }
      99           0 :                 break;
     100             :         }
     101             : 
     102           0 :         case SEC_CHAN_RODC:
     103           0 :                 s = talloc_strdup(mem_ctx, "RODC");
     104           0 :                 if (s == NULL) {
     105           0 :                         return NULL;
     106             :                 }
     107           0 :                 break;
     108             : 
     109           0 :         case SEC_CHAN_DNS_DOMAIN:
     110           0 :                 if (tdc->trust_attribs & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) {
     111           0 :                         s = talloc_strdup(mem_ctx, "External");
     112           0 :                         if (s == NULL) {
     113           0 :                                 return NULL;
     114             :                         }
     115           0 :                         break;
     116             :                 }
     117           0 :                 if (tdc->trust_attribs & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
     118           0 :                         s = talloc_strdup(mem_ctx, "In Forest");
     119           0 :                         if (s == NULL) {
     120           0 :                                 return NULL;
     121             :                         }
     122           0 :                         break;
     123             :                 }
     124           0 :                 if (tdc->trust_attribs & LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL) {
     125           0 :                         s = talloc_strdup(mem_ctx, "External");
     126           0 :                         if (s == NULL) {
     127           0 :                                 return NULL;
     128             :                         }
     129           0 :                         break;
     130             :                 }
     131           0 :                 if (tdc->trust_attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
     132           0 :                         s = talloc_strdup(mem_ctx, "Forest");
     133           0 :                         if (s == NULL) {
     134           0 :                                 return NULL;
     135             :                         }
     136           0 :                         break;
     137             :                 }
     138           0 :                 s = talloc_strdup(mem_ctx, "External");
     139           0 :                 if (s == NULL) {
     140           0 :                         return NULL;
     141             :                 }
     142           0 :                 break;
     143             : 
     144           0 :         case SEC_CHAN_DOMAIN:
     145           0 :                 s = talloc_strdup(mem_ctx, "External");
     146           0 :                 if (s == NULL) {
     147           0 :                         return NULL;
     148             :                 }
     149           0 :                 break;
     150             : 
     151           0 :         default:
     152           0 :                 DBG_ERR("Unhandled secure_channel_type %d for domain[%s]\n",
     153             :                         secure_channel_type, tdc->domain_name);
     154           0 :                 return NULL;
     155             :         }
     156             : 
     157         256 :         return s;
     158             : }
     159             : 
     160         256 : static bool trust_is_inbound(struct winbindd_tdc_domain *domain)
     161             : {
     162         256 :         if (domain->trust_flags & NETR_TRUST_FLAG_INBOUND) {
     163           0 :                 return true;
     164             :         }
     165         256 :         return false;
     166             : }
     167             : 
     168         256 : static bool trust_is_outbound(struct winbindd_tdc_domain *domain)
     169             : {
     170         256 :         if (domain->trust_flags & NETR_TRUST_FLAG_OUTBOUND) {
     171         186 :                 return true;
     172             :         }
     173          70 :         return false;
     174             : }
     175             : 
     176         256 : static bool trust_is_transitive(struct winbindd_tdc_domain *domain)
     177             : {
     178         256 :         bool transitive = false;
     179             : 
     180             :         /*
     181             :          * Beware: order matters
     182             :          */
     183             : 
     184         256 :         if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
     185           0 :                 transitive = true;
     186             :         }
     187             : 
     188         256 :         if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
     189           0 :                 transitive = true;
     190             :         }
     191             : 
     192         256 :         if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
     193           0 :                 transitive = false;
     194             :         }
     195             : 
     196         256 :         if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) {
     197           0 :                 transitive = false;
     198             :         }
     199             : 
     200         256 :         if (domain->trust_flags & NETR_TRUST_FLAG_PRIMARY) {
     201          70 :                 transitive = true;
     202             :         }
     203             : 
     204         256 :         return transitive;
     205             : }
     206             : 
     207          70 : bool winbindd_list_trusted_domains(struct winbindd_cli_state *state)
     208             : {
     209          70 :         struct winbindd_tdc_domain *dom_list = NULL;
     210          70 :         size_t num_domains = 0;
     211          70 :         int extra_data_len = 0;
     212          70 :         char *extra_data = NULL;
     213          70 :         size_t i = 0;
     214          70 :         bool ret = false;
     215             : 
     216          70 :         DBG_NOTICE("[%s (%u)]: list trusted domains\n",
     217             :                    state->client_name,
     218             :                    (unsigned int)state->pid);
     219             : 
     220          70 :         if( !wcache_tdc_fetch_list( &dom_list, &num_domains )) {
     221           0 :                 goto done;
     222             :         }
     223             : 
     224          70 :         extra_data = talloc_strdup(state->mem_ctx, "");
     225          70 :         if (extra_data == NULL) {
     226           0 :                 goto done;
     227             :         }
     228             : 
     229         326 :         for ( i = 0; i < num_domains; i++ ) {
     230           0 :                 struct winbindd_domain *domain;
     231         256 :                 bool is_online = true;
     232         256 :                 struct winbindd_tdc_domain *d = NULL;
     233         256 :                 char *trust_type = NULL;
     234           0 :                 struct dom_sid_buf buf;
     235             : 
     236         256 :                 d = &dom_list[i];
     237         256 :                 domain = find_domain_from_name_noinit(d->domain_name);
     238         256 :                 if (domain) {
     239         256 :                         is_online = domain->online;
     240             :                 }
     241             : 
     242         256 :                 trust_type = get_trust_type_string(talloc_tos(), d, domain);
     243         256 :                 if (trust_type == NULL) {
     244           0 :                         continue;
     245             :                 }
     246             : 
     247        1280 :                 extra_data = talloc_asprintf_append_buffer(
     248             :                         extra_data,
     249             :                         "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s\n",
     250             :                         d->domain_name,
     251         256 :                         d->dns_name ? d->dns_name : "",
     252         256 :                         dom_sid_str_buf(&d->sid, &buf),
     253             :                         trust_type,
     254         256 :                         trust_is_transitive(d) ? "Yes" : "No",
     255         256 :                         trust_is_inbound(d) ? "Yes" : "No",
     256         256 :                         trust_is_outbound(d) ? "Yes" : "No",
     257             :                         is_online ? "Online" : "Offline" );
     258             : 
     259         256 :                 TALLOC_FREE(trust_type);
     260             :         }
     261             : 
     262          70 :         state->response->data.num_entries = num_domains;
     263             : 
     264          70 :         extra_data_len = strlen(extra_data);
     265          70 :         if (extra_data_len > 0) {
     266             : 
     267             :                 /* Strip the last \n */
     268          70 :                 extra_data[extra_data_len-1] = '\0';
     269             : 
     270          70 :                 state->response->extra_data.data = extra_data;
     271          70 :                 state->response->length += extra_data_len;
     272             :         }
     273             : 
     274          70 :         ret = true;
     275          70 : done:
     276          70 :         TALLOC_FREE( dom_list );
     277          70 :         return ret;
     278             : }
     279             : 
     280           4 : bool winbindd_dc_info(struct winbindd_cli_state *cli)
     281             : {
     282           0 :         struct winbindd_domain *domain;
     283           0 :         char *dc_name, *dc_ip;
     284             : 
     285           4 :         cli->request->domain_name[sizeof(cli->request->domain_name)-1] = '\0';
     286             : 
     287           4 :         DBG_NOTICE("[%s (%u)]: domain_info [%s]\n",
     288             :                    cli->client_name,
     289             :                    (unsigned int)cli->pid,
     290             :                    cli->request->domain_name);
     291             : 
     292           4 :         if (cli->request->domain_name[0] != '\0') {
     293           4 :                 domain = find_trust_from_name_noinit(
     294           4 :                         cli->request->domain_name);
     295           4 :                 if (domain == NULL) {
     296           0 :                         DEBUG(10, ("Could not find domain %s\n",
     297             :                                    cli->request->domain_name));
     298           0 :                         return false;
     299             :                 }
     300             :         } else {
     301           0 :                 domain = find_our_domain();
     302             :         }
     303             : 
     304           4 :         if (!fetch_current_dc_from_gencache(
     305           4 :                     talloc_tos(), domain->name, &dc_name, &dc_ip)) {
     306           0 :                 DEBUG(10, ("fetch_current_dc_from_gencache(%s) failed\n",
     307             :                            domain->name));
     308           0 :                 return false;
     309             :         }
     310             : 
     311           4 :         cli->response->data.num_entries = 1;
     312           8 :         cli->response->extra_data.data = talloc_asprintf(
     313           4 :                 cli->mem_ctx, "%s\n%s\n", dc_name, dc_ip);
     314             : 
     315           4 :         TALLOC_FREE(dc_name);
     316           4 :         TALLOC_FREE(dc_ip);
     317             : 
     318           4 :         if (cli->response->extra_data.data == NULL) {
     319           0 :                 return false;
     320             :         }
     321             : 
     322             :         /* must add one to length to copy the 0 for string termination */
     323           4 :         cli->response->length +=
     324           4 :                 strlen((char *)cli->response->extra_data.data) + 1;
     325             : 
     326           4 :         return true;
     327             : }
     328             : 
     329      112557 : bool winbindd_ping(struct winbindd_cli_state *state)
     330             : {
     331      112557 :         DBG_NOTICE("[%s (%u)]: ping\n",
     332             :                    state->client_name,
     333             :                    (unsigned int)state->pid);
     334      112557 :         return true;
     335             : }
     336             : 
     337             : /* List various tidbits of information */
     338             : 
     339        2137 : bool winbindd_info(struct winbindd_cli_state *state)
     340             : {
     341             : 
     342        2137 :         DBG_NOTICE("[%s (%u)]: request misc info\n",
     343             :                    state->client_name,
     344             :                    (unsigned int)state->pid);
     345             : 
     346        2137 :         state->response->data.info.winbind_separator = *lp_winbind_separator();
     347        2137 :         fstrcpy(state->response->data.info.samba_version, samba_version_string());
     348        2137 :         return true;
     349             : }
     350             : 
     351             : /* Tell the client the current interface version */
     352             : 
     353        7544 : bool winbindd_interface_version(struct winbindd_cli_state *state)
     354             : {
     355        7544 :         DBG_NOTICE("[%s (%u)]: request interface version (version = %d)\n",
     356             :                    state->client_name,
     357             :                    (unsigned int)state->pid,
     358             :                    WINBIND_INTERFACE_VERSION);
     359             : 
     360        7544 :         state->response->data.interface_version = WINBIND_INTERFACE_VERSION;
     361        7544 :         return true;
     362             : }
     363             : 
     364             : /* What domain are we a member of? */
     365             : 
     366         725 : bool winbindd_domain_name(struct winbindd_cli_state *state)
     367             : {
     368         725 :         DBG_NOTICE("[%s (%u)]: request domain name\n",
     369             :                    state->client_name,
     370             :                    (unsigned int)state->pid);
     371             : 
     372         725 :         fstrcpy(state->response->data.domain_name, lp_workgroup());
     373         725 :         return true;
     374             : }
     375             : 
     376             : /* What's my name again? */
     377             : 
     378         721 : bool winbindd_netbios_name(struct winbindd_cli_state *state)
     379             : {
     380         721 :         DBG_NOTICE("[%s (%u)]: request netbios name\n",
     381             :                    state->client_name,
     382             :                    (unsigned int)state->pid);
     383             : 
     384         721 :         fstrcpy(state->response->data.netbios_name, lp_netbios_name());
     385         721 :         return true;
     386             : }
     387             : 
     388             : /* Where can I find the privileged pipe? */
     389             : 
     390        1266 : char *get_winbind_priv_pipe_dir(void)
     391             : {
     392        1266 :         return state_path(talloc_tos(), WINBINDD_PRIV_SOCKET_SUBDIR);
     393             : }
     394             : 
     395        1184 : bool winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
     396             : {
     397           0 :         char *priv_dir;
     398             : 
     399        1184 :         DBG_NOTICE("[%s (%u)]: request location of privileged pipe\n",
     400             :                    state->client_name,
     401             :                    (unsigned int)state->pid);
     402             : 
     403        1184 :         priv_dir = get_winbind_priv_pipe_dir();
     404        1184 :         state->response->extra_data.data = talloc_move(state->mem_ctx,
     405             :                                                       &priv_dir);
     406             : 
     407             :         /* must add one to length to copy the 0 for string termination */
     408        1184 :         state->response->length +=
     409        1184 :                 strlen((char *)state->response->extra_data.data) + 1;
     410             : 
     411        1184 :         DBG_NOTICE("[%s (%u)]: response location of privileged pipe: %s\n",
     412             :                    state->client_name,
     413             :                    (unsigned int)state->pid,
     414             :                    priv_dir);
     415             : 
     416        1184 :         return true;
     417             : }
     418             : 
     419         123 : static void winbindd_setup_max_fds(void)
     420             : {
     421         123 :         int num_fds = MAX_OPEN_FUDGEFACTOR;
     422           0 :         int actual_fds;
     423             : 
     424         123 :         num_fds += lp_winbind_max_clients();
     425             :         /* Add some more to account for 2 sockets open
     426             :            when the client transitions from unprivileged
     427             :            to privileged socket
     428             :         */
     429         123 :         num_fds += lp_winbind_max_clients() / 10;
     430             : 
     431             :         /* Add one socket per child process
     432             :            (yeah there are child processes other than the
     433             :            domain children but only domain children can vary
     434             :            with configuration
     435             :         */
     436         123 :         num_fds += lp_winbind_max_domain_connections() *
     437         123 :                    (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
     438             : 
     439         123 :         actual_fds = set_maxfiles(num_fds);
     440             : 
     441         123 :         if (actual_fds < num_fds) {
     442           0 :                 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
     443             :                           "requested %d open files, %d are available.\n",
     444             :                           num_fds, actual_fds));
     445             :         }
     446         123 : }
     447             : 
     448         123 : bool winbindd_reload_services_file(const char *lfile)
     449             : {
     450           0 :         const struct loadparm_substitution *lp_sub =
     451         123 :                 loadparm_s3_global_substitution();
     452           0 :         bool ret;
     453             : 
     454         123 :         if (lp_loaded()) {
     455         123 :                 char *fname = lp_next_configfile(talloc_tos(), lp_sub);
     456             : 
     457         123 :                 if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
     458           0 :                         set_dyn_CONFIGFILE(fname);
     459             :                 }
     460         123 :                 TALLOC_FREE(fname);
     461             :         }
     462             : 
     463         123 :         reopen_logs();
     464         123 :         ret = lp_load_global(get_dyn_CONFIGFILE());
     465             : 
     466             :         /* if this is a child, restore the logfile to the special
     467             :            name - <domain>, idmap, etc. */
     468         123 :         if (lfile && *lfile) {
     469           0 :                 lp_set_logfile(lfile);
     470             :         }
     471             : 
     472         123 :         reopen_logs();
     473         123 :         load_interfaces();
     474         123 :         winbindd_setup_max_fds();
     475             : 
     476         123 :         return(ret);
     477             : }
     478             : 
     479             : static size_t *debug_call_depth = NULL;
     480             : 
     481          41 : void winbind_debug_call_depth_setup(size_t *depth)
     482             : {
     483          41 :         debug_call_depth = depth;
     484          41 : }
     485             : 
     486           0 : void winbind_call_flow(void *private_data,
     487             :                        enum tevent_thread_call_depth_cmd cmd,
     488             :                        struct tevent_req *req,
     489             :                        size_t depth,
     490             :                        const char *fname)
     491             : {
     492           0 :         switch (cmd) {
     493           0 :         case TEVENT_CALL_FLOW_REQ_CREATE:
     494           0 :                 *debug_call_depth = depth;
     495           0 :                 DEBUG(20, ("flow: -> %s\n", fname));
     496           0 :                 break;
     497           0 :         case TEVENT_CALL_FLOW_REQ_NOTIFY_CB:
     498           0 :                 *debug_call_depth = depth;
     499           0 :                 DEBUG(20, ("flow: <- %s\n", fname));
     500           0 :                 break;
     501           0 :         case TEVENT_CALL_FLOW_REQ_QUEUE_TRIGGER:
     502           0 :                 *debug_call_depth = depth;
     503           0 :                 break;
     504           0 :         case TEVENT_CALL_FLOW_REQ_RESET:
     505           0 :                 *debug_call_depth = depth;
     506           0 :                 break;
     507           0 :         case TEVENT_CALL_FLOW_REQ_CANCEL:
     508             :         case TEVENT_CALL_FLOW_REQ_CLEANUP:
     509             :         case TEVENT_CALL_FLOW_REQ_QUEUE_ENTER:
     510             :         case TEVENT_CALL_FLOW_REQ_QUEUE_LEAVE:
     511           0 :                 break;
     512             :         }
     513           0 : }

Generated by: LCOV version 1.14