X-Git-Url: http://git.samba.org/?a=blobdiff_plain;f=source3%2Fmodules%2Fvfs_expand_msdfs.c;h=96f68e02c8d3024a686ef26688392407c6d24690;hb=HEAD;hp=46a6616db95d81503764c99df3fbc036fda965dd;hpb=f6d86af4a2488aee1b8fdacc7228c18e12edde37;p=samba.git diff --git a/source3/modules/vfs_expand_msdfs.c b/source3/modules/vfs_expand_msdfs.c index 46a6616db95..503ee84e8a4 100644 --- a/source3/modules/vfs_expand_msdfs.c +++ b/source3/modules/vfs_expand_msdfs.c @@ -5,7 +5,7 @@ * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or + * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, @@ -14,11 +14,18 @@ * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * along with this program; if not, see . */ #include "includes.h" +#include "system/filesys.h" +#include "smbd/smbd.h" +#include "../librpc/gen_ndr/ndr_netlogon.h" +#include "smbd/globals.h" +#include "auth.h" +#include "../lib/tsocket/tsocket.h" +#include "msdfs.h" +#include "source3/lib/substitute.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_VFS @@ -36,26 +43,27 @@ This is to redirect a DFS client to a host close to it. ***********************************************************/ -static BOOL read_target_host(const char *mapfile, pstring targethost) +static char *read_target_host(TALLOC_CTX *ctx, const char *mapfile, + const char *clientaddr) { - XFILE *f; - pstring buf; - char *s, *space = buf; - BOOL found = False; - - f = x_fopen(mapfile, O_RDONLY, 0); + FILE *f; + char buf[1024]; + char *space = buf; + bool found = false; + + f = fopen(mapfile, "r"); if (f == NULL) { DEBUG(0,("can't open IP map %s. Error %s\n", mapfile, strerror(errno) )); - return False; + return NULL; } DEBUG(10, ("Scanning mapfile [%s]\n", mapfile)); - while ((s=x_fgets(buf, sizeof(buf), f)) != NULL) { + while (fgets(buf, sizeof(buf), f) != NULL) { - if (buf[strlen(buf)-1] == '\n') + if ((strlen(buf) > 0) && (buf[strlen(buf)-1] == '\n')) buf[strlen(buf)-1] = '\0'; DEBUG(10, ("Scanning line [%s]\n", buf)); @@ -69,24 +77,24 @@ static BOOL read_target_host(const char *mapfile, pstring targethost) *space = '\0'; - if (strncmp(client_addr(), buf, strlen(buf)) == 0) { - found = True; + if (strncmp(clientaddr, buf, strlen(buf)) == 0) { + found = true; break; } } - x_fclose(f); + fclose(f); - if (!found) - return False; + if (!found) { + return NULL; + } space += 1; while (isspace(*space)) space += 1; - pstrcpy(targethost, space); - return True; + return talloc_strdup(ctx, space); } /********************************************************** @@ -102,90 +110,161 @@ static BOOL read_target_host(const char *mapfile, pstring targethost) ***********************************************************/ -static BOOL expand_msdfs_target(connection_struct* conn, pstring target) +static char *expand_msdfs_target(TALLOC_CTX *ctx, + connection_struct *conn, + char *target) { - pstring mapfilename; + const struct loadparm_substitution *lp_sub = + loadparm_s3_global_substitution(); + char *mapfilename = NULL; char *filename_start = strchr_m(target, '@'); - char *filename_end; - int filename_len; - pstring targethost; - pstring new_target; + char *filename_end = NULL; + int filename_len = 0; + char *targethost = NULL; + char *new_target = NULL; + char *raddr; if (filename_start == NULL) { DEBUG(10, ("No filename start in %s\n", target)); - return False; + return NULL; } filename_end = strchr_m(filename_start+1, '@'); if (filename_end == NULL) { DEBUG(10, ("No filename end in %s\n", target)); - return False; + return NULL; } filename_len = PTR_DIFF(filename_end, filename_start+1); - pstrcpy(mapfilename, filename_start+1); + mapfilename = talloc_strdup(ctx, filename_start+1); + if (!mapfilename) { + return NULL; + } mapfilename[filename_len] = '\0'; + /* + * dfs links returned have had '/' characters replaced with '\'. + * Return them to '/' so we can have absolute path mapfilenames. + */ + string_replace(mapfilename, '\\', '/'); + DEBUG(10, ("Expanding from table [%s]\n", mapfilename)); - if (!read_target_host(mapfilename, targethost)) { + raddr = tsocket_address_inet_addr_string(conn->sconn->remote_address, + ctx); + if (raddr == NULL) { + return NULL; + } + + targethost = read_target_host(ctx, mapfilename, raddr); + if (targethost == NULL) { DEBUG(1, ("Could not expand target host from file %s\n", mapfilename)); - return False; + return NULL; } - standard_sub_conn(conn, mapfilename, sizeof(mapfilename)); + targethost = talloc_sub_full(ctx, + lp_servicename(talloc_tos(), lp_sub, SNUM(conn)), + conn->session_info->unix_info->unix_name, + conn->connectpath, + conn->session_info->unix_token->gid, + conn->session_info->unix_info->sanitized_username, + conn->session_info->info->domain_name, + targethost); DEBUG(10, ("Expanded targethost to %s\n", targethost)); + /* Replace the part between '@...@' */ *filename_start = '\0'; - pstrcpy(new_target, target); - pstrcat(new_target, targethost); - pstrcat(new_target, filename_end+1); + new_target = talloc_asprintf(ctx, + "%s%s%s", + target, + targethost, + filename_end+1); + if (!new_target) { + return NULL; + } DEBUG(10, ("New DFS target: %s\n", new_target)); - pstrcpy(target, new_target); - return True; + return new_target; } -static int expand_msdfs_readlink(struct vfs_handle_struct *handle, - struct connection_struct *conn, - const char *path, char *buf, size_t bufsiz) +static NTSTATUS expand_read_dfs_pathat(struct vfs_handle_struct *handle, + TALLOC_CTX *mem_ctx, + struct files_struct *dirfsp, + struct smb_filename *smb_fname, + struct referral **ppreflist, + size_t *preferral_count) { - pstring target; - int result; - - result = SMB_VFS_NEXT_READLINK(handle, conn, path, target, - sizeof(target)); - - if (result < 0) - return result; + NTSTATUS status; + size_t i; + struct referral *reflist = NULL; + size_t count = 0; + TALLOC_CTX *frame = talloc_stackframe(); + + /* + * Always call the NEXT function first, then + * modify the return if needed. + */ + status = SMB_VFS_NEXT_READ_DFS_PATHAT(handle, + mem_ctx, + dirfsp, + smb_fname, + ppreflist, + preferral_count); + + if (!NT_STATUS_IS_OK(status)) { + TALLOC_FREE(frame); + return status; + } - target[result] = '\0'; + /* + * This function can be called to check if a pathname + * is an MSDFS link, but not return the values of it. + * In this case ppreflist and preferral_count are NULL, + * so don't bother trying to look at any returns. + */ + if (ppreflist == NULL || preferral_count == NULL) { + TALLOC_FREE(frame); + return status; + } - if ((strncmp(target, "msdfs:", strlen("msdfs:")) == 0) && - (strchr_m(target, '@') != NULL)) { - if (!expand_msdfs_target(conn, target)) { - errno = ENOENT; - return -1; + /* + * We are always returning the values returned + * returned by the NEXT call, but we might mess + * with the reflist[i].alternate_path values, + * so use local pointers to minimise indirections. + */ + count = *preferral_count; + reflist = *ppreflist; + + for (i = 0; i < count; i++) { + if (strchr_m(reflist[i].alternate_path, '@') != NULL) { + char *new_altpath = expand_msdfs_target(frame, + handle->conn, + reflist[i].alternate_path); + if (new_altpath == NULL) { + TALLOC_FREE(*ppreflist); + *preferral_count = 0; + TALLOC_FREE(frame); + return NT_STATUS_NO_MEMORY; + } + reflist[i].alternate_path = talloc_move(reflist, + &new_altpath); } } - - safe_strcpy(buf, target, bufsiz-1); - return strlen(buf); + TALLOC_FREE(frame); + return status; } -/* VFS operations structure */ - -static vfs_op_tuple expand_msdfs_ops[] = { - {SMB_VFS_OP(expand_msdfs_readlink), SMB_VFS_OP_READLINK, - SMB_VFS_LAYER_TRANSPARENT}, - {SMB_VFS_OP(NULL), SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP} +static struct vfs_fn_pointers vfs_expand_msdfs_fns = { + .read_dfs_pathat_fn = expand_read_dfs_pathat, }; -NTSTATUS vfs_expand_msdfs_init(void) +static_decl_vfs; +NTSTATUS vfs_expand_msdfs_init(TALLOC_CTX *ctx) { return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "expand_msdfs", - expand_msdfs_ops); + &vfs_expand_msdfs_fns); }