mirror of https://github.com/daffainfo/nuclei.git
feat: introduce nucleijs utils
parent
3b5ce39e86
commit
2c2cc2774a
|
@ -16,12 +16,14 @@ var (
|
|||
dir string
|
||||
generatedDir string
|
||||
targetModules string
|
||||
goOnly bool
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.StringVar(&dir, "dir", "libs", "directory to process")
|
||||
flag.StringVar(&generatedDir, "out", "generated", "directory to output generated files")
|
||||
flag.StringVar(&targetModules, "target", "", "target modules to generate")
|
||||
flag.BoolVar(&goOnly, "go", false, "generate only go files")
|
||||
flag.Parse()
|
||||
log.SetFlags(0)
|
||||
if !fileutil.FolderExists(dir) {
|
||||
|
@ -52,10 +54,12 @@ func process() error {
|
|||
}
|
||||
|
||||
prefixed := "lib" + module
|
||||
if !goOnly {
|
||||
err = data.WriteJSTemplate(filepath.Join(generatedDir, "js/"+prefixed), module)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not write js template: %v", err)
|
||||
}
|
||||
}
|
||||
err = data.WriteGoTemplate(path.Join(generatedDir, "go/"+prefixed), module)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not write go template: %v", err)
|
||||
|
|
|
@ -346,6 +346,10 @@ func (d *TemplateData) handleStarExpr(v *ast.StarExpr) string {
|
|||
}
|
||||
|
||||
func (d *TemplateData) collectTypeFromExternal(pkg *types.Package, pkgName, name string) {
|
||||
if pkgName == "goja" {
|
||||
// no need to attempt to collect types from goja ( this is metadata )
|
||||
return
|
||||
}
|
||||
extra := PackageTypeExtra{
|
||||
Fields: make(map[string]string),
|
||||
}
|
||||
|
|
|
@ -15,16 +15,22 @@ func init() {
|
|||
module.Set(
|
||||
gojs.Objects{
|
||||
// Functions
|
||||
"Client": lib_kerberos.NewKerberosClient,
|
||||
|
||||
// Var and consts
|
||||
|
||||
// Types (value type)
|
||||
// "Client": func() lib_kerberos.Client { return lib_kerberos.Client{} },
|
||||
"EnumerateUserResponse": func() lib_kerberos.EnumerateUserResponse { return lib_kerberos.EnumerateUserResponse{} },
|
||||
"KerberosClient": func() lib_kerberos.KerberosClient { return lib_kerberos.KerberosClient{} },
|
||||
"ServiceOptions": func() lib_kerberos.ServiceOptions { return lib_kerberos.ServiceOptions{} },
|
||||
"TGS": func() lib_kerberos.TGS { return lib_kerberos.TGS{} },
|
||||
|
||||
// Types (pointer type)
|
||||
"NewClient": func() *lib_kerberos.Client { return &lib_kerberos.Client{} },
|
||||
"NewEnumerateUserResponse": func() *lib_kerberos.EnumerateUserResponse { return &lib_kerberos.EnumerateUserResponse{} },
|
||||
"NewKerberosClient": func() *lib_kerberos.KerberosClient { return &lib_kerberos.KerberosClient{} },
|
||||
"NewServiceOptions": func() *lib_kerberos.ServiceOptions { return &lib_kerberos.ServiceOptions{} },
|
||||
"NewTGS": func() *lib_kerberos.TGS { return &lib_kerberos.TGS{} },
|
||||
},
|
||||
).Register()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package kerberos
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/dop251/goja"
|
||||
"github.com/projectdiscovery/nuclei/v3/pkg/js/utils"
|
||||
)
|
||||
|
||||
// Updated Package definations and structure
|
||||
type Client struct {
|
||||
nj *utils.NucleiJS // helper functions/bindings
|
||||
}
|
||||
|
||||
// Constructor for KerberosClient
|
||||
// creates client object and can be created using new
|
||||
// var client = new kerberos.Client(domain,controller);
|
||||
func NewKerberosClient(call goja.ConstructorCall, runtime *goja.Runtime) *goja.Object {
|
||||
// setup nucleijs utils
|
||||
c := &Client{nj: utils.NewNucleiJS(runtime)}
|
||||
c.nj.ObjectSig = "Client(domain, controller)" // will be included in error messages
|
||||
|
||||
// get arguments (type assertion is efficient than reflection)
|
||||
// when accepting type as input like net.Conn we can use utils.GetArg
|
||||
domain, _ := c.nj.GetArg(call.Arguments, 0).(string)
|
||||
controller, _ := c.nj.GetArg(call.Arguments, 1).(string)
|
||||
|
||||
// validate arguments
|
||||
c.nj.Require(domain != "", "domain cannot be empty")
|
||||
c.nj.Require(controller != "", "controller cannot be empty")
|
||||
|
||||
// Link Constructor to Client and return
|
||||
return utils.LinkConstructor(call, runtime, c)
|
||||
}
|
||||
|
||||
// EnumerateUserResponse is the response from EnumerateUsers
|
||||
func (c *Client) EnumerateUser(username string) (EnumerateUserResponse, error) {
|
||||
return EnumerateUserResponse{}, nil
|
||||
}
|
||||
|
||||
type ServiceOptions struct {
|
||||
Username string
|
||||
Password string
|
||||
Target string
|
||||
SPN string
|
||||
}
|
||||
|
||||
func (c *Client) GetServiceTicket(sv ServiceOptions) (TGS, error) {
|
||||
fmt.Printf("get service ticket %v\n", sv)
|
||||
return TGS{}, nil
|
||||
}
|
||||
|
||||
// prefer using string or hex over byte array in javascript modules
|
||||
func (c *Client) Send(data string) (string, error) {
|
||||
return "", nil
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/dop251/goja"
|
||||
)
|
||||
|
||||
// temporary on demand runtime to throw errors when vm is not available
|
||||
var (
|
||||
tmpRuntime *goja.Runtime
|
||||
runtimeInit func() = sync.OnceFunc(func() {
|
||||
tmpRuntime = goja.New()
|
||||
})
|
||||
)
|
||||
|
||||
func getRuntime() *goja.Runtime {
|
||||
runtimeInit()
|
||||
return tmpRuntime
|
||||
}
|
||||
|
||||
// NucleiJS is js bindings that handles goja runtime related issue
|
||||
// and allows setting a defer statements to close resources
|
||||
type NucleiJS struct {
|
||||
vm *goja.Runtime
|
||||
ObjectSig string
|
||||
}
|
||||
|
||||
// NewNucleiJS creates a new nucleijs instance
|
||||
func NewNucleiJS(vm *goja.Runtime) *NucleiJS {
|
||||
return &NucleiJS{vm: vm}
|
||||
}
|
||||
|
||||
// internal runtime getter
|
||||
func (j *NucleiJS) runtime() *goja.Runtime {
|
||||
if j == nil {
|
||||
return getRuntime()
|
||||
}
|
||||
return j.vm
|
||||
}
|
||||
|
||||
// see: https://arc.net/l/quote/wpenftpc for throwing docs
|
||||
|
||||
// ThrowError throws an error in goja runtime
|
||||
func (j *NucleiJS) ThrowError(err error) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
panic(j.runtime().ToValue(err.Error()))
|
||||
}
|
||||
|
||||
// Throw throws an error in goja runtime
|
||||
func (j *NucleiJS) Throw(format string, args ...interface{}) {
|
||||
panic(j.runtime().ToValue(fmt.Sprintf(format, args...)))
|
||||
}
|
||||
|
||||
// GetArg returns argument at index from goja runtime if not found throws error
|
||||
func (j *NucleiJS) GetArg(args []goja.Value, index int) any {
|
||||
if index >= len(args) {
|
||||
j.Throw("Missing argument at index %v: %v", index, j.ObjectSig)
|
||||
}
|
||||
val := args[index]
|
||||
if goja.IsUndefined(val) {
|
||||
j.Throw("Missing argument at index %v: %v", index, j.ObjectSig)
|
||||
}
|
||||
return val.Export()
|
||||
}
|
||||
|
||||
// GetArgSafe returns argument at index from goja runtime if not found returns default value
|
||||
func (j *NucleiJS) GetArgSafe(args []goja.Value, index int, defaultValue any) any {
|
||||
if index >= len(args) {
|
||||
return defaultValue
|
||||
}
|
||||
val := args[index]
|
||||
if goja.IsUndefined(val) {
|
||||
return defaultValue
|
||||
}
|
||||
return val.Export()
|
||||
}
|
||||
|
||||
// Require throws an error if expression is false
|
||||
func (j *NucleiJS) Require(expr bool, msg string) {
|
||||
if !expr {
|
||||
j.Throw(msg)
|
||||
}
|
||||
}
|
||||
|
||||
// LinkConstructor links a type with invocation doing this allows
|
||||
// usage of instance of type in js
|
||||
func LinkConstructor[T any](call goja.ConstructorCall, vm *goja.Runtime, obj T) *goja.Object {
|
||||
instance := vm.ToValue(obj).(*goja.Object)
|
||||
_ = instance.SetPrototype(call.This.Prototype())
|
||||
return instance
|
||||
}
|
||||
|
||||
// GetStructType gets a type defined in go and passed as argument from goja runtime if not found throws error
|
||||
// Donot use this unless you are accepting a struct type from constructor
|
||||
func GetStructType[T any](nj *NucleiJS, args []goja.Value, index int, FuncSig string) T {
|
||||
if nj == nil {
|
||||
nj = &NucleiJS{}
|
||||
}
|
||||
if index >= len(args) {
|
||||
if FuncSig == "" {
|
||||
nj.Throw("Missing argument at index %v", index)
|
||||
}
|
||||
nj.Throw("Missing arguments expected : %v", FuncSig)
|
||||
}
|
||||
value := args[index]
|
||||
// validate type
|
||||
var ptr T
|
||||
expected := reflect.ValueOf(ptr).Type()
|
||||
argType := expected.Name()
|
||||
valueType := value.ExportType().Name()
|
||||
|
||||
if argType != valueType {
|
||||
nj.Throw("Type Mismatch expected %v got %v", argType, valueType)
|
||||
}
|
||||
|
||||
ptrValue := reflect.New(expected).Elem()
|
||||
ptrValue.Set(reflect.ValueOf(value.Export()))
|
||||
|
||||
return ptrValue.Interface().(T)
|
||||
}
|
||||
|
||||
// GetStructTypeSafe gets an type defined in go and passed as argument from goja runtime if not found returns default value
|
||||
// Donot use this unless you are accepting a struct type from constructor
|
||||
func GetStructTypeSafe[T any](nj *NucleiJS, args []goja.Value, index int, defaultValue T) T {
|
||||
if nj == nil {
|
||||
nj = &NucleiJS{}
|
||||
}
|
||||
if index >= len(args) {
|
||||
return defaultValue
|
||||
}
|
||||
value := args[index]
|
||||
// validate type
|
||||
var ptr T
|
||||
argType := reflect.ValueOf(ptr).Type().Name()
|
||||
valueType := value.ExportType().Name()
|
||||
|
||||
if argType != valueType {
|
||||
return defaultValue
|
||||
}
|
||||
return value.ToObject(nj.runtime()).Export().(T)
|
||||
}
|
Loading…
Reference in New Issue