ParallelSSH / ssh2-python

Python bindings for libssh2 C library.
https://parallel-ssh.org
GNU Lesser General Public License v2.1
229 stars 73 forks source link

mkdir fails to set the mode #129

Closed Togtja closed 3 years ago

Togtja commented 4 years ago

Bug reports

Steps to reproduce:


def chmod(sftp, path, permissions):
    stat = sftp.stat(path)
    print("old perm", oct(stat.permissions))
    stat.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS
    stat.permissions = permissions

    sftp.setstat(path, stat)
    stat = sftp.stat(path)
    print("new perm", oct(stat.permissions))

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("host_ip", 22))

session = Session()
session.handshake(sock)
session.userauth_password("root", "root")

sftp = session.sftp_init()

sftp.mkdir("/Test_folder", LIBSSH2_SFTP_S_IRWXU | LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IWGRP)
#Here the "Test_folder" has the permissions "rwx------"
chmod(sftp, "/Test_folder", LIBSSH2_SFTP_S_IRWXU | LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IWGRP)
#Here the "Test_folder" has the permissions "rwxrw----"

It logs:

old perm 0o40700
new perm 0o40760

Expected behaviour: [What was expected to happen.] That the mode set in mkdir get uphold, and the folder get the correct permission

Actual behaviour: [What actually happened.] I have not tested it with too many different combination, so don't know to much detail, but the mode does not always get upheld. It seems that the issue is with group and other permissions, as the user permission is always upheld

Additional info: [Include version of libssh2 and any other relevant information.] Running newst ssh2-python 0.23.0 .whl binary.

Thank you for your work, the LIBSSH2_SFTP_ATTR_PERMISSIONS flag worked wounders, as you can see that my chmod function fix and correct the mistake by the mkdir

pkittenis commented 3 years ago

Cannot reproduce.

This is likely a server issue. Servers are not guaranteed to honour these flags. File attributes may be set on creation by server regardless of what is requested (see server's default umask).

On my host the above works as expected:

    _path = "/tmp/test_dir"
    sftp.mkdir(_path, LIBSSH2_SFTP_S_IRWXU | LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IWGRP)
    chmod(sftp, _path, LIBSSH2_SFTP_S_IRWXU | LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IWGRP)

old perm 0o40740
new perm 0o40760
Togtja commented 3 years ago

The expected is that "old" and "new" perm should be the same. IE rwxrw---- for both, as the same permissions are placed for the created directory and the chmod. When you gave the permissions LIBSSH2_SFTP_S_IRWXU | LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IWGRP it returned as 0o40740 where as LIBSSH2_SFTP_S_IRWXU | LIBSSH2_SFTP_S_IRGRP | LIBSSH2_SFTP_S_IWGRP should be: 0o40760, it did not become so before you called chmod (that called setstat). I believe you managed to reproduce a very similar error, you just can't mkdir with LIBSSH2_SFTP_S_IWGRP set, and I can't with both LIBSSH2_SFTP_S_IWGRP and LIBSSH2_SFTP_S_IRGRP

pkittenis commented 3 years ago

What the file permissions on a newly created file or directory will be depends on the server. See man umask. The library is sending the flags, the server is not guaranteed to honour them.

On my server configuration allows for group read/execute to be set but not write. On yours no group permissions can be set. Umask 0022 and (probably) umask 0077 respectively. No idea how that works on windows servers.

    _path = "/tmp/test_dir"
    sftp.mkdir(_path, LIBSSH2_SFTP_S_IRWXU | LIBSSH2_SFTP_S_IRWXG)
    stat = os.stat(_path)
    print("mkdir perm", oct(stat.st_mode))
mkdir perm 0o40750

It is not a bug. Code will have to use setstat explicitly to guarantee permissions after creating a file.

pkittenis commented 3 years ago

Forgot to include example:

$ umask
0022
$ umask 0022; mkdir t; ls -lhd t; rm -rf t
drwxr-xr-x 2 xx xx 4.0K Dec  4 21:15 t
$ umask 0077; mkdir t; ls -lhd t; rm -rf t
drwx------ 2 xx xx 4.0K Dec  4 21:15 t