Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cifs.upcall.c
Original file line number Diff line number Diff line change
Expand Up @@ -1719,7 +1719,7 @@ int main(const int argc, char *const argv[])
/* pack SecurityBlob and SessionKey into downcall packet */
datalen =
sizeof(struct cifs_spnego_msg) + secblob.length + sess_key.length;
keydata = (struct cifs_spnego_msg *)calloc(sizeof(char), datalen);
keydata = (struct cifs_spnego_msg *)calloc(datalen, sizeof(char));
if (!keydata) {
rc = 1;
goto out;
Expand Down
19 changes: 8 additions & 11 deletions mount.cifs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,14 @@ username=arg|user=arg
specifies the username to connect as. If this is not
given, then the environment variable USER is used.

Earlier versions of mount.cifs also allowed one to specify the
username in a ``user%password`` or ``workgroup/user`` or
``workgroup/user%password`` to allow the password and workgroup to
be specified as part of the username. Support for those alternate
username formats is now deprecated and should no longer be
used. Users should use the discrete ``password=`` and ``domain=`` to
specify those values. While some versions of the cifs kernel module
accept ``user=`` as an abbreviation for this option, its use can
confuse the standard mount program into thinking that this is a
non-superuser mount. It is therefore recommended to use the full
``username=`` option name.
Users must use the discrete ``password=`` and ``domain=`` options to
specify relevant values. Including these in the ``username=`` option
is no longer supported.

While some versions of the cifs kernel module accept ``user=`` as an
abbreviation for this option, its use can confuse the standard mount
program into thinking that this is a non-superuser mount. It is
therefore recommended to use the full ``username=`` option name.

password=arg|pass=arg
specifies the CIFS password. If this option is not given then the
Expand Down
78 changes: 78 additions & 0 deletions smbinfo
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import struct
import stat
import datetime
import calendar
import threading

VERBOSE = False

Expand All @@ -36,6 +37,7 @@ CIFS_ENUMERATE_SNAPSHOTS = 0x800ccf06
CIFS_DUMP_KEY = 0xc03acf08
CIFS_DUMP_FULL_KEY = 0xc011cf0a
CIFS_GET_TCON_INFO = 0x800ccf0c
CIFS_IOC_NOTIFY_INFO = 0xc009cf0b

# large enough input buffer length
INPUT_BUFFER_LENGTH = 16384
Expand Down Expand Up @@ -294,6 +296,10 @@ def main():
sap.add_argument("file")
sap.set_defaults(func=cmd_gettconinfo)

sap = subp.add_parser("notify", help="Query a directory for change notifications")
sap.add_argument("file")
sap.set_defaults(func=cmd_notify)

# parse arguments
args = ap.parse_args()

Expand Down Expand Up @@ -905,5 +911,77 @@ def cmd_gettconinfo(args):
print("TCON Id: 0x%x"%tcon.tid)
print("Session Id: 0x%x"%tcon.session_id)

def cmd_notify(args):
try:
fd = os.open(args.file, os.O_RDONLY)
except Exception as e:
print("syscall failed: %s"%e)
return False

thread = threading.Thread(target=notify_thread, args=(fd,))
thread.start()

try:
thread.join()
except KeyboardInterrupt:
pass
finally:
os.close(fd)
return False

def notify_thread(fd):
fmt = "<IBI"
# See `struct smb3_notify_info` in linux kernel fs/smb/client/cifs_ioctl.h
completion_filter = 0xFFF
watch_tree = True
data_len = 1000

while True:
buf = bytearray(struct.pack(fmt, completion_filter, watch_tree, data_len))
buf.extend(bytearray(data_len))

try:
fcntl.ioctl(fd, CIFS_IOC_NOTIFY_INFO, buf, True)
except Exception as e:
print("syscall failed: %s"%e)
return False

_, _, data_len_returned = struct.unpack_from(fmt, buf, 0)
print("Notify completed, returned data_len is", data_len_returned)
notify_data, = struct.unpack_from(f'{data_len_returned}s', buf, struct.calcsize(fmt))
print_notify(notify_data)

def print_notify(notify_data):
if notify_data is None:
return

data_size = len(notify_data)
if data_size == 0:
return

BYTES_PER_LINE = 16
for offset in range(0, data_size, BYTES_PER_LINE):
chunk = notify_data[offset:offset + BYTES_PER_LINE]

# raw hex data
hex_bytes = "".join(
(" " if i % 8 == 0 else "") + f"{x:02x} "
for i, x in enumerate(chunk)
)

# padding
pad_len = BYTES_PER_LINE - len(chunk)
pad = " " * pad_len
if pad_len >= 8:
pad += " " * (pad_len // 8)

# ASCII
ascii_part = "".join(
chr(x) if 31 < x < 127 else "."
for x in chunk
)

print(f"{offset:08x}: {hex_bytes}{pad} {ascii_part}")

if __name__ == '__main__':
main()
2 changes: 2 additions & 0 deletions smbinfo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ the SMB3 traffic of this mount can be decryped e.g. via wireshark

`gettconinfo`: Prints both the TCON Id and Session Id for a cifs file.

`notify`: Query a directory for change notifications.

*****
NOTES
*****
Expand Down