Repository: rclone/rclone (language: go)

Issue:
[sftp] rclone sftp serve cannot parse authorized_keys file ends with comments
<!--

We understand you are having a problem with rclone; we want to help you with that!

**STOP and READ**
**YOUR POST WILL BE REMOVED IF IT IS LOW QUALITY**:
Please show the effort you've put into solving the problem and please be specific.
People are volunteering their time to help! Low effort posts are not likely to get good answers!

If you think you might have found a bug, try to replicate it with the latest beta (or stable).
The update instructions are available at https://rclone.org/commands/rclone_selfupdate/

If you can still replicate it or just got a question then please use the rclone forum:

    https://forum.rclone.org/

for a quick response instead of filing an issue on this repo.

If nothing else helps, then please fill in the info below which helps us help you.

**DO NOT REDACT** any information except passwords/keys/personal info.

You should use 3 backticks to begin and end your paste to make it readable.

Make sure to include a log obtained with '-vv'.

You can also use '-vv --log-file bug.log' and a service such as https://pastebin.com or https://gist.github.com/

Thank you

The Rclone Developers

-->

#### What is the problem you are having with rclone?

When I tried to run `rclone sftp serve` with authorized_keys below, rclone cannot load the public keys. (`2024/12/04 11:11:05 NOTICE: Loaded 0 authorized keys from "/home/pusnow/.ssh/authorized_keys"`)

```
ssh-ed25519 <MY_PUBLIC_KEY1>
ssh-ed25519 <MY_PUBLIC_KEY2>
ecdsa-sha2-nistp256 <MY_PUBLIC_KEY3>
ssh-ed25519 <MY_PUBLIC_KEY4>
ecdsa-sha2-nistp256 <MY_PUBLIC_KEY5>
# comment
```

Removing the comment temporary fixes the problem.



#### What is your rclone version (output from `rclone version`)

```
rclone v1.68.2-DEV
- os/version: fedora 41 (64 bit)
- os/kernel: 6.11.6-300.fc41.x86_64 (x86_64)
- os/type: linux
- os/arch: amd64
- go/version: go1.23.3
- go/linking: static
- go/tags: none
```


#### Which OS you are using and how many bits (e.g. Windows 7, 64 bit)

Fedora 41, 64bit, x86_64

#### Which cloud storage system are you using? (e.g. Google Drive)

rclone serve sftp

#### The command you were trying to run (e.g. `rclone copy /tmp remote:tmp`)

`rclone serve sftp  $(pwd)`

#### A log from the command with the `-vv` flag (e.g. output from `rclone -vv copy /tmp remote:tmp`)

```
2024/12/04 11:17:46 DEBUG : rclone: Version "v1.68.2-DEV" starting with parameters ["rclone" "-vv" "serve" "sftp" "/home/pusnow"]
2024/12/04 11:17:46 DEBUG : Creating backend with remote "/home/pusnow"
2024/12/04 11:17:46 DEBUG : Using config file from "/home/pusnow/.config/rclone/rclone.conf"
2024/12/04 11:17:46 INFO  : Local file system at /home/pusnow: poll-interval is not supported by this remote
2024/12/04 11:17:46 NOTICE: Loaded 0 authorized keys from "/home/pusnow/.ssh/authorized_keys"
2024/12/04 11:17:46 INFO  : 
Transferred:   	          0 B / 0 B, -, 0 B/s, ETA -
Errors:                 1 (retrying may help)
Elapsed time:         0.0s

2024/12/04 11:17:46 DEBUG : 4 go routines active
2024/12/04 11:17:46 NOTICE: Failed to sftp: no authorization found, use --user/--pass or --authorized-keys or --no-auth or --auth-proxy
```

<!--- Please keep the note below for others who read your bug report. -->

#### How to use GitHub

* Please use the 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to show that you are affected by the same issue.
* Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
* Subscribe to receive notifications on status change and new comments.

[sftp] rclone sftp serve cannot parse authorized_keys file ends with comments
<!--

We understand you are having a problem with rclone; we want to help you with that!

**STOP and READ**
**YOUR POST WILL BE REMOVED IF IT IS LOW QUALITY**:
Please show the effort you've put into solving the problem and please be specific.
People are volunteering their time to help! Low effort posts are not likely to get good answers!

If you think you might have found a bug, try to replicate it with the latest beta (or stable).
The update instructions are available at https://rclone.org/commands/rclone_selfupdate/

