1
0
mirror of https://github.com/samba-team/samba.git synced 2025-01-03 01:18:10 +03:00

Compare commits

...

52 Commits

Author SHA1 Message Date
Volker Lendecke
c7839facdb smbd: Remove non_widelink_open()
Better look at the final code, not at the patch. The idea is to call
filename_convert_dirfsp() from fd_openat() and just have one place to
follow symlinks.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>

Autobuild-User(master): Ralph Böhme <slow@samba.org>
Autobuild-Date(master): Tue Nov 12 19:21:11 UTC 2024 on atb-devel-224
2024-11-12 19:21:11 +00:00
Volker Lendecke
31eac22e08 smbd: simplify openat_pathref_fullname()
We don't have to deal with stream opens anymore.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
9a80e4e27a smbd: simplify open_stream_pathref_fsp()
Looks more complex, but we don't have to go through all of
fd_openat()/non_widelink_open() for opening streams. SMB_VFS_OPENAT
knows how to deal with this.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
0bb35e2461 pysmbd: Python code calls smbd code with "." and ".."
Soon we will call filename_convert_dirfsp() on these, which can't deal
with paths that are invalid by containing . and .. as path components.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
800363a2cd smbd: Simplify filename_convert_dirfsp_nosymlink()
Looks more complex, but this avoids calling openat_pathref_fsp, which
eventually calls into non_widelink_open(). We need to open the pretty paranoid
SMB_ASSERT in openat_pathref_fsp_lcomp() a little bit.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
5052be5162 net: filename_convert_dirfsp() needs mangling initialized
We'll call filename_convert_dirfsp() from a lot more places soon.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
56e3a8e3f8 smbd: Add open_rootdir_pathref_fsp()
Get a pathref handle on the file system root. This will serve as
"basedir" for filename_convert_dirfsp_rel() to turn an absolute path
into one relative to the handle created here.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
0fc8d8bfc5 smbd: Factor out filename_convert_dirfsp_rel()
Soon we'll have a caller that needs the last component as a relative
file name. Make sure it does not have to call get_lcomp or so.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
99fa20b418 smbd: Fix following symlinks if basedir != cwd_fsp
Unused so far, but soon we'll call this routine with a basedir that's
somewhere below the share root.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
82fd2230a8 smbd: Slightly simplify filename_convert_dirfsp_nosymlink()
Reference conn->cwd_fsp just once, shrinks next patches

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
88abb775dc smbd: Use OpenDir_from_pathref() in rmdir_internals()
Make strace look nicer

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
10512eebec smbd: Use OpenDir_from_pathref() in can_delete_directory_fsp()
This avoids a full path traversal if /proc/self/fd is available.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
c0bbeded93 smbd: Simplify OpenDir_from_pathref()
Use the /proc/self/fd trick to make get_real_filename_fullscan_at look
a bit nicer and faster in strace. Direct SMB_VFS_OPENAT also is
cheaper in user space, we don't need the full fd_openat and
non_widelink_open magic here.

Also avoid opening ".", which can fail where a full path open would
succeed: If the directory in question does not give "x" perms to the
user, we get a handle on the dir as such but can't cd into it.

I haven't seen real-world cases of this, but one of our tests creates
such a scenario. I have further refactoring in my local tree that make
this patch necessary.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
9550f4370e smbd: Enable fd_openat(cwd_fsp, "/absolute/share/path")
So far fd_openat needed to be called with cwd_fsp and "." if you
wanted to open the share root, this enables using the absolute share
path. The next patch will remove sending the "." with cwd_fsp as a
simplification. Enable that with this little change.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
e571da800f smbd: Tighten non_wide_link_open() for absolute root share open
Make it clear that non_widelink_open being called for absolute paths
is not done during regular operations, i.e. when we have passed our
pathnames through filename_convert_dirfsp and we work on a real
dirfsp.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
88f582d3ca smbd: Ignore twrp in chdir_below_conn()
We can't deal with snapdir paths in non_widelink_open fully with
snapdirseverywhere active: There is no way for
shadow_copy2_parent_pathname() to work when a snapshot directory is
below the directory that we want to calculate the parent for. What is
the parent directory supposed to point at? I don't know.

For me the only way out is to accept that we should ignore what
happens behind shadow_copy2's path manipulation in core
smbd. This *might* open symlink races, but the whole point of
snapshots is that they are r/o copies of the real active file system
and as such they should be immune to those races.

Found while trying to refactor code around fd_openat()

P.S: This code will go away pretty soon

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
bd30c9c128 smbd: Simplify filename_convert_dirfsp()
If we do the S_ISLNK check in the lower level, the if-condition is
simpler and we get the close_file_free() call for free.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
3ab6a9a9bf smbd: Inline dup_file_fsp() into fcb_or_dos_open()
Only used once, an not really complex

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 18:07:33 +00:00
Volker Lendecke
6e9c6dd6d6 vfs: Don't ever call openat(-1, ...) for relative paths
This is always a bug, we should never do this. In one iteration of my
code I was doing this, which led to an invalid fallback code, which
itself lead to an infinite recursion. Make this more obvious with an
assert.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>

Autobuild-User(master): Ralph Böhme <slow@samba.org>
Autobuild-Date(master): Tue Nov 12 15:13:03 UTC 2024 on atb-devel-224
2024-11-12 15:13:03 +00:00
Volker Lendecke
dade2981c3 vfs: Only call openat for valid params in fake_acls_stat
openat(-1, "relative path", ..) is invalid. I've tried to also tighten
this down to just relative paths (i.e. base_name[0] != '/'), but
non_widelink_open makes modifications further down that make this more
difficult.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 13:44:32 +00:00
Volker Lendecke
142a78eb24 vfs: Use the getwd-cache only if we have a valid tcon
A valid tcon will have changed fsp_get_pathref_fd() to AT_FDCWD, -100
on Linux.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 13:44:32 +00:00
Volker Lendecke
c31e7aecba vfs: Change the condition when to fill the getwd cache
The next patch will add another excluding condition, this change
keeps the if-condition that is changed here simple.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 13:44:32 +00:00
Volker Lendecke
0ab88a1fe7 smbd: Don't print cwd before tcon is done
vfs_GetWd depends upon a current tcon in fake_acls, otherwise it will
call openat with an invalid dirfd on a relative pathname.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 13:44:32 +00:00
Volker Lendecke
f8994bc289 smbd: Fix an error resource leak in OpenDir_from_pathref()
We have to undo the fsp allocation and open we've done. Not noticed,
it's probably highly unlikely OpenDir_fsp() fails.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>

Autobuild-User(master): Ralph Böhme <slow@samba.org>
Autobuild-Date(master): Tue Nov 12 13:26:10 UTC 2024 on atb-devel-224
2024-11-12 13:26:10 +00:00
Volker Lendecke
01f15d0e5e libsmb: Use SMB2_0_INFO_FILE instead of a simple "1"
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
48464c66f8 smbd: Simplify smbd_smb2_query_directory_send()
Use reopen_from_fsp(), this will use the /proc/self/fd/<fd> trick if
available, no need to go through non_widelink_open

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
774005be76 smbd: reopen_from_fsp also works for full fsps
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
3b38639330 smbd: Make reopen_from_fsp() public
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
45f50eee06 vfs: Fix streams_xattr_openat
This emulates openat, and trying to open a non-existing file should
result in ENOENT and not ENOATTR

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
ea597019aa vfs: Simplify streams_xattr_openat()
Don't go via NTSTATUS in error handling

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
bea01e845c vfs: Convert streams_xattr_get_name() to return 0/errno
This function is pretty simple, this avoids a few calls to
map_errno_from_nt_status in the callers

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
7430831f88 smbd: Convert get_ea_value_fsp() to return 0/errno
Avoid a map_errno_from_nt_status()

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
eecdd0fb59 smbd: Convert refuse_symlink_fsp() to bool
I want to simplify get_ea_value_fsp next

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
4b3b283b1f smbd: Simplify make_connection_snum()
Avoid nested if's, don't check for ISDIR twice

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
47c8d9b62a pylibsmb: Add NFS reparse tag types
To be used in tests later

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
3dc89edf9c libsmb: Fix a "cast increases required alignment" warning
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
6c8d817f00 libsmb: Fix trailing whitespace
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
4f727b919a lsasrv: Simplify dcesrv_lsa_AddRemoveAccountRights()
Use dom_sid_string_buf, no need to talloc.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
7c4d1f9de1 lib: Simplify nybble_to_hex_*
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
542cf01bfe ldb: User hexchars_upper from replace.h
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
fd5562bee7 libreplace: Introduce hexchars_{upper|lower}
We use that in quite a few places in our code.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
72ff0312d1 libcli: Convert an int to a size_t
More appropriate for an array length

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
83582d417c lib: Modernize a DEBUG
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
83bb0c4ae6 idl: Fix trailing whitespace
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:35 +00:00
Volker Lendecke
804568a1d7 lib: simplify smbpasswd_sethexpwd() with hex_encode_buf()
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:34 +00:00
Volker Lendecke
282a5778fb lib: simplify smbpasswd_gethexpwd() with strhex_to_str()
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:34 +00:00
Volker Lendecke
3a5068f294 libcli: Try to fix CID 1609583 Overflowed constant
Coverity does not like the --i

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:34 +00:00
Volker Lendecke
8a64775334 vfs_fruit: Align a few integer types
Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:34 +00:00
Volker Lendecke
63f0b59cbe vfs_fruit: Simplify filter_empty_rsrc_stream()
Inspired by Coverity finding CID 1609584 Overflowed constant -- not
sure it fixes it.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:34 +00:00
Volker Lendecke
ccb6e6634a libndr: Early overflow detection
This is an addition without an overflow check. Do it right there.

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:34 +00:00
Volker Lendecke
5d19591e75 libndr: Simplify data flow in ndr_push_relative_ptr2
Consolidate saving/replacing ndr->offset right around the push_uint32

Signed-off-by: Volker Lendecke <vl@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
2024-11-12 12:09:34 +00:00
Douglas Bagnall
b80afa1ca0 libgpo:admx:: s/the the\b/the/
Signed-off-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
Reviewed-by: Volker Lendecke <vl@samba.org>

Autobuild-User(master): Volker Lendecke <vl@samba.org>
Autobuild-Date(master): Tue Nov 12 09:21:53 UTC 2024 on atb-devel-224
2024-11-12 09:21:53 +00:00
40 changed files with 695 additions and 906 deletions

View File

@ -232,11 +232,10 @@ static int ldb_dn_escape_internal(char *dst, const char *src, int len)
case '\0': {
/* any others get \XX form */
unsigned char v;
const char *hexbytes = "0123456789ABCDEF";
v = (const unsigned char)c;
*d++ = '\\';
*d++ = hexbytes[v>>4];
*d++ = hexbytes[v&0xF];
*d++ = hexchars_upper[v>>4];
*d++ = hexchars_upper[v&0xF];
break;
}
default:

View File

