lib9p

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

commit 39912e51561efeca6d0fd179d365ef3ab99eb081
parent c8017f6c77407151e2d758d5f828fe74fed62e2b
Author: Matsuda Kenji <info@mtkn.jp>
Date:   Tue, 27 Aug 2024 17:46:27 +0900

try to negosiate with factotum

Diffstat:
Mauth_test.go | 7++++---
Mcmd/diskfs/main.go | 8+++++++-
Afactotum.go | 64++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mserver.go | 13++++++++-----
Mserver_test.go | 12+++++++-----
5 files changed, 90 insertions(+), 14 deletions(-)

diff --git a/auth_test.go b/auth_test.go @@ -18,7 +18,7 @@ func TestAuth(t *testing.T) { go sOpen(ctx, c, otc) acr, asw := io.Pipe() asr, acw := io.Pipe() - c.s.Auth = func(ctx context.Context, r *request) { + c.s.Auth = func(ctx context.Context, r *request) error { ifcall := r.ifcall.(*TAuth) aqid := Qid{Type: QTAUTH, Vers: 0, Path: ^uint64(0)} r.afid.file = &AuthFile{ @@ -28,8 +28,9 @@ func TestAuth(t *testing.T) { W: acw, R: acr, } - runAuth(ctx, t, r.afid.file.(*AuthFile), asr, asw) + runTestAuth(ctx, t, r.afid.file.(*AuthFile), asr, asw) r.ofcall = &RAuth{Tag: ifcall.Tag, Aqid: aqid} + return nil } atc <- &request{ifcall: &TAuth{Afid: 0, Uname: "kenji"}} ofcall := (<-rc).ofcall @@ -56,7 +57,7 @@ func TestAuth(t *testing.T) { // Dumb state machine... // TODO: return when ctx is canceled -func runAuth(ctx context.Context, t *testing.T, afile *AuthFile, r io.Reader, w io.Writer) { +func runTestAuth(ctx context.Context, t *testing.T, afile *AuthFile, r io.Reader, w io.Writer) { go func() { buf := make([]byte, 10) uname := "kenji" diff --git a/cmd/diskfs/main.go b/cmd/diskfs/main.go @@ -31,6 +31,7 @@ import ( var dFlag = flag.Bool("D", false, "Prints chatty message to the stderr.") var aFlag = flag.String("a", "127.0.0.1", "Address the server listens to.") +var fFlag = flag.String("f", "", "Rpc file of factotum to be used for authentication") var pFlag = flag.Int("p", 5640, "Port number the server listens to.") var PFlag = flag.Int("P", 0, "Enables pprof over http on this port.") var gFlag = flag.Bool("g", false, "Prints goroutin count once per second.") @@ -38,7 +39,7 @@ var gFlag = flag.Bool("g", false, "Prints goroutin count once per second.") func main() { flag.Parse() if flag.NArg() != 1 { - fmt.Fprintf(os.Stderr, "usage: %s [-D] [-P profport] [-a addr] [-p port] root\n", os.Args[0]) + fmt.Fprintf(os.Stderr, "usage: %s [-D] [-P profport] [-f rpcfile] [-a addr] [-p port] root\n", os.Args[0]) os.Exit(1) } if *gFlag { @@ -72,6 +73,11 @@ func main() { if *dFlag { s.Chatty() } + if *fFlag != "" { + if err := lib9p.SetFactotum(s, *fFlag); err != nil { + log.Fatalf("setfactotum: %v", err) + } + } L: for { conn, err := listener.Accept() diff --git a/factotum.go b/factotum.go @@ -0,0 +1,63 @@ +package lib9p + +import ( + "context" + "fmt" + "io" + "log" + "os" +) + +func SetFactotum(s *Server, rpcpath string) error { + s.Auth = func(ctx context.Context, r *request) error { + ifcall := r.ifcall.(*TAuth) // TODO: need assertion? + rpcfile, err := os.OpenFile(rpcpath, os.O_RDWR, 0) + if err != nil { + return fmt.Errorf("openfile: %v", err) + } + cr, sw := io.Pipe() + sr, cw := io.Pipe() + // TODO: close rpcfile. + // TODO: check race condition. Can I ignore? + afile := &AuthFile{ + // TODO: BUG: allocate Qid + Qid: Qid{Type: QTAUTH, Vers: 0, Path: ^uint64(0)}, + Uname: ifcall.Uname, // TODO: need to check. + Aname: ifcall.Aname, + AuthOK: false, + W: cw, + R: cr, + } + r.afid.file = afile + runAuth(ctx, rpcfile, afile, sr, sw) + r.ofcall = &RAuth{Tag: ifcall.Tag, Aqid: afile.Qid} + return nil + } + return nil +} + +func runAuth(ctx context.Context, rpcfile *os.File, afile *AuthFile, r io.Reader, w io.Writer) { + buf := make([]byte, 1024) + for { + n, err := r.Read(buf) + if err != nil { + log.Printf("read from auth channel: %v", err) + } + n, err = rpcfile.Write(buf[:n]) + if err != nil { + log.Printf("write to auth file: %v", err) + } + n, err = rpcfile.Read(buf) + if err != nil { + log.Printf("read from auth file: %v", err) + } + if n >= 4 && string(buf[:4]) == "done" { + afile.AuthOK = true + break + } + n, err = w.Write(buf[:n]) + if err != nil { + log.Printf("write to auth channel: %v", err) + } + } +} +\ No newline at end of file diff --git a/server.go b/server.go @@ -43,7 +43,7 @@ type Server struct { // authenticate via the Read()/Write() calls to request.Afid.file. // Auth should clean up everything it creates when ctx is canceled. // If this is nil, no authentication is performed. - Auth func(ctx context.Context, r *request) + Auth func(ctx context.Context, r *request) error } // NewServer creates a Server. @@ -278,10 +278,13 @@ func sAuth(ctx context.Context, c *conn, rc <-chan *request) { if r.err != nil { setError(r, r.err) } else { - c.s.Auth(ctx, r) - // TODO: should move this code to c.s.Auth? - if rauth, ok := r.ofcall.(*RAuth); ok { - r.afid.qidpath = rauth.Aqid.Path + if err := c.s.Auth(ctx, r); err != nil { + setError(r, fmt.Errorf("auth: %v", err)) + } else { + // TODO: should move this code to c.s.Auth? + if rauth, ok := r.ofcall.(*RAuth); ok { + r.afid.qidpath = rauth.Aqid.Path + } } } select { diff --git a/server_test.go b/server_test.go @@ -177,22 +177,24 @@ func TestSAuth(t *testing.T) { tests := []struct { input *TAuth want Msg - authFunc func(context.Context, *request) + authFunc func(context.Context, *request) error }{ {&TAuth{Afid: NOFID, Uname: "kenji", Aname: ""}, &RError{Ename: errors.New("authentication not required")}, nil}, {&TAuth{Afid: NOFID, Uname: "kenji", Aname: ""}, &RError{Ename: errors.New("NOFID can't be used for afid")}, - func(ctx context.Context, r *request) {}}, + func(ctx context.Context, r *request) error { return nil }}, {&TAuth{Afid: 0, Uname: "kenji", Aname: ""}, &RAuth{Tag: 0, Aqid: Qid{0, 1, 2}}, - func(ctx context.Context, r *request) { + func(ctx context.Context, r *request) error { r.ofcall = &RAuth{Tag: 0, Aqid: Qid{0, 1, 2}} + return nil }}, {&TAuth{Afid: 0, Uname: "kenji", Aname: "fs"}, &RError{Ename: errors.New("no such file system")}, - func(ctx context.Context, r *request) { + func(ctx context.Context, r *request) error { r.ofcall = &RAuth{Tag: 0, Aqid: Qid{0, 1, 2}} + return nil }}, } for i, test := range tests { @@ -267,7 +269,7 @@ func TestSAttach(t *testing.T) { c, rc := setupConn(testfs) c.s.fsmap["fs"] = testfs tc := make(chan *request) - dammyAuth := func(context.Context, *request) {} + dammyAuth := func(context.Context, *request) error { return nil } af := &AuthFile{ Qid: Qid{Type: QTAUTH}, Uname: "kenji",