LCOV - code coverage report
Current view: top level - source3/modules - vfs_expand_msdfs.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 2 98 2.0 %
Date: 2021-09-23 10:06:22 Functions: 1 4 25.0 %

          Line data    Source code
       1             : /* 
       2             :  * Expand msdfs targets based on client IP
       3             :  *
       4             :  * Copyright (C) Volker Lendecke, 2004
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify
       7             :  * it under the terms of the GNU General Public License as published by
       8             :  * the Free Software Foundation; either version 3 of the License, or
       9             :  * (at your option) any later version.
      10             :  *  
      11             :  * This program is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :  * GNU General Public License for more details.
      15             :  *  
      16             :  * You should have received a copy of the GNU General Public License
      17             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include "includes.h"
      21             : #include "system/filesys.h"
      22             : #include "smbd/smbd.h"
      23             : #include "../librpc/gen_ndr/ndr_netlogon.h"
      24             : #include "smbd/globals.h"
      25             : #include "auth.h"
      26             : #include "../lib/tsocket/tsocket.h"
      27             : #include "msdfs.h"
      28             : 
      29             : #undef DBGC_CLASS
      30             : #define DBGC_CLASS DBGC_VFS
      31             : 
      32             : /**********************************************************
      33             :   Under mapfile we expect a table of the following format:
      34             : 
      35             :   IP-Prefix whitespace expansion
      36             : 
      37             :   For example:
      38             :   192.168.234 local.samba.org
      39             :   192.168     remote.samba.org
      40             :               default.samba.org
      41             : 
      42             :   This is to redirect a DFS client to a host close to it.
      43             : ***********************************************************/
      44             : 
      45           0 : static char *read_target_host(TALLOC_CTX *ctx, const char *mapfile,
      46             :                               const char *clientaddr)
      47             : {
      48             :         FILE *f;
      49             :         char buf[1024];
      50           0 :         char *space = buf;
      51           0 :         bool found = false;
      52             : 
      53           0 :         f = fopen(mapfile, "r");
      54             : 
      55           0 :         if (f == NULL) {
      56           0 :                 DEBUG(0,("can't open IP map %s. Error %s\n",
      57             :                          mapfile, strerror(errno) ));
      58           0 :                 return NULL;
      59             :         }
      60             : 
      61           0 :         DEBUG(10, ("Scanning mapfile [%s]\n", mapfile));
      62             : 
      63           0 :         while (fgets(buf, sizeof(buf), f) != NULL) {
      64             : 
      65           0 :                 if ((strlen(buf) > 0) && (buf[strlen(buf)-1] == '\n'))
      66           0 :                         buf[strlen(buf)-1] = '\0';
      67             : 
      68           0 :                 DEBUG(10, ("Scanning line [%s]\n", buf));
      69             : 
      70           0 :                 space = strchr_m(buf, ' ');
      71             : 
      72           0 :                 if (space == NULL) {
      73           0 :                         DEBUG(0, ("Ignoring invalid line %s\n", buf));
      74           0 :                         continue;
      75             :                 }
      76             : 
      77           0 :                 *space = '\0';
      78             : 
      79           0 :                 if (strncmp(clientaddr, buf, strlen(buf)) == 0) {
      80           0 :                         found = true;
      81           0 :                         break;
      82             :                 }
      83             :         }
      84             : 
      85           0 :         fclose(f);
      86             : 
      87           0 :         if (!found) {
      88           0 :                 return NULL;
      89             :         }
      90             : 
      91           0 :         space += 1;
      92             : 
      93           0 :         while (isspace(*space))
      94           0 :                 space += 1;
      95             : 
      96           0 :         return talloc_strdup(ctx, space);
      97             : }
      98             : 
      99             : /**********************************************************
     100             : 
     101             :   Expand the msdfs target host using read_target_host
     102             :   explained above. The syntax used in the msdfs link is
     103             : 
     104             :   msdfs:@table-filename@/share
     105             : 
     106             :   Everything between and including the two @-signs is
     107             :   replaced by the substitution string found in the table
     108             :   described above.
     109             : 
     110             : ***********************************************************/
     111             : 
     112           0 : static char *expand_msdfs_target(TALLOC_CTX *ctx,
     113             :                                 connection_struct *conn,
     114             :                                 char *target)
     115             : {
     116           0 :         const struct loadparm_substitution *lp_sub =
     117             :                 loadparm_s3_global_substitution();
     118           0 :         char *mapfilename = NULL;
     119           0 :         char *filename_start = strchr_m(target, '@');
     120           0 :         char *filename_end = NULL;
     121           0 :         int filename_len = 0;
     122           0 :         char *targethost = NULL;
     123           0 :         char *new_target = NULL;
     124             :         char *raddr;
     125             : 
     126           0 :         if (filename_start == NULL) {
     127           0 :                 DEBUG(10, ("No filename start in %s\n", target));
     128           0 :                 return NULL;
     129             :         }
     130             : 
     131           0 :         filename_end = strchr_m(filename_start+1, '@');
     132             : 
     133           0 :         if (filename_end == NULL) {
     134           0 :                 DEBUG(10, ("No filename end in %s\n", target));
     135           0 :                 return NULL;
     136             :         }
     137             : 
     138           0 :         filename_len = PTR_DIFF(filename_end, filename_start+1);
     139           0 :         mapfilename = talloc_strdup(ctx, filename_start+1);
     140           0 :         if (!mapfilename) {
     141           0 :                 return NULL;
     142             :         }
     143           0 :         mapfilename[filename_len] = '\0';
     144             : 
     145             :         /*
     146             :          * dfs links returned have had '/' characters replaced with '\'.
     147             :          * Return them to '/' so we can have absoute path mapfilenames.
     148             :          */
     149           0 :         string_replace(mapfilename, '\\', '/');
     150             : 
     151           0 :         DEBUG(10, ("Expanding from table [%s]\n", mapfilename));
     152             : 
     153           0 :         raddr = tsocket_address_inet_addr_string(conn->sconn->remote_address,
     154             :                                                  ctx);
     155           0 :         if (raddr == NULL) {
     156           0 :                 return NULL;
     157             :         }
     158             : 
     159           0 :         targethost = read_target_host(ctx, mapfilename, raddr);
     160           0 :         if (targethost == NULL) {
     161           0 :                 DEBUG(1, ("Could not expand target host from file %s\n",
     162             :                           mapfilename));
     163           0 :                 return NULL;
     164             :         }
     165             : 
     166           0 :         targethost = talloc_sub_full(ctx,
     167           0 :                                 lp_servicename(talloc_tos(), lp_sub, SNUM(conn)),
     168           0 :                                 conn->session_info->unix_info->unix_name,
     169           0 :                                 conn->connectpath,
     170           0 :                                 conn->session_info->unix_token->gid,
     171           0 :                                 conn->session_info->unix_info->sanitized_username,
     172           0 :                                 conn->session_info->info->domain_name,
     173             :                                 targethost);
     174             : 
     175           0 :         DEBUG(10, ("Expanded targethost to %s\n", targethost));
     176             : 
     177             :         /* Replace the part between '@...@' */
     178           0 :         *filename_start = '\0';
     179           0 :         new_target = talloc_asprintf(ctx,
     180             :                                 "%s%s%s",
     181             :                                 target,
     182             :                                 targethost,
     183             :                                 filename_end+1);
     184           0 :         if (!new_target) {
     185           0 :                 return NULL;
     186             :         }
     187             : 
     188           0 :         DEBUG(10, ("New DFS target: %s\n", new_target));
     189           0 :         return new_target;
     190             : }
     191             : 
     192           0 : static NTSTATUS expand_read_dfs_pathat(struct vfs_handle_struct *handle,
     193             :                                 TALLOC_CTX *mem_ctx,
     194             :                                 struct files_struct *dirfsp,
     195             :                                 struct smb_filename *smb_fname,
     196             :                                 struct referral **ppreflist,
     197             :                                 size_t *preferral_count)
     198             : {
     199             :         NTSTATUS status;
     200             :         size_t i;
     201           0 :         struct referral *reflist = NULL;
     202           0 :         size_t count = 0;
     203           0 :         TALLOC_CTX *frame = talloc_stackframe();
     204             : 
     205             :         /*
     206             :          * Always call the NEXT function first, then
     207             :          * modify the return if needed.
     208             :          */
     209           0 :         status = SMB_VFS_NEXT_READ_DFS_PATHAT(handle,
     210             :                                 mem_ctx,
     211             :                                 dirfsp,
     212             :                                 smb_fname,
     213             :                                 ppreflist,
     214             :                                 preferral_count);
     215             : 
     216           0 :         if (!NT_STATUS_IS_OK(status)) {
     217           0 :                 TALLOC_FREE(frame);
     218           0 :                 return status;
     219             :         }
     220             : 
     221             :         /*
     222             :          * This function can be called to check if a pathname
     223             :          * is an MSDFS link, but not return the values of it.
     224             :          * In this case ppreflist and preferral_count are NULL,
     225             :          * so don't bother trying to look at any returns.
     226             :          */
     227           0 :         if (ppreflist == NULL || preferral_count == NULL) {
     228           0 :                 TALLOC_FREE(frame);
     229           0 :                 return status;
     230             :         }
     231             : 
     232             :         /*
     233             :          * We are always returning the values returned
     234             :          * returned by the NEXT call, but we might mess
     235             :          * with the reflist[i].alternate_path values,
     236             :          * so use local pointers to minimise indirections.
     237             :          */
     238           0 :         count = *preferral_count;
     239           0 :         reflist = *ppreflist;
     240             : 
     241           0 :         for (i = 0; i < count; i++) {
     242           0 :                 if (strchr_m(reflist[i].alternate_path, '@') != NULL) {
     243           0 :                         char *new_altpath = expand_msdfs_target(frame,
     244           0 :                                                 handle->conn,
     245           0 :                                                 reflist[i].alternate_path);
     246           0 :                         if (new_altpath == NULL) {
     247           0 :                                 TALLOC_FREE(*ppreflist);
     248           0 :                                 *preferral_count = 0;
     249           0 :                                 TALLOC_FREE(frame);
     250           0 :                                 return NT_STATUS_NO_MEMORY;
     251             :                         }
     252           0 :                         reflist[i].alternate_path = talloc_move(reflist,
     253             :                                                         &new_altpath);
     254             :                 }
     255             :         }
     256           0 :         TALLOC_FREE(frame);
     257           0 :         return status;
     258             : }
     259             : 
     260             : static struct vfs_fn_pointers vfs_expand_msdfs_fns = {
     261             :         .read_dfs_pathat_fn = expand_read_dfs_pathat,
     262             : };
     263             : 
     264             : static_decl_vfs;
     265          20 : NTSTATUS vfs_expand_msdfs_init(TALLOC_CTX *ctx)
     266             : {
     267          20 :         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "expand_msdfs",
     268             :                                 &vfs_expand_msdfs_fns);
     269             : }

Generated by: LCOV version 1.13