go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

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 }