summaryrefslogtreecommitdiffstats
path: root/back/cmd/authfs/authfs.go
diff options
context:
space:
mode:
Diffstat (limited to 'back/cmd/authfs/authfs.go')
-rw-r--r--back/cmd/authfs/authfs.go130
1 files changed, 130 insertions, 0 deletions
diff --git a/back/cmd/authfs/authfs.go b/back/cmd/authfs/authfs.go
new file mode 100644
index 0000000..e2a8bf9
--- /dev/null
+++ b/back/cmd/authfs/authfs.go
@@ -0,0 +1,130 @@
+package main
+
+import (
+ "fmt"
+ "path"
+ "sync"
+
+ p9 "github.com/Harvey-OS/ninep/protocol"
+
+ "git.samanthony.xyz/buth/back/auth"
+)
+
+const (
+ _ uint64 = iota
+ rootQidPath
+ usersQidPath
+ sessionsQidPath
+)
+
+type File interface {
+ Qid() (p9.QID, error)
+ // TODO
+}
+
+type Dir interface {
+ File
+ // TODO: walk, create
+}
+
+// Authfs is the root p9.NineServer.
+type Authfs struct {
+ *RootDir
+ *UsersDir
+ *SessionsDir
+
+ mu sync.Mutex // guards below
+ files map[p9.FID]File
+}
+
+func NewAuthfs(rootPath string) (*Authfs, error) {
+ root := NewRootDir()
+ users, err := NewUsersDir(rootPath, root.Version)
+ if err != nil {
+ return nil, err
+ }
+ return &Authfs{
+ root,
+ users,
+ NewSessionsDir(root.Version),
+ sync.Mutex{},
+ make(map[p9.FID]File),
+ }, nil
+}
+
+func (fs *Authfs) Close() {
+ fs.RootDir.Close()
+ fs.UsersDir.Close()
+ fs.SessionsDir.Close()
+}
+
+func (fs *Authfs) Rattach(fid, afid p9.FID, uname, aname string) (p9.QID, error) {
+ if afid != p9.NOFID {
+ return p9.QID{}, fmt.Errorf("authfs: no authentication required")
+ }
+
+ var (
+ f File
+ err error
+ ok bool
+ )
+
+ aname = path.Clean(path.Join("/", aname))
+ dir, file := path.Split(aname)
+ switch dir {
+ case "/":
+ switch file {
+ case "":
+ f = fs.RootDir
+ case "users":
+ f = fs.UsersDir
+ case "sessions":
+ f = fs.SessionsDir
+ default:
+ return p9.QID{}, ErrFileNotExist
+ }
+
+ case "/users/":
+ f, err = fs.UsersDir.Walk(file)
+ if err != nil {
+ return p9.QID{}, err
+ }
+
+ case "/sessions/":
+ sessid, err := auth.ParseSessId(file)
+ if err != nil {
+ return p9.QID{}, err
+ }
+ f, ok = fs.SessionsDir.Get(sessid)
+ if !ok {
+ return p9.QID{}, ErrFileNotExist
+ }
+
+ default:
+ return p9.QID{}, ErrFileNotExist
+ }
+ if f == nil {
+ panic("unreachable")
+ }
+
+ qid, err := f.Qid()
+ if err != nil {
+ return p9.QID{}, err
+ }
+ if err := fs.attach(fid, f); err != nil {
+ return p9.QID{}, err
+ }
+ return qid, nil
+}
+
+func (fs *Authfs) attach(fid p9.FID, f File) error {
+ fs.mu.Lock()
+ defer fs.mu.Unlock()
+
+ if _, exists := fs.files[fid]; exists {
+ return ErrFidExist
+ }
+
+ fs.files[fid] = f
+ return nil
+}