mirror of
https://github.com/shadow1ng/fscan.git
synced 2026-09-22 03:10:42 +08:00
102 lines
3.1 KiB
Go
102 lines
3.1 KiB
Go
//go:build plugin_nfs || !plugin_selective
|
|
|
|
package services
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"io"
|
|
"testing"
|
|
)
|
|
|
|
type nfsTestConn struct {
|
|
data []byte
|
|
chunkSize int
|
|
w bytes.Buffer
|
|
}
|
|
|
|
func (c *nfsTestConn) Read(p []byte) (int, error) {
|
|
if len(c.data) == 0 {
|
|
return 0, io.EOF
|
|
}
|
|
n := len(c.data)
|
|
if c.chunkSize > 0 && n > c.chunkSize {
|
|
n = c.chunkSize
|
|
}
|
|
if n > len(p) {
|
|
n = len(p)
|
|
}
|
|
copy(p, c.data[:n])
|
|
c.data = c.data[n:]
|
|
return n, nil
|
|
}
|
|
|
|
func (c *nfsTestConn) Write(p []byte) (int, error) { return c.w.Write(p) }
|
|
|
|
func TestNFSRPCNullCallHandlesFragmentedReads(t *testing.T) {
|
|
p := NewNFSPlugin()
|
|
xid := uint32(0x12340000 + 100003)
|
|
reply := make([]byte, 24)
|
|
binary.BigEndian.PutUint32(reply[0:4], xid)
|
|
binary.BigEndian.PutUint32(reply[4:8], 1)
|
|
|
|
if err := p.rpcNullCall(&nfsTestConn{data: wrapNFSReply(reply), chunkSize: 2}, 100003, 3); err != nil {
|
|
t.Fatalf("rpcNullCall() error = %v", err)
|
|
}
|
|
}
|
|
|
|
func TestNFSGetExportsHandlesVerifierPadding(t *testing.T) {
|
|
p := NewNFSPlugin()
|
|
var reply []byte
|
|
reply = binary.BigEndian.AppendUint32(reply, 0x12345678) // xid
|
|
reply = binary.BigEndian.AppendUint32(reply, 1) // reply
|
|
reply = binary.BigEndian.AppendUint32(reply, 0) // accepted
|
|
reply = binary.BigEndian.AppendUint32(reply, 0) // verifier flavor
|
|
reply = binary.BigEndian.AppendUint32(reply, 3) // verifier length
|
|
reply = append(reply, 'a', 'b', 'c', 0) // padded verifier
|
|
reply = binary.BigEndian.AppendUint32(reply, 0) // accept success
|
|
reply = binary.BigEndian.AppendUint32(reply, 1) // export follows
|
|
reply = binary.BigEndian.AppendUint32(reply, 2) // path length
|
|
reply = append(reply, '/', 'x', 0, 0) // padded path
|
|
reply = binary.BigEndian.AppendUint32(reply, 0) // no groups
|
|
reply = binary.BigEndian.AppendUint32(reply, 0) // no more exports
|
|
|
|
exports, err := p.getExports(&nfsTestConn{data: wrapNFSReply(reply), chunkSize: 3})
|
|
if err != nil {
|
|
t.Fatalf("getExports() error = %v", err)
|
|
}
|
|
if len(exports) != 1 || exports[0] != "/x" {
|
|
t.Fatalf("exports = %#v, want [/x]", exports)
|
|
}
|
|
}
|
|
|
|
func TestNFSReadRPCFragmentRejectsInvalidSize(t *testing.T) {
|
|
header := make([]byte, 4)
|
|
binary.BigEndian.PutUint32(header, 0x80000000)
|
|
if _, err := readRPCFragment(&nfsTestConn{data: header}, 4096); err == nil {
|
|
t.Fatal("readRPCFragment() error = nil, want invalid zero-size fragment error")
|
|
}
|
|
}
|
|
|
|
func TestNFSParseExportListStopsOnTruncatedGroup(t *testing.T) {
|
|
p := NewNFSPlugin()
|
|
var data []byte
|
|
data = binary.BigEndian.AppendUint32(data, 1)
|
|
data = binary.BigEndian.AppendUint32(data, 2)
|
|
data = append(data, '/', 'x', 0, 0)
|
|
data = binary.BigEndian.AppendUint32(data, 1)
|
|
data = binary.BigEndian.AppendUint32(data, 100)
|
|
|
|
exports := p.parseExportList(data)
|
|
if len(exports) != 1 || exports[0] != "/x" {
|
|
t.Fatalf("exports = %#v, want [/x]", exports)
|
|
}
|
|
}
|
|
|
|
func wrapNFSReply(payload []byte) []byte {
|
|
out := make([]byte, 4+len(payload))
|
|
binary.BigEndian.PutUint32(out[:4], uint32(len(payload))|0x80000000)
|
|
copy(out[4:], payload)
|
|
return out
|
|
}
|