@ -131,8 +131,6 @@ inet_pton6(src, dst)
const char *src;
unsigned char *dst;
{
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
const char *xdigits, *curtok;
int ch, saw_xdigit;
@ -151,8 +149,8 @@ inet_pton6(src, dst)
while ((ch = *src++) != '\0') {
const char *pch;
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
pch = strchr((xdigits = xdigits_u), ch);
if ((pch = strchr((xdigits = hexchars_lower), ch)) == NULL)
pch = strchr((xdigits = hexchars_upper), ch);
if (pch != NULL) {
val <<= 4;
val |= (pch - xdigits);

View File

@ -1231,3 +1231,6 @@ int rep_renameat2(int __oldfd, const char *__old, int __newfd,
return renameat(__oldfd, __old, __newfd, __new);
}
#endif /* ! HAVE_RENAMEAT2 */
const char hexchars_lower[] = "0123456789abcdef";
const char hexchars_upper[] = "0123456789ABCDEF";

View File

@ -1101,6 +1101,9 @@ static inline bool hex_byte(const char *in, uint8_t *out)
return ok;
}
extern const char hexchars_lower[];
extern const char hexchars_upper[];
/* Needed for Solaris atomic_add_XX functions. */
#if defined(HAVE_SYS_ATOMIC_H)
#include <sys/atomic.h>

View File

@ -832,9 +832,8 @@ static void fmtint(char *buffer, size_t *currlen, size_t maxlen,
if (flags & DP_F_UP) caps = 1; /* Should characters be upper case? */
do {
convert[place++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")
[uvalue % (unsigned)base ];
convert[place++] = (caps ? hex_upper
: hex_lower)[uvalue % (unsigned)base];
uvalue = (uvalue / (unsigned)base );
} while(uvalue && (place < sizeof(convert)));
if (place == sizeof(convert)) place--;
@ -1028,8 +1027,8 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
idx = (int) ((temp -intpart +0.05)* 10.0);
/* idx = (int) (((double)(temp*0.1) -intpart +0.05) *10.0); */
/* printf ("%llf, %f, %x\n", temp, intpart, idx); */
iconvert[iplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
iconvert[iplace++] = (caps ? hexchars_upper
: hexchars_lower)[idx];
} while (intpart && (iplace < 311));
if (iplace == 311) iplace--;
iconvert[iplace] = 0;
@ -1043,8 +1042,8 @@ static void fmtfp (char *buffer, size_t *currlen, size_t maxlen,
idx = (int) ((temp -fracpart +0.05)* 10.0);
/* idx = (int) ((((temp/10) -fracpart) +0.05) *10); */
/* printf ("%lf, %lf, %ld\n", temp, fracpart, idx ); */
fconvert[fplace++] =
(caps? "0123456789ABCDEF":"0123456789abcdef")[idx];
fconvert[fplace++] = (caps ? hexchars_upper
: hexchars_lower)[idx];
} while(fracpart && (fplace < 311));
if (fplace == 311) fplace--;
}

View File

@ -652,54 +652,12 @@ void samba_tevent_set_debug(struct tevent_context *ev, const char *name);
static inline char nybble_to_hex_lower(uint8_t val)
{
uint8_t nybble = val & 0xf;
switch (nybble) {
case 0x0: case 0x1: case 0x2: case 0x3: case 0x4:
case 0x5: case 0x6: case 0x7: case 0x8: case 0x9:
return '0' + nybble;
case 0xa:
return 'a';
case 0xb:
return 'b';
case 0xc:
return 'c';
case 0xd:
return 'd';
case 0xe:
return 'e';
case 0xf:
return 'f';
}
/* unreachable */
return '\0';
return hexchars_lower[val & 0xf];
}
static inline char nybble_to_hex_upper(uint8_t val)
{
uint8_t nybble = val & 0xf;
switch (nybble) {
case 0x0: case 0x1: case 0x2: case 0x3: case 0x4:
case 0x5: case 0x6: case 0x7: case 0x8: case 0x9:
return '0' + nybble;
case 0xa:
return 'A';
case 0xb:
return 'B';
case 0xc:
return 'C';
case 0xd:
return 'D';
case 0xe:
return 'E';
case 0xf:
return 'F';
}
/* unreachable */
return '\0';
return hexchars_upper[val & 0xf];
}
#endif /* _SAMBA_UTIL_H_ */

View File

@ -34,7 +34,7 @@
struct security_acl *make_sec_acl(
TALLOC_CTX *ctx,
enum security_acl_revision revision,
int num_aces,
size_t num_aces,
const struct security_ace *ace_list)
{
struct security_acl *dst;

View File

@ -26,7 +26,7 @@
struct security_acl *make_sec_acl(
TALLOC_CTX *ctx,
enum security_acl_revision revision,
int num_aces,
size_t num_aces,
const struct security_ace *ace_list);
#endif /*_SECACL_H_*/

View File

@ -399,7 +399,10 @@ static NTSTATUS security_descriptor_acl_del(struct security_descriptor *sd,
}
/* there can be multiple ace's for one trustee */
for (i=0;i<acl->num_aces;i++) {
i = 0;
while (i<acl->num_aces) {
if (dom_sid_equal(trustee, &acl->aces[i].trustee)) {
ARRAY_DEL_ELEMENT(acl->aces, i, acl->num_aces);
acl->num_aces--;
@ -407,7 +410,8 @@ static NTSTATUS security_descriptor_acl_del(struct security_descriptor *sd,
acl->aces = NULL;
}
found = true;
--i;
} else {
i += 1;
}
}

View File

@ -70,7 +70,7 @@ Example: MYNAME</string>
<string id="POL_3B93FDE1_6461_572C_AD2E_6AEEAE4EA949_Help">This sets the NetBIOS scope that Samba will operate under. This should not be set unless every machine on your LAN also sets this value.</string>
<string id="POL_E633B0BE_9CF3_5D79_A9F1_CB782C82A19C">prefork backoff increment</string>
<string id="POL_E633B0BE_9CF3_5D79_A9F1_CB782C82A19C_Help">This option specifies the number of seconds added to the delay before a prefork master or worker process is restarted. The restart is initially zero, the prefork backoff increment is added to the delay on each restart up to the value specified by &quot;prefork maximum backoff&quot;.
Additionally the the backoff for an individual service by using &quot;prefork backoff increment: service name&quot; i.e. &quot;prefork backoff increment:ldap = 2&quot; to set the backoff increment to 2.
Additionally the backoff for an individual service by using &quot;prefork backoff increment: service name&quot; i.e. &quot;prefork backoff increment:ldap = 2&quot; to set the backoff increment to 2.
If the backoff increment is 2 and the maximum backoff is 5. There will be a zero second delay for the first restart. A two second delay for the second restart. A four second delay for the third and any subsequent restarts</string>
<string id="POL_B4E848BD_E606_552C_8C9F_3F8CC1AEF191">prefork children</string>
<string id="POL_B4E848BD_E606_552C_8C9F_3F8CC1AEF191_Help">This option controls the number of worker processes that are started for each service when prefork process model is enabled (see samba 8 -M) The prefork children are only started for those services that support prefork (currently ldap, kdc and netlogon). For processes that don't support preforking all requests are handled by a single process for that service.

View File

@ -1726,19 +1726,23 @@ static enum ndr_err_code ndr_push_relative_ptr2(struct ndr_push *ndr, const void
if (p == NULL) {
return NDR_ERR_SUCCESS;
}
save_offset = ndr->offset;
if (ndr->offset < ndr->relative_base_offset) {
return ndr_push_error(
ndr,
NDR_ERR_BUFSIZE,
"ndr_push_relative_ptr2 ndr->offset(%" PRIu32 ") "
"< ndr->relative_base_offset(%" PRIu32 ")",
ndr->offset,
ndr->relative_base_offset);
}
NDR_CHECK(ndr_token_retrieve(&ndr->relative_list, p, &ptr_offset));
if (ptr_offset > ndr->offset) {
return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
"ndr_push_relative_ptr2 ptr_offset(%"PRIu32") > ndr->offset(%"PRIu32")",
ptr_offset, ndr->offset);
}
save_offset = ndr->offset;
ndr->offset = ptr_offset;
if (save_offset < ndr->relative_base_offset) {
return ndr_push_error(ndr, NDR_ERR_BUFSIZE,
"ndr_push_relative_ptr2 save_offset(%"PRIu32") < ndr->relative_base_offset(%"PRIu32")",
save_offset, ndr->relative_base_offset);
}
NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, save_offset - ndr->relative_base_offset));
ndr->offset = save_offset;
return NDR_ERR_SUCCESS;
@ -2014,6 +2018,14 @@ _PUBLIC_ enum ndr_err_code ndr_pull_relative_ptr1(struct ndr_pull *ndr, const vo
{
enum ndr_err_code ret;
rel_offset += ndr->relative_base_offset;
if (rel_offset < ndr->relative_base_offset) {
return ndr_pull_error(ndr,
NDR_ERR_INVALID_POINTER,
"Overflow rel_offset=%" PRIu32 " + "
"relative_base_offset=%" PRIu32,
rel_offset,
ndr->relative_base_offset);
}
if (rel_offset > ndr->data_size) {
return ndr_pull_error(ndr, NDR_ERR_BUFSIZE,
"ndr_pull_relative_ptr1 rel_offset(%"PRIu32") > ndr->data_size(%"PRIu32")",

View File

@ -713,6 +713,15 @@ NTSTATUS safe_symlink_target_path(TALLOC_CTX *mem_ctx,
const char *target,
size_t unparsed,
char **_relative);
NTSTATUS filename_convert_dirfsp_rel(TALLOC_CTX *mem_ctx,
connection_struct *conn,
struct files_struct *basedir,
const char *name_in,
uint32_t ucf_flags,
NTTIME twrp,
struct files_struct **_dirfsp,
struct smb_filename **_smb_fname,
struct smb_filename **_smb_fname_rel);
NTSTATUS filename_convert_dirfsp(
TALLOC_CTX *ctx,
connection_struct *conn,

View File

@ -83,12 +83,17 @@ static int tdb_validate_child(struct tdb_context *tdb,
ret = 0; /* Cache is good. */
out:
DEBUG(10, ("tdb_validate_child: summary of validation status:\n"));
DEBUGADD(10,(" * tdb error: %s\n", v_status.tdb_error ? "yes" : "no"));
DEBUGADD(10,(" * bad freelist: %s\n",v_status.bad_freelist?"yes":"no"));
DEBUGADD(10,(" * bad entry: %s\n", v_status.bad_entry ? "yes" : "no"));
DEBUGADD(10,(" * unknown key: %s\n", v_status.unknown_key?"yes":"no"));
DEBUGADD(10,(" => overall success: %s\n", v_status.success?"yes":"no"));
DBG_DEBUG("summary of validation status:\n"
" * tdb error: %s\n"
" * bad freelist: %s\n"
" * bad entry: %s\n"
" * unknown key: %s\n"
" => overall success: %s\n",
v_status.tdb_error ? "yes" : "no",
v_status.bad_freelist ? "yes" : "no",
v_status.bad_entry ? "yes" : "no",
v_status.unknown_key ? "yes" : "no",
v_status.success ? "yes" : "no");
return ret;
}

View File

@ -2251,7 +2251,7 @@ static void cli_smb2_qpathinfo_opened(struct tevent_req *subreq)
state->ev,
state->cli,
state->fnum,
1, /* in_info_type */
SMB2_0_INFO_FILE,
state->level,
state->max_rdata,
NULL, /* in_input_buffer */

View File

@ -6648,7 +6648,7 @@ NTSTATUS cli_posix_rmdir(struct cli_state *cli, const char *fname)
struct cli_notify_state {
struct tevent_req *subreq;
uint8_t setup[8];
uint16_t setup[4];
uint32_t num_changes;
struct notify_change *changes;
};

View File

@ -3169,6 +3169,12 @@ MODULE_INIT_FUNC(libsmb_samba_cwrapper)
ADD_FLAGS(IO_REPARSE_TAG_DFS);
ADD_FLAGS(IO_REPARSE_TAG_NFS);
ADD_FLAGS(NFS_SPECFILE_LNK);
ADD_FLAGS(NFS_SPECFILE_CHR);
ADD_FLAGS(NFS_SPECFILE_BLK);
ADD_FLAGS(NFS_SPECFILE_FIFO);
ADD_FLAGS(NFS_SPECFILE_SOCK);
ADD_FLAGS(FSCC_FILE_DIRECTORY_INFORMATION);
ADD_FLAGS(FSCC_FILE_FULL_DIRECTORY_INFORMATION);
ADD_FLAGS(FSCC_FILE_BOTH_DIRECTORY_INFORMATION);

View File

@ -607,6 +607,7 @@ static int vfswrap_openat(vfs_handle_struct *handle,
files_struct *fsp,
const struct vfs_open_how *how)
{
int dirfd = fsp_get_pathref_fd(dirfsp);
int flags = how->flags;
mode_t mode = how->mode;
bool have_opath = false;
@ -615,6 +616,8 @@ static int vfswrap_openat(vfs_handle_struct *handle,
START_PROFILE(syscall_openat);
SMB_ASSERT((dirfd != -1) || (smb_fname->base_name[0] == '/'));
if (how->resolve & ~(VFS_OPEN_HOW_RESOLVE_NO_SYMLINKS |
VFS_OPEN_HOW_WITH_BACKUP_INTENT)) {
errno = ENOSYS;
@ -656,7 +659,7 @@ static int vfswrap_openat(vfs_handle_struct *handle,
.resolve = RESOLVE_NO_SYMLINKS,
};
result = openat2(fsp_get_pathref_fd(dirfsp),
result = openat2(dirfd,
smb_fname->base_name,
&linux_how,
sizeof(linux_how));
@ -683,7 +686,7 @@ static int vfswrap_openat(vfs_handle_struct *handle,
became_root = true;
}
result = openat(fsp_get_pathref_fd(dirfsp),
result = openat(dirfd,
smb_fname->base_name,
flags,
mode);

View File

@ -126,12 +126,20 @@ static int fake_acls_stat(vfs_handle_struct *handle,
return -1;
}
if (fsp_get_pathref_fd(handle->conn->cwd_fsp) == -1) {
/*
* No tcon around, fail as if we don't have
* the EAs
*/
status = NT_STATUS_INVALID_HANDLE;
} else {
/* Recursion guard. */
prd->calling_pathref_fsp = true;
status = openat_pathref_fsp(handle->conn->cwd_fsp,
smb_fname_cp);
/* End recursion guard. */
prd->calling_pathref_fsp = false;
}
if (!NT_STATUS_IS_OK(status)) {
/*

View File

@ -413,34 +413,22 @@ static bool add_fruit_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
return true;
}
static bool filter_empty_rsrc_stream(unsigned int *num_streams,
static void filter_empty_rsrc_stream(unsigned int *num_streams,
struct stream_struct **streams)
{
struct stream_struct *tmp = *streams;
unsigned int i;
if (*num_streams == 0) {
return true;
}
for (i = 0; i < *num_streams; i++) {
if (strequal_m(tmp[i].name, AFPRESOURCE_STREAM)) {
break;
}
}
struct stream_struct *s = &(*streams)[i];
if (i == *num_streams) {
return true;
}
if (tmp[i].size > 0) {
return true;
}
TALLOC_FREE(tmp[i].name);
ARRAY_DEL_ELEMENT(tmp, i, *num_streams);
if (strequal_m(s->name, AFPRESOURCE_STREAM) &&
(s->size == 0)) {
TALLOC_FREE(s->name);
ARRAY_DEL_ELEMENT(streams, i, *num_streams);
*num_streams -= 1;
return true;
return;
}
}
}
static bool del_fruit_stream(TALLOC_CTX *mem_ctx, unsigned int *num_streams,
@ -3745,8 +3733,7 @@ static NTSTATUS fruit_streaminfo_meta_stream(
struct stream_struct **pstreams)
{
struct stream_struct *stream = *pstreams;
unsigned int num_streams = *pnum_streams;
int i;
unsigned int i, num_streams = *pnum_streams;
for (i = 0; i < num_streams; i++) {
if (strequal_m(stream[i].name, AFPINFO_STREAM)) {
@ -3783,10 +3770,9 @@ static NTSTATUS fruit_streaminfo_meta_netatalk(
struct stream_struct **pstreams)
{
struct stream_struct *stream = *pstreams;
unsigned int num_streams = *pnum_streams;
unsigned int i, num_streams = *pnum_streams;
struct adouble *ad = NULL;
bool is_fi_empty;
int i;
bool ok;
/* Remove the Netatalk xattr from the list */
@ -3880,13 +3866,7 @@ static NTSTATUS fruit_streaminfo_rsrc_stream(
unsigned int *pnum_streams,
struct stream_struct **pstreams)
{
bool ok;
ok = filter_empty_rsrc_stream(pnum_streams, pstreams);
if (!ok) {
DBG_ERR("Filtering resource stream failed\n");
return NT_STATUS_INTERNAL_ERROR;
}
filter_empty_rsrc_stream(pnum_streams, pstreams);
return NT_STATUS_OK;
}
@ -3898,13 +3878,7 @@ static NTSTATUS fruit_streaminfo_rsrc_xattr(
unsigned int *pnum_streams,
struct stream_struct **pstreams)
{
bool ok;
ok = filter_empty_rsrc_stream(pnum_streams, pstreams);
if (!ok) {
DBG_ERR("Filtering resource stream failed\n");
return NT_STATUS_INTERNAL_ERROR;
}
filter_empty_rsrc_stream(pnum_streams, pstreams);
return NT_STATUS_OK;
}
@ -3917,11 +3891,10 @@ static NTSTATUS fruit_streaminfo_rsrc_adouble(
struct stream_struct **pstreams)
{
struct stream_struct *stream = *pstreams;
unsigned int num_streams = *pnum_streams;
unsigned int i, num_streams = *pnum_streams;
struct adouble *ad = NULL;
bool ok;
size_t rlen;
int i;
/*
* Check if there's a AFPRESOURCE_STREAM from the VFS streams backend

View File

@ -48,15 +48,12 @@ struct stream_io {
static ssize_t get_xattr_size_fsp(struct files_struct *fsp,
const char *xattr_name)
{
NTSTATUS status;
int ret;
struct ea_struct ea;
ssize_t result;
status = get_ea_value_fsp(talloc_tos(),
fsp,
xattr_name,
&ea);
if (!NT_STATUS_IS_OK(status)) {
ret = get_ea_value_fsp(talloc_tos(), fsp, xattr_name, &ea);
if (ret != 0) {
return -1;
}
@ -69,7 +66,7 @@ static ssize_t get_xattr_size_fsp(struct files_struct *fsp,
* Given a stream name, populate xattr_name with the xattr name to use for
* accessing the stream.
*/
static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle,
static int streams_xattr_get_name(vfs_handle_struct *handle,
TALLOC_CTX *ctx,
const char *stream_name,
char **xattr_name)
@ -78,8 +75,10 @@ static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle,
char *stype;
struct streams_xattr_config *config;
SMB_VFS_HANDLE_GET_DATA(handle, config, struct streams_xattr_config,
return NT_STATUS_UNSUCCESSFUL);
SMB_VFS_HANDLE_GET_DATA(handle,
config,
struct streams_xattr_config,
return EACCES);
SMB_ASSERT(stream_name[0] == ':');
stream_name += 1;
@ -105,7 +104,7 @@ static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle,
* We only support one stream type: "$DATA"
*/
if (strcasecmp_m(stype, ":$DATA") != 0) {
return NT_STATUS_INVALID_PARAMETER;
return EINVAL;
}
/* Split name and type */
@ -118,18 +117,18 @@ static NTSTATUS streams_xattr_get_name(vfs_handle_struct *handle,
stream_name,
config->store_stream_type ? ":$DATA" : "");
if (*xattr_name == NULL) {
return NT_STATUS_NO_MEMORY;
return ENOMEM;
}
DEBUG(10, ("xattr_name: %s, stream_name: %s\n", *xattr_name,
stream_name));
return NT_STATUS_OK;
return 0;
}
static bool streams_xattr_recheck(struct stream_io *sio)
{
NTSTATUS status;
int ret;
char *xattr_name = NULL;
if (sio->fsp->fsp_name == sio->fsp_name_ptr) {
@ -142,10 +141,11 @@ static bool streams_xattr_recheck(struct stream_io *sio)
return false;
}
status = streams_xattr_get_name(sio->handle, talloc_tos(),
ret = streams_xattr_get_name(sio->handle,
talloc_tos(),
sio->fsp->fsp_name->stream_name,
&xattr_name);
if (!NT_STATUS_IS_OK(status)) {
if (ret != 0) {
return false;
}
@ -215,6 +215,7 @@ static int streams_xattr_stat(vfs_handle_struct *handle,
struct smb_filename *smb_fname)
{
NTSTATUS status;
int ret;
int result = -1;
char *xattr_name = NULL;
char *tmp_stream_name = NULL;
@ -241,10 +242,12 @@ static int streams_xattr_stat(vfs_handle_struct *handle,
}
/* Derive the xattr name to lookup. */
status = streams_xattr_get_name(handle, talloc_tos(),
smb_fname->stream_name, &xattr_name);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
ret = streams_xattr_get_name(handle,
talloc_tos(),
smb_fname->stream_name,
&xattr_name);
if (ret != 0) {
errno = ret;
return -1;
}
@ -313,7 +316,6 @@ static int streams_xattr_openat(struct vfs_handle_struct *handle,
files_struct *fsp,
const struct vfs_open_how *how)
{
NTSTATUS status;
struct streams_xattr_config *config = NULL;
struct stream_io *sio = NULL;
struct ea_struct ea;
@ -345,22 +347,20 @@ static int streams_xattr_openat(struct vfs_handle_struct *handle,
SMB_ASSERT(fsp_is_alternate_stream(fsp));
SMB_ASSERT(dirfsp == NULL);
status = streams_xattr_get_name(handle, talloc_tos(),
smb_fname->stream_name, &xattr_name);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
ret = streams_xattr_get_name(handle,
talloc_tos(),
smb_fname->stream_name,
&xattr_name);
if (ret != 0) {
errno = ret;
goto fail;
}
status = get_ea_value_fsp(talloc_tos(),
fsp->base_fsp,
xattr_name,
&ea);
ret = get_ea_value_fsp(talloc_tos(), fsp->base_fsp, xattr_name, &ea);
if (ret != 0) {
DBG_DEBUG("get_ea_value_fsp returned %s\n", strerror(ret));
DBG_DEBUG("get_ea_value_fsp returned %s\n", nt_errstr(status));
if (!NT_STATUS_IS_OK(status)) {
if (!NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
if (ret != ENOATTR) {
/*
* The base file is not there. This is an error even if
* we got O_CREAT, the higher levels should have created
@ -373,7 +373,7 @@ static int streams_xattr_openat(struct vfs_handle_struct *handle,
}
if (!(how->flags & O_CREAT)) {
errno = ENOATTR;
errno = ENOENT;
goto fail;
}
@ -492,10 +492,12 @@ static int streams_xattr_unlinkat(vfs_handle_struct *handle,
/* A stream can never be rmdir'ed */
SMB_ASSERT((flags & AT_REMOVEDIR) == 0);
status = streams_xattr_get_name(handle, talloc_tos(),
smb_fname->stream_name, &xattr_name);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
ret = streams_xattr_get_name(handle,
talloc_tos(),
smb_fname->stream_name,
&xattr_name);
if (ret != 0) {
errno = ret;
goto fail;
}
@ -584,18 +586,20 @@ static int streams_xattr_renameat(vfs_handle_struct *handle,
}
/* Get the xattr names. */
status = streams_xattr_get_name(handle, talloc_tos(),
ret = streams_xattr_get_name(handle,
talloc_tos(),
smb_fname_src->stream_name,
&src_xattr_name);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
if (ret != 0) {
errno = ret;
goto fail;
}
status = streams_xattr_get_name(handle, talloc_tos(),
ret = streams_xattr_get_name(handle,
talloc_tos(),
smb_fname_dst->stream_name,
&dst_xattr_name);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
if (ret != 0) {
errno = ret;
goto fail;
}
@ -629,12 +633,12 @@ static int streams_xattr_renameat(vfs_handle_struct *handle,
}
/* Read the old stream from the base file fsp. */
status = get_ea_value_fsp(talloc_tos(),
ret = get_ea_value_fsp(talloc_tos(),
pathref_src->fsp,
src_xattr_name,
&ea);
if (!NT_STATUS_IS_OK(status)) {
errno = map_errno_from_nt_status(status);
if (ret != 0) {
errno = ret;
goto fail;
}
@ -716,6 +720,7 @@ static NTSTATUS walk_xattr_streams(vfs_handle_struct *handle,
for (i=0; i<num_names; i++) {
struct ea_struct ea;
int ret;
/*
* We want to check with samba_private_attr_name()
@ -740,15 +745,12 @@ static NTSTATUS walk_xattr_streams(vfs_handle_struct *handle,
continue;
}
status = get_ea_value_fsp(names,
smb_fname->fsp,
names[i],
&ea);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(10, ("Could not get ea %s for file %s: %s\n",
ret = get_ea_value_fsp(names, smb_fname->fsp, names[i], &ea);
if (ret != 0) {
DBG_DEBUG("Could not get ea %s for file %s: %s\n",
names[i],
smb_fname->base_name,
nt_errstr(status)));
strerror(ret));
continue;
}
@ -922,7 +924,6 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle,
struct stream_io *sio =
(struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
struct ea_struct ea;
NTSTATUS status;
int ret;
DEBUG(10, ("streams_xattr_pwrite called for %d bytes\n", (int)n));
@ -956,11 +957,12 @@ static ssize_t streams_xattr_pwrite(vfs_handle_struct *handle,
return -1;
}
status = get_ea_value_fsp(talloc_tos(),
ret = get_ea_value_fsp(talloc_tos(),
fsp->base_fsp,
sio->xattr_name,
&ea);
if (!NT_STATUS_IS_OK(status)) {
if (ret != 0) {
errno = ret;
return -1;
}
@ -1003,7 +1005,7 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
struct stream_io *sio =
(struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
struct ea_struct ea;
NTSTATUS status;
int ret;
size_t length, overlap;
DEBUG(10, ("streams_xattr_pread: offset=%d, size=%d\n",
@ -1017,11 +1019,12 @@ static ssize_t streams_xattr_pread(vfs_handle_struct *handle,
return -1;
}
status = get_ea_value_fsp(talloc_tos(),
ret = get_ea_value_fsp(talloc_tos(),
fsp->base_fsp,
sio->xattr_name,
&ea);
if (!NT_STATUS_IS_OK(status)) {
if (ret != 0) {
errno = ret;
return -1;
}
@ -1209,7 +1212,6 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle,
int ret;
uint8_t *tmp;
struct ea_struct ea;
NTSTATUS status;
struct stream_io *sio =
(struct stream_io *)VFS_FETCH_FSP_EXTENSION(handle, fsp);
@ -1224,11 +1226,12 @@ static int streams_xattr_ftruncate(struct vfs_handle_struct *handle,
return -1;
}
status = get_ea_value_fsp(talloc_tos(),
ret = get_ea_value_fsp(talloc_tos(),
fsp->base_fsp,
sio->xattr_name,
&ea);
if (!NT_STATUS_IS_OK(status)) {
if (ret != 0) {
errno = ret;
return -1;
}

View File

@ -1183,12 +1183,7 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
* files non-visible to the client. If not, fail the delete.
*/
status = OpenDir(talloc_tos(),
conn,
smb_dname,
NULL,
0,
&dir_hnd);
status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
if (!NT_STATUS_IS_OK(status)) {
/*
* Note, we deliberately squash the error here

View File

@ -1066,17 +1066,55 @@ NTSTATUS OpenDir_from_pathref(TALLOC_CTX *mem_ctx,
uint32_t attr,
struct smb_Dir **_dir_hnd)
{
struct files_struct *fsp = NULL;
struct connection_struct *conn = dirfsp->conn;
struct files_struct *new_fsp = NULL;
struct smb_Dir *dir_hnd = NULL;
const struct vfs_open_how how = {.flags = O_RDONLY | O_DIRECTORY};
int old_fd;
NTSTATUS status;
status = openat_internal_dir_from_pathref(dirfsp, O_RDONLY, &fsp);
status = create_internal_dirfsp(conn, dirfsp->fsp_name, &new_fsp);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
status = OpenDir_fsp(mem_ctx, fsp->conn, fsp, mask, attr, &dir_hnd);
if (dirfsp->fsp_flags.have_proc_fds &&
((old_fd = fsp_get_pathref_fd(dirfsp)) != -1))
{
struct sys_proc_fd_path_buf buf;
struct smb_filename proc_fname = {
.base_name = sys_proc_fd_path(old_fd, &buf),
};
int new_fd;
new_fd = SMB_VFS_OPENAT(
conn, conn->cwd_fsp, &proc_fname, new_fsp, &how);
if (new_fd == -1) {
status = map_nt_error_from_unix(errno);
DBG_DEBUG("SMB_VFS_OPENAT(%s) returned %s\n",
proc_fname.base_name, strerror(errno));
file_free(NULL, new_fsp);
return status;
}
fsp_set_fd(new_fsp, new_fd);
} else {
status = fd_openat(conn->cwd_fsp,
dirfsp->fsp_name,
new_fsp,
&how);
if (!NT_STATUS_IS_OK(status)) {
DBG_DEBUG("fd_openat(%s) returned %s\n",
dirfsp->fsp_name->base_name,
nt_errstr(status));
file_free(NULL, new_fsp);
return status;
}
}
status = OpenDir_fsp(mem_ctx, conn, new_fsp, mask, attr, &dir_hnd);
if (!NT_STATUS_IS_OK(status)) {
fd_close(new_fsp);
file_free(NULL, new_fsp);
return status;
}
@ -1512,8 +1550,7 @@ NTSTATUS can_delete_directory_fsp(files_struct *fsp)
struct connection_struct *conn = fsp->conn;
struct smb_Dir *dir_hnd = NULL;
status = OpenDir(
talloc_tos(), conn, fsp->fsp_name, NULL, 0, &dir_hnd);
status = OpenDir_from_pathref(talloc_tos(), fsp, NULL, 0, &dir_hnd);
if (!NT_STATUS_IS_OK(status)) {
return status;
}

View File

@ -667,11 +667,13 @@ fail:
static NTSTATUS filename_convert_dirfsp_nosymlink(
TALLOC_CTX *mem_ctx,
connection_struct *conn,
struct files_struct *basedir,
const char *name_in,
uint32_t ucf_flags,
NTTIME twrp,
struct files_struct **_dirfsp,
struct smb_filename **_smb_fname,
struct smb_filename **_smb_fname_rel,
struct reparse_data_buffer **_symlink_err)
{
struct smb_filename *smb_dirname = NULL;
@ -704,7 +706,7 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
.st_ex_ctime = omit,
};
*_dirfsp = conn->cwd_fsp;
*_dirfsp = basedir;
*_smb_fname = smb_fname;
return NT_STATUS_OK;
}
@ -750,15 +752,19 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
}
if (dirname[0] == '\0') {
status = synthetic_pathref(
smb_dirname = synthetic_smb_fname(
mem_ctx,
conn->cwd_fsp,
".",
NULL,
NULL,
0,
posix ? SMB_FILENAME_POSIX_PATH : 0,
&smb_dirname);
posix ? SMB_FILENAME_POSIX_PATH : 0);
if (smb_dirname == NULL) {
return NT_STATUS_NO_MEMORY;
}
status = openat_pathref_fsp_lcomp(basedir,
smb_dirname,
UCF_POSIX_PATHNAMES);
} else {
status = normalize_filename_case(conn, dirname, ucf_flags);
if (!NT_STATUS_IS_OK(status)) {
@ -770,7 +776,7 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
status = openat_pathref_fsp_nosymlink(mem_ctx,
conn,
conn->cwd_fsp,
basedir,
dirname,
twrp,
posix,
@ -1033,12 +1039,19 @@ static NTSTATUS filename_convert_dirfsp_nosymlink(
}
done:
if (S_ISLNK(smb_fname->st.st_ex_mode) &&
!(ucf_flags & UCF_LCOMP_LNK_OK)) {
status = NT_STATUS_STOPPED_ON_SYMLINK;
*_symlink_err = symlink_err;
goto fail;
}
*_dirfsp = smb_dirname->fsp;
*_smb_fname = smb_fname;
*_symlink_err = symlink_err;
smb_fname_fsp_unlink(smb_fname_rel);
TALLOC_FREE(smb_fname_rel);
*_smb_fname_rel = smb_fname_rel;
return NT_STATUS_OK;
fail:
@ -1059,19 +1072,21 @@ fail:
return status;
}
NTSTATUS filename_convert_dirfsp(
TALLOC_CTX *mem_ctx,
NTSTATUS filename_convert_dirfsp_rel(TALLOC_CTX *mem_ctx,
connection_struct *conn,
struct files_struct *basedir,
const char *name_in,
uint32_t ucf_flags,
NTTIME twrp,
struct files_struct **_dirfsp,
struct smb_filename **_smb_fname)
struct smb_filename **_smb_fname,
struct smb_filename **_smb_fname_rel)
{
struct reparse_data_buffer *symlink_err = NULL;
struct symlink_reparse_struct *lnk = NULL;
NTSTATUS status;
char *target = NULL;
char *base_name = NULL;
char *safe_target = NULL;
size_t symlink_redirects = 0;
int ret;
@ -1083,28 +1098,20 @@ next:
status = filename_convert_dirfsp_nosymlink(mem_ctx,
conn,
basedir,
name_in,
ucf_flags,
twrp,
_dirfsp,
_smb_fname,
_smb_fname_rel,
&symlink_err);
if (NT_STATUS_IS_OK(status) && S_ISLNK((*_smb_fname)->st.st_ex_mode)) {
/*
* lcomp is a symlink
*/
if (ucf_flags & UCF_LCOMP_LNK_OK) {
TALLOC_FREE(symlink_err);
return NT_STATUS_OK;
}
close_file_free(NULL, _dirfsp, ERROR_CLOSE);
status = NT_STATUS_STOPPED_ON_SYMLINK;
}
if (!NT_STATUS_EQUAL(status, NT_STATUS_STOPPED_ON_SYMLINK)) {
return status;
}
TALLOC_FREE(*_smb_fname_rel);
lnk = &symlink_err->parsed.lnk;
/*
@ -1150,9 +1157,13 @@ next:
return map_nt_error_from_unix(ret);
}
if (basedir != conn->cwd_fsp) {
base_name = basedir->fsp_name->base_name;
}
status = safe_symlink_target_path(mem_ctx,
conn->connectpath,
NULL,
base_name,
target,
lnk->unparsed_path_length,
&safe_target);
@ -1161,12 +1172,37 @@ next:
return status;
}
name_in = safe_target;
basedir = conn->cwd_fsp;
symlink_redirects += 1;
goto next;
}
NTSTATUS filename_convert_dirfsp(TALLOC_CTX *ctx,
connection_struct *conn,
const char *name_in,
uint32_t ucf_flags,
NTTIME twrp,
struct files_struct **_dirfsp,
struct smb_filename **_smb_name)
{
struct smb_filename *smb_fname_rel = NULL;
NTSTATUS status;
status = filename_convert_dirfsp_rel(ctx,
conn,
conn->cwd_fsp,
name_in,
ucf_flags,
twrp,
_dirfsp,
_smb_name,
&smb_fname_rel);
TALLOC_FREE(smb_fname_rel);
return status;
}
char *full_path_from_dirfsp_at_basename(TALLOC_CTX *mem_ctx,
const struct files_struct *dirfsp,
const char *at_base_name)

View File

@ -286,52 +286,6 @@ NTSTATUS open_internal_dirfsp(connection_struct *conn,
return NT_STATUS_OK;
}
/*
* Convert a pathref dirfsp into a real fsp. No need to do any cwd
* tricks, we just open ".".
*/
NTSTATUS openat_internal_dir_from_pathref(
struct files_struct *dirfsp,
int _open_flags,
struct files_struct **_fsp)
{
struct connection_struct *conn = dirfsp->conn;
struct smb_filename *smb_dname = dirfsp->fsp_name;
struct files_struct *fsp = NULL;
char dot[] = ".";
struct smb_filename smb_dot = {
.base_name = dot,
.flags = smb_dname->flags,
.twrp = smb_dname->twrp,
};
struct vfs_open_how how = { .flags = _open_flags, };
NTSTATUS status;
status = create_internal_dirfsp(conn, smb_dname, &fsp);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
/*
* Pointless for opening ".", but you never know...
*/
how.flags |= O_NOFOLLOW;
status = fd_openat(dirfsp, &smb_dot, fsp, &how);
if (!NT_STATUS_IS_OK(status)) {
DBG_INFO("fd_openat(\"%s\", \".\") failed: %s\n",
fsp_str_dbg(dirfsp),
nt_errstr(status));
file_free(NULL, fsp);
return status;
}
fsp->fsp_name->st = smb_dname->st;
fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
*_fsp = fsp;
return NT_STATUS_OK;
}
/*
* The "link" in the name doesn't imply link in the filesystem
* sense. It's a object that "links" together an fsp and an smb_fname
@ -450,20 +404,16 @@ static int smb_fname_fsp_destructor(struct smb_filename *smb_fname)
static NTSTATUS openat_pathref_fullname(
struct connection_struct *conn,
const struct files_struct *dirfsp,
struct files_struct *basefsp,
struct smb_filename **full_fname,
struct smb_filename *smb_fname,
const struct vfs_open_how *how)
{
struct files_struct *fsp = NULL;
bool have_dirfsp = (dirfsp != NULL);
bool have_basefsp = (basefsp != NULL);
NTSTATUS status;
DBG_DEBUG("smb_fname [%s]\n", smb_fname_str_dbg(smb_fname));
SMB_ASSERT(smb_fname->fsp == NULL);
SMB_ASSERT(have_dirfsp != have_basefsp);
status = fsp_new(conn, conn, &fsp);
if (!NT_STATUS_IS_OK(status)) {
@ -480,7 +430,6 @@ static NTSTATUS openat_pathref_fullname(
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
fsp_set_base_fsp(fsp, basefsp);
status = fd_openat(dirfsp, smb_fname, fsp, how);
if (!NT_STATUS_IS_OK(status)) {
@ -539,7 +488,6 @@ fail:
smb_fname_str_dbg(smb_fname),
nt_errstr(status));
fsp_set_base_fsp(fsp, NULL);
fd_close(fsp);
file_free(NULL, fsp);
return status;
@ -592,7 +540,7 @@ NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
goto fail;
}
status = openat_pathref_fullname(
conn, dirfsp, NULL, &full_fname, smb_fname, &how);
conn, dirfsp, &full_fname, smb_fname, &how);
TALLOC_FREE(full_fname);
return status;
}
@ -615,7 +563,7 @@ NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
}
status = openat_pathref_fullname(
conn, dirfsp, NULL, &full_fname, base_fname, &how);
conn, dirfsp, &full_fname, base_fname, &how);
TALLOC_FREE(full_fname);
if (!NT_STATUS_IS_OK(status)) {
DBG_DEBUG("openat_pathref_fullname() failed: %s\n",
@ -636,6 +584,62 @@ fail:
return status;
}
NTSTATUS open_rootdir_pathref_fsp(connection_struct *conn,
struct files_struct **_fsp)
{
struct smb_filename slash = { .base_name = discard_const_p(char, "/") };
struct vfs_open_how how = { .flags = O_RDONLY|O_DIRECTORY, };
struct files_struct *fsp = NULL;
NTSTATUS status;
int fd;
status = fsp_new(conn, conn, &fsp);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
GetTimeOfDay(&fsp->open_time);
fsp_set_gen_id(fsp);
ZERO_STRUCT(conn->sconn->fsp_fi_cache);
fsp->fsp_flags.is_pathref = true;
status = fsp_set_smb_fname(fsp, &slash);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
fd = SMB_VFS_OPENAT(conn,
conn->cwd_fsp,
fsp->fsp_name,
fsp,
&how);
if (fd == -1) {
status = map_nt_error_from_unix(errno);
goto fail;
}
fsp_set_fd(fsp, fd);
status = vfs_stat_fsp(fsp);
if (!NT_STATUS_IS_OK(status)) {
DBG_DEBUG("vfs_stat_fsp(\"/\") failed: %s\n", nt_errstr(status));
goto close_fail;
}
fsp->fsp_flags.is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
if (!fsp->fsp_flags.is_directory) {
DBG_DEBUG("\"/\" not a directory\n");
status = NT_STATUS_UNEXPECTED_IO_ERROR;
goto close_fail;
}
fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
*_fsp = fsp;
return NT_STATUS_OK;
close_fail:
fd_close(fsp);
fail:
file_free(NULL, fsp);
return status;
}
/*
* Open a stream given an already opened base_fsp. Avoid
* non_widelink_open: This is only valid for the case where we have a
@ -646,11 +650,13 @@ NTSTATUS open_stream_pathref_fsp(
struct smb_filename *smb_fname)
{
struct files_struct *base_fsp = *_base_fsp;
struct files_struct *fsp = NULL;
connection_struct *conn = base_fsp->conn;
struct smb_filename *base_fname = base_fsp->fsp_name;
struct smb_filename *full_fname = NULL;
struct vfs_open_how how = { .flags = O_RDONLY|O_NONBLOCK, };
NTSTATUS status;
int fd;
SMB_ASSERT(smb_fname->fsp == NULL);
SMB_ASSERT(is_named_stream(smb_fname));
@ -666,9 +672,61 @@ NTSTATUS open_stream_pathref_fsp(
return NT_STATUS_NO_MEMORY;
}
status = openat_pathref_fullname(
conn, NULL, base_fsp, &full_fname, smb_fname, &how);
status = fsp_new(conn, conn, &fsp);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
GetTimeOfDay(&fsp->open_time);
fsp_set_gen_id(fsp);
ZERO_STRUCT(conn->sconn->fsp_fi_cache);
fsp->fsp_flags.is_pathref = true;
status = fsp_attach_smb_fname(fsp, &full_fname);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
fsp_set_base_fsp(fsp, base_fsp);
fd = SMB_VFS_OPENAT(conn,
NULL, /* stream open is relative to fsp->base_fsp */
smb_fname,
fsp,
&how);
if (fd == -1) {
status = map_nt_error_from_unix(errno);
goto fail;
}
fsp_set_fd(fsp, fd);
status = vfs_stat_fsp(fsp);
if (!NT_STATUS_IS_OK(status)) {
DBG_DEBUG("vfs_stat_fsp failed: %s\n", nt_errstr(status));
fd_close(fsp);
goto fail;
}
smb_fname->st = fsp->fsp_name->st;
fsp->fsp_flags.is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
status = fsp_smb_fname_link(fsp, &smb_fname->fsp_link, &smb_fname->fsp);
if (!NT_STATUS_IS_OK(status)) {
goto fail;
}
DBG_DEBUG("fsp [%s]: OK\n", fsp_str_dbg(fsp));
talloc_set_destructor(smb_fname, smb_fname_fsp_destructor);
return NT_STATUS_OK;
fail:
TALLOC_FREE(full_fname);
if (fsp != NULL) {
fsp_set_base_fsp(fsp, NULL);
fd_close(fsp);
file_free(NULL, fsp);
}
return status;
}
@ -1477,7 +1535,8 @@ NTSTATUS openat_pathref_fsp_lcomp(struct files_struct *dirfsp,
*/
SMB_ASSERT((smb_fname_rel->fsp == NULL) &&
(dirfsp != dirfsp->conn->cwd_fsp) &&
((dirfsp != dirfsp->conn->cwd_fsp) ||
ISDOT(smb_fname_rel->base_name)) &&
(strchr_m(smb_fname_rel->base_name, '/') == NULL) &&
!is_named_stream(smb_fname_rel));
@ -2412,52 +2471,6 @@ struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req,
return fsp;
}
/****************************************************************************
Duplicate the file handle part for a DOS or FCB open.
****************************************************************************/
NTSTATUS dup_file_fsp(
files_struct *from,
uint32_t access_mask,
files_struct *to)
{
size_t new_refcount;
/* this can never happen for print files */
SMB_ASSERT(from->print_file == NULL);
TALLOC_FREE(to->fh);
to->fh = from->fh;
new_refcount = fh_get_refcount(to->fh) + 1;
fh_set_refcount(to->fh, new_refcount);
to->file_id = from->file_id;
to->initial_allocation_size = from->initial_allocation_size;
to->file_pid = from->file_pid;
to->vuid = from->vuid;
to->open_time = from->open_time;
to->access_mask = access_mask;
to->oplock_type = from->oplock_type;
to->fsp_flags.can_lock = from->fsp_flags.can_lock;
to->fsp_flags.can_read = ((access_mask & FILE_READ_DATA) != 0);
to->fsp_flags.can_write =
CAN_WRITE(from->conn) &&
((access_mask & (FILE_WRITE_DATA | FILE_APPEND_DATA)) != 0);
if (from->fsp_name->twrp != 0) {
to->fsp_flags.can_write = false;
}
to->fsp_flags.modified = from->fsp_flags.modified;
to->fsp_flags.is_directory = from->fsp_flags.is_directory;
to->fsp_flags.aio_write_behind = from->fsp_flags.aio_write_behind;
to->fsp_flags.is_fsa = from->fsp_flags.is_fsa;
to->fsp_flags.is_pathref = from->fsp_flags.is_pathref;
to->fsp_flags.have_proc_fds = from->fsp_flags.have_proc_fds;
to->fsp_flags.is_dirfsp = from->fsp_flags.is_dirfsp;
return fsp_set_smb_fname(to, from->fsp_name);
}
/**
* Return a jenkins hash of a pathname on a connection.
*/

View File

@ -467,383 +467,6 @@ static NTSTATUS check_base_file_access(struct files_struct *fsp,
access_mask);
}
static NTSTATUS chdir_below_conn(
TALLOC_CTX *mem_ctx,
connection_struct *conn,
const char *connectpath,
size_t connectpath_len,
struct smb_filename *dir_fname,
struct smb_filename **_oldwd_fname)
{
struct smb_filename *oldwd_fname = NULL;
struct smb_filename *smb_fname_dot = NULL;
struct smb_filename *real_fname = NULL;
const char *relative = NULL;
NTSTATUS status;
int ret;
bool ok;
if (!ISDOT(dir_fname->base_name)) {
oldwd_fname = vfs_GetWd(talloc_tos(), conn);
if (oldwd_fname == NULL) {
status = map_nt_error_from_unix(errno);
goto out;
}
/* Pin parent directory in place. */
ret = vfs_ChDir(conn, dir_fname);
if (ret == -1) {
status = map_nt_error_from_unix(errno);
DBG_DEBUG("chdir to %s failed: %s\n",
dir_fname->base_name,
strerror(errno));
goto out;
}
}
smb_fname_dot = synthetic_smb_fname(
talloc_tos(),
".",
NULL,
NULL,
dir_fname->twrp,
dir_fname->flags);
if (smb_fname_dot == NULL) {
status = NT_STATUS_NO_MEMORY;
goto out;
}
real_fname = SMB_VFS_REALPATH(conn, talloc_tos(), smb_fname_dot);
if (real_fname == NULL) {
status = map_nt_error_from_unix(errno);
DBG_DEBUG("realpath in %s failed: %s\n",
dir_fname->base_name,
strerror(errno));
goto out;
}
TALLOC_FREE(smb_fname_dot);
ok = subdir_of(connectpath,
connectpath_len,
real_fname->base_name,
&relative);
if (ok) {
TALLOC_FREE(real_fname);
*_oldwd_fname = oldwd_fname;
return NT_STATUS_OK;
}
DBG_NOTICE("Bad access attempt: %s is a symlink "
"outside the share path\n"
"conn_rootdir =%s\n"
"resolved_name=%s\n",
dir_fname->base_name,
connectpath,
real_fname->base_name);
TALLOC_FREE(real_fname);
status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
out:
if (oldwd_fname != NULL) {
ret = vfs_ChDir(conn, oldwd_fname);
SMB_ASSERT(ret == 0);
TALLOC_FREE(oldwd_fname);
}
return status;
}
/*
* Get the symlink target of dirfsp/symlink_name, making sure the
* target is below connection_path.
*/
static NTSTATUS symlink_target_below_conn(
TALLOC_CTX *mem_ctx,
const char *connection_path,
struct files_struct *fsp,
struct files_struct *dirfsp,
struct smb_filename *symlink_name,
char **_target)
{
char *target = NULL;
char *absolute = NULL;
NTSTATUS status;
if (fsp_get_pathref_fd(fsp) != -1) {
/*
* fsp is an O_PATH open, Linux does a "freadlink"
* with an empty name argument to readlinkat
*/
status = readlink_talloc(talloc_tos(), fsp, NULL, &target);
} else {
status = readlink_talloc(
talloc_tos(), dirfsp, symlink_name, &target);
}
if (!NT_STATUS_IS_OK(status)) {
return status;
}
status = safe_symlink_target_path(talloc_tos(),
connection_path,
dirfsp->fsp_name->base_name,
target,
0,
&absolute);
if (!NT_STATUS_IS_OK(status)) {
DBG_DEBUG("safe_symlink_target_path() failed: %s\n",
nt_errstr(status));
return status;
}
if (absolute[0] == '\0') {
/*
* special case symlink to share root: "." is our
* share root filename
*/
TALLOC_FREE(absolute);
absolute = talloc_strdup(talloc_tos(), ".");
if (absolute == NULL) {
return NT_STATUS_NO_MEMORY;
}
}
*_target = absolute;
return NT_STATUS_OK;
}
/****************************************************************************
Non-widelink open.
****************************************************************************/
static NTSTATUS non_widelink_open(const struct files_struct *dirfsp,
files_struct *fsp,
struct smb_filename *smb_fname,
const struct vfs_open_how *_how)
{
struct connection_struct *conn = fsp->conn;
const char *connpath = SMB_VFS_CONNECTPATH(conn, dirfsp, smb_fname);
size_t connpath_len;
NTSTATUS status = NT_STATUS_OK;
int fd = -1;
char *orig_smb_fname_base = smb_fname->base_name;
struct smb_filename *orig_fsp_name = fsp->fsp_name;
struct smb_filename *smb_fname_rel = NULL;
struct smb_filename *oldwd_fname = NULL;
struct smb_filename *parent_dir_fname = NULL;
struct vfs_open_how how = *_how;
char *target = NULL;
size_t link_depth = 0;
int ret;
SMB_ASSERT(!fsp_is_alternate_stream(fsp));
if (connpath == NULL) {
/*
* This can happen with shadow_copy2 if the snapshot
* path is not found
*/
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
connpath_len = strlen(connpath);
again:
if (smb_fname->base_name[0] == '/') {
int cmp = strcmp(connpath, smb_fname->base_name);
if (cmp == 0) {
smb_fname->base_name = talloc_strdup(smb_fname, "");
if (smb_fname->base_name == NULL) {
status = NT_STATUS_NO_MEMORY;
goto out;
}
}
}
if (dirfsp == conn->cwd_fsp) {
status = SMB_VFS_PARENT_PATHNAME(fsp->conn,
talloc_tos(),
smb_fname,
&parent_dir_fname,
&smb_fname_rel);
if (!NT_STATUS_IS_OK(status)) {
goto out;
}
status = chdir_below_conn(
talloc_tos(),
conn,
connpath,
connpath_len,
parent_dir_fname,
&oldwd_fname);
if (!NT_STATUS_IS_OK(status)) {
goto out;
}
/* Setup fsp->fsp_name to be relative to cwd */
fsp->fsp_name = smb_fname_rel;
} else {
/*
* fsp->fsp_name is unchanged as it is already correctly
* relative to dirfsp.
*/
smb_fname_rel = smb_fname;
}
{
/*
* Assert nobody can step in with a symlink on the
* path, there is no path anymore and we'll use
* O_NOFOLLOW to open.
*/
char *slash = strchr_m(smb_fname_rel->base_name, '/');
SMB_ASSERT(slash == NULL);
}
how.flags |= O_NOFOLLOW;
fd = SMB_VFS_OPENAT(conn,
dirfsp,
smb_fname_rel,
fsp,
&how);
fsp_set_fd(fsp, fd); /* This preserves errno */
if (fd == -1) {
status = map_nt_error_from_unix(errno);
if (errno == ENOENT) {
goto out;
}
/*
* ENOENT makes it worthless retrying with a
* stat, we know for sure the file does not
* exist. For everything else we want to know
* what's there.
*/
ret = SMB_VFS_FSTATAT(
fsp->conn,
dirfsp,
smb_fname_rel,
&fsp->fsp_name->st,
AT_SYMLINK_NOFOLLOW);
if (ret == -1) {
/*
* Keep the original error. Otherwise we would
* mask for example EROFS for open(O_CREAT),
* turning it into ENOENT.
*/
goto out;
}
} else {
ret = SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
}
if (ret == -1) {
status = map_nt_error_from_unix(errno);
DBG_DEBUG("fstat[at](%s) failed: %s\n",
smb_fname_str_dbg(smb_fname),
strerror(errno));
goto out;
}
fsp->fsp_flags.is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
orig_fsp_name->st = fsp->fsp_name->st;
if (!S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
goto out;
}
/*
* Found a symlink to follow in user space
*/
if (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH) {
/* Never follow symlinks on posix open. */
status = NT_STATUS_STOPPED_ON_SYMLINK;
goto out;
}
if (!lp_follow_symlinks(SNUM(conn))) {
/* Explicitly no symlinks. */
status = NT_STATUS_STOPPED_ON_SYMLINK;
goto out;
}
link_depth += 1;
if (link_depth >= 40) {
status = NT_STATUS_STOPPED_ON_SYMLINK;
goto out;
}
fsp->fsp_name = orig_fsp_name;
status = symlink_target_below_conn(
talloc_tos(),
connpath,
fsp,
discard_const_p(files_struct, dirfsp),
smb_fname_rel,
&target);
if (!NT_STATUS_IS_OK(status)) {
DBG_DEBUG("symlink_target_below_conn() failed: %s\n",
nt_errstr(status));
goto out;
}
/*
* Close what openat(O_PATH) potentially left behind
*/
fd_close(fsp);
if (smb_fname->base_name != orig_smb_fname_base) {
TALLOC_FREE(smb_fname->base_name);
}
smb_fname->base_name = target;
if (oldwd_fname != NULL) {
ret = vfs_ChDir(conn, oldwd_fname);
if (ret == -1) {
smb_panic("unable to get back to old directory\n");
}
TALLOC_FREE(oldwd_fname);
}
/*
* And do it all again... As smb_fname is not relative to the passed in
* dirfsp anymore, we pass conn->cwd_fsp as dirfsp to
* non_widelink_open() to trigger the chdir(parentdir) logic.
*/
dirfsp = conn->cwd_fsp;
goto again;
out:
fsp->fsp_name = orig_fsp_name;
smb_fname->base_name = orig_smb_fname_base;
TALLOC_FREE(parent_dir_fname);
if (!NT_STATUS_IS_OK(status)) {
fd_close(fsp);
}
if (oldwd_fname != NULL) {
ret = vfs_ChDir(conn, oldwd_fname);
if (ret == -1) {
smb_panic("unable to get back to old directory\n");
}
TALLOC_FREE(oldwd_fname);
}
return status;
}
/****************************************************************************
fd support routines - attempt to do a dos_open.
****************************************************************************/
@ -858,21 +481,16 @@ NTSTATUS fd_openat(const struct files_struct *dirfsp,
NTSTATUS status = NT_STATUS_OK;
bool fsp_is_stream = fsp_is_alternate_stream(fsp);
bool smb_fname_is_stream = is_named_stream(smb_fname);
struct files_struct *dirfsp_conv = NULL;
struct smb_filename *smb_fname_conv = NULL;
struct smb_filename *smb_fname_rel = NULL;
struct files_struct *root_fsp = NULL;
const char *name_in = smb_fname->base_name;
int fd;
SMB_ASSERT(fsp_is_stream == smb_fname_is_stream);
/*
* Never follow symlinks on a POSIX client. The
* client should be doing this.
*/
if (fsp->fsp_flags.posix_open || !lp_follow_symlinks(SNUM(conn))) {
how.flags |= O_NOFOLLOW;
}
if (fsp_is_stream) {
int fd;
fd = SMB_VFS_OPENAT(
conn,
NULL, /* stream open is relative to fsp->base_fsp */
@ -882,26 +500,100 @@ NTSTATUS fd_openat(const struct files_struct *dirfsp,
if (fd == -1) {
status = map_nt_error_from_unix(errno);
}
goto done;
}
how.flags |= O_NOFOLLOW; /* just to be sure */
if (strchr(smb_fname->base_name, '/') == NULL) {
/*
* With O_NOFOLLOW and no intermediate path components
* we can try directly.
*/
fd = SMB_VFS_OPENAT(conn, dirfsp, smb_fname, fsp, &how);
if (fd >= 0) {
fsp_set_fd(fsp, fd);
if (fd != -1) {
status = vfs_stat_fsp(fsp);
if (!NT_STATUS_IS_OK(status)) {
DBG_DEBUG("vfs_stat_fsp failed: %s\n",
nt_errstr(status));
fd_close(fsp);
}
}
return status;
if (NT_STATUS_IS_OK(status) &&
!S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
smb_fname->st = fsp->fsp_name->st;
fsp->fsp_flags.is_directory = S_ISDIR(
fsp->fsp_name->st.st_ex_mode);
return NT_STATUS_OK;
}
/*
* Only follow symlinks within a share
* definition.
* We found a symlink in the lcomp via O_PATH,
* let filename_convert_dirfsp_rel follow
* it. This means we're going to open the
* symlink twice, but this is something to
* optimize when it becomes a problem.
*/
status = non_widelink_open(dirfsp, fsp, smb_fname, &how);
SMB_VFS_CLOSE(fsp);
fsp_set_fd(fsp, -1);
fd = -1;
}
}
if (name_in[0] == '/') {
/*
* filename_convert_dirfsp can't deal with absolute
* paths, make this relative to "/"
*/
name_in += 1;
status = open_rootdir_pathref_fsp(conn, &root_fsp);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
dirfsp = root_fsp;
}
if (ISDOT(name_in)) {
/*
* filename_convert_dirfsp does not like ".", use ""
*/
name_in += 1;
}
status = filename_convert_dirfsp_rel(
talloc_tos(),
conn,
discard_const_p(struct files_struct, dirfsp),
name_in,
UCF_POSIX_PATHNAMES, /* no case insensitive search */
smb_fname->twrp,
&dirfsp_conv,
&smb_fname_conv,
&smb_fname_rel);
dirfsp = NULL;
if (root_fsp != NULL) {
fd_close(root_fsp);
file_free(NULL, root_fsp);
root_fsp = NULL;
}
if (!NT_STATUS_IS_OK(status)) {
DBG_DEBUG("filename_convert_dirfsp_rel returned %s\n",
nt_errstr(status));
return status;
}
fd = SMB_VFS_OPENAT(conn, dirfsp_conv, smb_fname_rel, fsp, &how);
if (fd == -1) {
status = map_nt_error_from_unix(errno);
}
fd_close(dirfsp_conv);
file_free(NULL, dirfsp_conv);
dirfsp_conv = NULL;
TALLOC_FREE(smb_fname_conv);
done:
fsp_set_fd(fsp, fd); /* This preserves errno */
if (fd == -1) {
if (NT_STATUS_EQUAL(status, NT_STATUS_TOO_MANY_OPENED_FILES)) {
static time_t last_warned = 0L;
@ -921,7 +613,18 @@ NTSTATUS fd_openat(const struct files_struct *dirfsp,
fsp_get_pathref_fd(fsp),
nt_errstr(status));
return status;
} else {
status = vfs_stat_fsp(fsp);
if (!NT_STATUS_IS_OK(status)) {
DBG_DEBUG("vfs_stat_fsp failed: %s\n",
nt_errstr(status));
fd_close(fsp);
return status;
}
}
smb_fname->st = fsp->fsp_name->st;
fsp->fsp_flags.is_directory = S_ISDIR(fsp->fsp_name->st.st_ex_mode);
DBG_DEBUG("name %s, flags = 0%o mode = 0%o, fd = %d\n",
smb_fname_str_dbg(smb_fname),
@ -1153,7 +856,7 @@ static NTSTATUS fd_open_atomic(struct files_struct *dirfsp,
return status;
}
static NTSTATUS reopen_from_fsp(struct files_struct *dirfsp,
NTSTATUS reopen_from_fsp(struct files_struct *dirfsp,
struct smb_filename *smb_fname,
struct files_struct *fsp,
const struct vfs_open_how *how,
@ -1172,8 +875,6 @@ static NTSTATUS reopen_from_fsp(struct files_struct *dirfsp,
mode_t mode = fsp->fsp_name->st.st_ex_mode;
int new_fd;
SMB_ASSERT(fsp->fsp_flags.is_pathref);
if (S_ISLNK(mode)) {
return NT_STATUS_STOPPED_ON_SYMLINK;
}

View File

@ -344,10 +344,6 @@ struct files_struct *file_fsp_get(struct smbd_smb2_request *smb2req,
struct files_struct *file_fsp_smb2(struct smbd_smb2_request *smb2req,
uint64_t persistent_id,
uint64_t volatile_id);
NTSTATUS dup_file_fsp(
files_struct *from,
uint32_t access_mask,
files_struct *to);
NTSTATUS file_name_hash(connection_struct *conn,
const char *name, uint32_t *p_name_hash);
NTSTATUS fsp_set_smb_fname(struct files_struct *fsp,
@ -370,11 +366,9 @@ NTSTATUS open_internal_dirfsp(connection_struct *conn,
const struct smb_filename *smb_dname,
int open_flags,
struct files_struct **_fsp);
NTSTATUS openat_internal_dir_from_pathref(
struct files_struct *dirfsp,
int open_flags,
struct files_struct **_fsp);
NTSTATUS open_rootdir_pathref_fsp(connection_struct *conn,
struct files_struct **_fsp);
NTSTATUS openat_pathref_fsp(const struct files_struct *dirfsp,
struct smb_filename *smb_fname);
NTSTATUS open_stream_pathref_fsp(
@ -669,6 +663,11 @@ NTSTATUS fd_openat(const struct files_struct *dirfsp,
files_struct *fsp,
const struct vfs_open_how *how);
NTSTATUS fd_close(files_struct *fsp);
NTSTATUS reopen_from_fsp(struct files_struct *dirfsp,
struct smb_filename *smb_fname,
struct files_struct *fsp,
const struct vfs_open_how *how,
bool *p_file_created);
bool is_oplock_stat_open(uint32_t access_mask);
bool is_lease_stat_open(uint32_t access_mask);
NTSTATUS send_break_message(struct messaging_context *msg_ctx,
@ -1061,12 +1060,12 @@ NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
int total_data,
files_struct *fsp,
struct smb_filename *smb_fname);
NTSTATUS refuse_symlink_fsp(const struct files_struct *fsp);
bool refuse_symlink_fsp(const struct files_struct *fsp);
NTSTATUS check_any_access_fsp(struct files_struct *fsp,
uint32_t access_requested);
uint64_t smb_roundup(connection_struct *conn, uint64_t val);
bool samba_private_attr_name(const char *unix_ea_name);
NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
int get_ea_value_fsp(TALLOC_CTX *mem_ctx,
files_struct *fsp,
const char *ea_name,
struct ea_struct *pea);

View File

@ -133,8 +133,9 @@ static int set_sys_acl_conn(const char *fname,
TALLOC_CTX *frame = talloc_stackframe();
NTSTATUS status;
smb_fname = synthetic_smb_fname_split(frame,
fname,
smb_fname = synthetic_smb_fname_split(
frame,
canonicalize_absolute_path(talloc_tos(), fname),
lp_posix_pathnames());
if (smb_fname == NULL) {
TALLOC_FREE(frame);
@ -186,8 +187,9 @@ static NTSTATUS init_files_struct(TALLOC_CTX *mem_ctx,
}
fsp->conn = conn;
smb_fname = synthetic_smb_fname_split(fsp,
fname,
smb_fname = synthetic_smb_fname_split(
fsp,
canonicalize_absolute_path(talloc_tos(), fname),
lp_posix_pathnames());
if (smb_fname == NULL) {
return NT_STATUS_NO_MEMORY;
@ -302,8 +304,9 @@ static NTSTATUS get_nt_acl_conn(TALLOC_CTX *mem_ctx,
NTSTATUS status;
struct smb_filename *smb_fname = NULL;
smb_fname = synthetic_smb_fname_split(frame,
fname,
smb_fname = synthetic_smb_fname_split(
frame,
canonicalize_absolute_path(talloc_tos(), fname),
lp_posix_pathnames());
if (smb_fname == NULL) {
@ -697,8 +700,9 @@ static PyObject *py_smbd_unlink(PyObject *self, PyObject *args, PyObject *kwargs
return NULL;
}
smb_fname = synthetic_smb_fname_split(frame,
fname,
smb_fname = synthetic_smb_fname_split(
frame,
canonicalize_absolute_path(talloc_tos(), fname),
lp_posix_pathnames());
if (smb_fname == NULL) {
TALLOC_FREE(frame);
@ -1038,8 +1042,9 @@ static PyObject *py_smbd_get_sys_acl(PyObject *self, PyObject *args, PyObject *k
return NULL;
}
smb_fname = synthetic_smb_fname_split(frame,
fname,
smb_fname = synthetic_smb_fname_split(
frame,
canonicalize_absolute_path(talloc_tos(), fname),
lp_posix_pathnames());
if (smb_fname == NULL) {
TALLOC_FREE(frame);
@ -1127,13 +1132,13 @@ static PyObject *py_smbd_mkdir(PyObject *self, PyObject *args, PyObject *kwargs)
return NULL;
}
smb_fname = synthetic_smb_fname(talloc_tos(),
fname,
smb_fname = synthetic_smb_fname(
talloc_tos(),
canonicalize_absolute_path(talloc_tos(), fname),
NULL,
NULL,
0,
lp_posix_pathnames() ?
SMB_FILENAME_POSIX_PATH : 0);
lp_posix_pathnames() ? SMB_FILENAME_POSIX_PATH : 0);
if (smb_fname == NULL) {
TALLOC_FREE(frame);

View File

@ -2389,7 +2389,7 @@ static NTSTATUS smb_q_posix_acl(
uint16_t num_def_acls = 0;
unsigned int size_needed = 0;
NTSTATUS status;
bool ok;
bool ok, refuse;
bool close_fsp = false;
/*
@ -2415,8 +2415,9 @@ static NTSTATUS smb_q_posix_acl(
SMB_ASSERT(fsp != NULL);
status = refuse_symlink_fsp(fsp);
if (!NT_STATUS_IS_OK(status)) {
refuse = refuse_symlink_fsp(fsp);
if (refuse) {
status = NT_STATUS_ACCESS_DENIED;
goto out;
}
@ -4273,6 +4274,7 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
unsigned int size_needed;
unsigned int total_data;
bool close_fsp = false;
bool refuse;
if (total_data_in < 0) {
status = NT_STATUS_INVALID_PARAMETER;
@ -4359,8 +4361,9 @@ static NTSTATUS smb_set_posix_acl(connection_struct *conn,
/* Here we know fsp != NULL */
SMB_ASSERT(fsp != NULL);
status = refuse_symlink_fsp(fsp);
if (!NT_STATUS_IS_OK(status)) {
refuse = refuse_symlink_fsp(fsp);
if (refuse) {
status = NT_STATUS_ACCESS_DENIED;
goto out;
}

View File

@ -41,6 +41,7 @@ struct files_struct *fcb_or_dos_open(
struct connection_struct *conn = req->conn;
struct file_id id = vfs_file_id_from_sbuf(conn, &smb_fname->st);
struct files_struct *fsp = NULL, *new_fsp = NULL;
size_t new_refcount;
NTSTATUS status;
if ((private_flags &
@ -97,10 +98,35 @@ struct files_struct *fcb_or_dos_open(
return NULL;
}
status = dup_file_fsp(fsp, access_mask, new_fsp);
/*
* Share the fsp->fh between old and new
*/
TALLOC_FREE(new_fsp->fh);
new_fsp->fh = fsp->fh;
new_refcount = fh_get_refcount(new_fsp->fh) + 1;
fh_set_refcount(new_fsp->fh, new_refcount);
new_fsp->file_id = fsp->file_id;
new_fsp->initial_allocation_size = fsp->initial_allocation_size;
new_fsp->file_pid = fsp->file_pid;
new_fsp->vuid = fsp->vuid;
new_fsp->open_time = fsp->open_time;
new_fsp->access_mask = access_mask;
new_fsp->oplock_type = fsp->oplock_type;
new_fsp->fsp_flags = fsp->fsp_flags;
new_fsp->fsp_flags.can_read = ((access_mask & FILE_READ_DATA) != 0);
new_fsp->fsp_flags.can_write = CAN_WRITE(fsp->conn) &&
((access_mask & (FILE_WRITE_DATA |
FILE_APPEND_DATA)) !=
0);
if (fsp->fsp_name->twrp != 0) {
new_fsp->fsp_flags.can_write = false;
}
status = fsp_set_smb_fname(new_fsp, fsp->fsp_name);
if (!NT_STATUS_IS_OK(status)) {
DBG_DEBUG("dup_file_fsp failed: %s\n", nt_errstr(status));
DBG_DEBUG("fsp_set_smb_fname failed: %s\n", nt_errstr(status));
file_free(req, new_fsp);
return NULL;
}

View File

@ -83,6 +83,7 @@ NTSTATUS set_sd(files_struct *fsp, struct security_descriptor *psd,
{
files_struct *sd_fsp = NULL;
NTSTATUS status;
bool refuse;
if (!CAN_WRITE(fsp->conn)) {
return NT_STATUS_ACCESS_DENIED;
@ -92,11 +93,11 @@ NTSTATUS set_sd(files_struct *fsp, struct security_descriptor *psd,
return NT_STATUS_OK;
}
status = refuse_symlink_fsp(fsp);
if (!NT_STATUS_IS_OK(status)) {
refuse = refuse_symlink_fsp(fsp);
if (refuse) {
DBG_DEBUG("ACL set on symlink %s denied.\n",
fsp_str_dbg(fsp));
return status;
return NT_STATUS_ACCESS_DENIED;
}
if (psd->owner_sid == NULL) {
@ -480,6 +481,7 @@ static NTSTATUS smbd_fetch_security_desc(connection_struct *conn,
NTSTATUS status;
struct security_descriptor *psd = NULL;
bool need_to_read_sd = false;
bool refuse;
/*
* Get the permissions to return.
@ -501,11 +503,11 @@ static NTSTATUS smbd_fetch_security_desc(connection_struct *conn,
}
}
status = refuse_symlink_fsp(fsp);
if (!NT_STATUS_IS_OK(status)) {
refuse = refuse_symlink_fsp(fsp);
if (refuse) {
DBG_DEBUG("ACL get on symlink %s denied.\n",
fsp_str_dbg(fsp));
return status;
return NT_STATUS_ACCESS_DENIED;
}
if (security_info_wanted & (SECINFO_DACL|SECINFO_OWNER|

View File

@ -381,21 +381,17 @@ static struct tevent_req *smbd_smb2_query_directory_send(TALLOC_CTX *mem_ctx,
if (in_flags & SMB2_CONTINUE_FLAG_REOPEN) {
struct vfs_open_how how = { .flags = O_RDONLY, };
status = fd_close(fsp);
if (tevent_req_nterror(req, status)) {
return tevent_req_post(req, ev);
}
/*
* fd_close() will close and invalidate the fsp's file
* descriptor. So we have to reopen it.
*/
bool file_was_created;
#ifdef O_DIRECTORY
how.flags |= O_DIRECTORY;
#endif
status = fd_openat(conn->cwd_fsp, fsp->fsp_name, fsp, &how);
status = reopen_from_fsp(conn->cwd_fsp,
fsp->fsp_name,
fsp,
&how,
&file_was_created);
if (tevent_req_nterror(req, status)) {
return tevent_req_post(req, ev);
}

View File

@ -785,22 +785,26 @@ NTSTATUS make_connection_snum(struct smbXsrv_connection *xconn,
I have disabled this chdir check (tridge) */
/* the alternative is just to check the directory exists */
if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
!S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
DBG_ERR("'%s' is not a directory, when connecting to "
"[%s]\n", conn->connectpath,
lp_const_servicename(snum));
} else {
ret = SMB_VFS_STAT(conn, smb_fname_cpath);
if (ret != 0) {
DBG_ERR("'%s' does not exist or permission denied "
"when connecting to [%s] Error was %s\n",
conn->connectpath,
lp_const_servicename(snum),
strerror(errno));
}
status = NT_STATUS_BAD_NETWORK_NAME;
goto err_root_exit;
}
if (!S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
DBG_ERR("'%s' is not a directory, when connecting to "
"[%s]\n",
conn->connectpath,
lp_const_servicename(snum));
status = NT_STATUS_BAD_NETWORK_NAME;
goto err_root_exit;
}
conn->base_share_dev = smb_fname_cpath->st.st_ex_dev;
/* Figure out the characteristics of the underlying filesystem. This

View File

@ -60,19 +60,19 @@ static uint32_t generate_volume_serial_number(
Check if an open file handle is a symlink.
****************************************************************************/
NTSTATUS refuse_symlink_fsp(const files_struct *fsp)
bool refuse_symlink_fsp(const files_struct *fsp)
{
if (!VALID_STAT(fsp->fsp_name->st)) {
return NT_STATUS_ACCESS_DENIED;
return true;
}
if (S_ISLNK(fsp->fsp_name->st.st_ex_mode)) {
return NT_STATUS_ACCESS_DENIED;
return true;
}
if (fsp_get_pathref_fd(fsp) == -1) {
return NT_STATUS_ACCESS_DENIED;
return true;
}
return NT_STATUS_OK;
return false;
}
/**
@ -184,7 +184,7 @@ bool samba_private_attr_name(const char *unix_ea_name)
Get one EA value. Fill in a struct ea_struct.
****************************************************************************/
NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
int get_ea_value_fsp(TALLOC_CTX *mem_ctx,
files_struct *fsp,
const char *ea_name,
struct ea_struct *pea)
@ -194,14 +194,14 @@ NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
char *val = NULL;
ssize_t sizeret;
size_t max_xattr_size = 0;
NTSTATUS status;
bool refuse;
if (fsp == NULL) {
return NT_STATUS_INVALID_HANDLE;
return EINVAL;
}
status = refuse_symlink_fsp(fsp);
if (!NT_STATUS_IS_OK(status)) {
return status;
refuse = refuse_symlink_fsp(fsp);
if (refuse) {
return EACCES;
}
max_xattr_size = lp_smbd_max_xattr_size(SNUM(fsp->conn));
@ -210,7 +210,7 @@ NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
val = talloc_realloc(mem_ctx, val, char, attr_size);
if (!val) {
return NT_STATUS_NO_MEMORY;
return ENOMEM;
}
sizeret = SMB_VFS_FGETXATTR(fsp, ea_name, val, attr_size);
@ -220,7 +220,7 @@ NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
}
if (sizeret == -1) {
return map_nt_error_from_unix(errno);
return errno;
}
DBG_DEBUG("EA %s is of length %zd\n", ea_name, sizeret);
@ -234,11 +234,11 @@ NTSTATUS get_ea_value_fsp(TALLOC_CTX *mem_ctx,
}
if (pea->name == NULL) {
TALLOC_FREE(val);
return NT_STATUS_NO_MEMORY;
return ENOMEM;
}
pea->value.data = (unsigned char *)val;
pea->value.length = (size_t)sizeret;
return NT_STATUS_OK;
return 0;
}
NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
@ -263,7 +263,7 @@ NTSTATUS get_ea_names_from_fsp(TALLOC_CTX *mem_ctx,
}
*pnum_names = 0;
if ((fsp == NULL) || !NT_STATUS_IS_OK(refuse_symlink_fsp(fsp))) {
if ((fsp == NULL) || refuse_symlink_fsp(fsp)) {
/*
* Callers may pass fsp == NULL when passing smb_fname->fsp of a
* symlink. This is ok, handle it here, by just return no EA's
@ -410,6 +410,7 @@ static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
for (i=0; i<num_names; i++) {
struct ea_list *listp;
fstring dos_ea_name;
int ret;
/*
* POSIX EA names are divided into several namespaces by
@ -441,14 +442,11 @@ static NTSTATUS get_ea_list_from_fsp(TALLOC_CTX *mem_ctx,
return NT_STATUS_NO_MEMORY;
}
status = get_ea_value_fsp(listp,
fsp,
names[i],
&listp->ea);
ret = get_ea_value_fsp(listp, fsp, names[i], &listp->ea);
if (!NT_STATUS_IS_OK(status)) {
if (ret != 0) {
TALLOC_FREE(listp);
return status;
return map_nt_error_from_unix(ret);
}
if (listp->ea.value.length == 0) {
@ -711,6 +709,7 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
{
NTSTATUS status;
bool posix_pathnames = false;
bool refuse;
if (!lp_ea_support(SNUM(conn))) {
return NT_STATUS_EAS_NOT_SUPPORTED;
@ -722,9 +721,9 @@ NTSTATUS set_ea(connection_struct *conn, files_struct *fsp,
posix_pathnames = (fsp->fsp_name->flags & SMB_FILENAME_POSIX_PATH);
status = refuse_symlink_fsp(fsp);
if (!NT_STATUS_IS_OK(status)) {
return status;
refuse = refuse_symlink_fsp(fsp);
if (refuse) {
return NT_STATUS_ACCESS_DENIED;
}
status = check_any_access_fsp(fsp, FILE_WRITE_EA);

View File

@ -453,9 +453,8 @@ static void print_impersonation_info(connection_struct *conn)
return;
}
if (conn->tcon_done) {
cwdfname = vfs_GetWd(talloc_tos(), conn);
if (cwdfname == NULL) {
return;
}
DBG_INFO("Impersonated user: uid=(%d,%d), gid=(%d,%d), cwd=[%s]\n",
@ -463,7 +462,7 @@ static void print_impersonation_info(connection_struct *conn)
(int)geteuid(),
(int)getgid(),
(int)getegid(),
cwdfname->base_name);
cwdfname ? cwdfname->base_name : "no cwd");
TALLOC_FREE(cwdfname);
}

View File

@ -1022,6 +1022,9 @@ struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
if (!lp_getwd_cache()) {
goto nocache;
}
if (fsp_get_pathref_fd(conn->cwd_fsp) == -1) {
goto nocache;
}
smb_fname_dot = synthetic_smb_fname(ctx,
".",
@ -1086,7 +1089,7 @@ struct smb_filename *vfs_GetWd(TALLOC_CTX *ctx, connection_struct *conn)
goto out;
}
if (lp_getwd_cache() && VALID_STAT(smb_fname_dot->st)) {
if ((smb_fname_dot != NULL) && VALID_STAT(smb_fname_dot->st)) {
key = vfs_file_id_from_sbuf(conn, &smb_fname_dot->st);
/*

View File

@ -144,6 +144,7 @@ static int net_vfs_init(struct net_context *c, int argc, const char **argv)
sec_init();
setup_logging("net", DEBUG_STDOUT);
lpcfg_set_cmdline(c->lp_ctx, "log level", "0");
mangle_change_to_posix();
ok = lp_load_with_registry_shares(get_dyn_CONFIGFILE());
if (!ok) {

View File

@ -60,31 +60,27 @@
struct samr_Password *smbpasswd_gethexpwd(TALLOC_CTX *mem_ctx, const char *p)
{
int i;
unsigned char lonybble, hinybble;
const char *hexchars = "0123456789ABCDEF";
const char *p1, *p2;
struct samr_Password *pwd = talloc(mem_ctx, struct samr_Password);
struct samr_Password *pwd = NULL;
size_t len;
if (!p) return NULL;
for (i = 0; i < (sizeof(pwd->hash) * 2); i += 2)
{
hinybble = toupper(p[i]);
lonybble = toupper(p[i + 1]);
p1 = strchr_m(hexchars, hinybble);
p2 = strchr_m(hexchars, lonybble);
if (!p1 || !p2) {
if (p == NULL) {
return NULL;
}
hinybble = PTR_DIFF(p1, hexchars);
lonybble = PTR_DIFF(p2, hexchars);
pwd->hash[i / 2] = (hinybble << 4) | lonybble;
pwd = talloc(mem_ctx, struct samr_Password);
if (pwd == NULL) {
return NULL;
}
len = strhex_to_str((char *)pwd->hash,
sizeof(pwd->hash),
p,
sizeof(pwd->hash) * 2);
if (len != sizeof(pwd->hash)) {
TALLOC_FREE(pwd);
return NULL;
}
return pwd;
}
@ -93,14 +89,11 @@ char *smbpasswd_sethexpwd(TALLOC_CTX *mem_ctx, struct samr_Password *pwd, uint16
{
char *p;
if (pwd != NULL) {
int i;
p = talloc_array(mem_ctx, char, 33);
if (!p) {
return NULL;
}
for (i = 0; i < sizeof(pwd->hash); i++)
slprintf(&p[i*2], 3, "%02X", pwd->hash[i]);
hex_encode_buf(p, pwd->hash, sizeof(pwd->hash));
} else {
if (acb_info & ACB_PWNOTREQ)
p = talloc_strdup(mem_ctx, "NO PASSWORDXXXXXXXXXXXXXXXXXXXXX");

View File

@ -28,7 +28,6 @@ interface ntp_signd
uint16 packet_id;
[flag(NDR_LITTLE_ENDIAN)] uint32 key_id;
[flag(NDR_REMAINING)] DATA_BLOB packet_to_sign;
} sign_request;
typedef [flag(NDR_BIG_ENDIAN),public] struct samba_key_out {

View File

@ -3059,7 +3059,8 @@ static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_
{
struct auth_session_info *session_info =
dcesrv_call_session_info(dce_call);
const char *sidstr, *sidndrstr;
struct dom_sid_buf sidbuf;
const char *sidndrstr = NULL;
struct ldb_message *msg;
struct ldb_message_element *el;
int ret;
@ -3084,13 +3085,7 @@ static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_
return NT_STATUS_NO_MEMORY;
}
sidstr = dom_sid_string(msg, sid);
if (sidstr == NULL) {
TALLOC_FREE(msg);
return NT_STATUS_NO_MEMORY;
}
dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
dnstr = talloc_asprintf(msg, "sid=%s", dom_sid_str_buf(sid, &sidbuf));
if (dnstr == NULL) {
TALLOC_FREE(msg);
return NT_STATUS_NO_MEMORY;