79 lines
2.5 KiB
Go
79 lines
2.5 KiB
Go
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
|
|||
|
|
// SPDX-License-Identifier: MIT
|
||
|
|
|
||
|
|
package rpc
|
||
|
|
|
||
|
|
import (
|
||
|
|
"testing"
|
||
|
|
|
||
|
|
"sourcedock.dev/petrbalvin/nfs/internal/xdr"
|
||
|
|
)
|
||
|
|
|
||
|
|
// The RPCSEC_GSSv3 credential round trips with the version field in
|
||
|
|
// front, RFC 7861 section 5.1.
|
||
|
|
func TestGSSv3CredShape(t *testing.T) {
|
||
|
|
body := AppendGSSv3Cred(nil, GSSProcCreate, 7, SvcPrivacy, []byte("parent"))
|
||
|
|
cred, err := DecodeGSSv3Cred(body)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if cred.Proc != GSSProcCreate || cred.Seq != 7 || cred.Service != SvcPrivacy ||
|
||
|
|
string(cred.Handle) != "parent" {
|
||
|
|
t.Fatalf("cred %+v", cred)
|
||
|
|
}
|
||
|
|
if _, err := DecodeGSSv3Cred(append([]byte{0, 0, 0, 1}, body[4:]...)); err != ErrGSSv3 {
|
||
|
|
t.Fatalf("version one body accepted: %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// The create arguments and reply round trip through their codecs,
|
||
|
|
// including the optional fields and the assertion union.
|
||
|
|
func TestGSSv3CreateShapes(t *testing.T) {
|
||
|
|
args := AppendCreateArgs(nil,
|
||
|
|
&MpAuth{InnerHandle: []byte("inner"), HeaderMic: []byte("mic")},
|
||
|
|
[]byte("binding"),
|
||
|
|
[]Assertion{
|
||
|
|
{Type: AssertionLabel, Label: Label{LfsId: 1, PiId: 2, Bytes: []byte("secret")}},
|
||
|
|
{Type: AssertionPrivs, Privs: Privs{Who: "petr", Grant: "admin", Bytes: []byte("x")}},
|
||
|
|
{Type: 9, Ext: []byte("ext")},
|
||
|
|
})
|
||
|
|
mp, bind, assertions, err := DecodeCreateArgs(args)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if mp == nil || string(mp.InnerHandle) != "inner" || string(mp.HeaderMic) != "mic" {
|
||
|
|
t.Fatalf("mp auth %+v", mp)
|
||
|
|
}
|
||
|
|
if string(bind) != "binding" {
|
||
|
|
t.Fatalf("binding %q", bind)
|
||
|
|
}
|
||
|
|
if len(assertions) != 3 || assertions[0].Label.LfsId != 1 ||
|
||
|
|
assertions[1].Privs.Who != "petr" || assertions[2].Ext == nil {
|
||
|
|
t.Fatalf("assertions %+v", assertions)
|
||
|
|
}
|
||
|
|
|
||
|
|
// The reply mirrors the shape with the child handle.
|
||
|
|
res := AppendCreateRes(nil, []byte("child"), nil, nil,
|
||
|
|
[]Assertion{{Type: AssertionLabel, Label: Label{LfsId: 1, Bytes: []byte("secret")}}})
|
||
|
|
handle, _, _, granted, err := DecodeCreateRes(res)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if string(handle) != "child" || len(granted) != 1 {
|
||
|
|
t.Fatalf("res handle %q granted %d", handle, len(granted))
|
||
|
|
}
|
||
|
|
|
||
|
|
// The list reply carries the type array.
|
||
|
|
list := AppendListRes(nil, []uint32{AssertionLabel, AssertionPrivs})
|
||
|
|
d := xdr.NewDecoder(list)
|
||
|
|
n, err := d.Uint32()
|
||
|
|
if err != nil || n != 2 {
|
||
|
|
t.Fatalf("list count %d: %v", n, err)
|
||
|
|
}
|
||
|
|
t1, _ := d.Uint32()
|
||
|
|
t2, _ := d.Uint32()
|
||
|
|
if t1 != AssertionLabel || t2 != AssertionPrivs {
|
||
|
|
t.Fatalf("list types %d %d", t1, t2)
|
||
|
|
}
|
||
|
|
}
|