Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doesn't set proper mode #1463

Closed
atanas18 opened this issue Mar 25, 2020 · 15 comments
Closed

doesn't set proper mode #1463

atanas18 opened this issue Mar 25, 2020 · 15 comments

Comments

@atanas18
Copy link

$attr = $mode == -1 ? "\0\0\0\0" : pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777);

First of all excuse me for my English .. it's not my native language.

I have been having issues with creating directory with proper permissions trough SFTP.
Doing many tests .. it doesn't set proper mode for the directory .. like 0777 0775 etc. It was doing all kind of strange permissions, just not the ones I wanted it to.. Tried many different modes, none works.

Once changed that from 07777 to 0777 .. the mode start working as expected.
Not sure if this is just a coincidence or there is a real issue there.
In the file there are another 3 usages of 07777 which are probably causing similar issues (I didn't tried the other options, as I only needed mkdir).

@terrafrost
Copy link
Member

Once changed that from 07777 to 0777 .. the mode start working as expected.

The extra 7 is for "special modes". setuid, setgid and sticky.

Anyway, I tried it without issue. Here's what ls -latr reported on filename.ext before $sftp->chmod('filename.ext', 0777):

-rw-rw-r-- 

Here's what it reported after:

-rwxrwxrwx

ie. it's behaving exactly as it should.

If you're saying it's not behaving that way then I think you're going to need to provide more info. I guess enable logging. You can do so by doing define('NET_SSH2_LOGGING', 2) and then echo $ssh->getLog() after your attempt to set the permission.

I suppose it's possible you have special modes set and that they're interfering with stuff. I don't have any real hands on experience with the special modes.

I suppose it's also possible you're running an SFTP server on Windows. If so then, in-so-far as I know, Windows doesn't offer true POSIX support and setting permissions on Windows... well it's not completely clear how that'd translate to a chmod command. In this scenario it's probably more of an issue with your SFTP server than it is with phpseclib and you'll, in all likelihood, be able to reproduce the issue with any SFTP client (WinSCP, etc).

@atanas18
Copy link
Author

Hi, thanks for the comment.
Maybe I need to add more clarity .. My issue is about creating the directories (mkdir), not chmod (I didn't tested chmod, as is creating the files with Read flag, which is enough for me).
I'm using CentOS 7 as a Client and Ubuntu 18.04.1 LTS as SFTP server.

Directories however, in our case need special mode. Our directories must be created as (and this is the default mode)

drwxrwsr-x
This is a representation of 2775

If not passing any mode (so guessing the default from the umask), it should be created like that... Using a Filezilla (without any custom settings) to upload files (and create directories) to the same SFTP add the corresponding mode with the correct default.

Doing trough the library however, as default, without passing a mode, it creates the directories as drwxr-Sr-- .. without the x flag (so it shows uppercase S) on the group, the files inside can't be reached by the group members.
Passing a custom mode of 2775 to the library creates the directories with d-wx-wSr-t ... which is wrong representation of 2775 - again, no read flag, no executable on the group, and sticky.

Only after removing the last 7 digit on the 1700 line in that file, set the correct permission to 2775 or drwxrwsr-x for the directory.

@terrafrost
Copy link
Member

If not passing any mode (so guessing the default from the umask), it should be created like that... Using a Filezilla (without any custom settings) to upload files (and create directories) to the same SFTP add the corresponding mode with the correct default.

drwxrwsr-x
This is a representation of 2775

If not passing any mode (so guessing the default from the umask), it should be created like that... Using a Filezilla (without any custom settings) to upload files (and create directories) to the same SFTP add the corresponding mode with the correct default.

That's exactly what phpseclib does:

function mkdir($dir, $mode = -1, $recursive = false)
{
if (!($this->bitmap & SSH2::MASK_LOGIN)) {
return false;
}
$dir = $this->_realpath($dir);
// by not providing any permissions, hopefully the server will use the logged in users umask - their
// default permissions.
$attr = $mode == -1 ? "\0\0\0\0" : pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777);
if ($recursive) {
$dirs = explode('/', preg_replace('#/(?=/)|/$#', '', $dir));

If you want directories to be created with 2775 then the umask would need to be 1002 (eg. ~2775) (if i'm understanding umask correctly), altho when I try umask 1002 on the CLI I get a bash: umask: 1002: octal number out of range error.

Anyway, I did some testing with WinSCP and did encounter some wonkiness with mkdir with permissions being manually set. Apparently what WinSCP does is that it creates the directory with an SSH_FXP_MKDIR packet and then it sets the permissions with an SSH_FXP_SETSTAT packet. Permissions can be set with SSH_FXP_MKDIR but that's not the technique WinSCP is using.

When I updated phpseclib to do what WinSCP does it seemed to work better:

https://github.com/terrafrost/phpseclib/tree/2.0-mkdir-mode-adjustment

So I guess try that branch and lmk if it works out better for you?

Thanks!

@atanas18
Copy link
Author

Hi there.
Thanks for the update.

Just tried it out.
Well, with default permissions (without changing them) it creates
drwxr--r--
Which differs from when creating with FileZilla (then it's drwxrwsr-x .. so it's somehow getting the default value better).

When set $mode to 2775, it creates them as it should
drwxrwsr-x

This is definitely a better solution and I can call this an update and fix!
Thank you very much.

@terrafrost
Copy link
Member

Just tried it out.
Well, with default permissions (without changing them) it creates
drwxr--r--
Which differs from when creating with FileZilla (then it's drwxrwsr-x .. so it's somehow getting the default value better).

How does WinSCP behave?

FileZilla's logging (Edit -> Settings -> Logging) doesn't provide much insight into what, specifically, it's doing, so it's not super helpful.

In my testing phpseclib appears to be doing the same thing as WinSCP, now, but if it isn't, for you, then maybe you could provide me with the log files to do further analysis!

@atanas18
Copy link
Author

Hi.
Unfortunately, I don't have Win PC to test with WinSCP right now.

In FileZilla you can add more output to the logging, by enabling the Debug (in Debug Menu right after Logging), and choose appropriate level.
Overall, this is what's doing:

08:56:41 Status: Creating directory '/data/public/articles/x'...
08:56:41 Trace: CControlSocket::SendNextCommand()
08:56:41 Trace: CSftpMkdirOpData::Send() in state 0
08:56:41 Trace: CSftpMkdirOpData::Send() in state 2
08:56:41 Command: mkdir "x"
08:56:41 Response: mkdir /data/public/articles/x: OK
08:56:41 Trace: CSftpMkdirOpData::ParseResponse() in state 2
08:56:41 Trace: CControlSocket::ResetOperation(0)
08:56:41 Trace: CSftpMkdirOpData::Reset(0) in state 2

Another thing which might help is probably to specify the right umask we have.
/etc/pam.d/sshd contains this lines at the end:

#UMask for chrooted SFTP users
session optional pam_umask.so umask=002

@terrafrost
Copy link
Member

08:56:41 Command: mkdir "x"
08:56:41 Response: mkdir /data/public/articles/x: OK

Unfortunately, that doesn't tell me what exactly it's doing whereas WinSCP's logs would.

Installing PuTTY's psftp on Linux would do the trick too. eg. do sudo apt-get install putty-tools and then you should be able to do psftp. psftp -pw pass -sshlog test.log user@website.tld will enable logging.

Thanks!

@atanas18
Copy link
Author

atanas18 commented Apr 1, 2020

Hi.

below is the log attached ..
test.log

There has been some "ls" and "cd path" commands before the actual mkdir.
Mainly the mkdir is made when inside /data/public/articles ... and the new directory which was made is 8 ... then the session is closed.
Hope you will get it.

@terrafrost
Copy link
Member

Did psftp create the directory with the umask permissions?

It looks like psftp is doing pretty much exactly wht phpsecilb is doing. I extracted the SFTP logs from the PuTTY logs you provided and this is what I'm seeing:

-> NET_SFTP_MKDIR
00000000  00:00:00:17:2f:64:61:74:61:2f:70:75:62:6c:69:63  ..../data/public
00000010  2f:61:72:74:69:63:6c:65:73:2f:38:00:00:00:00     /articles/8....

<- NET_SFTP_STATUS
00000000  00:00:00:00:00:00:00:07:53:75:63:63:65:73:73:00  ........Success.
00000010  00:00:00                                         ...

-> NET_SFTP_REALPATH
00000000  00:00:00:17:2f:64:61:74:61:2f:70:75:62:6c:69:63  ..../data/public
00000010  2f:61:72:74:69:63:6c:65:73:2f:2e                 /articles/.

<- NET_SFTP_NAME
00000000  00:00:00:01:00:00:00:15:2f:64:61:74:61:2f:70:75  ......../data/pu
00000010  62:6c:69:63:2f:61:72:74:69:63:6c:65:73:00:00:00  blic/articles...
00000020  15:2f:64:61:74:61:2f:70:75:62:6c:69:63:2f:61:72  ./data/public/ar
00000030  74:69:63:6c:65:73:00:00:00:00                    ticles....

-> NET_SFTP_OPENDIR
00000000  00:00:00:15:2f:64:61:74:61:2f:70:75:62:6c:69:63  ..../data/public
00000010  2f:61:72:74:69:63:6c:65:73                       /articles

No attributes are being set (as evidenced by the 00:00:00:00 bit of the NET_SFTP_MKDIR packet), which is exactly what phpseclib does (or rather, doesn't do lol)...

@atanas18
Copy link
Author

atanas18 commented Apr 6, 2020

Hi,
yes, the psftp created the directory with the correct permissions.
Not sure what's the difference between the php and psftp in this case as you say they do the same.

Probably it has something to do with

#UMask for chrooted SFTP users
session optional pam_umask.so umask=002

As you see it's not 022 (or 0022 default) ..
Strange :)

@terrafrost
Copy link
Member

Probably it has something to do with

#UMask for chrooted SFTP users
session optional pam_umask.so umask=002

As you see it's not 022 (or 0022 default) ..
Strange :)

I mean, I suppose anything is possible, but I'm just not seeing it.

All phpseclib is sending is "\0\0\0\0" for the attributes part of the MKDIR packet. That's interpreted by the SSH server as a 32-bit integer (4 bytes = 32 bits) of 0. Each bit that is set constitutes a flag. https://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-5 elaborates:

        uint32   flags
        uint64   size           present only if flag SSH_FILEXFER_ATTR_SIZE
        uint32   uid            present only if flag SSH_FILEXFER_ATTR_UIDGID
        uint32   gid            present only if flag SSH_FILEXFER_ATTR_UIDGID
        uint32   permissions    present only if flag SSH_FILEXFER_ATTR_PERMISSIONS
        uint32   atime          present only if flag SSH_FILEXFER_ACMODTIME
        uint32   mtime          present only if flag SSH_FILEXFER_ACMODTIME
        uint32   extended_count present only if flag SSH_FILEXFER_ATTR_EXTENDED
        string   extended_type
        string   extended_data
        ...      more extended data (extended_type - extended_data pairs),
                   so that number of pairs equals extended_count

The fact that it's a 0 means that no flags are being set. As such what the server is doing should be completely immaterial. phpseclib doesn't know and doesn't care.

I mean, if you were explicitly passing the permissions (eg. mkdir('whatever', 2)) then it doesn't seem unreasonable to think that maybe phpseclib was just screwing up the encoding (which it isn't) but in this case we're talking about the scenario where the permissions are not being passed to mkdir.

I had said in an earlier post that I was unable to reproduce the issue locally. I can make another attempt in the next few days. Maybe I'll get lucky and something will occur to me that hadn't occurred to me the first time I tried it out.

In the mean time, would you be up for giving me SFTP access to the server that reproduces the issue? I'll make a second attempt to reproduce the issue, myself, but, like I said, I'm not confident.

If you are willing to give SFTP access you can send the credentials to terrafrost@php.net.

Thanks!

@atanas18
Copy link
Author

atanas18 commented Apr 8, 2020

you have mail :)
happy debugging

@brenard
Copy link

brenard commented May 18, 2020

Hello, same bug here : I try to force mode 2775 on mkdir and the resulting directory created is:
d-wxrwsr-t+ 4 ee ee 4096 May 18 15:51 adm

I should get :
drwsrwsr-x+ 4 ee ee 4096 May 18 15:58 adm

I try to replace 07777 by 0777 as proposed, but it doesn't solve the problem for me. I also try to apply terrafrost@7e67f88 and it doesn't solve my problem too.

Notes:

  • I'm using phpseclib from Debian package (2.0.4-1)
  • I have the same problem if I use chmod after mkdir

@terrafrost
Copy link
Member

terrafrost commented May 19, 2020

In the case of atanas18's issue... here's the resolution to that:

I tried creating directories with phpseclib (test) and FileZilla (New Directory) and they both appear to have the same permissions.

Here's the PHP code I used:

<?php
require __DIR__ . '/vendor/autoload.php';

use phpseclib\Net\SFTP;

$sftp = new SFTP(...);
$sftp->login(...);
$sftp->mkdir('test');

Given that that works I'm thinking the problem is with https://github.com/thephpleague/flysystem-sftp/ .

I can try to play around with flysystem SFTP but since I didn't write it it feels like the people who did might be able to more quickly diagnose the issue!

Anyway @brenard - I'd say: give me SFTP access and I'll see if I can reproduce the issue. I'd try to reproduce it locally, multiple times, without success. You can email the credentials to terrafrost@php.net.

Thanks!

For my reference https://file-permissions.ninja/ is a good site for decoding permission stuff.

@brenard
Copy link

brenard commented May 19, 2020

Thanks for your answer. My SSH host isn't publicly available, so, trying to reproduce my problem on another host, I finally solve my problem: To create a directory with mode 2775, I have to specify mode=02775 (as an octal number, with a leading zero, like with mkdir PHP function):

$sftp -> mkdir('/path/to/dir', 02775);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants