mirror of https://github.com/daffainfo/nuclei.git
feat: introduce nucleijs utils
parent
3b5ce39e86
commit
2c2cc2774a
|
@ -16,12 +16,14 @@ var (
|
||||||
dir string
|
dir string
|
||||||
generatedDir string
|
generatedDir string
|
||||||
targetModules string
|
targetModules string
|
||||||
|
goOnly bool
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
flag.StringVar(&dir, "dir", "libs", "directory to process")
|
flag.StringVar(&dir, "dir", "libs", "directory to process")
|
||||||
flag.StringVar(&generatedDir, "out", "generated", "directory to output generated files")
|
flag.StringVar(&generatedDir, "out", "generated", "directory to output generated files")
|
||||||
flag.StringVar(&targetModules, "target", "", "target modules to generate")
|
flag.StringVar(&targetModules, "target", "", "target modules to generate")
|
||||||
|
flag.BoolVar(&goOnly, "go", false, "generate only go files")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
log.SetFlags(0)
|
log.SetFlags(0)
|
||||||
if !fileutil.FolderExists(dir) {
|
if !fileutil.FolderExists(dir) {
|
||||||
|
@ -52,10 +54,12 @@ func process() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
prefixed := "lib" + module
|
prefixed := "lib" + module
|
||||||
|
if !goOnly {
|
||||||
err = data.WriteJSTemplate(filepath.Join(generatedDir, "js/"+prefixed), module)
|
err = data.WriteJSTemplate(filepath.Join(generatedDir, "js/"+prefixed), module)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not write js template: %v", err)
|
return fmt.Errorf("could not write js template: %v", err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
err = data.WriteGoTemplate(path.Join(generatedDir, "go/"+prefixed), module)
|
err = data.WriteGoTemplate(path.Join(generatedDir, "go/"+prefixed), module)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not write go template: %v", err)
|
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) {
|
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{
|
extra := PackageTypeExtra{
|
||||||
Fields: make(map[string]string),
|
Fields: make(map[string]string),
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,16 +15,22 @@ func init() {
|
||||||
module.Set(
|
module.Set(
|
||||||
gojs.Objects{
|
gojs.Objects{
|
||||||
// Functions
|
// Functions
|
||||||
|
"Client": lib_kerberos.NewKerberosClient,
|
||||||
|
|
||||||
// Var and consts
|
// Var and consts
|
||||||
|
|
||||||
// Types (value type)
|
// Types (value type)
|
||||||
|
// "Client": func() lib_kerberos.Client { return lib_kerberos.Client{} },
|
||||||
"EnumerateUserResponse": func() lib_kerberos.EnumerateUserResponse { return lib_kerberos.EnumerateUserResponse{} },
|
"EnumerateUserResponse": func() lib_kerberos.EnumerateUserResponse { return lib_kerberos.EnumerateUserResponse{} },
|
||||||
"KerberosClient": func() lib_kerberos.KerberosClient { return lib_kerberos.KerberosClient{} },
|
"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)
|
// Types (pointer type)
|
||||||
|
"NewClient": func() *lib_kerberos.Client { return &lib_kerberos.Client{} },
|
||||||
"NewEnumerateUserResponse": func() *lib_kerberos.EnumerateUserResponse { return &lib_kerberos.EnumerateUserResponse{} },
|
"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()
|
).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