If you can still replicate it or just got a question then please use the rclone forum:

    https://forum.rclone.org/

for a quick response instead of filing an issue on this repo.

If nothing else helps, then please fill in the info below which helps us help you.

**DO NOT REDACT** any information except passwords/keys/personal info.

You should use 3 backticks to begin and end your paste to make it readable.

Make sure to include a log obtained with '-vv'.

You can also use '-vv --log-file bug.log' and a service such as https://pastebin.com or https://gist.github.com/

Thank you

The Rclone Developers

-->

#### What is the problem you are having with rclone?

When I tried to run `rclone sftp serve` with authorized_keys below, rclone cannot load the public keys. (`2024/12/04 11:11:05 NOTICE: Loaded 0 authorized keys from "/home/pusnow/.ssh/authorized_keys"`)

```
ssh-ed25519 <MY_PUBLIC_KEY1>
ssh-ed25519 <MY_PUBLIC_KEY2>
ecdsa-sha2-nistp256 <MY_PUBLIC_KEY3>
ssh-ed25519 <MY_PUBLIC_KEY4>
ecdsa-sha2-nistp256 <MY_PUBLIC_KEY5>
# comment
```

Removing the comment temporary fixes the problem.



#### What is your rclone version (output from `rclone version`)

```
rclone v1.68.2-DEV
- os/version: fedora 41 (64 bit)
- os/kernel: 6.11.6-300.fc41.x86_64 (x86_64)
- os/type: linux
- os/arch: amd64
- go/version: go1.23.3
- go/linking: static
- go/tags: none
```


#### Which OS you are using and how many bits (e.g. Windows 7, 64 bit)

Fedora 41, 64bit, x86_64

#### Which cloud storage system are you using? (e.g. Google Drive)

rclone serve sftp

#### The command you were trying to run (e.g. `rclone copy /tmp remote:tmp`)

`rclone serve sftp  $(pwd)`

#### A log from the command with the `-vv` flag (e.g. output from `rclone -vv copy /tmp remote:tmp`)

```
2024/12/04 11:17:46 DEBUG : rclone: Version "v1.68.2-DEV" starting with parameters ["rclone" "-vv" "serve" "sftp" "/home/pusnow"]
2024/12/04 11:17:46 DEBUG : Creating backend with remote "/home/pusnow"
2024/12/04 11:17:46 DEBUG : Using config file from "/home/pusnow/.config/rclone/rclone.conf"
2024/12/04 11:17:46 INFO  : Local file system at /home/pusnow: poll-interval is not supported by this remote
2024/12/04 11:17:46 NOTICE: Loaded 0 authorized keys from "/home/pusnow/.ssh/authorized_keys"
2024/12/04 11:17:46 INFO  : 
Transferred:   	          0 B / 0 B, -, 0 B/s, ETA -
Errors:                 1 (retrying may help)
Elapsed time:         0.0s

2024/12/04 11:17:46 DEBUG : 4 go routines active
2024/12/04 11:17:46 NOTICE: Failed to sftp: no authorization found, use --user/--pass or --authorized-keys or --no-auth or --auth-proxy
```

<!--- Please keep the note below for others who read your bug report. -->

#### How to use GitHub

