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:
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",