Ejemplo n.º 1
0
int get_real_filename(connection_struct *conn, const char *path,
		      const char *name, TALLOC_CTX *mem_ctx,
		      char **found_name)
{
	struct smb_Dir *cur_dir;
	const char *dname;
	bool mangled;
	char *unmangled_name = NULL;
	long curpos;

	/* open the directory */
	if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) {
		DEBUG(3,("scan dir didn't open dir [%s]\n",path));
		TALLOC_FREE(unmangled_name);
		return -1;
	}

	/* now scan for matching names */
	curpos = 0;
	while ((dname = ReadDirName(cur_dir, &curpos, NULL))) {

		/* Is it dot or dot dot. */
		if (ISDOT(dname) || ISDOTDOT(dname)) {
			continue;
		}

		/*
		 * At this point dname is the unmangled name.
		 * name is either mangled or not, depending on the state
		 * of the "mangled" variable. JRA.
		 */

		/*
		 * Check mangled name against mangled name, or unmangled name
		 * against unmangled name.
		 */

		if ((mangled && mangled_equal(name,dname,conn->params)) ||
			fname_equal(name, dname, conn->case_sensitive)) {
			/* we've found the file, change it's name and return */
			*found_name = talloc_strdup(mem_ctx, dname);
			TALLOC_FREE(unmangled_name);
			TALLOC_FREE(cur_dir);
			if (!*found_name) {
				errno = ENOMEM;
				return -1;
			}
			return 0;
		}
	}

	TALLOC_FREE(unmangled_name);
	TALLOC_FREE(cur_dir);
	errno = ENOENT;
	return -1;
}
Ejemplo n.º 2
0
static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
				  connection_struct *conn,
				  const char *orig_path,
				  struct smb_filename *smb_fname)
{
	NTSTATUS status;
	unsigned int i, num_streams = 0;
	struct stream_struct *streams = NULL;

	if (SMB_VFS_STAT(conn, smb_fname) == 0) {
		DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
		return NT_STATUS_OK;
	}

