lib9p

Go 9P library.
Log | Files | Refs | LICENSE

commit 6fbe899e8c228f2bfacf0b6a917a49c398999a8f
parent 19d4963812366e7de84fc013423db627419bb344
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Wed, 20 Dec 2023 12:40:26 +0900

add auth test

Diffstat:
Mauth.go | 3+--
Mauth_test.go | 90+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mfid.go | 4----
Mserver.go | 37++++++++++++++++++++++++++++---------
4 files changed, 115 insertions(+), 19 deletions(-)

diff --git a/auth.go b/auth.go @@ -22,13 +22,12 @@ func (af *AuthFile) Stat() (fs.FileInfo, error) { } s := Stat{ Qid: af.Qid, - Mode: fs.ModeAppend | fs.ModeExclusive | fs.ModeTemporary, // TODO: right? + Mode: fs.ModeAppend | fs.ModeExclusive | fs.ModeTemporary | 0666, // TODO: right? Name: "auth", Uid: af.Uname, Gid: af.Uname, Muid: af.Uname, } - return &FileInfo{Stat: s}, nil } diff --git a/auth_test.go b/auth_test.go @@ -1,12 +1,94 @@ package lib9p_test -/* + import ( + "context" + "io" "testing" "git.mtkn.jp/lib9p" "git.mtkn.jp/lib9p/client" + "git.mtkn.jp/lib9p/testfs" ) func TestAuth(t *testing.T) { - s := lib9p.NewServer() -}*/ -\ No newline at end of file + const ( + mSize = 8 * 1024 + uname = "kenji" + ) + cr, sw := io.Pipe() + sr, cw := io.Pipe() + defer func() { + cr.Close() + cw.Close() + sr.Close() + sw.Close() + }() + server := lib9p.NewServer(testfs.FS, mSize, sr, sw) + server.Chatty() + acr, asw := io.Pipe() + asr, acw := io.Pipe() + defer func() { + acr.Close() + acw.Close() + asr.Close() + asw.Close() + }() + server.Auth = func(ctx context.Context, r *lib9p.Req) { + ifcall := r.Ifcall.(*lib9p.TAuth) + aqid := lib9p.Qid{Type: lib9p.QTAUTH, Vers: 0, Path: ^uint64(0)} + r.Afid.File = &lib9p.AuthFile{ + Qid: aqid, + Uname: ifcall.Uname, + Aname: ifcall.Aname, + W: acw, + R: acr, + } + runAuth(ctx, t, r.Afid.File.(*lib9p.AuthFile), asr, asw) + r.Ofcall = &lib9p.RAuth{Tag: ifcall.Tag, Aqid: aqid} + lib9p.Respond(ctx, r, nil) + } + clnt := client.NewClient(mSize, uname, cr, cw) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + go server.Serve(ctx) + _, _, err := clnt.Version(ctx, lib9p.NOTAG, mSize, "9P2000") + if err != nil { + t.Log(err) + } + _, err = clnt.Auth(ctx, 0, 0, "kenji", "") + if err != nil { + t.Error(err) + } + _, err = clnt.Attach(ctx, 0, 1, 0, "kenji", "") + if err == nil { + t.Error("authentication skipped") + } + _, _, err = clnt.Open(ctx, 0, 0, lib9p.ORDWR) + if err != nil { + t.Error(err) + } + _, err = clnt.Write(ctx, 0, 0, 0, 5, []byte("kenji")) + if err != nil { + t.Error(err) + } + _, err = clnt.Write(ctx, 0, 0, 0, 8, []byte("password")) + if err != nil { + t.Error(err) + } + _, err = clnt.Attach(ctx, 0, 1, 0, "kenji", "") + if err != nil { + t.Error(err) + } +} + +func runAuth(ctx context.Context, t *testing.T, afile *lib9p.AuthFile, r io.Reader, w io.Writer) { + go func() { + buf := make([]byte, 10) + r.Read(buf) + t.Logf("read username: %s", string(buf)) + r.Read(buf) + t.Logf("read password: %s", string(buf)) + afile.AuthOK = true + t.Log("authenticated") + }() +} +\ No newline at end of file diff --git a/fid.go b/fid.go @@ -64,7 +64,6 @@ func newFidPool() *FidPool { func (pool *FidPool) lookup(fid uint32) (*Fid, bool) { pool.lock.Lock() defer pool.lock.Unlock() - f, ok := pool.m[fid] return f, ok } @@ -72,7 +71,6 @@ func (pool *FidPool) lookup(fid uint32) (*Fid, bool) { func (pool *FidPool) add(fid uint32) (*Fid, error) { pool.lock.Lock() defer pool.lock.Unlock() - if _, ok := pool.m[fid]; ok { return nil, fmt.Errorf("fid already in use.") } @@ -89,8 +87,6 @@ func (pool *FidPool) delete(fid uint32) { } func (pool *FidPool) String() string { - pool.lock.Lock() // TODO: need? - defer pool.lock.Unlock() s := "&FidPool{\n" for fnum, fstruct := range pool.m { if fstruct.File == nil { diff --git a/server.go b/server.go @@ -270,6 +270,7 @@ func sAttach(ctx context.Context, s *Server, r *Req) { } af, ok := afid.File.(*AuthFile) if !ok { + log.Printf("afile: %[1]T, %[1]v", afid.File) Respond(ctx, r, fmt.Errorf("not auth file")) return } @@ -402,16 +403,31 @@ func sOpen(ctx context.Context, s *Server, r *Req) { Respond(ctx, r, ErrBotch) return } - // Write attempt to a directory is prohibitted by the protocol. - // See open(5). - // In plan9 implementation, ifcall.Mode() is ANDed with ^ORCLOSE, - // but ORCLOSE is also prohibitted by the protocol... - st, err := fs.Stat(ExportFS{s.fs}, r.Fid.path) - if err != nil { - Respond(ctx, r, fmt.Errorf("stat: %v", err)) - return + var ( + err error + qid Qid + st fs.FileInfo + ) + if afile, ok := r.Fid.File.(*AuthFile); ok { + // TODO: r.Fid.File should not be nil. + st, err = r.Fid.File.Stat() + if err != nil { + Respond(ctx, r, fmt.Errorf("stat: %v", err)) + return + } + qid = afile.Qid + } else { + // Write attempt to a directory is prohibitted by the protocol. + // See open(5). + // In plan9 implementation, ifcall.Mode() is ANDed with ^ORCLOSE, + // but ORCLOSE is also prohibitted by the protocol... + st, err = fs.Stat(ExportFS{s.fs}, r.Fid.path) + if err != nil { + Respond(ctx, r, fmt.Errorf("stat: %v", err)) + return + } + qid = st.Sys().(*Stat).Qid } - qid := st.Sys().(*Stat).Qid if qid.Type == QTDIR && ifcall.Mode != OREAD { Respond(ctx, r, fmt.Errorf("is a directory")) return @@ -465,6 +481,9 @@ func rOpen(r *Req, err error) { return } r.Fid.OMode = r.Ifcall.(*TOpen).Mode + if _, ok := r.Fid.File.(*AuthFile); ok { + return + } f, err := r.Srv.fs.OpenFile(r.Fid.path, r.Fid.OMode) if err != nil { setError(r, err)