Opendir return an error status when not found

The initial Opendir packet is supposed to repond with an error status if
the directory wasn't found. It was just returning a handle without
checking, now it does a Stat on the path and only returns the handle if
the Stat is successful and it indicates it is a directory, otherwise it
returns an error.
This commit is contained in:
John Eikenberry 2018-05-25 21:47:30 -07:00
parent f01c3557dc
commit 218c0d4148
4 changed files with 27 additions and 3 deletions

View File

@ -4,6 +4,7 @@ import (
"context"
"encoding"
"io"
"os"
"path"
"path/filepath"
"strconv"
@ -172,9 +173,19 @@ func (rs *RequestServer) packetWorker(
case *sshFxpRealpathPacket:
rpkt = cleanPacketPath(pkt)
case *sshFxpOpendirPacket:
request := requestFromPacket(ctx, pkt)
rpkt = request.call(rs.Handlers, pkt)
request.close()
if stat, ok := rpkt.(*sshFxpStatResponse); ok {
if stat.info.IsDir() {
request := requestFromPacket(ctx, pkt)
handle := rs.nextRequest(request)
rpkt = sshFxpHandlePacket{pkt.id(), handle}
} else {
rpkt = statusFromError(pkt, &os.PathError{
Path: request.Filepath, Err: syscall.ENOTDIR})
}
}
case *sshFxpOpenPacket:
request := requestFromPacket(ctx, pkt)
handle := rs.nextRequest(request)

View File

@ -355,6 +355,11 @@ func TestRequestReaddir(t *testing.T) {
_, err := putTestFile(p.cli, fname, fname)
assert.Nil(t, err)
}
_, err := p.cli.ReadDir("/foo_01")
assert.Equal(t, &StatusError{Code: ssh_FX_FAILURE,
msg: " /foo_01: not a directory"}, err)
_, err = p.cli.ReadDir("/does_not_exist")
assert.Equal(t, os.ErrNotExist, err)
di, err := p.cli.ReadDir("/")
assert.Nil(t, err)
assert.Len(t, di, 100)

View File

@ -338,8 +338,10 @@ func requestMethod(p requestPacket) (method string) {
method = "Put"
case *sshFxpReaddirPacket:
method = "List"
case *sshFxpOpenPacket, *sshFxpOpendirPacket:
case *sshFxpOpenPacket:
method = "Open"
case *sshFxpOpendirPacket:
method = "Stat"
case *sshFxpSetstatPacket, *sshFxpFsetstatPacket:
method = "Setstat"
case *sshFxpRenamePacket:

View File

@ -240,6 +240,12 @@ func handlePacket(s *Server, p interface{}) error {
}},
})
case *sshFxpOpendirPacket:
if stat, err := os.Stat(p.Path); err != nil {
return s.sendError(p, err)
} else if !stat.IsDir() {
return s.sendError(p, &os.PathError{
Path: p.Path, Err: syscall.ENOTDIR})
}
return sshFxpOpenPacket{
ID: p.ID,
Path: p.Path,