From 5cac17676a6c2963f21eedae14845b59cd89899b Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 21 Sep 2024 00:32:39 +0100 Subject: [PATCH 01/13] WIP adapt ssh server sketch to urdt setup --- cmd/ssh/main.go | 240 ++++++++++++++++++++++++++++++++++++ internal/storage/storage.go | 4 + 2 files changed, 244 insertions(+) create mode 100644 cmd/ssh/main.go diff --git a/cmd/ssh/main.go b/cmd/ssh/main.go new file mode 100644 index 0000000..f973dff --- /dev/null +++ b/cmd/ssh/main.go @@ -0,0 +1,240 @@ +package main + +import ( + "context" + "flag" + "fmt" + "log" + "net" + "path" + "os" + "sync" + + "golang.org/x/crypto/ssh" + + "git.defalsify.org/vise.git/db" + "git.defalsify.org/vise.git/engine" + "git.defalsify.org/vise.git/logging" + "git.defalsify.org/vise.git/resource" + gdbmdb "git.defalsify.org/vise.git/db/gdbm" + + "git.grassecon.net/urdt/ussd/internal/handlers" + "git.grassecon.net/urdt/ussd/internal/storage" + "git.grassecon.net/urdt/ussd/internal/handlers/ussd" +) + +var ( + wg sync.WaitGroup + auth map[string]string + keyStore db.Db + logg = logging.NewVanilla() + scriptDir = path.Join("services", "registration") +) + +type auther struct { + SessionId string + Ctx context.Context +} + +func(a *auther) Check(conn ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) { + keyStore.SetPrefix(storage.DATATYPE_CUSTOM) + k := append([]byte{0x01}, pubKey.Marshal()...) + v, err := keyStore.Get(a.Ctx, k) + if err != nil { + return nil, err + } + a.SessionId = string(v) + fmt.Fprintf(os.Stderr, "connect: %s\n", a.SessionId) + return nil, nil +} + +func populateAuth() { + auth = make(map[string]string) + pubKey, _, _, rest, err := ssh.ParseAuthorizedKey([]byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCu5rYCxMBsVAL1TEkMQgmElAYEZj5zYDdyHjUxZ6qzHBOZD9GAzdxx9GyQDx2vdYm3329tLH/69ky1YA3nUz8SnJGBD6hC5XrqwN6zo9R9oOHAKTwiPGhey2NTVmheP+9XNHukBnOlkkWOQlpDDvMbWOztaZOWDaA8OIeP0t6qzFqLyelyg65lxzM3BKd7bCmmfzl/64BcP1MotAmB9DUxmY0Wb4Q2hYZfNYBx50Z4xthTgKV+Xoo8CbTduKotIz6hluQGvWdtxlCJQEiZ2f4RYY87JSA6/BAH2fhxuLHMXRpzocJNqARqCWpdcTGSg7bzxbKvTFH9OU4wZtr9ie40OR4zsc1lOBZL0rnp8GLkG8ZmeBQrgEDlmR9TTlz4okgtL+c5TCS37rjZYVjmtGwihws0EL9+wyv2dSQibirklC4wK5eWHKXl5vab19qzw/qRLdoRBK40DxbRKggxA7gqSsKrmrf+z7CuLIz/kxF+169FBLbh1MfBOGdx1awm6aU= lash@furioso")) + if err != nil { + panic(err) + } + auth[string(pubKey.Marshal())] = "+25113243546" + _ = rest +} + +func serve(ch ssh.NewChannel) { + if ch == nil { + return + } + if ch.ChannelType() != "session" { + ch.Reject(ssh.UnknownChannelType, "that is not the channel you are looking for") + return + } + channel, requests, err := ch.Accept() + if err != nil { + panic(err) + } + defer channel.Close() + wg.Add(1) + go func(reqIn <-chan *ssh.Request) { + defer wg.Done() + for req := range reqIn { + req.Reply(req.Type == "shell", nil) + } + _ = requests + }(requests) + + n, err := channel.Write([]byte("foobarbaz\n")) + if err != nil { + panic(err) + } + log.Printf("wrote %d", n) +} + +func sshRun(ctx context.Context, hl *ussd.Handlers) { + running := true + + defer wg.Wait() + + auth := auther{Ctx: ctx} + cfg := ssh.ServerConfig{ + PublicKeyCallback: auth.Check, + } + + privateBytes, err := os.ReadFile("/home/lash/.ssh/id_rsa_tmp") + if err != nil { + log.Fatal("Failed to load private key: ", err) + } + private, err := ssh.ParsePrivateKey(privateBytes) + if err != nil { + log.Fatal("Failed to parse private key: ", err) + } + cfg.AddHostKey(private) + + lst, err := net.Listen("tcp", "0.0.0.0:2022") + if err != nil { + panic(err) + } + + for running { + conn, err := lst.Accept() + if err != nil { + panic(err) + } + + go func(conn net.Conn) { + defer conn.Close() + for true { + srvConn, nC, rC, err := ssh.NewServerConn(conn, &cfg) + if err != nil { + log.Printf("rejected client: %v", err) + } + log.Printf("haveconn %v", srvConn) + + wg.Add(1) + go func() { + ssh.DiscardRequests(rC) + wg.Done() + }() + + for ch := range nC { + serve(ch) + } + } + }(conn) + } +} + +func sshLoadKeys(ctx context.Context, dbDir string) error { + keyStoreFile := path.Join(dbDir, "ssh_authorized_keys.gdbm") + keyStore = gdbmdb.NewGdbmDb() + keyStore.Connect(ctx, keyStoreFile) + pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCu5rYCxMBsVAL1TEkMQgmElAYEZj5zYDdyHjUxZ6qzHBOZD9GAzdxx9GyQDx2vdYm3329tLH/69ky1YA3nUz8SnJGBD6hC5XrqwN6zo9R9oOHAKTwiPGhey2NTVmheP+9XNHukBnOlkkWOQlpDDvMbWOztaZOWDaA8OIeP0t6qzFqLyelyg65lxzM3BKd7bCmmfzl/64BcP1MotAmB9DUxmY0Wb4Q2hYZfNYBx50Z4xthTgKV+Xoo8CbTduKotIz6hluQGvWdtxlCJQEiZ2f4RYY87JSA6/BAH2fhxuLHMXRpzocJNqARqCWpdcTGSg7bzxbKvTFH9OU4wZtr9ie40OR4zsc1lOBZL0rnp8GLkG8ZmeBQrgEDlmR9TTlz4okgtL+c5TCS37rjZYVjmtGwihws0EL9+wyv2dSQibirklC4wK5eWHKXl5vab19qzw/qRLdoRBK40DxbRKggxA7gqSsKrmrf+z7CuLIz/kxF+169FBLbh1MfBOGdx1awm6aU= lash@furioso")) + if err != nil { + return err + } + //auth[string(pubKey.Marshal())] = "+25113243546" + k := append([]byte{0x01}, pubKey.Marshal()...) + keyStore.SetPrefix(storage.DATATYPE_CUSTOM) + return keyStore.Put(ctx, k, []byte("+25113243546")) +} + +func main() { + var dbDir string + var resourceDir string + var size uint + var engineDebug bool + var stateDebug bool + var host string + var port uint + flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") + flag.StringVar(&resourceDir, "resourcedir", path.Join("services", "registration"), "resource dir") + flag.BoolVar(&engineDebug, "engine-debug", false, "use engine debug output") + flag.BoolVar(&stateDebug, "state-debug", false, "use engine debug output") + flag.UintVar(&size, "s", 160, "max size of output") + flag.StringVar(&host, "h", "127.0.0.1", "http host") + flag.UintVar(&port, "p", 7123, "http port") + flag.Parse() + + logg.Infof("start command", "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size) + + ctx := context.Background() + pfp := path.Join(scriptDir, "pp.csv") + + cfg := engine.Config{ + Root: "root", + OutputSize: uint32(size), + FlagCount: uint32(16), + } + if stateDebug { + cfg.StateDebug = true + } + if engineDebug { + cfg.EngineDebug = true + } + + menuStorageService := storage.MenuStorageService{} + rs, err := menuStorageService.GetResource(scriptDir, ctx) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + + err = menuStorageService.EnsureDbDir(dbDir) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + + userdataStore := menuStorageService.GetUserdataDb(dbDir, ctx) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + defer userdataStore.Close() + + dbResource, ok := rs.(*resource.DbResource) + if !ok { + os.Exit(1) + } + + lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) + lhs.WithDataStore(&userdataStore) + + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + + hl, err := lhs.GetHandler() + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + + stateStore, err := menuStorageService.GetStateStore(dbDir, ctx) + if err != nil { + fmt.Fprintf(os.Stderr, err.Error()) + os.Exit(1) + } + defer stateStore.Close() + + sshLoadKeys(ctx, dbDir) + sshRun(ctx, hl) +} diff --git a/internal/storage/storage.go b/internal/storage/storage.go index 53f4392..009819e 100644 --- a/internal/storage/storage.go +++ b/internal/storage/storage.go @@ -5,6 +5,10 @@ import ( "git.defalsify.org/vise.git/persist" ) +const ( + DATATYPE_CUSTOM = 128 +) + type Storage struct { Persister *persist.Persister UserdataDb db.Db From 8dcba67fe922c4a4f90721dc010f398b7070e62c Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 21 Sep 2024 18:49:11 +0100 Subject: [PATCH 02/13] WIP can execute single session, but persister fails in next --- cmd/africastalking/main.go | 11 +- cmd/async/main.go | 11 +- cmd/http/main.go | 9 +- cmd/main.go | 15 +-- cmd/ssh/main.go | 158 +++++++++++++++++++--------- internal/handlers/handlerservice.go | 93 ++++++++-------- internal/storage/storageservice.go | 41 +++++--- 7 files changed, 206 insertions(+), 132 deletions(-) diff --git a/cmd/africastalking/main.go b/cmd/africastalking/main.go index c0db723..3e17d81 100644 --- a/cmd/africastalking/main.go +++ b/cmd/africastalking/main.go @@ -98,21 +98,22 @@ func main() { cfg.EngineDebug = true } - menuStorageService := storage.MenuStorageService{} + resourceDir := scriptDir + menuStorageService := storage.NewMenuStorageService(dbDir, resourceDir) - rs, err := menuStorageService.GetResource(scriptDir, ctx) + rs, err := menuStorageService.GetResource(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - err = menuStorageService.EnsureDbDir(dbDir) + err = menuStorageService.EnsureDbDir() if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - userdataStore := menuStorageService.GetUserdataDb(dbDir, ctx) + userdataStore := menuStorageService.GetUserdataDb(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) @@ -138,7 +139,7 @@ func main() { os.Exit(1) } - stateStore, err := menuStorageService.GetStateStore(dbDir, ctx) + stateStore, err := menuStorageService.GetStateStore(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) diff --git a/cmd/async/main.go b/cmd/async/main.go index 2ff0d1e..8d50e4a 100644 --- a/cmd/async/main.go +++ b/cmd/async/main.go @@ -71,20 +71,21 @@ func main() { cfg.EngineDebug = true } - menuStorageService := storage.MenuStorageService{} - rs, err := menuStorageService.GetResource(scriptDir, ctx) + resourceDir := scriptDir + menuStorageService := storage.NewMenuStorageService(dbDir, resourceDir) + rs, err := menuStorageService.GetResource(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - err = menuStorageService.EnsureDbDir(dbDir) + err = menuStorageService.EnsureDbDir() if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - userdataStore := menuStorageService.GetUserdataDb(dbDir, ctx) + userdataStore := menuStorageService.GetUserdataDb(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) @@ -105,7 +106,7 @@ func main() { os.Exit(1) } - stateStore, err := menuStorageService.GetStateStore(dbDir, ctx) + stateStore, err := menuStorageService.GetStateStore(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) diff --git a/cmd/http/main.go b/cmd/http/main.go index 7b74e19..a9e7d00 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -59,20 +59,21 @@ func main() { cfg.EngineDebug = true } - menuStorageService := storage.MenuStorageService{} - rs, err := menuStorageService.GetResource(scriptDir, ctx) + resourceDir := scriptDir + menuStorageService := storage.NewMenuStorageService(dbDir, resourceDir) + rs, err := menuStorageService.GetResource(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - err = menuStorageService.EnsureDbDir(dbDir) + err = menuStorageService.EnsureDbDir() if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - userdataStore := menuStorageService.GetUserdataDb(dbDir, ctx) + userdataStore := menuStorageService.GetUserdataDb(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) diff --git a/cmd/main.go b/cmd/main.go index 26ffe3a..2a2f896 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -43,27 +43,28 @@ func main() { FlagCount: uint32(16), } - menuStorageService := storage.MenuStorageService{} + resourceDir := scriptDir + menuStorageService := storage.NewMenuStorageService(dbDir, resourceDir) - err := menuStorageService.EnsureDbDir(dbDir) + err := menuStorageService.EnsureDbDir() if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - rs, err := menuStorageService.GetResource(scriptDir, ctx) + rs, err := menuStorageService.GetResource(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - pe, err := menuStorageService.GetPersister(dbDir, ctx) + pe, err := menuStorageService.GetPersister(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - userdatastore := menuStorageService.GetUserdataDb(dbDir, ctx) + userdatastore := menuStorageService.GetUserdataDb(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) @@ -76,8 +77,8 @@ func main() { } lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) - lhs.WithDataStore(&userdatastore) - lhs.WithPersister(pe) + lhs.SetDataStore(&userdatastore) + lhs.SetPersister(pe) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) diff --git a/cmd/ssh/main.go b/cmd/ssh/main.go index f973dff..5728aa6 100644 --- a/cmd/ssh/main.go +++ b/cmd/ssh/main.go @@ -2,6 +2,8 @@ package main import ( "context" + "encoding/hex" + "errors" "flag" "fmt" "log" @@ -16,55 +18,75 @@ import ( "git.defalsify.org/vise.git/engine" "git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/resource" + "git.defalsify.org/vise.git/state" gdbmdb "git.defalsify.org/vise.git/db/gdbm" "git.grassecon.net/urdt/ussd/internal/handlers" "git.grassecon.net/urdt/ussd/internal/storage" - "git.grassecon.net/urdt/ussd/internal/handlers/ussd" ) var ( wg sync.WaitGroup - auth map[string]string keyStore db.Db logg = logging.NewVanilla() scriptDir = path.Join("services", "registration") ) type auther struct { - SessionId string Ctx context.Context + auth map[string]string +} + +func NewAuther(ctx context.Context) *auther { + return &auther{ + Ctx: ctx, + auth: make(map[string]string), + } } func(a *auther) Check(conn ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) { + keyStore.SetLanguage(nil) keyStore.SetPrefix(storage.DATATYPE_CUSTOM) k := append([]byte{0x01}, pubKey.Marshal()...) v, err := keyStore.Get(a.Ctx, k) if err != nil { return nil, err } - a.SessionId = string(v) - fmt.Fprintf(os.Stderr, "connect: %s\n", a.SessionId) + ka := hex.EncodeToString(conn.SessionID()) + va := string(v) + a.auth[ka] = va + fmt.Fprintf(os.Stderr, "connect: %s -> %s\n", ka, v) return nil, nil } -func populateAuth() { - auth = make(map[string]string) - pubKey, _, _, rest, err := ssh.ParseAuthorizedKey([]byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCu5rYCxMBsVAL1TEkMQgmElAYEZj5zYDdyHjUxZ6qzHBOZD9GAzdxx9GyQDx2vdYm3329tLH/69ky1YA3nUz8SnJGBD6hC5XrqwN6zo9R9oOHAKTwiPGhey2NTVmheP+9XNHukBnOlkkWOQlpDDvMbWOztaZOWDaA8OIeP0t6qzFqLyelyg65lxzM3BKd7bCmmfzl/64BcP1MotAmB9DUxmY0Wb4Q2hYZfNYBx50Z4xthTgKV+Xoo8CbTduKotIz6hluQGvWdtxlCJQEiZ2f4RYY87JSA6/BAH2fhxuLHMXRpzocJNqARqCWpdcTGSg7bzxbKvTFH9OU4wZtr9ie40OR4zsc1lOBZL0rnp8GLkG8ZmeBQrgEDlmR9TTlz4okgtL+c5TCS37rjZYVjmtGwihws0EL9+wyv2dSQibirklC4wK5eWHKXl5vab19qzw/qRLdoRBK40DxbRKggxA7gqSsKrmrf+z7CuLIz/kxF+169FBLbh1MfBOGdx1awm6aU= lash@furioso")) - if err != nil { - panic(err) +func(a *auther) FromConn(c *ssh.ServerConn) (string, error) { + if c == nil { + return "", errors.New("nil server conn") } - auth[string(pubKey.Marshal())] = "+25113243546" - _ = rest + if c.Conn == nil { + return "", errors.New("nil underlying conn") + } + return a.Get(c.Conn.SessionID()) } -func serve(ch ssh.NewChannel) { + +func(a *auther) Get(k []byte) (string, error) { + ka := hex.EncodeToString(k) + v, ok := a.auth[ka] + if !ok { + return "", errors.New("not found") + } + return v, nil +} + +// TODO: where should the session id be uniquely embedded +func serve(ctx context.Context, sessionId string, ch ssh.NewChannel, mss *storage.MenuStorageService, lhs *handlers.LocalHandlerService) error { if ch == nil { - return + return errors.New("nil channel") } if ch.ChannelType() != "session" { ch.Reject(ssh.UnknownChannelType, "that is not the channel you are looking for") - return + return errors.New("not a session") } channel, requests, err := ch.Accept() if err != nil { @@ -80,19 +102,65 @@ func serve(ch ssh.NewChannel) { _ = requests }(requests) - n, err := channel.Write([]byte("foobarbaz\n")) + pe, err := mss.GetPersister(ctx) if err != nil { - panic(err) + return fmt.Errorf("cannot get persister: %v", err) } - log.Printf("wrote %d", n) + lhs.SetPersister(pe) + lhs.Cfg.SessionId = sessionId + + hl, err := lhs.GetHandler() + if err != nil { + return fmt.Errorf("cannot get handler: %v", err) + } + + en := lhs.GetEngine() + en = en.WithFirst(hl.Init) + en = en.WithDebug(nil) + defer en.Finish() + + cont, err := en.Exec(ctx, []byte{}) + if err != nil { + return fmt.Errorf("initial engine exec err: %v", err) + } + + var input [state.INPUT_LIMIT]byte + for cont { + c, err := en.Flush(ctx, channel) + if err != nil { + return fmt.Errorf("flush err: %v", err) + } + _, err = channel.Write([]byte{0x0a}) + if err != nil { + return fmt.Errorf("newline err: %v", err) + } + c, err = channel.Read(input[:]) + if err != nil { + return fmt.Errorf("read input fail: %v", err) + } + logg.TraceCtxf(ctx, "input read", "c", c, "input", input[:c-1]) + cont, err = en.Exec(ctx, input[:c-1]) + if err != nil { + return fmt.Errorf("engine exec err: %v", err) + } + logg.TraceCtxf(ctx, "exec cont", "cont", cont, "en", en) + _ = c + } + c, err := en.Flush(ctx, channel) + if err != nil { + return fmt.Errorf("last flush err: %v", err) + } + _ = c + return nil } -func sshRun(ctx context.Context, hl *ussd.Handlers) { +func sshRun(ctx context.Context, mss *storage.MenuStorageService, lhs *handlers.LocalHandlerService) { running := true defer wg.Wait() - auth := auther{Ctx: ctx} + // TODO: must set ServerConn.Conn.SessionId to phone sessionid + auth := NewAuther(ctx) cfg := ssh.ServerConfig{ PublicKeyCallback: auth.Check, } @@ -118,23 +186,31 @@ func sshRun(ctx context.Context, hl *ussd.Handlers) { panic(err) } + go func(conn net.Conn) { defer conn.Close() for true { srvConn, nC, rC, err := ssh.NewServerConn(conn, &cfg) if err != nil { - log.Printf("rejected client: %v", err) + logg.InfoCtxf(ctx, "rejected client", "err", err) + return } - log.Printf("haveconn %v", srvConn) + logg.DebugCtxf(ctx, "ssh client connected", "conn", srvConn) wg.Add(1) go func() { ssh.DiscardRequests(rC) wg.Done() }() - + + sessionId, err := auth.FromConn(srvConn) + if err != nil { + logg.ErrorCtxf(ctx, "Cannot find authentication") + return + } for ch := range nC { - serve(ch) + err = serve(ctx, sessionId, ch, mss, lhs) + logg.ErrorCtxf(ctx, "ssh server finish", "err", err) } } }(conn) @@ -149,7 +225,6 @@ func sshLoadKeys(ctx context.Context, dbDir string) error { if err != nil { return err } - //auth[string(pubKey.Marshal())] = "+25113243546" k := append([]byte{0x01}, pubKey.Marshal()...) keyStore.SetPrefix(storage.DATATYPE_CUSTOM) return keyStore.Put(ctx, k, []byte("+25113243546")) @@ -189,52 +264,37 @@ func main() { cfg.EngineDebug = true } - menuStorageService := storage.MenuStorageService{} - rs, err := menuStorageService.GetResource(scriptDir, ctx) + mss := storage.NewMenuStorageService(dbDir, resourceDir) + rs, err := mss.GetResource(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - err = menuStorageService.EnsureDbDir(dbDir) + err = mss.EnsureDbDir() if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - userdataStore := menuStorageService.GetUserdataDb(dbDir, ctx) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - defer userdataStore.Close() - dbResource, ok := rs.(*resource.DbResource) if !ok { os.Exit(1) } - - lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) - lhs.WithDataStore(&userdataStore) - + userdataStore := mss.GetUserdataDb(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - hl, err := lhs.GetHandler() + lhs, err := handlers.NewLocalHandlerService(pfp, engineDebug, dbResource, cfg, rs) + lhs.SetDataStore(&userdataStore) + + err = sshLoadKeys(ctx, dbDir) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - stateStore, err := menuStorageService.GetStateStore(dbDir, ctx) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - defer stateStore.Close() - - sshLoadKeys(ctx, dbDir) - sshRun(ctx, hl) + sshRun(ctx, mss, lhs) } diff --git a/internal/handlers/handlerservice.go b/internal/handlers/handlerservice.go index 93c5a10..1d6f5fd 100644 --- a/internal/handlers/handlerservice.go +++ b/internal/handlers/handlerservice.go @@ -44,62 +44,63 @@ func NewLocalHandlerService(fp string, debug bool, dbResource *resource.DbResour }, nil } -func (localHandlerService *LocalHandlerService) WithPersister(Pe *persist.Persister) { - localHandlerService.Pe = Pe +func (ls *LocalHandlerService) SetPersister(Pe *persist.Persister) { + ls.Pe = Pe } -func (localHandlerService *LocalHandlerService) WithDataStore(db *db.Db) { - localHandlerService.UserdataStore = db +func (ls *LocalHandlerService) SetDataStore(db *db.Db) { + ls.UserdataStore = db } -func (localHandlerService *LocalHandlerService) GetHandler() (*ussd.Handlers, error) { - ussdHandlers, err := ussd.NewHandlers(localHandlerService.Parser, *localHandlerService.UserdataStore) +func (ls *LocalHandlerService) GetHandler() (*ussd.Handlers, error) { + ussdHandlers, err := ussd.NewHandlers(ls.Parser, *ls.UserdataStore) if err != nil { return nil, err } - ussdHandlers = ussdHandlers.WithPersister(localHandlerService.Pe) - localHandlerService.DbRs.AddLocalFunc("set_language", ussdHandlers.SetLanguage) - localHandlerService.DbRs.AddLocalFunc("create_account", ussdHandlers.CreateAccount) - localHandlerService.DbRs.AddLocalFunc("save_pin", ussdHandlers.SavePin) - localHandlerService.DbRs.AddLocalFunc("verify_pin", ussdHandlers.VerifyPin) - localHandlerService.DbRs.AddLocalFunc("check_identifier", ussdHandlers.CheckIdentifier) - localHandlerService.DbRs.AddLocalFunc("check_account_status", ussdHandlers.CheckAccountStatus) - localHandlerService.DbRs.AddLocalFunc("authorize_account", ussdHandlers.Authorize) - localHandlerService.DbRs.AddLocalFunc("quit", ussdHandlers.Quit) - localHandlerService.DbRs.AddLocalFunc("check_balance", ussdHandlers.CheckBalance) - localHandlerService.DbRs.AddLocalFunc("validate_recipient", ussdHandlers.ValidateRecipient) - localHandlerService.DbRs.AddLocalFunc("transaction_reset", ussdHandlers.TransactionReset) - localHandlerService.DbRs.AddLocalFunc("max_amount", ussdHandlers.MaxAmount) - localHandlerService.DbRs.AddLocalFunc("validate_amount", ussdHandlers.ValidateAmount) - localHandlerService.DbRs.AddLocalFunc("reset_transaction_amount", ussdHandlers.ResetTransactionAmount) - localHandlerService.DbRs.AddLocalFunc("get_recipient", ussdHandlers.GetRecipient) - localHandlerService.DbRs.AddLocalFunc("get_sender", ussdHandlers.GetSender) - localHandlerService.DbRs.AddLocalFunc("get_amount", ussdHandlers.GetAmount) - localHandlerService.DbRs.AddLocalFunc("reset_incorrect", ussdHandlers.ResetIncorrectPin) - localHandlerService.DbRs.AddLocalFunc("save_firstname", ussdHandlers.SaveFirstname) - localHandlerService.DbRs.AddLocalFunc("save_familyname", ussdHandlers.SaveFamilyname) - localHandlerService.DbRs.AddLocalFunc("save_gender", ussdHandlers.SaveGender) - localHandlerService.DbRs.AddLocalFunc("save_location", ussdHandlers.SaveLocation) - localHandlerService.DbRs.AddLocalFunc("save_yob", ussdHandlers.SaveYob) - localHandlerService.DbRs.AddLocalFunc("save_offerings", ussdHandlers.SaveOfferings) - localHandlerService.DbRs.AddLocalFunc("quit_with_balance", ussdHandlers.QuitWithBalance) - localHandlerService.DbRs.AddLocalFunc("reset_account_authorized", ussdHandlers.ResetAccountAuthorized) - localHandlerService.DbRs.AddLocalFunc("reset_allow_update", ussdHandlers.ResetAllowUpdate) - localHandlerService.DbRs.AddLocalFunc("get_profile_info", ussdHandlers.GetProfileInfo) - localHandlerService.DbRs.AddLocalFunc("verify_yob", ussdHandlers.VerifyYob) - localHandlerService.DbRs.AddLocalFunc("reset_incorrect_date_format", ussdHandlers.ResetIncorrectYob) - localHandlerService.DbRs.AddLocalFunc("set_reset_single_edit", ussdHandlers.SetResetSingleEdit) - localHandlerService.DbRs.AddLocalFunc("initiate_transaction", ussdHandlers.InitiateTransaction) - localHandlerService.DbRs.AddLocalFunc("save_temporary_pin", ussdHandlers.SaveTemporaryPin) - localHandlerService.DbRs.AddLocalFunc("verify_new_pin", ussdHandlers.VerifyNewPin) - localHandlerService.DbRs.AddLocalFunc("confirm_pin_change", ussdHandlers.ConfirmPinChange) - localHandlerService.DbRs.AddLocalFunc("quit_with_help", ussdHandlers.QuitWithHelp) + ussdHandlers = ussdHandlers.WithPersister(ls.Pe) + ls.DbRs.AddLocalFunc("set_language", ussdHandlers.SetLanguage) + ls.DbRs.AddLocalFunc("create_account", ussdHandlers.CreateAccount) + ls.DbRs.AddLocalFunc("save_pin", ussdHandlers.SavePin) + ls.DbRs.AddLocalFunc("verify_pin", ussdHandlers.VerifyPin) + ls.DbRs.AddLocalFunc("check_identifier", ussdHandlers.CheckIdentifier) + ls.DbRs.AddLocalFunc("check_account_status", ussdHandlers.CheckAccountStatus) + ls.DbRs.AddLocalFunc("authorize_account", ussdHandlers.Authorize) + ls.DbRs.AddLocalFunc("quit", ussdHandlers.Quit) + ls.DbRs.AddLocalFunc("check_balance", ussdHandlers.CheckBalance) + ls.DbRs.AddLocalFunc("validate_recipient", ussdHandlers.ValidateRecipient) + ls.DbRs.AddLocalFunc("transaction_reset", ussdHandlers.TransactionReset) + ls.DbRs.AddLocalFunc("max_amount", ussdHandlers.MaxAmount) + ls.DbRs.AddLocalFunc("validate_amount", ussdHandlers.ValidateAmount) + ls.DbRs.AddLocalFunc("reset_transaction_amount", ussdHandlers.ResetTransactionAmount) + ls.DbRs.AddLocalFunc("get_recipient", ussdHandlers.GetRecipient) + ls.DbRs.AddLocalFunc("get_sender", ussdHandlers.GetSender) + ls.DbRs.AddLocalFunc("get_amount", ussdHandlers.GetAmount) + ls.DbRs.AddLocalFunc("reset_incorrect", ussdHandlers.ResetIncorrectPin) + ls.DbRs.AddLocalFunc("save_firstname", ussdHandlers.SaveFirstname) + ls.DbRs.AddLocalFunc("save_familyname", ussdHandlers.SaveFamilyname) + ls.DbRs.AddLocalFunc("save_gender", ussdHandlers.SaveGender) + ls.DbRs.AddLocalFunc("save_location", ussdHandlers.SaveLocation) + ls.DbRs.AddLocalFunc("save_yob", ussdHandlers.SaveYob) + ls.DbRs.AddLocalFunc("save_offerings", ussdHandlers.SaveOfferings) + ls.DbRs.AddLocalFunc("quit_with_balance", ussdHandlers.QuitWithBalance) + ls.DbRs.AddLocalFunc("reset_account_authorized", ussdHandlers.ResetAccountAuthorized) + ls.DbRs.AddLocalFunc("reset_allow_update", ussdHandlers.ResetAllowUpdate) + ls.DbRs.AddLocalFunc("get_profile_info", ussdHandlers.GetProfileInfo) + ls.DbRs.AddLocalFunc("verify_yob", ussdHandlers.VerifyYob) + ls.DbRs.AddLocalFunc("reset_incorrect_date_format", ussdHandlers.ResetIncorrectYob) + ls.DbRs.AddLocalFunc("set_reset_single_edit", ussdHandlers.SetResetSingleEdit) + ls.DbRs.AddLocalFunc("initiate_transaction", ussdHandlers.InitiateTransaction) + ls.DbRs.AddLocalFunc("save_temporary_pin", ussdHandlers.SaveTemporaryPin) + ls.DbRs.AddLocalFunc("verify_new_pin", ussdHandlers.VerifyNewPin) + ls.DbRs.AddLocalFunc("confirm_pin_change", ussdHandlers.ConfirmPinChange) + ls.DbRs.AddLocalFunc("quit_with_help", ussdHandlers.QuitWithHelp) return ussdHandlers, nil } -func (localHandlerService *LocalHandlerService) GetEngine() *engine.DefaultEngine { - en := engine.NewEngine(localHandlerService.Cfg, localHandlerService.Rs) - en = en.WithPersister(localHandlerService.Pe) +// TODO: enable setting of sessionId on engine init time +func (ls *LocalHandlerService) GetEngine() *engine.DefaultEngine { + en := engine.NewEngine(ls.Cfg, ls.Rs) + en = en.WithPersister(ls.Pe) return en } diff --git a/internal/storage/storageservice.go b/internal/storage/storageservice.go index a3f50d6..3b622a1 100644 --- a/internal/storage/storageservice.go +++ b/internal/storage/storageservice.go @@ -14,33 +14,42 @@ import ( ) type StorageService interface { - GetPersister(dbDir string, ctx context.Context) (*persist.Persister, error) - GetUserdataDb(dbDir string, ctx context.Context) db.Db - GetResource(resourceDir string, ctx context.Context) (resource.Resource, error) - EnsureDbDir(dbDir string) error + GetPersister(ctx context.Context) (*persist.Persister, error) + GetUserdataDb(ctx context.Context) db.Db + GetResource(ctx context.Context) (resource.Resource, error) + EnsureDbDir() error } -type MenuStorageService struct{} +type MenuStorageService struct{ + dbDir string + resourceDir string +} -func (menuStorageService *MenuStorageService) GetPersister(dbDir string, ctx context.Context) (*persist.Persister, error) { +func NewMenuStorageService(dbDir string, resourceDir string) *MenuStorageService { + return &MenuStorageService{ + dbDir: dbDir, + resourceDir: resourceDir, + } +} + +func (ms *MenuStorageService) GetPersister(ctx context.Context) (*persist.Persister, error) { store := gdbmdb.NewGdbmDb() - storeFile := path.Join(dbDir, "state.gdbm") + storeFile := path.Join(ms.dbDir, "state.gdbm") store.Connect(ctx, storeFile) pr := persist.NewPersister(store) return pr, nil } -func (menuStorageService *MenuStorageService) GetUserdataDb(dbDir string, ctx context.Context) db.Db { +func (ms *MenuStorageService) GetUserdataDb(ctx context.Context) db.Db { store := gdbmdb.NewGdbmDb() - storeFile := path.Join(dbDir, "userdata.gdbm") + storeFile := path.Join(ms.dbDir, "userdata.gdbm") store.Connect(ctx, storeFile) - return store } -func (menuStorageService *MenuStorageService) GetResource(resourceDir string, ctx context.Context) (resource.Resource, error) { +func (ms *MenuStorageService) GetResource(ctx context.Context) (resource.Resource, error) { store := fsdb.NewFsDb() - err := store.Connect(ctx, resourceDir) + err := store.Connect(ctx, ms.resourceDir) if err != nil { return nil, err } @@ -48,15 +57,15 @@ func (menuStorageService *MenuStorageService) GetResource(resourceDir string, ct return rfs, nil } -func (menuStorageService *MenuStorageService) GetStateStore(dbDir string, ctx context.Context) (db.Db, error) { +func (ms *MenuStorageService) GetStateStore(ctx context.Context) (db.Db, error) { store := gdbmdb.NewGdbmDb() - storeFile := path.Join(dbDir, "state.gdbm") + storeFile := path.Join(ms.dbDir, "state.gdbm") store.Connect(ctx, storeFile) return store, nil } -func (menuStorageService *MenuStorageService) EnsureDbDir(dbDir string) error { - err := os.MkdirAll(dbDir, 0700) +func (ms *MenuStorageService) EnsureDbDir() error { + err := os.MkdirAll(ms.dbDir, 0700) if err != nil { return fmt.Errorf("state dir create exited with error: %v\n", err) } From 5ed9d2643bf44c4c2a700663e8f483fef4d84e04 Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 21 Sep 2024 18:56:20 +0100 Subject: [PATCH 03/13] WIP can execute single session, but persister fails in next --- cmd/ssh/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/ssh/main.go b/cmd/ssh/main.go index 5728aa6..649d2ae 100644 --- a/cmd/ssh/main.go +++ b/cmd/ssh/main.go @@ -154,6 +154,7 @@ func serve(ctx context.Context, sessionId string, ch ssh.NewChannel, mss *storag return nil } +// adapted example from crypto/ssh package, NewServerConn doc func sshRun(ctx context.Context, mss *storage.MenuStorageService, lhs *handlers.LocalHandlerService) { running := true From 0813a619b4dddff14aeaf084cc4052a9e7bf369f Mon Sep 17 00:00:00 2001 From: lash Date: Sat, 21 Sep 2024 21:32:02 +0100 Subject: [PATCH 04/13] Add hacky db closer function in ssh --- cmd/ssh/main.go | 147 +++++++++++++++++++---------- internal/storage/storageservice.go | 71 ++++++++++---- 2 files changed, 146 insertions(+), 72 deletions(-) diff --git a/cmd/ssh/main.go b/cmd/ssh/main.go index 649d2ae..ddf2937 100644 --- a/cmd/ssh/main.go +++ b/cmd/ssh/main.go @@ -6,7 +6,6 @@ import ( "errors" "flag" "fmt" - "log" "net" "path" "os" @@ -79,8 +78,8 @@ func(a *auther) Get(k []byte) (string, error) { return v, nil } -// TODO: where should the session id be uniquely embedded -func serve(ctx context.Context, sessionId string, ch ssh.NewChannel, mss *storage.MenuStorageService, lhs *handlers.LocalHandlerService) error { +//func serve(ctx context.Context, sessionId string, ch ssh.NewChannel, mss *storage.MenuStorageService, lhs *handlers.LocalHandlerService) error { +func serve(ctx context.Context, sessionId string, ch ssh.NewChannel, en engine.Engine) error { if ch == nil { return errors.New("nil channel") } @@ -102,23 +101,6 @@ func serve(ctx context.Context, sessionId string, ch ssh.NewChannel, mss *storag _ = requests }(requests) - pe, err := mss.GetPersister(ctx) - if err != nil { - return fmt.Errorf("cannot get persister: %v", err) - } - lhs.SetPersister(pe) - lhs.Cfg.SessionId = sessionId - - hl, err := lhs.GetHandler() - if err != nil { - return fmt.Errorf("cannot get handler: %v", err) - } - - en := lhs.GetEngine() - en = en.WithFirst(hl.Init) - en = en.WithDebug(nil) - defer en.Finish() - cont, err := en.Exec(ctx, []byte{}) if err != nil { return fmt.Errorf("initial engine exec err: %v", err) @@ -154,8 +136,75 @@ func serve(ctx context.Context, sessionId string, ch ssh.NewChannel, mss *storag return nil } +type sshRunner struct { + Ctx context.Context + Cfg engine.Config + FlagFile string + DbDir string + ResourceDir string + Debug bool +} + +func(s *sshRunner) GetEngine(sessionId string) (engine.Engine, func(), error) { + ctx := s.Ctx + menuStorageService := storage.NewMenuStorageService(s.DbDir, s.ResourceDir) + + err := menuStorageService.EnsureDbDir() + if err != nil { + return nil, nil, err + } + + rs, err := menuStorageService.GetResource(ctx) + if err != nil { + return nil, nil, err + } + + pe, err := menuStorageService.GetPersister(ctx) + if err != nil { + return nil, nil, err + } + + userdatastore, err := menuStorageService.GetUserdataDb(ctx) + if err != nil { + return nil, nil, err + } + + dbResource, ok := rs.(*resource.DbResource) + if !ok { + return nil, nil, err + } + + lhs, err := handlers.NewLocalHandlerService(s.FlagFile, true, dbResource, s.Cfg, rs) + lhs.SetDataStore(&userdatastore) + lhs.SetPersister(pe) + lhs.Cfg.SessionId = sessionId + + if err != nil { + return nil, nil, err + } + + hl, err := lhs.GetHandler() + if err != nil { + return nil, nil, err + } + + en := lhs.GetEngine() + en = en.WithFirst(hl.Init) + if s.Debug { + en = en.WithDebug(nil) + } + // TODO: this is getting very hacky! + closer := func() { + err := menuStorageService.Close() + if err != nil { + logg.ErrorCtxf(ctx, "menu storage service cleanup fail", "err", err) + } + } + return en, closer, nil +} + // adapted example from crypto/ssh package, NewServerConn doc -func sshRun(ctx context.Context, mss *storage.MenuStorageService, lhs *handlers.LocalHandlerService) { +func(s *sshRunner) Run(ctx context.Context) {//, mss *storage.MenuStorageService, lhs *handlers.LocalHandlerService) { running := true defer wg.Wait() @@ -168,11 +217,11 @@ func sshRun(ctx context.Context, mss *storage.MenuStorageService, lhs *handlers. privateBytes, err := os.ReadFile("/home/lash/.ssh/id_rsa_tmp") if err != nil { - log.Fatal("Failed to load private key: ", err) + logg.ErrorCtxf(ctx, "Failed to load private key", "err", err) } private, err := ssh.ParsePrivateKey(privateBytes) if err != nil { - log.Fatal("Failed to parse private key: ", err) + logg.ErrorCtxf(ctx, "Failed to parse private key", "err", err) } cfg.AddHostKey(private) @@ -209,8 +258,20 @@ func sshRun(ctx context.Context, mss *storage.MenuStorageService, lhs *handlers. logg.ErrorCtxf(ctx, "Cannot find authentication") return } + en, closer, err := s.GetEngine(sessionId) + if err != nil { + logg.ErrorCtxf(ctx, "engine won't start", "err", err) + return + } + defer func() { + err := en.Finish() + if err != nil { + logg.ErrorCtxf(ctx, "engine won't stop", "err", err) + } + closer() + }() for ch := range nC { - err = serve(ctx, sessionId, ch, mss, lhs) + err = serve(ctx, sessionId, ch, en) logg.ErrorCtxf(ctx, "ssh server finish", "err", err) } } @@ -218,6 +279,7 @@ func sshRun(ctx context.Context, mss *storage.MenuStorageService, lhs *handlers. } } + func sshLoadKeys(ctx context.Context, dbDir string) error { keyStoreFile := path.Join(dbDir, "ssh_authorized_keys.gdbm") keyStore = gdbmdb.NewGdbmDb() @@ -264,38 +326,19 @@ func main() { if engineDebug { cfg.EngineDebug = true } - - mss := storage.NewMenuStorageService(dbDir, resourceDir) - rs, err := mss.GetResource(ctx) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - - err = mss.EnsureDbDir() - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - - dbResource, ok := rs.(*resource.DbResource) - if !ok { - os.Exit(1) - } - userdataStore := mss.GetUserdataDb(ctx) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - - lhs, err := handlers.NewLocalHandlerService(pfp, engineDebug, dbResource, cfg, rs) - lhs.SetDataStore(&userdataStore) - err = sshLoadKeys(ctx, dbDir) + err := sshLoadKeys(ctx, dbDir) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) } - sshRun(ctx, mss, lhs) + runner := &sshRunner{ + Cfg: cfg, + Debug: engineDebug, + FlagFile: pfp, + DbDir: dbDir, + ResourceDir: resourceDir, + } + runner.Run(ctx) } diff --git a/internal/storage/storageservice.go b/internal/storage/storageservice.go index 3b622a1..7cceb4e 100644 --- a/internal/storage/storageservice.go +++ b/internal/storage/storageservice.go @@ -11,8 +11,13 @@ import ( gdbmdb "git.defalsify.org/vise.git/db/gdbm" "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" + "git.defalsify.org/vise.git/logging" ) +var ( + logg = logging.NewVanilla().WithDomain("storage") +) + type StorageService interface { GetPersister(ctx context.Context) (*persist.Persister, error) GetUserdataDb(ctx context.Context) db.Db @@ -23,6 +28,9 @@ type StorageService interface { type MenuStorageService struct{ dbDir string resourceDir string + resourceStore db.Db + stateStore db.Db + userDataStore db.Db } func NewMenuStorageService(dbDir string, resourceDir string) *MenuStorageService { @@ -33,35 +41,48 @@ func NewMenuStorageService(dbDir string, resourceDir string) *MenuStorageService } func (ms *MenuStorageService) GetPersister(ctx context.Context) (*persist.Persister, error) { - store := gdbmdb.NewGdbmDb() + ms.stateStore = gdbmdb.NewGdbmDb() storeFile := path.Join(ms.dbDir, "state.gdbm") - store.Connect(ctx, storeFile) - pr := persist.NewPersister(store) - return pr, nil -} - -func (ms *MenuStorageService) GetUserdataDb(ctx context.Context) db.Db { - store := gdbmdb.NewGdbmDb() - storeFile := path.Join(ms.dbDir, "userdata.gdbm") - store.Connect(ctx, storeFile) - return store -} - -func (ms *MenuStorageService) GetResource(ctx context.Context) (resource.Resource, error) { - store := fsdb.NewFsDb() - err := store.Connect(ctx, ms.resourceDir) + err := ms.stateStore.Connect(ctx, storeFile) if err != nil { return nil, err } - rfs := resource.NewDbResource(store) + pr := persist.NewPersister(ms.stateStore) + logg.TraceCtxf(ctx, "menu storage service", "persist", pr, "store", ms.stateStore) + return pr, nil +} + +func (ms *MenuStorageService) GetUserdataDb(ctx context.Context) (db.Db, error) { + ms.userDataStore = gdbmdb.NewGdbmDb() + storeFile := path.Join(ms.dbDir, "userdata.gdbm") + err := ms.userDataStore.Connect(ctx, storeFile) + if err != nil { + return nil, err + } + return ms.userDataStore, nil +} + +func (ms *MenuStorageService) GetResource(ctx context.Context) (resource.Resource, error) { + ms.resourceStore = fsdb.NewFsDb() + err := ms.resourceStore.Connect(ctx, ms.resourceDir) + if err != nil { + return nil, err + } + rfs := resource.NewDbResource(ms.resourceStore) return rfs, nil } func (ms *MenuStorageService) GetStateStore(ctx context.Context) (db.Db, error) { - store := gdbmdb.NewGdbmDb() + if ms.stateStore != nil { + panic("set up store when already exists") + } + ms.stateStore = gdbmdb.NewGdbmDb() storeFile := path.Join(ms.dbDir, "state.gdbm") - store.Connect(ctx, storeFile) - return store, nil + err := ms.stateStore.Connect(ctx, storeFile) + if err != nil { + return nil, err + } + return ms.stateStore, nil } func (ms *MenuStorageService) EnsureDbDir() error { @@ -71,3 +92,13 @@ func (ms *MenuStorageService) EnsureDbDir() error { } return nil } + +func (ms *MenuStorageService) Close() error { + errA := ms.stateStore.Close() + errB := ms.userDataStore.Close() + errC := ms.resourceStore.Close() + if errA != nil || errB != nil || errC != nil { + return fmt.Errorf("%v %v %v", errA, errB, errC) + } + return nil +} From 78d349ccc769614072c5d447955c42454d4b6c99 Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 22 Sep 2024 02:21:56 +0100 Subject: [PATCH 05/13] Add threaded gdbm wrapper --- cmd/ssh/main.go | 8 ++- internal/storage/gdbm.go | 116 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 internal/storage/gdbm.go diff --git a/cmd/ssh/main.go b/cmd/ssh/main.go index ddf2937..096c870 100644 --- a/cmd/ssh/main.go +++ b/cmd/ssh/main.go @@ -18,7 +18,6 @@ import ( "git.defalsify.org/vise.git/logging" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/state" - gdbmdb "git.defalsify.org/vise.git/db/gdbm" "git.grassecon.net/urdt/ussd/internal/handlers" "git.grassecon.net/urdt/ussd/internal/storage" @@ -282,8 +281,11 @@ func(s *sshRunner) Run(ctx context.Context) {//, mss *storage.MenuStorageService func sshLoadKeys(ctx context.Context, dbDir string) error { keyStoreFile := path.Join(dbDir, "ssh_authorized_keys.gdbm") - keyStore = gdbmdb.NewGdbmDb() - keyStore.Connect(ctx, keyStoreFile) + keyStore = storage.NewThreadGdbmDb() + err := keyStore.Connect(ctx, keyStoreFile) + if err != nil { + return err + } pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCu5rYCxMBsVAL1TEkMQgmElAYEZj5zYDdyHjUxZ6qzHBOZD9GAzdxx9GyQDx2vdYm3329tLH/69ky1YA3nUz8SnJGBD6hC5XrqwN6zo9R9oOHAKTwiPGhey2NTVmheP+9XNHukBnOlkkWOQlpDDvMbWOztaZOWDaA8OIeP0t6qzFqLyelyg65lxzM3BKd7bCmmfzl/64BcP1MotAmB9DUxmY0Wb4Q2hYZfNYBx50Z4xthTgKV+Xoo8CbTduKotIz6hluQGvWdtxlCJQEiZ2f4RYY87JSA6/BAH2fhxuLHMXRpzocJNqARqCWpdcTGSg7bzxbKvTFH9OU4wZtr9ie40OR4zsc1lOBZL0rnp8GLkG8ZmeBQrgEDlmR9TTlz4okgtL+c5TCS37rjZYVjmtGwihws0EL9+wyv2dSQibirklC4wK5eWHKXl5vab19qzw/qRLdoRBK40DxbRKggxA7gqSsKrmrf+z7CuLIz/kxF+169FBLbh1MfBOGdx1awm6aU= lash@furioso")) if err != nil { return err diff --git a/internal/storage/gdbm.go b/internal/storage/gdbm.go new file mode 100644 index 0000000..5b6867c --- /dev/null +++ b/internal/storage/gdbm.go @@ -0,0 +1,116 @@ +package storage + +import ( + "context" + + "git.defalsify.org/vise.git/db" + "git.defalsify.org/vise.git/lang" + gdbmdb "git.defalsify.org/vise.git/db/gdbm" +) + +var ( + dbC map[string]chan db.Db +) + +type ThreadGdbmDb struct { + db db.Db + registered bool + connStr string +} + +func NewThreadGdbmDb() *ThreadGdbmDb { + if dbC == nil { + dbC = make(map[string]chan db.Db) + } + return &ThreadGdbmDb{} +} + +func(tdb *ThreadGdbmDb) Connect(ctx context.Context, connStr string) error { + var ok bool + _, ok = dbC[connStr] + if ok { + logg.WarnCtxf(ctx, "already registered thread gdbm, skipping", "connStr", connStr) + } + gdb := gdbmdb.NewGdbmDb() + err := gdb.Connect(ctx, connStr) + if err != nil { + return err + } + dbC[connStr] = make(chan db.Db, 1) + dbC[connStr]<- gdb + tdb.connStr = connStr + tdb.registered = true + return nil +} + +func(tdb *ThreadGdbmDb) reserve() { + if tdb.db == nil { + tdb.db = <-dbC[tdb.connStr] + } +} + +func(tdb *ThreadGdbmDb) release() { + if tdb.db == nil { + return + } + dbC[tdb.connStr] <- tdb.db + tdb.db = nil +} + +func(tdb *ThreadGdbmDb) SetPrefix(pfx uint8) { + tdb.reserve() + tdb.db.SetPrefix(pfx) +} + +func(tdb *ThreadGdbmDb) SetSession(sessionId string) { + tdb.reserve() + tdb.db.SetSession(sessionId) +} + +func(tdb *ThreadGdbmDb) SetLanguage(lng *lang.Language) { + tdb.reserve() + tdb.db.SetLanguage(lng) +} + +func(tdb *ThreadGdbmDb) Safe() bool { + tdb.reserve() + v := tdb.db.Safe() + tdb.release() + return v +} + +func(tdb *ThreadGdbmDb) Prefix() uint8 { + tdb.reserve() + v := tdb.db.Prefix() + tdb.release() + return v +} + +func(tdb *ThreadGdbmDb) SetLock(typ uint8, locked bool) error { + tdb.reserve() + err := tdb.db.SetLock(typ, locked) + tdb.release() + return err +} + +func(tdb *ThreadGdbmDb) Put(ctx context.Context, key []byte, val []byte) error { + tdb.reserve() + err := tdb.db.Put(ctx, key, val) + tdb.release() + return err +} + +func(tdb *ThreadGdbmDb) Get(ctx context.Context, key []byte) ([]byte, error) { + tdb.reserve() + v, err := tdb.db.Get(ctx, key) + tdb.release() + return v, err +} + +func(tdb *ThreadGdbmDb) Close() error { + tdb.reserve() + close(dbC[tdb.connStr]) + err := tdb.db.Close() + tdb.db = nil + return err +} From 28fc7a0462b82942c6c2c56f00bdd4f69d580089 Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 22 Sep 2024 02:28:00 +0100 Subject: [PATCH 06/13] Implement threaded gdbm in storageservice --- internal/storage/storageservice.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/storage/storageservice.go b/internal/storage/storageservice.go index 7cceb4e..07bccd6 100644 --- a/internal/storage/storageservice.go +++ b/internal/storage/storageservice.go @@ -8,7 +8,6 @@ import ( "git.defalsify.org/vise.git/db" fsdb "git.defalsify.org/vise.git/db/fs" - gdbmdb "git.defalsify.org/vise.git/db/gdbm" "git.defalsify.org/vise.git/persist" "git.defalsify.org/vise.git/resource" "git.defalsify.org/vise.git/logging" @@ -41,7 +40,7 @@ func NewMenuStorageService(dbDir string, resourceDir string) *MenuStorageService } func (ms *MenuStorageService) GetPersister(ctx context.Context) (*persist.Persister, error) { - ms.stateStore = gdbmdb.NewGdbmDb() + ms.stateStore = NewThreadGdbmDb() storeFile := path.Join(ms.dbDir, "state.gdbm") err := ms.stateStore.Connect(ctx, storeFile) if err != nil { @@ -53,7 +52,7 @@ func (ms *MenuStorageService) GetPersister(ctx context.Context) (*persist.Persis } func (ms *MenuStorageService) GetUserdataDb(ctx context.Context) (db.Db, error) { - ms.userDataStore = gdbmdb.NewGdbmDb() + ms.userDataStore = NewThreadGdbmDb() storeFile := path.Join(ms.dbDir, "userdata.gdbm") err := ms.userDataStore.Connect(ctx, storeFile) if err != nil { @@ -76,7 +75,7 @@ func (ms *MenuStorageService) GetStateStore(ctx context.Context) (db.Db, error) if ms.stateStore != nil { panic("set up store when already exists") } - ms.stateStore = gdbmdb.NewGdbmDb() + ms.stateStore = NewThreadGdbmDb() storeFile := path.Join(ms.dbDir, "state.gdbm") err := ms.stateStore.Connect(ctx, storeFile) if err != nil { From 84422684c5d196cc20201c35b445fe9d99466d81 Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 22 Sep 2024 02:33:11 +0100 Subject: [PATCH 07/13] Rehabilitate all executables --- cmd/africastalking/main.go | 6 ++---- cmd/async/main.go | 5 ++--- cmd/http/main.go | 7 +++---- cmd/main.go | 2 +- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/cmd/africastalking/main.go b/cmd/africastalking/main.go index 3e17d81..6c19aa3 100644 --- a/cmd/africastalking/main.go +++ b/cmd/africastalking/main.go @@ -98,9 +98,7 @@ func main() { cfg.EngineDebug = true } - resourceDir := scriptDir menuStorageService := storage.NewMenuStorageService(dbDir, resourceDir) - rs, err := menuStorageService.GetResource(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) @@ -113,7 +111,7 @@ func main() { os.Exit(1) } - userdataStore := menuStorageService.GetUserdataDb(ctx) + userdataStore, err := menuStorageService.GetUserdataDb(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) @@ -126,7 +124,7 @@ func main() { } lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) - lhs.WithDataStore(&userdataStore) + lhs.SetDataStore(&userdataStore) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) diff --git a/cmd/async/main.go b/cmd/async/main.go index 8d50e4a..fbcf9d8 100644 --- a/cmd/async/main.go +++ b/cmd/async/main.go @@ -71,7 +71,6 @@ func main() { cfg.EngineDebug = true } - resourceDir := scriptDir menuStorageService := storage.NewMenuStorageService(dbDir, resourceDir) rs, err := menuStorageService.GetResource(ctx) if err != nil { @@ -85,7 +84,7 @@ func main() { os.Exit(1) } - userdataStore := menuStorageService.GetUserdataDb(ctx) + userdataStore, err := menuStorageService.GetUserdataDb(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) @@ -98,7 +97,7 @@ func main() { } lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) - lhs.WithDataStore(&userdataStore) + lhs.SetDataStore(&userdataStore) hl, err := lhs.GetHandler() if err != nil { diff --git a/cmd/http/main.go b/cmd/http/main.go index a9e7d00..9c24a55 100644 --- a/cmd/http/main.go +++ b/cmd/http/main.go @@ -59,7 +59,6 @@ func main() { cfg.EngineDebug = true } - resourceDir := scriptDir menuStorageService := storage.NewMenuStorageService(dbDir, resourceDir) rs, err := menuStorageService.GetResource(ctx) if err != nil { @@ -73,7 +72,7 @@ func main() { os.Exit(1) } - userdataStore := menuStorageService.GetUserdataDb(ctx) + userdataStore, err := menuStorageService.GetUserdataDb(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) @@ -86,7 +85,7 @@ func main() { } lhs, err := handlers.NewLocalHandlerService(pfp, true, dbResource, cfg, rs) - lhs.WithDataStore(&userdataStore) + lhs.SetDataStore(&userdataStore) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) @@ -99,7 +98,7 @@ func main() { os.Exit(1) } - stateStore, err := menuStorageService.GetStateStore(dbDir, ctx) + stateStore, err := menuStorageService.GetStateStore(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) diff --git a/cmd/main.go b/cmd/main.go index 2a2f896..bd3d634 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -64,7 +64,7 @@ func main() { os.Exit(1) } - userdatastore := menuStorageService.GetUserdataDb(ctx) + userdatastore, err := menuStorageService.GetUserdataDb(ctx) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) From e07f88b3681a6236ea17f15558183466834de618 Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 22 Sep 2024 02:57:10 +0100 Subject: [PATCH 08/13] Settable ssh keyfile, host, port --- cmd/ssh/main.go | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/cmd/ssh/main.go b/cmd/ssh/main.go index 096c870..2741798 100644 --- a/cmd/ssh/main.go +++ b/cmd/ssh/main.go @@ -142,6 +142,9 @@ type sshRunner struct { DbDir string ResourceDir string Debug bool + KeyFile string + Host string + Port uint } func(s *sshRunner) GetEngine(sessionId string) (engine.Engine, func(), error) { @@ -203,18 +206,18 @@ func(s *sshRunner) GetEngine(sessionId string) (engine.Engine, func(), error) { } // adapted example from crypto/ssh package, NewServerConn doc -func(s *sshRunner) Run(ctx context.Context) {//, mss *storage.MenuStorageService, lhs *handlers.LocalHandlerService) { +func(s *sshRunner) Run(ctx context.Context) { running := true + // TODO: waitgroup should probably not be global defer wg.Wait() - // TODO: must set ServerConn.Conn.SessionId to phone sessionid auth := NewAuther(ctx) cfg := ssh.ServerConfig{ PublicKeyCallback: auth.Check, } - privateBytes, err := os.ReadFile("/home/lash/.ssh/id_rsa_tmp") + privateBytes, err := os.ReadFile(s.KeyFile) if err != nil { logg.ErrorCtxf(ctx, "Failed to load private key", "err", err) } @@ -224,7 +227,7 @@ func(s *sshRunner) Run(ctx context.Context) {//, mss *storage.MenuStorageService } cfg.AddHostKey(private) - lst, err := net.Listen("tcp", "0.0.0.0:2022") + lst, err := net.Listen("tcp", fmt.Sprintf("%s:%d", s.Host, s.Port)) if err != nil { panic(err) } @@ -278,7 +281,7 @@ func(s *sshRunner) Run(ctx context.Context) {//, mss *storage.MenuStorageService } } - +// TODO: This is test code, move to external tool for adding and removing keys func sshLoadKeys(ctx context.Context, dbDir string) error { keyStoreFile := path.Join(dbDir, "ssh_authorized_keys.gdbm") keyStore = storage.NewThreadGdbmDb() @@ -309,10 +312,17 @@ func main() { flag.BoolVar(&stateDebug, "state-debug", false, "use engine debug output") flag.UintVar(&size, "s", 160, "max size of output") flag.StringVar(&host, "h", "127.0.0.1", "http host") - flag.UintVar(&port, "p", 7123, "http port") + flag.UintVar(&port, "p", 7122, "http port") flag.Parse() - logg.Infof("start command", "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size) + sshKeyFile := flag.Arg(0) + _, err := os.Stat(sshKeyFile) + if err != nil { + fmt.Fprintf(os.Stderr, "cannot open ssh server private key file: %v\n", err) + os.Exit(1) + } + + logg.Infof("start command", "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size, "keyfile", sshKeyFile, "host", host, "port", port) ctx := context.Background() pfp := path.Join(scriptDir, "pp.csv") @@ -329,7 +339,7 @@ func main() { cfg.EngineDebug = true } - err := sshLoadKeys(ctx, dbDir) + err = sshLoadKeys(ctx, dbDir) if err != nil { fmt.Fprintf(os.Stderr, err.Error()) os.Exit(1) @@ -341,6 +351,9 @@ func main() { FlagFile: pfp, DbDir: dbDir, ResourceDir: resourceDir, + KeyFile: sshKeyFile, + Host: host, + Port: port, } runner.Run(ctx) } From 1cc2f58ab3f5865b9a170293c14c45375b77a4a5 Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 22 Sep 2024 03:03:03 +0100 Subject: [PATCH 09/13] Remove ssh --- cmd/ssh/main.go | 359 ------------------------------------------------ 1 file changed, 359 deletions(-) delete mode 100644 cmd/ssh/main.go diff --git a/cmd/ssh/main.go b/cmd/ssh/main.go deleted file mode 100644 index 2741798..0000000 --- a/cmd/ssh/main.go +++ /dev/null @@ -1,359 +0,0 @@ -package main - -import ( - "context" - "encoding/hex" - "errors" - "flag" - "fmt" - "net" - "path" - "os" - "sync" - - "golang.org/x/crypto/ssh" - - "git.defalsify.org/vise.git/db" - "git.defalsify.org/vise.git/engine" - "git.defalsify.org/vise.git/logging" - "git.defalsify.org/vise.git/resource" - "git.defalsify.org/vise.git/state" - - "git.grassecon.net/urdt/ussd/internal/handlers" - "git.grassecon.net/urdt/ussd/internal/storage" -) - -var ( - wg sync.WaitGroup - keyStore db.Db - logg = logging.NewVanilla() - scriptDir = path.Join("services", "registration") -) - -type auther struct { - Ctx context.Context - auth map[string]string -} - -func NewAuther(ctx context.Context) *auther { - return &auther{ - Ctx: ctx, - auth: make(map[string]string), - } -} - -func(a *auther) Check(conn ssh.ConnMetadata, pubKey ssh.PublicKey) (*ssh.Permissions, error) { - keyStore.SetLanguage(nil) - keyStore.SetPrefix(storage.DATATYPE_CUSTOM) - k := append([]byte{0x01}, pubKey.Marshal()...) - v, err := keyStore.Get(a.Ctx, k) - if err != nil { - return nil, err - } - ka := hex.EncodeToString(conn.SessionID()) - va := string(v) - a.auth[ka] = va - fmt.Fprintf(os.Stderr, "connect: %s -> %s\n", ka, v) - return nil, nil -} - -func(a *auther) FromConn(c *ssh.ServerConn) (string, error) { - if c == nil { - return "", errors.New("nil server conn") - } - if c.Conn == nil { - return "", errors.New("nil underlying conn") - } - return a.Get(c.Conn.SessionID()) -} - - -func(a *auther) Get(k []byte) (string, error) { - ka := hex.EncodeToString(k) - v, ok := a.auth[ka] - if !ok { - return "", errors.New("not found") - } - return v, nil -} - -//func serve(ctx context.Context, sessionId string, ch ssh.NewChannel, mss *storage.MenuStorageService, lhs *handlers.LocalHandlerService) error { -func serve(ctx context.Context, sessionId string, ch ssh.NewChannel, en engine.Engine) error { - if ch == nil { - return errors.New("nil channel") - } - if ch.ChannelType() != "session" { - ch.Reject(ssh.UnknownChannelType, "that is not the channel you are looking for") - return errors.New("not a session") - } - channel, requests, err := ch.Accept() - if err != nil { - panic(err) - } - defer channel.Close() - wg.Add(1) - go func(reqIn <-chan *ssh.Request) { - defer wg.Done() - for req := range reqIn { - req.Reply(req.Type == "shell", nil) - } - _ = requests - }(requests) - - cont, err := en.Exec(ctx, []byte{}) - if err != nil { - return fmt.Errorf("initial engine exec err: %v", err) - } - - var input [state.INPUT_LIMIT]byte - for cont { - c, err := en.Flush(ctx, channel) - if err != nil { - return fmt.Errorf("flush err: %v", err) - } - _, err = channel.Write([]byte{0x0a}) - if err != nil { - return fmt.Errorf("newline err: %v", err) - } - c, err = channel.Read(input[:]) - if err != nil { - return fmt.Errorf("read input fail: %v", err) - } - logg.TraceCtxf(ctx, "input read", "c", c, "input", input[:c-1]) - cont, err = en.Exec(ctx, input[:c-1]) - if err != nil { - return fmt.Errorf("engine exec err: %v", err) - } - logg.TraceCtxf(ctx, "exec cont", "cont", cont, "en", en) - _ = c - } - c, err := en.Flush(ctx, channel) - if err != nil { - return fmt.Errorf("last flush err: %v", err) - } - _ = c - return nil -} - -type sshRunner struct { - Ctx context.Context - Cfg engine.Config - FlagFile string - DbDir string - ResourceDir string - Debug bool - KeyFile string - Host string - Port uint -} - -func(s *sshRunner) GetEngine(sessionId string) (engine.Engine, func(), error) { - ctx := s.Ctx - menuStorageService := storage.NewMenuStorageService(s.DbDir, s.ResourceDir) - - err := menuStorageService.EnsureDbDir() - if err != nil { - return nil, nil, err - } - - rs, err := menuStorageService.GetResource(ctx) - if err != nil { - return nil, nil, err - } - - pe, err := menuStorageService.GetPersister(ctx) - if err != nil { - return nil, nil, err - } - - userdatastore, err := menuStorageService.GetUserdataDb(ctx) - if err != nil { - return nil, nil, err - } - - dbResource, ok := rs.(*resource.DbResource) - if !ok { - return nil, nil, err - } - - lhs, err := handlers.NewLocalHandlerService(s.FlagFile, true, dbResource, s.Cfg, rs) - lhs.SetDataStore(&userdatastore) - lhs.SetPersister(pe) - lhs.Cfg.SessionId = sessionId - - if err != nil { - return nil, nil, err - } - - hl, err := lhs.GetHandler() - if err != nil { - return nil, nil, err - } - - en := lhs.GetEngine() - en = en.WithFirst(hl.Init) - if s.Debug { - en = en.WithDebug(nil) - } - // TODO: this is getting very hacky! - closer := func() { - err := menuStorageService.Close() - if err != nil { - logg.ErrorCtxf(ctx, "menu storage service cleanup fail", "err", err) - } - } - return en, closer, nil -} - -// adapted example from crypto/ssh package, NewServerConn doc -func(s *sshRunner) Run(ctx context.Context) { - running := true - - // TODO: waitgroup should probably not be global - defer wg.Wait() - - auth := NewAuther(ctx) - cfg := ssh.ServerConfig{ - PublicKeyCallback: auth.Check, - } - - privateBytes, err := os.ReadFile(s.KeyFile) - if err != nil { - logg.ErrorCtxf(ctx, "Failed to load private key", "err", err) - } - private, err := ssh.ParsePrivateKey(privateBytes) - if err != nil { - logg.ErrorCtxf(ctx, "Failed to parse private key", "err", err) - } - cfg.AddHostKey(private) - - lst, err := net.Listen("tcp", fmt.Sprintf("%s:%d", s.Host, s.Port)) - if err != nil { - panic(err) - } - - for running { - conn, err := lst.Accept() - if err != nil { - panic(err) - } - - - go func(conn net.Conn) { - defer conn.Close() - for true { - srvConn, nC, rC, err := ssh.NewServerConn(conn, &cfg) - if err != nil { - logg.InfoCtxf(ctx, "rejected client", "err", err) - return - } - logg.DebugCtxf(ctx, "ssh client connected", "conn", srvConn) - - wg.Add(1) - go func() { - ssh.DiscardRequests(rC) - wg.Done() - }() - - sessionId, err := auth.FromConn(srvConn) - if err != nil { - logg.ErrorCtxf(ctx, "Cannot find authentication") - return - } - en, closer, err := s.GetEngine(sessionId) - if err != nil { - logg.ErrorCtxf(ctx, "engine won't start", "err", err) - return - } - defer func() { - err := en.Finish() - if err != nil { - logg.ErrorCtxf(ctx, "engine won't stop", "err", err) - } - closer() - }() - for ch := range nC { - err = serve(ctx, sessionId, ch, en) - logg.ErrorCtxf(ctx, "ssh server finish", "err", err) - } - } - }(conn) - } -} - -// TODO: This is test code, move to external tool for adding and removing keys -func sshLoadKeys(ctx context.Context, dbDir string) error { - keyStoreFile := path.Join(dbDir, "ssh_authorized_keys.gdbm") - keyStore = storage.NewThreadGdbmDb() - err := keyStore.Connect(ctx, keyStoreFile) - if err != nil { - return err - } - pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQCu5rYCxMBsVAL1TEkMQgmElAYEZj5zYDdyHjUxZ6qzHBOZD9GAzdxx9GyQDx2vdYm3329tLH/69ky1YA3nUz8SnJGBD6hC5XrqwN6zo9R9oOHAKTwiPGhey2NTVmheP+9XNHukBnOlkkWOQlpDDvMbWOztaZOWDaA8OIeP0t6qzFqLyelyg65lxzM3BKd7bCmmfzl/64BcP1MotAmB9DUxmY0Wb4Q2hYZfNYBx50Z4xthTgKV+Xoo8CbTduKotIz6hluQGvWdtxlCJQEiZ2f4RYY87JSA6/BAH2fhxuLHMXRpzocJNqARqCWpdcTGSg7bzxbKvTFH9OU4wZtr9ie40OR4zsc1lOBZL0rnp8GLkG8ZmeBQrgEDlmR9TTlz4okgtL+c5TCS37rjZYVjmtGwihws0EL9+wyv2dSQibirklC4wK5eWHKXl5vab19qzw/qRLdoRBK40DxbRKggxA7gqSsKrmrf+z7CuLIz/kxF+169FBLbh1MfBOGdx1awm6aU= lash@furioso")) - if err != nil { - return err - } - k := append([]byte{0x01}, pubKey.Marshal()...) - keyStore.SetPrefix(storage.DATATYPE_CUSTOM) - return keyStore.Put(ctx, k, []byte("+25113243546")) -} - -func main() { - var dbDir string - var resourceDir string - var size uint - var engineDebug bool - var stateDebug bool - var host string - var port uint - flag.StringVar(&dbDir, "dbdir", ".state", "database dir to read from") - flag.StringVar(&resourceDir, "resourcedir", path.Join("services", "registration"), "resource dir") - flag.BoolVar(&engineDebug, "engine-debug", false, "use engine debug output") - flag.BoolVar(&stateDebug, "state-debug", false, "use engine debug output") - flag.UintVar(&size, "s", 160, "max size of output") - flag.StringVar(&host, "h", "127.0.0.1", "http host") - flag.UintVar(&port, "p", 7122, "http port") - flag.Parse() - - sshKeyFile := flag.Arg(0) - _, err := os.Stat(sshKeyFile) - if err != nil { - fmt.Fprintf(os.Stderr, "cannot open ssh server private key file: %v\n", err) - os.Exit(1) - } - - logg.Infof("start command", "dbdir", dbDir, "resourcedir", resourceDir, "outputsize", size, "keyfile", sshKeyFile, "host", host, "port", port) - - ctx := context.Background() - pfp := path.Join(scriptDir, "pp.csv") - - cfg := engine.Config{ - Root: "root", - OutputSize: uint32(size), - FlagCount: uint32(16), - } - if stateDebug { - cfg.StateDebug = true - } - if engineDebug { - cfg.EngineDebug = true - } - - err = sshLoadKeys(ctx, dbDir) - if err != nil { - fmt.Fprintf(os.Stderr, err.Error()) - os.Exit(1) - } - - runner := &sshRunner{ - Cfg: cfg, - Debug: engineDebug, - FlagFile: pfp, - DbDir: dbDir, - ResourceDir: resourceDir, - KeyFile: sshKeyFile, - Host: host, - Port: port, - } - runner.Run(ctx) -} From a455cfb854ccee0407804ae2f8bda3814b42f893 Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 22 Sep 2024 03:09:53 +0100 Subject: [PATCH 10/13] Return if duplicate connect --- internal/storage/gdbm.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/storage/gdbm.go b/internal/storage/gdbm.go index 5b6867c..7646159 100644 --- a/internal/storage/gdbm.go +++ b/internal/storage/gdbm.go @@ -30,6 +30,7 @@ func(tdb *ThreadGdbmDb) Connect(ctx context.Context, connStr string) error { _, ok = dbC[connStr] if ok { logg.WarnCtxf(ctx, "already registered thread gdbm, skipping", "connStr", connStr) + return nil } gdb := gdbmdb.NewGdbmDb() err := gdb.Connect(ctx, connStr) From 7d3ff690f0d12b9f9d6830c60726669d8c64eb20 Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 22 Sep 2024 03:10:58 +0100 Subject: [PATCH 11/13] Remove useless 'registered' member in thread gdbm --- internal/storage/gdbm.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/internal/storage/gdbm.go b/internal/storage/gdbm.go index 7646159..eb959cf 100644 --- a/internal/storage/gdbm.go +++ b/internal/storage/gdbm.go @@ -14,7 +14,6 @@ var ( type ThreadGdbmDb struct { db db.Db - registered bool connStr string } @@ -40,7 +39,6 @@ func(tdb *ThreadGdbmDb) Connect(ctx context.Context, connStr string) error { dbC[connStr] = make(chan db.Db, 1) dbC[connStr]<- gdb tdb.connStr = connStr - tdb.registered = true return nil } From 8a5209584d665e87d035d85d0c9af298736be51a Mon Sep 17 00:00:00 2001 From: lash Date: Sun, 22 Sep 2024 16:25:04 +0100 Subject: [PATCH 12/13] Update go module deps --- go.mod | 5 ++++- go.sum | 14 ++++++++------ 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/go.mod b/go.mod index 7cceaa6..486f8ee 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,15 @@ module git.grassecon.net/urdt/ussd go 1.22.6 require ( - git.defalsify.org/vise.git v0.1.0-rc.3.0.20240920144308-b2d2c5f18f38 + git.defalsify.org/vise.git v0.1.0-rc.3.0.20240922152136-7ea16f9137b4 github.com/alecthomas/assert/v2 v2.2.2 github.com/peteole/testdata-loader v0.3.0 + golang.org/x/crypto v0.17.0 gopkg.in/leonelquinteros/gotext.v1 v1.3.1 ) +require golang.org/x/sys v0.15.0 // indirect + require ( github.com/alecthomas/participle/v2 v2.0.0 // indirect github.com/alecthomas/repr v0.2.0 // indirect diff --git a/go.sum b/go.sum index 5d235cc..8dfead8 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,5 @@ -git.defalsify.org/vise.git v0.1.0-rc.3.0.20240911231817-0d23e0dbb57f h1:CuJvG3NyMoRtHUim4aZdrfjjJBg2AId7z0yp7Q97bRM= -git.defalsify.org/vise.git v0.1.0-rc.3.0.20240911231817-0d23e0dbb57f/go.mod h1:JDguWmcoWBdsnpw7PUjVZAEpdC/ubBmjdUBy3tjP63M= -git.defalsify.org/vise.git v0.1.0-rc.3.0.20240914163514-577f56f43bea h1:6ZYT+dIjd/f5vn9y5AJDZ7SQQckA6w5ZfUoKygyI11o= -git.defalsify.org/vise.git v0.1.0-rc.3.0.20240914163514-577f56f43bea/go.mod h1:JDguWmcoWBdsnpw7PUjVZAEpdC/ubBmjdUBy3tjP63M= -git.defalsify.org/vise.git v0.1.0-rc.3.0.20240920144308-b2d2c5f18f38 h1:4aAZijIcq33ixnZ+U48ckDIkwSfZL3St/CqoXZcC5K8= -git.defalsify.org/vise.git v0.1.0-rc.3.0.20240920144308-b2d2c5f18f38/go.mod h1:JDguWmcoWBdsnpw7PUjVZAEpdC/ubBmjdUBy3tjP63M= +git.defalsify.org/vise.git v0.1.0-rc.3.0.20240922152136-7ea16f9137b4 h1:IMVUK9OkZ/QtYZPHgTZ+XUs5VQ4eIewIaTyVSCF/nAY= +git.defalsify.org/vise.git v0.1.0-rc.3.0.20240922152136-7ea16f9137b4/go.mod h1:JDguWmcoWBdsnpw7PUjVZAEpdC/ubBmjdUBy3tjP63M= github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g= @@ -32,6 +28,12 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= +golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/leonelquinteros/gotext.v1 v1.3.1 h1:8d9/fdTG0kn/B7NNGV1BsEyvektXFAbkMsTZS2sFSCc= From c02d70eaa4e2825905ec50b60e8bfcf4837e425e Mon Sep 17 00:00:00 2001 From: lash Date: Mon, 23 Sep 2024 17:35:17 +0100 Subject: [PATCH 13/13] Upgrade dep, improve logging --- cmd/async/main.go | 4 ++++ go.mod | 5 +---- go.sum | 10 ++-------- internal/handlers/base.go | 2 +- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/cmd/async/main.go b/cmd/async/main.go index fbcf9d8..b936538 100644 --- a/cmd/async/main.go +++ b/cmd/async/main.go @@ -138,22 +138,26 @@ func main() { for true { rqs, err = sh.Process(rqs) if err != nil { + logg.ErrorCtxf(ctx, "error in process: %v", "err", err) fmt.Errorf("error in process: %v", err) os.Exit(1) } rqs, err = sh.Output(rqs) if err != nil { + logg.ErrorCtxf(ctx, "error in output: %v", "err", err) fmt.Errorf("error in output: %v", err) os.Exit(1) } rqs, err = sh.Reset(rqs) if err != nil { + logg.ErrorCtxf(ctx, "error in reset: %v", "err", err) fmt.Errorf("error in reset: %v", err) os.Exit(1) } fmt.Println("") _, err = fmt.Scanln(&rqs.Input) if err != nil { + logg.ErrorCtxf(ctx, "error in input", "err", err) fmt.Errorf("error in input: %v", err) os.Exit(1) } diff --git a/go.mod b/go.mod index 486f8ee..c4c5167 100644 --- a/go.mod +++ b/go.mod @@ -3,15 +3,12 @@ module git.grassecon.net/urdt/ussd go 1.22.6 require ( - git.defalsify.org/vise.git v0.1.0-rc.3.0.20240922152136-7ea16f9137b4 + git.defalsify.org/vise.git v0.1.0-rc.3.0.20240923162317-c20d557a3dbb github.com/alecthomas/assert/v2 v2.2.2 github.com/peteole/testdata-loader v0.3.0 - golang.org/x/crypto v0.17.0 gopkg.in/leonelquinteros/gotext.v1 v1.3.1 ) -require golang.org/x/sys v0.15.0 // indirect - require ( github.com/alecthomas/participle/v2 v2.0.0 // indirect github.com/alecthomas/repr v0.2.0 // indirect diff --git a/go.sum b/go.sum index 8dfead8..ed5636f 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -git.defalsify.org/vise.git v0.1.0-rc.3.0.20240922152136-7ea16f9137b4 h1:IMVUK9OkZ/QtYZPHgTZ+XUs5VQ4eIewIaTyVSCF/nAY= -git.defalsify.org/vise.git v0.1.0-rc.3.0.20240922152136-7ea16f9137b4/go.mod h1:JDguWmcoWBdsnpw7PUjVZAEpdC/ubBmjdUBy3tjP63M= +git.defalsify.org/vise.git v0.1.0-rc.3.0.20240923162317-c20d557a3dbb h1:6P4kxihcwMjDKzvUFC6t2zGNb7MDW+l/ACGlSAN1N8Y= +git.defalsify.org/vise.git v0.1.0-rc.3.0.20240923162317-c20d557a3dbb/go.mod h1:JDguWmcoWBdsnpw7PUjVZAEpdC/ubBmjdUBy3tjP63M= github.com/alecthomas/assert/v2 v2.2.2 h1:Z/iVC0xZfWTaFNE6bA3z07T86hd45Xe2eLt6WVy2bbk= github.com/alecthomas/assert/v2 v2.2.2/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ= github.com/alecthomas/participle/v2 v2.0.0 h1:Fgrq+MbuSsJwIkw3fEj9h75vDP0Er5JzepJ0/HNHv0g= @@ -28,12 +28,6 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= -golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/leonelquinteros/gotext.v1 v1.3.1 h1:8d9/fdTG0kn/B7NNGV1BsEyvektXFAbkMsTZS2sFSCc= diff --git a/internal/handlers/base.go b/internal/handlers/base.go index aa83e0b..4d2aa4c 100644 --- a/internal/handlers/base.go +++ b/internal/handlers/base.go @@ -46,7 +46,7 @@ func(f *BaseSessionHandler) Process(rqs RequestSession) (RequestSession, error) var err error var ok bool - logg.InfoCtxf(rqs.Ctx, "new request", rqs) + logg.InfoCtxf(rqs.Ctx, "new request", "data", rqs) rqs.Storage, err = f.provider.Get(rqs.Config.SessionId) if err != nil {