Skip to content

Error creating/writing public key file on network drive "Bad file descriptor" -- tested on 9.5.0.0 and 9.8.1.0 #2298

New issue

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

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

Already on GitHub? # to your account

Closed
3 tasks done
Saxomania opened this issue Nov 7, 2024 · 3 comments · Fixed by PowerShell/openssh-portable#764
Assignees
Milestone

Comments

@Saxomania
Copy link

Prerequisites

  • Write a descriptive title.
  • Make sure you are able to repro it on the latest version
  • Search the existing issues.

Steps to reproduce

Windows: creating pub/priv key file works on default folder (if you dont enter any path) and for example on D drive (just a local volume) will work but will not work on a mapped network share.

Write rights are there so this should not be problem otherwise it couldnt write into my userprofile folder as well

Expected behavior

ssh-keygen -t ed25519 -C "Test"
Generating public/private ed25519 key pair.
Enter file in which to save the key (C:\Users\username/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in C:\Users\username/.ssh/id_ed25519
Your public key has been saved in C:\Users\username/.ssh/id_ed25519.pub

Actual behavior

ssh-keygen -t ed25519 -C "Test"
Generating public/private ed25519 key pair.
Enter file in which to save the key (C:\Users\username/.ssh/id_ed25519): Q:\documents\key
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in q:\documents\key
Unable to save public key to Q:\\documents\\key.pub: Bad file descriptor

Error details

Q is my mapped home drive on a network share
Documents is a folder inside it and its accessible 

an extract of "set" shows following variables:

HOMEDRIVE=Q:
HOMEPATH=\
HOMESHARE=\\server.domain.de\share\somefoldername\username

Environment data

PS Q:\> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.19041.5007
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.19041.5007
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

Version

9.8.1.0

Visuals

No response

@mgkuhn
Copy link

mgkuhn commented Nov 8, 2024

I can reproduce this.

Creates and leaves an empty key.pub file on the intended network folder.

I suspect the problem is that this fdopen() call fails if path is on a network drive:

        int fd, oerrno;
        FILE *f = NULL;
        int r = SSH_ERR_INTERNAL_ERROR;

        if ((fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1)
                return SSH_ERR_SYSTEM_ERROR;
        if ((f = fdopen(fd, "w")) == NULL) {
                r = SSH_ERR_SYSTEM_ERROR;
                close(fd);
                goto fail;
        }

May be too much paranoid Unix-specific file-opening trickery for Windows libc to handle on a network drive?

@mgkuhn
Copy link

mgkuhn commented Nov 8, 2024

It looks like this has previously been noted elsewhere, judging from e.g. this comment in auth2-pubkeyfile.c:

#ifdef WINDOWS
        /* Windows POSIX adapter does not support fdopen() on open(file)*/
        if ((f = fopen(file, "r")) == NULL) {
[...]
#else  /* !WINDOWS */
        if ((fd = open(file, O_RDONLY|O_NONBLOCK)) == -1) {

I guess the thing to do is to review all uses of fdopen() after open(), and then introduce a proper abstraction for what they actually try to achieve.

@mgkuhn
Copy link

mgkuhn commented Nov 8, 2024

I don't really understand why upstream isn't simply using

        if ((f = fopen(fd, "w")) == NULL)
                return SSH_ERR_SYSTEM_ERROR;

here.

It's not about the flags bits, because according to the Linux fopen() man page and the POSIX standard:

The file descriptor associated with the stream is opened as if by a call to open(2) with the following flags:
| w │ O_WRONLY | O_CREAT | O_TRUNC |

I suspect this is merely done to mask out u+x,go+wx permissions.

@StevenBucher98 StevenBucher98 added this to the vNext milestone Nov 11, 2024
@tgauth tgauth added 2 - In progress Implementation is underway and removed 0 - Backlog labels Nov 15, 2024
@tgauth tgauth added 3 - In Review Implementation complete and removed 2 - In progress Implementation is underway labels Nov 15, 2024
@tgauth tgauth removed the 3 - In Review Implementation complete label Dec 10, 2024
@tgauth tgauth modified the milestones: vNext, V9.8.2.0 Apr 3, 2025
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants