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

File operations on Windows with Python 3.13 give Permission denied #650

Closed
Tracked by #6166
wRAR opened this issue Oct 18, 2024 · 12 comments · Fixed by #652
Closed
Tracked by #6166

File operations on Windows with Python 3.13 give Permission denied #650

wRAR opened this issue Oct 18, 2024 · 12 comments · Fixed by #652

Comments

@wRAR
Copy link

wRAR commented Oct 18, 2024

Steps to reproduce:

  1. Take the server example from the tutorial and run it (I replaced '' with 127.0.0.1 for simplification but kept the rest).
  2. Run the builtin ftp.exe, issue open localhost 2121, log in with either of the users defined in the server code. Issue dir, so far it works.
  3. Issue get <any existing file>.

What happens:

  • the client says "550 Permission denied"
  • the server doesn't log anything helpful even with the debug log level, except clearly showing that it responded with 550 to RETR.

Same with STOR or APPE (though it looks like it responds "550 File exists" for STOR, even if it doesn't exist).

@giampaolo
Copy link
Owner

That means you can't open that specific file for reading. It's a problem of Windows permissions about that file / directory. You should fix it at system level, either by changing permissions for that specific user or changing the user.

@wRAR
Copy link
Author

wRAR commented Oct 20, 2024

That means you can't open that specific file for reading.

I can.

It's a problem of Windows permissions about that file / directory.

Nope.

Also, I now see how this could be seen as a stupid newbie question, especially as I forgot to specify that the same code works with the same files with Python 3.12 so I'm not surprised that it was quickly closed but please reconsider.

@giampaolo
Copy link
Owner

giampaolo commented Oct 20, 2024

OK then please show your code and also the server logs (or traceback, if any).

@giampaolo giampaolo reopened this Oct 20, 2024
@wRAR
Copy link
Author

wRAR commented Oct 20, 2024

As I said the code is at https://pyftpdlib.readthedocs.io/en/latest/tutorial.html#a-base-ftp-server

The server logs:

INFO:pyftpdlib:concurrency model: async
INFO:pyftpdlib:masquerade (NAT) address: None
INFO:pyftpdlib:passive ports: None
DEBUG:pyftpdlib:poller: 'pyftpdlib.ioloop.Select'
DEBUG:pyftpdlib:authorizer: 'pyftpdlib.authorizers.DummyAuthorizer'
DEBUG:pyftpdlib:handler: 'pyftpdlib.handlers.type'
DEBUG:pyftpdlib:max connections: 256
DEBUG:pyftpdlib:max connections per ip: 5
DEBUG:pyftpdlib:timeout: 300
DEBUG:pyftpdlib:banner: 'pyftpdlib based FTP server ready.'
DEBUG:pyftpdlib:max login attempts: 3
INFO:pyftpdlib:>>> starting FTP server on :::2121, pid=2560 <<<
INFO:pyftpdlib:::1:51618-[] FTP session opened (connect)
DEBUG:pyftpdlib:::1:51618-[] -> 220 pyftpdlib based FTP server ready.
DEBUG:pyftpdlib:::1:51618-[] <- OPTS UTF8 ON
DEBUG:pyftpdlib:::1:51618-[] -> 530 Log in with USER and PASS first.
DEBUG:pyftpdlib:::1:51618-[] <- USER user
DEBUG:pyftpdlib:::1:51618-[] -> 331 Username ok, send password.
DEBUG:pyftpdlib:::1:51618-[user] <- PASS ******
DEBUG:pyftpdlib:::1:51618-[user] -> 230 Login successful.
INFO:pyftpdlib:::1:51618-[user] USER 'user' logged in.
DEBUG:pyftpdlib:::1:51618-[user] <- EPRT |2|::1|51619|
DEBUG:pyftpdlib:::1:51618-[user] -> 200 Active data connection established.
DEBUG:pyftpdlib:::1:51618-[user] <- RETR foo
DEBUG:pyftpdlib:::1:51618-[user] -> 550 Permission denied.
DEBUG:pyftpdlib:[debug] call: close() (<DTPHandler(id=1338375264240, addr='::1:51618', user='user')>)

@giampaolo
Copy link
Owner

giampaolo commented Oct 20, 2024

I don't have a Windows box at the moment, but your error originates from here:

try:
fd = self.run_as_current_user(self.fs.open, file, 'rb')
except (OSError, FilesystemError) as err:
why = _strerror(err)
self.respond(f'550 {why}.')
return

What fails is the open() call, that's why I confirm that my suspicion is that the file path or its directory doesn't have enough permissions for your user. Try to add a raise statement at line 2425 and you should see the full file path + traceback.

@wRAR
Copy link
Author

wRAR commented Oct 21, 2024

  File "C:\Users\wRAR\AppData\Local\Programs\Python\Python313\Lib\site-packages\pyftpdlib\handlers.py", line 2427, in ftp_RETR
    fd = self.run_as_current_user(self.fs.open, file, 'rb')
  File "C:\Users\wRAR\AppData\Local\Programs\Python\Python313\Lib\site-packages\pyftpdlib\handlers.py", line 1971, in run_as_current_user
    return function(*args, **kwargs)
  File "C:\Users\wRAR\AppData\Local\Programs\Python\Python313\Lib\site-packages\pyftpdlib\filesystems.py", line 222, in open
    return open(filename, mode)
PermissionError: [Errno 13] Permission denied: 'C:\\Users\\wRAR\\Documents'

Looks like it tries to open a dir for reading.

I guess I can debug it from here later.

@wRAR
Copy link
Author

wRAR commented Oct 21, 2024

pyftpdlib.filesystems.AbstractedFS("C:\\foo", None).ftpnorm("bar") returns "/bar" on 3.12 but "/" on 3.13, because os.path.isabs("/bar") is True on 3.12 but not on 3.13.

@giampaolo
Copy link
Owner

os.path.isabs("/bar") is True on 3.12 but not on 3.13.

Damn! This is huge in terms of backward compatibility breakage. It's also interesting that this is a cPython ticket from 17 years ago which was fixed very recently.

As for what it concerns pyftpdlib, I'm gonna enable CI tests for python 3.13 and see if they turn red. I hope this is already covered by the test suite. After that we should think about a fix. This definitively breaks everything on Windows.

@giampaolo
Copy link
Owner

I'm gonna enable CI tests for python 3.13 and see if they turn red.

They do (this is good):

giampaolo added a commit that referenced this issue Oct 22, 2024
Fixes #650. 

Starting from Python 3.13, `os.path.isabs("/foo")` on Windows return `False`. This causes many file operations on Windows to fail with "Permission denied". This PR makes `os.path.isabs()` on Windows behave like in Python <= 3.12.
@giampaolo
Copy link
Owner

This should now be fixed. Please confirm it worked if you have the chance.

@wRAR
Copy link
Author

wRAR commented Oct 22, 2024

Thanks! I haven't tried manual tests but the Scrapy tests which failed on Windows+3.13 before don't fail with pyftpdlib master.

@giampaolo
Copy link
Owner

Since this was a critical issue, I've just released pyftpdlib 2.0.1.

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

Successfully merging a pull request may close this issue.

2 participants