	if (errno != ENOENT) {
		DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno)));
		status = map_nt_error_from_unix(errno);
		goto fail;
	}

	/* Fall back to a case-insensitive scan of all streams on the file. */
	status = vfs_streaminfo(conn, NULL, smb_fname->base_name, mem_ctx,
				&num_streams, &streams);

	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
		SET_STAT_INVALID(smb_fname->st);
		return NT_STATUS_OK;
	}

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status)));
		goto fail;
	}

	for (i=0; i<num_streams; i++) {
		DEBUG(10, ("comparing [%s] and [%s]: ",
			   smb_fname->stream_name, streams[i].name));
		if (fname_equal(smb_fname->stream_name, streams[i].name,
				conn->case_sensitive)) {
			DEBUGADD(10, ("equal\n"));
			break;
		}
		DEBUGADD(10, ("not equal\n"));
	}

	/* Couldn't find the stream. */
	if (i == num_streams) {
		SET_STAT_INVALID(smb_fname->st);
		TALLOC_FREE(streams);
		return NT_STATUS_OK;
	}

	DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n",
		smb_fname->stream_name, streams[i].name));


	TALLOC_FREE(smb_fname->stream_name);
	smb_fname->stream_name = talloc_strdup(smb_fname, streams[i].name);
	if (smb_fname->stream_name == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto fail;
	}

	SET_STAT_INVALID(smb_fname->st);

	if (SMB_VFS_STAT(conn, smb_fname) == 0) {
		DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname)));
	}
	status = NT_STATUS_OK;
 fail:
	TALLOC_FREE(streams);
	return status;
}
Ejemplo n.º 3
0
static int get_real_filename_full_scan(connection_struct *conn,
				       const char *path, const char *name,
				       bool mangled,
				       TALLOC_CTX *mem_ctx, char **found_name)
{
	struct smb_Dir *cur_dir;
	const char *dname = NULL;
	char *talloced = NULL;
	char *unmangled_name = NULL;
	long curpos;

	/* handle null paths */
	if ((path == NULL) || (*path == 0)) {
		path = ".";
	}

	/* If we have a case-sensitive filesystem, it doesn't do us any
	 * good to search for a name. If a case variation of the name was
	 * there, then the original stat(2) would have found it.
	 */
	if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
		errno = ENOENT;
		return -1;
	}

	/*
	 * The incoming name can be mangled, and if we de-mangle it
	 * here it will not compare correctly against the filename (name2)
	 * read from the directory and then mangled by the name_to_8_3()
	 * call. We need to mangle both names or neither.
	 * (JRA).
	 *
	 * Fix for bug found by Dina Fine. If in case sensitive mode then
	 * the mangle cache is no good (3 letter extension could be wrong
	 * case - so don't demangle in this case - leave as mangled and
	 * allow the mangling of the directory entry read (which is done
	 * case insensitively) to match instead. This will lead to more
	 * false positive matches but we fail completely without it. JRA.
	 */

	if (mangled && !conn->case_sensitive) {
		mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name,
						       &unmangled_name,
						       conn->params);
		if (!mangled) {
			/* Name is now unmangled. */
			name = unmangled_name;
		}
	}

	/* open the directory */
	if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) {
		DEBUG(3,("scan dir didn't open dir [%s]\n",path));
		TALLOC_FREE(unmangled_name);
		return -1;
	}

	/* now scan for matching names */
	curpos = 0;
	while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) {

		/* Is it dot or dot dot. */
		if (ISDOT(dname) || ISDOTDOT(dname)) {
			TALLOC_FREE(talloced);
			continue;
		}

		/*
		 * At this point dname is the unmangled name.
		 * name is either mangled or not, depending on the state
		 * of the "mangled" variable. JRA.
		 */

		/*
		 * Check mangled name against mangled name, or unmangled name
		 * against unmangled name.
		 */

		if ((mangled && mangled_equal(name,dname,conn->params)) ||
			fname_equal(name, dname, conn->case_sensitive)) {
			/* we've found the file, change it's name and return */
			*found_name = talloc_strdup(mem_ctx, dname);
			TALLOC_FREE(unmangled_name);
			TALLOC_FREE(cur_dir);
			if (!*found_name) {
				errno = ENOMEM;
				TALLOC_FREE(talloced);
				return -1;
			}
			TALLOC_FREE(talloced);
			return 0;
		}
		TALLOC_FREE(talloced);
	}

	TALLOC_FREE(unmangled_name);
	TALLOC_FREE(cur_dir);
	errno = ENOENT;
	return -1;
}
Ejemplo n.º 4
0
static BOOL scan_directory(connection_struct *conn, const char *path, char *name, size_t maxlength)
{
	struct smb_Dir *cur_dir;
	const char *dname;
	BOOL mangled;
	long curpos;

	mangled = mangle_is_mangled(name, conn->params);

	/* handle null paths */
	if (*path == 0)
		path = ".";

	/* If we have a case-sensitive filesystem, it doesn't do us any
	 * good to search for a name. If a case variation of the name was
	 * there, then the original stat(2) would have found it.
	 */
	if (!(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) {
		errno = ENOENT;
		return False;
	}

	/*
	 * The incoming name can be mangled, and if we de-mangle it
	 * here it will not compare correctly against the filename (name2)
	 * read from the directory and then mangled by the mangle_map()
	 * call. We need to mangle both names or neither.
	 * (JRA).
	 *
	 * Fix for bug found by Dina Fine. If in case sensitive mode then
	 * the mangle cache is no good (3 letter extension could be wrong
	 * case - so don't demangle in this case - leave as mangled and
	 * allow the mangling of the directory entry read (which is done
	 * case insensitively) to match instead. This will lead to more
	 * false positive matches but we fail completely without it. JRA.
	 */

	if (mangled && !conn->case_sensitive) {
		mangled = !mangle_check_cache( name, maxlength, conn->params);
	}

	/* open the directory */
	if (!(cur_dir = OpenDir(conn, path, NULL, 0))) {
		DEBUG(3,("scan dir didn't open dir [%s]\n",path));
		return(False);
	}

	/* now scan for matching names */
	curpos = 0;
	while ((dname = ReadDirName(cur_dir, &curpos))) {

		/* Is it dot or dot dot. */
		if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) {
			continue;
		}

		/*
		 * At this point dname is the unmangled name.
		 * name is either mangled or not, depending on the state of the "mangled"
		 * variable. JRA.
		 */

		/*
		 * Check mangled name against mangled name, or unmangled name
		 * against unmangled name.
		 */

		if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) {
			/* we've found the file, change it's name and return */
			safe_strcpy(name, dname, maxlength);
			CloseDir(cur_dir);
			return(True);
		}
	}

	CloseDir(cur_dir);
	errno = ENOENT;
	return(False);
}
Ejemplo n.º 5
0
static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx,
				  connection_struct *conn,
				  const char *orig_path,
				  const char *basepath,
				  const char *streamname,
				  SMB_STRUCT_STAT *pst,
				  char **path)
{
	SMB_STRUCT_STAT st;
	char *result = NULL;
	NTSTATUS status;
	unsigned int i, num_streams;
	struct stream_struct *streams = NULL;

	result = talloc_asprintf(mem_ctx, "%s%s", basepath, streamname);
	if (result == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	if (SMB_VFS_STAT(conn, result, &st) == 0) {
		*pst = st;
		*path = result;
		return NT_STATUS_OK;
	}

	if (errno != ENOENT) {
		status = map_nt_error_from_unix(errno);
		DEBUG(10, ("vfs_stat failed: %s\n", nt_errstr(status)));
		goto fail;
	}

	status = SMB_VFS_STREAMINFO(conn, NULL, basepath, mem_ctx,
				    &num_streams, &streams);

	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
		SET_STAT_INVALID(*pst);
		*path = result;
		return NT_STATUS_OK;
	}

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status)));
		goto fail;
	}

	for (i=0; i<num_streams; i++) {
		DEBUG(10, ("comparing [%s] and [%s]: ",
			   streamname, streams[i].name));
		if (fname_equal(streamname, streams[i].name,
				conn->case_sensitive)) {
			DEBUGADD(10, ("equal\n"));
			break;
		}
		DEBUGADD(10, ("not equal\n"));
	}

	if (i == num_streams) {
		SET_STAT_INVALID(*pst);
		*path = result;
		TALLOC_FREE(streams);
		return NT_STATUS_OK;
	}

	TALLOC_FREE(result);

	result = talloc_asprintf(mem_ctx, "%s%s", basepath, streams[i].name);
	if (result == NULL) {
		status = NT_STATUS_NO_MEMORY;
		goto fail;
	}

	SET_STAT_INVALID(*pst);

	if (SMB_VFS_STAT(conn, result, pst) == 0) {
		stat_cache_add(orig_path, result, conn->case_sensitive);
	}

	*path = result;
	TALLOC_FREE(streams);
	return NT_STATUS_OK;

 fail:
	TALLOC_FREE(result);
	TALLOC_FREE(streams);
	return status;
}