root/source3/modules/vfs_expand_msdfs.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. read_target_host
  2. expand_msdfs_target
  3. expand_msdfs_readlink
  4. vfs_expand_msdfs_init

   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 
  22 #undef DBGC_CLASS
  23 #define DBGC_CLASS DBGC_VFS
  24 
  25 /**********************************************************
  26   Under mapfile we expect a table of the following format:
  27 
  28   IP-Prefix whitespace expansion
  29 
  30   For example:
  31   192.168.234 local.samba.org
  32   192.168     remote.samba.org
  33               default.samba.org
  34 
  35   This is to redirect a DFS client to a host close to it.
  36 ***********************************************************/
  37 
  38 static char *read_target_host(TALLOC_CTX *ctx, const char *mapfile)
     /* [<][>][^][v][top][bottom][index][help] */
  39 {
  40         XFILE *f;
  41         char buf[1024];
  42         char *space = buf;
  43         bool found = false;
  44 
  45         f = x_fopen(mapfile, O_RDONLY, 0);
  46 
  47         if (f == NULL) {
  48                 DEBUG(0,("can't open IP map %s. Error %s\n",
  49                          mapfile, strerror(errno) ));
  50                 return NULL;
  51         }
  52 
  53         DEBUG(10, ("Scanning mapfile [%s]\n", mapfile));
  54 
  55         while (x_fgets(buf, sizeof(buf), f) != NULL) {
  56                 char addr[INET6_ADDRSTRLEN];
  57 
  58                 if ((strlen(buf) > 0) && (buf[strlen(buf)-1] == '\n'))
  59                         buf[strlen(buf)-1] = '\0';
  60 
  61                 DEBUG(10, ("Scanning line [%s]\n", buf));
  62 
  63                 space = strchr_m(buf, ' ');
  64 
  65                 if (space == NULL) {
  66                         DEBUG(0, ("Ignoring invalid line %s\n", buf));
  67                         continue;
  68                 }
  69 
  70                 *space = '\0';
  71 
  72                 if (strncmp(client_addr(get_client_fd(),addr,sizeof(addr)),
  73                                 buf, strlen(buf)) == 0) {
  74                         found = true;
  75                         break;
  76                 }
  77         }
  78 
  79         x_fclose(f);
  80 
  81         if (!found) {
  82                 return NULL;
  83         }
  84 
  85         space += 1;
  86 
  87         while (isspace(*space))
  88                 space += 1;
  89 
  90         return talloc_strdup(ctx, space);
  91 }
  92 
  93 /**********************************************************
  94 
  95   Expand the msdfs target host using read_target_host
  96   explained above. The syntax used in the msdfs link is
  97 
  98   msdfs:@table-filename@/share
  99 
 100   Everything between and including the two @-signs is
 101   replaced by the substitution string found in the table
 102   described above.
 103 
 104 ***********************************************************/
 105 
 106 static char *expand_msdfs_target(TALLOC_CTX *ctx,
     /* [<][>][^][v][top][bottom][index][help] */
 107                                 connection_struct *conn,
 108                                 char *target)
 109 {
 110         char *mapfilename = NULL;
 111         char *filename_start = strchr_m(target, '@');
 112         char *filename_end = NULL;
 113         int filename_len = 0;
 114         char *targethost = NULL;
 115         char *new_target = NULL;
 116 
 117         if (filename_start == NULL) {
 118                 DEBUG(10, ("No filename start in %s\n", target));
 119                 return NULL;
 120         }
 121 
 122         filename_end = strchr_m(filename_start+1, '@');
 123 
 124         if (filename_end == NULL) {
 125                 DEBUG(10, ("No filename end in %s\n", target));
 126                 return NULL;
 127         }
 128 
 129         filename_len = PTR_DIFF(filename_end, filename_start+1);
 130         mapfilename = talloc_strdup(ctx, filename_start+1);
 131         if (!mapfilename) {
 132                 return NULL;
 133         }
 134         mapfilename[filename_len] = '\0';
 135 
 136         DEBUG(10, ("Expanding from table [%s]\n", mapfilename));
 137 
 138         if ((targethost = read_target_host(ctx, mapfilename)) == NULL) {
 139                 DEBUG(1, ("Could not expand target host from file %s\n",
 140                           mapfilename));
 141                 return NULL;
 142         }
 143 
 144         targethost = talloc_sub_advanced(ctx,
 145                                 lp_servicename(SNUM(conn)),
 146                                 conn->server_info->unix_name,
 147                                 conn->connectpath,
 148                                 conn->server_info->utok.gid,
 149                                 conn->server_info->sanitized_username,
 150                                 pdb_get_domain(conn->server_info->sam_account),
 151                                 targethost);
 152 
 153         DEBUG(10, ("Expanded targethost to %s\n", targethost));
 154 
 155         /* Replace the part between '@...@' */
 156         *filename_start = '\0';
 157         new_target = talloc_asprintf(ctx,
 158                                 "%s%s%s",
 159                                 target,
 160                                 targethost,
 161                                 filename_end+1);
 162         if (!new_target) {
 163                 return NULL;
 164         }
 165 
 166         DEBUG(10, ("New DFS target: %s\n", new_target));
 167         return new_target;
 168 }
 169 
 170 static int expand_msdfs_readlink(struct vfs_handle_struct *handle,
     /* [<][>][^][v][top][bottom][index][help] */
 171                                  const char *path, char *buf, size_t bufsiz)
 172 {
 173         TALLOC_CTX *ctx = talloc_tos();
 174         int result;
 175         char *target = TALLOC_ARRAY(ctx, char, PATH_MAX+1);
 176 
 177         if (!target) {
 178                 errno = ENOMEM;
 179                 return -1;
 180         }
 181         result = SMB_VFS_NEXT_READLINK(handle, path, target,
 182                                        PATH_MAX);
 183 
 184         if (result < 0)
 185                 return result;
 186 
 187         target[result] = '\0';
 188 
 189         if ((strncmp(target, "msdfs:", strlen("msdfs:")) == 0) &&
 190             (strchr_m(target, '@') != NULL)) {
 191                 target = expand_msdfs_target(ctx, handle->conn, target);
 192                 if (!target) {
 193                         errno = ENOENT;
 194                         return -1;
 195                 }
 196         }
 197 
 198         safe_strcpy(buf, target, bufsiz-1);
 199         return strlen(buf);
 200 }
 201 
 202 /* VFS operations structure */
 203 
 204 static vfs_op_tuple expand_msdfs_ops[] = {
 205         {SMB_VFS_OP(expand_msdfs_readlink), SMB_VFS_OP_READLINK,
 206          SMB_VFS_LAYER_TRANSPARENT},
 207         {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
 208 };
 209 
 210 NTSTATUS vfs_expand_msdfs_init(void);
 211 NTSTATUS vfs_expand_msdfs_init(void)
     /* [<][>][^][v][top][bottom][index][help] */
 212 {
 213         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "expand_msdfs",
 214                                 expand_msdfs_ops);
 215 }

/* [<][>][^][v][top][bottom][index][help] */