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

Generated by: LCOV version 1.14