main.go (4332B)
1 // Example: Sub-machine using the first function feature in engine 2 package main 3 4 import ( 5 "context" 6 "encoding/hex" 7 "errors" 8 "flag" 9 "fmt" 10 "os" 11 "path" 12 "crypto/rand" 13 "crypto/sha256" 14 15 testdataloader "github.com/peteole/testdata-loader" 16 17 "git.defalsify.org/vise.git/db" 18 "git.defalsify.org/vise.git/engine" 19 "git.defalsify.org/vise.git/persist" 20 "git.defalsify.org/vise.git/resource" 21 "git.defalsify.org/vise.git/state" 22 "git.defalsify.org/vise.git/logging" 23 fsdb "git.defalsify.org/vise.git/db/fs" 24 ) 25 26 const ( 27 USER_CHALLENGED = iota + state.FLAG_USERSTART 28 USER_FAILED 29 USER_SUCCEEDED 30 ) 31 32 var ( 33 logg = logging.NewVanilla() 34 baseDir = testdataloader.GetBasePath() 35 scriptDir = path.Join(baseDir, "examples", "first") 36 storeDir = path.Join(scriptDir, ".state") 37 authStoreDir = path.Join(scriptDir, ".auth") 38 ) 39 40 type firstAuthResource struct { 41 st *state.State 42 store db.Db 43 } 44 45 func(f *firstAuthResource) challenge(ctx context.Context, sym string, input []byte) (resource.Result, error) { 46 var err error 47 var r resource.Result 48 49 if len(input) == 0 { 50 return r, nil 51 } 52 if input[0] != 0x25 { // % 53 return r, nil 54 } 55 56 sessionId, ok := ctx.Value("SessionId").(string) 57 if !ok { 58 return r, errors.New("missing session") 59 } 60 61 if !f.st.GetFlag(USER_CHALLENGED) { 62 succeed := f.st.GetFlag(USER_SUCCEEDED) 63 failed := f.st.GetFlag(USER_FAILED) 64 if succeed { 65 return r, nil 66 } else { 67 if failed { 68 r.FlagReset = append(r.FlagReset, USER_FAILED) 69 } 70 b := make([]byte, 32) 71 _, err = rand.Read(b) 72 if err != nil { 73 return r, err 74 } 75 f.store.SetPrefix(db.DATATYPE_USERDATA) 76 f.store.SetSession(sessionId) 77 err := f.store.Put(ctx, []byte("challenge"), b) 78 if err != nil { 79 return r, err 80 } 81 r.FlagSet = append(r.FlagSet, USER_CHALLENGED) 82 r.FlagSet = append(r.FlagSet, state.FLAG_TERMINATE) 83 r.Content = hex.EncodeToString(b) 84 return r, nil 85 } 86 } else { 87 logg.DebugCtxf(ctx, "have challenge response", "input", input) 88 f.store.SetPrefix(db.DATATYPE_USERDATA) 89 f.store.SetSession(sessionId) 90 v, err := f.store.Get(ctx, []byte("challenge")) 91 if err != nil { 92 return r, err 93 } 94 h := sha256.New() 95 h.Write([]byte(sessionId)) 96 h.Write(v) 97 b := h.Sum(nil) 98 x := hex.EncodeToString(b) 99 if x != string(input[1:]) { 100 r.FlagSet = append(r.FlagSet, USER_FAILED) 101 r.FlagSet = append(r.FlagSet, state.FLAG_TERMINATE) 102 r.FlagReset = append(r.FlagReset, USER_CHALLENGED) 103 } else { 104 r.FlagSet = append(r.FlagSet, USER_SUCCEEDED) 105 } 106 } 107 return r, nil 108 } 109 110 func main() { 111 var cont bool 112 var sessionId string 113 var input string 114 root := "root" 115 flag.StringVar(&sessionId, "session-id", "default", "session id") 116 flag.Parse() 117 input = flag.Arg(0) 118 fmt.Fprintf(os.Stderr, "starting session at symbol '%s' using resource dir: %s\n", root, scriptDir) 119 120 ctx := context.Background() 121 st := state.NewState(3) 122 st.UseDebug() 123 state.FlagDebugger.Register(USER_CHALLENGED, "AUTHCHALLENGED") 124 state.FlagDebugger.Register(USER_FAILED, "AUTHFAILED") 125 state.FlagDebugger.Register(USER_SUCCEEDED, "AUTHSUCCEEDED") 126 store := fsdb.NewFsDb() 127 err := store.Connect(ctx, scriptDir) 128 if err != nil { 129 panic(err) 130 } 131 stateStore := fsdb.NewFsDb() 132 err = stateStore.Connect(ctx, storeDir) 133 if err != nil { 134 panic(err) 135 } 136 authStore := fsdb.NewFsDb() 137 err = authStore.Connect(ctx, authStoreDir) 138 if err != nil { 139 panic(err) 140 } 141 142 rs := resource.NewDbResource(store) 143 cfg := engine.Config{ 144 Root: "root", 145 SessionId: sessionId, 146 } 147 148 aux := &firstAuthResource{ 149 st: st, 150 store: authStore, 151 } 152 153 pe := persist.NewPersister(stateStore) 154 en := engine.NewEngine(cfg, rs) 155 en = en.WithState(st) 156 en = en.WithFirst(aux.challenge) 157 en = en.WithPersister(pe) 158 err = en.AddValidInput("^%.*") 159 if err != nil { 160 fmt.Fprintf(os.Stderr, "engine inputvalid add fail: %v\n", err) 161 os.Exit(1) 162 } 163 164 cont, err = en.Exec(ctx, []byte(input)) 165 if err != nil { 166 fmt.Fprintf(os.Stderr, "engine init pre fail: %v\n", err) 167 os.Exit(1) 168 } 169 if cont { 170 _, err = en.Exec(ctx, []byte(input)) 171 if err != nil { 172 fmt.Fprintf(os.Stderr, "engine init after fail: %v\n", err) 173 os.Exit(1) 174 } 175 } 176 177 _, err = en.Flush(ctx, os.Stdout) 178 if err != nil { 179 fmt.Fprintf(os.Stderr, "engine finish fail: %v\n", err) 180 os.Exit(1) 181 } 182 183 err = en.Finish() 184 if err != nil { 185 fmt.Fprintf(os.Stderr, "engine finish fail: %v\n", err) 186 os.Exit(1) 187 } 188 }