* Please use the 👍 [reaction](https://blog.github.com/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/) to show that you are affected by the same issue.
* Please don't comment if you have no relevant information to add. It's just extra noise for everyone subscribed to this issue.
* Subscribe to receive notifications on status change and new comments.



Discussion / hints:
Hi. Thank you for the issue report. I think I have it reproduced, and are looking into a fix.

One question, just to confirm:

> NOTICE: Loaded 0 authorized keys from "/home/pusnow/.ssh/authorized_keys"

> Removing the comment temporary fixes the problem.

What does it log when it works? Loaded **5** or **1** authorized keys?


When it works (without the comment), it loads 5 authorized keys:

```
2024/12/04 20:33:02 DEBUG : rclone: Version "v1.68.2-DEV" starting with parameters ["rclone" "-vv" "serve" "sftp" "/home/pusnow"]
2024/12/04 20:33:02 DEBUG : Creating backend with remote "/home/pusnow"
2024/12/04 20:33:02 DEBUG : Using config file from "/home/pusnow/.config/rclone/rclone.conf"
2024/12/04 20:33:02 INFO  : Local file system at /home/pusnow: poll-interval is not supported by this remote
2024/12/04 20:33:02 NOTICE: Loaded 5 authorized keys from "/home/pusnow/.ssh/authorized_keys"
2024/12/04 20:33:02 DEBUG : Loaded private key from "/home/pusnow/.cache/rclone/serve-sftp/id_rsa"
2024/12/04 20:33:02 DEBUG : Loaded private key from "/home/pusnow/.cache/rclone/serve-sftp/id_ecdsa"
2024/12/04 20:33:02 DEBUG : Loaded private key from "/home/pusnow/.cache/rclone/serve-sftp/id_ed25519"
2024/12/04 20:33:02 NOTICE: SFTP server listening on 127.0.0.1:2022
^C
2024/12/04 20:33:05 INFO  : Signal received: interrupt
2024/12/04 20:33:05 INFO  : Exiting...
```
Hi. Thank you for the issue report. I think I have it reproduced, and are looking into a fix.

One question, just to confirm:

> NOTICE: Loaded 0 authorized keys from "/home/pusnow/.ssh/authorized_keys"

> Removing the comment temporary fixes the problem.

What does it log when it works? Loaded **5** or **1** authorized keys?


When it works (without the comment), it loads 5 authorized keys:

```
2024/12/04 20:33:02 DEBUG : rclone: Version "v1.68.2-DEV" starting with parameters ["rclone" "-vv" "serve" "sftp" "/home/pusnow"]
2024/12/04 20:33:02 DEBUG : Creating backend with remote "/home/pusnow"
2024/12/04 20:33:02 DEBUG : Using config file from "/home/pusnow/.config/rclone/rclone.conf"
2024/12/04 20:33:02 INFO  : Local file system at /home/pusnow: poll-interval is not supported by this remote
2024/12/04 20:33:02 NOTICE: Loaded 5 authorized keys from "/home/pusnow/.ssh/authorized_keys"
2024/12/04 20:33:02 DEBUG : Loaded private key from "/home/pusnow/.cache/rclone/serve-sftp/id_rsa"
2024/12/04 20:33:02 DEBUG : Loaded private key from "/home/pusnow/.cache/rclone/serve-sftp/id_ecdsa"
2024/12/04 20:33:02 DEBUG : Loaded private key from "/home/pusnow/.cache/rclone/serve-sftp/id_ed25519"
2024/12/04 20:33:02 NOTICE: SFTP server listening on 127.0.0.1:2022
^C
2024/12/04 20:33:05 INFO  : Signal received: interrupt
2024/12/04 20:33:05 INFO  : Exiting...
```

Fix patch:
diff --git a/cmd/serve/sftp/server.go b/cmd/serve/sftp/server.go
index 843b3c640df9b..44bd28795fdff 100644
--- a/cmd/serve/sftp/server.go
+++ b/cmd/serve/sftp/server.go
@@ -143,8 +143,13 @@ func (s *server) serve() (err error) {
 		authKeysFile := env.ShellExpand(s.opt.AuthorizedKeys)
 		authorizedKeysMap, err = loadAuthorizedKeys(authKeysFile)
 		// If user set the flag away from the default then report an error
-		if err != nil && s.opt.AuthorizedKeys != Opt.AuthorizedKeys {
-			return err
+		if s.opt.AuthorizedKeys != Opt.AuthorizedKeys {
+			if err != nil {
+				return err
+			}
+			if len(authorizedKeysMap) == 0 {
+				return fmt.Errorf("failed to parse authorized keys")
+			}
 		}
 		fs.Logf(nil, "Loaded %d authorized keys from %q", len(authorizedKeysMap), authKeysFile)
 	}
@@ -349,11 +354,10 @@ func loadAuthorizedKeys(authorizedKeysPath string) (authorizedKeysMap map[string
 	authorizedKeysMap = make(map[string]struct{})
 	for len(authorizedKeysBytes) > 0 {
 		pubKey, _, _, rest, err := ssh.ParseAuthorizedKey(authorizedKeysBytes)
-		if err != nil {
-			return nil, fmt.Errorf("failed to parse authorized keys: %w", err)
+		if err == nil {
+			authorizedKeysMap[string(pubKey.Marshal())] = struct{}{}
+			authorizedKeysBytes = bytes.TrimSpace(rest)
 		}
-		authorizedKeysMap[string(pubKey.Marshal())] = struct{}{}
-		authorizedKeysBytes = bytes.TrimSpace(rest)
 	}
 	return authorizedKeysMap, nil
 }


Test patch: